Skip to content
Closed
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
28 changes: 20 additions & 8 deletions docs-internal/registry-parity-worklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ actual backing:
| **findutils** (`find`,`xargs`) | TODO | our hand-rolled on `regex`/shims | real GNU findutils, or `uutils/findutils` |
| **tree** | DONE | our hand-rolled, zero deps | real `tree`, or an established one |
| **grep** | DONE | our `secureexec-grep` on raw `regex` (**not** an established grep pkg) | real **GNU grep** |
| **ripgrep** (`rg`) | TODO | our `secureexec-grep` recursive search shim, not real ripgrep | real upstream **ripgrep** |
| **ripgrep** (`rg`) | DONE | our `secureexec-grep` recursive search shim, not real ripgrep | real upstream **ripgrep** |
| **zip** | DONE | our 203-line `zip.c` over zlib/minizip (not Info-ZIP) | real Info-ZIP, or an established lib's CLI |
| **unzip** | DONE | our 669-line `unzip.c` over zlib/minizip | real Info-ZIP unzip |
| **sqlite3 CLI** | DONE | our 558-line `sqlite3_cli.c` (engine is real SQLite; the shell is ours) | real SQLite `shell.c` (its official CLI) |
Expand Down Expand Up @@ -267,8 +267,20 @@ works (`wasi-spawn` broker), so `xargs` is not a blocker.
and `2026-07-08T06-42-18-0700-grep-check-types-final.log`; e2e grep tests
pass 8/8 in `2026-07-08T06-43-59-0700-grep-vitest-after-wrapper-cache-repair.log`.
Rev: `uyukolvr` — `fix(grep): build upstream GNU grep`.
NB: `secureexec-grep` remains only because `@agentos-software/ripgrep` still
uses it for `rg`; replace `rg` with real ripgrep in a separate rev.
- **ripgrep — DONE.** Replaced the `@agentos-software/ripgrep` package's custom
`secureexec-grep` recursive search shim with upstream ripgrep 15.1.0 from the
canonical `BurntSushi/ripgrep` crate/release. The local `cmd-rg` crate is now
only a build trigger, and `toolchain/Makefile` builds ripgrep's own `rg` bin
directly. The old `secureexec-grep` library is gone. Proof: latest upstream
release captured in `2026-07-08T06-50-40-0700-ripgrep-github-latest-release.json`;
crate metadata captured in `2026-07-08T06-52-00-0700-ripgrep-cargo-info.log`;
upstream WASM build passes in
`2026-07-08T06-56-00-0700-ripgrep-upstream-wasm-build-after-grep-dir-remove-fixed.log`;
package build and check-types pass in
`2026-07-08T06-58-55-0700-ripgrep-package-build-after-install.log` and
`2026-07-08T06-58-56-0700-ripgrep-check-types-after-install.log`; e2e ripgrep
tests pass 8/8 in `2026-07-08T07-02-00-0700-ripgrep-vitest-after-git-fixture.log`.
Rev: `msypkqmo` — `fix(ripgrep): build upstream ripgrep`.
- **zip / unzip — moderate.** Real **Info-ZIP** source (fetch+pin like zlib/sqlite);
zlib is already vendored. Filesystem + `isatty`/`utime`/`chmod`/perms stubs; no
sockets/threads/spawn. Friction is Info-ZIP's crufty build, not syscalls.
Expand Down Expand Up @@ -472,12 +484,12 @@ real e2e tests that prove Linux-parity behavior — not smoke tests.
- **Proof:** each un-skipped suite passes with real behavior.
- **rev:** one per command, e.g. `test(duckdb): real analytical-SQL e2e; un-skip`

### 12. No tests at all — 12 software + 5 agents
- **Broken:** zero e2e coverage: `gawk, sed, grep, tar, gzip, jq, ripgrep, yq,
diffutils, file, vim`; agents `claude, codex, opencode, pi, pi-cli`.
### 12. No tests at all — 9 software + 5 agents
- **Broken:** zero e2e coverage: `gawk, sed, tar, gzip, jq, yq, diffutils,
file, vim`; agents `claude, codex, opencode, pi, pi-cli`.
- **Objective:** write real e2e tests proving each behaves like its Linux
counterpart (jq processes real JSON, sed edits streams, tar round-trips archives,
grep/rg search real trees, gzip round-trips, etc.); agents exercise the real ACP
counterpart (jq processes real JSON, sed edits streams, tar round-trips archives,
gzip round-trips, etc.); agents exercise the real ACP
adapter against the upstream SDK.
- **Proof:** `software/<pkg>/test/` exists and passes for each; coverage gate green.
- **rev:** one per package, e.g. `test(jq): add real JSON-processing e2e`
Expand Down
Binary file modified packages/runtime-core/commands/rg
Binary file not shown.
Binary file modified software/ripgrep/bin/rg
Binary file not shown.
10 changes: 5 additions & 5 deletions software/ripgrep/native/crates/cmd-rg/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ version.workspace = true
edition.workspace = true
license.workspace = true
description = "rg (ripgrep) standalone binary for secure-exec VM"

[[bin]]
name = "rg"
path = "src/main.rs"
publish = false

[dependencies]
secureexec-grep = { path = "../../../../../toolchain/crates/libs/grep" }
# ripgrep is a bin-only crate. `toolchain/Makefile` builds its upstream `rg`
# binary directly; this local package exists only so `cmd/rg` is discoverable
# and the upstream package is present in Cargo's resolved/vendor set.
ripgrep = { version = "15.1.0", default-features = false }
1 change: 1 addition & 0 deletions software/ripgrep/native/crates/cmd-rg/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//! Build trigger for the upstream `ripgrep` command package.
4 changes: 0 additions & 4 deletions software/ripgrep/native/crates/cmd-rg/src/main.rs

This file was deleted.

128 changes: 128 additions & 0 deletions software/ripgrep/test/ripgrep.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { dirname, join } from "node:path";
import { createWasmVmRuntime } from "@agentos/test-harness";
import {
COMMANDS_DIR,
NodeFileSystem,
createKernel,
describeIf,
hasWasmBinaries,
} from "@agentos/test-harness";
import type { Kernel } from "@agentos/test-harness";
import { afterEach, describe, expect, it } from "vitest";

let tempRoot: string | undefined;

async function createTestVFS(): Promise<NodeFileSystem> {
tempRoot = await mkdtemp(join(tmpdir(), "agentos-ripgrep-"));

await writeFixture(
"/project/src/main.rs",
["fn main() {", ' println!("needle");', "}"].join("\n") + "\n",
);
await writeFixture(
"/project/src/lib.rs",
["pub fn helper() {", " // Needle in a comment", "}"].join("\n") + "\n",
);
await writeFixture("/project/docs/readme.md", "needle in docs\n");
await writeFixture("/project/vendor/generated.rs", "needle in vendor\n");
await writeFixture("/project/.hidden.txt", "needle hidden\n");
await writeFixture("/project/.gitignore", "vendor/\n");
await writeFixture("/project/.git/HEAD", "ref: refs/heads/main\n");

return new NodeFileSystem({ root: tempRoot });
}

async function writeFixture(path: string, contents: string): Promise<void> {
if (!tempRoot) throw new Error("fixture root not initialized");
const hostPath = join(tempRoot, path.replace(/^\/+/, ""));
await mkdir(dirname(hostPath), { recursive: true });
await writeFile(hostPath, contents);
}

function lines(stdout: string): string[] {
return stdout
.split("\n")
.filter((line) => line.length > 0)
.sort();
}

describeIf(hasWasmBinaries, "ripgrep command", { timeout: 10_000 }, () => {
let kernel: Kernel;

afterEach(async () => {
await kernel?.dispose();
if (tempRoot) {
await rm(tempRoot, { recursive: true, force: true });
tempRoot = undefined;
}
});

async function mountFixture(): Promise<void> {
const vfs = await createTestVFS();
kernel = createKernel({ filesystem: vfs });
await kernel.mount(createWasmVmRuntime({ commandDirs: [COMMANDS_DIR] }));
}

it("reports the upstream ripgrep version", async () => {
await mountFixture();

const result = await kernel.exec("rg --version", {});
expect(result.stdout).toContain("ripgrep 15.1.0");
expect(result.stdout).not.toContain("secure-exec");
});

it("searches recursively and respects .gitignore by default", async () => {
await mountFixture();

const result = await kernel.exec("rg needle /project", {});
const output = lines(result.stdout);

expect(output).toContain('/project/src/main.rs: println!("needle");');
expect(output).toContain("/project/docs/readme.md:needle in docs");
expect(output).not.toContain("/project/vendor/generated.rs:needle in vendor");
expect(output).not.toContain("/project/.hidden.txt:needle hidden");
});

it("supports case-insensitive search", async () => {
await mountFixture();

const result = await kernel.exec("rg -i needle /project/src", {});
expect(lines(result.stdout)).toContain("/project/src/lib.rs: // Needle in a comment");
});

it("supports fixed-string search", async () => {
await mountFixture();

const result = await kernel.exec("rg -F 'println!(\"needle\")' /project/src", {});
expect(result.stdout.trim()).toBe('/project/src/main.rs: println!("needle");');
});

it("supports glob filtering", async () => {
await mountFixture();

const result = await kernel.exec("rg needle /project -g '*.md'", {});
expect(result.stdout.trim()).toBe("/project/docs/readme.md:needle in docs");
});

it("can include hidden and ignored files when requested", async () => {
await mountFixture();

const result = await kernel.exec("rg -uu needle /project", {});
const output = lines(result.stdout);

expect(output).toContain("/project/.hidden.txt:needle hidden");
expect(output).toContain("/project/vendor/generated.rs:needle in vendor");
});

it("emits JSON search records", async () => {
await mountFixture();

const result = await kernel.exec("rg --json needle /project/docs", {});
const records = lines(result.stdout).map((line) => JSON.parse(line));

expect(records.some((record) => record.type === "match")).toBe(true);
expect(records.some((record) => record.type === "summary")).toBe(true);
});
});
Loading