Condense the documentation and thin the server's comments

The markdown had accumulated a lot that was stale rather than wrong.
PLAN.md still described pi as the llama.cpp harness, a refcounted
LlamaServerManager, and a providers-by-hosts cross-product, all of which
were superseded or never built; it also carried a second copy of the HTTP
table that routes.rs owns. EXPLORER.md and TRANSCRIPT_CACHE.md held
implementation checklists for work that has since landed. AGENTS.md
restated most of PLAN.md's design instead of being the working-notes
layer it says it is. 3225 lines of markdown to 2180, with the stale
sections gone rather than reworded.

On the server, comments explaining what the code already says are out and
the ones recording a constraint, a measurement or an incident are kept but
cut to a few lines each: 5504 comment lines to 4586.

Four doc comments in session/mod.rs, and one each in process.rs and
usage.rs, had drifted onto the item above the one they describe --
functions were reordered without them, so `stop_session`'s doc sat on
`set_session_cwd`, `stat_of`'s on `struct Stat`, and `UsageMonitor`'s on
`type Cached`. Each is back on its own item.

routes.rs's module table also claimed later phases would add `/hosts`,
which setups replaced.

cargo test (127 passed), clippy --all-targets and fmt are clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
irisandClaude Opus 5 committed 2026-09-04 15:45:43 -04:00
1 parent e3e02d55f7
commit 79682f03a7
24 files changed
+4572 -6821

No files matched your search

+69 -92
View File
@@ -1,45 +1,39 @@
//! Building the command a driver actually spawns -- locally, or wrapped in
//! `ssh` when the session names a host to run on.
//!
//! The whole point of the session design is that a driver speaks JSONL over
//! a child process's stdio and doesn't care what that child is. A remote
//! session is therefore the identical command with `ssh host …` in front:
//! stdio doesn't care, so nothing downstream of here changes.
//! A driver speaks JSONL over a child process's stdio and doesn't care what
//! that child is, so a remote session is the identical command with `ssh host …`
//! in front.
//!
//! Uses the system `ssh` client rather than a Rust SSH library, so
//! `~/.ssh/config`, agents, and jump hosts all keep working and there is
//! only one place to configure connections (PLAN.md, rule 23).
//! `~/.ssh/config`, agents and jump hosts all keep working and there is only
//! one place to configure connections.
use std::path::{Path, PathBuf};
use std::process::Command;
use crate::config::SshConfig;
/// Options forced onto every connection. `BatchMode` makes a missing key
/// fail immediately with a readable message instead of hanging on a
/// password prompt that nothing can answer; the keepalives turn a silently
/// dropped link into a process exit, which the session reports as `exited`
/// rather than appearing to hang forever.
/// Options forced onto every connection. `BatchMode` makes a missing key fail
/// immediately with a readable message instead of hanging on a password prompt
/// nothing can answer; the keepalives turn a silently dropped link into a
/// process exit, which the session reports as `exited` rather than hanging.
const SSH_OPTIONS: [&str; 3] = [
"BatchMode=yes",
"ServerAliveInterval=30",
"ServerAliveCountMax=3",
];
/// Builds the child process for `program args…`, run in `cwd`, either on
/// this machine (`ssh` absent) or on the machine it describes.
/// Builds the child process for `program args…`, run in `cwd`, either on this
/// machine (`ssh` absent) or on the machine it describes.
///
/// Stdio is left alone: how the streams are connected is the caller's
/// decision and differs by more than the transport does -- a probe wants
/// pipes it will drain, a session wants files that outlive this server --
/// so `Transport::spawn` applies it rather than this.
/// Stdio is left alone: how the streams are connected is the caller's decision
/// and differs by more than the transport does -- a probe wants pipes it will
/// drain, a session wants files that outlive this server.
///
/// A plain [`std::process::Command`], which `tokio` converts from, because
/// not every caller is async: the usage fetch is blocking by nature (it
/// makes a blocking HTTP call) and reads a file from the same machine on
/// the way, and it should not have to build an ssh invocation of its own
/// to do that. One place knows what a correct invocation is; how it is run
/// is the caller's business.
/// A plain [`std::process::Command`], which `tokio` converts from, because not
/// every caller is async: the usage fetch is blocking by nature and should not
/// have to build an ssh invocation of its own.
pub fn command(
remote: Option<&SshConfig>,
program: &str,
@@ -50,22 +44,19 @@ pub fn command(
let mut command = Command::new(program);
command.args(args);
if let Some(cwd) = cwd {
// Expanded here for the same reason `quote_path` expands it on
// the far side: a working directory typed as `~/repos/ai-app`
// has to mean the same thing whichever machine runs it. There
// is no shell in this branch, so nothing else would --
// `current_dir` would be handed the literal one-character
// directory `~`, and the session would fail to start with an
// error naming a path nobody typed. Only the cwd, matching
// the remote side, where arguments stay literal.
// Expanded here for the same reason `quote_path` expands it on the
// far side: a working directory typed as `~/repos/ai-app` has to
// mean the same thing whichever machine runs it. There is no shell
// in this branch, so nothing else would -- `current_dir` would be
// handed the literal one-character directory `~`.
command.current_dir(expand_home(cwd));
}
return command;
};
let mut command = Command::new("ssh");
// -T: no pty. This carries JSONL, and a pty would rewrite it (echo,
// CRLF translation, ^C handling) into something the parser can't read.
// -T: no pty. This carries JSONL, and a pty would rewrite it (echo, CRLF
// translation, ^C handling) into something the parser can't read.
command.arg("-T");
for option in SSH_OPTIONS {
command.args(["-o", option]);
@@ -78,9 +69,8 @@ pub fn command(
}
if let Some(identity) = &ssh.identity_file {
command.arg("-i").arg(identity);
// Without this, ssh may offer an agent key first and authenticate
// as somebody else entirely -- silently, and with different
// permissions than intended.
// Without this, ssh may offer an agent key first and authenticate as
// somebody else entirely -- silently, and with different permissions.
command.args(["-o", "IdentitiesOnly=yes"]);
}
command.arg(&ssh.address);
@@ -88,11 +78,10 @@ pub fn command(
command
}
/// The single argument handed to the remote login shell.
///
/// `exec` so the CLI replaces that shell: the process the connection is
/// attached to is then the CLI itself, and dropping the connection takes
/// it down rather than leaving an orphan behind a live wrapper.
/// The single argument handed to the remote login shell. `exec` so the CLI
/// replaces that shell: the process the connection is attached to is then the
/// CLI itself, and dropping the connection takes it down rather than leaving an
/// orphan behind a live wrapper.
fn remote_script(program: &str, args: &[String], cwd: Option<&Path>) -> String {
let mut script = String::new();
if let Some(cwd) = cwd {
@@ -112,11 +101,9 @@ fn remote_script(program: &str, args: &[String], cwd: Option<&Path>) -> String {
/// A path with a leading `~` replaced by this machine's home directory.
///
/// The local half of the rule [`quote_path`] states for the remote one, and
/// the two are deliberately the same shape: the tilde is expanded, `~user`
/// is not (there is no portable expansion for another account's home), and
/// nothing else in the path gains a meaning. A machine with no home
/// directory at all leaves the path alone, which fails with the operating
/// system's own message rather than with a guess.
/// deliberately the same shape: the tilde is expanded, `~user` is not, and
/// nothing else in the path gains a meaning. A machine with no home directory
/// leaves the path alone, which fails with the operating system's own message.
pub(crate) fn expand_home(path: &Path) -> PathBuf {
let Some(rest) = path.to_str().and_then(|p| {
if p == "~" {
@@ -136,23 +123,19 @@ pub(crate) fn expand_home(path: &Path) -> PathBuf {
/// Quotes a path, expanding a leading `~` and nothing else.
///
/// [`quote`] is right for every other word crossing to the remote side and
/// wrong for exactly one character. `~` means "expand me", and single
/// quotes are what stop expansion -- so a working directory typed as
/// `~/repos/ai-app` arrived as the literal four-character directory `~`,
/// and the remote shell said it did not exist. Which is true, and reads
/// like the path being wrong rather than the quoting.
/// wrong for exactly one character. `~` means "expand me", and single quotes
/// are what stop expansion -- so a working directory typed as `~/repos/ai-app`
/// arrived as the literal four-character directory `~`, and the remote shell
/// said it did not exist, which reads like the path being wrong.
///
/// `"$HOME"` rather than handing the tilde to the shell unquoted: the
/// variable is expanded, the expansion is not re-split or globbed because
/// it is double-quoted, and everything after it stays single-quoted and
/// literal. So the one character that has to mean something keeps meaning
/// it, and nothing else gains a meaning. `$HOME` is set by every shell
/// this can land in, including the fish login shell on the dev VM, which
/// is why this does not depend on the remote shell being POSIX.
/// `"$HOME"` rather than handing the tilde to the shell unquoted: the variable
/// is expanded, the expansion is not re-split or globbed because it is
/// double-quoted, and everything after it stays single-quoted and literal.
/// `$HOME` is set by every shell this can land in, including the fish login
/// shell on the dev VM, so this does not depend on the remote shell being POSIX.
///
/// `~user` is deliberately not handled: there is no portable expansion for
/// it, and inventing one would mean guessing another account's home
/// directory. It stays literal and fails with the shell's own message.
/// `~user` is deliberately not handled: there is no portable expansion for it,
/// and inventing one would mean guessing another account's home directory.
pub(crate) fn quote_path(path: &str) -> String {
if path == "~" {
return "\"$HOME\"".to_string();
@@ -163,15 +146,13 @@ pub(crate) fn quote_path(path: &str) -> String {
}
}
/// Single-quotes one word for a POSIX shell.
///
/// Everything crossing to the remote side goes through here: paths, model
/// names, and prompts-as-arguments are all attacker-adjacent input in a
/// server whose whole job is running commands, and unquoted they would be
/// shell syntax rather than data.
/// Single-quotes one word for a POSIX shell. Everything crossing to the remote
/// side goes through here: paths, model names and prompts-as-arguments are all
/// attacker-adjacent input in a server whose whole job is running commands, and
/// unquoted they would be shell syntax rather than data.
pub(crate) fn quote(word: &str) -> String {
// Inside single quotes every character is literal except `'` itself,
// which is closed, escaped, and reopened.
// Inside single quotes every character is literal except `'` itself, which
// is closed, escaped, and reopened.
format!("'{}'", word.replace('\'', r"'\''"))
}
@@ -192,8 +173,8 @@ mod tests {
}
/// A host with nothing configured but a name to dial, so `~/.ssh/config`
/// decides everything else -- the case that proves this adds no flags of
/// its own when it was not told to.
/// decides everything else -- the case that proves this adds no flags of its
/// own when it was not told to.
fn bare_host() -> SshConfig {
SshConfig {
address: "vm".to_string(),
@@ -256,19 +237,17 @@ mod tests {
assert!(!rendered.contains(&"IdentitiesOnly=yes".to_string()));
}
/// The one character quoting must not swallow.
///
/// A working directory typed as `~/repos/ai-app` was arriving as the
/// literal directory `~`, and the remote shell reported it missing --
/// which reads as the path being wrong rather than the quoting being
/// wrong, and cost an evening on exactly that misreading.
/// The one character quoting must not swallow. A working directory typed as
/// `~/repos/ai-app` was arriving as the literal directory `~`, and the
/// remote shell reported it missing -- which reads as the path being wrong
/// rather than the quoting being wrong, and cost an evening.
#[test]
fn a_leading_tilde_expands_and_nothing_else_does() {
assert_eq!(quote_path("~"), "\"$HOME\"");
assert_eq!(quote_path("~/repos/ai-app"), "\"$HOME\"/'repos/ai-app'");
// Only leading, and only its own segment: a tilde anywhere else is
// an ordinary character in a filename, and `~user` has no portable
// expansion so it stays literal and fails with the shell's message.
// Only leading, and only its own segment: a tilde anywhere else is an
// ordinary character in a filename, and `~user` has no portable
// expansion so it stays literal.
assert_eq!(quote_path("/tmp/~/x"), "'/tmp/~/x'");
assert_eq!(quote_path("~user/x"), "'~user/x'");
@@ -279,13 +258,11 @@ mod tests {
);
}
/// The same character, on the transport with no shell to expand it.
///
/// The local branch runs the program directly, so a working directory
/// of `~/repos/ai-app` would reach `current_dir` as the literal
/// one-character directory `~` -- a session that fails to start,
/// naming a path nobody typed. The two transports have to agree about
/// what a tilde means or a path is only portable by accident.
/// The same character, on the transport with no shell to expand it. The
/// local branch runs the program directly, so a working directory of
/// `~/repos/ai-app` would reach `current_dir` as the literal one-character
/// directory `~`. The two transports have to agree about what a tilde means
/// or a path is only portable by accident.
#[test]
fn a_local_cwd_expands_its_tilde_the_same_way() {
let Some(home) = std::env::home_dir() else {
@@ -306,9 +283,9 @@ mod tests {
#[test]
fn shell_metacharacters_cross_as_data_not_syntax() {
// Expanding $HOME must not open a door for anything else: the rest
// stays single-quoted, so this remains one absurd path rather than
// three commands.
// Expanding $HOME must not open a door for anything else: the rest stays
// single-quoted, so this remains one absurd path rather than three
// commands.
assert_eq!(
quote_path("~/'; touch /tmp/pwned; '"),
r#""$HOME"/''\''; touch /tmp/pwned; '\'''"#,
@@ -320,8 +297,8 @@ mod tests {
assert_eq!(quote("$(whoami)"), "'$(whoami)'");
assert_eq!(quote("it's"), r"'it'\''s'");
// The end-to-end version of the same worry: a working directory
// that tries to close the quote and start a new command.
// The end-to-end version of the same worry: a working directory that
// tries to close the quote and start a new command.
let ssh = bare_host();
let evil = Path::new("/tmp/'; touch /tmp/pwned; '");
let rendered = argv(&command(Some(&ssh), "claude", &[], Some(evil)));