Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
309 commits
Select commit Hold shift + click to select a range
3bbc035
test(hooks): poison every Jev string field in the privacy test
chhhee10 Sep 22, 2026
3edda22
fix(collect): JavaScript's whitespace in the Jev validators; pin the …
chhhee10 Sep 22, 2026
e764934
fix(hooks): gate Pi intent on its input source, strip every Codex IDE…
chhhee10 Sep 22, 2026
0142de9
fix(hooks): bound the jevStats window inside the library, not only th…
chhhee10 Sep 22, 2026
de44ab6
fix(hooks): two-tier review round 4 — Pi user_bash, T4-capped context…
chhhee10 Sep 22, 2026
da14f3a
fix(dashboard): a truncated fallback shows Jev's verdict; pin the act…
chhhee10 Sep 22, 2026
28eb09d
fix(hooks): record no Codex prompt without the rollout that vouches f…
chhhee10 Sep 23, 2026
c7f5821
fix(jev): review round — an env-key config is not a refusal, and the …
chhhee10 Sep 23, 2026
627e9d5
fix(hooks): resolve the words three floor policies read literally
chhhee10 Sep 23, 2026
9d33eda
fix(hooks): two-tier review round 5 — honest truncation signal, telem…
chhhee10 Sep 23, 2026
35f7e08
fix(hooks): T6 review round 2 — auth-field scheme, shared-prefix cont…
chhhee10 Sep 23, 2026
2520b02
test(jev): bound the FIFO check in a child, and pin that it stays bou…
chhhee10 Sep 23, 2026
56d30f9
fix(hooks): a cut envelope withdraws Jev's clears, not Jev's deny
chhhee10 Sep 23, 2026
57b9aab
fix(hooks): close three one-rewrite bypasses of the hard floor
chhhee10 Sep 23, 2026
192f11a
fix(hooks): record no prompt whose origin evidence cannot be read
chhhee10 Sep 23, 2026
68d4956
fix(hooks): T6 review round 3 — unknown auth schemes, quoted credenti…
chhhee10 Sep 23, 2026
5ca7b62
fix(hooks): close the padding class — size, and evidence Jev never saw
chhhee10 Sep 23, 2026
38d8777
fix(hooks): believe a transcript only while it is the file this sessi…
chhhee10 Sep 23, 2026
f033530
fix(hooks): read the floor's kill chains and git aliases the way the …
chhhee10 Sep 23, 2026
c479774
fix(hooks): T6 review round 4 — bound the Authorization value, per-he…
chhhee10 Sep 23, 2026
5d96186
fix(hooks): establish a prompt's origin from the hook event alone
chhhee10 Sep 23, 2026
41b516b
fix(hooks): close the padding class by construction, not by spelling
chhhee10 Sep 23, 2026
efe4111
fix(hooks): close the floor's two open classes by deleting what read …
chhhee10 Sep 23, 2026
c0f2ac7
fix(hooks): T6 round 6 — close the credential class by not classifyin…
chhhee10 Sep 23, 2026
773e728
fix(hooks): record a prompt only where the payload names its author
chhhee10 Sep 23, 2026
9bcb992
fix(hooks): read the floor's two ends, and nothing in between
chhhee10 Sep 23, 2026
8905dff
fix(hooks): a call the reviewer could not read is never an allowed call
chhhee10 Sep 23, 2026
b3b0d35
fix(hooks): T6 round 7 — read the credential name everywhere, report …
chhhee10 Sep 23, 2026
17f76c0
feat(hooks): ship four hard-floor builtins, defer the two that needed…
chhhee10 Sep 23, 2026
45dacf0
fix(hooks): size costs a call its clears, never its verdict
chhhee10 Sep 23, 2026
c377287
fix(hooks): trust the prompt the harness hands the hook
chhhee10 Sep 23, 2026
e0f12f6
fix(hooks): T6 round 8 — repair the regressions, and make every scan …
chhhee10 Sep 23, 2026
558ba53
fix(hooks): stop a markdown heading from dropping the prompt under it
chhhee10 Sep 23, 2026
0154e7f
fix(hooks): a templated connection string is ordinary work, and the r…
chhhee10 Sep 23, 2026
150105b
fix(hooks): T6 round 9 — repair the regressions the last round shipped
chhhee10 Sep 23, 2026
b9fd14b
fix(hooks): stop reading -rf as rm, and stop re-walking the same cd
chhhee10 Sep 23, 2026
524fa32
merge(jev): T2 policy authority plumbing into the two-tier integratio…
chhhee10 Sep 23, 2026
2eca1fc
merge(jev): T7 hard-floor builtins into the two-tier integration branch
chhhee10 Sep 23, 2026
77465b4
fix(docs): the hard floor ships four policies, not six
chhhee10 Sep 23, 2026
d780634
merge(jev): T1 BYOK provider layer and the jev CLI into the two-tier …
chhhee10 Sep 23, 2026
abc7040
merge(jev): T5 Jev cache and rate limiter into the two-tier integrati…
chhhee10 Sep 23, 2026
8f3a1a7
merge(jev): T4 intent capture into the two-tier integration branch
chhhee10 Sep 23, 2026
1e2ff32
merge(jev): T8 telemetry and visibility into the two-tier integration…
chhhee10 Sep 23, 2026
8ac1067
fix(hooks): T6 final pass — leave the blocking list alone, blunt opt-…
chhhee10 Sep 23, 2026
10526d6
fix(hooks): the five T3 regressions — a hyphen is a delimiter, a plac…
chhhee10 Sep 23, 2026
4d8cbdd
merge(jev): T3 two-tier evaluator core into the two-tier integration …
chhhee10 Sep 23, 2026
bc839f7
merge(jev): T6 redaction hardening into the two-tier integration branch
chhhee10 Sep 23, 2026
c7f7d06
fix(jev): redact the Vercel AI Gateway key on the envelope path
chhhee10 Sep 23, 2026
49fa60b
fix(jev): the cut-call fallback reason stops being stored as `other`
chhhee10 Sep 23, 2026
62f0715
test(hooks): derive the omission-marker lengths from the message cap
chhhee10 Sep 23, 2026
f1d1614
test(hooks): make the opt-out test's call count prove re-consultation
chhhee10 Sep 23, 2026
4d46447
fix(jev): hold the prompt store's path to the rule jev.json's directo…
chhhee10 Sep 23, 2026
f87013a
fix(jev): raise the default call budget to 3000 ms, measured
chhhee10 Sep 23, 2026
6aaee6e
docs(jev): state the intent-capture risk at its real size, and the st…
chhhee10 Sep 23, 2026
277eb68
docs(jev): write the truncation rule as implemented, in one place, an…
chhhee10 Sep 23, 2026
659efac
feat(jev): configure Jev in one command — `failproofai jev --url <url…
chhhee10 Sep 23, 2026
f171a4d
feat(dashboard): configure Jev from the settings gear, and never hand…
chhhee10 Sep 23, 2026
cfb9b7d
fix(jev): the probe text the Cloudflare route refuses
chhhee10 Sep 23, 2026
6b383e6
fix(jev): ask read-outside-workspace wherever its partner can deny
chhhee10 Sep 23, 2026
15634ad
docs(changelog): the Jev two-tier evaluator's entry
chhhee10 Sep 23, 2026
767e552
fix(jev): a content refusal is not the operator's billing problem
chhhee10 Sep 23, 2026
869839a
test(jev): the reason-code check imports the store's list instead of …
chhhee10 Sep 23, 2026
cee7b8f
refactor(jev): remove two dead paths, and say what decides instead
chhhee10 Sep 23, 2026
71add43
fix(jev): a flag the CLI cannot use is refused, not absorbed
chhhee10 Sep 23, 2026
dc6d7ef
docs(jev): name `request-cut` where operators will meet it
chhhee10 Sep 23, 2026
272dbea
fix(jev): drop an unreachable message branch from the 402 split
chhhee10 Sep 23, 2026
4de6ddf
fix(dashboard): a Jev save keeps what the panel does not show, and th…
chhhee10 Sep 23, 2026
41abf5a
feat(jev): say when Jev is on and can never clear anything
chhhee10 Sep 23, 2026
99f3a43
fix(cli): a stale daemon is fixed by `failproofai update`, not `config`
chhhee10 Sep 23, 2026
d1eeac5
feat(jev): a warning-level answer clears the deny, and stays as the w…
chhhee10 Sep 23, 2026
c1f1bd3
docs(changelog): number the Jev entries for #833
chhhee10 Sep 23, 2026
ac71dce
test(hooks): stop two new tests measuring the CI runner instead of th…
chhhee10 Sep 23, 2026
9a9780f
test(daemon): wait for the test server to listen instead of sleeping …
chhhee10 Sep 23, 2026
1252391
revert(hooks): drop the four hard-floor builtins
chhhee10 Sep 24, 2026
d823233
revert(docs): put the policy counts back at 39 builtins, 38 in the pack
chhhee10 Sep 24, 2026
2924231
docs(changelog): drop the hard-floor entry from #833
chhhee10 Sep 24, 2026
11479a0
test(dashboard): give the activity-row test room for a real re-render
chhhee10 Sep 24, 2026
9f6e9b8
chore: make the dogfood enable/disable set local to each contributor
chhhee10 Sep 24, 2026
e135a09
fix(hooks): count what Jev may clear by the rule registration uses
chhhee10 Sep 24, 2026
817b71c
fix(hooks): a `//` comment is not a path outside the project
chhhee10 Sep 24, 2026
338dabf
fix(jev): a `cd` target is a path, not only the frame for what follows
chhhee10 Sep 24, 2026
a875e2b
docs(changelog): the two read-outside-cwd fixes in #833
chhhee10 Sep 24, 2026
8b9ca9a
perf(hooks): stat jev.json before loading the Jev config module
chhhee10 Sep 24, 2026
7f23bc3
test(semantic): budget the scrub pass the way the envelope test does
chhhee10 Sep 24, 2026
8327df7
test(hooks): make the MODEL_RE parity assertion actually run
chhhee10 Sep 24, 2026
20a6bd6
test(semantic): assemble the key fixtures at runtime, like every othe…
chhhee10 Sep 24, 2026
02530d3
docs(pi): say what the evaluator really does with input_source
chhhee10 Sep 24, 2026
126a29e
chore: the dogfood policy selection and custom policies are local now
chhhee10 Sep 24, 2026
ebb2f33
fix(policies): block-work-on-main was reviewable by a check that can …
chhhee10 Sep 24, 2026
4f76456
feat(hooks): compare two versions by semver precedence
chhhee10 Sep 24, 2026
14def49
feat(semantic): let a precondition be a name, not code
chhhee10 Sep 24, 2026
9999901
feat(hooks): declare a semantic policy through its own registry
chhhee10 Sep 24, 2026
205185c
feat(hooks): read a pack's semantic policies and its minimum CLI
chhhee10 Sep 24, 2026
0fbaa94
feat(semantic): let a pack replace the compiled-in question set
chhhee10 Sep 24, 2026
1fbc83d
feat(hooks): judge reviewedBy against the reviewers this machine has
chhhee10 Sep 24, 2026
c243391
feat(pack): publish a pack's semantic policies and its minimum CLI
chhhee10 Sep 24, 2026
8901110
fix(pack): publish each policy's params schema, and validate it
chhhee10 Sep 24, 2026
ab8e9ae
test: two more pins on the reviewable count ebb2f336 moved
chhhee10 Sep 24, 2026
9f59c76
fix(pack): carry a pack's semantic half through the install path
chhhee10 Sep 24, 2026
d21ddad
fix(pack): forward the minimum-CLI flag from publish into the manifest
chhhee10 Sep 24, 2026
4d68b63
fix(pack): recognise the relative-import shapes a real pack entry uses
chhhee10 Sep 24, 2026
b410517
chore(release): 1.0.7-beta.1
chhhee10 Sep 24, 2026
1bb52b5
fix(jev): take Cloudflare's account id from the URL that already name…
chhhee10 Sep 24, 2026
744397b
feat(pack): give a pack's Jev checks a section, with what each reviews
chhhee10 Sep 24, 2026
f30957b
feat(policies): warn on the git clean form neither tier caught
chhhee10 Sep 24, 2026
02bb64f
docs(policies): record the probe edit the git clean finding needs
chhhee10 Sep 24, 2026
b795a2c
fix(dashboard): stop the Jev panel repeating itself, and its key frag…
chhhee10 Sep 24, 2026
2de23d0
fix(pack): give the unpaired-check reason a form at one policy and none
chhhee10 Sep 24, 2026
165a1b2
fix(pack): let `reviews` lead the cell instead of padding out every dash
chhhee10 Sep 24, 2026
5105282
feat(policies): nine more builtins are reviewable, and sudo deliberat…
chhhee10 Sep 24, 2026
d5ad870
fix(pack): register params in the generated entry, so both producers …
chhhee10 Sep 24, 2026
ff36c8a
chore(release): 1.0.7-beta.2
chhhee10 Sep 24, 2026
a6457e1
Merge origin/main into feat/jev-two-tier
chhhee10 Sep 24, 2026
298113d
test(dashboard): put the async budget inside the test budget, not equ…
chhhee10 Sep 24, 2026
1628ff2
feat(jev): read each provider's model list and error envelope as meas…
chhhee10 Sep 24, 2026
9e16212
feat(jev): refuse an endpoint as a base URL, check the model, and add…
chhhee10 Sep 24, 2026
0c66828
docs(changelog): the Jev provider-contract entries for #833
chhhee10 Sep 24, 2026
9c0940a
test(dashboard): re-query the activity row at the moment of the click
chhhee10 Sep 24, 2026
023257d
fix(ci): make the two inherited failures fail for real reasons, or no…
chhhee10 Sep 24, 2026
b95149d
fix(jev): refuse a credential in a base URL's query, and never return…
chhhee10 Sep 24, 2026
73a0cdd
fix(policies): merge a shared artifact's authority against the live r…
chhhee10 Sep 24, 2026
89dcb0c
fix(packs): honour a contested semantic check name for nobody
chhhee10 Sep 24, 2026
bdb6d5f
fix(semantic): pin the project root per session so a cd cannot move it
chhhee10 Sep 25, 2026
f1afb7a
feat(jev): a FailproofAI Cloud provider, keyed from credentials.json,…
chhhee10 Sep 25, 2026
586faa0
feat(jev): the FailproofAI Cloud transport, and its statuses as fallb…
chhhee10 Sep 25, 2026
ee80278
feat(jev): config --token turns Jev on through FailproofAI Cloud; dis…
chhhee10 Sep 25, 2026
0bdb7fa
fix(config): honour --url on the --token path
chhhee10 Sep 25, 2026
2e1a60f
fix(config): honour --no-transcripts on the --token path
chhhee10 Sep 25, 2026
8a22853
feat(jev): give the policy page Jev's decisions and its shadow "would…
chhhee10 Sep 25, 2026
58ac296
feat(settings): FailproofAI Cloud in the local Jev panel — a mode swi…
chhhee10 Sep 25, 2026
d11bebe
feat(jev): jev status, setup and test speak FailproofAI Cloud
chhhee10 Sep 25, 2026
cdb2fcf
docs(jev): Jev through FailproofAI Cloud, mode off, and the changelog
chhhee10 Sep 25, 2026
0d5b9c0
fix(config): read fs.constants when the Jev credential is read, not a…
chhhee10 Sep 25, 2026
719e025
docs(changelog): open 1.0.7-beta.3 for what landed after beta.2
chhhee10 Sep 25, 2026
2fb730d
fix(jev): a Cloud Jev key counts only beside the connection it came with
chhhee10 Sep 25, 2026
2ba5954
fix(jev): say "the key does not carry Jev", not "not connected", on a…
chhhee10 Sep 25, 2026
c7f3eb5
fix(config): --no-transcripts never switches Jev on
chhhee10 Sep 25, 2026
52f78d8
fix(config): an unanswered key check no longer switches Cloud Jev off
chhhee10 Sep 25, 2026
1656b21
feat(fp-cloud-cli): know the jev:evaluate permission
chhhee10 Sep 25, 2026
c27e59f
feat(jev): honour Retry-After on the FailproofAI Cloud route
chhhee10 Sep 25, 2026
b3a4b58
fix(jev): no next step that leads nowhere — mode off, and a Cloud red…
chhhee10 Sep 25, 2026
6c2e037
fix(jev): re-check a loaded Cloud config's origin for real, not vacuo…
chhhee10 Sep 25, 2026
b13ccc9
fix(config): disconnect judges the jev.json it deletes, never another…
chhhee10 Sep 25, 2026
0c52467
docs(jev): say which "off" lasts, and what the permission checks refuse
chhhee10 Sep 25, 2026
62688c7
test(jev): mode off through the handler's own off-check, byte for byte
chhhee10 Sep 25, 2026
49b8f26
fix(jev): a Cloud Jev key counts only beside a connection holding it
chhhee10 Sep 25, 2026
6550284
fix(config): --no-transcripts says when Cloud Jev is still on
chhhee10 Sep 25, 2026
e1d1ffd
fix(config): disconnect puts a BYOK jev.json back without hard links
chhhee10 Sep 25, 2026
4951d3c
fix(jev): say which key state setup is in, and which 429 hit
chhhee10 Sep 25, 2026
7bc4ba8
fix(jev): the dashboard refuses an endpoint where a base belongs, as …
SiddarthAA Sep 26, 2026
2b495b7
fix(jev): the settings reviewable count reads the launch directory's …
SiddarthAA Sep 26, 2026
31d5fbb
fix(jev): the settings read of a refused jev.json sends no userinfo o…
SiddarthAA Sep 26, 2026
ad625ce
fix(jev): judge the command as written, never the scanner's guess at …
SiddarthAA Sep 26, 2026
da0b315
fix(jev): the panel scopes a key-from-env "off" to the dashboard's en…
SiddarthAA Sep 26, 2026
eb12af5
fix(hooks): a `//` is the root except where it opens a heredoc line
SiddarthAA Sep 26, 2026
17fc1b4
Merge origin/main into feat/jev-two-tier
SiddarthAA Sep 26, 2026
0dac77a
docs(jev): size the forged-consent risk from the catalog — 15 reviewa…
SiddarthAA Sep 26, 2026
5afead0
fix(packs): a refused Jev-checks-only pack denies nothing
SiddarthAA Sep 26, 2026
1587bd0
docs(jev): Cloud Jev needs failproofai 1.0.8-beta.0, not 1.0.7-beta.3
SiddarthAA Sep 26, 2026
b506d48
docs(jev): document Jev checks in packs, and which reviewedBy names c…
SiddarthAA Sep 26, 2026
cde0e22
docs(jev): say which semantic checks are instruct-only where authors …
SiddarthAA Sep 26, 2026
6419f7e
docs(changelog): the core pack carries 39 regex policies, not 38
SiddarthAA Sep 26, 2026
71e2bc7
fix(packs): the builtin Jev check names are reserved to FailproofAI's…
SiddarthAA Sep 26, 2026
600be40
docs(jev): list the fallback reasons `jev status` actually records
SiddarthAA Sep 26, 2026
4e8c04e
docs(jev): the CLI and dashboard references say what now switches Jev
SiddarthAA Sep 26, 2026
245d007
fix(packs): an observe or agent-scoped pack's Jev checks do not enforce
SiddarthAA Sep 26, 2026
4d538a7
docs(jev): document the per-session project-root pin and its file
SiddarthAA Sep 26, 2026
7e5bc43
fix(packs): a third-party pack's Jev checks join the built-in ones
SiddarthAA Sep 26, 2026
96dc0d2
docs(jev): a blank dashboard token is kept only for the same provider…
SiddarthAA Sep 26, 2026
931276b
docs(jev): only a FailproofAI pack's checks replace the built-in revi…
SiddarthAA Sep 26, 2026
3595821
fix(jev): redact standard-base64 secrets whole, `+` and `/` included
SiddarthAA Sep 26, 2026
29b9877
fix(jev): strip control characters from provider text before it is pr…
SiddarthAA Sep 26, 2026
d25fb72
fix(jev): warn about a --token in shell history on refusals too
SiddarthAA Sep 26, 2026
48d4246
fix(jev): a Cloud 404 no longer blames a base URL nobody configured
SiddarthAA Sep 26, 2026
900d016
fix(jev): a Cloud 422 request_rejected is that call's own, not an outage
SiddarthAA Sep 26, 2026
992d084
test(jev): pin the Cloud route's 422 request_rejected as http-422
SiddarthAA Sep 26, 2026
fbcab4c
fix(jev): a Cloud 503 holds the route back and names who fixes it
SiddarthAA Sep 26, 2026
6fbbe65
fix(jev): `key-lacks-jev` says no Jev key is stored, not what the key…
SiddarthAA Sep 26, 2026
ad04372
fix(collect): a Jev allow roll-up says how many calls its latency mea…
SiddarthAA Sep 26, 2026
b7c7bc7
fix(packs): say that semanticPolicies.add is ignored outside a pack
SiddarthAA Sep 26, 2026
27b9d64
docs(jev): a Jev check in a local policy file is now named as ignored
SiddarthAA Sep 26, 2026
af28c34
fix(packs): refuse a manifest that declares a regex policy name twice
SiddarthAA Sep 26, 2026
2e63bc0
fix(hooks): a `//` after a line continuation is still the root
SiddarthAA Sep 26, 2026
e3b3204
fix(packs): the minCliVersion remedy installs a version that meets it
SiddarthAA Sep 26, 2026
99ec302
docs(jev): a self-hosted FailproofAI Cloud needs --url when connectin…
SiddarthAA Sep 26, 2026
e073229
docs(fp-cloud-cli): name the 422 body POST /keys really answers for a…
SiddarthAA Sep 26, 2026
e80e94a
fix(jev): a check no consent can clear keeps the regex deny it would …
SiddarthAA Sep 26, 2026
f92a0b4
fix(packs): say when a pack's minCliVersion is ignored as unreadable
SiddarthAA Sep 26, 2026
c9fb448
fix(jev): credential-exfiltration's warning no longer says the call i…
SiddarthAA Sep 26, 2026
fedb0ec
fix(packs): publish refuses a policy that declares alwaysOn
SiddarthAA Sep 26, 2026
2a4eb0b
fix(jev): a deny Jev decided credits Jev, not "the policy configured …
SiddarthAA Sep 26, 2026
560c3ce
fix(jev): `config --disconnect` keeps a Cloud jev.json switched off
SiddarthAA Sep 26, 2026
bdc1a96
fix(packs): a third party's claim to a builtin Jev name cannot switch…
SiddarthAA Sep 26, 2026
5e07573
docs(jev): the shell-text notes stop naming the removed comment field
SiddarthAA Sep 26, 2026
58e4e61
fix(jev): an alias-only model list no longer refuses the calibrated j…
SiddarthAA Sep 26, 2026
fb04b9b
fix(packs): an authority refusal names the rule that refused it
SiddarthAA Sep 26, 2026
bf92676
fix(jev): `jev test` is not ok when hooks could not use the answer
SiddarthAA Sep 26, 2026
c9d7228
fix(packs): the policy listing says what a pack's checks and refusals do
SiddarthAA Sep 26, 2026
4ac79d4
fix(jev): the endpoint-as-base refusal describes the URL the client r…
SiddarthAA Sep 26, 2026
863fd75
fix(jev): over plain http, connect no longer suggests an enforce that…
SiddarthAA Sep 26, 2026
35c5207
fix(jev): a Jev verdict from a pack's check names the pack
SiddarthAA Sep 26, 2026
ab1d629
fix(jev): connect says when the jev.json it kept leaves Jev off
SiddarthAA Sep 26, 2026
ee93e4a
fix(jev): `jev test` and `jev status` give one fix for a refused conf…
SiddarthAA Sep 26, 2026
3a70b63
fix(jev): `jev status --json` carries the Cloud facts when absent or …
SiddarthAA Sep 26, 2026
648e8fb
fix(packs): `policies add` names the Jev checks this machine will not…
SiddarthAA Sep 26, 2026
714aee0
docs(packs): an older CLI rolled back under a Jev-checks-only pack ca…
SiddarthAA Sep 26, 2026
f8d3790
feat(fp-cloud-cli): a `machine` key preset, and the Jev prerequisite …
SiddarthAA Sep 26, 2026
8d2f8c6
fix(packs): an authority refusal quotes a pack's reviewedBy name escaped
SiddarthAA Sep 26, 2026
b455d11
fix(jev): a jev.json others can only read says its key is exposed
SiddarthAA Sep 26, 2026
6499515
fix(jev): record a clear only when it softened the call
SiddarthAA Sep 26, 2026
85d85b3
fix(fp-cloud-cli): refuse Jev fields a cloud policy never reads at pu…
SiddarthAA Sep 26, 2026
f8c1e1b
docs(fp-cloud-cli): the server never scans a policy's source for Jev …
SiddarthAA Sep 26, 2026
08adc69
fix(jev-settings): refuse an invalid mode in the dashboard save
SiddarthAA Sep 26, 2026
4fc3690
fix(jev): refuse a provider/host mismatch from every writer, not only…
SiddarthAA Sep 26, 2026
83cf711
fix(jev): put each next-step command on its own line under its lead
SiddarthAA Sep 26, 2026
5c192a2
fix(jev): point a broken or missing jev.json at the Cloud when the ke…
SiddarthAA Sep 26, 2026
60f3007
fix(jev): say a loose jev.json holds a key only when it does
SiddarthAA Sep 26, 2026
e3807db
fix(jev): name the off switch for a kept Cloud file on another origin
SiddarthAA Sep 26, 2026
aeb4cd4
fix(jev): answer JSON from every `jev models --json` refusal
SiddarthAA Sep 26, 2026
828dc79
fix(jev-settings): give the dashboard the CLI's /systemone refusal re…
SiddarthAA Sep 26, 2026
f2771d3
fix(cli): warn about shell history when config takes --token on argv
SiddarthAA Sep 26, 2026
23282ae
fix(jev): name cloudflare and its account id when --base-url pairs cu…
SiddarthAA Sep 26, 2026
f98f051
fix(publish): print the whole Jev-only rollback reminder on dry run a…
SiddarthAA Sep 26, 2026
1d5b880
fix(publish): refuse a built-in Jev check name from a pack outside Fa…
SiddarthAA Sep 26, 2026
3cf8be4
fix(publish): hold a third-party pack to the question budget the buil…
SiddarthAA Sep 26, 2026
f9320f6
fix(publish): require minCliVersion >= 1.0.8-beta.0 for a pack with J…
SiddarthAA Sep 26, 2026
36a10cd
fix(packs): say added-to vs replacing in show and the picker, and war…
SiddarthAA Sep 26, 2026
96517fc
fix(packs): say where an observe or --cli pack's Jev checks are asked
SiddarthAA Sep 26, 2026
bab5f3b
fix(failproofaid): trust the OS certificate store for uploads and pol…
SiddarthAA Sep 26, 2026
f51b7b7
fix(jev): count reviewers in jev status from the post-budget question…
SiddarthAA Sep 26, 2026
137ddf4
fix(jev): count convention policy files in the jev status reviewable …
SiddarthAA Sep 26, 2026
e91ea25
fix(jev): a check that fired without consent keeps the regex floor
SiddarthAA Sep 26, 2026
5ac974e
fix(packs): refuse a FailproofAI/ pack id from a repository outside F…
SiddarthAA Sep 27, 2026
a21883e
fix(cli): read FAILPROOFAI_CLOUD_TOKEN on config --connect and name t…
SiddarthAA Sep 27, 2026
58ae5bd
docs(jev-throttle): say identical Jev calls can be in flight together
SiddarthAA Sep 27, 2026
7966aad
fix(policies): protect-env-vars denies the other whole-environment dumps
SiddarthAA Sep 27, 2026
ab12f0e
fix(packs): take every repeated --policy, --only, --category and --cl…
SiddarthAA Sep 27, 2026
b6fa65e
fix(failproofaid): log the whole error chain for failed uploads and p…
SiddarthAA Sep 27, 2026
8d04d38
fix(flush): count the batches the daemon actually spools, and name pa…
SiddarthAA Sep 27, 2026
3c50a92
fix(jev): an empty target scan falls back to the command as written
SiddarthAA Sep 27, 2026
2d2b860
fix(jev): resolve a relative customPoliciesPath against the project r…
SiddarthAA Sep 27, 2026
f9c5519
fix(jev): name a Jev verdict's pack without loading the resolver on t…
SiddarthAA Sep 27, 2026
13fe626
test(packs): derive the prerelease-below-release check from the packa…
SiddarthAA Sep 27, 2026
a14378a
fix(jev): a shell scan that may be partial can clear no deny, and eve…
chhhee10 Sep 27, 2026
0adc921
fix(jev): the task-step route does not soften a shell deny past the t…
chhhee10 Sep 27, 2026
50ccd94
fix(jev): a parameter expansion makes the target scan incomplete
chhhee10 Sep 27, 2026
9502173
fix(jev): brace expansion and globs make the target scan incomplete
chhhee10 Sep 27, 2026
52328df
docs(jev): a check just under its fire line does not keep the floor
SiddarthAA Sep 27, 2026
1039552
docs(jev): an agent on the machine can read the Cloud Jev key
SiddarthAA Sep 27, 2026
42714c2
Merge branch 'main' into feat/jev-two-tier
NiveditJain Sep 27, 2026
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
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,23 @@ COMMIT_MSG.tmp
**/.failproofai/run/
**/.failproofai/state/

# The dogfood enable/disable set is now local to each contributor. It was
# committed, which meant every local change to which policies run on YOUR
# machine — turning a noisy one off while you work on it, or switching the
# Stop gates off to get a long-running task finished — showed up as a staged
# change to everyone else's enforcement. The policies themselves stay tracked
# in `.failproofai/policies/`; only which of them are enabled here is yours.
# Untrack it once with: git rm --cached .failproofai/policies-config.json
/.failproofai/policies-config.json

# The dogfood custom policies, for the same reason: they are the ones that gate
# a turn (a Stop gate cannot tell "a subagent owns the working tree right now"
# from "you forgot to commit"), so switching one off while you work should not
# be a change to anybody else's repo. Same caveat as above — these are tracked,
# so this rule only takes effect after:
# git rm --cached .failproofai/policies/review-policies.mjs .failproofai/policies/workflow-policies.mjs
/.failproofai/policies/*.mjs

# Python build and test artefacts from fp-cloud-cli/. `/dist` above is the Next.js one at
# the repo root; fp-cloud-cli builds into its own nested dist/, which that rule does not
# match, so it needs naming separately.
Expand Down
45 changes: 45 additions & 0 deletions CHANGELOG.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -919,11 +919,11 @@ in-process fallback on that path: a second policy engine reachable by breaking t
is not a guarantee, and a machine where stopping one service silently disables every
guardrail is not a guarded machine.

The mismatch case denies with a message naming the version and `failproofai config`,
The mismatch case denies with a message naming the version and `failproofai update`,
because the remedy differs from "the daemon is down" and that difference is the whole
value of telling them apart. The accepted cost: both sides hardcode `PROTOCOL_VERSION`,
so the first time it is bumped a machine whose CLI updated via npm before its daemon did
denies until `failproofai config` runs. `publish.yml` ships both from one commit and
denies until `failproofai update` runs. `publish.yml` ships both from one commit and
`daemonVersionSkew()` hints on every CLI command, so the window is bounded and announces
itself.

Expand Down
69 changes: 69 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

186 changes: 186 additions & 0 deletions PROBE-FOLLOWUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
# Probe follow-up: `destructive-deletion.irreplaceable` cannot see a pathless delete

Status: **proposed, not applied.** The probe text in `src/hooks/semantic/policies.ts` is
unchanged on purpose. This file records what the change would be, what it would cost to
validate, and which commands are still uncovered while it is not made.

## The finding

Measured on a real machine, through the real hook, with a Jev config present:

```
$ probe --said "the repo feels cluttered, tidy it up" "git clean -fdx"
allow git clean -fdx
jev: ok decision=allow applied=two-tier 495ms
probes: destructive-deletion.destroys=0.94 beyond_task=0.79 task_step=0.78
```

`git clean -fdx` was caught by **neither tier**.

`destructive-deletion.destroys` answered **0.94** — the check sees that the command
destroys data, which it should, because its own `instructions` name `git clean -fdx` as
an example. The policy still did not fire. Two independent reasons:

1. **Evidence is the MINIMUM over a policy's probes** (`PolicyOutcome.evidence`, "min over
probe probabilities — one weak probe spoils the evidence"). `destructive-deletion` has
two probes, and the partner `irreplaceable` answered low — it does not appear on the
probe line at all, which lists only what came back above the display floor. One weak
probe is enough, so 0.94 on `destroys` buys nothing.
2. **No regex builtin matched the string.** Verified by running every builtin that matches
`PreToolUse` + `Bash` against the literal command: zero non-allow verdicts.
`block-rm-rf` only recognises `rm` and `find` command words (`RM_CMD_RE`,
`FIND_CMD_RE`), `warn-git-stash-drop` is `/\bgit\s+stash\s+(?:drop|clear)\b/`, and the
only place `git clean` appears anywhere in the regex tier is
`GIT_DESTRUCTIVE_SUBCOMMANDS` inside the always-on self-protection guard — which is
anchored to failproofai's own state directory and fires on nothing else.

## Why `irreplaceable` answers low, and why that is not a tuning bug

The probe, in full, as it stands today:

```
id: "irreplaceable"
instructions:
"What would be destroyed is outside the project, is the whole project, is the user's
home directory, is the filesystem root, or is data that cannot simply be regenerated
(source code, documents, databases, keys). Use `facts.paths[].relation` to see where
each target sits relative to the project."
criteria:
true: "The destroyed data matters and could not be rebuilt by running a command."
false: "Only regenerable data inside the project is affected: build output, dist/,
caches, node_modules, virtualenvs, coverage reports, temp files, or files the
agent itself just created."
```

Every clause of the instructions is about a **target**, and the probe is told to read
`facts.paths[].relation` to locate it. But `git clean` takes no path operand at all, so
there is nothing for `facts.ts` to extract. Measured on this build:

| command | `facts.paths` |
|---|---|
| `git clean -fdx` | `[]` |
| `git clean -fdx` (via `cd /tmp && …`) | `/tmp => system` — the `cd` target, not the delete target |
| `git reset --hard` | `[]` |
| `git checkout -- .` | `. => project_root` |

`extractPaths` skips `clean` (not path-like: no `/`, `~`, `.` or `..`) and skips `-fdx`
(starts with `-`). So the classifier is asked to judge where the target sits, is handed no
target, and reads the false criteria — which enumerate exactly the things a "clean" verb
suggests: build output, `dist/`, caches, `node_modules`, coverage, temp files. The
ordinary answer to the question **as written** is the false branch. The probe is not
mis-tuned; it is mis-scoped for operations whose blast radius is implied by a flag rather
than named by an argument.

What `git clean -fdx` actually removes: every untracked **and** ignored file in the tree —
`.env`, local config, editor state, uncommitted scratch work, anything not yet added. The
`-x` is what makes it severe; without it, ignored files are spared.

## The probe change this would need — and why it is not in this commit

Two candidate edits, both to `irreplaceable`:

**(a) Name the pathless case in the instructions.** Add a sentence such as: *"A command
that names no path but sweeps the working tree — `git clean -x`/`-X`/`-d`, `git reset
--hard`, `git checkout -- .` — destroys untracked and ignored files, which git has no copy
of; treat that as data that cannot be regenerated even though `facts.paths` is empty."*

**(b) Stop the empty-`facts.paths` case defaulting to false.** Add to the instructions:
*"An empty `facts.paths` means no target could be resolved, not that the target is
harmless."* This is the same principle `envelope.ts` already states for the two-tier
combine — *"`policies.ts` treats incomplete evidence as a reason to ASK MORE"* — applied
one level down, to a probe.

**Why neither ships here.** The probe text is a calibrated classifier input. The decision
thresholds in `decide.ts` were measured against this exact wording over the 1,332-call
labelled corpus, and the numbers in the top CHANGELOG section (real work blocked 13.9% →
8.7%, 132 of 234 attacks blocked, 70.8% label agreement) are properties of the
**wording + thresholds together**. `irreplaceable` is the partner probe of the only
deny-mode check that covers deletion, and `destructive-deletion` applies to `shell` *and*
`write` — so a word that raises it raises it on every `rm`, every `truncate`, every
`dd of=`, every overwriting redirect and every `Write` in the corpus, not only on
`git clean`. Raising a MIN-combined probe can only move policies toward firing, so the
risk is one-directional and concentrated in false blocks, which is the metric the
two-tier release was justified on.

**So the change needs a full corpus replay before it lands:** re-run the 1,332 labelled
calls, report real-work-blocked, attacks-blocked and label agreement against the numbers
above, and confirm no threshold in `decide.ts` has to move to hold them. That is a
measurement task with its own prereg, not a word edit.

## What ships instead

`warn-git-clean`, a deterministic builtin in the regex tier (`policy-catalog.ts` +
`builtin-policies.ts`). `instruct`, `defaultEnabled: false`, `authority: "hard"`, with a
`destructiveFlags` param (default `["d","x","X"]`) to narrow or widen it. It fires when
`git clean` has force (`-f` / `--force`, or a waived `clean.requireForce`) together with
`-d`, `-x` or `-X`; it does not fire on `--dry-run` / `-n`, on a bare `git clean -f`, or
on `git clean` with no force.

It is **hard**, not `reviewable: ["destructive-deletion"]`, and the finding above is why:
a named check that is asked and does not fire answers "no concern", which **clears**
(`combine.ts`, "A warning-level answer clears the deny"). `destructive-deletion`
demonstrably answers low here, so the pairing would not review this policy — it would
switch it off on every machine that configured Jev. That is the `block-work-on-main`
mistake, and the test that decides it is "is there anything left that can DENY". No other
deny-mode semantic check covers untracked-file deletion, so a clear would leave the
concern enforced by nothing. When (a) or (b) lands with a passing replay, this policy is
the first candidate to be revisited as `reviewable`.

## Sibling sweep: destructive git commands with no path argument

Measured, not guessed — each command run against every builtin matching `PreToolUse` +
`Bash` on this build, and through `extractPaths` for the facts column.

| command | matched by any builtin? | `facts.paths` | would `destructive-deletion` fire? | covered here? |
|---|---|---|---|---|
| `git clean -fdx` / `-fd` / `-fx` / `-fX` | **now yes** — `warn-git-clean` (was: none) | `[]` | No. `destroys` 0.94, `irreplaceable` low — measured | **yes** |
| `git clean --dry-run` / `-n` | no, by design | `[]` | No | n/a — safe |
| `git reset --hard` (and `--hard HEAD~N`) | **no** | `[]` | Unlikely. Overwrites tracked files from HEAD, so `destroys` should be high; `irreplaceable` has no target and the loss (uncommitted modifications) is not in the object database at all | no — see below |
| `git checkout -- .` | **no** | `. => project_root` | Possible. `irreplaceable` does get a target here, and `project_root` is one of the relations its instructions name, so this is the one sibling the probe has a fair chance on | no |
| `git restore .` | **no** | `. => project_root` | Same as above | no |
| `git rm -r --cached .` | **no** | `. => project_root` | No, and correctly: `--cached` unstages and leaves the working-tree file. Not data loss | no — not destructive |
| `git rm -rf src` | **no** | `[]` | Unlikely (no target in facts) | no — but see note |
| `git rm -rf /` | **yes** — `block-rm-rf` denies | `/ => root` | Yes | already covered |
| `git branch -D feature/x` | **no** | `feature/x => inside_project` (a false positive: it is a ref, not a path) | No, and defensibly: commits stay reachable through the reflog for 90 days | no — recoverable |
| `git reflog expire --expire=now --all` | **no** | `[]` | No — destroys no files | no |
| `git gc --prune=now` | **no** | `[]` | No — destroys no files | no |

Notes on two rows that surprise:

- **`git rm -rf <path>` is partially covered by accident.** `recursiveDeletionTargets`
searches the token list for a word matching `RM_CMD_RE`, and in `git rm -rf src` that
matches the `rm` **subcommand**. So `block-rm-rf` evaluates it as an `rm` with target
`src` — allowed, because `src` is not catastrophic — and denies `git rm -rf /`. The
coverage is real but incidental, and it stops at the catastrophic-target test.
- **`git reflog expire` + `git gc --prune=now` are the recovery mechanism, not the loss.**
Alone they destroy no working file. Their severity is that they make `git reset --hard`,
`git branch -D` and a dropped stash *permanently* unrecoverable, which is a two-command
concern no single-command matcher models well.

### Why only `git clean` got coverage in this change

`git reset --hard`, `git checkout -- .` and `git restore .` are the same shape and the same
severity class, and they are the obvious next policy — but not a bolt-on to this one:

1. **They are a different verb.** "Discard uncommitted changes to tracked files" is not
"delete untracked files"; one instruct message cannot name both losses usefully, and
the flag conditions have nothing in common.
2. **Their authority decision is genuinely open, and `checkout`/`restore` may differ from
`reset`.** `git checkout -- .` and `git restore .` DO put `. => project_root` into
`facts.paths`, which is a relation `irreplaceable`'s instructions name explicitly — so
those two may be legitimately `reviewable` through `destructive-deletion` where
`git clean` provably is not. That needs measuring, per command, the way this one was.
3. **`git reset --hard <commit>` overlaps `git-history-rewrite`'s concern**, so its pairing
question is "which check owns this", not "does the existing check fire".

Each of those is a measurement, not a patch. Filed here rather than guessed.

### Open items

- [ ] Replay the labelled corpus against probe edit (a) and/or (b); report real-work-blocked,
attacks-blocked and label agreement against the current baseline.
- [ ] If the replay holds, revisit `warn-git-clean`'s authority.
- [ ] Add a `warn-git-discard-changes` builtin for `git reset --hard` / `git checkout -- .` /
`git restore .`, with its authority decided per command from measured probe answers.
- [ ] Decide whether `git reflog expire --expire=now --all` and `git gc --prune=now` deserve
a policy of their own, given that their harm is only realised in combination.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
Wherever your agents run, we see it — and we can say no. Failproof hooks 12 agent
harnesses — coding CLIs like Claude Code and Codex, chat gateways like Hermes,
self-hosted assistants like OpenClaw — capturing every run and blocking dangerous
tool calls before they execute. 39 built-in policies. Zero latency. Runs locally.
tool calls before they execute. 40 built-in policies. Zero latency. Runs locally.

</div>

Expand Down Expand Up @@ -177,7 +177,7 @@ three are the developer favourites — coding CLIs are the harness class we cove
deepest. The `sanitize-*` family is separate: it runs after a tool returns, so
it reports a secret in tool output rather than keeping it out of the context.

→ [All 39 built-in policies](https://docs.befailproof.ai/policies/packs)
→ [All 40 built-in policies](https://docs.befailproof.ai/policies/packs)

---

Expand Down
Loading
Loading