Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
4c84b35
report: remove the proxy era
k4rthiknerella Oct 13, 2026
157edee
report: say what the nono field is without the proxy it was compared …
k4rthiknerella Oct 13, 2026
7c5340a
mutation: judge b9's count mutant by the rewritten tests only
k4rthiknerella Oct 13, 2026
0f1d86d
store: the forget record's hole no longer names a proxy store
k4rthiknerella Oct 14, 2026
8820f54
restate host and sandbox comments without the retired proxy
k4rthiknerella Oct 15, 2026
211bce0
correct H-86's premise comment about when baseline writes
k4rthiknerella Oct 15, 2026
de5979e
leave an unrelated marker-less baseline on disk
k4rthiknerella Oct 15, 2026
3c4c287
remove the project-keyed baseline forget wrapper
k4rthiknerella Oct 15, 2026
5603922
match a baseline host truncated mid-write
k4rthiknerella Oct 15, 2026
7e5fbec
feed ssh hosts into the novelty candidates
k4rthiknerella Oct 15, 2026
0740309
count ssh hosts in family coverage
k4rthiknerella Oct 15, 2026
f6cceb3
print the forget summary before either step's error
k4rthiknerella Oct 15, 2026
fb8a65d
suppress a stale forgotten host in destinations, families and chains
k4rthiknerella Oct 15, 2026
8824b30
reword stale proxy-era comments and drop a test that passes for the w…
k4rthiknerella Oct 15, 2026
fc849d9
carry a version field on every rendered report
k4rthiknerella Oct 15, 2026
741d105
assert no non-stdlib module and pin the release listing's own environ…
k4rthiknerella Oct 15, 2026
23f6a72
scan source for syscalls the import-based no-network check cannot see
k4rthiknerella Oct 15, 2026
e054b64
reword novelty as baseline absence, not as being first
k4rthiknerella Oct 15, 2026
2a0b0cf
perf: budgets.json and the resource gates
k4rthiknerella Oct 13, 2026
cc3bc00
benchgate: refuse a foreign toolchain, report unbudgeted runs, pin th…
k4rthiknerella Oct 13, 2026
c5bc597
perf: the RES-2 scan follows every path initialisation takes
k4rthiknerella Oct 13, 2026
387f775
perf: measure every entry row on the store its budget names
k4rthiknerella Oct 13, 2026
a1888ed
ci: pin the perf jobs to the toolchain the rows were measured under
k4rthiknerella Oct 13, 2026
aacb3e7
perf: pin the harness's toolchain preflight and its run checks untagged
k4rthiknerella Oct 13, 2026
4d5c317
perf: the RES-2 scan follows a sync.Once result that initialisation c…
k4rthiknerella Oct 13, 2026
6af732a
perf: read each child's peak rss through a reaper that holds nothing
k4rthiknerella Oct 15, 2026
6151591
benchgate: exit 2 when budgets.json has no benchmark rows
k4rthiknerella Oct 15, 2026
6ca138a
budget: say which entry figures are gated and which are information only
k4rthiknerella Oct 15, 2026
739e94c
h17: scope the import ban to what a shipped binary can link
k4rthiknerella Oct 14, 2026
f890e0f
store: group commit, one full sync per hook process
k4rthiknerella Oct 13, 2026
a0ce550
store: a failed barrier is final, as a failed flush is
k4rthiknerella Oct 13, 2026
ec656ee
perf: RES-30 gates the per-process rule against a measured 1-way figure
k4rthiknerella Oct 13, 2026
817a7cf
store: the sync recorder logs the barrier the kernel accepted
k4rthiknerella Oct 13, 2026
802618f
store: every lock is counted and every sync is seen by the recorder
k4rthiknerella Oct 13, 2026
22d5ffe
report: a flush_failed marker naming no call is not a lost call
k4rthiknerella Oct 13, 2026
3e0b2cc
store: say when group commit's kill window closes, and what the burst…
k4rthiknerella Oct 13, 2026
4c15041
perf: res-30 judges every process, and hook and post run on one proc
k4rthiknerella Oct 13, 2026
2affcea
store: every full sync is syncFull's, checked from the source
k4rthiknerella Oct 13, 2026
0834653
perf: hook and post keep the runtime's default gomaxprocs
k4rthiknerella Oct 13, 2026
d6c0d9e
perf: res-30 holds the largest process to 1.25x the median of 25 solo…
k4rthiknerella Oct 13, 2026
f84b321
store: a barrier that was a full sync leaves flush nothing
k4rthiknerella Oct 13, 2026
4d2c5b0
store: one source check reads every lock, sync and the barrier's command
k4rthiknerella Oct 13, 2026
236ada7
store: name every way a process ends before its flush
k4rthiknerella Oct 13, 2026
d01c596
report: name each call a flush_failed marker covers
k4rthiknerella Oct 13, 2026
1cc9a52
store: a refused darwin barrier is judged through an fcntl seam
k4rthiknerella Oct 13, 2026
765bb44
perf: res-30's ratio tolerance is chosen in the untagged gate
k4rthiknerella Oct 13, 2026
955d3ea
perf: res-30 runs on the rig every entry row is measured on
k4rthiknerella Oct 14, 2026
e1bf931
perf: remeasure the rows group commit changes
k4rthiknerella Oct 14, 2026
5c3dfa2
store: the forgotten-host record locks and syncs where the recorder s…
k4rthiknerella Oct 14, 2026
1f947a9
schema: flush_failed closes nothing, and the terminal enum names it
k4rthiknerella Oct 14, 2026
de959c8
ci: run the darwin half of group commit and the parallel gate
k4rthiknerella Oct 15, 2026
1597a66
hook: catch SIGHUP and SIGQUIT in WatchSignals
k4rthiknerella Oct 15, 2026
7802e11
hook: add a fault point between Close and Flush
k4rthiknerella Oct 15, 2026
96f7cb8
mutation: skip a mutant whose target does not build on this GOOS
k4rthiknerella Oct 15, 2026
ad7f6c6
contracts: the types and stubs the 1.2.0 tracks build against
k4rthiknerella Oct 14, 2026
64f8246
intake: one bounded read and one scan of every hook payload
k4rthiknerella Oct 13, 2026
8f74b5e
perf: read peak rss through one helper that builds on every platform
k4rthiknerella Oct 13, 2026
3d77918
perf: every entry row's peak-rss p50 is measured on the reference mac…
k4rthiknerella Oct 14, 2026
58a7da6
perf: record this tree's rss case medians beside their lines
k4rthiknerella Oct 14, 2026
45f9c42
perf: measure each child's peak rss through a reaper that holds nothing
k4rthiknerella Oct 13, 2026
4d8416d
perf: post.edit_314k's p95 is RES-28's line now that P-10 has landed
k4rthiknerella Oct 14, 2026
6751cdc
perf: an entry gated against the reference row on another platform sa…
k4rthiknerella Oct 13, 2026
d998149
schema: flush_failed and payload_too_large join the record reason enums
k4rthiknerella Oct 14, 2026
82dce08
jsonscan: measure the walk, not Valid's own pool, for zero allocation
k4rthiknerella Oct 14, 2026
81eff7d
cmd/rashomon: separate RES7's race growth bound from the non-race one
k4rthiknerella Oct 14, 2026
df17877
jsonscan: keep Top's zero-allocation check where the pool is determin…
k4rthiknerella Oct 14, 2026
55031e8
hookio: cover Read under slow readers and both intake caps
k4rthiknerella Oct 15, 2026
d8bc1ac
report: payload_too_large is refused without parsing, not unread
k4rthiknerella Oct 15, 2026
99466c2
hookio: say Lines and Tail are staged, not already in use
k4rthiknerella Oct 15, 2026
a3f9a9e
hookio: say which fields Strs may have already written
k4rthiknerella Oct 15, 2026
e20cb84
shape: hold the lexer's per-word state in one value
k4rthiknerella Oct 13, 2026
c51a946
shape: stop lexing at a token bound derived from Derive's cost per token
k4rthiknerella Oct 13, 2026
f5b2406
hook: bound the leading-cd fold at 64 steps and walk past cds in a loop
k4rthiknerella Oct 13, 2026
343295d
shape: pin maxNest at its deepest level and one past it
k4rthiknerella Oct 13, 2026
1a0e075
host: one spelling per address, a shape check and a length bound for …
k4rthiknerella Oct 13, 2026
83711bc
baseline: lock the load-fold-save, cap the host map, write only what …
k4rthiknerella Oct 13, 2026
3a0c85a
bounds: test every input bound at N and N+1
k4rthiknerella Oct 13, 2026
1292605
shape: read the leading cds of a line cut at the token bound
k4rthiknerella Oct 13, 2026
a0fad10
shape: split lex into a lexer and one method per construct
k4rthiknerella Oct 13, 2026
c86c532
shape: search the removed backslash-newlines instead of scanning them
k4rthiknerella Oct 13, 2026
06b4053
shape: bound every reading of a pathological line, not only its tokens
k4rthiknerella Oct 13, 2026
4711333
shape: restate the token bound from Derive's measured cost per token
k4rthiknerella Oct 13, 2026
0d2f496
hook: say what bounds the work on a payload, and that it is measured
k4rthiknerella Oct 13, 2026
ed78d20
shape: split shape.go by what each part reads
k4rthiknerella Oct 13, 2026
4e35daf
shape: split masked.go and parseSimple under the size limits
k4rthiknerella Oct 13, 2026
80b04d4
shape: pin that Derive reads a line three times
k4rthiknerella Oct 13, 2026
0e7900c
hook: state the measured rss peak as measured
k4rthiknerella Oct 13, 2026
0dce181
mutation: name only lld-9's own tests in its mutant file
k4rthiknerella Oct 13, 2026
4b7664c
forget: ask about a host in the spelling it is recorded in
k4rthiknerella Oct 13, 2026
5df7bdb
cmd/rashomon: pin the hook's exit, deadline and peak rss on pathologi…
k4rthiknerella Oct 13, 2026
c026aa2
shape: report a line cut at the token bound or the cd fold
k4rthiknerella Oct 13, 2026
f19d4e0
res10/res29: gate on work, not wall time, under the race detector
k4rthiknerella Oct 14, 2026
e39d29a
schema: the hosts, ssh_hosts, cwd_digest and host_digest bounds
k4rthiknerella Oct 14, 2026
c1b7264
shape: cap the runner groups statusMasked re-runs the line for
k4rthiknerella Oct 15, 2026
a50049e
shape: bound how far authority scans for its terminator
k4rthiknerella Oct 15, 2026
71ba162
shape: gate two tests on allocation, or wall time only under no race
k4rthiknerella Oct 15, 2026
a74f61f
baseline, report: canonicalise legacy hosts wherever they are read back
k4rthiknerella Oct 15, 2026
c86edb4
shape: gofmt the authority window test
k4rthiknerella Oct 15, 2026
2719cac
report: canonicalise a host before asking whether it was forgotten
k4rthiknerella Oct 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
22 changes: 10 additions & 12 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
# rashomon dependency updates
#
# This file used to say there was no `gomod` entry because the module declared
# no requirements -- standard library only, on the grounds that a PreToolUse
# hook which blocks tool calls when it panics has no room for a supply chain --
# and to add one the day that stopped being true. That day arrived with the
# destinations work: reading the proxy's store needs a SQLite driver.
# The module declares no requirements: standard library only, on the grounds
# that a PreToolUse hook which blocks tool calls when it panics has no room
# for a supply chain. It carried one dependency for a while, a pure-Go SQLite
# driver that read a proxy's store, and the proxy went with its era. The
# `gomod` entry stays, so that the next dependency is watched from its first
# day rather than from the day somebody remembers this file.
#
# The recorder's guarantee did not change, and it is not the absence of
# dependencies that holds it up. modernc.org/sqlite is pure Go, so it adds no
# C toolchain and no cgo; it reaches the hook's own dependency graph not at all
# (a test asserts internal/hook imports no networking package, and a second
# asserts only internal/launch may import os/exec); and it is opened read-only
# against a database this program never writes. What a dependency DOES add is
# a supply chain, which is what this entry watches.
# The recorder's guarantee is not the absence of dependencies: a test asserts
# that no package in the binary imports a networking package, and another
# that nothing imports os/exec. What a dependency DOES add is a supply chain,
# which is what the entry watches.
version: 2

updates:
Expand Down
83 changes: 75 additions & 8 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,6 @@ jobs:
# message in the log right above it;
# - each dynamic test must positively `--- PASS`, so renaming or
# deleting one cannot slip past a grep that only hunts skips.
#
# What this job still does NOT cover: TestRead_AgainstARealProxyStore
# (internal/wire/real_store_check_test.go) stays opt-in behind
# RASHOMON_REAL_STORE=/path/to/causal.db and has never run, here or
# anywhere. It is the one test that would catch the Altrace proxy
# drifting causal.db's schema out from under internal/wire's reader,
# and it needs a store the real proxy wrote, which the proxy team has
# yet to provide. When such a fixture lands, wire it into this job.
- name: H-17 dynamic tests (a SKIP is a failure)
shell: bash
run: |
Expand Down Expand Up @@ -272,3 +264,78 @@ jobs:
env:
GOOS: windows
run: go vet ./...

perf-linux:
name: Perf gates (linux)
runs-on: ubuntu-latest
# Benchmarks run 3x20 iterations, the RSS harness runs the release binary
# some three hundred times; the bound is DEL-17's.
timeout-minutes: 25
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
# The rows in test/perf/budgets.json were measured under go1.27.2
# (its go_version), and allocation figures are the toolchain's:
# BenchmarkBuild/188 makes 21,660 allocations per op under 1.25.8
# and 6,832 under 1.27.2. benchgate and the harness refuse any other
# toolchain, so this pin moves only with a remeasurement.
go-version: "1.27.2"
cache: true
cache-dependency-path: go.sum # See the test job.

# Allocations and allocation counts do not depend on the runner's load,
# which is why they gate on every PR and wall time never does (RES-36).
# The best of three runs is compared against test/perf/budgets.json at
# ten percent over.
# shell: bash runs with -o pipefail; without it the step's status is
# benchgate's alone, and a go test that failed to build or crashed
# midway would pass on whatever partial output reached the gate.
- name: Benchmark allocations against the budgets
shell: bash
run: |
set -o pipefail
go test -run '^$' -bench . -benchtime 20x -count 3 ./... | tee bench.txt | go run ./scripts/benchgate

# Peak RSS of the release binary per entry and per RES-28 case, the
# median of nine runs, and the init budget from the runtime's own trace
# (RES-2). Linux figures are gated against the reference rows until the
# platform's own baseline is recorded in budgets.json. `go test` passes
# a run in which every gate skipped; RASHOMON_PERF_REQUIRE_ALL fails it
# unless every entry row, every case gating in this tree and the init
# budget were compared.
- name: Peak RSS and init budget
env:
RASHOMON_PERF_REQUIRE_ALL: "1"
run: go test -tags perf ./test/perf -run 'TestRES2_|TestRES28' -count=1 -v

perf-macos:
name: Perf gates (macos)
runs-on: macos-latest
# The macOS runner is a 3-core M1 with 7 GB, not the M3 reference; its
# tolerance is 15% until 2026-11-06 while its variance is learned, then
# 10% (test/perf/budgets.json, platforms.darwin/arm64).
timeout-minutes: 25
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: "1.27.2" # Measured under it; see the perf-linux job.
cache: true
cache-dependency-path: go.sum # See the test job.

- name: Peak RSS and init budget
env:
RASHOMON_PERF_REQUIRE_ALL: "1" # See the perf-linux job.
run: go test -tags perf ./test/perf -run 'TestRES2_|TestRES28|TestRES30_' -count=1 -v

# internal/store and test/acceptance's race suite runs on ubuntu-latest
# (the test job) but not here, so the darwin branch of REC-34's group
# commit -- sync_darwin.go, and the acceptance tests that exercise a
# real barrier and a real flush -- had no CI coverage at all: nothing
# ever ran them anywhere automated. This is a plain test, not the
# mutation sweep, which stays on ubuntu-latest in its own job.
- name: REC-34 group commit (darwin)
run: go test -race -count=1 -run 'TestREC34' ./internal/store ./test/acceptance
8 changes: 4 additions & 4 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ jobs:
- name: Vet
run: go vet ./...

# The module gained a dependency graph when it started reading the
# proxy's SQLite store. Publishing a binary with a known-vulnerable
# module in it is the failure this catches, and a release is the last
# moment it is cheap to catch.
# go.mod names no module, so this checks the standard library and the
# toolchain itself rather than a dependency graph. Publishing a binary
# built with a known-vulnerable stdlib version is the failure this
# catches, and a release is the last moment it is cheap to catch.
- name: govulncheck
run: go run golang.org/x/vuln/cmd/govulncheck@v1.1.4 ./...

Expand Down
17 changes: 7 additions & 10 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Contributing

This program records what a Claude Code session declared, what ran, and what
the wire saw, and says in fixed vocabulary what it does not know. Two
properties carry everything else, and a change that weakens either is a change
that should not land, however much else it improves.
This program records what a Claude Code session declared and what ran, and
says in fixed vocabulary what it does not know. Two properties carry
everything else, and a change that weakens either is a change that should not
land, however much else it improves.

**It never records content.** No prompt, response, file content, tool output or
argument value reaches a record or a file in the store. The exceptions are the
Expand All @@ -25,9 +25,9 @@ never as a negative finding.
go build ./cmd/rashomon
go test ./...

Go 1.25 or later (`go.mod` says 1.25.0). The one non-standard dependency is a
pure-Go SQLite driver, linked for a proxy-store reader the alpha leaves dormant
(#28).
Go 1.25 or later (`go.mod` says 1.25.0). There are no dependencies outside the
standard library, and a test fails the build if one brings a networking package
in.

Run the tool against a scratch store rather than your own while you work:

Expand Down Expand Up @@ -94,7 +94,6 @@ is noise.
| `internal/store` | the append-only record store and its locking |
| `internal/settings` | reading and editing Claude Code settings files |
| `internal/report` | reconciling the three records and rendering them |
| `internal/wire` | reading the proxy's store |
| `internal/install` | the hook entries, and what counts as one of ours |

`internal/shape` deserves a note. It is the single file anyone has to audit to
Expand All @@ -116,8 +115,6 @@ Stated so nobody rediscovers them as bugs:
- **Two H-17 halves are Linux-only.** They gate on `unshare` and `strace`, so
they skip on macOS. CI installs both on the Linux runner and treats a skip as
a failure, which is where that coverage actually happens.
- **`TestRead_AgainstARealProxyStore` is opt-in** behind `RASHOMON_REAL_STORE`
and has never run against a store the proxy itself wrote.

## Reporting a security issue

Expand Down
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,10 @@ transcript; that quote is never stored.

**Does it send anything anywhere?**
It has no account, no telemetry and no network code of its own, and what it
records is kept in a folder on your machine. No rashomon package imports a
networking package, and CI checks that on every pull request, every push to
main and every release tag. On Linux, CI also runs the
records is kept in a folder on your machine. No package in the rashomon
binary, its own or a dependency's, imports crypto/tls, net, net/http,
net/http/httptrace or os/exec, and CI checks that on every pull request, every
push to main and every release tag. On Linux, CI also runs the
declaration hook with the network switched off; the other hooks, the report and
the end-of-turn line have no such runtime test yet.

Expand All @@ -147,9 +148,10 @@ from changing its records. It is a second, independent account of what happened,
to set beside the agent's own.

**Can I see network activity?**
rashomon itself observes no network traffic in this alpha: the report says
`destinations: not observed in this alpha`, and `--chain` lists only the hosts
each command *named*. If you run Claude Code inside the
rashomon itself observes no network traffic: the report lists the hosts each
command *named* (`hosts named by tool calls`), and `--chain` shows them beside
the call that named them; nothing in it observed whether a host was reached.
If you run Claude Code inside the
[nono](https://github.com/nolabs-ai/nono) sandbox,
`rashomon report --nono-audit <path to nono's audit-events.ndjson>` adds what
nono allowed and refused in that session's window. If the session has no end
Expand All @@ -162,8 +164,8 @@ Plugin: open `/plugin` in Claude Code and turn it off. Command line:
until you delete that folder.

**Is it finished?**
No. This is an alpha: Windows is not supported yet, and network destinations are
not observed in this release.
No. This is an alpha: Windows is not supported yet, and rashomon observes no
network traffic; the report lists the hosts commands named.

## Inside a sandbox

Expand Down Expand Up @@ -211,8 +213,7 @@ What was measured, on macOS with nono 0.79.0 and Claude Code 2.1.285:
- `rashomon forget --host` also keeps the host out of the sandbox section, even
when rashomon's own records never named it.

Not yet measured: Linux (Landlock), and the comparison with the Altrace proxy's
records.
Not yet measured: Linux (Landlock).

## Commands

Expand Down
Loading
Loading