Skip to content

file-safety (S2/S4 follow-up): track read completeness in FileObservation; require complete observation for full-file update #46

Description

@easonLiangWorldedtech

Scope

Follow-up from the CodeRabbit review of #1408 (S4b, epic #1375 file-safety series). The review finding (comment on src/core/tools/ReadFileTool.ts:238) points out that read completeness is not tracked:

  • processTextFile() is slice-based by default: even a read_file without explicit offset/limit returns at most DEFAULT_LINE_LIMIT lines (truncated, with a warning), and indentation mode returns only a semantic block.
  • The observation registered after such a read is file-level onlyFileObservation = { version, observedAt } (src/core/task/observationRegistry.ts), with the version token derived from on-disk fs.stat.
  • So fs.readFile can complete successfully, the version tokens can match, and a later write_to_file full-file replacement still passes the guardedWrite() update path — even though the model only ever saw a slice of the file.

Proposed behavior

  1. Extend FileObservation with read scope (S2 registry, feat(task): per-task file observation registry (A2, #1375) Zoo-Code-Org/Zoo-Code#1394): e.g. complete: boolean plus the observed line range / total line count (from processTextFile's result: returnedLines, totalLines, includedRanges).
  2. Registration records the scope (ReadFileTool): a read that delivered the whole file (or an explicit full-file read) marks the observation complete; slice/indentation/truncated reads mark it partial with the delivered range.
  3. guardedWrite() requires a complete observation for the update kind (full-file replacement): a partial observation rejects the update with the standard stale/guard rejection (re-read remediation), while the edit kind keeps working on any prior observation (optionally, a later step could also scope edit to the observed range).
  4. Re-reading the file extends/refreshes the observation as today; a complete read supersedes a partial one.

Acceptance criteria

  • Regression test: file read through a truncated slice → write_to_file full replacement → rejected with the standard guard error; after a complete read → allowed.
  • Regression test: edit kind still permitted after a slice read (no behavior change for scoped edits in this step).
  • FileObservation scope fields round-trip through the registry semantics (re-observe replaces the entry).

References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions