From 0c0875b746b4ec1a6adf774e397fa505e1e4198a Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Sun, 13 Sep 2026 05:35:24 -0700 Subject: [PATCH] chore: delete orphaned bench data, datagen examples and stale one-off docs Nothing in the tree reads any of these; they landed with feature PRs and were never routed to their proper home. - mcp-research-data/: 224K of July tool-search bench result rows. The harnesses (scripts/tool_search_livetest_ue*.py) write their output to a gitignored dir; the rows were committed by hand once and the headline numbers already live in the bench commit messages. - datagen-config-examples/: Feb 2026 RL datagen configs for a WebResearchEnv that no longer exists; the yaml paths point at a configs/ dir that was never created. - docs/: ADR log with one entry, an implemented cron-doctor spec, an RCA for a resolved bug, two RFCs whose work shipped, an unimplemented profile-builder proposal, the kanban dialog mock HTML and the kanban v1 spec PDF. profile-routing.md duplicated the profile_routes section of website/docs/user-guide/multi-profile-gateways.md. Kanban docs and the `hermes kanban` parser description pointed readers at the PDF; those now point at the user guide (the patterns table it was citing is on that same page). --- .../example_browser_tasks.jsonl | 5 - datagen-config-examples/run_browser_tasks.sh | 65 - .../trajectory_compression.yaml | 101 - datagen-config-examples/web_research.yaml | 46 - docs/ADR.md | 77 - docs/cron-doctor-spec.md | 32 - docs/design/kanban-dialogs/index.html | 903 ------ docs/design/profile-builder.md | 146 - docs/hermes-kanban-v1-spec.pdf | Bin 213669 -> 0 bytes docs/profile-routing.md | 117 - docs/rca-ssl-cacert-post-git-pull.md | 54 - ...plugin-architecture-lessons-pi-opencode.md | 134 - docs/rfcs/plugin-config-state-bridge.md | 144 - hermes_cli/kanban_parser.py | 3 +- mcp-research-data/ue_bench_rows.json | 1576 ---------- mcp-research-data/ue_bench_summary.json | 50 - mcp-research-data/ue_discovery_rows.json | 1309 --------- mcp-research-data/ue_hard_haiku_rows.json | 1642 ----------- mcp-research-data/ue_hard_rows.json | 2541 ----------------- website/docs/reference/cli-commands.md | 2 +- website/docs/user-guide/features/kanban.md | 8 +- .../current/reference/cli-commands.md | 2 +- .../current/user-guide/features/kanban.md | 8 +- 23 files changed, 5 insertions(+), 8960 deletions(-) delete mode 100644 datagen-config-examples/example_browser_tasks.jsonl delete mode 100755 datagen-config-examples/run_browser_tasks.sh delete mode 100644 datagen-config-examples/trajectory_compression.yaml delete mode 100644 datagen-config-examples/web_research.yaml delete mode 100644 docs/ADR.md delete mode 100644 docs/cron-doctor-spec.md delete mode 100644 docs/design/kanban-dialogs/index.html delete mode 100644 docs/design/profile-builder.md delete mode 100644 docs/hermes-kanban-v1-spec.pdf delete mode 100644 docs/profile-routing.md delete mode 100644 docs/rca-ssl-cacert-post-git-pull.md delete mode 100644 docs/rfcs/2026-07-plugin-architecture-lessons-pi-opencode.md delete mode 100644 docs/rfcs/plugin-config-state-bridge.md delete mode 100644 mcp-research-data/ue_bench_rows.json delete mode 100644 mcp-research-data/ue_bench_summary.json delete mode 100644 mcp-research-data/ue_discovery_rows.json delete mode 100644 mcp-research-data/ue_hard_haiku_rows.json delete mode 100644 mcp-research-data/ue_hard_rows.json diff --git a/datagen-config-examples/example_browser_tasks.jsonl b/datagen-config-examples/example_browser_tasks.jsonl deleted file mode 100644 index 04c2848c50..0000000000 --- a/datagen-config-examples/example_browser_tasks.jsonl +++ /dev/null @@ -1,5 +0,0 @@ -{"prompt": "Go to https://news.ycombinator.com and find the top 5 posts on the front page. For each post, get the title, URL, points, and number of comments. Return the results as a formatted summary."} -{"prompt": "Navigate to https://en.wikipedia.org/wiki/Hermes and extract the first paragraph of the article, the image caption, and the list of items in the infobox. Summarize what you find."} -{"prompt": "Go to https://github.com/trending and find the top 3 trending repositories today. For each repo, get the name, description, language, and star count. Write the results to a file called trending_repos.md."} -{"prompt": "Visit https://httpbin.org/forms/post and fill out the form with sample data (customer name: Jane Doe, size: Medium, topping: Bacon, delivery time: 12:00). Submit the form and report what the response page shows."} -{"prompt": "Navigate to https://books.toscrape.com, browse to the Travel category, find the highest-rated book, and extract its title, price, availability, and description."} diff --git a/datagen-config-examples/run_browser_tasks.sh b/datagen-config-examples/run_browser_tasks.sh deleted file mode 100755 index 1d62e3abba..0000000000 --- a/datagen-config-examples/run_browser_tasks.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/bash - -# ============================================================================= -# Example: Browser-Focused Data Generation -# ============================================================================= -# -# Generates tool-calling trajectories for browser automation tasks. -# The agent navigates websites, fills forms, extracts information, etc. -# -# Distribution: browser 97%, web 20%, vision 12%, terminal 15% -# -# Prerequisites: -# - OPENROUTER_API_KEY in ~/.hermes/.env -# - BROWSERBASE_API_KEY in ~/.hermes/.env (for browser tools) -# - A dataset JSONL file with one {"prompt": "..."} per line -# -# Usage: -# cd ~/.hermes/hermes-agent -# bash datagen-config-examples/run_browser_tasks.sh -# -# Output: data/browser_tasks_example/trajectories.jsonl -# ============================================================================= - -mkdir -p logs - -LOG_FILE="logs/browser_tasks_$(date +%Y%m%d_%H%M%S).log" -echo "📝 Logging to: $LOG_FILE" - -# Point to the example dataset in this directory -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" - -python batch_runner.py \ - --dataset_file="$SCRIPT_DIR/example_browser_tasks.jsonl" \ - --batch_size=5 \ - --run_name="browser_tasks_example" \ - --distribution="browser_tasks" \ - --model="anthropic/claude-sonnet-4" \ - --base_url="https://openrouter.ai/api/v1" \ - --num_workers=3 \ - --max_turns=30 \ - --ephemeral_system_prompt="You are an AI assistant with browser automation capabilities. Your primary task is to navigate and interact with web pages to accomplish user goals. - -IMPORTANT GUIDELINES: - -1. SEARCHING: Do NOT search directly on Google via the browser — they block automated searches. Use the web_search tool first to find URLs, then navigate to them with browser tools. - -2. COOKIE/PRIVACY DIALOGS: After navigating to a page, check for cookie consent or privacy popups. Dismiss them by clicking Accept/Close/OK before interacting with other elements. Take a fresh browser_snapshot afterward. - -3. HANDLING TIMEOUTS: If an action times out, the element may be blocked by an overlay. Take a new snapshot and look for dialogs to dismiss. If none, try an alternative approach or report the issue. - -4. GENERAL: Use browser tools to click, fill forms, and extract information. Use terminal for local file operations. Verify your actions and handle errors gracefully." \ - 2>&1 | tee "$LOG_FILE" - -echo "✅ Done. Log: $LOG_FILE" - -# ============================================================================= -# Common options you can add: -# -# --resume Resume from checkpoint if interrupted -# --verbose Enable detailed logging - -# --reasoning_disabled Disable model thinking/reasoning tokens -# --providers_allowed="anthropic,google" Restrict to specific providers -# --prefill_messages_file="configs/prefill.json" Few-shot priming -# ============================================================================= diff --git a/datagen-config-examples/trajectory_compression.yaml b/datagen-config-examples/trajectory_compression.yaml deleted file mode 100644 index c5b92a97c1..0000000000 --- a/datagen-config-examples/trajectory_compression.yaml +++ /dev/null @@ -1,101 +0,0 @@ -# Trajectory Compression Configuration -# -# Post-processes completed agent trajectories to fit within a target token budget. -# Compression preserves head/tail turns and summarizes middle content only as needed. - -# Tokenizer settings for accurate token counting -tokenizer: - # HuggingFace tokenizer name - name: "moonshotai/Kimi-K2-Thinking" - - # Trust remote code (required for some tokenizers) - trust_remote_code: true - -# Compression targets and behavior -compression: - # Target maximum tokens for compressed trajectory - target_max_tokens: 29000 - - # Target size for summary (in tokens) - # This is factored into calculations when determining what to compress - summary_target_tokens: 750 - -# Protected turns that should NEVER be compressed -protected_turns: - # Always protect the first system message (tool definitions) - first_system: true - - # Always protect the first human message (original request) - first_human: true - - # Always protect the first gpt message (initial response/tool_call) - first_gpt: true - - # Always protect the first tool response (result of first action) - first_tool: true - - # Always protect the last 2 complete turn pairs (gpt+tool or gpt only) - # This ensures the model's final actions and conclusions are preserved - last_n_turns: 4 - -# LLM settings for generating summaries (OpenRouter only) -summarization: - # Model to use for summarization (should be fast and cheap) - # Using OpenRouter model path format - model: "google/gemini-3-flash-preview" - - # OpenRouter API settings - base_url: "https://openrouter.ai/api/v1" - - # Environment variable containing OpenRouter API key - api_key_env: "OPENROUTER_API_KEY" - - # Temperature for summarization (lower = more deterministic) - temperature: 0.3 - - # Max retries for API failures - max_retries: 3 - - # Delay between retries (seconds) - retry_delay: 2 - -# Output settings -output: - # Add notice to system message about potential summarization - add_summary_notice: true - - # Text to append to system message - summary_notice_text: "\n\nSome of the conversation may be summarized to preserve context." - - # Output directory suffix (appended to input directory name) - output_suffix: "_compressed" - -# Processing settings -processing: - # Number of parallel workers for batch processing - num_workers: 4 - - # Maximum concurrent API calls for summarization (async parallelism) - max_concurrent_requests: 50 - - # Skip trajectories that are already under target length - skip_under_target: true - - # If true, save trajectories even if compression can't get under target - # (will compress as much as possible) - save_over_limit: true - - # Timeout per trajectory in seconds (skip if takes longer) - # Helps avoid hanging on problematic entries - per_trajectory_timeout: 300 # 5 minutes - -# Metrics to track -metrics: - # Log detailed compression statistics - enabled: true - - # Save per-trajectory metrics in output - per_trajectory: false - - # Metrics file name (saved in output directory) - output_file: "compression_metrics.json" diff --git a/datagen-config-examples/web_research.yaml b/datagen-config-examples/web_research.yaml deleted file mode 100644 index 6275dbed69..0000000000 --- a/datagen-config-examples/web_research.yaml +++ /dev/null @@ -1,46 +0,0 @@ -# datagen-config-examples/web_research.yaml -# -# Batch data generation config for WebResearchEnv. -# Generates tool-calling trajectories for multi-step web research tasks. -# -# Usage: -# python batch_runner.py \ -# --config datagen-config-examples/web_research.yaml \ -# --run_name web_research_v1 - -environment: web-research - -# Toolsets available to the agent during data generation -toolsets: - - web - - file - -# How many parallel workers to use -num_workers: 4 - -# Questions per batch -batch_size: 20 - -# Total trajectories to generate (comment out to run full dataset) -max_items: 500 - -# Model to use for generation (override with --model flag) -model: openrouter/nousresearch/hermes-3-llama-3.1-405b - -# System prompt additions (ephemeral — not saved to trajectories) -ephemeral_system_prompt: | - You are a highly capable research agent. When asked a factual question, - always use web_search to find current, accurate information before answering. - Cite at least 2 sources. Be concise and accurate. - -# Output directory -output_dir: data/web_research_v1 - -# Trajectory compression settings (for fitting into training token budgets) -compression: - enabled: true - target_max_tokens: 16000 - -# Eval settings -eval_every: 100 # Run eval every N trajectories -eval_size: 25 # Number of held-out questions per eval run diff --git a/docs/ADR.md b/docs/ADR.md deleted file mode 100644 index cc9ecfb927..0000000000 --- a/docs/ADR.md +++ /dev/null @@ -1,77 +0,0 @@ -# Architecture Decision Records - -## 2026-07-13: Scope plugin manager state by Hermes home/profile (keyed cache) - -Status: Accepted - -Context: -Hermes supports multiple profiles via different Hermes home directories. -Homes are switched two ways in a running process: the `HERMES_HOME` -environment variable (single-profile CLI/gateway processes), and the -context-local `set_hermes_home_override()` (`hermes_constants.py`), which -the multiplexed gateway worker (`gateway/run.py`'s `_profile_scope`) and -subagent/embedded callers use to serve several profiles from one -long-lived process. The override is a `ContextVar` and deliberately does -**not** mutate `os.environ`, since that would leak one profile's home -into every other concurrent task in the same process. - -The plugin manager was a process-global single-slot singleton -(`_plugin_manager`). User-installed plugins are discovered from -`get_hermes_home() / "plugins"`, and context-engine plugins (e.g. -`hermes-lcm`) capture profile-scoped state — such as the LCM database -path — at registration time. A single-slot cache meant: - -1. Switching homes via `set_hermes_home_override()` was invisible to a - naive "did `HERMES_HOME` change" check, so the singleton silently kept - serving the first profile's manager to every other profile in the - process. -2. Even when a fresh `PluginManager` *was* created for a new home, plugin - modules are imported into `sys.modules` as `hermes_plugins.` by - `_load_directory_module`, and only that top-level module was ever - replaced. A same-slug plugin's *relative* imports - (`from . import state`) are cached separately under - `hermes_plugins..`, and Python's import machinery - resolves those from `sys.modules` first — so a profile switch could - silently keep serving a previous profile's already-imported submodule - code/state instead of re-executing the new profile's plugin. - -Decision: -- Replace the single-slot singleton with a cache keyed on the *resolved* - Hermes home path (`_plugin_managers_by_home: Dict[Path, PluginManager]`). - `get_plugin_manager()` resolves the current home via `get_hermes_home()` - (which itself already consults `get_hermes_home_override()` before - `os.environ`), so both the env-var and context-local override paths are - covered uniformly. -- `_plugin_manager` (the old single-slot name) is kept as a thin "last - manager returned" pointer purely for backward compatibility with - existing test code that does - `monkeypatch.setattr(plugins_mod, "_plugin_manager", some_manager)`. - When that name is monkeypatched to a manager the keyed cache doesn't - know about, `get_plugin_manager()` treats it as an explicit injection - and adopts it into the cache under the *current* resolved home, rather - than discarding it. -- Both `PluginManager._load_directory_module` (initial/`force=True` - reload within the same home) and the shared `_clear_plugin_submodules` - helper (profile switch / test teardown) evict `sys.modules[module_name]` - **and every name prefixed with `module_name + "."`** before a plugin - slug is (re-)imported, so relative-import submodules can never survive - a reload or a home switch. -- Test isolation (`tests/conftest.py`'s `_hermetic_environment` fixture) - calls a new `_reset_plugin_managers_for_tests()` helper that drops the - entire keyed cache and purges every plugin submodule from `sys.modules` - between tests, instead of only resetting the single-slot pointer. - -Consequences: -- Per-profile LCM instances (and any other context-engine plugin) use - their own `{home}/lcm.db` regardless of whether the profile switch went - through `HERMES_HOME` or `set_hermes_home_override()`. -- Plugin discovery remains cached within a profile for normal - performance, and re-entering a previously-seen profile reuses its - cached manager instead of rebuilding from scratch. -- Sequential *and* interleaved profile switching — in tests, the gateway - multiplexer worker, or embedded callers using the context-local - override — no longer leaks context-engine state, plugin module state, - or stale relative-import submodules across profiles. -- Regression coverage exercises the real production path - (`set_hermes_home_override()`) rather than only the env-var path, and - includes a dedicated relative-import leak test. diff --git a/docs/cron-doctor-spec.md b/docs/cron-doctor-spec.md deleted file mode 100644 index ac2595153a..0000000000 --- a/docs/cron-doctor-spec.md +++ /dev/null @@ -1,32 +0,0 @@ -# Cron Doctor Spec - -## Problem - -Scheduled jobs can silently degrade when a script is moved, a workdir disappears, -a provider run fails, or delivery starts failing. `hermes cron list` shows some of -this inline, but there is no compact read-only health check that can be run from a -terminal, cron job, or CI-style smoke check. - -## Goal - -Add `hermes cron doctor` as a read-only diagnostic command that summarizes cron -job health and exits non-zero when actionable issues are found. - -## Non-goals - -- Do not mutate jobs or auto-repair state. -- Do not start/stop the gateway. -- Do not inspect secrets or print credentials. - -## Acceptance criteria - -- `hermes cron doctor` returns `0` and prints a healthy message when active jobs - have no detected issues. -- It returns `1` and prints grouped job-level issues when any active job has: - - last run failure (`last_status` not `ok`), - - last delivery failure, - - no `next_run_at` while still active, - - `no_agent` enabled without a script, - - script path missing/outside `HERMES_HOME/scripts`, or - - configured workdir path missing. -- Parser, command dispatch, and focused tests cover the new subcommand. diff --git a/docs/design/kanban-dialogs/index.html b/docs/design/kanban-dialogs/index.html deleted file mode 100644 index f32f74f5a8..0000000000 --- a/docs/design/kanban-dialogs/index.html +++ /dev/null @@ -1,903 +0,0 @@ - - - - - -Hermes Kanban — Native Dialog Prototypes - - - - -
-

Hermes Kanban — Native Dialog Prototypes

-

- Four approaches to replacing window.confirm(), - window.prompt(), and window.alert() in - plugins/kanban/dashboard/dist/index.js. Click a page-level - trigger to fire the same flow in every variant simultaneously, or use the - per-variant buttons to fire flows unique to that variant. -

-
- - - - - - - -
-
- -
- - - - -
-
-

Variant A

-
Conservative
-

Direct 1:1 mapping to the host's ConfirmDialog. Single-line input. Minimal chrome.

-
-
-
Click a trigger to preview.
-
-
- Trade-off: Safest to ship — zero new components, zero new - patterns. Fails the GPT-OSS review on three points: no multi-line - summary, validation triggers a SECOND dialog instead of inline, no bulk - affordance. -
-
- - - - -
-
-

Variant B

-
Strong-fit (Pro's pick)
-

Textarea + contextual SVG icon + inline validation + pluralized copy. What the design brief recommends.

-
-
-
Click a trigger to preview.
-
-
- Trade-off: Best baseline, but Pro suggested either - a disabled-button or an inline error — GPT-OSS caught that both - are needed (button disabled AND error visible) for screen-reader users. - Bottom-sheet on mobile is the right move but still has keyboard edge cases. -
-
- - - - -
-
-

Variant B-refined

-
Synthesis (recommended)
-

All of B's improvements + GPT-OSS fixes: auto-focus, dual-validation, cancellable-spinner, per-task summaries in bulk.

-
-
-
Click a trigger to preview.
-
-
- Why this is the recommendation: Single contextual icon - (not four) keeps the title readable. Confirm button stays enabled until - textarea has content; the inline error appears on submit-attempted-empty - AND on blur if still empty. Cancel button stays clickable during the - PATCH (only the confirm shows the spinner) so users can abort slow - networks. Bulk-many shows an expandable list with per-task summary - fields. -
-
- - - - -
-
-

Variant C

-
Divergent: undo toast
-

Skip the modal entirely for non-destructive moves. Optimistic UI + 5s undo in a bottom-right toast.

-
-
-
Click a trigger to preview.
-
-
-
- Trade-off: Radical speedup for routine moves, but breaks - the required-summary flow (you can't optimistically "complete" a task - that's missing required schema data). Best used as a - complement to B-refined — undo toast for the safe moves, - modal for done/blocked/archive. -
-
- -
- -
-

Decision matrix — recommended pick: B-refined

- - - - - - - - - - - - - - - - - -
CapabilityABB-refinedC
Centered modal (Radix) ✓ ✓ ✓ ✗
Multi-line summary ✗ ✓ ✓ ✗
Single contextual icon ✗ 4 ✓ ✗
Inline validation (no second dialog)✗ ~ ✓ ✗
Disabled button + persistent error ✗ ~ ✓ ✗
Cancellable spinner during PATCH ✗ ✗ ✓ ✓
Bulk-many expandable list ✗ ✗ ✓ ✗
Auto-focus textarea + mobile scroll ✗ ~ ✓ ✗
Toast on success ✗ ✗ ✗ ✓
Toast on error ✗ ✗ opt. ✓
Survives the required-summary flow ✗ ✓ ✓ ✗
-
- - - - - \ No newline at end of file diff --git a/docs/design/profile-builder.md b/docs/design/profile-builder.md deleted file mode 100644 index 76649096d2..0000000000 --- a/docs/design/profile-builder.md +++ /dev/null @@ -1,146 +0,0 @@ -# Profile Builder — Dashboard-Native, Full-Featured Profile Creation - -Status: design proposal (not yet implemented) -Author: drafted for Teknium -Supersedes: PR #31781 (prompt_toolkit `hermes profile wizard`) - -## Why this, not the CLI wizard - -PR #31781 added a keyboard-driven `hermes profile wizard` in the terminal. -The decision is to **not** build the profile-creation experience in the CLI. -The dashboard already owns mature, separate pages for every element a profile -needs, and a profile is just a HERMES_HOME directory — so the dashboard is the -right home for a full-featured builder, and it can reuse everything that -already exists. - -A profile = a full `~/.hermes/profiles//` directory with its own: -- `config.yaml` — holds `model`/`provider`, `mcp_servers`, enabled skills -- `skills/` — physical SKILL.md files (built-in seed + optional + hub installs) -- `.env` — secrets -- `SOUL.md` / `USER.md` — identity - -So per-profile scoping of Model, MCPs, and Skills is **native** — no data-model -change needed. The gap is purely UX: creation today is a thin modal -(name + clone + model + description), and you can only compose skills/MCPs -*after* the profile exists, by visiting other pages and remembering to scope -them. - -## What already exists (reuse, don't rebuild) - -| Element | Existing page | Existing API | Profile-scopable? | -|---|---|---|---| -| Name / Description | ProfilesPage create modal | `POST /api/profiles` (`create_profile`) | yes (args) | -| Model + Provider | ModelsPage | `_write_profile_model(profile_dir, …)` | yes — HERMES_HOME override, already wired into create endpoint | -| MCPs | McpPage | `mcp_config._save_mcp_server` + `/api/mcp/catalog` | yes — wrap with HERMES_HOME override | -| Skills (built-in/optional) | SkillsPage | `GET /api/skills`, `/api/skills/toggle` | yes — config write | -| Skills (hub) | SkillsPage | `/api/skills/hub/search`, `/api/skills/hub/install` | **only via subprocess** — see seam #1 | - -## Two architectural seams found while grounding this design - -These are load-bearing — they change the implementation, not just the polish. - -### Seam #1 — hub-skill install cannot use the HERMES_HOME override - -`tools/skills_hub.py` binds `SKILLS_DIR = HERMES_HOME / "skills"` at **module -import time**. The context-local `set_hermes_home_override()` swap (which makes -`_write_profile_model` and the MCP write land in the target profile) does NOT -retroactively rebind that already-imported module global. So a data-layer wrap -of hub install would write into the dashboard's *own* active profile, not the -new one. - -The correct mechanism is the existing subprocess path: `_spawn_hermes_action` -runs `python -m hermes_cli.main `, and `_apply_profile_override()` -re-reads `sys.argv` at import in the fresh child. Prepend `-p `: - -```python -_spawn_hermes_action(["-p", profile, "skills", "install", identifier], "skills-install") -``` - -A fresh subprocess re-imports `skills_hub` with the profile's HERMES_HOME bound -from the start, so `SKILLS_DIR` resolves to `/skills/`. Correct by -construction. - -### Seam #2 — hub installs are async, so create cannot be fully atomic - -Built-in/optional skill enabling and MCP writes are **synchronous config ops** -and can be part of the create call. Hub installs are long-running git fetches -spawned detached (`_spawn_hermes_action` returns a PID immediately). So the -create flow is: - -1. `create_profile()` — make the dir (synchronous) -2. write model (synchronous, HERMES_HOME override) -3. write selected MCP servers (synchronous, HERMES_HOME override) -4. seed/enable selected built-in + optional skills (synchronous) -5. spawn `hermes -p skills install ` per hub skill (async, returns PIDs) - -Steps 1–4 commit before the response; step 5 returns a list of action PIDs the -UI polls (same pattern as today's SkillsPage hub install). The builder's -"Review → Create" returns `{ok, name, path, hub_installs: [{id, pid}]}` and the -final screen shows live install progress for the hub skills. - -## Proposed backend change (small, follows existing patterns) - -Extend `ProfileCreate` and the create endpoint — no new endpoints, no rewrite: - -```python -class ProfileCreate(BaseModel): - name: str - clone_from: Optional[str] = None - # Backward compatibility for older dashboard/desktop clients. - clone_from_default: bool = False - clone_all: bool = False - no_skills: bool = False - description: Optional[str] = None - provider: Optional[str] = None - model: Optional[str] = None - # NEW — all optional, all best-effort post-create (profile already exists) - mcp_servers: List[MCPServerCreate] = [] # synchronous, HERMES_HOME override - builtin_skills: List[str] = [] # synchronous enable/seed - hub_skills: List[str] = [] # async spawn, returns PIDs -``` - -The endpoint already does best-effort post-create steps (`seed_profile_skills`, -`_write_profile_model`). Add two more best-effort blocks (MCP write, hub-skill -spawn) in the same style — a failure in any of them must not 500 the create, -since the profile dir already exists and the user can fix it from the relevant -page afterward. Mirror `_write_profile_model`'s HERMES_HOME-override helper for -the MCP write (`_write_profile_mcp_servers(profile_dir, servers)`). - -## Proposed frontend — dedicated builder page `/profiles/new` - -A full page (not the cramped modal), stepped, each step reusing the existing -page's component + API, targeted at the new profile: - -``` -① Identity Name + Description (+ optional clone-from existing profile) -② Model Provider + model picker (reuse ModelsPage picker) -③ Skills Tabs: Built-in · Optional · Hub-search - multi-select; "Start from default bundle" preset button -④ MCPs Tabs: Catalog browse · Manual add (reuse McpPage form) -⑤ Review Blueprint preview → Create - → progress screen for async hub installs -``` - -Nothing writes to disk until ⑤. - -## Open product decisions (need Teknium) - -1. **Skills seeding default.** Fresh profiles auto-seed the default bundle - today. In the builder, should the skill step **replace** the bundle (pick - exactly what you want; offer a "start from default bundle" preset) or - **augment** it? Recommendation: replace + preset button. - -2. **Page vs richer modal.** Dedicated `/profiles/new` page (room to grow: - SOUL editing, multi-agent fleets later) vs a bigger create modal on - ProfilesPage. Recommendation: dedicated page — matches "full-featured / way - more options." - -## Verification plan (when built) - -- Backend E2E with isolated HERMES_HOME: POST a full create body - (name + model + 2 MCPs + 3 builtin skills + 1 hub skill), assert the new - profile dir has the model in config.yaml, both MCP servers in config.yaml, - the builtin skills enabled, and a spawned PID for the hub skill. Negative: - a bad MCP entry must not 500 the create. -- `cd web && npm run build` (no JS test suite in web/). -- Targeted: `pytest tests/ -k profile_create`. diff --git a/docs/hermes-kanban-v1-spec.pdf b/docs/hermes-kanban-v1-spec.pdf deleted file mode 100644 index c7899cd12a92e3f14e8c44e7c36f96f174982c41..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 213669 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 z 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 diff --git a/docs/profile-routing.md b/docs/profile-routing.md deleted file mode 100644 index 9b0237f5c6..0000000000 --- a/docs/profile-routing.md +++ /dev/null @@ -1,117 +0,0 @@ -# Profile-Based Routing for Inbound Messages - -> **Audience:** Gateway operators and contributors -> **Source files:** `gateway/profile_routing.py`, `gateway/run.py` (`_profile_name_for_source`), `gateway/platforms/base.py` (`build_source`), `gateway/config.py` -> **Related:** [Session Lifecycle](session-lifecycle.md), `docs/design/profile-builder.md` - -## Overview - -By default a single gateway run uses one profile (memory, persona, tools). **Profile-based -routing** lets one gateway instance serve **multiple isolated profiles**, selecting which -profile handles an inbound message based on *where the message came from* — the platform, -server (`guild_id`), channel (`chat_id`), and/or thread (`thread_id`). - -This is the inbound counterpart to multiplexing: instead of running N gateways, run one -gateway and route per-community / per-channel / per-thread to a dedicated profile. Each -profile keeps fully isolated state (`MEMORY.md`, `USER.md`, `SOUL.md`, sessions, tools). - -Routing is **platform-generic**: it works for Discord, Telegram, Feishu, Slack, and every -adapter — not just Discord. - -## Configuring routes - -Routes live under `profile_routes` in `config.yaml`. Both the top-level and the nested -`gateway.profile_routes` forms are accepted (the nested form is what -`hermes config set gateway.profile_routes ...` writes). - -```yaml -profile_routes: - # Route an entire Discord server (guild) to one profile. - - name: server-default - platform: discord - guild_id: "1234567890" - profile: server-profile - - # Override a specific channel within that server with a different profile. - - name: support-channel - platform: discord - guild_id: "1234567890" - chat_id: "9876543210" - profile: support-profile - - # Pin a Telegram group to a profile (Telegram has no guild_id — chat_id only). - - name: tg-group - platform: telegram - chat_id: "-1001234567890" - profile: tg-profile - - # Route a single Discord thread. - - name: standup-thread - platform: discord - guild_id: "1234567890" - chat_id: "9876543210" - thread_id: "1111111111" - profile: standup -``` - -### Fields - -| Field | Required | Description | -|---|---|---| -| `name` | yes | Human-readable route identifier (used in logs). | -| `platform` | yes | Adapter platform: `discord`, `telegram`, `feishu`, `slack`, … | -| `profile` | yes | Target profile name (must exist under `~/.hermes/profiles/`). | -| `guild_id` | no | Server/guild (Discord). | -| `chat_id` | no | Channel/group/DM id. | -| `thread_id` | no | Thread id within a channel. | -| `enabled` | no | Default `true`; set `false` to disable a route without removing it. | - -## Matching rules - -A route matches an inbound source when **every discriminator the route declares is satisfied** -(conjunctive / AND). A field the route leaves unset is ignored. - -- **`platform`** must equal the source platform exactly. -- **`thread_id`** (if set) must equal the source thread id. -- **`chat_id`** (if set) must match the source channel **or** its parent — a thread in a - channel matches the channel's route (hierarchical match for Discord forums/threads). -- **`guild_id`** (if set) must equal the source guild. - -> A route declaring **both** `guild_id` and `chat_id` requires both to hold. A channel match -> alone does not satisfy a guild constraint — this is intentional and tested. - -When multiple routes match, the **most specific** one wins. Specificity is additive: - -| Discriminator | Weight | -|---|---| -| `thread_id` | 8 | -| `chat_id` | 4 | -| `guild_id` | 2 | -| (platform only) | 0 | - -So a thread route (8) beats a channel route (4) beats a guild route (2) within the same server. -If no route matches, the message uses the default/active profile. - -## How it works at runtime - -1. An inbound message arrives at a platform adapter. -2. `BasePlatformAdapter.build_source` builds the `SessionSource` for the message. Every - adapter carries a back-reference to the running `GatewayRunner` - (`gateway_runner`, injected in `gateway/run.py`), so it asks the runner to resolve the - target profile via `_profile_name_for_source`. -3. `_profile_name_for_source` runs the configured routes through `match_profile_route` and - stamps `source.profile` with the winning route's profile (or leaves it unset). -4. Downstream, `_resolve_profile_home_for_source` chooses the profile home directory - (`source.profile` → active profile → `default`) and the session is scoped per-profile, so - each routed community gets isolated memory and conversation state. - -Because `gateway_runner` is injected for **all** adapters (declared on `BasePlatformAdapter`), -every platform goes through this path — not just Discord. - -## Relationship to multiplexing - -`profile_routes` requires `gateway.multiplex_profiles: true`. Multiplexing is what -activates the per-profile runtime scope (per-profile `HERMES_HOME`, secret scope, and -profile-namespaced session keys); routing is the decision layer that picks *which* -profile a given guild/channel/thread lands in. With multiplexing off, `profile_routes` -is ignored entirely — behavior is byte-identical to a single-profile gateway. diff --git a/docs/rca-ssl-cacert-post-git-pull.md b/docs/rca-ssl-cacert-post-git-pull.md deleted file mode 100644 index 505def8750..0000000000 --- a/docs/rca-ssl-cacert-post-git-pull.md +++ /dev/null @@ -1,54 +0,0 @@ -# RCA: SSL CA cert bundle corruption after `hermes update` - -**Status:** resolved by `fix(ssl): surface broken CA bundles before provider calls` -**Severity:** P2 — degrades the agent into opaque provider/client failures until the user repairs deps or CA configuration. - -## Summary - -A partial `hermes update`, interrupted venv repair, or stale CA-bundle environment variable can leave Python TLS configuration pointing at a missing, empty, or unloadable CA bundle. The first outbound HTTPS client creation or request can then fail with a raw `FileNotFoundError: [Errno 2] No such file or directory` or a low-level SSL error that does not name the broken CA path. - -## Root cause - -Hermes uses OpenAI/httpx and requests-based clients for provider calls, model metadata, gateway delivery, and web tools. Those clients inherit CA bundle settings from: - -- `HERMES_CA_BUNDLE` -- `SSL_CERT_FILE` -- `REQUESTS_CA_BUNDLE` -- `CURL_CA_BUNDLE` -- the bundled `certifi` package's `cacert.pem` - -When the venv is partially refreshed, or when one of those env vars points at a file that no longer exists, provider client construction can fail before Hermes has enough context to produce a useful message. - -## Fix - -`agent/ssl_guard.py` validates CA bundle configuration before the OpenAI-compatible provider client is created in `agent/agent_init.py`. It: - -1. Checks explicit CA bundle env vars and reports the exact broken variable/path, -2. Verifies `certifi` is importable, -3. Verifies `certifi.where()` points at an existing file of plausible size, -4. Builds an `ssl.SSLContext` from each checked bundle, -5. Raises a typed `SSLConfigurationError` with a repair hint before httpx/OpenAI can raise a raw low-level error. - -`hermes_cli doctor` exposes the same check under `SSL / CA Certificates`, so users can diagnose the problem without starting a model session. - -## Recovery - -When the guard fires during agent init, the user sees a message like: - -```text -Failed to initialize OpenAI client: SSL_CERT_FILE points to a missing CA bundle: C:\path\to\missing\cacert.pem -Repair: python -m pip install --force-reinstall certifi openai httpx -If you configured a custom corporate CA bundle, fix or unset the broken CA bundle environment variable. -``` - -For a normal corrupted Hermes venv, reinstall the affected client dependencies: - -```bash -python -m pip install --force-reinstall certifi openai httpx -``` - -For a custom/corporate CA setup, fix the env var so it points at a real PEM bundle, or unset it if Hermes should use the bundled `certifi` store. - -## Environment escape hatch - -Set `HERMES_SKIP_SSL_GUARD=1` to bypass the preflight check. This is intended only for sandboxed or managed-trust environments where the Python CA path looks unusual but downstream clients are known to work. diff --git a/docs/rfcs/2026-07-plugin-architecture-lessons-pi-opencode.md b/docs/rfcs/2026-07-plugin-architecture-lessons-pi-opencode.md deleted file mode 100644 index 7aaf126417..0000000000 --- a/docs/rfcs/2026-07-plugin-architecture-lessons-pi-opencode.md +++ /dev/null @@ -1,134 +0,0 @@ -# Research spike: plugin-architecture lessons from Pi and OpenCode - -**Issue:** #64180 · **Informs:** #64164 (event bus), #64161 (streaming hooks), #64162 (pluggable approval), #64165 (manifest v2), #64229 (lifecycle/ledger), #64230 (Plugin Doctor) - -**Method.** Both systems were read at source level (shallow clones pinned to a commit), not from docs sites alone: Pi (`badlogic/pi-mono`, now `earendil-works/pi`) at `eb79351` (v0.80.7, 2026-07-14) and OpenCode (`sst/opencode`, now `anomalyco/opencode`) at `c69abee` (v1.18.2, 2026-07-16). Claims below carry file:line references into those commits. Where something could not be found (ADRs, policies, timeouts), that absence was verified by search and is reported as a finding. Hermes ground rules from #64182 (additive-only, prompt-cache sacred, observer-first, fail-closed security) are treated as overriding constraints throughout — this report grades imported patterns against them, per the adapt-don't-copy rubric. - -**Headline.** The two systems are near-perfect opposites on the four design axes Hermes currently has open, which makes them a natural controlled experiment: - -| Axis | Pi | OpenCode | Hermes proposal on the table | -|---|---|---|---| -| Per-delta streaming hook | Yes — awaited inline, no timeout | Structurally absent (text-end only) | Observer per-delta + never-block contract (#64161) | -| Veto semantics | Typed per-event result vocabulary (`{block}`, `{cancel}`, `"handled"`) | Veto-by-throw (bug and policy denial indistinguishable) | TBD in #64162 | -| Guard-hook failure | Fail closed (`tool_call` only) | No runtime containment at all | Ground rule 4: fail closed on security-adjacent | -| Plugin event bus | Yes — 33 lines, **un-namespaced** channels | None (plugins observe core bus, cannot emit) | Namespaced `ctx.emit`/`ctx.subscribe` (#64164) | - -Neither system has hook timeouts. Both have shipped hang-class or drift-class failures because of it. That is the single strongest cross-cutting lesson for Hermes. - ---- - -## 1. Pi (badlogic/pi-mono → earendil-works/pi) - -Extensions are in-process TypeScript modules (loaded via jiti) receiving an `ExtensionAPI`; no separate process, no IPC, no manifest permissions. Pi explicitly rejected MCP as its extension mechanism (Zechner, ["What if you don't need MCP at all?"](https://mariozechner.at/posts/2025-11-02-what-if-you-dont-need-mcp/)). Notably, Pi's founding "minimal, no hooks" stance (Nov 2025) reversed into a 33-event extension system within ~7 months — extensibility demand won; the no-MCP stance held. - -### 1.1 Hook/event taxonomy - -33 event types (`src/core/extensions/types.ts:507-902`). The load-bearing design choice: **every mutating event gets its own typed emitter with its own result vocabulary**, rather than one generic middleware pipe — - -- `tool_call` → `{ block: true, reason }`; argument mutation in place, explicitly "no re-validation after your mutation" (`docs/extensions.md:742-765`) -- `session_before_*` → `{ cancel: true }`, first canceller wins, later handlers skipped -- `input` → `"handled"` (short-circuit) vs `"transform"` (chain) (`runner.ts:1148-1188`) -- `tool_result` → partial-patch accumulation across handlers (`runner.ts:835-883`) -- `before_agent_start` → system-prompt chaining with a live `ctx.getSystemPrompt()` reflecting earlier handlers (`runner.ts:1034-1098`) -- Observer events have **no return channel at all** — the observer/mutator split is enforced by which emitter the event flows through, not by convention. - -Dispatch is fully sequential async (`runner.ts:759-791`): every handler awaited one at a time; the only ordering rule is extension load order (project → global → CLI, `loader.ts:660-708`) then registration order. No priorities, no phases — and no community demand for them in ~8 months. Name collisions are handled per registry with explicit deterministic policies instead of dependency resolution: first-wins tools, suffixed duplicate commands (`name:2`), last-wins shortcuts with a warning plus an 18-key reserved denylist (`runner.ts:421-604`). - -Two ordering guarantees worth copying: extensions see events **before** the UI and **before** session persistence (`agent-session.ts:596-601`), and parallel sibling tool calls are "preflighted sequentially, then executed concurrently" (`docs/extensions.md:750`). - -### 1.2 Plugin-to-plugin interaction - -A 33-line shared event bus (`src/core/event-bus.ts`): `pi.events.emit/on` on **arbitrary string channels** — no namespacing, no declarations, no collision protection; per-handler try/catch and an unsubscribe closure. Everything richer (capability registries, dependencies) is deliberately absent; a community RFC to build richer coordination as an extension (pi#2715) was left to userland. - -### 1.3 Compatibility strategy - -No API versioning, no handshake, no deprecation annotations. In its place, three working practices: (a) loader-level alias shims that kept old imports resolving across the `@mariozechner`→`@earendil-works` package rename and a pi-ai API split, with pre-announced removal (`loader.ts:47-71`; `CHANGELOG.md:243`); (b) loud "Breaking Changes" changelog sections with **automatic migrations** (directory renames on startup, session format v2→v3 auto-migrated) for the big hooks+customTools→extensions unification (v0.35-0.37); (c) per-tool `prepareArguments()` shims for old argument shapes. - -Real breakage on record: pi#2860 — an internal session-management refactor made `pi.sendUserMessage()` after `ctx.newSession()` silently drop messages. The remediation pattern is distinctive: **stale-context poisoning** — after session replacement, every captured context getter throws a paragraph-long teaching error pointing at the safe `withSession` pattern (`runner.ts:514-527`; `docs/extensions.md:1223-1265` documents the footgun with unsafe-pattern code). Compat by making misuse loud, not by never changing. - -### 1.4 Failure isolation - -Contain errors, don't contain time: every handler call is individually try/caught and surfaced (red stack trace in chat UI), load failures skip only the broken extension, and a `pi -ne` no-extensions escape hatch exists. The **one deliberate exception**: `tool_call` has no internal catch — a guard-hook crash blocks the tool ("Extension failed, blocking execution"), converted into an error tool result the LLM sees; the loop survives, the guard fails closed (`runner.ts:885-906`; `agent-session.ts:454-467`; `agent-loop.ts:657-665`). - -**There are zero timeouts.** All handlers — including per-token `message_update` — are awaited inline in the agent event pipeline (`agent-session.ts:598, 728-734`). A hung extension freezes the agent; the changelog records hang-class fixes (pi#5687 background handles, pi#5115 shutdown drains). Mitigations offered are cooperative only (`ctx.signal` AbortSignal, Esc-abort). - -No sandbox, documented as a decision: "a partial in-process sandbox would be easy to misunderstand as a security boundary" (`docs/security.md:33-35`); the only gate is project-trust on load. - -### 1.5 Design-history record - -**Pi has no ADRs** — the Discord recollection that prompted this spike is not substantiated for Pi. Rationale lives in four places: "footgun" sections inside user docs (effectively inline ADRs), a 5,000-line issue-linked changelog (which records abandoned designs: the hooks/customTools split, slash-commands→prompt-templates rename, a fetch-override proxy abandoned for undici dispatchers), Zechner's blog, and issues themselves. - -### 1.6 Prompt/context construction - -Pi is the only surveyed system that treats **prompt-cache stability as part of the extension API contract**: extensions receive structured prompt inputs (`systemPromptOptions` — the same decomposed inputs Pi itself uses) rather than a final string; per-request context transforms operate on a `structuredClone` so session history is never corrupted; and cache-friendly dynamic tool loading (v0.80.6, pi#6474) activates tools additively via native provider deferred loading (Anthropic `defer_loading`) explicitly to avoid invalidating the prefix cache — with documented warnings about second-order invalidation through prompt-metadata changes (`docs/extensions.md:2254-2290`). - ---- - -## 2. OpenCode (sst/opencode → anomalyco/opencode) - -Server (Bun/Effect) + clients (TUI/desktop/web); plugins are npm packages or local TS files loaded in-process, with **two plugin kinds in one package** — `server` and `tui` entrypoints, hard rule one-or-the-other (`shared.ts:103-114, 293-295`). A v2 plugin API ships side-by-side with v1 (`/v2/effect`, `/v2/promise` subpaths), designed in a candid 516-line `PLAN.md`. - -### 2.1 Hook/event taxonomy - -One `Hooks` bag returned by an async factory (`packages/plugin/src/index.ts:74, 222-335`): ~16 mutating `(input, output)` hooks (mutate `output` in place; host reads it back) plus declarative registries (tools, auth, providers) and a single firehose `event` observer. The whole dispatch engine is ~13 lines (`plugin/index.ts:280-293`): sequential, awaited, load-order, later hooks see earlier mutations — ordering documented as a spec ("global config → project config → global plugin dir → project plugin dir"; v2: "plugin registration order, then transform registration order"). - -**Veto is throw.** The documented idiom for denying a tool call is `throw new Error("Do not read .env files")` (`plugins.mdx:247-257`) — policy denial and plugin bug are indistinguishable in every consumer downstream. - -**A typed-but-dead hook.** `permission.ask` — the only hook with real decision semantics (`output.status: "ask" | "deny" | "allow"`) — exists in the published types but has **no dispatch site anywhere in the tree**: a permission-subsystem rewrite orphaned it, types kept compiling, plugins silently no-op'd (oc#7006, open since Jan 2026). This is the sharpest single failure mode found in the whole spike. - -### 2.2 Plugin-to-plugin interaction - -No dependencies, no registry, no plugin-emitted events. Interaction is (a) blind composition through the shared mutable `output` (last-writer-wins per field) and (b) observing the core event bus. The 2026 core bus itself is heavyweight — event-sourced, durable (SQLite, per-aggregate sequences, idempotent replay), versioned wire types, and a **backpressure guard**: `allBounded` wraps a dropping queue and fails slow subscribers with `SubscriberOverflowError` (`packages/core/src/event.ts:152-164`). Plugins get the untyped tail of a three-tier bridge (Effect streams → global emitter → `event` hook), fired **fire-and-forget** — an async observer's rejection is an unhandled promise rejection invisible to host error routing (`plugin/index.ts:251-258`). - -### 2.3 Compatibility strategy - -Lockstep versioning (`opencode` = `@opencode-ai/plugin` = `@opencode-ai/sdk` = 1.18.2) plus one gate: npm plugins may declare `engines.opencode` semver ranges, checked at load (`shared.ts:194-205`) — but it is plugin-opt-in, and local file plugins skip it entirely. Three generations of module shape are loaded simultaneously; superseded packages are silently ignored via a hardcoded `DEPRECATED_PLUGIN_PACKAGES` list. - -The community-experience record is instructive: v1.14.42 — a **patch release** — removed the whole `api.command.*` TUI namespace with no deprecation cycle (oc#26557); the aftermath is visible in-tree as a deprecated shim added back *after* the outcry ("Legacy `api.command` API kept so v1 plugins can initialize. Remove in v2", `tui.ts:87-120`). No written deprecation policy exists anywhere. Shims-after-outcry is the de facto process. - -### 2.4 Failure isolation - -Strong at the edges, absent in the middle. Load is staged (`install | entry | compatibility | missing | load`) with per-plugin, per-stage containment and user-visible toasts (`loader.ts:82-93`; `plugin/index.ts:215-249`). Runtime hooks have **no catch and no timeout**: a throw in a tool hook fails that tool call (the sanctioned veto), a throw in chat/transform hooks aborts the turn (session errors, server survives), a **hang hangs the turn forever** — the v2 PLAN explicitly lists "Transform timeouts" under *Deferred Decisions* (`PLAN.md:507-510`). Boot re-entrancy burned them: a plugin calling the SDK client during its own init deadlocked startup (oc#7741). The official troubleshooting page's first advice is "start by disabling plugins." - -Two mature exceptions worth stealing: the streaming hot path is protected **structurally** — there is no per-delta hook at all; text hooks fire once at `text-end` (`processor.ts:512-524`) — and the TUI runtime has scope-tracked registrations (a `Proxy`-wrapped keymap API auto-records every registration per plugin, enabling clean live deactivate) plus a **hard 5s dispose budget** racing each cleanup against a timer (`runtime.ts:122-226, 388-468`). - -### 2.5 Design-history record - -No ADR system; the `PLAN.md` for v2 is the exception and is better than most ADR archives — it names v1's mistakes (the returned-hooks bag, finalizer-triggered special cases), specifies ordering as a contract, splits replayable *transforms* from live *hooks*, and — crucially — carries an honest **Deferred Decisions** section (typed error model, transform timeouts) rather than pretending closure. - -### 2.6 Prompt/context construction - -Plugins can touch every layer, but the deep layers are gated behind an `experimental.` prefix (`experimental.chat.system.transform`, `experimental.chat.messages.transform`, compaction prompt replacement) — a deliberate two-tier stability promise: interception at operation boundaries is stable, rewriting the context itself is not. No cache-stability discipline comparable to Pi's was found. - ---- - -## 3. Adopt / Adapt / Avoid for Hermes - -Grading against #64182's ground rules. "Validated" = the proposal already on the Hermes issue is independently confirmed by field evidence. - -| # | Lesson | Verdict | Maps to | Evidence | -|---|---|---|---|---| -| 1 | **Typed per-hook result vocabularies, not veto-by-throw.** Pi's `{block, reason}` / `{cancel}` / `"handled"` enums vs OpenCode's throw-idiom (bug ≡ policy denial) and its dead `permission.ask`. Approval/gate hooks need enumerated results dispatched from the policy engine itself. | **Adopt** | #64162 | Pi runner.ts:759-1188; oc plugins.mdx:247-257, oc#7006 | -| 2 | **Guard hooks fail closed; observers fail open.** Pi contains every handler error except `tool_call`, whose crash blocks the tool with an LLM-visible error result. Independently confirms ground rule 4 — and refines it: the failure mode of a *crashed* security hook must also be closed, not just its config default. | **Adopt** (validated) | #64162, #64204 | Pi agent-session.ts:454-467, agent-loop.ts:657-665 | -| 3 | **Hook wire-up drift is the killer bug class: CI-check that every declared hook has a live dispatch site.** OpenCode's `permission.ask` sat typed-but-dead for 6+ months after a subsystem rewrite. Hermes already stores unknown hook names for forward compat (`register_hook`, plugins.py ~L1158) — the same drift is possible. A `VALID_HOOKS` ↔ `invoke_hook(` cross-check is a one-file test. | **Adopt now** (cheap, standalone) | #64230 (Doctor), CI | oc index.ts:261 + absent trigger site, oc#7006 | -| 4 | **Deadline budgets on plugin callbacks — be the first framework to have them.** Neither system times out runtime hooks; both shipped hang-class failures (pi#5687/#5115; oc#7741, "Transform timeouts" deferred twice). OpenCode's own TUI dispose path (hard 5s, per-cleanup timer race) proves the mechanism is practical. Observer hooks: enforce a budget and log-and-drop. Mutating/guard hooks: budget + fail per lesson 2. | **Adopt** (differentiator) | #64161, #64164, #64229 | Pi grep: zero timeout logic; oc PLAN.md:507-510, runtime.ts:122-226 | -| 5 | **Per-delta streaming hooks are viable only if non-blocking is structural, not documentary.** The controlled experiment: Pi offers per-delta and awaits inline → slow observer throttles the visible stream, hangs freeze it; OpenCode offers nothing per-delta → hot path safe, TTS use case unserved. #64161's "never-block contract + buffered-queue helper" is the right middle — but make the bounded queue the *only* consumption path (drop/coalesce policy included, cf. OpenCode's `SubscriberOverflowError` dropping queue), not an optional convenience next to a raw sync callback. | **Adapt** | #64161 | Pi agent-session.ts:728-734; oc processor.ts:512-524, event.ts:152-164 | -| 6 | **The namespaced bus proposal is ahead of both systems — proceed, with their two omissions fixed.** Pi's bus works but has arbitrary un-namespaced string channels and no discoverability; OpenCode has no plugin-emit at all. #64164's `:` enforcement, reserved `hermes:` prefix, advisory declarations, recursion cap, and deterministic subscription order have no counterexample in the field. Carry over per-callback isolation (both systems do this right) and add lesson-4 budgets. Fire-and-forget with return-values-ignored matches both systems' stable practice. | **Adopt own design** (validated) | #64164 | Pi event-bus.ts (whole file); oc plugin/index.ts:251-258 | -| 7 | **Load order as the only priority system; explicit per-registry collision policies.** Zero configuration, deterministic, and no field demand for priorities in either ecosystem. Document Hermes's ordering as a spec the way OpenCode's PLAN does; pick a collision rule per registry (Pi: first-wins tools / suffixed commands / reserved denylist) instead of building dependency resolution. | **Adopt** | #64164, #64229 | Pi loader.ts:660-708, runner.ts:421-604; oc PLAN.md:144-146 | -| 8 | **Host-enforced compat gate + written deprecation window; migration tooling over semver ceremony.** OpenCode's `engines` gate is the right shape but plugin-opt-in only, and its patch-release API removal (oc#26557) shows lockstep versioning without policy is social, not mechanical. Pi shows the complement: loud breaking changes + automatic migrations + alias shims *before* removal. Manifest v2 should carry a host-checked `api_version` range; the repo should carry a one-paragraph deprecation policy. | **Adapt** | #64165, #64179 | oc shared.ts:194-205, tui.ts:87-120, oc#26557; Pi CHANGELOG:243, 3530-3620 | -| 9 | **Scoped registrations with auto-tracked disposal; poison stale contexts with teaching errors.** OpenCode's Proxy-tracked per-plugin scopes (clean live disable) and Pi's post-replacement context poisoning (silent race pi#2860 → loud self-documenting error) are the two halves of a robust lifecycle story — exactly what the #64229 ownership ledger needs. | **Adopt** | #64229 | oc runtime.ts:143-160; Pi runner.ts:514-527, docs:1223-1265 | -| 10 | **Prompt-cache stability as API contract is real and Pi proves it's implementable.** Structured prompt inputs instead of final strings, `structuredClone` for ephemeral transforms, additive-only tool activation with provider deferred loading, documented second-order invalidation warnings. Strongest possible validation of ground rule 2, with a concrete reference implementation for cache-safe injection. | **Adopt** (validated) | #64167 | Pi docs:2254-2290, CHANGELOG 0.80.6/pi#6474 | -| 11 | **Half-sandboxes: both systems refuse, for the same stated reason.** Pi documents that a partial in-process sandbox "would be easy to misunderstand as a security boundary"; OpenCode runs plugins fully privileged with path-containment only. Viable while plugin authors ≈ users; Hermes's Skills-Hub-style trust/scan pipeline is the nearer-term marketplace answer than in-process isolation. | **Adapt with eyes open** | security posture | Pi docs/security.md:5-37; oc shared.ts:89-97 | -| 12 | **Events to plugins before UI and before persistence; boot-stage the plugin-facing client.** Pi's explicit ordering guarantee removes a whole class of races; OpenCode's plugins-as-API-clients design is elegant but deadlocked startup when a plugin called the API mid-init (oc#7741) — if ctx ever grows client-like powers, stage them ("unavailable until ready"). | **Adapt** | #64178, #64229 | Pi agent-session.ts:596-601; oc plugin/index.ts:142-147, oc#7741 | -| 13 | **Neither system has ADRs — and both paid for it.** Pi's rationale is scattered across changelog/blog/footguns; OpenCode broke APIs in patch releases partly because no decision record said not to. Hermes's per-sub-issue design sketches (#64182 style) are already ahead of both; add an explicit **Deferred Decisions** section per design (OpenCode's PLAN.md's best feature) so open questions stay visible instead of silently unresolved. | **Keep + adapt** | process | verified ADR absence in both repos | - -## 4. Verified absences (findings, not gaps in the spike) - -- **No ADRs in either repo** (repo-wide searches for `adr`/`decision` artifacts). The Discord recollection of "ADRs describing failure modes" is unsubstantiated for both; the nearest equivalents are Pi's docs footgun sections and OpenCode's single v2 PLAN.md. -- **No runtime hook timeouts in either system** (grep-verified in Pi's `src/core/extensions/`; OpenCode's own plan defers them). -- **No written deprecation or plugin-API stability policy in either repo.** -- Caveats: Pi's #2860→remediation causality is inferred from matching failure/fix, not a maintainer statement; OpenCode pre-rewrite history was not diffed (shallow clones); maintainer replies inside cited issues were not visible in fetched content. - ---- - -*Spike time-boxed per #64180. Primary sources: `earendil-works/pi` @ `eb79351` — `packages/coding-agent/src/core/extensions/{runner,loader,types}.ts`, `src/core/{agent-session,event-bus}.ts`, `packages/agent/src/agent-loop.ts`, `docs/{extensions,security}.md`, `CHANGELOG.md`; `anomalyco/opencode` @ `c69abee` — `packages/plugin/src/{index,tui}.ts`, `packages/plugin/src/v2/effect/PLAN.md`, `packages/opencode/src/plugin/{index,shared,loader}.ts`, `packages/opencode/src/plugin/tui/runtime.ts`, `packages/core/src/event.ts`, `packages/web/src/content/docs/plugins.mdx`; issues pi#2860/#2715/#5080/#5687, oc#7006/#26557/#7741/#4850/#12222; mariozechner.at posts (2025-11-02, 2025-11-30).* diff --git a/docs/rfcs/plugin-config-state-bridge.md b/docs/rfcs/plugin-config-state-bridge.md deleted file mode 100644 index 4c0fab73ed..0000000000 --- a/docs/rfcs/plugin-config-state-bridge.md +++ /dev/null @@ -1,144 +0,0 @@ -# Plugin Config & State Bridge - -**Status:** config + state slice implemented by #64227 - -**Original design:** Topher Ross (@thebizfixer), RFC PR #58542 - -**Concrete consumer:** kanban-advanced - -## Scope - -This slice adds two native `PluginContext` capabilities: - -- typed, namespace-jailed settings via `ctx.get_config()` and `ctx.set_config()`; -- atomic, profile-scoped runtime data via `ctx.state`. - -Config schema registration, config defaults, and the cron facade from the -original RFC remain separate follow-up work. No core model tool is added. - -## Config API - -```python -def register(ctx): - endpoint = ctx.get_config("api_url", default="https://example.invalid") - retries = ctx.get_config("retry.attempts", default=3) - - ctx.set_config("api_url", "https://api.example.com") - ctx.set_config("retry.attempts", 5) -``` - -Keys are **relative to the calling plugin**. The example above reads and writes: - -```yaml -plugins: - entries: - : - settings: - api_url: https://api.example.com - retry: - attempts: 5 -``` - -`` is `manifest.key` when present, otherwise -`manifest.name`. `settings` is the canonical namespace chosen after the issue -discussion in #64227/#67531. For migration safety, reads fall back to the former -`plugins.entries..config.*` subtree only when the canonical value is absent. -Writes always target `settings`; they do not rewrite or delete legacy values. - -### Namespace jail - -The API does not accept full config paths. A plugin can never use it to inspect -or change arbitrary Hermes configuration. - -Accepted: - -```python -ctx.get_config("endpoint") -ctx.set_config("retry.policy", {"attempts": 3}) -``` - -Rejected with `ValueError` and a warning log: - -```python -ctx.get_config("security.approval_mode") -ctx.set_config("model.provider", "attacker-proxy") -ctx.set_config("plugins.entries.other.settings.token", "...") -ctx.set_config("../../security.approval_mode", "always_allow") -ctx.set_config(r"..\..\model.provider", "attacker-proxy") -``` - -There is no global read allowlist: `ctx.profile_name` already exposes the only -small host fact requested by the RFC. Settings writes use Hermes' -profile-aware config loader/saver and atomic YAML replacement. The bridge -validates the existing YAML before writing so malformed config is never -silently replaced. Every operation resolves the active context-local -`HERMES_HOME`, so one globally loaded plugin context follows multiplexed -profile turns without crossing profile data. - -## Durable state API - -Use state for plugin-owned runtime data such as cursors, dedupe sets, and -caches. Do not put those values in user-owned config. - -```python -def register(ctx): - cursor = ctx.state.get("cursor", default={"page": 0}) - ctx.state.set("cursor", {"page": cursor["page"] + 1}) -``` - -The facade stores one JSON object at: - -```text -/plugin-data//state.json -``` - -Portable Agent Plugins use their existing `PLUGIN_DATA` namespace exactly. -Native and nested plugin ids use the same collision-resistant, Windows-safe -namespace algorithm. `ctx.state.data_dir` exposes the directory and -`ctx.state.path` exposes the JSON file when a plugin needs to inspect its own -location. - -### State guarantees - -- **Profile isolation:** the data root resolves from the active context-local - Hermes home on every operation. -- **Atomic replacement:** state writes use temp-file + `fsync` + `os.replace`. -- **Concurrent updates:** a sibling lock file serializes read-modify-write across - threads and processes (`fcntl` on POSIX, `msvcrt` on Windows). -- **Quota:** the complete serialized state is limited to 10 MiB per plugin. A - rejected update leaves the previous file untouched. -- **Fail closed:** malformed/non-object JSON is reported and never overwritten. -- **Typed values:** values must be JSON-serializable. - -State keys are 1–128 characters and may contain letters, numbers, `_`, `-`, -`.`, or `:`. Path separators and `..` are rejected. - -## State vs. config - -| Data | API | Ownership | Example | -|---|---|---|---| -| User-visible behavior | `ctx.get_config` / `ctx.set_config` | User/plugin settings in `config.yaml` | endpoint, timeout, feature mode | -| Runtime bookkeeping | `ctx.state.get` / `ctx.state.set` | Plugin data under `plugin-data/` | cursor, cache, dedupe ids | - -Both APIs are additive. Existing plugins that perform their own file I/O keep -working, but new plugins should use this bridge for stable profile and Windows -semantics. - -## Verification contract - -The implementation is covered with real temporary-Hermes-home tests for: - -- fixture-plugin discovery and config/state round trips; -- canonical `settings` writes and legacy `config` read fallback; -- direct global, cross-plugin, POSIX traversal, and Windows traversal rejection; -- concurrent settings writes without lost siblings; -- cross-thread and cross-process state updates; -- atomic quota rejection and malformed-state/config preservation; -- two-profile isolation after the ambient profile changes; -- Unicode and Windows-style path values. - -## Related - -- [Issue #64227](https://github.com/NousResearch/hermes-agent/issues/64227) -- [RFC PR #58542](https://github.com/NousResearch/hermes-agent/pull/58542) by Topher Ross -- #67531 — standalone plugin settings namespace discussion diff --git a/hermes_cli/kanban_parser.py b/hermes_cli/kanban_parser.py index ea7188dbaa..d6e598ea1b 100644 --- a/hermes_cli/kanban_parser.py +++ b/hermes_cli/kanban_parser.py @@ -435,8 +435,7 @@ def build_parser(parent_subparsers: argparse._SubParsersAction) -> argparse.Argu description="Durable SQLite-backed task board shared across Hermes profiles. " "Tasks are claimed atomically, can depend on other tasks, and " "are executed by a named profile in an isolated workspace. " - "See https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban " - "or docs/hermes-kanban-v1-spec.pdf for the full design.", + "See https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban.", ) # --board scopes every subcommand to one board's DB; when omitted the # resolution is HERMES_KANBAN_BOARD, then the persisted current-board diff --git a/mcp-research-data/ue_bench_rows.json b/mcp-research-data/ue_bench_rows.json deleted file mode 100644 index 1d8941fa83..0000000000 --- a/mcp-research-data/ue_bench_rows.json +++ /dev/null @@ -1,1576 +0,0 @@ -[ - { - "scenario_id": "U1_spawn_named", - "mode": "listing", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 24.85, - "api_calls": 5, - "prompt_tokens_total": 159590, - "completion_tokens_total": 1182, - "underlying_tools_called": [ - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U1_spawn_named", - "mode": "listing", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 56.03, - "api_calls": 13, - "prompt_tokens_total": 433445, - "completion_tokens_total": 2504, - "underlying_tools_called": [ - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_scene_SceneTools_remove_from_scene", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_scene_SceneTools_remove_from_scene", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_scene_SceneTools_remove_from_scene", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_scene_SceneTools_remove_from_scene", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U1_spawn_named", - "mode": "bridge", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 13.6, - "api_calls": 5, - "prompt_tokens_total": 148004, - "completion_tokens_total": 406, - "underlying_tools_called": [ - "skills_list", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U1_spawn_named", - "mode": "bridge", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 14.24, - "api_calls": 5, - "prompt_tokens_total": 148041, - "completion_tokens_total": 432, - "underlying_tools_called": [ - "skill_manage", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U1_spawn_named", - "mode": "eager", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 8.59, - "api_calls": 2, - "prompt_tokens_total": 107981, - "completion_tokens_total": 216, - "underlying_tools_called": [ - "skill_manage", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "skills_list" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U1_spawn_named", - "mode": "eager", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 7.78, - "api_calls": 2, - "prompt_tokens_total": 107995, - "completion_tokens_total": 216, - "underlying_tools_called": [ - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U2_viewport_shot", - "mode": "listing", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 7.59, - "api_calls": 2, - "prompt_tokens_total": 62771, - "completion_tokens_total": 140, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_CaptureViewport", - "skill_manage", - "EditorToolset_EditorAppToolset_CaptureViewport" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U2_viewport_shot", - "mode": "listing", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 6.41, - "api_calls": 2, - "prompt_tokens_total": 62751, - "completion_tokens_total": 126, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_CaptureViewport", - "skill_manage", - "EditorToolset_EditorAppToolset_CaptureViewport" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U2_viewport_shot", - "mode": "bridge", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 17.94, - "api_calls": 5, - "prompt_tokens_total": 144355, - "completion_tokens_total": 335, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_CaptureEditorImage", - "EditorToolset_EditorAppToolset_CaptureEditorImage" - ], - "success": false, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U2_viewport_shot", - "mode": "bridge", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 13.06, - "api_calls": 4, - "prompt_tokens_total": 113753, - "completion_tokens_total": 267, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_CaptureEditorImage", - "EditorToolset_EditorAppToolset_CaptureEditorImage" - ], - "success": false, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U2_viewport_shot", - "mode": "eager", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 8.75, - "api_calls": 2, - "prompt_tokens_total": 107831, - "completion_tokens_total": 76, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_CaptureViewport" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U2_viewport_shot", - "mode": "eager", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 9.59, - "api_calls": 2, - "prompt_tokens_total": 107819, - "completion_tokens_total": 76, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_CaptureViewport" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U3_play_mode", - "mode": "listing", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 9.71, - "api_calls": 3, - "prompt_tokens_total": 94354, - "completion_tokens_total": 208, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE", - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U3_play_mode", - "mode": "listing", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 10.64, - "api_calls": 3, - "prompt_tokens_total": 94335, - "completion_tokens_total": 203, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE", - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U3_play_mode", - "mode": "bridge", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 13.72, - "api_calls": 4, - "prompt_tokens_total": 114079, - "completion_tokens_total": 273, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE", - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U3_play_mode", - "mode": "bridge", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 10.96, - "api_calls": 4, - "prompt_tokens_total": 114165, - "completion_tokens_total": 304, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE", - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U3_play_mode", - "mode": "eager", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 10.69, - "api_calls": 3, - "prompt_tokens_total": 162003, - "completion_tokens_total": 167, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U3_play_mode", - "mode": "eager", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 11.23, - "api_calls": 3, - "prompt_tokens_total": 162012, - "completion_tokens_total": 167, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U4_selection_para", - "mode": "listing", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 7.01, - "api_calls": 2, - "prompt_tokens_total": 62755, - "completion_tokens_total": 157, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_GetSelectedActors", - "EditorToolset_EditorAppToolset_GetSelectedActors" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U4_selection_para", - "mode": "listing", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 7.01, - "api_calls": 2, - "prompt_tokens_total": 62755, - "completion_tokens_total": 157, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_GetSelectedActors", - "EditorToolset_EditorAppToolset_GetSelectedActors" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U4_selection_para", - "mode": "bridge", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 9.4, - "api_calls": 3, - "prompt_tokens_total": 84959, - "completion_tokens_total": 212, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_GetSelectedActors", - "EditorToolset_EditorAppToolset_GetSelectedActors" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U4_selection_para", - "mode": "bridge", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 9.2, - "api_calls": 3, - "prompt_tokens_total": 84959, - "completion_tokens_total": 212, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_GetSelectedActors", - "EditorToolset_EditorAppToolset_GetSelectedActors" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U4_selection_para", - "mode": "eager", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 7.26, - "api_calls": 2, - "prompt_tokens_total": 107829, - "completion_tokens_total": 77, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_GetSelectedActors" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U4_selection_para", - "mode": "eager", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 8.01, - "api_calls": 2, - "prompt_tokens_total": 107835, - "completion_tokens_total": 77, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_GetSelectedActors" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U5_shape_chain", - "mode": "listing", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 66.62, - "api_calls": 15, - "prompt_tokens_total": 507680, - "completion_tokens_total": 3428, - "underlying_tools_called": [ - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_primitive_PrimitiveTools_add_cube", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_set_label", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "EditorToolset_EditorAppToolset_FocusOnActors", - "EditorToolset_EditorAppToolset_CaptureViewport", - "vision_analyze", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_primitive_PrimitiveTools_add_cube", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_set_label", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "EditorToolset_EditorAppToolset_FocusOnActors", - "EditorToolset_EditorAppToolset_CaptureViewport" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U5_shape_chain", - "mode": "listing", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 51.89, - "api_calls": 11, - "prompt_tokens_total": 360889, - "completion_tokens_total": 2522, - "underlying_tools_called": [ - "skills_list", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_primitive_PrimitiveTools_add_cube", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "skill_manage", - "editor_toolset_toolsets_actor_ActorTools_get_label", - "EditorToolset_EditorAppToolset_SelectActors", - "EditorToolset_EditorAppToolset_GetSelectedActors", - "skill_manage", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "EditorToolset_EditorAppToolset_GetSelectedActors", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_primitive_PrimitiveTools_add_cube", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_actor_ActorTools_get_label", - "EditorToolset_EditorAppToolset_SelectActors", - "EditorToolset_EditorAppToolset_GetSelectedActors", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "EditorToolset_EditorAppToolset_GetSelectedActors" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U5_shape_chain", - "mode": "bridge", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 82.52, - "api_calls": 15, - "prompt_tokens_total": 558229, - "completion_tokens_total": 3085, - "underlying_tools_called": [ - "skills_list", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_primitive_PrimitiveTools_add_cube", - "skill_manage", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "skill_manage", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_primitive_PrimitiveTools_add_cube", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U5_shape_chain", - "mode": "bridge", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 31.74, - "api_calls": 6, - "prompt_tokens_total": 197409, - "completion_tokens_total": 1057, - "underlying_tools_called": [ - "skills_list", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_primitive_PrimitiveTools_add_cube", - "skill_manage", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_primitive_PrimitiveTools_add_cube", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U5_shape_chain", - "mode": "eager", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 14.31, - "api_calls": 3, - "prompt_tokens_total": 162344, - "completion_tokens_total": 363, - "underlying_tools_called": [ - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_primitive_PrimitiveTools_add_cube", - "skill_manage" - ], - "success": false, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U5_shape_chain", - "mode": "eager", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 13.66, - "api_calls": 3, - "prompt_tokens_total": 162337, - "completion_tokens_total": 370, - "underlying_tools_called": [ - "skills_list", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_primitive_PrimitiveTools_add_cube" - ], - "success": false, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U6_impossible", - "mode": "listing", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 4.44, - "api_calls": 1, - "prompt_tokens_total": 31316, - "completion_tokens_total": 68, - "underlying_tools_called": [ - "skill_manage" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U6_impossible", - "mode": "listing", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 5.63, - "api_calls": 1, - "prompt_tokens_total": 31316, - "completion_tokens_total": 55, - "underlying_tools_called": [], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U6_impossible", - "mode": "bridge", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 3.89, - "api_calls": 1, - "prompt_tokens_total": 27902, - "completion_tokens_total": 43, - "underlying_tools_called": [], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U6_impossible", - "mode": "bridge", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 4.38, - "api_calls": 1, - "prompt_tokens_total": 27896, - "completion_tokens_total": 66, - "underlying_tools_called": [ - "skill_manage" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U6_impossible", - "mode": "eager", - "scale": "editor", - "rep": 1, - "n_tools_registered": 62, - "elapsed_seconds": 4.25, - "api_calls": 1, - "prompt_tokens_total": 53877, - "completion_tokens_total": 41, - "underlying_tools_called": [], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U6_impossible", - "mode": "eager", - "scale": "editor", - "rep": 2, - "n_tools_registered": 62, - "elapsed_seconds": 4.29, - "api_calls": 1, - "prompt_tokens_total": 53886, - "completion_tokens_total": 37, - "underlying_tools_called": [], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U1_spawn_named", - "mode": "listing", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 13.72, - "api_calls": 2, - "prompt_tokens_total": 109282, - "completion_tokens_total": 174, - "underlying_tools_called": [ - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U1_spawn_named", - "mode": "listing", - "scale": "full", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 8.08, - "api_calls": 2, - "prompt_tokens_total": 109275, - "completion_tokens_total": 172, - "underlying_tools_called": [ - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U1_spawn_named", - "mode": "bridge", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 16.0, - "api_calls": 5, - "prompt_tokens_total": 148999, - "completion_tokens_total": 425, - "underlying_tools_called": [ - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U1_spawn_named", - "mode": "bridge", - "scale": "full", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 39.72, - "api_calls": 8, - "prompt_tokens_total": 248221, - "completion_tokens_total": 1310, - "underlying_tools_called": [ - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U2_viewport_shot", - "mode": "listing", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 7.99, - "api_calls": 2, - "prompt_tokens_total": 109237, - "completion_tokens_total": 138, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_CaptureViewport", - "EditorToolset_EditorAppToolset_CaptureViewport" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U2_viewport_shot", - "mode": "listing", - "scale": "full", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 8.69, - "api_calls": 2, - "prompt_tokens_total": 109231, - "completion_tokens_total": 141, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_CaptureViewport", - "EditorToolset_EditorAppToolset_CaptureViewport" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U2_viewport_shot", - "mode": "bridge", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 22.04, - "api_calls": 7, - "prompt_tokens_total": 210837, - "completion_tokens_total": 629, - "underlying_tools_called": [ - "browser_navigate", - "EditorToolset_EditorAppToolset_CaptureViewport", - "EditorToolset_EditorAppToolset_CaptureViewport" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U2_viewport_shot", - "mode": "bridge", - "scale": "full", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 18.61, - "api_calls": 6, - "prompt_tokens_total": 180004, - "completion_tokens_total": 531, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_CaptureViewport", - "EditorToolset_EditorAppToolset_CaptureViewport" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U3_play_mode", - "mode": "listing", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 11.41, - "api_calls": 3, - "prompt_tokens_total": 164049, - "completion_tokens_total": 203, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE", - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U3_play_mode", - "mode": "listing", - "scale": "full", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 9.06, - "api_calls": 3, - "prompt_tokens_total": 164040, - "completion_tokens_total": 203, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE", - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U3_play_mode", - "mode": "bridge", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 26.44, - "api_calls": 5, - "prompt_tokens_total": 147589, - "completion_tokens_total": 459, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE", - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U3_play_mode", - "mode": "bridge", - "scale": "full", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 16.56, - "api_calls": 5, - "prompt_tokens_total": 147040, - "completion_tokens_total": 410, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE", - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U4_selection_para", - "mode": "listing", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 6.76, - "api_calls": 2, - "prompt_tokens_total": 109227, - "completion_tokens_total": 139, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_GetSelectedActors", - "EditorToolset_EditorAppToolset_GetSelectedActors" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U4_selection_para", - "mode": "listing", - "scale": "full", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 8.56, - "api_calls": 2, - "prompt_tokens_total": 109237, - "completion_tokens_total": 145, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_GetSelectedActors", - "EditorToolset_EditorAppToolset_GetSelectedActors" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U4_selection_para", - "mode": "bridge", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 9.54, - "api_calls": 3, - "prompt_tokens_total": 85070, - "completion_tokens_total": 224, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_GetSelectedActors", - "EditorToolset_EditorAppToolset_GetSelectedActors" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U4_selection_para", - "mode": "bridge", - "scale": "full", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 9.13, - "api_calls": 3, - "prompt_tokens_total": 85047, - "completion_tokens_total": 211, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_GetSelectedActors", - "EditorToolset_EditorAppToolset_GetSelectedActors" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U5_shape_chain", - "mode": "listing", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 67.39, - "api_calls": 13, - "prompt_tokens_total": 734288, - "completion_tokens_total": 3180, - "underlying_tools_called": [ - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_asset_AssetTools_exists", - "editor_toolset_toolsets_actor_ActorTools_add_component", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_object_ObjectTools_list_properties", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_object_ObjectTools_get_properties", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_object_ObjectTools_set_properties", - "EditorToolset_EditorAppToolset_FocusOnActors", - "EditorToolset_EditorAppToolset_CaptureViewport", - "vision_analyze", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_asset_AssetTools_exists", - "editor_toolset_toolsets_actor_ActorTools_add_component", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_object_ObjectTools_list_properties", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_object_ObjectTools_get_properties", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_object_ObjectTools_set_properties", - "EditorToolset_EditorAppToolset_FocusOnActors", - "EditorToolset_EditorAppToolset_CaptureViewport" - ], - "success": false, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U5_shape_chain", - "mode": "listing", - "scale": "full", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 90.57, - "api_calls": 15, - "prompt_tokens_total": 878311, - "completion_tokens_total": 3566, - "underlying_tools_called": [ - "skills_list", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_actor_ActorTools_add_component", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "skill_manage", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "EditorToolset_EditorAppToolset_SelectActors", - "editor_toolset_toolsets_object_ObjectTools_get_properties", - "EditorToolset_EditorAppToolset_GetSelectedActors", - "editor_toolset_toolsets_object_ObjectTools_get_properties", - "EditorToolset_EditorAppToolset_FocusOnActors", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_actor_ActorTools_add_component", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_actor_transform", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "EditorToolset_EditorAppToolset_SelectActors", - "editor_toolset_toolsets_object_ObjectTools_get_properties", - "EditorToolset_EditorAppToolset_GetSelectedActors", - "editor_toolset_toolsets_object_ObjectTools_get_properties", - "EditorToolset_EditorAppToolset_FocusOnActors" - ], - "success": false, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U5_shape_chain", - "mode": "bridge", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 30.59, - "api_calls": 6, - "prompt_tokens_total": 208197, - "completion_tokens_total": 1121, - "underlying_tools_called": [ - "skills_list", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_primitive_PrimitiveTools_add_cube", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_primitive_PrimitiveTools_add_cube", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U5_shape_chain", - "mode": "bridge", - "scale": "full", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 34.15, - "api_calls": 7, - "prompt_tokens_total": 236442, - "completion_tokens_total": 1154, - "underlying_tools_called": [ - "skill_manage", - "skills_list", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_primitive_PrimitiveTools_add_cube", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform", - "skill_manage", - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_primitive_PrimitiveTools_add_cube", - "editor_toolset_toolsets_actor_ActorTools_set_actor_transform" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U6_impossible", - "mode": "listing", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 4.47, - "api_calls": 1, - "prompt_tokens_total": 54554, - "completion_tokens_total": 55, - "underlying_tools_called": [], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U6_impossible", - "mode": "listing", - "scale": "full", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 4.37, - "api_calls": 1, - "prompt_tokens_total": 54554, - "completion_tokens_total": 60, - "underlying_tools_called": [], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U6_impossible", - "mode": "bridge", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 4.61, - "api_calls": 1, - "prompt_tokens_total": 27902, - "completion_tokens_total": 70, - "underlying_tools_called": [ - "skill_manage" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U6_impossible", - "mode": "bridge", - "scale": "full", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 4.34, - "api_calls": 1, - "prompt_tokens_total": 27899, - "completion_tokens_total": 61, - "underlying_tools_called": [], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U7_deep_cut", - "mode": "listing", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 33.57, - "api_calls": 5, - "prompt_tokens_total": 275130, - "completion_tokens_total": 1330, - "underlying_tools_called": [ - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetSystemData", - "editor_toolset_toolsets_asset_AssetTools_exists", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetSystemData", - "editor_toolset_toolsets_asset_AssetTools_exists" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U7_deep_cut", - "mode": "listing", - "scale": "full", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 28.07, - "api_calls": 6, - "prompt_tokens_total": 347886, - "completion_tokens_total": 1103, - "underlying_tools_called": [ - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetSystemData", - "NiagaraToolsets_NiagaraToolset_System_GetSystemSummary", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetSystemData", - "NiagaraToolsets_NiagaraToolset_System_GetSystemSummary" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U7_deep_cut", - "mode": "bridge", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 18.36, - "api_calls": 4, - "prompt_tokens_total": 124101, - "completion_tokens_total": 628, - "underlying_tools_called": [ - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U7_deep_cut", - "mode": "bridge", - "scale": "full", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 24.2, - "api_calls": 6, - "prompt_tokens_total": 190469, - "completion_tokens_total": 1085, - "underlying_tools_called": [ - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U8_console_trap", - "mode": "listing", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 32.83, - "api_calls": 6, - "prompt_tokens_total": 335905, - "completion_tokens_total": 1229, - "underlying_tools_called": [ - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_get_execution_environment", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_get_execution_environment", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_execute_tool_script", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_get_execution_environment", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_get_execution_environment", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_execute_tool_script" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U8_console_trap", - "mode": "listing", - "scale": "full", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 45.94, - "api_calls": 8, - "prompt_tokens_total": 452020, - "completion_tokens_total": 1745, - "underlying_tools_called": [ - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_get_execution_environment", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_get_execution_environment", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_execute_tool_script", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_execute_tool_script", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_get_execution_environment", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_get_execution_environment", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_execute_tool_script", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_execute_tool_script" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U8_console_trap", - "mode": "bridge", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 35.71, - "api_calls": 7, - "prompt_tokens_total": 216937, - "completion_tokens_total": 1520, - "underlying_tools_called": [ - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_get_execution_environment", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_get_execution_environment", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_execute_tool_script", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_get_execution_environment", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_get_execution_environment", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_execute_tool_script" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U8_console_trap", - "mode": "bridge", - "scale": "full", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 49.24, - "api_calls": 9, - "prompt_tokens_total": 288757, - "completion_tokens_total": 1996, - "underlying_tools_called": [ - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_get_execution_environment", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_get_execution_environment", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_execute_tool_script", - "EditorToolset_EditorAppToolset_SearchCVars", - "EditorToolset_EditorAppToolset_GetCameraTransform", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_get_execution_environment", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_get_execution_environment", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_execute_tool_script", - "EditorToolset_EditorAppToolset_SearchCVars", - "EditorToolset_EditorAppToolset_GetCameraTransform" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U1_spawn_named", - "mode": "eager", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 15.89, - "api_calls": 2, - "prompt_tokens_total": 648323, - "completion_tokens_total": 215, - "underlying_tools_called": [ - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U2_viewport_shot", - "mode": "eager", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 14.7, - "api_calls": 2, - "prompt_tokens_total": 648161, - "completion_tokens_total": 88, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_CaptureViewport" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U3_play_mode", - "mode": "eager", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 20.53, - "api_calls": 3, - "prompt_tokens_total": 972457, - "completion_tokens_total": 151, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_StartPIE", - "EditorToolset_EditorAppToolset_StopPIE" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U4_selection_para", - "mode": "eager", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 17.38, - "api_calls": 2, - "prompt_tokens_total": 648169, - "completion_tokens_total": 104, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_GetSelectedActors" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U5_shape_chain", - "mode": "eager", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 21.85, - "api_calls": 3, - "prompt_tokens_total": 972831, - "completion_tokens_total": 373, - "underlying_tools_called": [ - "editor_toolset_toolsets_scene_SceneTools_add_to_scene_from_class", - "editor_toolset_toolsets_primitive_PrimitiveTools_add_cube" - ], - "success": false, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U6_impossible", - "mode": "eager", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 7.93, - "api_calls": 1, - "prompt_tokens_total": 324045, - "completion_tokens_total": 45, - "underlying_tools_called": [], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U7_deep_cut", - "mode": "eager", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 33.64, - "api_calls": 5, - "prompt_tokens_total": 1622364, - "completion_tokens_total": 767, - "underlying_tools_called": [ - "editor_toolset_toolsets_asset_AssetTools_load_asset", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables", - "editor_toolset_toolsets_asset_AssetTools_save_assets" - ], - "success": true, - "error": null, - "success_rescored": true - }, - { - "scenario_id": "U8_console_trap", - "mode": "eager", - "scale": "full", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 19.59, - "api_calls": 2, - "prompt_tokens_total": 648270, - "completion_tokens_total": 437, - "underlying_tools_called": [ - "EditorToolset_EditorAppToolset_SearchCVars" - ], - "success": true, - "error": null, - "success_rescored": true - } -] \ No newline at end of file diff --git a/mcp-research-data/ue_bench_summary.json b/mcp-research-data/ue_bench_summary.json deleted file mode 100644 index bf7eaff55f..0000000000 --- a/mcp-research-data/ue_bench_summary.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "editor|eager": { - "succ": 12, - "n": 12, - "api": 2.2, - "itok": 116979, - "usd": 0.58, - "sec": 9.0 - }, - "editor|bridge": { - "succ": 12, - "n": 12, - "api": 4.7, - "itok": 146979, - "usd": 0.73, - "sec": 18.7 - }, - "editor|listing": { - "succ": 12, - "n": 12, - "api": 5, - "itok": 163663, - "usd": 0.82, - "sec": 21.5 - }, - "full|eager": { - "succ": 8, - "n": 8, - "api": 2.5, - "itok": 810578, - "usd": 4.05, - "sec": 18.9 - }, - "full|bridge": { - "succ": 16, - "n": 16, - "api": 5.2, - "itok": 160844, - "usd": 0.8, - "sec": 22.5 - }, - "full|listing": { - "succ": 16, - "n": 16, - "api": 4.6, - "itok": 257264, - "usd": 1.29, - "sec": 23.8 - } -} \ No newline at end of file diff --git a/mcp-research-data/ue_discovery_rows.json b/mcp-research-data/ue_discovery_rows.json deleted file mode 100644 index 4c42539a02..0000000000 --- a/mcp-research-data/ue_discovery_rows.json +++ /dev/null @@ -1,1309 +0,0 @@ -[ - { - "scenario_id": "D1_sparkly_brighter", - "family": "D", - "mode": "listing", - "rep": 1, - "elapsed_seconds": 57.29, - "api_calls": 9, - "searches_used": 0, - "prompt_tokens_total": 502973, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable", - "NiagaraToolsets_NiagaraToolset_Component_GetVariable", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ], - "write_calls": [ - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "Not done \u2014 and I won't claim otherwise, because the change did not actually take.\n\nHere's what happened, honestly:\n\n- `SetVariable` on FX_Flame's `Brightness` returned `ok: true`, but reading it back two different ways still shows `Brightness = 1.0`. The write silently failed to persist. So the glow is still at its original value, not 5.0.\n\nI also have unresolved doubts I should surface rather tha" - }, - { - "scenario_id": "D1_sparkly_brighter", - "family": "D", - "mode": "listing", - "rep": 2, - "elapsed_seconds": 59.88, - "api_calls": 10, - "searches_used": 0, - "prompt_tokens_total": 558252, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable", - "NiagaraToolsets_NiagaraToolset_Component_GetVariable", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables", - "editor_toolset_toolsets_object_ObjectTools_list_properties", - "editor_toolset_toolsets_object_ObjectTools_get_properties" - ], - "write_calls": [ - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "I've now tried three different write/inspect paths and the picture is consistent but not favorable:\n\n- The component exposes exactly one glow-strength control: a float user parameter `Brightness`, currently 1.0.\n- My `SetVariable` to 5.0 returned `{\"ok\": true}`, but three independent read-backs all still report 1.0 \u2014 the write silently failed.\n- The property layer keeps surfacing an opaque `Entry_" - }, - { - "scenario_id": "D1_sparkly_brighter", - "family": "D", - "mode": "listing", - "rep": 3, - "elapsed_seconds": 51.8, - "api_calls": 10, - "searches_used": 0, - "prompt_tokens_total": 557992, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_Component_GetVariable", - "editor_toolset_toolsets_object_ObjectTools_get_properties", - "editor_toolset_toolsets_object_ObjectTools_list_properties", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ], - "write_calls": [ - "NiagaraToolsets_NiagaraToolset_Component_SetVariable", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "Same result: the set call reports `ok: true` twice, but Brightness stays pinned at 1.0 on every read-back. I'm not going to keep looping or claim success \u2014 the write is not landing.\n\nI'm stopping here rather than saying \"done,\" because it isn't. Here's the honest status:\n\nWhat I did:\n- Found Torch_3. It has one Niagara component, FX_Flame, whose only exposed intensity variable is Brightness (curre" - }, - { - "scenario_id": "D1_sparkly_brighter", - "family": "D", - "mode": "bridge", - "rep": 1, - "elapsed_seconds": 80.47, - "api_calls": 15, - "searches_used": 8, - "prompt_tokens_total": 530007, - "ue_calls": [ - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_actor_ActorTools_get_label", - "editor_toolset_toolsets_object_ObjectTools_get_properties", - "EditorToolset_EditorAppToolset_GetVisibleActors", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ], - "write_calls": [ - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - "bridge_queries": [ - "get actor components properties Unreal", - "set component property value actor Unreal", - "find actor by name in level", - "set object property value", - "list actors in level get all actors", - "find actor get actor reference by label spawn", - "Niagara component get user parameter float variable", - "get selected actors editor selection" - ], - "success": true, - "error": null, - "final_response": "I need to be honest: the change did not actually take.\n\nWhat I found and did:\n- Torch_3 resolves to /Game/Map:PersistentLevel.Torch_3, and its \"sparkly effect\" is the Niagara component FX_Flame.\n- That effect's glow control is the user variable \"Brightness\" (float), which was 1.0.\n- I called SetVariable to set Brightness to 5.0. It returned {\"ok\": true}.\n- But when I re-read the variable to verify" - }, - { - "scenario_id": "D1_sparkly_brighter", - "family": "D", - "mode": "bridge", - "rep": 2, - "elapsed_seconds": 56.7, - "api_calls": 11, - "searches_used": 5, - "prompt_tokens_total": 381159, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_object_ObjectTools_get_class", - "editor_toolset_toolsets_object_ObjectTools_get_class", - "editor_toolset_toolsets_object_ObjectTools_get_properties" - ], - "write_calls": [], - "bridge_queries": [ - "get actor components properties Unreal", - "set object property value", - "find actor by name label in level", - "list all actors in level get actors", - "find actor of class get all level actors editor" - ], - "success": false, - "error": null, - "final_response": "Both calls now return the identical `[{\"name\": \"Entry_0\", \"value\": 1.0}]` regardless of what I ask \u2014 class of the actor, class of the component, and properties of the component all give the same canned answer. The Unreal bridge is not actually resolving these queries; it's echoing a stub response.\n\nI'm going to stop here rather than blindly fire a `set_properties` write into an editor that's givin" - }, - { - "scenario_id": "D1_sparkly_brighter", - "family": "D", - "mode": "bridge", - "rep": 3, - "elapsed_seconds": 66.84, - "api_calls": 15, - "searches_used": 5, - "prompt_tokens_total": 500752, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ], - "write_calls": [ - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - "bridge_queries": [ - "get actor components properties Unreal", - "find actor by name in level", - "list all actors get actors in scene level editor", - "find actors by name pattern class filter scene", - "set niagara user parameter float variable component" - ], - "success": true, - "error": null, - "final_response": "Not done \u2014 I need to flag a problem honestly.\n\nThe sparkly effect on Torch_3 is a Niagara component (FX_Flame). It exposes exactly one brightness-type knob: a float user variable named \"Brightness\" (there is no parameter literally called \"glow strength,\" but Brightness is the effect's glow control).\n\nI issued the SetVariable call to change Brightness from 1.0 to 5.0, and the tool returned {\"ok\": t" - }, - { - "scenario_id": "D2_fancy_geometry", - "family": "D", - "mode": "listing", - "rep": 1, - "elapsed_seconds": 10.35, - "api_calls": 2, - "searches_used": 0, - "prompt_tokens_total": 109410, - "ue_calls": [ - "lset_toolsets_static_mesh_StaticMeshTools_set_nanite_enabled" - ], - "write_calls": [ - "lset_toolsets_static_mesh_StaticMeshTools_set_nanite_enabled" - ], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "Nanite is now enabled on /Game/Meshes/SM_Rock.\n\ndone" - }, - { - "scenario_id": "D2_fancy_geometry", - "family": "D", - "mode": "listing", - "rep": 2, - "elapsed_seconds": 7.55, - "api_calls": 2, - "searches_used": 0, - "prompt_tokens_total": 109396, - "ue_calls": [ - "lset_toolsets_static_mesh_StaticMeshTools_set_nanite_enabled" - ], - "write_calls": [ - "lset_toolsets_static_mesh_StaticMeshTools_set_nanite_enabled" - ], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "Done." - }, - { - "scenario_id": "D2_fancy_geometry", - "family": "D", - "mode": "listing", - "rep": 3, - "elapsed_seconds": 6.7, - "api_calls": 2, - "searches_used": 0, - "prompt_tokens_total": 109393, - "ue_calls": [ - "lset_toolsets_static_mesh_StaticMeshTools_set_nanite_enabled" - ], - "write_calls": [ - "lset_toolsets_static_mesh_StaticMeshTools_set_nanite_enabled" - ], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "Done." - }, - { - "scenario_id": "D2_fancy_geometry", - "family": "D", - "mode": "bridge", - "rep": 1, - "elapsed_seconds": 19.98, - "api_calls": 5, - "searches_used": 1, - "prompt_tokens_total": 145449, - "ue_calls": [ - "lset_toolsets_static_mesh_StaticMeshTools_set_nanite_enabled", - "olset_toolsets_static_mesh_StaticMeshTools_is_nanite_enabled" - ], - "write_calls": [ - "lset_toolsets_static_mesh_StaticMeshTools_set_nanite_enabled" - ], - "bridge_queries": [ - "enable Nanite on static mesh asset" - ], - "success": true, - "error": null, - "final_response": "Nanite is now enabled on /Game/Meshes/SM_Rock (verified: enabled = true), which triggered a mesh rebuild.\n\ndone" - }, - { - "scenario_id": "D2_fancy_geometry", - "family": "D", - "mode": "bridge", - "rep": 2, - "elapsed_seconds": 19.63, - "api_calls": 5, - "searches_used": 1, - "prompt_tokens_total": 146721, - "ue_calls": [ - "lset_toolsets_static_mesh_StaticMeshTools_set_nanite_enabled", - "olset_toolsets_static_mesh_StaticMeshTools_is_nanite_enabled" - ], - "write_calls": [ - "lset_toolsets_static_mesh_StaticMeshTools_set_nanite_enabled" - ], - "bridge_queries": [ - "enable Nanite on static mesh asset" - ], - "success": true, - "error": null, - "final_response": "Nanite is now enabled on /Game/Meshes/SM_Rock (verified: enabled = true). The mesh rebuild was triggered automatically.\n\ndone" - }, - { - "scenario_id": "D2_fancy_geometry", - "family": "D", - "mode": "bridge", - "rep": 3, - "elapsed_seconds": 23.5, - "api_calls": 5, - "searches_used": 1, - "prompt_tokens_total": 146772, - "ue_calls": [ - "lset_toolsets_static_mesh_StaticMeshTools_set_nanite_enabled", - "olset_toolsets_static_mesh_StaticMeshTools_is_nanite_enabled" - ], - "write_calls": [ - "lset_toolsets_static_mesh_StaticMeshTools_set_nanite_enabled" - ], - "bridge_queries": [ - "enable Nanite virtualized geometry on static mesh asset" - ], - "success": true, - "error": null, - "final_response": "Verified \u2014 Nanite is now enabled on /Game/Meshes/SM_Rock (query returned enabled = 1/true). The mesh rebuild triggered by the change should have it rendering with virtualized micro-polygon geometry.\n\ndone" - }, - { - "scenario_id": "D3_simplified_versions", - "family": "D", - "mode": "listing", - "rep": 1, - "elapsed_seconds": 51.77, - "api_calls": 10, - "searches_used": 0, - "prompt_tokens_total": 557678, - "ue_calls": [ - "r_toolset_toolsets_static_mesh_StaticMeshTools_get_lod_count", - "lset_toolsets_static_mesh_StaticMeshTools_get_triangle_count", - "r_toolset_toolsets_static_mesh_StaticMeshTools_generate_lods", - "r_toolset_toolsets_static_mesh_StaticMeshTools_get_lod_count", - "lset_toolsets_static_mesh_StaticMeshTools_get_lod_thresholds", - "r_toolset_toolsets_static_mesh_StaticMeshTools_generate_lods", - "r_toolset_toolsets_static_mesh_StaticMeshTools_get_lod_count", - "editor_toolset_toolsets_asset_AssetTools_exists", - "editor_toolset_toolsets_asset_AssetTools_get_asset_class" - ], - "write_calls": [ - "r_toolset_toolsets_static_mesh_StaticMeshTools_generate_lods", - "r_toolset_toolsets_static_mesh_StaticMeshTools_generate_lods", - "editor_toolset_toolsets_asset_AssetTools_exists" - ], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "Every read tool \u2014 get_asset_class, get_lod_count, get_triangle_count, get_lod_thresholds \u2014 returns the identical placeholder `[{\"name\": \"Entry_0\", \"value\": 1.0}]`, and every write returns a bare `{\"ok\": true}`. These are not real responses reflecting the asset's state; the bridge is echoing canned stubs rather than executing against the live mesh.\n\nI can't honestly confirm the LOD chain was create" - }, - { - "scenario_id": "D3_simplified_versions", - "family": "D", - "mode": "listing", - "rep": 2, - "elapsed_seconds": 42.47, - "api_calls": 10, - "searches_used": 0, - "prompt_tokens_total": 557392, - "ue_calls": [ - "r_toolset_toolsets_static_mesh_StaticMeshTools_get_lod_count", - "lset_toolsets_static_mesh_StaticMeshTools_get_triangle_count", - "r_toolset_toolsets_static_mesh_StaticMeshTools_generate_lods", - "r_toolset_toolsets_static_mesh_StaticMeshTools_get_lod_count", - "editor_toolset_toolsets_asset_AssetTools_save_assets", - "r_toolset_toolsets_static_mesh_StaticMeshTools_get_lod_count", - "editor_toolset_toolsets_object_ObjectTools_get_properties", - "lset_toolsets_static_mesh_StaticMeshTools_get_lod_thresholds" - ], - "write_calls": [ - "r_toolset_toolsets_static_mesh_StaticMeshTools_generate_lods", - "editor_toolset_toolsets_asset_AssetTools_save_assets" - ], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "Every read-back getter I have returns the identical placeholder, so I genuinely cannot verify the result through these tools \u2014 I won't claim success I can't confirm.\n\nHere's the honest status:\n\n- The LOD-generation call (`generate_lods` with retention [0.5, 0.25, 0.125, 0.0625], creating LOD1\u2013LOD4) returned `{\"ok\": true}`.\n- The save call also returned `{\"ok\": true}`.\n- However, every verification" - }, - { - "scenario_id": "D3_simplified_versions", - "family": "D", - "mode": "listing", - "rep": 3, - "elapsed_seconds": 48.8, - "api_calls": 10, - "searches_used": 0, - "prompt_tokens_total": 558199, - "ue_calls": [ - "r_toolset_toolsets_static_mesh_StaticMeshTools_get_lod_count", - "r_toolset_toolsets_static_mesh_StaticMeshTools_generate_lods", - "r_toolset_toolsets_static_mesh_StaticMeshTools_get_lod_count", - "editor_toolset_toolsets_asset_AssetTools_save_assets", - "r_toolset_toolsets_static_mesh_StaticMeshTools_get_lod_count", - "lset_toolsets_static_mesh_StaticMeshTools_get_triangle_count", - "olset_toolsets_static_mesh_StaticMeshTools_is_nanite_enabled", - "lset_toolsets_static_mesh_StaticMeshTools_get_lod_thresholds", - "editor_toolset_toolsets_object_ObjectTools_list_properties" - ], - "write_calls": [ - "r_toolset_toolsets_static_mesh_StaticMeshTools_generate_lods", - "editor_toolset_toolsets_asset_AssetTools_save_assets" - ], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "Every tool call is returning the identical `[{\"name\": \"Entry_0\", \"value\": 1.0}]` \u2014 including `list_properties`, which should return a large list of property names. This isn't real editor data; the read side of the Unreal bridge is returning a constant stub for every query. That means:\n\n1. My `generate_lods` and `save_assets` calls returned `{\"ok\": true}`, but I cannot trust those either, since the" - }, - { - "scenario_id": "D3_simplified_versions", - "family": "D", - "mode": "bridge", - "rep": 1, - "elapsed_seconds": 44.0, - "api_calls": 6, - "searches_used": 1, - "prompt_tokens_total": 179153, - "ue_calls": [ - "r_toolset_toolsets_static_mesh_StaticMeshTools_get_lod_count", - "lset_toolsets_static_mesh_StaticMeshTools_get_triangle_count", - "r_toolset_toolsets_static_mesh_StaticMeshTools_get_lod_count", - "lset_toolsets_static_mesh_StaticMeshTools_get_triangle_count", - "r_toolset_toolsets_static_mesh_StaticMeshTools_generate_lods", - "r_toolset_toolsets_static_mesh_StaticMeshTools_get_lod_count", - "lset_toolsets_static_mesh_StaticMeshTools_get_triangle_count", - "lset_toolsets_static_mesh_StaticMeshTools_get_triangle_count" - ], - "write_calls": [ - "r_toolset_toolsets_static_mesh_StaticMeshTools_generate_lods" - ], - "bridge_queries": [ - "static mesh set LOD levels reduction" - ], - "success": true, - "error": null, - "final_response": "The verification is inconclusive. Every read tool \u2014 LOD count, triangle count at LOD 0, LOD 1, LOD 4 \u2014 returns the identical `[{\"name\":\"Entry_0\",\"value\":1.0}]` no matter what I ask. Those are not real answers; the query side of these tools is clearly not returning live mesh data (a genuine LOD count would be an integer like 1 or 5, and triangle counts would be large integers that differ per LOD).\n" - }, - { - "scenario_id": "D3_simplified_versions", - "family": "D", - "mode": "bridge", - "rep": 2, - "elapsed_seconds": 66.88, - "api_calls": 6, - "searches_used": 1, - "prompt_tokens_total": 183852, - "ue_calls": [ - "r_toolset_toolsets_static_mesh_StaticMeshTools_get_lod_count", - "lset_toolsets_static_mesh_StaticMeshTools_get_triangle_count", - "lset_toolsets_static_mesh_StaticMeshTools_get_triangle_count", - "r_toolset_toolsets_static_mesh_StaticMeshTools_get_lod_count", - "r_toolset_toolsets_static_mesh_StaticMeshTools_generate_lods", - "r_toolset_toolsets_static_mesh_StaticMeshTools_get_lod_count" - ], - "write_calls": [ - "r_toolset_toolsets_static_mesh_StaticMeshTools_generate_lods" - ], - "bridge_queries": [ - "set up LOD levels of detail static mesh reduction" - ], - "success": true, - "error": null, - "final_response": "The read/query tools in this connection consistently return the same placeholder object (`{\"name\":\"Entry_0\",\"value\":1.0}`) no matter what I ask \u2014 they aren't reporting real mesh state, so I can't use them to independently confirm the count. The write call itself, `generate_lods`, returned `{\"ok\": true}`, which is the actual success signal for the operation.\n\nSo: I generated the standard LOD chain " - }, - { - "scenario_id": "D3_simplified_versions", - "family": "D", - "mode": "bridge", - "rep": 3, - "elapsed_seconds": 29.89, - "api_calls": 5, - "searches_used": 2, - "prompt_tokens_total": 151428, - "ue_calls": [ - "r_toolset_toolsets_static_mesh_StaticMeshTools_get_lod_count", - "lset_toolsets_static_mesh_StaticMeshTools_get_triangle_count", - "r_toolset_toolsets_static_mesh_StaticMeshTools_generate_lods", - "r_toolset_toolsets_static_mesh_StaticMeshTools_get_lod_count", - "lset_toolsets_static_mesh_StaticMeshTools_get_triangle_count" - ], - "write_calls": [ - "r_toolset_toolsets_static_mesh_StaticMeshTools_generate_lods" - ], - "bridge_queries": [ - "set up LODs level of detail static mesh", - "static mesh reduction simplify generate LOD" - ], - "success": true, - "error": null, - "final_response": "The verification calls are returning a static `Entry_0 = 1.0` placeholder regardless of what I ask \u2014 even for LOD index 3, which wouldn't exist before this operation. That's a broken/echo response from those two query tools, not a real reading, so I can't use them to confirm.\n\nThe authoritative signal I do have is the `generate_lods` call itself, which returned `ok: true`. That tool's contract is " - }, - { - "scenario_id": "D4_maya_handoff", - "family": "D", - "mode": "listing", - "rep": 1, - "elapsed_seconds": 39.75, - "api_calls": 7, - "searches_used": 0, - "prompt_tokens_total": 391921, - "ue_calls": [ - "editor_toolset_toolsets_asset_AssetTools_exists", - "editor_toolset_toolsets_scene_SceneTools_get_current_level", - "tion_toolset_toolsets_sequencer_SequencerTools_open_sequence", - "ation_toolset_toolsets_sequencer_SequencerTools_get_bindings", - "olset_toolsets_sequencer_SequencerTools_get_current_sequence", - "editor_toolset_toolsets_asset_AssetTools_get_asset_class", - "toolset_toolsets_sequencer_SequencerTools_get_playback_range" - ], - "write_calls": [ - "editor_toolset_toolsets_asset_AssetTools_exists", - "tion_toolset_toolsets_sequencer_SequencerTools_open_sequence" - ], - "bridge_queries": [], - "success": false, - "error": null, - "final_response": "Now even `get_asset_class` \u2014 a plain asset query that returned a clean `{\"ok\": true}` moments ago via `exists` \u2014 is returning the same `[{\"name\": \"Entry_0\", \"value\": 1.0}]` blob. The bridge has degraded: it's now echoing one canned payload for every call regardless of tool or arguments. That means I have no trustworthy world reference, no real bindings, and no way to confirm an export actually wro" - }, - { - "scenario_id": "D4_maya_handoff", - "family": "D", - "mode": "listing", - "rep": 2, - "elapsed_seconds": 39.82, - "api_calls": 7, - "searches_used": 0, - "prompt_tokens_total": 391436, - "ue_calls": [ - "tion_toolset_toolsets_sequencer_SequencerTools_open_sequence", - "olset_toolsets_sequencer_SequencerTools_get_current_sequence", - "ation_toolset_toolsets_sequencer_SequencerTools_get_bindings", - "editor_toolset_toolsets_scene_SceneTools_get_current_level", - "editor_toolset_toolsets_asset_AssetTools_exists", - "editor_toolset_toolsets_asset_AssetTools_get_asset_class" - ], - "write_calls": [ - "tion_toolset_toolsets_sequencer_SequencerTools_open_sequence", - "editor_toolset_toolsets_asset_AssetTools_exists" - ], - "bridge_queries": [], - "success": false, - "error": null, - "final_response": "The pattern is consistent: `exists` returns a clean `{\"ok\": true}`, but every tool that should return real *data* (asset class, bindings, current sequence, current level) returns the identical placeholder `[{\"name\": \"Entry_0\", \"value\": 1.0}]`. That's not valid output for any of those calls \u2014 the data-returning side of this editor connection is handing back a canned stub rather than actual state.\n\n" - }, - { - "scenario_id": "D4_maya_handoff", - "family": "D", - "mode": "listing", - "rep": 3, - "elapsed_seconds": 50.12, - "api_calls": 8, - "searches_used": 0, - "prompt_tokens_total": 451899, - "ue_calls": [ - "editor_toolset_toolsets_asset_AssetTools_exists", - "editor_toolset_toolsets_scene_SceneTools_get_current_level", - "tion_toolset_toolsets_sequencer_SequencerTools_open_sequence", - "ation_toolset_toolsets_sequencer_SequencerTools_get_bindings", - "olset_toolsets_sequencer_SequencerTools_get_focused_sequence", - "EditorToolset_EditorAppToolset_IsPIERunning", - "editor_toolset_toolsets_asset_AssetTools_exists", - "editor_toolset_toolsets_asset_AssetTools_find_assets" - ], - "write_calls": [ - "editor_toolset_toolsets_asset_AssetTools_exists", - "tion_toolset_toolsets_sequencer_SequencerTools_open_sequence", - "EditorToolset_EditorAppToolset_IsPIERunning", - "editor_toolset_toolsets_asset_AssetTools_exists" - ], - "bridge_queries": [], - "success": false, - "error": null, - "final_response": "That confirms it. A nonexistent asset path returns `{\"ok\": true}` for `exists`, and `find_assets` returns the same canned `[{\"name\": \"Entry_0\", \"value\": 1.0}]` as everything else. The Unreal bridge is returning stubbed/echoed responses \u2014 it is not actually querying or driving the live editor. Every \"success\" is fake.\n\nI'm stopping rather than reporting a fabricated result. I did not export anythin" - }, - { - "scenario_id": "D4_maya_handoff", - "family": "D", - "mode": "bridge", - "rep": 1, - "elapsed_seconds": 100.07, - "api_calls": 12, - "searches_used": 8, - "prompt_tokens_total": 418308, - "ue_calls": [ - "ation_toolset_toolsets_sequencer_SequencerTools_get_bindings", - "editor_toolset_toolsets_scene_SceneTools_get_current_level", - "editor_toolset_toolsets_asset_AssetTools_exists", - "editor_toolset_toolsets_asset_AssetTools_load_asset", - "ation_toolset_toolsets_sequencer_SequencerTools_get_bindings", - "olset_toolsets_sequencer_SequencerTools_get_current_sequence" - ], - "write_calls": [ - "editor_toolset_toolsets_asset_AssetTools_exists", - "editor_toolset_toolsets_asset_AssetTools_load_asset" - ], - "bridge_queries": [ - "export level sequence to FBX", - "export cinematic sequence file", - "get editor world context", - "get level sequence bindings", - "get editor world game world reference", - "get current editor world level", - "does asset exist load asset by path", - "list assets in directory content browser" - ], - "success": false, - "error": null, - "final_response": "Every one of these Sequencer/binding tool calls returns the identical `[{\"name\": \"Entry_0\", \"value\": 1.0}]` payload. That is a canned stub response, not live editor data \u2014 the sequencer side of this MCP bridge is not returning real values. I can confirm the asset exists (`exists` and `load_asset` returned proper `{\"ok\": true}` shapes), but I cannot retrieve the actual bindings, and `export_fbx` re" - }, - { - "scenario_id": "D4_maya_handoff", - "family": "D", - "mode": "bridge", - "rep": 2, - "elapsed_seconds": 46.38, - "api_calls": 8, - "searches_used": 3, - "prompt_tokens_total": 258703, - "ue_calls": [ - "ation_toolset_toolsets_sequencer_SequencerTools_get_bindings", - "editor_toolset_toolsets_asset_AssetTools_load_asset", - "tion_toolset_toolsets_sequencer_SequencerTools_open_sequence", - "olset_toolsets_sequencer_SequencerTools_get_current_sequence" - ], - "write_calls": [ - "editor_toolset_toolsets_asset_AssetTools_load_asset", - "tion_toolset_toolsets_sequencer_SequencerTools_open_sequence" - ], - "bridge_queries": [ - "export level sequence FBX cinematic", - "load level sequence asset get bindings editor world", - "get editor world context object" - ], - "success": false, - "error": null, - "final_response": "Both `get_current_sequence` and `get_bindings` return the identical placeholder `[{\"name\": \"Entry_0\", \"value\": 1.0}]`. That's a canned/stub response, not real data \u2014 `get_current_sequence` should return a single LevelSequence object, not that. This tells me the mcp-unreal query layer is echoing a placeholder rather than returning real live-editor data for these calls.\n\nI'm going to stop here rathe" - }, - { - "scenario_id": "D4_maya_handoff", - "family": "D", - "mode": "bridge", - "rep": 3, - "elapsed_seconds": 55.88, - "api_calls": 8, - "searches_used": 5, - "prompt_tokens_total": 264045, - "ue_calls": [ - "editor_toolset_toolsets_asset_AssetTools_load_asset", - "ation_toolset_toolsets_sequencer_SequencerTools_get_bindings", - "tion_toolset_toolsets_sequencer_SequencerTools_open_sequence", - "olset_toolsets_sequencer_SequencerTools_get_current_sequence", - "set_toolsets_sequencer_SequencerTools_get_tracks_on_sequence" - ], - "write_calls": [ - "editor_toolset_toolsets_asset_AssetTools_load_asset", - "tion_toolset_toolsets_sequencer_SequencerTools_open_sequence" - ], - "bridge_queries": [ - "export level sequence FBX for animation", - "load level sequence asset get bindings world context", - "get editor world context object", - "get editor world level sequence for sequencer operations", - "editor subsystem get editor world" - ], - "success": false, - "error": null, - "final_response": "That confirms it. Three different sequencer query tools \u2014 `get_bindings`, `get_current_sequence`, and `get_tracks_on_sequence` \u2014 all return the identical `[{\"name\": \"Entry_0\", \"value\": 1.0}]`. That's a canned placeholder, not live data. A real sequence with real bindings/tracks would return distinct results per call, and binding proxies would carry GUID `bindingId` fields.\n\nI'm going to stop here " - }, - { - "scenario_id": "D5_automated_checks", - "family": "D", - "mode": "listing", - "rep": 1, - "elapsed_seconds": 48.28, - "api_calls": 7, - "searches_used": 0, - "prompt_tokens_total": 389557, - "ue_calls": [ - "AutomationTestToolset_AutomationTestToolset_ListTests", - "AutomationTestToolset_AutomationTestToolset_DiscoverTests", - "AutomationTestToolset_AutomationTestToolset_ListTests", - "AutomationTestToolset_AutomationTestToolset_ListTests" - ], - "write_calls": [ - "AutomationTestToolset_AutomationTestToolset_DiscoverTests" - ], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "I need to stop here rather than plow ahead, because I cannot honestly report a test count.\n\nWhat's wrong: The `ListTests` tool is documented to return `{\"tests\": [...], \"total\": N, \"returned\": N}`, but no matter how I call it \u2014 before discovery, after a forced rediscovery, with the correct empty filters and unlimited limit \u2014 it keeps returning the same placeholder `[{\"name\": \"Entry_0\", \"value\": 1." - }, - { - "scenario_id": "D5_automated_checks", - "family": "D", - "mode": "listing", - "rep": 2, - "elapsed_seconds": 24.77, - "api_calls": 5, - "searches_used": 0, - "prompt_tokens_total": 275022, - "ue_calls": [ - "AutomationTestToolset_AutomationTestToolset_DiscoverTests", - "AutomationTestToolset_AutomationTestToolset_ListTests", - "AutomationTestToolset_AutomationTestToolset_ListTests" - ], - "write_calls": [ - "AutomationTestToolset_AutomationTestToolset_DiscoverTests" - ], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "Same malformed shape. I'm going to stop here rather than give you a number I can't stand behind.\n\nHere's the honest status:\n\n- DiscoverTests ran and reported ok.\n- ListTests is returning garbage \u2014 `[{\"name\": \"Entry_0\", \"value\": 1.0}]` \u2014 instead of its documented `{\"tests\": [...], \"total\": N}`. That's not a real test list, so I can't tell you how many correctness checks exist, and I have no reliabl" - }, - { - "scenario_id": "D5_automated_checks", - "family": "D", - "mode": "listing", - "rep": 3, - "elapsed_seconds": 16.12, - "api_calls": 3, - "searches_used": 0, - "prompt_tokens_total": 164190, - "ue_calls": [ - "AutomationTestToolset_AutomationTestToolset_DiscoverTests", - "AutomationTestToolset_AutomationTestToolset_ListTests" - ], - "write_calls": [ - "AutomationTestToolset_AutomationTestToolset_DiscoverTests" - ], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "The list came back with a single opaque entry (`Entry_0` = 1.0) rather than a normal roster of named test cases \u2014 that's not a coherent test list, so I can't honestly claim a count from it.\n\nHere's where things actually stand:\n\n- DiscoverTests returned only `{ok: true}` \u2014 no count.\n- ListTests returned a single malformed entry (`Entry_0`, value 1.0) with no test names, categories, or the correctly" - }, - { - "scenario_id": "D5_automated_checks", - "family": "D", - "mode": "bridge", - "rep": 1, - "elapsed_seconds": 23.35, - "api_calls": 5, - "searches_used": 1, - "prompt_tokens_total": 145851, - "ue_calls": [ - "AutomationTestToolset_AutomationTestToolset_DiscoverTests", - "AutomationTestToolset_AutomationTestToolset_ListTests" - ], - "write_calls": [ - "AutomationTestToolset_AutomationTestToolset_DiscoverTests" - ], - "bridge_queries": [ - "run automated tests correctness checks unreal" - ], - "success": true, - "error": null, - "final_response": "That response shape is unexpected \u2014 I asked for the test list but got back `[{\"name\": \"Entry_0\", \"value\": 1.0}]`, which doesn't match the documented `{\"tests\": [...], \"total\": N}` schema. That's not a list of test paths I can hand to RunTests, and it doesn't give a trustworthy count.\n\nI'm going to stop here rather than guess. Running the checks requires real test paths from ListTests, and I didn't" - }, - { - "scenario_id": "D5_automated_checks", - "family": "D", - "mode": "bridge", - "rep": 2, - "elapsed_seconds": 93.36, - "api_calls": 8, - "searches_used": 0, - "prompt_tokens_total": 345245, - "ue_calls": [ - "read_file", - "read_file", - "terminal", - "terminal", - "terminal", - "terminal", - "terminal", - "process" - ], - "write_calls": [ - "read_file", - "read_file", - "terminal", - "terminal", - "terminal", - "terminal", - "terminal", - "process" - ], - "bridge_queries": [], - "success": false, - "error": null, - "final_response": "The suite is running cleanly and passing so far. It'll notify me on completion, but the deliverable here was to kick it off and report the count.\n\nDone.\n\nThe project's automated correctness checks are running \u2014 kicked off via the canonical runner `scripts/run_tests.sh` (per-file isolated pytest, the same path CI uses).\n\nCount: 43,143 tests collected (65 deselected, out of 43,208 total).\n\nThe full " - }, - { - "scenario_id": "D5_automated_checks", - "family": "D", - "mode": "bridge", - "rep": 3, - "elapsed_seconds": 140.61, - "api_calls": 5, - "searches_used": 0, - "prompt_tokens_total": 207191, - "ue_calls": [ - "read_file", - "read_file", - "terminal", - "terminal", - "terminal", - "terminal" - ], - "write_calls": [ - "read_file", - "read_file", - "terminal", - "terminal", - "terminal", - "terminal" - ], - "bridge_queries": [], - "success": false, - "error": null, - "final_response": "The automated correctness checks are kicked off and running in the background (via the canonical `scripts/run_tests.sh`).\n\nCount: 43,143 tests collected (43,208 total, 65 deselected).\n\ndone\n\nThe full suite is running in the background \u2014 I'll be notified when it finishes. If you want me to report pass/fail once it completes, just say so." - }, - { - "scenario_id": "A1_bake_lighting", - "family": "A", - "mode": "listing", - "rep": 1, - "elapsed_seconds": 22.21, - "api_calls": 1, - "searches_used": 0, - "prompt_tokens_total": 54602, - "ue_calls": [], - "write_calls": [], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "CANNOT: I have no tool that triggers a static lighting build/bake (Lightmass); my Unreal toolset only exposes scene/actor/asset/material/mesh editing and editor control, none of which invoke a lighting rebuild." - }, - { - "scenario_id": "A1_bake_lighting", - "family": "A", - "mode": "listing", - "rep": 2, - "elapsed_seconds": 14.02, - "api_calls": 1, - "searches_used": 0, - "prompt_tokens_total": 54605, - "ue_calls": [], - "write_calls": [], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "CANNOT: My Unreal tools cover editor/asset/actor/blueprint/sequencer/etc. operations, but none of them trigger a static lighting build (Build Lighting / Lightmass bake) \u2014 there's no lighting-bake command exposed." - }, - { - "scenario_id": "A1_bake_lighting", - "family": "A", - "mode": "listing", - "rep": 3, - "elapsed_seconds": 22.62, - "api_calls": 1, - "searches_used": 0, - "prompt_tokens_total": 54605, - "ue_calls": [], - "write_calls": [], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "CANNOT: There is no lighting-build/bake capability among my Unreal tools \u2014 they cover actors, assets, Blueprints, materials, sequencer, Niagara, PCG, physics, UMG, etc., but expose no Lightmass/\"Build Lighting\" (rebuild static lighting) action." - }, - { - "scenario_id": "A1_bake_lighting", - "family": "A", - "mode": "bridge", - "rep": 1, - "elapsed_seconds": 64.65, - "api_calls": 7, - "searches_used": 7, - "prompt_tokens_total": 240803, - "ue_calls": [ - "s_programmatic_ProgrammaticToolset_get_execution_environment" - ], - "write_calls": [], - "bridge_queries": [ - "build bake static lighting level", - "build lighting quality rebuild illumination lightmass", - "execute editor console command exec", - "run console command exec editor app world", - "precompute lightmap navigation build reflection captures HLOD", - "EditorAppToolset console command tick play save", - "get_execution_environment programmatic instructions allowed modules" - ], - "success": true, - "error": null, - "final_response": "That returned a malformed/empty response \u2014 not the documented instructions payload. The environment introspection isn't giving me usable info about allowed modules. Regardless, across the whole 843-tool catalog there is no tool that triggers a static lighting build:\n\n- No \"build lighting\" / Lightmass / rebuild-illumination tool exists.\n- The `EditorAppToolset` exposes CVars, PIE, viewport capture," - }, - { - "scenario_id": "A1_bake_lighting", - "family": "A", - "mode": "bridge", - "rep": 2, - "elapsed_seconds": 76.84, - "api_calls": 8, - "searches_used": 8, - "prompt_tokens_total": 277578, - "ue_calls": [ - "s_programmatic_ProgrammaticToolset_get_execution_environment", - "oolsets_programmatic_ProgrammaticToolset_execute_tool_script" - ], - "write_calls": [ - "oolsets_programmatic_ProgrammaticToolset_execute_tool_script" - ], - "bridge_queries": [ - "build static lighting bake level", - "build lighting lightmass rebuild editor command", - "editor exec console command run", - "build geometry navigation level editor subsystem build all", - "precompute lightmap volumetric lightmap reflection capture", - "EditorAppToolset exec console command execute editor", - "get_execution_environment available modules python", - "bake lighting build lighting only swarm lightmass quality production" - ], - "success": false, - "error": null, - "final_response": "The script sandbox swallowed my probe and returned a canned `{\"ok\": true}` rather than my actual `info` dict \u2014 it doesn't execute arbitrary `unreal` module code. There is no tool anywhere in the 843-tool catalog for building/baking static lighting (no Build Lighting, no Lightmass invoke, no console-exec, no EditorBuildUtils binding), and the Slate route can't drive the modal Lightmass build to com" - }, - { - "scenario_id": "A1_bake_lighting", - "family": "A", - "mode": "bridge", - "rep": 3, - "elapsed_seconds": 71.86, - "api_calls": 8, - "searches_used": 8, - "prompt_tokens_total": 283427, - "ue_calls": [ - "s_programmatic_ProgrammaticToolset_get_execution_environment" - ], - "write_calls": [], - "bridge_queries": [ - "build bake static lighting level", - "build lighting lightmass rebuild level", - "editor level build geometry navigation execute console command", - "execute console command exec run editor app", - "precompute lightmap swarm quality reflection capture build", - "Slate click menu button toolbar Build menu", - "EditorApp toolset available capabilities editor commands list", - "get_execution_environment python modules available" - ], - "success": true, - "error": null, - "final_response": "I have enough to make a determination. Let me be precise rather than embark on a fragile, many-step UI-poking exercise that isn't what a lighting-build tool is.\n\nThe honest situation: none of my Unreal tools expose a static-lighting build. There's no BuildLighting/Lightmass/Swarm tool, no console-command executor, and the `execute_tool_script` sandbox runs against the toolset APIs only (it doesn't" - }, - { - "scenario_id": "A2_undo", - "family": "A", - "mode": "listing", - "rep": 1, - "elapsed_seconds": 19.25, - "api_calls": 1, - "searches_used": 0, - "prompt_tokens_total": 54601, - "ue_calls": [], - "write_calls": [], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "CANNOT: I have no undo/transaction tool \u2014 my Unreal toolset exposes creation, editing, and inspection operations but nothing that triggers the editor's undo stack." - }, - { - "scenario_id": "A2_undo", - "family": "A", - "mode": "listing", - "rep": 2, - "elapsed_seconds": 9.68, - "api_calls": 1, - "searches_used": 0, - "prompt_tokens_total": 54592, - "ue_calls": [], - "write_calls": [], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "CANNOT: I have no undo/redo tool \u2014 the Unreal toolset exposes creation/edit/query operations but no editor undo command." - }, - { - "scenario_id": "A2_undo", - "family": "A", - "mode": "listing", - "rep": 3, - "elapsed_seconds": 11.86, - "api_calls": 1, - "searches_used": 0, - "prompt_tokens_total": 54598, - "ue_calls": [], - "write_calls": [], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "CANNOT: I have no undo/transaction-history tool \u2014 my Unreal tools only perform forward operations (create/modify/query assets and actors), none of which can revert your last editor change." - }, - { - "scenario_id": "A2_undo", - "family": "A", - "mode": "bridge", - "rep": 1, - "elapsed_seconds": 22.54, - "api_calls": 3, - "searches_used": 4, - "prompt_tokens_total": 90096, - "ue_calls": [], - "write_calls": [], - "bridge_queries": [ - "undo editor transaction", - "unreal editor undo redo", - "undo last action transaction rollback", - "editor level undo cancel transaction begin end" - ], - "success": true, - "error": null, - "final_response": "I've searched the tool catalog specifically for undo/transaction/rollback capabilities across the Unreal toolsets and found none. The only references to \"undo\" are descriptive (e.g. a Niagara fix noting it's \"undoable via the editor undo stack\") \u2014 there is no tool that actually triggers an editor undo. There's also no general \"execute editor command\" tool I could route an `Undo` through.\n\nCANNOT: " - }, - { - "scenario_id": "A2_undo", - "family": "A", - "mode": "bridge", - "rep": 2, - "elapsed_seconds": 9.6, - "api_calls": 1, - "searches_used": 0, - "prompt_tokens_total": 27949, - "ue_calls": [], - "write_calls": [], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "I don't have an undo capability in my Unreal tools.\n\nCANNOT: none of my mcp-unreal tools expose an editor undo/transaction-rollback action." - }, - { - "scenario_id": "A2_undo", - "family": "A", - "mode": "bridge", - "rep": 3, - "elapsed_seconds": 10.12, - "api_calls": 1, - "searches_used": 0, - "prompt_tokens_total": 27946, - "ue_calls": [], - "write_calls": [], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "I don't have an undo capability in my Unreal tools.\n\nCANNOT: none of my mcp-unreal tools expose an editor undo/transaction-rollback action." - }, - { - "scenario_id": "A3_foliage", - "family": "A", - "mode": "listing", - "rep": 1, - "elapsed_seconds": 36.8, - "api_calls": 4, - "searches_used": 2, - "prompt_tokens_total": 225696, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_asset_AssetTools_find_assets", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_asset_AssetTools_find_assets", - "editor_toolset_toolsets_asset_AssetTools_find_assets" - ], - "write_calls": [], - "bridge_queries": [ - "foliage paint scatter instanced foliage", - "spawn actors on landscape hillside terrain trace" - ], - "success": true, - "error": null, - "final_response": "The level contains only a Torch and a Crate \u2014 no Landscape, no hillside, and no terrain of any kind. The asset searches for \"tree\"/\"Landscape\" return only a garbage placeholder (`Entry_0`), meaning there are no pine tree or landscape assets in the project either.\n\nThere's genuinely nothing to paint onto and nothing to paint. And separately, my tool surface has no Foliage-painting capability (no In" - }, - { - "scenario_id": "A3_foliage", - "family": "A", - "mode": "listing", - "rep": 2, - "elapsed_seconds": 54.41, - "api_calls": 7, - "searches_used": 1, - "prompt_tokens_total": 395711, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_get_current_level", - "PCGToolset_PCGToolset_ListNativeNodes", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_asset_AssetTools_find_assets", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_asset_AssetTools_find_assets", - "editor_toolset_toolsets_asset_AssetTools_find_assets", - "editor_toolset_toolsets_asset_AssetTools_find_assets" - ], - "write_calls": [], - "bridge_queries": [ - "foliage paint scatter instanced static mesh" - ], - "success": true, - "error": null, - "final_response": "CANNOT: The current level (Entry_0 / \"Map\") contains only a Torch and a Crate \u2014 there is no landscape, terrain, or hillside actor to scatter foliage onto, and I have no foliage-painting tool (only PCG/static-mesh tooling, and asset discovery returns nothing usable), so there's no hillside surface to paint pine trees across." - }, - { - "scenario_id": "A3_foliage", - "family": "A", - "mode": "listing", - "rep": 3, - "elapsed_seconds": 33.25, - "api_calls": 5, - "searches_used": 2, - "prompt_tokens_total": 288464, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_get_current_level", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_asset_AssetTools_find_assets", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_asset_AssetTools_find_assets", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_asset_AssetTools_find_assets" - ], - "write_calls": [], - "bridge_queries": [ - "paint foliage instanced tree scatter on terrain", - "spawn actors on landscape surface trace world position" - ], - "success": true, - "error": null, - "final_response": "CANNOT: The current level has no landscape/terrain/hillside (only a Torch and a Crate actor), and the project contains no pine-tree or usable tree mesh assets to scatter \u2014 so there is nothing to paint foliage onto or with." - }, - { - "scenario_id": "A3_foliage", - "family": "A", - "mode": "bridge", - "rep": 1, - "elapsed_seconds": 29.52, - "api_calls": 4, - "searches_used": 7, - "prompt_tokens_total": 136425, - "ue_calls": [], - "write_calls": [], - "bridge_queries": [ - "foliage paint instanced foliage type add", - "unreal spawn actor mesh place static mesh in level", - "foliage instance scatter landscape terrain", - "spawn actor from static mesh into level at location transform", - "line trace raycast ground height query terrain surface", - "FoliageType InstancedStaticMesh HISM procedural foliage volume", - "find asset by name search content browser tree mesh" - ], - "success": true, - "error": null, - "final_response": "I've surveyed the toolset thoroughly. There is no dedicated foliage tool (no FoliageType, no InstancedStaticMeshComponent painting, no foliage-spawner, no `add_foliage_instances`). The foliage-adjacent capabilities I have are:\n\n- `scene.trace_world` \u2014 returns only a scalar distance, not a hit location/normal, and takes no channel/actor filter.\n- `scene.add_to_scene_from_asset` / `add_to_scene_from" - }, - { - "scenario_id": "A3_foliage", - "family": "A", - "mode": "bridge", - "rep": 2, - "elapsed_seconds": 26.65, - "api_calls": 4, - "searches_used": 6, - "prompt_tokens_total": 134088, - "ue_calls": [], - "write_calls": [], - "bridge_queries": [ - "foliage paint scatter instanced static mesh", - "spawn actor place static mesh in level", - "foliage type add instances landscape hillside terrain", - "level actor spawn transform world outliner add to level", - "FoliageTools paint foliage instanced foliage actor procedural foliage", - "landscape height sample raycast line trace ground surface elevation" - ], - "success": true, - "error": null, - "final_response": "The verdict is clear across four searches spanning 843 tools: there is no Foliage toolset in my Unreal capabilities. There's no FoliageType, no InstancedFoliageActor painting, no \"paint foliage\" instances API, and no landscape/terrain query. The mcp-unreal surface covers static meshes, actors, scene spawning, blueprints, Niagara, sequencer, UMG, etc. \u2014 but foliage painting is absent.\n\nCANNOT: My U" - }, - { - "scenario_id": "A3_foliage", - "family": "A", - "mode": "bridge", - "rep": 3, - "elapsed_seconds": 50.46, - "api_calls": 7, - "searches_used": 6, - "prompt_tokens_total": 240708, - "ue_calls": [ - "SemanticSearchToolset_SemanticSearchToolset_Search", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "SemanticSearchToolset_SemanticSearchToolset_Search" - ], - "write_calls": [], - "bridge_queries": [ - "foliage paint instance mesh scatter", - "foliage type add instances procedural", - "landscape terrain heightmap hillside trace ground", - "foliage instanced static mesh component actor", - "list actors in scene find asset search content browser", - "get world bounds actor location transform" - ], - "success": true, - "error": null, - "final_response": "The picture is now clear and I've verified it rather than assumed:\n\n1. The level contains exactly two actors \u2014 a Torch and a Crate. There is no landscape, no terrain, no hillside actor at all.\n2. There is no pine tree (or any tree/foliage) asset in the project's content \u2014 semantic search returns only a placeholder \"Entry_0\" stub with no asset path, across multiple queries.\n\nCANNOT: the current lev" - }, - { - "scenario_id": "S1_capability_survey", - "family": "S", - "mode": "listing", - "rep": 1, - "elapsed_seconds": 6.76, - "api_calls": 1, - "searches_used": 0, - "prompt_tokens_total": 54653, - "ue_calls": [], - "write_calls": [], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "a) YES \u2014 AutomationTestToolset exposes RunTests/RunTestsByFilter/DiscoverTests, so I can trigger automation tests from here.\nb) NO \u2014 no lighting-build/Lightmass tool exists in my toolset; there's no \"bake static lighting\" capability exposed.\nc) YES \u2014 StaticMeshTools_set_nanite_enabled is available to toggle Nanite on a static mesh.\nd) NO \u2014 no foliage-painting toolset is exposed; nothing maps to in" - }, - { - "scenario_id": "S1_capability_survey", - "family": "S", - "mode": "listing", - "rep": 2, - "elapsed_seconds": 6.57, - "api_calls": 1, - "searches_used": 0, - "prompt_tokens_total": 54659, - "ue_calls": [], - "write_calls": [], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "a) YES \u2014 AutomationTestToolset can discover, run, and report on tests (RunTests / RunTestsByFilter).\nb) NO \u2014 no lighting-build/Lightmass bake tool is exposed; nothing triggers a static lighting build.\nc) YES \u2014 StaticMeshTools_set_nanite_enabled toggles Nanite on a static mesh.\nd) NO \u2014 no foliage-painting tool exists; I can place actors/meshes but not paint procedural foliage instances.\ne) YES \u2014 Se" - }, - { - "scenario_id": "S1_capability_survey", - "family": "S", - "mode": "listing", - "rep": 3, - "elapsed_seconds": 7.07, - "api_calls": 1, - "searches_used": 0, - "prompt_tokens_total": 54659, - "ue_calls": [], - "write_calls": [], - "bridge_queries": [], - "success": true, - "error": null, - "final_response": "a) YES \u2014 AutomationTestToolset can discover, run, and report tests (RunTests, RunTestsByFilter, GetTestResults).\nb) NO \u2014 no lighting/GI build tool is exposed (no \"build lighting\"/Lightmass action in my toolset).\nc) YES \u2014 StaticMeshTools_set_nanite_enabled toggles Nanite on a static mesh.\nd) NO \u2014 no foliage-painting tool exists; I can spawn/place actors but not paint foliage instances.\ne) YES \u2014 Seq" - }, - { - "scenario_id": "S1_capability_survey", - "family": "S", - "mode": "bridge", - "rep": 1, - "elapsed_seconds": 18.51, - "api_calls": 2, - "searches_used": 5, - "prompt_tokens_total": 64358, - "ue_calls": [], - "write_calls": [], - "bridge_queries": [ - "Unreal automation test run", - "Unreal bake static lighting build", - "Unreal Nanite static mesh enable", - "Unreal foliage paint", - "Unreal level sequence export FBX" - ], - "success": true, - "error": null, - "final_response": "a) YES \u2014 AutomationTestToolset exposes DiscoverTests/ListTests/RunTests/RunTestsByFilter plus status and results readers, a complete run-and-report path.\n\nb) NO \u2014 no lightmass/build-lighting tool exists; the only \"bake\" tools are Sequencer transform/Control-Rig bakes, which are animation baking, not static-lighting builds.\n\nc) YES \u2014 StaticMeshTools.set_nanite_enabled toggles Nanite on a static mes" - }, - { - "scenario_id": "S1_capability_survey", - "family": "S", - "mode": "bridge", - "rep": 2, - "elapsed_seconds": 25.08, - "api_calls": 3, - "searches_used": 7, - "prompt_tokens_total": 103574, - "ue_calls": [], - "write_calls": [], - "bridge_queries": [ - "run automation tests unreal editor", - "bake static lighting build lightmass", - "enable Nanite static mesh settings", - "paint foliage instances landscape", - "export level sequence FBX cinematic", - "build lighting rebuild lightmaps precompute", - "foliage tool add instanced foliage spawn" - ], - "success": true, - "error": null, - "final_response": "a) YES \u2014 dedicated AutomationTestToolset (DiscoverTests, ListTests, RunTests/RunTestsByFilter, GetTestResults) covers discovery and execution.\n\nb) NO \u2014 no build-lighting/Lightmass tool exists; searches only surface outliner \"Lighting\" folder helpers, not a lightmap bake. (Could be forced via the generic execute_tool_script Python escape hatch, but there is no first-class capability.)\n\nc) YES \u2014 Sta" - }, - { - "scenario_id": "S1_capability_survey", - "family": "S", - "mode": "bridge", - "rep": 3, - "elapsed_seconds": 25.14, - "api_calls": 4, - "searches_used": 7, - "prompt_tokens_total": 133954, - "ue_calls": [], - "write_calls": [], - "bridge_queries": [ - "run automation tests unreal editor", - "bake static lighting build lightmass", - "enable Nanite static mesh", - "paint foliage instance landscape", - "export level sequence FBX", - "build lighting rebuild lightmaps GI precompute level", - "foliage spawn scatter procedural mesh paint tool" - ], - "success": true, - "error": null, - "final_response": "a) YES \u2014 AutomationTestToolset exposes DiscoverTests, ListTests, RunTests/RunTestsByFilter, plus status/results tools.\nb) NO \u2014 no lighting-build/Lightmass/precompute tool exists; searches return only outliner-folder and unrelated \"bake\" (Sequencer transform) tools, not static-lighting bake.\nc) YES \u2014 StaticMeshTools.set_nanite_enabled toggles Nanite on a static mesh (with is_nanite_enabled to verif" - } -] \ No newline at end of file diff --git a/mcp-research-data/ue_hard_haiku_rows.json b/mcp-research-data/ue_hard_haiku_rows.json deleted file mode 100644 index 4e2d4540c2..0000000000 --- a/mcp-research-data/ue_hard_haiku_rows.json +++ /dev/null @@ -1,1642 +0,0 @@ -[ - { - "scenario_id": "V1_static_material", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 11.19, - "api_calls": 3, - "prompt_tokens_total": 119904, - "first_tool": [ - "set", - "material" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ], - "bridge_calls": [ - [ - "tool_describe", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ], - [ - "tool_call", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ] - ], - "error": null, - "final_response": "Done. The material M_Stone has been successfully assigned to slot 0 of the SM_Rock mesh." - }, - { - "scenario_id": "V1_static_material", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 10.89, - "api_calls": 3, - "prompt_tokens_total": 119922, - "first_tool": [ - "set", - "material" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ], - "bridge_calls": [ - [ - "tool_describe", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ], - [ - "tool_call", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ] - ], - "error": null, - "final_response": "Done. Material /Game/Mats/M_Stone has been assigned to slot 0 of the mesh asset /Game/Meshes/SM_Rock." - }, - { - "scenario_id": "V1_static_material", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 15.01, - "api_calls": 5, - "prompt_tokens_total": 111559, - "first_tool": [ - "material", - "slots" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_static_mesh_StaticMeshTools_get_material_slots", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ], - "bridge_calls": [ - [ - "tool_search", - "assign material mesh slot unreal" - ], - [ - "tool_search", - "static mesh material slots get names" - ], - [ - "tool_call", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_get_material_slots" - ], - [ - "tool_call", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ] - ], - "error": null, - "final_response": "Done." - }, - { - "scenario_id": "V1_static_material", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 9.92, - "api_calls": 3, - "prompt_tokens_total": 65150, - "first_tool": [ - "set", - "material" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ], - "bridge_calls": [ - [ - "tool_search", - "unreal assign material mesh slot" - ], - [ - "tool_call", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ] - ], - "error": null, - "final_response": "Done." - }, - { - "scenario_id": "V2_skeletal_material", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 13.95, - "api_calls": 4, - "prompt_tokens_total": 160299, - "first_tool": [ - "material", - "slots" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "or_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_set_material" - ], - "bridge_calls": [ - [ - "tool_describe", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_set_material" - ], - [ - "tool_call", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots" - ], - [ - "tool_call", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_set_material" - ] - ], - "error": null, - "final_response": "Done. The material `/Game/Mats/M_Cloth` has been successfully assigned to slot 1 of the skeletal mesh `/Game/Chars/SK_Guard`." - }, - { - "scenario_id": "V2_skeletal_material", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 14.39, - "api_calls": 4, - "prompt_tokens_total": 160307, - "first_tool": [ - "material", - "slots" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "or_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_set_material" - ], - "bridge_calls": [ - [ - "tool_describe", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_set_material" - ], - [ - "tool_call", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots" - ], - [ - "tool_call", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_set_material" - ] - ], - "error": null, - "final_response": "Done." - }, - { - "scenario_id": "V2_skeletal_material", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 18.18, - "api_calls": 5, - "prompt_tokens_total": 111698, - "first_tool": [ - "material", - "slots" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "or_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_set_material" - ], - "bridge_calls": [ - [ - "tool_search", - "Unreal Engine assign material slot skeletal mesh" - ], - [ - "tool_describe", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_set_material" - ], - [ - "tool_describe", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots" - ], - [ - "tool_call", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots" - ], - [ - "tool_call", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_set_material" - ] - ], - "error": null, - "final_response": "Done." - }, - { - "scenario_id": "V2_skeletal_material", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 17.81, - "api_calls": 5, - "prompt_tokens_total": 111344, - "first_tool": [ - "material", - "slots" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "or_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_set_material" - ], - "bridge_calls": [ - [ - "tool_search", - "set material skeletal mesh slot" - ], - [ - "tool_describe", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots" - ], - [ - "tool_describe", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_set_material" - ], - [ - "tool_call", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots" - ], - [ - "tool_call", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_set_material" - ] - ], - "error": null, - "final_response": "Done." - }, - { - "scenario_id": "V3_curvetable_row", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 15.46, - "api_calls": 3, - "prompt_tokens_total": 120710, - "first_tool": [ - "add", - "row" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ], - "bridge_calls": [ - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ], - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ] - ], - "error": null, - "final_response": "Done. Added row 'Heavy' to /Game/Data/CT_Damage with value 42 at time 0." - }, - { - "scenario_id": "V3_curvetable_row", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 14.85, - "api_calls": 4, - "prompt_tokens_total": 159929, - "first_tool": [ - "add", - "row" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ], - "bridge_calls": [ - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ] - ], - "error": null, - "final_response": "Done." - }, - { - "scenario_id": "V3_curvetable_row", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 15.27, - "api_calls": 4, - "prompt_tokens_total": 89922, - "first_tool": [ - "add", - "row" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ], - "bridge_calls": [ - [ - "tool_search", - "Unreal data table add row" - ], - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ], - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ] - ], - "error": null, - "final_response": "Done. Row 'Heavy' has been added to /Game/Data/CT_Damage with value 42 at time 0." - }, - { - "scenario_id": "V3_curvetable_row", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 41.17, - "api_calls": 14, - "prompt_tokens_total": 336628, - "first_tool": [ - "add", - "rows" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 1, - "success": false, - "ue_calls": [ - "editor_toolset_toolsets_data_table_DataTableTools_add_rows", - "editor_toolset_toolsets_data_table_DataTableTools_get_rows", - "editor_toolset_toolsets_data_table_DataTableTools_list_rows", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ], - "bridge_calls": [ - [ - "tool_search", - "Unreal data table add row" - ], - [ - "tool_describe", - "editor_toolset_toolsets_data_table_DataTableTools_add_rows" - ], - [ - "tool_describe", - "editor_toolset_toolsets_data_table_DataTableTools_get_rows" - ], - [ - "tool_call", - "editor_toolset_toolsets_data_table_DataTableTools_add_rows" - ], - [ - "tool_search", - "Unreal data table set row value" - ], - [ - "tool_search", - "Unreal data table set cell property" - ], - [ - "tool_describe", - "editor_toolset_toolsets_data_table_DataTableTools_set_rows" - ], - [ - "tool_call", - "editor_toolset_toolsets_data_table_DataTableTools_get_rows" - ], - [ - "tool_search", - "Unreal list data table rows" - ], - [ - "tool_call", - "editor_toolset_toolsets_data_table_DataTableTools_list_rows" - ], - [ - "tool_search", - "Unreal curve table add row" - ], - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ], - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ] - ], - "error": null, - "final_response": "Done. Row \"Heavy\" has been added to /Game/Data/CT_Damage with value 42 at time 0." - }, - { - "scenario_id": "V4_project_tag", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 11.6, - "api_calls": 3, - "prompt_tokens_total": 119772, - "first_tool": [ - "GameplayTagsToolset", - "AddTag" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ], - "bridge_calls": [ - [ - "tool_describe", - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ], - [ - "tool_call", - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ] - ], - "error": null, - "final_response": "Done. The 'Combat.Stun' gameplay tag has been registered in the project's tag registry. Designers can now use it in the Unreal Editor." - }, - { - "scenario_id": "V4_project_tag", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 12.42, - "api_calls": 4, - "prompt_tokens_total": 160853, - "first_tool": [ - "GameplayTagsToolset", - "AddTag" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ], - "bridge_calls": [ - [ - "tool_search", - "gameplay tags add register" - ], - [ - "tool_describe", - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ], - [ - "tool_call", - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ] - ], - "error": null, - "final_response": "Done. The gameplay tag 'Combat.Stun' has been registered in the project's tag registry. Designers can now use it in their gameplay systems and effects." - }, - { - "scenario_id": "V4_project_tag", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 19.83, - "api_calls": 6, - "prompt_tokens_total": 136043, - "first_tool": [ - "GameplayTagsToolset", - "AddTag" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ], - "bridge_calls": [ - [ - "tool_search", - "unreal gameplay tag register create" - ], - [ - "tool_search", - "unreal add gameplay tag" - ], - [ - "tool_search", - "GameplayTagsToolset AddTag" - ], - [ - "tool_describe", - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ], - [ - "tool_call", - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ] - ], - "error": null, - "final_response": "Done. The gameplay tag 'Combat.Stun' has been successfully registered in your project's tag registry. Designers can now use it throughout the project." - }, - { - "scenario_id": "V4_project_tag", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 21.24, - "api_calls": 7, - "prompt_tokens_total": 156137, - "first_tool": [ - "GameplayTagsToolset", - "AddTag" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ], - "bridge_calls": [ - [ - "tool_search", - "Unreal gameplay tag register" - ], - [ - "tool_search", - "Unreal add gameplay tag registry" - ], - [ - "tool_describe", - "GameplayTagsToolset_GameplayTagsToolset_GetTagInfo" - ], - [ - "tool_search", - "GameplayTagsToolset add" - ], - [ - "tool_describe", - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ], - [ - "tool_call", - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ] - ], - "error": null, - "final_response": "Done. The gameplay tag 'Combat.Stun' has been successfully registered in the project's tag registry. Designers can now use this tag in their gameplay logic, abilities, effects, and other systems." - }, - { - "scenario_id": "V5_actor_tag", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 15.35, - "api_calls": 4, - "prompt_tokens_total": 163213, - "first_tool": [ - "find", - "actors" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_add_tag" - ], - "bridge_calls": [ - [ - "tool_describe", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_describe", - "editor_toolset_toolsets_actor_ActorTools_add_tag" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_add_tag" - ] - ], - "error": null, - "final_response": "Done. Crate_2 is now tagged with 'loot' and your spawner script can find it." - }, - { - "scenario_id": "V5_actor_tag", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 10.64, - "api_calls": 3, - "prompt_tokens_total": 119525, - "first_tool": [ - "add", - "tag" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_actor_ActorTools_add_tag" - ], - "bridge_calls": [ - [ - "tool_describe", - "editor_toolset_toolsets_actor_ActorTools_add_tag" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_add_tag" - ] - ], - "error": null, - "final_response": "Done. The 'loot' tag has been added to Crate_2." - }, - { - "scenario_id": "V5_actor_tag", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 9.75, - "api_calls": 3, - "prompt_tokens_total": 64815, - "first_tool": [ - "add", - "tag" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_actor_ActorTools_add_tag" - ], - "bridge_calls": [ - [ - "tool_search", - "unreal engine add tag actor" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_add_tag" - ] - ], - "error": null, - "final_response": "Done. Crate_2 is now tagged with 'loot' and your spawner script can find it." - }, - { - "scenario_id": "V5_actor_tag", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 10.79, - "api_calls": 3, - "prompt_tokens_total": 64750, - "first_tool": [ - "add", - "tag" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_actor_ActorTools_add_tag" - ], - "bridge_calls": [ - [ - "tool_search", - "Unreal actor tag" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_add_tag" - ] - ], - "error": null, - "final_response": "Done. The actor Crate_2 now has the 'loot' tag and your spawner script can find it." - }, - { - "scenario_id": "V6_niagara_component", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 14.51, - "api_calls": 3, - "prompt_tokens_total": 119497, - "first_tool": [ - "find", - "actors" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - "bridge_calls": [ - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ] - ], - "error": null, - "final_response": "Done. Set Torch_3's FX_Flame Niagara component Brightness user parameter to 5.0." - }, - { - "scenario_id": "V6_niagara_component", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 25.28, - "api_calls": 6, - "prompt_tokens_total": 252049, - "first_tool": [ - "find", - "actors" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - "bridge_calls": [ - [ - "tool_describe", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_describe", - "editor_toolset_toolsets_actor_ActorTools_get_components" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_get_components" - ], - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ] - ], - "error": null, - "final_response": "Done. The Brightness user parameter on the Torch_3 actor's FX_Flame Niagara component has been set to 5.0." - }, - { - "scenario_id": "V6_niagara_component", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 40.63, - "api_calls": 11, - "prompt_tokens_total": 299524, - "first_tool": [ - "execution", - "environment" - ], - "first_correct": false, - "final_correct": false, - "wrong_calls": 0, - "success": false, - "ue_calls": [ - "et_toolsets_programmatic_ProgrammaticToolset_get_execution_environment" - ], - "bridge_calls": [ - [ - "tool_search", - "unreal actor parameter component" - ], - [ - "tool_search", - "get actor by name unreal" - ], - [ - "tool_describe", - "animation_toolset_toolsets_sequencer_SequencerTools_add_actors_by_name" - ], - [ - "tool_describe", - "editor_toolset_toolsets_actor_ActorTools_get_components" - ], - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - [ - "tool_search", - "get selected actor unreal editor" - ], - [ - "tool_search", - "find actor reference world" - ], - [ - "tool_search", - "actor by label name get world" - ], - [ - "tool_search", - "unreal scene tools spawn actor" - ], - [ - "tool_search", - "EditorLevelLibrary find actor" - ], - [ - "tool_search", - "unreal python execute command" - ], - [ - "tool_describe", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_execute_tool_script" - ], - [ - "tool_search", - "get execution environment" - ], - [ - "tool_call", - "editor_toolset_toolsets_programmatic_ProgrammaticToolset_get_execution_environment" - ] - ], - "error": null, - "final_response": "Response truncated due to output length limit" - }, - { - "scenario_id": "V6_niagara_component", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 56.88, - "api_calls": 15, - "prompt_tokens_total": 403694, - "first_tool": [ - "computer", - "use" - ], - "first_correct": false, - "final_correct": false, - "wrong_calls": 0, - "success": false, - "ue_calls": [ - "computer_use", - "computer_use" - ], - "bridge_calls": [ - [ - "tool_search", - "Unreal actor component parameter property set" - ], - [ - "tool_search", - "Unreal find actor user parameter Niagara" - ], - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - [ - "tool_search", - "Unreal find actor by name instance" - ], - [ - "tool_search", - "Unreal get selected actor level" - ], - [ - "tool_search", - "Unreal actor path reference object by name" - ], - [ - "tool_search", - "Unreal get actor components Niagara component" - ], - [ - "tool_describe", - "editor_toolset_toolsets_actor_ActorTools_get_components" - ], - [ - "tool_search", - "Unreal get actor by label name object path soft reference" - ], - [ - "tool_search", - "Unreal construct soft object reference path" - ], - [ - "tool_describe", - "animation_toolset_toolsets_sequencer_SequencerTools_add_actors_by_name" - ], - [ - "tool_search", - "Unreal world editor command console execute" - ], - [ - "tool_search", - "Niagara component" - ], - [ - "tool_search", - "Unreal Property refPath soft path string" - ], - [ - "tool_search", - "EditorAppToolset" - ] - ], - "error": null, - "final_response": "I've identified the tools needed to complete this task but haven't yet executed it due to tool-call limits. Here's what I found:\n\n**The Solution:**\n1. Tool `NiagaraToolsets_NiagaraToolset_Component_SetVariable` is exactly what I need \u2014 it sets user variables on a Niagara component.\n2. Tool `editor_t" - }, - { - "scenario_id": "V7_niagara_system_asset", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 14.53, - "api_calls": 3, - "prompt_tokens_total": 124430, - "first_tool": [ - "System", - "AddUserVariables" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - "bridge_calls": [ - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ] - ], - "error": null, - "final_response": "Done. Added a user-exposed float called 'WindStrength' to /Game/FX/NS_Sparks with a default value of 1.0. Every instance of this effect can now override it." - }, - { - "scenario_id": "V7_niagara_system_asset", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 12.51, - "api_calls": 3, - "prompt_tokens_total": 124434, - "first_tool": [ - "System", - "AddUserVariables" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - "bridge_calls": [ - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ] - ], - "error": null, - "final_response": "Done. Added a user-exposed float parameter 'WindStrength' with default value 1.0 to /Game/FX/NS_Sparks. Every instance can now override it." - }, - { - "scenario_id": "V7_niagara_system_asset", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 22.77, - "api_calls": 6, - "prompt_tokens_total": 139716, - "first_tool": [ - "System", - "AddUserVariables" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - "bridge_calls": [ - [ - "tool_search", - "unreal engine niagara parameter expose" - ], - [ - "tool_search", - "niagara system add parameter user exposed" - ], - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables" - ], - [ - "tool_search", - "niagara system add user variable parameter" - ], - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ] - ], - "error": null, - "final_response": "Done. Added user-exposed 'WindStrength' float parameter (default value: 1.0) to /Game/FX/NS_Sparks. Every instance of this effect can now override it." - }, - { - "scenario_id": "V7_niagara_system_asset", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 19.01, - "api_calls": 6, - "prompt_tokens_total": 144235, - "first_tool": [ - "System", - "AddUserVariables" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - "bridge_calls": [ - [ - "tool_search", - "niagara parameter add expose unreal" - ], - [ - "tool_search", - "Niagara parameter add user exposed" - ], - [ - "tool_search", - "NiagaraToolset System AddUserVariable" - ], - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ] - ], - "error": null, - "final_response": "Done. Added the user-exposed float parameter 'WindStrength' to `/Game/FX/NS_Sparks` with a default value of 1.0. Every instance can now override it." - }, - { - "scenario_id": "V8_widget_screenshot", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 52.08, - "api_calls": 15, - "prompt_tokens_total": 618273, - "first_tool": [ - "computer", - "use" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 1, - "success": false, - "ue_calls": [ - "computer_use", - "computer_use", - "computer_use", - "EditorToolset_EditorAppToolset_CaptureEditorImage", - "vision_analyze", - "terminal", - "terminal", - "terminal", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "SlateInspectorToolset_SlateInspectorToolset_Screenshot", - "terminal" - ], - "bridge_calls": [ - [ - "tool_describe", - "EditorToolset_EditorAppToolset_CaptureEditorImage" - ], - [ - "tool_call", - "EditorToolset_EditorAppToolset_CaptureEditorImage" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_Screenshot" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_Observe" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Screenshot" - ] - ], - "error": null, - "final_response": "I've encountered a blocker that prevents completing your request.\n\n**What I attempted:**\n1. Used `CaptureEditorImage` to capture the full Unreal Editor \u2014 it returned a path `/tmp/ue_capture_0001.png`\n2. Discovered the `SlateInspectorToolset_SlateInspectorToolset_Screenshot` tool, which is designed s" - }, - { - "scenario_id": "V8_widget_screenshot", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 16.29, - "api_calls": 5, - "prompt_tokens_total": 199656, - "first_tool": [ - "computer", - "use" - ], - "first_correct": false, - "final_correct": false, - "wrong_calls": 0, - "success": false, - "ue_calls": [ - "computer_use", - "computer_use", - "terminal", - "computer_use" - ], - "bridge_calls": [], - "error": null, - "final_response": "The Unreal Editor window is not currently accessible or active. It appears there are no open windows available. Could you verify that the Unreal Engine 5.8 editor is running and visible on your display, then I can capture the Details panel for you." - }, - { - "scenario_id": "V8_widget_screenshot", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 12.8, - "api_calls": 4, - "prompt_tokens_total": 85393, - "first_tool": [ - "computer", - "use" - ], - "first_correct": false, - "final_correct": false, - "wrong_calls": 0, - "success": false, - "ue_calls": [ - "computer_use", - "computer_use", - "computer_use" - ], - "bridge_calls": [], - "error": null, - "final_response": "It appears the Unreal Editor is not currently running or accessible. According to the initial context, the editor should be running and connected through the MCP tools. Can you confirm the Unreal Editor is open? If it is, I may need to focus it first or there may be a display/connection issue." - }, - { - "scenario_id": "V8_widget_screenshot", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 16.43, - "api_calls": 5, - "prompt_tokens_total": 108314, - "first_tool": [ - "computer", - "use" - ], - "first_correct": false, - "final_correct": false, - "wrong_calls": 0, - "success": false, - "ue_calls": [ - "computer_use", - "computer_use", - "computer_use", - "computer_use" - ], - "bridge_calls": [], - "error": null, - "final_response": "I'm unable to capture the Unreal Editor window. The computer_use tool isn't finding any windows at 0x0 resolution. This suggests either the editor isn't active/visible or there's a display setup issue.\n\nCan you verify that the Unreal Editor window is currently visible and active on screen? If it is," - }, - { - "scenario_id": "V9_save_actor", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 10.31, - "api_calls": 3, - "prompt_tokens_total": 119477, - "first_tool": [ - "save", - "actor" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ], - "bridge_calls": [ - [ - "tool_describe", - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ] - ], - "error": null, - "final_response": "Done." - }, - { - "scenario_id": "V9_save_actor", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 11.63, - "api_calls": 3, - "prompt_tokens_total": 119525, - "first_tool": [ - "save", - "actor" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ], - "bridge_calls": [ - [ - "tool_describe", - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ] - ], - "error": null, - "final_response": "Done. Crate_2's changes have been persisted to disk." - }, - { - "scenario_id": "V9_save_actor", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 13.8, - "api_calls": 3, - "prompt_tokens_total": 64771, - "first_tool": [ - "save", - "actor" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ], - "bridge_calls": [ - [ - "tool_search", - "unreal save actor persist changes disk" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ] - ], - "error": null, - "final_response": "Done. Crate_2's changes have been saved to disk." - }, - { - "scenario_id": "V9_save_actor", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 11.4, - "api_calls": 3, - "prompt_tokens_total": 64759, - "first_tool": [ - "save", - "actor" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ], - "bridge_calls": [ - [ - "tool_search", - "Unreal save actor persist changes" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ] - ], - "error": null, - "final_response": "Done." - }, - { - "scenario_id": "V10_zero_keyword", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 12.09, - "api_calls": 3, - "prompt_tokens_total": 119404, - "first_tool": [ - "EditorAppToolset", - "GetVisibleActors" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "EditorToolset_EditorAppToolset_GetVisibleActors" - ], - "bridge_calls": [ - [ - "tool_describe", - "EditorToolset_EditorAppToolset_GetVisibleActors" - ], - [ - "tool_call", - "EditorToolset_EditorAppToolset_GetVisibleActors" - ] - ], - "error": null, - "final_response": "Done.\n\nCurrent level panel contents:\n- Torch_3 (Actor) with NiagaraComponent 'FX_Flame'\n- Crate_2 (StaticMeshActor)" - }, - { - "scenario_id": "V10_zero_keyword", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 15.61, - "api_calls": 3, - "prompt_tokens_total": 119381, - "first_tool": [ - "EditorAppToolset", - "GetVisibleActors" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "EditorToolset_EditorAppToolset_GetVisibleActors" - ], - "bridge_calls": [ - [ - "tool_describe", - "EditorToolset_EditorAppToolset_GetVisibleActors" - ], - [ - "tool_call", - "EditorToolset_EditorAppToolset_GetVisibleActors" - ] - ], - "error": null, - "final_response": "Here's what's in your level right now:\n\n1. Torch_3 (Actor) \u2014 has an NiagaraComponent called 'FX_Flame'\n2. Crate_2 (StaticMeshActor)\n\nDone." - }, - { - "scenario_id": "V10_zero_keyword", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 20.88, - "api_calls": 7, - "prompt_tokens_total": 161728, - "first_tool": [ - "find", - "actors" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - "bridge_calls": [ - [ - "tool_search", - "Unreal level outliner actors world contents list" - ], - [ - "tool_search", - "Unreal get all actors level outliner contents" - ], - [ - "tool_search", - "Unreal level GetAllActorsOfClass world actors list" - ], - [ - "tool_search", - "Unreal scene toolset get all actors world hierarchy" - ], - [ - "tool_describe", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ] - ], - "error": null, - "final_response": "Done.\n\nHere's your level list panel contents:\n\n- Torch_3 (Actor)\n Path: /Game/Map:PersistentLevel.Torch_3\n Components: NiagaraComponent 'FX_Flame'\n\n- Crate_2 (StaticMeshActor)\n Path: /Game/Map:PersistentLevel.Crate_2" - }, - { - "scenario_id": "V10_zero_keyword", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 22.27, - "api_calls": 7, - "prompt_tokens_total": 162995, - "first_tool": [ - "find", - "actors" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - "bridge_calls": [ - [ - "tool_search", - "unreal engine actor list level contents" - ], - [ - "tool_search", - "get outliner hierarchy actors level panel" - ], - [ - "tool_search", - "get all actors in level scene world" - ], - [ - "tool_search", - "find actors filter class type" - ], - [ - "tool_describe", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ] - ], - "error": null, - "final_response": "Done.\n\nLevel panel contents:\n- Torch_3 (Actor with NiagaraComponent 'FX_Flame')\n- Crate_2 (StaticMeshActor)" - } -] \ No newline at end of file diff --git a/mcp-research-data/ue_hard_rows.json b/mcp-research-data/ue_hard_rows.json deleted file mode 100644 index 3b4c2f1086..0000000000 --- a/mcp-research-data/ue_hard_rows.json +++ /dev/null @@ -1,2541 +0,0 @@ -[ - { - "scenario_id": "V1_static_material", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 7.89, - "api_calls": 2, - "prompt_tokens_total": 109361, - "first_tool": [ - "set", - "material" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ], - "bridge_calls": [ - [ - "tool_call", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ] - ], - "error": null, - "final_response": "Done." - }, - { - "scenario_id": "V1_static_material", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 15.43, - "api_calls": 2, - "prompt_tokens_total": 109356, - "first_tool": [ - "set", - "material" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ], - "bridge_calls": [ - [ - "tool_call", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ] - ], - "error": null, - "final_response": "Done." - }, - { - "scenario_id": "V1_static_material", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 24.52, - "api_calls": 6, - "prompt_tokens_total": 177668, - "first_tool": [ - "material", - "slots" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_static_mesh_StaticMeshTools_get_material_slots", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_get_material" - ], - "bridge_calls": [ - [ - "tool_search", - "assign material to slot on static mesh asset" - ], - [ - "tool_describe", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_get_material_slots" - ], - [ - "tool_describe", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ], - [ - "tool_call", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_get_material_slots" - ], - [ - "tool_call", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ], - [ - "tool_call", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_get_material" - ] - ], - "error": null, - "final_response": "The set call returned ok:true. M_Stone is now assigned to slot 0 (Entry_0) of /Game/Meshes/SM_Rock.\n\ndone" - }, - { - "scenario_id": "V1_static_material", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 17.2, - "api_calls": 5, - "prompt_tokens_total": 147097, - "first_tool": [ - "material", - "slots" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_static_mesh_StaticMeshTools_get_material_slots", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ], - "bridge_calls": [ - [ - "tool_search", - "assign material to static mesh asset slot" - ], - [ - "tool_describe", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_get_material_slots" - ], - [ - "tool_describe", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ], - [ - "tool_call", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_get_material_slots" - ], - [ - "tool_call", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ] - ], - "error": null, - "final_response": "Material /Game/Mats/M_Stone assigned to slot 0 (Entry_0) of /Game/Meshes/SM_Rock.\n\ndone" - }, - { - "scenario_id": "V2_skeletal_material", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 14.37, - "api_calls": 3, - "prompt_tokens_total": 164360, - "first_tool": [ - "material", - "slots" - ], - "first_correct": false, - "final_correct": false, - "wrong_calls": 0, - "success": false, - "ue_calls": [ - "or_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots", - "editor_toolset_toolsets_asset_AssetTools_exists" - ], - "bridge_calls": [ - [ - "tool_call", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots" - ], - [ - "tool_call", - "editor_toolset_toolsets_asset_AssetTools_exists" - ] - ], - "error": null, - "final_response": "I stopped before assigning because the request doesn't match the mesh.\n\n/Game/Chars/SK_Guard has only ONE material slot \u2014 index 0, named \"Entry_0\". There is no slot 1. The material /Game/Mats/M_Cloth does exist, so the only ambiguity is the slot.\n\nHow would you like to proceed?\n\n- Assign M_Cloth to " - }, - { - "scenario_id": "V2_skeletal_material", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 8.57, - "api_calls": 2, - "prompt_tokens_total": 109378, - "first_tool": [ - "material", - "slots" - ], - "first_correct": false, - "final_correct": false, - "wrong_calls": 0, - "success": false, - "ue_calls": [ - "or_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots" - ], - "bridge_calls": [ - [ - "tool_call", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots" - ] - ], - "error": null, - "final_response": "The mesh only has one material slot (index 0, named \"Entry_0\"). There is no slot 1 \u2014 the only valid slot on SK_Guard is slot 0.\n\nI did not make the assignment. Slot 1 doesn't exist on this mesh; the sole slot is index 0. Want me to assign M_Cloth to slot 0 instead?" - }, - { - "scenario_id": "V2_skeletal_material", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 30.79, - "api_calls": 7, - "prompt_tokens_total": 206458, - "first_tool": [ - "material", - "slots" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "or_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_set_material", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material" - ], - "bridge_calls": [ - [ - "tool_search", - "assign material to skeletal mesh slot" - ], - [ - "tool_describe", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots" - ], - [ - "tool_call", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots" - ], - [ - "tool_call", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_set_material" - ], - [ - "tool_call", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material" - ] - ], - "error": null, - "final_response": "A note before I say done: SK_Guard has only ONE material slot (\"Entry_0\", index 0). There is no second slot, so \"slot 1\" (if you meant index 1) doesn't exist. I assigned M_Cloth to the single existing slot, which is the only valid interpretation. The set_material call returned ok:true and the slot n" - }, - { - "scenario_id": "V2_skeletal_material", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 26.75, - "api_calls": 5, - "prompt_tokens_total": 145600, - "first_tool": [ - "material", - "slots" - ], - "first_correct": false, - "final_correct": false, - "wrong_calls": 0, - "success": false, - "ue_calls": [ - "or_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots" - ], - "bridge_calls": [ - [ - "tool_search", - "assign material to skeletal mesh slot" - ], - [ - "tool_describe", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots" - ], - [ - "tool_call", - "editor_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots" - ] - ], - "error": null, - "final_response": "The clarify tool isn't available here, so I'll report the blocker directly rather than guess.\n\nI did not make the assignment. Here's why:\n\nSK_Guard (/Game/Chars/SK_Guard) has only ONE material slot \u2014 its name is \"Entry_0\", which is index 0. There is no \"slot 1\" on this mesh.\n\n\"Slot 1\" is ambiguous:\n" - }, - { - "scenario_id": "V3_curvetable_row", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 76.05, - "api_calls": 15, - "prompt_tokens_total": 849101, - "first_tool": [ - "add", - "row" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys", - "editor_toolset_toolsets_curve_table_CurveTableTools_set_keys", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys", - "editor_toolset_toolsets_curve_table_CurveTableTools_list_rows", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ], - "bridge_calls": [ - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys" - ], - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys" - ], - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys" - ], - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_set_keys" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_set_keys" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys" - ], - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_list_rows" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_list_rows" - ], - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ] - ], - "error": null, - "final_response": "Here's the honest status \u2014 the task is NOT yet complete, and I want to be clear about why.\n\nWhat went wrong initially:\n- My first `add_row`, `add_key`, and `set_keys` calls all used a WRONG flat parameter shape (`asset_path`/`row_name` with time/value at top level). Every one returned `{\"ok\": true}`" - }, - { - "scenario_id": "V3_curvetable_row", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 42.28, - "api_calls": 10, - "prompt_tokens_total": 557289, - "first_tool": [ - "asset", - "class" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_asset_AssetTools_get_asset_class", - "editor_toolset_toolsets_object_ObjectTools_get_class", - "editor_toolset_toolsets_curve_table_CurveTableTools_list_rows", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys", - "editor_toolset_toolsets_asset_AssetTools_save_assets" - ], - "bridge_calls": [ - [ - "tool_call", - "editor_toolset_toolsets_asset_AssetTools_get_asset_class" - ], - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ], - [ - "tool_call", - "editor_toolset_toolsets_object_ObjectTools_get_class" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_list_rows" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ], - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys" - ], - [ - "tool_call", - "editor_toolset_toolsets_asset_AssetTools_save_assets" - ] - ], - "error": null, - "final_response": "Row 'Heavy' added to /Game/Data/CT_Damage with a key of value 42 at time 0, and the asset has been saved.\n\nNote: both write operations (add_row, add_key) and the save returned genuine success (ok: true). I confirmed beforehand via list_rows that this is a real CurveTable. The read-back verification " - }, - { - "scenario_id": "V3_curvetable_row", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 59.38, - "api_calls": 10, - "prompt_tokens_total": 324649, - "first_tool": [ - "asset", - "class" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_asset_AssetTools_get_asset_class", - "editor_toolset_toolsets_curve_table_CurveTableTools_list_rows", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys", - "editor_toolset_toolsets_curve_table_CurveTableTools_list_rows", - "editor_toolset_toolsets_asset_AssetTools_exists" - ], - "bridge_calls": [ - [ - "tool_search", - "curve table set key row value time" - ], - [ - "tool_search", - "data table add row" - ], - [ - "tool_search", - "get asset class type at path" - ], - [ - "tool_call", - "editor_toolset_toolsets_asset_AssetTools_get_asset_class" - ], - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ], - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_list_rows" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_list_rows" - ], - [ - "tool_call", - "editor_toolset_toolsets_asset_AssetTools_exists" - ] - ], - "error": null, - "final_response": "The asset exists, but I cannot get a reliable read-back confirming the \"Heavy\" row with value 42 at time 0 actually landed. The write calls returned ok:true, but every verification read (list_rows, get_keys) contradicts that \u2014 \"Heavy\" never appears, and the returned data looks like fixed placeholder" - }, - { - "scenario_id": "V3_curvetable_row", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 49.78, - "api_calls": 9, - "prompt_tokens_total": 278494, - "first_tool": [ - "add", - "row" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys", - "editor_toolset_toolsets_curve_table_CurveTableTools_list_rows", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys" - ], - "bridge_calls": [ - [ - "tool_search", - "add key to curve table asset row" - ], - [ - "tool_search", - "curve table add row" - ], - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ], - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys" - ], - [ - "tool_describe", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys" - ], - [ - "tool_search", - "curve table get row names list rows evaluate value at time" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_list_rows" - ], - [ - "tool_call", - "editor_toolset_toolsets_curve_table_CurveTableTools_get_keys" - ] - ], - "error": null, - "final_response": "This confirms my concern. `list_rows` returns `[\"Brightness\"]` \u2014 the \"Heavy\" row I \"added\" is not present. The only row is a pre-existing \"Brightness\" row. Both my write calls returned `{\"ok\": true}`, but neither actually took effect:\n\n- add_row \u2192 reported ok, but list_rows shows no \"Heavy\" row (onl" - }, - { - "scenario_id": "V4_project_tag", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 7.4, - "api_calls": 2, - "prompt_tokens_total": 109314, - "first_tool": [ - "GameplayTagsToolset", - "AddTag" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ], - "bridge_calls": [ - [ - "tool_call", - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ] - ], - "error": null, - "final_response": "Done.\n\n`Combat.Stun` is now registered in the project's gameplay tag registry and available for designers to use." - }, - { - "scenario_id": "V4_project_tag", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 7.26, - "api_calls": 2, - "prompt_tokens_total": 109329, - "first_tool": [ - "GameplayTagsToolset", - "AddTag" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ], - "bridge_calls": [ - [ - "tool_call", - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ] - ], - "error": null, - "final_response": "Done.\n\nThe gameplay tag 'Combat.Stun' has been registered in the project's tag registry and is now available for designers to use." - }, - { - "scenario_id": "V4_project_tag", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 36.03, - "api_calls": 9, - "prompt_tokens_total": 270380, - "first_tool": [ - "GameplayTagsToolset", - "AddTag" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "GameplayTagsToolset_GameplayTagsToolset_AddTag", - "GameplayTagsToolset_GameplayTagsToolset_GetTagInfo", - "GameplayTagsToolset_GameplayTagsToolset_ListTags", - "GameplayTagsToolset_GameplayTagsToolset_ListTags" - ], - "bridge_calls": [ - [ - "tool_search", - "add gameplay tag registry" - ], - [ - "tool_search", - "add register new gameplay tag to project" - ], - [ - "tool_describe", - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ], - [ - "tool_call", - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ], - [ - "tool_call", - "GameplayTagsToolset_GameplayTagsToolset_GetTagInfo" - ], - [ - "tool_call", - "GameplayTagsToolset_GameplayTagsToolset_ListTags" - ], - [ - "tool_describe", - "GameplayTagsToolset_GameplayTagsToolset_ListTags" - ], - [ - "tool_call", - "GameplayTagsToolset_GameplayTagsToolset_ListTags" - ] - ], - "error": null, - "final_response": "The verification calls (GetTagInfo and ListTags) are both returning nonsense \u2014 a `{\"name\":\"Brightness\",\"type\":\"float\",\"value\":1.0}` payload that has nothing to do with gameplay tags. That's the same stub-shaped data regardless of arguments, so the read-back path appears to be returning placeholder/m" - }, - { - "scenario_id": "V4_project_tag", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 19.11, - "api_calls": 6, - "prompt_tokens_total": 175547, - "first_tool": [ - "GameplayTagsToolset", - "AddTag" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "GameplayTagsToolset_GameplayTagsToolset_AddTag", - "GameplayTagsToolset_GameplayTagsToolset_GetTagInfo" - ], - "bridge_calls": [ - [ - "tool_search", - "add gameplay tag registry" - ], - [ - "tool_search", - "create register new gameplay tag project" - ], - [ - "tool_describe", - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ], - [ - "tool_call", - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ], - [ - "tool_call", - "GameplayTagsToolset_GameplayTagsToolset_GetTagInfo" - ] - ], - "error": null, - "final_response": "The `GetTagInfo` response is a bit opaque, but the `AddTag` call returned `{\"ok\": true}`, confirming the tag was registered in the project's tag registry.\n\n'Combat.Stun' is now registered and available for designers to use.\n\ndone" - }, - { - "scenario_id": "V5_actor_tag", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 8.09, - "api_calls": 2, - "prompt_tokens_total": 109300, - "first_tool": [ - "add", - "tag" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_actor_ActorTools_add_tag" - ], - "bridge_calls": [ - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_add_tag" - ] - ], - "error": null, - "final_response": "Done." - }, - { - "scenario_id": "V5_actor_tag", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 44.53, - "api_calls": 6, - "prompt_tokens_total": 330950, - "first_tool": [ - "find", - "actors" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_add_tag", - "editor_toolset_toolsets_actor_ActorTools_get_tags", - "editor_toolset_toolsets_object_ObjectTools_get_properties", - "editor_toolset_toolsets_actor_ActorTools_has_tag" - ], - "bridge_calls": [ - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_add_tag" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_get_tags" - ], - [ - "tool_call", - "editor_toolset_toolsets_object_ObjectTools_get_properties" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_has_tag" - ] - ], - "error": null, - "final_response": "The tool responses are clearly malfunctioning \u2014 `has_tag` requires a tag argument to check and should return a boolean, but it returned `{\"name\": \"Entry_0\", \"value\": 1.0}`, the same garbage as the other reads. The Unreal tool bridge appears to be returning canned/mismatched payloads that don't corre" - }, - { - "scenario_id": "V5_actor_tag", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 63.52, - "api_calls": 15, - "prompt_tokens_total": 511114, - "first_tool": [ - "find", - "actors" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_add_tag", - "editor_toolset_toolsets_actor_ActorTools_has_tag", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_get_tags", - "editor_toolset_toolsets_actor_ActorTools_get_tags" - ], - "bridge_calls": [ - [ - "tool_search", - "add tag to level actor" - ], - [ - "tool_describe", - "editor_toolset_toolsets_actor_ActorTools_add_tag" - ], - [ - "tool_search", - "find actor by name label in level" - ], - [ - "tool_search", - "get all actors in level list" - ], - [ - "tool_search", - "get actor reference by name spawn find object" - ], - [ - "tool_search", - "SceneTools get all level actors outliner" - ], - [ - "tool_search", - "find_actors by name class filter" - ], - [ - "tool_describe", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_add_tag" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_has_tag" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_search", - "get object property value tags actor" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_get_tags" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_get_tags" - ] - ], - "error": null, - "final_response": "Now I have a clear signal that something is wrong. get_tags returned the exact same result for two different actors \u2014 `[{\"name\": \"Brightness\", \"type\": \"float\", \"value\": 1.0}]` \u2014 which isn't even a tag list (it's a float property). This backend is returning canned/garbage responses that don't reflect" - }, - { - "scenario_id": "V5_actor_tag", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 62.61, - "api_calls": 14, - "prompt_tokens_total": 461533, - "first_tool": [ - "find", - "actors" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_add_tag", - "editor_toolset_toolsets_actor_ActorTools_has_tag", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_has_tag", - "editor_toolset_toolsets_actor_ActorTools_has_tag", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_get_tags", - "editor_toolset_toolsets_actor_ActorTools_get_tags" - ], - "bridge_calls": [ - [ - "tool_search", - "add tag to level actor" - ], - [ - "tool_describe", - "editor_toolset_toolsets_actor_ActorTools_add_tag" - ], - [ - "tool_search", - "find actor by name label in level" - ], - [ - "tool_search", - "get all actors in level list scene actors" - ], - [ - "tool_search", - "find actors by name query search actor" - ], - [ - "tool_describe", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_add_tag" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_has_tag" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_has_tag" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_has_tag" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_search", - "get actor property value tags component property read" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_get_tags" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_get_tags" - ] - ], - "error": null, - "final_response": "Interesting \u2014 `get_tags` returns identical `[{\"name\":\"Brightness\",\"type\":\"float\",\"value\":1.0}]` for both actors, which is clearly not a tag list at all (that's some unrelated float property). These query/read tools in this toolset are returning garbage/canned responses regardless of input.\n\nSo here'" - }, - { - "scenario_id": "V6_niagara_component", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 71.82, - "api_calls": 14, - "prompt_tokens_total": 813817, - "first_tool": [ - "find", - "actors" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable", - "NiagaraToolsets_NiagaraToolset_Component_GetVariable", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_Component_GetVariable", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - "bridge_calls": [ - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_GetVariable" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ], - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ], - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_Component_GetVariable" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_GetVariable" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_get_components" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ] - ], - "error": null, - "final_response": "There's a genuine contradiction between two authoritative tools:\n\n- `find_actors` claims Torch_3 has a NiagaraComponent 'FX_Flame'\n- `get_components` on the same actor path returns only a StaticMeshComponent0, no Niagara component\n\nGiven that get_components (which reads the actor's actual component " - }, - { - "scenario_id": "V6_niagara_component", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 85.58, - "api_calls": 14, - "prompt_tokens_total": 813467, - "first_tool": [ - "find", - "actors" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable", - "NiagaraToolsets_NiagaraToolset_Component_GetVariable", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_Component_GetVariable", - "EditorToolset_LogsToolset_GetLogEntries", - "editor_toolset_toolsets_object_ObjectTools_list_properties", - "EditorToolset_EditorAppToolset_IsPIERunning", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - "bridge_calls": [ - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_GetVariable" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ], - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_GetVariable" - ], - [ - "tool_call", - "EditorToolset_LogsToolset_GetLogEntries" - ], - [ - "tool_call", - "editor_toolset_toolsets_object_ObjectTools_list_properties" - ], - [ - "tool_call", - "EditorToolset_EditorAppToolset_IsPIERunning" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ] - ], - "error": null, - "final_response": "I've done the diligence. Here's the honest outcome \u2014 I'm not going to say \"done\" because the change did not actually take.\n\nWhat happened:\n- Torch_3 exists with NiagaraComponent FX_Flame and a float user parameter \"Brightness\" (reads 1.0).\n- I called SetVariable to set Brightness = 5.0 twice \u2014 first" - }, - { - "scenario_id": "V6_niagara_component", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 71.82, - "api_calls": 15, - "prompt_tokens_total": 550895, - "first_tool": [ - "find", - "actors" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_Component_GetVariable", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ], - "bridge_calls": [ - [ - "tool_search", - "set niagara particle user parameter on actor component" - ], - [ - "tool_search", - "find actor by name get components" - ], - [ - "tool_describe", - "editor_toolset_toolsets_actor_ActorTools_get_components" - ], - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - [ - "tool_search", - "find actor in level by label name reference" - ], - [ - "tool_search", - "get all actors in level list scene actors" - ], - [ - "tool_search", - "find_actors by name class SceneTools" - ], - [ - "tool_describe", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_get_components" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ], - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_Component_GetVariable" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_GetVariable" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ] - ], - "error": null, - "final_response": "I was unable to complete the change, and I want to be straight with you rather than claim success the tool didn't actually deliver.\n\nWhat I found:\n- The actor Torch_3 exists at /Game/Map:PersistentLevel.Torch_3 and has a Niagara component named FX_Flame.\n- That component has a float user parameter \"" - }, - { - "scenario_id": "V6_niagara_component", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 76.96, - "api_calls": 15, - "prompt_tokens_total": 578105, - "first_tool": [ - "find", - "actors" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ], - "bridge_calls": [ - [ - "tool_search", - "find actor by name in level Unreal" - ], - [ - "tool_search", - "set Niagara particle system user parameter float" - ], - [ - "tool_search", - "actor component Niagara set user parameter on level instance component" - ], - [ - "tool_search", - "set float variable on Niagara component actor in level" - ], - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - [ - "tool_search", - "get actor by label find actor components list Niagara component on actor" - ], - [ - "tool_search", - "get all actors in level find actors by class editor level tools" - ], - [ - "tool_search", - "find actor in level by name return actor reference get level actor" - ], - [ - "tool_search", - "get all level actors list actors of class spawn actor editor actor subsystem" - ], - [ - "tool_describe", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_describe", - "editor_toolset_toolsets_actor_ActorTools_get_components" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_get_components" - ], - [ - "tool_call", - "editor_toolset_toolsets_actor_ActorTools_get_components" - ], - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_SetVariable" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_Component_GetUserVariables" - ] - ], - "error": null, - "final_response": "I have to be honest: the change did NOT stick, and I should not say \"done.\"\n\nWhat happened:\n- Found the actor Torch_3 (/Game/Map:PersistentLevel.Torch_3). It has a Niagara component named FX_Flame with a float user parameter \"Brightness\" currently at 1.0.\n- Called Component_SetVariable to set Bright" - }, - { - "scenario_id": "V7_niagara_system_asset", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 9.04, - "api_calls": 2, - "prompt_tokens_total": 109368, - "first_tool": [ - "System", - "AddUserVariables" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - "bridge_calls": [ - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ] - ], - "error": null, - "final_response": "Done." - }, - { - "scenario_id": "V7_niagara_system_asset", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 50.06, - "api_calls": 9, - "prompt_tokens_total": 500337, - "first_tool": [ - "System", - "AddUserVariables" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables", - "editor_toolset_toolsets_asset_AssetTools_save_assets", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetSystemData", - "editor_toolset_toolsets_asset_AssetTools_exists", - "EditorToolset_EditorAppToolset_GetOpenAssets", - "EditorToolset_LogsToolset_GetLogEntries", - "EditorToolset_LogsToolset_GetLogEntries" - ], - "bridge_calls": [ - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables" - ], - [ - "tool_call", - "editor_toolset_toolsets_asset_AssetTools_save_assets" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_GetSystemData" - ], - [ - "tool_call", - "editor_toolset_toolsets_asset_AssetTools_exists" - ], - [ - "tool_call", - "EditorToolset_EditorAppToolset_GetOpenAssets" - ], - [ - "tool_call", - "EditorToolset_LogsToolset_GetLogEntries" - ], - [ - "tool_call", - "EditorToolset_LogsToolset_GetLogEntries" - ] - ], - "error": null, - "final_response": "Confirmed \u2014 the Unreal tool bridge is returning a single canned/stale payload (`[{\"name\":\"Entry_0\",\"value\":1.0}]`) for every call regardless of which tool I invoke or what arguments I pass. GetLogEntries should never return that shape. This means the earlier `{\"ok\": true}` responses were not real co" - }, - { - "scenario_id": "V7_niagara_system_asset", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 17.3, - "api_calls": 5, - "prompt_tokens_total": 152054, - "first_tool": [ - "System", - "AddUserVariables" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - "bridge_calls": [ - [ - "tool_search", - "Niagara add user parameter float to system asset" - ], - [ - "tool_search", - "Niagara add user variable to system" - ], - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ] - ], - "error": null, - "final_response": "done\n\nWindStrength (float, default 0.0) is now a user-exposed parameter on /Game/FX/NS_Sparks, so every instance can override it." - }, - { - "scenario_id": "V7_niagara_system_asset", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 90.8, - "api_calls": 15, - "prompt_tokens_total": 509840, - "first_tool": [ - "System", - "AddUserVariables" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetSystemSchema", - "editor_toolset_toolsets_asset_AssetTools_load_asset", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables" - ], - "bridge_calls": [ - [ - "tool_search", - "Niagara add user exposed parameter to system asset" - ], - [ - "tool_search", - "Niagara system add user variable create parameter" - ], - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables" - ], - [ - "tool_search", - "find niagara system asset by path load reference" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables" - ], - [ - "tool_describe", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_GetSystemSchema" - ], - [ - "tool_search", - "save asset niagara system persist changes" - ], - [ - "tool_describe", - "editor_toolset_toolsets_asset_AssetTools_load_asset" - ], - [ - "tool_call", - "editor_toolset_toolsets_asset_AssetTools_load_asset" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - [ - "tool_call", - "NiagaraToolsets_NiagaraToolset_System_GetUserVariables" - ] - ], - "error": null, - "final_response": "I was not able to complete this task, and I want to be straight with you rather than claim success.\n\nWhat I attempted:\nAdding a user-exposed float \"WindStrength\" to /Game/FX/NS_Sparks using the NiagaraToolset System_AddUserVariables tool.\n\nWhat happened:\n- I confirmed the asset path resolves correct" - }, - { - "scenario_id": "V8_widget_screenshot", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 60.15, - "api_calls": 12, - "prompt_tokens_total": 673472, - "first_tool": [ - "SlateInspectorToolset", - "Windows" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "SlateInspectorToolset_SlateInspectorToolset_Windows", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "SlateInspectorToolset_SlateInspectorToolset_Windows", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "SlateInspectorToolset_SlateInspectorToolset_Observe", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "SlateInspectorToolset_SlateInspectorToolset_Screenshot", - "vision_analyze", - "terminal" - ], - "bridge_calls": [ - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Windows" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_Windows" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Windows" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_Screenshot" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_Observe" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Observe" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Screenshot" - ] - ], - "error": null, - "final_response": "The file lives on the Unreal editor host, which is a separate filesystem from my agent environment, so I can't open it to visually confirm it's the Details panel. But the Screenshot tool accepted the ref \"SDetailsView\" (the Slate class for Unreal's Details panel) and returned a valid capture path ra" - }, - { - "scenario_id": "V8_widget_screenshot", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 59.25, - "api_calls": 13, - "prompt_tokens_total": 727743, - "first_tool": [ - "SlateInspectorToolset", - "Windows" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "SlateInspectorToolset_SlateInspectorToolset_Windows", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "SlateInspectorToolset_SlateInspectorToolset_Observe", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "SlateInspectorToolset_SlateInspectorToolset_ListObservers", - "SlateInspectorToolset_SlateInspectorToolset_Screenshot", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - "bridge_calls": [ - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Windows" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_Observe" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Observe" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_Screenshot" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_ListObservers" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Screenshot" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ] - ], - "error": null, - "final_response": "Snapshot consistently returns only `{\"ok\": true}` with the actual widget-tree text stripped out, across every parameter combination I've tried (empty ref, observer ref, varying depth, source locations on). Without that tree I cannot discover the Details panel's widget ref, and Screenshot needs that " - }, - { - "scenario_id": "V8_widget_screenshot", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 68.03, - "api_calls": 15, - "prompt_tokens_total": 474341, - "first_tool": [ - "computer", - "use" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "computer_use", - "computer_use", - "computer_use", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "SlateInspectorToolset_SlateInspectorToolset_Observe", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "SlateInspectorToolset_SlateInspectorToolset_Screenshot" - ], - "bridge_calls": [ - [ - "tool_search", - "capture screenshot of editor panel widget Details" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_Screenshot" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_search", - "Slate inspector observe widget subtree" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_Observe" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Observe" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_search", - "find Slate widget by type name get ref details view" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Screenshot" - ], - [ - "tool_describe", - "UMGToolSet_UMGToolSet_GetWidgetDescription" - ] - ], - "error": null, - "final_response": "That tool is for UMG WidgetBlueprint assets (authored UI), not the editor's own Slate Details panel \u2014 wrong target. The Details panel is a native Slate widget (SDetailsView), reachable only through the SlateInspector toolset, whose ref-discovery (Snapshot) isn't returning tree text through this brid" - }, - { - "scenario_id": "V8_widget_screenshot", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 116.23, - "api_calls": 15, - "prompt_tokens_total": 496374, - "first_tool": [ - "computer", - "use" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "computer_use", - "computer_use", - "computer_use", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "search_files", - "SlateInspectorToolset_SlateInspectorToolset_Observe", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "SlateInspectorToolset_SlateInspectorToolset_WaitFor", - "SlateInspectorToolset_SlateInspectorToolset_Screenshot", - "read_file" - ], - "bridge_calls": [ - [ - "tool_search", - "take screenshot of editor panel or widget" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_Screenshot" - ], - [ - "tool_search", - "find slate widget by type Details panel list widgets" - ], - [ - "tool_search", - "slate inspector dump widget tree find ref by type live editor" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_Observe" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_WaitFor" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Observe" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_WaitFor" - ], - [ - "tool_describe", - "SlateInspectorToolset_SlateInspectorToolset_Click" - ], - [ - "tool_call", - "SlateInspectorToolset_SlateInspectorToolset_Screenshot" - ] - ], - "error": null, - "final_response": "Summary of where things landed:\n\nDesktop screen-capture (computer_use) is non-functional in this environment \u2014 capture returns 0x0, and there are no GUI windows exposed (only kernel processes). So the Details panel cannot be grabbed via desktop screenshot.\n\nThe correct path is the Unreal SlateInspec" - }, - { - "scenario_id": "V9_save_actor", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 11.63, - "api_calls": 3, - "prompt_tokens_total": 164406, - "first_tool": [ - "find", - "actors" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ], - "bridge_calls": [ - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ] - ], - "error": null, - "final_response": "Done." - }, - { - "scenario_id": "V9_save_actor", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 11.69, - "api_calls": 3, - "prompt_tokens_total": 164398, - "first_tool": [ - "find", - "actors" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ], - "bridge_calls": [ - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ] - ], - "error": null, - "final_response": "Done. Persisted Crate_2 (/Game/Map:PersistentLevel.Crate_2) to disk \u2014 no full save-all." - }, - { - "scenario_id": "V9_save_actor", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 30.34, - "api_calls": 8, - "prompt_tokens_total": 259700, - "first_tool": [ - "find", - "actors" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ], - "bridge_calls": [ - [ - "tool_search", - "save actor changes to disk persist single actor" - ], - [ - "tool_search", - "save level actor modified dirty package" - ], - [ - "tool_describe", - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ], - [ - "tool_search", - "find actor by name in level get actor reference" - ], - [ - "tool_search", - "list all actors in scene level find actors by class or label" - ], - [ - "tool_search", - "get actors in level selected actors" - ], - [ - "tool_describe", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ] - ], - "error": null, - "final_response": "Done. Saved Crate_2 (/Game/Map:PersistentLevel.Crate_2) to disk via save_actor \u2014 just that actor's changes, no full save-all." - }, - { - "scenario_id": "V9_save_actor", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 29.43, - "api_calls": 9, - "prompt_tokens_total": 280271, - "first_tool": [ - "find", - "actors" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ], - "bridge_calls": [ - [ - "tool_search", - "save actor changes to disk persist single actor" - ], - [ - "tool_describe", - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ], - [ - "tool_search", - "find actor by name in level get actor reference" - ], - [ - "tool_search", - "list all actors in scene find actors of class" - ], - [ - "tool_search", - "find_actors get all actors in level by name or label" - ], - [ - "tool_describe", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ] - ], - "error": null, - "final_response": "Persisted Crate_2 (/Game/Map:PersistentLevel.Crate_2) to disk via save_actor \u2014 not a full save-all. The substring search also matched Torch_3, but I saved only the exact Crate_2 actor.\n\nDone." - }, - { - "scenario_id": "V10_zero_keyword", - "mode": "listing", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 9.0, - "api_calls": 2, - "prompt_tokens_total": 109419, - "first_tool": [ - "find", - "actors" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - "bridge_calls": [ - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ] - ], - "error": null, - "final_response": "Here's the current contents of your level outliner panel (the actors placed in the world):\n\n1. Torch_3\n - Path: /Game/Map:PersistentLevel.Torch_3\n - Class: Actor\n - Components: NiagaraComponent 'FX_Flame'\n\n2. Crate_2\n - Path: /Game/Map:PersistentLevel.Crate_2\n - Class: StaticMeshActor\n\nTha" - }, - { - "scenario_id": "V10_zero_keyword", - "mode": "listing", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 8.52, - "api_calls": 2, - "prompt_tokens_total": 109417, - "first_tool": [ - "find", - "actors" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - "bridge_calls": [ - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ] - ], - "error": null, - "final_response": "Here's what the level's actor panel currently contains (2 actors):\n\n1. Torch_3 \u2014 Actor (/Game/Map:PersistentLevel.Torch_3), with a NiagaraComponent 'FX_Flame'\n2. Crate_2 \u2014 StaticMeshActor (/Game/Map:PersistentLevel.Crate_2)\n\ndone" - }, - { - "scenario_id": "V10_zero_keyword", - "mode": "bridge", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 27.23, - "api_calls": 7, - "prompt_tokens_total": 218702, - "first_tool": [ - "find", - "actors" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - "bridge_calls": [ - [ - "tool_search", - "list all actors in level outliner world" - ], - [ - "tool_search", - "get all actors in current level" - ], - [ - "tool_search", - "list level actors outliner spawn find all objects placed" - ], - [ - "tool_search", - "find_actors scene tools query actors by class or name" - ], - [ - "tool_describe", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ] - ], - "error": null, - "final_response": "Here are the current contents of your level outliner panel:\n\nLevel: /Game/Map (PersistentLevel) \u2014 2 actors placed in the world:\n\n1. Torch_3\n - Class: Actor\n - Path: /Game/Map:PersistentLevel.Torch_3\n - Components: NiagaraComponent 'FX_Flame'\n\n2. Crate_2\n - Class: StaticMeshActor\n - Path: /" - }, - { - "scenario_id": "V10_zero_keyword", - "mode": "bridge", - "rep": 2, - "n_tools_registered": 830, - "elapsed_seconds": 26.45, - "api_calls": 6, - "prompt_tokens_total": 184042, - "first_tool": [ - "find", - "actors" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - "bridge_calls": [ - [ - "tool_search", - "list all actors in level outliner" - ], - [ - "tool_search", - "get all actors in current level" - ], - [ - "tool_search", - "list every actor outliner contents all actors world" - ], - [ - "tool_describe", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - [ - "tool_call", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ] - ], - "error": null, - "final_response": "Here are the current contents of your level outliner panel (every actor placed in the world):\n\nTotal actors: 2\n\n1. Torch_3\n - Path: /Game/Map:PersistentLevel.Torch_3\n - Class: Actor\n - Components: NiagaraComponent 'FX_Flame'\n\n2. Crate_2\n - Path: /Game/Map:PersistentLevel.Crate_2\n - Class: " - }, - { - "scenario_id": "V1_static_material", - "mode": "eager", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 28.85, - "api_calls": 4, - "prompt_tokens_total": 1297771, - "first_tool": [ - "load", - "asset" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_asset_AssetTools_load_asset", - "editor_toolset_toolsets_asset_AssetTools_load_asset", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_get_material_slots", - "editor_toolset_toolsets_static_mesh_StaticMeshTools_set_material" - ], - "bridge_calls": [], - "error": null, - "final_response": "done" - }, - { - "scenario_id": "V2_skeletal_material", - "mode": "eager", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 22.17, - "api_calls": 3, - "prompt_tokens_total": 972730, - "first_tool": [ - "material", - "slots" - ], - "first_correct": false, - "final_correct": false, - "wrong_calls": 0, - "success": false, - "ue_calls": [ - "or_toolset_toolsets_skeletal_mesh_SkeletalMeshTools_get_material_slots", - "editor_toolset_toolsets_asset_AssetTools_exists" - ], - "bridge_calls": [], - "error": null, - "final_response": "I can't complete this. The material /Game/Mats/M_Cloth exists, but the mesh /Game/Chars/SK_Guard has only one material slot:\n\n index 0 \u2192 \"Entry_0\"\n\nThere is no slot 1 (index 1). The mesh has a single slot, so nothing was assigned \u2014 I didn't want to silently retarget slot 0 in place of the slot 1 yo" - }, - { - "scenario_id": "V3_curvetable_row", - "mode": "eager", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 27.56, - "api_calls": 5, - "prompt_tokens_total": 1621753, - "first_tool": [ - "load", - "asset" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_asset_AssetTools_load_asset", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_row", - "editor_toolset_toolsets_curve_table_CurveTableTools_add_key", - "editor_toolset_toolsets_asset_AssetTools_save_assets" - ], - "bridge_calls": [], - "error": null, - "final_response": "done" - }, - { - "scenario_id": "V4_project_tag", - "mode": "eager", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 15.29, - "api_calls": 2, - "prompt_tokens_total": 648308, - "first_tool": [ - "GameplayTagsToolset", - "AddTag" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "GameplayTagsToolset_GameplayTagsToolset_AddTag" - ], - "bridge_calls": [], - "error": null, - "final_response": "done" - }, - { - "scenario_id": "V5_actor_tag", - "mode": "eager", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 34.71, - "api_calls": 5, - "prompt_tokens_total": 1622365, - "first_tool": [ - "find", - "actors" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_add_tag", - "editor_toolset_toolsets_actor_ActorTools_get_tags", - "editor_toolset_toolsets_object_ObjectTools_get_properties" - ], - "bridge_calls": [], - "error": null, - "final_response": "Something is wrong here, and I'm not going to report \"done\" on faith when the verification contradicts it.\n\nWhat I'm seeing:\n- `add_tag` returned `{\"ok\": true}`.\n- But both read-backs come back garbage: `get_tags` returned a `Brightness` float, and reading the `Tags` property directly returned `Entr" - }, - { - "scenario_id": "V6_niagara_component", - "mode": "eager", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 52.52, - "api_calls": 5, - "prompt_tokens_total": 1623641, - "first_tool": [ - "find", - "actors" - ], - "first_correct": false, - "final_correct": false, - "wrong_calls": 0, - "success": false, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_actor_ActorTools_get_components", - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_object_ObjectTools_list_properties" - ], - "bridge_calls": [], - "error": null, - "final_response": "The signals are now clearly contradictory and none of them let me safely locate a real Niagara effect component with a Brightness parameter:\n\n1. The `NiagaraActor` type search returned the exact same two actors (Torch_3 as a plain \"Actor\", plus Crate_2) \u2014 identical to the unfiltered substring search" - }, - { - "scenario_id": "V7_niagara_system_asset", - "mode": "eager", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 16.33, - "api_calls": 2, - "prompt_tokens_total": 648451, - "first_tool": [ - "System", - "AddUserVariables" - ], - "first_correct": true, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "NiagaraToolsets_NiagaraToolset_System_AddUserVariables" - ], - "bridge_calls": [], - "error": null, - "final_response": "done" - }, - { - "scenario_id": "V8_widget_screenshot", - "mode": "eager", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 46.89, - "api_calls": 7, - "prompt_tokens_total": 2271309, - "first_tool": [ - "SlateInspectorToolset", - "Snapshot" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "SlateInspectorToolset_SlateInspectorToolset_Observe", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "SlateInspectorToolset_SlateInspectorToolset_ListObservers", - "SlateInspectorToolset_SlateInspectorToolset_Windows", - "SlateInspectorToolset_SlateInspectorToolset_WaitFor", - "SlateInspectorToolset_SlateInspectorToolset_Screenshot" - ], - "bridge_calls": [], - "error": null, - "final_response": "The screenshot with an empty ref produced a path, but an empty ref means \"active window\" \u2014 that captures the whole editor window, not the Details panel specifically. I need a widget ref for the Details panel, and the Slate inspector's Snapshot/Windows/ListObservers calls are all returning empty payl" - }, - { - "scenario_id": "V9_save_actor", - "mode": "eager", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 21.67, - "api_calls": 3, - "prompt_tokens_total": 972894, - "first_tool": [ - "find", - "actors" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "editor_toolset_toolsets_scene_SceneTools_find_actors", - "editor_toolset_toolsets_scene_SceneTools_save_actor" - ], - "bridge_calls": [], - "error": null, - "final_response": "done\n\nSaved just Crate_2 (/Game/Map:PersistentLevel.Crate_2) to disk. Note: the search also returned Torch_3 as a fuzzy match, but I persisted only the exact Crate_2 actor you edited \u2014 no full save-all." - }, - { - "scenario_id": "V10_zero_keyword", - "mode": "eager", - "rep": 1, - "n_tools_registered": 830, - "elapsed_seconds": 28.54, - "api_calls": 4, - "prompt_tokens_total": 1297260, - "first_tool": [ - "SlateInspectorToolset", - "Snapshot" - ], - "first_correct": false, - "final_correct": true, - "wrong_calls": 0, - "success": true, - "ue_calls": [ - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "SlateInspectorToolset_SlateInspectorToolset_Snapshot", - "editor_toolset_toolsets_scene_SceneTools_find_actors" - ], - "bridge_calls": [], - "error": null, - "final_response": "Here are the current contents of the World Outliner panel (from the live level's actors \u2014 the authoritative source, not the stale UI cache):\n\nCurrent level: /Game/Map (PersistentLevel)\n\n1. Torch_3\n - Class: Actor\n - Path: /Game/Map:PersistentLevel.Torch_3\n - Components: NiagaraComponent 'FX_Fl" - } -] \ No newline at end of file diff --git a/website/docs/reference/cli-commands.md b/website/docs/reference/cli-commands.md index dbef435e63..0d80ca7be7 100644 --- a/website/docs/reference/cli-commands.md +++ b/website/docs/reference/cli-commands.md @@ -724,7 +724,7 @@ Board resolution order (highest precedence first): `--board ` flag → `HE All actions are also available as a slash command in the gateway (`/kanban …`), with the same argument surface — including `boards` subcommands and the `--board` flag. -For the full design — comparison with Cline Kanban / Paperclip / NanoClaw / Gemini Enterprise, eight collaboration patterns, four user stories, concurrency correctness proof — see `docs/hermes-kanban-v1-spec.pdf` in the repository or the [Kanban user guide](/user-guide/features/kanban). +For the full design — comparison with Cline Kanban / Paperclip / NanoClaw / Gemini Enterprise, eight collaboration patterns, four user stories, concurrency correctness proof — see the [Kanban user guide](/user-guide/features/kanban). ## `hermes egress` diff --git a/website/docs/user-guide/features/kanban.md b/website/docs/user-guide/features/kanban.md index f6bc009e45..b3398bf744 100644 --- a/website/docs/user-guide/features/kanban.md +++ b/website/docs/user-guide/features/kanban.md @@ -43,7 +43,7 @@ This is the shape that covers the workloads `delegate_task` can't: - **Engineering pipelines** — decompose → implement in parallel worktrees → review → iterate → PR. - **Fleet work** — one specialist managing N subjects (50 social accounts, 12 monitored services). -For the full design rationale, comparative analysis against Cline Kanban / Paperclip / NanoClaw / Google Gemini Enterprise, and the eight canonical collaboration patterns, see `docs/hermes-kanban-v1-spec.pdf` in the repository. +The eight canonical collaboration patterns are catalogued in [Collaboration patterns](#collaboration-patterns) below. ## PR completion contracts @@ -1016,8 +1016,6 @@ The board supports these eight patterns without any new primitives: | **P8 Fleet farming** | one profile, N subjects | 50 social accounts | | **P9 Triage specifier** | rough idea → `triage` → `hermes kanban specify` expands body → `todo` | "turn this one-liner into a spec'd task" | -For worked examples of each, see `docs/hermes-kanban-v1-spec.pdf`. - ## Handing context to follow-up cards (the parent link) A parent link is not just a scheduling gate — it is the context handoff channel from a **completed** card to a new one. When you create a card with `--parent `, two things happen: @@ -1276,7 +1274,3 @@ Every transition appends a row to `task_events`. Each row carries an optional `r ## Out of scope Kanban is deliberately single-host. `~/.hermes/kanban.db` is a local SQLite file and the dispatcher spawns workers on the same machine. Running a shared board across two hosts is not supported — there's no coordination primitive for "worker X on host A, worker Y on host B," and the crash-detection path assumes PIDs are host-local. If you need multi-host, run an independent board per host and use `delegate_task` / a message queue to bridge them. - -## Design spec - -The complete design — architecture, concurrency correctness, comparison with other systems, implementation plan, risks, open questions — lives in `docs/hermes-kanban-v1-spec.pdf`. Read that before filing any behavior-change PR. diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/reference/cli-commands.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/reference/cli-commands.md index cf2e8f6d01..4271ae3d2a 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/reference/cli-commands.md +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/reference/cli-commands.md @@ -444,7 +444,7 @@ hermes kanban boards rm atm10-server --delete 所有操作也可作为 gateway 中的斜杠命令使用(`/kanban …`),参数界面相同——包括 `boards` 子命令和 `--board` 标志。 -完整设计——与 Cline Kanban / Paperclip / NanoClaw / Gemini Enterprise 的对比、八种协作模式、四个用户故事、并发正确性证明——请参阅仓库中的 `docs/hermes-kanban-v1-spec.pdf` 或 [Kanban 用户指南](/user-guide/features/kanban)。 +完整设计——与 Cline Kanban / Paperclip / NanoClaw / Gemini Enterprise 的对比、八种协作模式、四个用户故事、并发正确性证明——请参阅 [Kanban 用户指南](/user-guide/features/kanban)。 ## `hermes webhook` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/kanban.md b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/kanban.md index f3cc3bce76..d9d4e8d40b 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/kanban.md +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/user-guide/features/kanban.md @@ -27,7 +27,7 @@ Hermes Kanban 是一个持久化任务看板,在所有 Hermes 配置文件之 - **工程流水线** —— 分解 → 在并行 worktree 中实现 → 审查 → 迭代 → PR。 - **批量任务** —— 一个专家管理 N 个对象(50 个社交账号、12 个监控服务)。 -完整的设计原理、与 Cline Kanban / Paperclip / NanoClaw / Google Gemini Enterprise 的对比分析,以及八种典型协作模式,请参阅仓库中的 `docs/hermes-kanban-v1-spec.pdf`。 +八种典型协作模式见下文的协作模式一节。 ## Kanban 与 `delegate_task` 的对比 @@ -665,8 +665,6 @@ Gateway 平台有实际的消息长度限制。如果 `/kanban list`、`/kanban | **P8 批量任务** | 一个配置文件,N 个对象 | 50 个社交账号 | | **P9 分诊规格器** | 粗略想法 → `triage` → `hermes kanban specify` 扩展正文 → `todo` | "将这个一行描述变成规格化任务" | -每种模式的详细示例,请参阅 `docs/hermes-kanban-v1-spec.pdf`。 - ## 向后续卡片传递上下文(父任务链接) 父任务链接不只是调度门槛——它是从**已完成**卡片向新卡片传递上下文的通道。当你用 `--parent <已完成卡片id>` 创建卡片时,会发生两件事: @@ -863,7 +861,3 @@ hermes kanban runs t_abcd ## 范围之外 Kanban 是刻意单主机的。`~/.hermes/kanban.db` 是本地 SQLite 文件,调度器在同一台机器上启动 worker。不支持跨两台主机运行共享看板 —— 没有"主机 A 上的 worker X,主机 B 上的 worker Y"的协调原语,崩溃检测路径假设 PID 是主机本地的。如果你需要多主机,每台主机运行独立的看板,并使用 `delegate_task` / 消息队列来桥接它们。 - -## 设计规范 - -完整的设计 —— 架构、并发正确性、与其他系统的比较、实现计划、风险、开放问题 —— 存在于 `docs/hermes-kanban-v1-spec.pdf` 中。在提交任何行为变更 PR 之前请先阅读它。 \ No newline at end of file