Repository navigation
fix(harness): the save's import walk says when it leaves code unread, and reads more of it (TH-9543) - #283
Merged
khushalsonawat merged 3 commits intoNov 11, 2026
Conversation
… can spell a name A coding line can name a codec that spells ASCII letters in other bytes (raw_unicode_escape, utf-7, the iso2022 codecs, hz, mac-arabic and mac-farsi), so a file could import playwright or traceai_openai while its raw bytes never held the name. The browser and instrumentation scans searched those raw bytes, and the import walk decoded such files before ending their lines, or read unicode-escape as UTF-8. Every codec not proven safe to search as bytes is now decoded first, as Python reads source (lines ended, a final line end, NUL cut), under the scan's one 4 MiB decode total. The 81 safe codecs are proven by a sweep test. A decoded-first file passes the gate when a needle is in its text, or in its raw bytes when the text isn't ASCII, so no file base lets in is stopped. The walk reads the same way, with its own total, and follows the union of both readings for a unicode-escape file whose text holds a CR, charged once. Refs: TH-9490 Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
… and reads more of it (TH-9543)
- The walk sets stopped when it leaves code it reached unfollowed, beyond its limits:
- a .py holding import whose decoded reading isn't parsed (too big, past the total, or no
tree);
- a code file over the read limit, or a link to one;
- an import name dropped for its length or depth, scripts included;
- a link target past 128 parts;
- a file in a codec decoded first, left undecoded once the walk's decode total ran out.
- The save walk gets its own 512 KB parse total (the other scans keep 256 KB), and each reading
of a file read two ways is charged as it's parsed.
- One flag replaces the walk's two.
Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
The change review cleared with nothing above Medium. Its findings: - A folder link in the agent's folder that leads inside the repository says the walk stopped: the walk doesn't enter it, and the agent may run code there. One that leads out of the repository, such as a data folder, doesn't. - Tests for a refused link target before a candidate's last folder, a reading sized with its line ends folded (decoded and UTF-8), a script with more names than the walk tries, and a decode total spent exactly. - The save's warning says the walk stopped at its limits or left code unread; two test comments say which Python versions they describe. Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
khushalsonawat
added a commit
that referenced
this pull request
Nov 11, 2026
Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
15 of 16 tasks
cdileep23
approved these changes
Nov 11, 2026
khushalsonawat
merged commit Nov 11, 2026
53a54d8
into
feat/TH-8804-source-subfolder
11 checks passed
khushalsonawat
added a commit
that referenced
this pull request
Nov 11, 2026
…288) into TH-9491 - tests/test_harness_sandbox_server.py: both sides appended tests; kept both. - test_contract_writer's allow-list gains #269's two contract.json copies: reading_result.document's replace_if_unchanged (the saved contract's own bytes plus the reading record) and seed_contract.use_seed's _write_whole (the platform's seed, as written). - sandbox_server.py imports SecretResolutionError, which #284's resolver raises but the base never imports: seven sandbox-server tests fail with NameError on the base itself. Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
khushalsonawat
added a commit
that referenced
this pull request
Nov 11, 2026
…total Brings in #269, #276 (through #283), #283 and #288. Three hunks against #288 (TH-9448) were resolved by hand, keeping both intents: - a skipped file logs its type once at WARNING, and its path and trace at DEBUG (#288); it is also counted as the scan's `skipped` cut, and that count is in the cut line, so #288's separate "skipped N files" line is not repeated (TH-9512); - #288's skip tests and its NUL-byte test now expect the cut line, which holds names and counts only. Tests on 3.12.3: test_agent_type_refusal 720, test_browser_scan_cut 59, test_contract_tools_subfolder 180, all passed. Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
khushalsonawat
added a commit
that referenced
this pull request
Nov 11, 2026
- Comments in this branch's code and tests no longer name reviewers, rounds or people; the reason and the measurement stay. - A uv workspace member past the 256 read for names is read when a requirement names its folder, until one declares that name, at most 32 such reads a walk; the walk still says it was cut. A pyproject.toml whose project isn't a table is passed over instead of raising. - The save's import walk: a folder link back into the agent's folder isn't counted as code left unread, unless it leads into a part the walk skips (compared case-folded). Past 32 folder links it says the walk stopped without resolving more. A link to a code file, dangling or not, still counts: telling them apart would follow its chain uncharged. - The walk's docstring says any reached .py holding import that doesn't parse counts as unread, whatever the reason. TH-8804 Signed-off-by: khushalsonawat <khushalsonawat@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Review only commits after 73e9170. This PR carries #276 (TH-9490, 73e9170), which isn't in
feat/TH-8804-source-subfolderyet.Summary
When the contract is saved, the kit follows the agent's imports to the code it runs, so the browser check and instrumentation see shared code outside the agent's folder. That walk skipped some code without a word, and ran out of reading on ordinary agents.
stopped, which the save logs as a WARNING and bundling records astruncatedincredentials.json). This covers:.pyholdingimportwhose decoded reading isn't parsed: too big, past the total, or newer syntax;stopped: a file with no import, a standard-library name, a file Python itself refuses, a data file a script imports, and a folder link out of the repository.Why: an import Python runs could hide behind a file the walk couldn't parse, and every ordinary subfolder agent over 256 KB of Python was cut on every save.
TH-9543 lands before TH-9512, which re-points its walk-stop test when it merges this.
Known limits:
ai_toolsandagentic_eval, and the kit'ssrc/fi/alk/harnessandexamples/frameworks. They reach 4-32 MB of Python and more than 5,000 import names. Reading them fully is TH-9445's (one capped subprocess and one deadline for the save)..pyover 128 KB that holds an import now says the walk stopped: 53 tracked files in the futureagi backend, 18 in the kit'ssrc/.Pre-existing, for Khushal's read (TH-9445):
feat/TH-8804-source-subfolder, 6.3-8.0 s with fix(harness): decode a Python file before searching it when its codec can spell a name (TH-9490) #276, and 7.9-8.3 s with this change. On 3.12 it's 3.6-4.4 s before, and 4.2-4.8 s with this change, under the 5 s line Khushal set for feat(harness): build an agent from a repo's subfolder #225.Verification
uv run ruff check .: not run on the whole repo.ruff checkon the changed files passes. Focused pytest target, the seven changed-area files: 1532 passed on 3.12.14 and 3.12.3, and 1506 passed plus 26 skipped on 3.11 (25 of fix(harness): decode a Python file before searching it when its codec can spell a name (TH-9490) #276's are 3.12-only).tests/harness/test_agent_type_refusal.py: one test per case above, plus a test that pins 512 KB exactly.tests/test_harness_credentials.py: a walk that can't parse a file marks the manifest truncated.tests/harness/test_python_source_codecs.py: fix(harness): decode a Python file before searching it when its codec can spell a name (TH-9490) #276's charge test now charges each reading.pytest -qon each of those files.sdk-smoke.yml's list on 3.12.14: 3689 passed, 3 skipped, 2 deselected. The named list on 3.11: 4179 passed, 32 skipped and 16 failed, the same 16 that fail onfeat/TH-8804-source-subfolder, none about this walk.agent-learn release-proof: not run.Checklist
agent_learning.*,agent-learn, or@future-agi/agent-learning-kit