feat(file): wire the file agent's read/write/write-csv verbs (#268)#269
Merged
Conversation
The `_core/file` agent published a contract (read/write/write-csv/watch) but had
no runtime handler — the builtin dispatch in invoker.rs had arms for
html-report/ui/vision/viewer-3d/ifc but none for file, so every file/* node
fell through to "no handler" and apps referencing it were rejected at
validate/compile (status: planned).
Wire the three single-shot IO verbs (render/file.rs, mirroring ifc.rs):
- write — string→UTF-8, encoding:base64→raw bytes (land a pre-generated binary
artifact like a .xlsx), non-string JSON→compact JSON. mode: write
(mutates external state like http.post; a consuming app declares a
`safety:` block, which a frozen node skips).
- write-csv — RFC-4180 with explicit column order; object or positional-array
rows; a row wider than the columns is rejected (no silent truncation).
- read — UTF-8 text or base64; dry-run returns an empty stub (never requires
the file to exist). encoding validated up front.
The disk write is gated to a real run (skipped under --dry-run/--simulate),
exactly like ifc.write. Outputs report an absolute path. The streaming `watch`
event source (#240) stays per-command status: planned until its watcher lands.
Manifest flipped agent status planned→available; added the `encoding` input;
`columns` marked required; sidecar docs updated; registry-catalog regenerated.
Verified: cargo build/clippy -D warnings/fmt, full test suite, 10 new file unit
tests, `agent reindex --check` fresh, and a real `aware app run` writing a
correct CSV + a base64 binary file to disk. Dual-reviewed (Codex + pr-review).
pawellisowski
added a commit
that referenced
this pull request
Jun 25, 2026
pawellisowski
added a commit
that referenced
this pull request
Jun 26, 2026
…#269 file manifest fix) (#271) #269 changed `20-agents/_core/file/manifest.yaml` (status: planned → available) INSIDE the rolling `main.tar.gz`, but did not touch `registry-index.json`. The agent-install tarball cache is keyed on `Index::snapshot_fingerprint()` (a hash of registry-index.json), so a manifest change that leaves the index unchanged never rotates the key — users who cached `main.tar.gz` between #257 (2026-06-18) and #269 (2026-06-25) keep getting the STALE `file` manifest (status: planned). `aware app run` then rejects an actually-runnable `file/write` node with E_APP_AGENT_UNAVAILABLE. Bumping `updated-at` is the documented "manual refresh lever" (registry/index.rs): it rotates the fingerprint so every stale tarball cache busts on the next install (index is fetched live from main with a 1h TTL), and `file` installs as status: available. Data-only; `aware agent reindex --check` stays green (the catalog carries its own timestamp). Systemic fix tracked separately.
pawellisowski
added a commit
that referenced
this pull request
Jun 26, 2026
…backs (#270) Ships the residual tarball-cache staleness fixes merged since v0.81.0: - #272 (#270): 1h TTL on the agent-install tarball cache so an in-archive manifest change that leaves registry-index.json byte-identical self-heals within an hour, with graceful fallback to a prior index-consistent cache on offline/corrupt/raced refreshes. - #271: bump registry-index.json updated-at to bust warm caches for the #269 file agent.
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.
Closes #268.
What
The
_core/fileagent published a contract (read/write/write-csv/watch) but had no runtime handler — the builtin dispatch incli/src/runtime/invoker.rshad arms for html-report/ui/vision/viewer-3d/ifc but none forfile, so everyfile/*node fell through to"no handler"and apps referencing it were rejected at validate/compile (status: planned). This wires the three single-shot IO verbs so an app can export a node's output to disk.How
cli/src/render/file.rs(new, mirroringrender/ifc.rs) + 3 dispatch arms:write— string→UTF-8;encoding: base64→raw bytes (land a pre-generated binary artifact like a.xlsx/image/zip); non-string JSON→compact JSON.mode: write— it can overwrite an arbitrary path, so it mutates external state likehttp.post; a consuming app declares asafety:block (which a frozen node skips).write-csv— RFC-4180 with explicitcolumnsorder; object or positional-array rows; a row wider thancolumnsis rejected (no silent truncation).read— UTF-8 text or base64;encodingvalidated up front; dry-run returns an empty stub (never requires the file to exist).Disk write gated to a real run (skipped under
--dry-run/--simulate), likeifc.write. Outputs report an absolute path. Manifest: agentstatusplanned→available; addedencodinginput;columnsmarked required;watchkept per-commandstatus: planned(the #240 streaming watcher is separate). Sidecar docs updated;registry-catalog.jsonregenerated.Verification
cargo build·clippy -D warnings·fmt --check· fullcargo test(0 failures) ·agent reindex --checkfresh.aware app run: a.flowithfile/write-csv+file/write encoding:base64(each with asafety:block) wrote a correct RFC-4180 CSV and aPK-magic binary file to disk; a no-safety variant is correctly refused at the run pre-flight.Review
Dual-reviewed (Codex + pr-review-toolkit). Codex's blocker — read-mode bypasses the safety contract for an arbitrary-path writer — was upheld and fixed by restoring
mode: write(consistent withhttp.post;ifc.writeis the narrow domain-export exception). All should-fixes (absolute-path output, encoding-before-dry-run, over-wide-row rejection) and pr-review's doc/folder-alias/columns-required items are addressed.Why it matters
Unblocks floless.app's steel-takeoff BOM export as freezable run-stage nodes (
file/write-csvfor CSV;file/write+ base64 for a host-baked.xlsx) — and gives the substrate a generic "land tabular/binary output on disk" primitive any app can compose.