Where this starter repo deviates from plan.md
plan.md is the design doc. This is what actually got built for the MVP,
and where the two disagree.
-
Config is JSON, not TOML.
plan.md§6/§11 sketches aconfig.toml. The code uses~/.config/jevrail/config.jsoninstead, so the MVP has zero external dependencies:go.modhas norequirelines at all. Swap ingithub.com/pelletier/go-toml/v2later; onlyinternal/config/config.goneeds to change. -
No
mvdan.cc/shdependency.plan.md§11 names it as the shell parser.internal/shellparseis a small hand-rolled tokenizer instead: good enough to split on; && || |, honor quotes, strip comments, pull out$(...)/backtick substitutions, and recurse intobash -c/sh -cpayloads: but it is not a full POSIX parser. Exotic shell syntax (process substitution, complex heredocs, brace expansion) falls through toUnparsed: true, whichtier0.IsFastAllowand the policy's fail-safe handling both treat as non-trivial rather than silently ignoring. -
jevrail evalis now implemented (internal/eval,cmd/jevrail/eval.go).jevrail eval <corpus.jsonl> [--adversarial] [--no-model]prints recall on catastrophic, false-ask rate on safe, tier0-only baseline, latency, and per-entry triggers.testdata/corpus/corpus.jsonlnow has 80 entries covering safe/risky/catastrophic, obfuscation (bash -c,$(…),python -c) and adversarial persuasive comments;sample.jsonl(8 lines) is kept as a minimal example. Thresholds ininternal/policy/policy.goare still starting guesses: tune them against a larger labeled corpus before trusting them. -
jevrail daemon(Phase 2) does not exist. Everyjevrail hookinvocation pays a fresh process start and, when the model is consulted, a fresh TLS handshake. Fine for an MVP; worth fixing before this is on the hot path of every command. -
Codex adapter is a schema guess.
internal/adapter/codex.gois explicitly marked unverified andjevrail install --agent codexrefuses to run until someone confirms the real hook payload shape against Codex's docs and fills it in. -
No Write/Edit tool coverage. Only
Bash-shaped tool calls are evaluated (cmd/jevrail/main.go'sisShellTool). Overwriting an uncommitted file via aWrite/Edittool call is out of scope for v1, as plan.md §7 notes. -
Corpus is now 80 entries in
testdata/corpus/corpus.jsonlplus adversarial expansion (--adversarialadds ~216 variants). Still short of the 300+ target in plan.md §9, but enough for local smoke metrics.sample.jsonlremains as the 8-line shape example. -
Ctxinfo now enriches targets with
tracked_by_git,dirty,entry_count,truncated, and redacts secrets (internal/ctxinfo/redact.go) before sending state to the model. Earlier the targets were stubs.collectScriptBodiesalso now capturespython -c/node -einline bodies within the 8 KB budget. -
jevrail execshim exists (cmd/jevrail/exec.go) as the hookless-agent fallback from plan.md §7/§8.jevrail exec -- <cmd>evaluates then optionally executes with a y/N prompt onaskand a hard block ondeny. -
Doctor now checks model pinning (
jev-latestwarning), timeout range, API reachability (HEADbase_url), hook install, and a tier0 smoke table, not just key presence. -
Config
no_modelmerge fixed to distinguish absent vs. explicitfalsevia*boolraw struct, andTYPESAFE_API_KEYalways wins over file. Earliermergeunconditionally overwroteNoModel.