Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

### Fixed

- `xtask run-edict-operation` runs outside Git and resolves relative artifact and WAL paths from the caller directory. Repository maintenance commands retain their Git-root behavior.

- `WorldlineState::state_root` documentation now states its reachable-state boundary. Detached create-if-absent writes remain bound by patch and commit identities. Hash bytes are unchanged.

- `ReadView::at` validates the aperture and derives the selected current frontier
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ compiler-declared maximum result size is capped at 65,536 before private
scheduler evaluation. Produced canonical result bytes are measured against that
declared ceiling during evaluation.

The built `xtask run-edict-operation` binary keeps the caller's working directory and can run outside a Git checkout. Relative artifact and WAL paths resolve from that directory. `cargo xtask` still requires a Cargo workspace. Repository maintenance commands continue to resolve paths from their Git root.

## Contracts And Boundaries

Echo core is intentionally generic. Application nouns belong in authored
Expand Down
15 changes: 8 additions & 7 deletions xtask/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,15 +452,16 @@ struct PrPreflightArgs {
}

fn main() -> Result<()> {
// Ensure CWD is the repo root so that relative paths like "docs/",
// "scripts/ensure_spdx.sh", and git-ls-files all work regardless of
// where `cargo xtask` is invoked from.
let repo_root = find_repo_root()?;
std::env::set_current_dir(&repo_root)
.with_context(|| format!("failed to chdir to {}", repo_root.display()))?;

let cli = Cli::parse();

// Maintenance commands resolve repository paths from the Git root. The
// artifact runner resolves supplied paths from the caller's directory.
if !matches!(&cli.command, Commands::RunEdictOperation(_)) {
let repo_root = find_repo_root()?;
std::env::set_current_dir(&repo_root)
.with_context(|| format!("failed to chdir to {}", repo_root.display()))?;
}

match cli.command {
Commands::Bench(args) => run_bench(args),
Commands::Doghouse(args) => run_doghouse(args),
Expand Down
86 changes: 86 additions & 0 deletions xtask/tests/run_edict_operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ impl TempRunDir {
.expect("xtask belongs to the Echo workspace")
.join("target")
.join("xtask-test-tmp");
Self::new_in(root)
}

fn outside_repo() -> Self {
Self::new_in(std::env::temp_dir().join("echo-xtask-test"))
}

fn new_in(root: PathBuf) -> Self {
fs::create_dir_all(&root).expect("the xtask fixture root is creatable");
for _ in 0..1024 {
let ordinal = RUN_COUNTER.fetch_add(1, Ordering::Relaxed);
Expand Down Expand Up @@ -142,6 +150,84 @@ fn assert_rejected(output: &Output, expected_reason: &str) {
);
}

#[test]
fn runner_accepts_absolute_artifacts_outside_git() {
let run_dir = TempRunDir::outside_repo();
let git_probe = Command::new("git")
.args(["rev-parse", "--show-toplevel"])
.current_dir(run_dir.path())
.output()
.expect("the Git fixture probe starts");
assert!(!git_probe.status.success(), "fixture must be outside Git");
let output = runner_command(
&fixture_path("executable-operation-package.cbor"),
&fixture_path("verification-report.cbor"),
&fixture_path("input.json"),
&run_dir.path().join("wal"),
)
.current_dir(run_dir.path())
.output()
.expect("the standalone runner starts");
assert!(
output.status.success(),
"{}",
String::from_utf8_lossy(&output.stderr)
);
let report: serde_json::Value =
serde_json::from_slice(&output.stdout).expect("runner reports JSON");
assert_eq!(report["recovery"]["stateRecovered"], true);
assert_eq!(report["state"]["valueUtf8"], "Hello Echo");
}

#[test]
fn runner_preserves_relative_paths_in_an_unrelated_nested_repository() {
let run_dir = TempRunDir::outside_repo();
assert!(Command::new("git")
.args(["init", "-q"])
.current_dir(run_dir.path())
.status()
.expect("fixture Git initialization starts")
.success());
let nested = run_dir.path().join("nested");
fs::create_dir(&nested).expect("caller directory is creatable");
fs::copy(fixture_path("input.json"), nested.join("input.json")).expect("input is copied");
let output = runner_command(
&fixture_path("executable-operation-package.cbor"),
&fixture_path("verification-report.cbor"),
Path::new("input.json"),
Path::new("wal"),
)
.current_dir(&nested)
.output()
.expect("the nested runner starts");
assert!(
output.status.success(),
"{}",
String::from_utf8_lossy(&output.stderr)
);
let report: serde_json::Value =
serde_json::from_slice(&output.stdout).expect("runner reports JSON");
assert_eq!(report["recovery"]["stateRecovered"], true);
assert!(nested.join("wal").is_dir());
assert!(!run_dir.path().join("wal").exists());
}

#[test]
fn repository_commands_still_resolve_the_echo_root() {
let run_dir = TempRunDir::new();
let output = Command::new(env!("CARGO_BIN_EXE_xtask"))
.arg("lint-dead-refs")
.current_dir(run_dir.path())
.output()
.expect("repository command starts");
assert!(
output.status.success(),
"{}",
String::from_utf8_lossy(&output.stderr)
);
assert!(String::from_utf8_lossy(&output.stdout).contains("all links OK"));
}

#[test]
fn compiler_emitted_operation_runs_durably_without_native_callbacks() {
let run_dir = TempRunDir::new();
Expand Down
Loading