Skip to content

Copy only the tracked fixture into the harness run - #1063

Merged
saworbit merged 8 commits into
mainfrom
fix/harness-copies-tracked-fixture
Sep 29, 2026
Merged

saworbit merged 8 commits into
mainfrom
fix/harness-copies-tracked-fixture

Conversation

@saworbit

Copy link
Copy Markdown
Owner

Description

tests/run_godot_integration.ps1 built its fixture with Copy-Item -LiteralPath $sourceFixtureRoot -Destination $fixtureRoot -Recurse, copying tests/godot_smoke whole. The Python suites run the server against that directory and leave runtime state in its .didi/. So a local harness run started from whatever blackboards and locks earlier Python runs left. A Python suite running at the same time held a byte-range lock in there, and the copy failed before the first assertion with an error that pointed at neither suite.

The copy now leaves out .didi/ and .godot/ at the top of the fixture. Neither exists in a CI checkout, so what CI copies is the same as before.

Related Issues

Fixes #1036

Stacked on #1062, which merges first.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds new MCP tools or capabilities)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update

Checklist

  • My code adheres to the project's coding style guidelines (C++20, 4 spaces).
  • I have added automated tests in tests/ covering new functionality. The change is in the harness; verified below.
  • All native unit tests pass.
  • Live bridge changes pass tests/run_godot_integration.ps1 on Godot 4.5.1. A 4.7.2 run passes locally with the lock held; CI runs all three.
  • Runtime-session changes cover editor and game descriptors, authentication, attach rollback, pause/step/stop, cursor polling, cleanup, and token redaction. Not touched.
  • Expression changes cover the strict read-only grammar, receiver allowlist, output/depth bounds, and cooperative-timeout wording. Not touched.
  • The exact MCP smoke starts with an explicit Godot project, matches the manifest emitted by didi --dump-tool-manifest from the same build, preserves the Phase 4/5/6 contracts, and keeps reserved runtime debugger tools marked unimplemented. Not touched.
  • Any new tool name has an accepted record in docs/SURFACE_AMENDMENTS.md. No new tool.
  • Capability metadata, reference docs, roadmap, and changelog are current. Published tool counts are derived from the manifest, never hand-edited.
  • If this starts or finishes a Build Queue item, its row in docs/BUILD_QUEUE.md says IN PROGRESS, or COMPLETE (#<this pull request>). Not a queue item.
  • Tests added or removed: no count moved; test_inventory.py --check agrees.
  • I have updated relevant documentation in docs/ and README.md. None describes the copy.

Verification

With a separate process holding a byte-range lock on tests/godot_smoke/.didi/blackboard/verify1036.lock, the way a running Python suite does:

  • The old whole-directory copy fails: The process cannot access the file because another process has locked a portion of the file.
  • The harness on 4.7.2 passes, and its fixture holds no .didi/ file from the source tree.

signal_connect's target_script_not_compiled note and LLM_INSTRUCTIONS
said to restart the editor or call editor_reload_project. That tool is
EditorFileSystem.scan_sources, a file rescan, and the editor reads its
autoloads once at startup. project_set_autoload already said the rescan
does not register the singleton.

The live harness now asks the engine. After project_set_autoload it
calls editor_reload_project and repeats the refused connect, and the
script still does not compile on 4.5.1, 4.6.2 and 4.7.2. Both texts now
say to restart, and that the rescan does not register it.

Fixes #1002
The editor_reload_project call added for #1002 is the first
scan_sources after earlier blocks wrote editor_copy_probe.gd and
sandbox_run.gd behind the editor. On 4.5.1 and 4.6.2 the engine prints
Unrecognized UID for their two sidecars; 4.7.2 does not. The lines are
allowed by their exact UIDs and source file, which Godot derives from the
path and contents, so any other UID error still fails the run.
The editor_reload_project call added to the uncompiled-script block ran
a scan_sources in the middle of the harness. It met files other blocks
had written behind the editor and drew engine errors about them: two
Unrecognized UID lines on 4.5 and 4.6, and on CI's software-rendered
4.5.1 runner a frame_pre_draw connection error, on both attempts. None
of that is about the autoload advice.

The engine fact the rescan checked was measured on 4.5.1, 4.6.2 and
4.7.2 and is recorded beside the assertion. The block keeps checking
that the note says to restart and no longer offers the rescan.
runtime_read_output relayed Godot's colour escape codes in its records,
40 of a fresh headless editor's first 41, so a match against the visible
text failed. The ring now strips terminal escapes from a message when it
is captured, before the size bound. The stripper moves to
didi/common/terminal_text.hpp so the extension and the export tools
share it.

The offline helper Godot logged Didi's own INFO line before the WARN
default applies, so shader_check_compile's raw_output began with it.
That line is DEBUG now. The live contract snapshots show raw_output
starting with the engine's banner on 4.5, 4.6 and 4.7.

Fixes #1028
trial.py scored a Claude tester's transcript where the client filed it,
under its own projects store, and never copied it. Trial 05's is gone,
and nothing in its directory can reproduce its scores. The transcript is
now copied into the trial directory as transcript.jsonl and the copy is
scored.

And the tester's tool list restricted nothing: --allowed-tools only
pre-approves, and bypassPermissions approves everything, so trial 06's
tester also reached PowerShell and earlier ones met the host's skills.
The Claude tester now runs with --tools naming seven built-in tools,
ToolSearch among them because Didi's tools arrive deferred, with
--disable-slash-commands and --setting-sources project. A probe with
Claude Code 2.1.220 listed exactly those seven, with Didi's tools behind
ToolSearch. trial.json records the environment as tester_environment.

Fixes #1005
Fixes #1007
tools/localci built every lane with Ninja's default of CPUs + 2, and ASan
builds of the largest translation units need several GB each. On a
16.7 GB, 24-CPU Docker VM the asan lane was killed with "Killed signal
terminated program cc1plus", which reads like a compile error.

The asan lane now builds with one job per 2 GB of the container's
memory, never more than its CPUs; on that VM it chose 7. The gcc and
clang lanes keep Ninja's default. The lane prints the count it chose,
run.sh passes DIDI_LOCALCI_JOBS through, and that overrides any lane.

Fixes #1050
blackboard_write, blackboard_patch, blackboard_clear and the four task
calls built their answers from the board in memory before saving it,
and never read the saved board back, so a save the file did not keep
would still have read as done. Each now saves through saveAndReadBack,
which reloads the file and checks its revision, and takes its revision,
metadata, value and task from what was stored. blackboard_write also
returns the value now at its path, and a clear confirms the path it
removed is gone.

The seven move from exempt to observed in tests/observed_post_state.json.
The live harness compares each answer with the board file as Godot's own
JSON reader parses it, through a new board_file witness. Reporting a
revision one higher than the file holds fails the harness on
blackboard_write.revision.

Part of #1019. Fifteen tools remain on it.
The harness copied tests/godot_smoke whole, including the .didi/ runtime
state the Python suites leave there. A local run then started from that
state, and a suite running at the same time held a byte-range lock in
it that failed the copy before the first assertion.

The copy now leaves out .didi/ and .godot/. Neither exists in a CI
checkout. With a lock held on a file in the source .didi/, the old copy
fails with "locked a portion of the file" and the harness now passes on
4.7.2, with no .didi/ from the source in its fixture.

Fixes #1036
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests Test suites and the contracts they assert addon The Godot addon and the in-engine GDExtension tooling Generators, harnesses, and developer tooling labels Sep 29, 2026
@saworbit
saworbit merged commit 17faf99 into main Sep 29, 2026
28 checks passed
@saworbit
saworbit deleted the fix/harness-copies-tracked-fixture branch September 29, 2026 13:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

addon The Godot addon and the in-engine GDExtension documentation Improvements or additions to documentation tests Test suites and the contracts they assert tooling Generators, harnesses, and developer tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Harness] Copy the smoke fixture without the runtime state Python tests leave in it

1 participant