Problem
The daemon carries three parallel vocabularies for "the read side of a file or directory," under three different naming idioms, with overlapping or identical shapes. On top of that, the Git capability exposes two historical-read methods with distinct result contracts. This blurs the convention that #643 established (a bare name is the portable @endo/platform shape; an Endo prefix marks the daemon's authority-bearing specialization) and forces callers to learn more than one historical-read surface.
Symptoms
All references are in packages/daemon/src/types.d.ts (plus the Git surface in @endo/exo-git):
ReadableBlobView and EndoReadable have identical members (streamBase64, text, json, getInfo, fetch, help). Two names, one shape.
ReadableTreeView is EndoReadableTree minus the content-address identity (sha256). EndoGitTree is a third has / list / lookup read-tree. Three read-tree types share one structural core.
- Within a single type the idioms mix:
EndoMountFile.readOnly() returns a ReadableBlobView, while EndoMountFile.snapshot() returns an EndoReadable. Two read faces of the same file, two vocabularies.
- The
...View suffix collides with the platform names it says it mirrors, and it fits neither the bare-name axis nor the Endo axis.
Git.tree(ref): Promise<ReadableTree> and Git.filesystemAt(ref): Promise<Filesystem> are both live implementations. filesystemAt is the richer and preferred surface, and it already has a cross-package consumer in agent-tools.
Findings on the historical-read entry point
filesystemAt(ref) should be the canonical entry point for new caller and agent-facing work. It returns the same Filesystem vocabulary used for the live worktree, supports the richer directory/file operations, range reads, BlobRef snapshots, and composition, and gives a new caller one durable mental model.
Removing tree(ref) still fits the eventual small-surface goal, but it is not a documentation-only or mechanical migration:
- Both methods are implemented and covered by tests. The premise that they are Phase-1 stubs is stale.
filesystemAt(ref).root() returns an @endo/platform Directory; that interface has no readOnly() method. The proposed filesystemAt(ref).root().readOnly() replacement is therefore not type-correct.
ReadableTree and Directory have different contracts. A removal needs each current tree use to be rewritten to the operation it actually needs, or needs a deliberately designed adapter. A compatibility adapter would preserve a second public concept, so it should not be introduced merely to make the migration appear cheap.
The DX/AX decision is consequently: recommend filesystemAt now, retain tree only as the existing compatibility surface, and make removal a focused implementation change once its call-site rewrites are demonstrated. That change should delete tree, migrate the existing tests, and avoid adding a new public bridge unless a concrete consumer requires one.
Proposed solution
Collapse onto one Endo read hierarchy, retire the ...View idiom, and use one canonical historical-read entry point.
Read types:
EndoReadable: read side of a blob or file (streamBase64, text, json, getInfo, fetch, help). EndoMountFile.readOnly() returns this. Delete ReadableBlobView.
EndoReadableTree: base read-tree (has, list, lookup, help). EndoMount.readOnly() returns this. Delete ReadableTreeView.
EndoSnapshotTree extends EndoReadableTree, adding sha256 and getInfo (the content-addressed tree).
EndoGitTree extends EndoReadableTree, adding the git-archive methods (the historical view).
Surface:
filesystemAt(ref) is the canonical historical-read entry point.
tree(ref) is a compatibility surface, not a projection claim. A focused implementation follow-up may deprecate and remove it after it replaces each caller with a type-correct Filesystem operation and verifies no public bridge is needed.
Retire the ...View idiom entirely, folding makeReadableTreeView and makeReadableBlobView into the Endo readables.
Result
One daemon read hierarchy (EndoReadable, EndoReadableTree, plus the snapshot and git specializations) that mirrors the platform ReadableBlob / ReadableTree / SnapshotTree shapes, with no bare ...View names. New historical-read consumers use filesystemAt(ref); the implementation follow-up decides whether the remaining compatibility method can be removed without adding a kitchen-sink bridge.
Out of scope
References
Problem
The daemon carries three parallel vocabularies for "the read side of a file or directory," under three different naming idioms, with overlapping or identical shapes. On top of that, the
Gitcapability exposes two historical-read methods with distinct result contracts. This blurs the convention that #643 established (a bare name is the portable@endo/platformshape; anEndoprefix marks the daemon's authority-bearing specialization) and forces callers to learn more than one historical-read surface.Symptoms
All references are in
packages/daemon/src/types.d.ts(plus theGitsurface in@endo/exo-git):ReadableBlobViewandEndoReadablehave identical members (streamBase64,text,json,getInfo,fetch,help). Two names, one shape.ReadableTreeViewisEndoReadableTreeminus the content-address identity (sha256).EndoGitTreeis a thirdhas/list/lookupread-tree. Three read-tree types share one structural core.EndoMountFile.readOnly()returns aReadableBlobView, whileEndoMountFile.snapshot()returns anEndoReadable. Two read faces of the same file, two vocabularies....Viewsuffix collides with the platform names it says it mirrors, and it fits neither the bare-name axis nor theEndoaxis.Git.tree(ref): Promise<ReadableTree>andGit.filesystemAt(ref): Promise<Filesystem>are both live implementations.filesystemAtis the richer and preferred surface, and it already has a cross-package consumer inagent-tools.Findings on the historical-read entry point
filesystemAt(ref)should be the canonical entry point for new caller and agent-facing work. It returns the sameFilesystemvocabulary used for the live worktree, supports the richer directory/file operations, range reads,BlobRefsnapshots, and composition, and gives a new caller one durable mental model.Removing
tree(ref)still fits the eventual small-surface goal, but it is not a documentation-only or mechanical migration:filesystemAt(ref).root()returns an@endo/platformDirectory; that interface has noreadOnly()method. The proposedfilesystemAt(ref).root().readOnly()replacement is therefore not type-correct.ReadableTreeandDirectoryhave different contracts. A removal needs each currenttreeuse to be rewritten to the operation it actually needs, or needs a deliberately designed adapter. A compatibility adapter would preserve a second public concept, so it should not be introduced merely to make the migration appear cheap.The DX/AX decision is consequently: recommend
filesystemAtnow, retaintreeonly as the existing compatibility surface, and make removal a focused implementation change once its call-site rewrites are demonstrated. That change should deletetree, migrate the existing tests, and avoid adding a new public bridge unless a concrete consumer requires one.Proposed solution
Collapse onto one
Endoread hierarchy, retire the...Viewidiom, and use one canonical historical-read entry point.Read types:
EndoReadable: read side of a blob or file (streamBase64,text,json,getInfo,fetch,help).EndoMountFile.readOnly()returns this. DeleteReadableBlobView.EndoReadableTree: base read-tree (has,list,lookup,help).EndoMount.readOnly()returns this. DeleteReadableTreeView.EndoSnapshotTreeextendsEndoReadableTree, addingsha256andgetInfo(the content-addressed tree).EndoGitTreeextendsEndoReadableTree, adding the git-archive methods (the historical view).Surface:
filesystemAt(ref)is the canonical historical-read entry point.tree(ref)is a compatibility surface, not a projection claim. A focused implementation follow-up may deprecate and remove it after it replaces each caller with a type-correctFilesystemoperation and verifies no public bridge is needed.Retire the
...Viewidiom entirely, foldingmakeReadableTreeViewandmakeReadableBlobViewinto theEndoreadables.Result
One daemon read hierarchy (
EndoReadable,EndoReadableTree, plus the snapshot and git specializations) that mirrors the platformReadableBlob/ReadableTree/SnapshotTreeshapes, with no bare...Viewnames. New historical-read consumers usefilesystemAt(ref); the implementation follow-up decides whether the remaining compatibility method can be removed without adding a kitchen-sink bridge.Out of scope
@endo/platformand mount path-type consolidation in refactor(fs): consolidate mount and Git capability contracts #643 (landing separately).unknowndeclarations in@endo/exo-git(ensureCredentialUsablematerial,updatedRefs,head,branch), which are a separate builder change.References
Endo-prefix convention.filesystemAt, which makes thetree/filesystemAtreconciliation ripe.designs/daemon-git-next-steps.mdsection 5 ("Reconcile TreeRef and FilesystemAtRef into one canonical vocabulary").