[GH-ISSUE #1231] fix(process): truncated filesystem snapshots report surviving files as deleted #431

Closed
opened 2026-10-15 18:25:00 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 9, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/1231

Summary

Process capture reports a definite deleted filesystem effect for an unchanged file that remains on disk when the post-run snapshot reaches its file-count limit. The global truncated flag is present, but the effect itself asserts a deletion that did not occur. A larger-limit control reports the same file as unchanged.

Steps to reproduce

Run this script from a disposable working directory. It creates its own observation directory, uses the current Node executable's absolute path, keeps the scenario and results outside the observed directory, and runs the failing budget followed by the control against the package baseline below.

python3 - <<'PYTHON'
import json, pathlib, subprocess, tempfile
root = pathlib.Path(tempfile.mkdtemp(prefix='rea-filesystem-repro-'))
observed = root / 'observed'
observed.mkdir()
(observed / 'z.txt').write_text('unchanged')
node = subprocess.check_output(['node', '-p', 'process.execPath'], text=True).strip()
for limit in [2, 3]:
    (observed / 'a.txt').unlink(missing_ok=True)
    scenario = {'executable': node, 'arguments': ['-e', "require('node:fs').writeFileSync('a.txt','created')"], 'working_directory': str(observed), 'filesystem_observation_paths': ['.'], 'limits': {'files': limit}}
    scenario_path = root / 'scenario.json'
    scenario_path.write_text(json.dumps(scenario))
    result = subprocess.run(['npx', '-y', 'rea-agents@6.1.0', 'capture-process', str(scenario_path), '--json'], capture_output=True, text=True, timeout=60)
    (root / ('result-' + str(limit) + '.json')).write_text(result.stdout)
    capture = json.loads(result.stdout)['normalized_result']
    effect = next(item for item in capture['filesystem_effects'] if item['path'] == 'root_0:z.txt')
    print({'limit': limit, 'exit': result.returncode, 'truncated': capture['truncated'], 'z_exists': (observed / 'z.txt').exists(), 'z_contents': (observed / 'z.txt').read_text(), 'reported_status': effect['status']})
PYTHON

The directory itself counts toward limits.files. The second run changes that limit from 2 to 3 after removing only the file created by the first run. The existing z.txt remains unchanged throughout. The full outputs are retained in the script's disposable directory for inspection.

Expected behavior

A file omitted because observation limits were exhausted must not be reported as definitely deleted. The documented capture is a bounded snapshot of selected paths that records truncation and unknowns; it should distinguish unobserved state from observed absence. The unchanged file may remain unknown under the small budget, while the larger-budget control should continue to classify it as unchanged.

Actual behavior

Both runs exit 0. With the small limit, files_before contains root_0:. and root_0:z.txt; files_after contains root_0:. and newly created root_0:a.txt. The still-present z.txt is omitted by the after-snapshot limit, but filesystem_effects contains { "path": "root_0:z.txt", "status": "deleted", "after": null } and truncated is true. Direct filesystem inspection finds z.txt with its unchanged nine-byte contents. With the larger limit, truncated is false and the effect for z.txt is unchanged. The small-limit failure and larger-limit control both reproduce on the release and main source builds.

Evidence

  • Expected source: docs/process-capture.md, Capture a command, bounded filesystem snapshots and truncation/unknown guarantees; repository AGENTS.md, Boundary Contracts, the requirement that completeness follow what was examined and exhausted.
  • Failure source: Executed process-capture CLI trials, their returned before/after snapshots and effects, and post-run existence/content checks for the unchanged file; the only control change was the file-count budget after removing the created file.
  • Evidence provenance: observed
  • Local verification: reproduced
  • Reproduction completeness: complete

Runtime or environment

REA release source revision ae9aaee16b9c738d761d3938a3b34fdf37e581b5 reporting package 6.1.0; main source revision f0da05f67fff1411cf2f7a48a752ee7b348c71ff; Node.js v26.10.0; macOS 27.0.1 arm64. The target is a finite owned Node process creating one ordinary file.

Restoration check

Repeat both budget cases and directly check the file afterward. The small-budget capture must preserve its truncation coverage while avoiding a definite deletion assertion for the surviving file; the sufficient-budget control must still report the file as unchanged. An actual deletion under a complete observation must continue to be reported as deleted.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: Returned capture Evidence gives a false definite filesystem effect whenever a previously observed entry is omitted by a later bounded snapshot. The observed case incorrectly reports deletion of an unchanged file; the global truncated flag prevents some equivalence claims but does not correct the false effect.
  • Workaround status: available
  • Workaround basis: Raise the file-count budget enough to exhaust both snapshots; changing the reproduction's budget from 2 to 3 produced the correct unchanged effect with complete snapshots on both tested builds.
Originally created by @coygeek on GitHub (Oct 9, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/1231 ## Summary Process capture reports a definite `deleted` filesystem effect for an unchanged file that remains on disk when the post-run snapshot reaches its file-count limit. The global `truncated` flag is present, but the effect itself asserts a deletion that did not occur. A larger-limit control reports the same file as `unchanged`. ## Steps to reproduce Run this script from a disposable working directory. It creates its own observation directory, uses the current Node executable's absolute path, keeps the scenario and results outside the observed directory, and runs the failing budget followed by the control against the package baseline below. ```sh python3 - <<'PYTHON' import json, pathlib, subprocess, tempfile root = pathlib.Path(tempfile.mkdtemp(prefix='rea-filesystem-repro-')) observed = root / 'observed' observed.mkdir() (observed / 'z.txt').write_text('unchanged') node = subprocess.check_output(['node', '-p', 'process.execPath'], text=True).strip() for limit in [2, 3]: (observed / 'a.txt').unlink(missing_ok=True) scenario = {'executable': node, 'arguments': ['-e', "require('node:fs').writeFileSync('a.txt','created')"], 'working_directory': str(observed), 'filesystem_observation_paths': ['.'], 'limits': {'files': limit}} scenario_path = root / 'scenario.json' scenario_path.write_text(json.dumps(scenario)) result = subprocess.run(['npx', '-y', 'rea-agents@6.1.0', 'capture-process', str(scenario_path), '--json'], capture_output=True, text=True, timeout=60) (root / ('result-' + str(limit) + '.json')).write_text(result.stdout) capture = json.loads(result.stdout)['normalized_result'] effect = next(item for item in capture['filesystem_effects'] if item['path'] == 'root_0:z.txt') print({'limit': limit, 'exit': result.returncode, 'truncated': capture['truncated'], 'z_exists': (observed / 'z.txt').exists(), 'z_contents': (observed / 'z.txt').read_text(), 'reported_status': effect['status']}) PYTHON ``` The directory itself counts toward `limits.files`. The second run changes that limit from 2 to 3 after removing only the file created by the first run. The existing `z.txt` remains unchanged throughout. The full outputs are retained in the script's disposable directory for inspection. ## Expected behavior A file omitted because observation limits were exhausted must not be reported as definitely deleted. The documented capture is a bounded snapshot of selected paths that records truncation and unknowns; it should distinguish unobserved state from observed absence. The unchanged file may remain unknown under the small budget, while the larger-budget control should continue to classify it as unchanged. ## Actual behavior Both runs exit 0. With the small limit, `files_before` contains `root_0:.` and `root_0:z.txt`; `files_after` contains `root_0:.` and newly created `root_0:a.txt`. The still-present `z.txt` is omitted by the after-snapshot limit, but `filesystem_effects` contains `{ "path": "root_0:z.txt", "status": "deleted", "after": null }` and `truncated` is true. Direct filesystem inspection finds `z.txt` with its unchanged nine-byte contents. With the larger limit, `truncated` is false and the effect for `z.txt` is `unchanged`. The small-limit failure and larger-limit control both reproduce on the release and main source builds. ## Evidence - Expected source: `docs/process-capture.md`, Capture a command, bounded filesystem snapshots and truncation/unknown guarantees; repository `AGENTS.md`, Boundary Contracts, the requirement that completeness follow what was examined and exhausted. - Failure source: Executed process-capture CLI trials, their returned before/after snapshots and effects, and post-run existence/content checks for the unchanged file; the only control change was the file-count budget after removing the created file. - Evidence provenance: observed - Local verification: reproduced - Reproduction completeness: complete ## Runtime or environment REA release source revision `ae9aaee16b9c738d761d3938a3b34fdf37e581b5` reporting package 6.1.0; main source revision `f0da05f67fff1411cf2f7a48a752ee7b348c71ff`; Node.js v26.10.0; macOS 27.0.1 arm64. The target is a finite owned Node process creating one ordinary file. ## Restoration check Repeat both budget cases and directly check the file afterward. The small-budget capture must preserve its truncation coverage while avoiding a definite deletion assertion for the surviving file; the sufficient-budget control must still report the file as unchanged. An actual deletion under a complete observation must continue to be reported as deleted. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: Returned capture Evidence gives a false definite filesystem effect whenever a previously observed entry is omitted by a later bounded snapshot. The observed case incorrectly reports deletion of an unchanged file; the global truncated flag prevents some equivalence claims but does not correct the false effect. - Workaround status: available - Workaround basis: Raise the file-count budget enough to exhaust both snapshots; changing the reproduction's budget from 2 to 3 produced the correct unchanged effect with complete snapshots on both tested builds.
bsakaguchi 2026-10-15 18:25:00 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#431
No description provided.