docs: consolidate design documentation and standardize crate English

This commit is contained in:
2026-10-12 14:58:00 +09:00
parent a633a53274
commit 4efb0ace1f
404 changed files with 4556 additions and 11654 deletions
+11
View File
@@ -0,0 +1,11 @@
# fs-operation
Provides provider-side filesystem operations, bounded search, and pure text editing. Access checks and I/O for logical paths go through the provider's `FsAccessPolicy`. Does not own Workdir identity, Runtime transport, or Tool read history.
## Reference index
- [`FsAccessPolicy`] — provider access, I/O, and resource limits.
- [`CheckedTarget`] — checked saves retaining descriptors and identity.
- [`run_list`] — bounded live pagination.
- [`run_glob`] / [`run_grep`] — provider-side search.
- [`text`] — shared argument, UTF-8 byte limit, and edit result handling.
+17 -6
View File
@@ -1,9 +1,10 @@
//! Identity-fenced access adapter for the existing read/edit/write engine.
//! Identity-fenced access adapter for existing read/edit/write engines.
//!
//! Descriptor-rooted resolution is Linux-only and symlinks/mount crossings fail
//! closed. The final compare and atomic rename are NOT a kernel CAS against an
//! arbitrary external editor: external editors must cooperate with provider
//! serialization. A hostile rename in that last syscall gap is not excluded.
//! Retains target, save-parent, and provider-root descriptors to bind authorization to I/O.
//! Rejects unavailable Linux descriptor primitives, symlinks, and mount crossings.
//! Revalidates names/descriptors until just before save, but the final comparison and rename
//! are not kernel CAS. Does not guarantee against noncooperative external editors replacing
//! entries between those syscalls, or guarantee parent-directory crash durability.
use crate::{AtomicWriteMode, FsAccessPolicy};
use std::fs::{File, Metadata};
use std::io::{Seek, SeekFrom};
@@ -41,7 +42,17 @@ pub fn identity_validator(metadata: &Metadata) -> std::io::Result<Vec<u8>> {
}
}
/// One pinned target and its save parent. Retained through the shared operation.
/// Target, save-parent, and root descriptors retained during shared operations.
///
/// Validators encode device/inode and protected metadata, detecting same-content replacements
/// independently of content hashes. Excludes atime so Read does not invalidate its own observation.
/// Saves publish a new temporary inode by rename; updating one hard-link name does not alter
/// other aliases of the old inode.
///
/// Checks named targets and parents before commit, but cannot exclude external replacements between
/// the final check and rename. Pinned descriptors alone do not guarantee linearizability against
/// arbitrary external editors. Failures after parent creation or save begins report `effects_possible`
/// to callers rather than implying no effects.
pub struct CheckedTarget<'a> {
policy: &'a dyn FsAccessPolicy,
root: File,
+12 -2
View File
@@ -1,5 +1,15 @@
//! Ignore rules loaded only through the provider's authorized descriptor opens.
//! Never use GitignoreBuilder::add/build_global: those reopen host pathnames.
//! Ignore rules read only through provider-authorized descriptors.
//!
//! .ignore takes precedence over Git rules; nearer directories win within the same source class.
//! Retains only current ancestor matchers, pruning ignored directories before enumeration or reading
//! their own rules. Checks scope before opening rule sources; configuration discovery never expands
//! content authority.
//!
//! Glob requires an authorized .git marker; Grep applies .gitignore even without one.
//! Glob skips unavailable sources; Grep preserves existing explicit errors. Both skip scope-denied
//! sources before opening. UTF-8, file/line/aggregate byte limit, and cancellation violations are
//! not turned into under-filtered success. Does not follow global/ambient Git configuration or
//! linked-worktree gitdir/commondir pointers; .git files serve only as markers.
use crate::{FsAccessPolicy, FsError};
use ignore::gitignore::{Gitignore, GitignoreBuilder};
use std::io::{BufRead, BufReader, Read};
+7 -1
View File
@@ -5,7 +5,13 @@ use ignore::WalkBuilder;
use crate::{FsAccessPolicy, FsError, FsPath, GlobRequest, GlobResult};
/// Execute a bounded glob entirely inside the provider process.
/// Bounded Glob within the provider process.
///
/// Descriptor providers check scope before reading ignore rules and prune denied directories
/// before descent. .ignore takes precedence over Git rules; Git rules require an authorized .git
/// marker. Unavailable rule sources are skipped; byte limit or cancellation violations yield errors.
/// Does not follow ambient/global configuration or linked-worktree management pointers.
/// Separate from configuration discovery in regular path-backed walkers.
pub fn run_glob(
root: &Path,
base: &Path,
+1 -5
View File
@@ -1,8 +1,4 @@
//! Foundational filesystem operation contracts and provider-side search.
//!
//! This crate deliberately has no dependency on Workdir identity, Runtime
//! transport, or LLM Tool implementations. Paths are logical and root-relative;
//! providers supply host roots and access policy.
#![doc = include_str!("../README.md")]
mod checked;
pub use checked::{CheckedTarget, identity_validator};
+11
View File
@@ -473,6 +473,17 @@ fn list_entry_bytes(entry: &ListEntry) -> usize {
entry.path.as_str().len().saturating_add(64)
}
/// Bounded live pagination of direct children.
///
/// Sorts directories first, then logical paths within each group. Cursors are exclusive ordering
/// keys and need not still exist. List applies provider read/enumeration scope, not ignore/dotfile
/// filters. The full scan retains only limit+1 candidates within an aggregate path-byte limit.
/// Enumeration order is unspecified, so a full page does not end scanning. Totals describe current
/// visible entries, including those before the cursor.
///
/// No cross-page snapshot: insertions, removals, renames, and kind changes may omit or duplicate entries.
/// Cancellation and traversal ceilings apply even to excluded entries; resource exhaustion is not
/// converted into silent success.
pub fn run_list(
root: &Path,
request: ListRequest,
+7
View File
@@ -220,6 +220,13 @@ struct GrepParams {
offset: Option<usize>,
}
/// Bounded Grep reading content within provider scope.
///
/// Typed result paths come from reports retained after offset/limit, never reverse-parsed from
/// rendered filenames. Descriptor providers read only authorized ignore sources and apply .gitignore
/// without requiring .git markers. Unlike Glob, unavailable/symlinked ignore opens retain existing
/// explicit errors. Scope-denied sources are skipped before opening; global/ambient configuration
/// is not searched. Search is request-time traversal, not a snapshot.
pub fn run_grep(
root: &Path,
base: PathBuf,
+10 -3
View File
@@ -1,7 +1,14 @@
//! Pure text-operation policy shared by filesystem providers and operation frontends.
//! Pure text operations shared by providers and frontends.
//!
//! This module owns no paths, descriptors, version fences, or I/O. Limits count
//! UTF-8 bytes, not characters, and default to unlimited.
//! Owns argument schemas, JSON decoding, edit conditions, and result sizes, not paths, descriptors,
//! authorization, I/O, or version fences. Providers call within existing consistency boundaries;
//! checked edits must not be decomposed into unchecked Read–Write. Adapters own whole-text versus
//! line-range Read selection, history, digests, and canonical multi-file commits.
//!
//! Edit requires a nonempty old string and a different replacement, which may be empty.
//! Unless replace_all is set, the nonoverlapping match must be unique. Providers set UTF-8 byte limits. Arithmetic overflow and capacity are
//! checked before allocating results. Pure validation failures have no side effects; transport
//! failures after dispatch are not converted into validation failures here.
use schemars::JsonSchema;
use serde::{Deserialize, de::DeserializeOwned};