failproofai 0.0.2-beta.6 → 0.0.2-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.claude/settings.json +316 -0
- package/.next/standalone/.failproofai/policies/workflow-policies.mjs +62 -0
- package/.next/standalone/.failproofai/policies-config.json +39 -0
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +5 -5
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +2 -2
- package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__02nt~6d._.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_05pz9._._.js +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_0z7w.hh._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0u_n1xe._.js → [root-of-the-server]__0.t2266._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__092s1ta._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09icjsf._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0g.lg8b._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h..k-e._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0okos0k._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0epc5zr._.js → [root-of-the-server]__0pjorff._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0w6l33k._.js +8 -9
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11pa2ra._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__12t-wym._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_10lm7or._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_0xerkr6._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_0q-m0y-._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0a_7sdg.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0ef3uwk.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0j79~gv.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0pbja1x.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0r6o0i2.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_11y81~_.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_12or2kf.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_0mebn66._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +5 -5
- package/.next/standalone/.next/server/pages/404.html +2 -2
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +9 -9
- package/.next/standalone/.next/static/chunks/{0efsuf1p-k4qe.js → 04xfyqyhdxbxz.js} +1 -1
- package/.next/standalone/.next/static/chunks/{17p200_z1ivz4.js → 07g0rbtaux_1t.js} +1 -1
- package/.next/standalone/.next/static/chunks/{031pa5~qfzt~_.js → 09e7drilkf1sn.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0tood0~87-mm8.js → 0a_xh94bt.y0j.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0rvepm.~uvks4.js → 0j752uotyfvjh.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0wkzaq-8sxss7.js → 0qi0ubup__3pj.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0kbfx4p.g9wnr.js → 0xyvis4r_y.8o.js} +2 -2
- package/.next/standalone/.next/static/chunks/{0jqg886bw85_6.js → 0zfyfi1suoteq.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0_tx_~f8pi3d7.js → 121a-0zn-knuy.js} +1 -1
- package/.next/standalone/.next/static/chunks/{turbopack-0uc5y~g6h.n7-.js → turbopack-0r26pc8h0y_-e.js} +1 -1
- package/.next/standalone/CHANGELOG.md +88 -0
- package/.next/standalone/CLAUDE.md +14 -0
- package/.next/standalone/README.md +20 -3
- package/.next/standalone/bin/failproofai.mjs +5 -0
- package/.next/standalone/bun.lock +31 -63
- package/.next/standalone/dist/cli.mjs +268 -73
- package/.next/standalone/docs/built-in-policies.mdx +19 -3
- package/.next/standalone/docs/configuration.mdx +46 -0
- package/.next/standalone/docs/custom-policies.mdx +65 -7
- package/.next/standalone/docs/docs.json +3 -3
- package/.next/standalone/examples/convention-policies/security-policies.mjs +40 -0
- package/.next/standalone/examples/convention-policies/workflow-policies.mjs +41 -0
- package/.next/standalone/node_modules/@next/env/package.json +1 -1
- package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
- package/.next/standalone/node_modules/next/dist/compiled/jsonwebtoken/index.js +2 -2
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js +1 -1
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +1 -1
- package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-turbo.runtime.prod.js +1 -1
- package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
- package/.next/standalone/node_modules/next/dist/server/config.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-turbopack.js +7 -2
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-webpack.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/render.js +20 -19
- package/.next/standalone/node_modules/next/dist/shared/lib/errors/canary-only-config-error.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/anonymous-meta.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/swc-load-failure.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/version.js +2 -2
- package/.next/standalone/node_modules/next/package.json +15 -15
- package/.next/standalone/node_modules/react/cjs/react.development.js +1 -1
- package/.next/standalone/node_modules/react/cjs/react.production.js +1 -1
- package/.next/standalone/node_modules/react/package.json +1 -1
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.node.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.browser.production.js +3 -3
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.edge.production.js +3 -3
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.node.production.js +3 -3
- package/.next/standalone/node_modules/react-dom/cjs/react-dom.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/package.json +2 -2
- package/.next/standalone/package.json +1 -1
- package/.next/standalone/server.js +1 -1
- package/.next/standalone/src/hooks/builtin-policies.ts +70 -18
- package/.next/standalone/src/hooks/custom-hooks-loader.ts +165 -21
- package/.next/standalone/src/hooks/handler.ts +32 -6
- package/.next/standalone/src/hooks/hooks-config.ts +47 -2
- package/.next/standalone/src/hooks/llm-client.ts +2 -2
- package/.next/standalone/src/hooks/loader-utils.ts +4 -4
- package/.next/standalone/src/hooks/manager.ts +57 -14
- package/.next/standalone/src/hooks/policy-evaluator.ts +35 -17
- package/README.md +20 -3
- package/bin/failproofai.mjs +5 -0
- package/dist/cli.mjs +268 -73
- package/package.json +1 -1
- package/src/hooks/builtin-policies.ts +70 -18
- package/src/hooks/custom-hooks-loader.ts +165 -21
- package/src/hooks/handler.ts +32 -6
- package/src/hooks/hooks-config.ts +47 -2
- package/src/hooks/llm-client.ts +2 -2
- package/src/hooks/loader-utils.ts +4 -4
- package/src/hooks/manager.ts +57 -14
- package/src/hooks/policy-evaluator.ts +35 -17
- /package/.next/standalone/.next/static/{gDMch26rYN-bU-9f6ftKR → itedhTSyIDln6TUf41j5X}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{gDMch26rYN-bU-9f6ftKR → itedhTSyIDln6TUf41j5X}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{gDMch26rYN-bU-9f6ftKR → itedhTSyIDln6TUf41j5X}/_ssgManifest.js +0 -0
|
@@ -116,6 +116,35 @@ If a policy has parameters but you don't specify them, the policy's built-in def
|
|
|
116
116
|
|
|
117
117
|
Unknown keys inside a policy's params block are silently ignored at hook-fire time but flagged as warnings when you run `failproofai policies`.
|
|
118
118
|
|
|
119
|
+
#### `hint` (cross-cutting)
|
|
120
|
+
|
|
121
|
+
Type: `string` (optional)
|
|
122
|
+
|
|
123
|
+
A message appended to the reason when a policy returns `deny` or `instruct`. Use it to give Claude actionable guidance without modifying the policy itself.
|
|
124
|
+
|
|
125
|
+
Works with any policy type — built-in, custom (`custom/`), project convention (`.failproofai-project/`), or user convention (`.failproofai-user/`).
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"policyParams": {
|
|
130
|
+
"block-force-push": {
|
|
131
|
+
"hint": "Try creating a fresh branch instead."
|
|
132
|
+
},
|
|
133
|
+
"block-sudo": {
|
|
134
|
+
"allowPatterns": ["sudo apt-get"],
|
|
135
|
+
"hint": "Use apt-get directly without sudo."
|
|
136
|
+
},
|
|
137
|
+
"custom/my-policy": {
|
|
138
|
+
"hint": "Ask the user for approval first."
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
When `block-force-push` denies, Claude sees: *"Force-pushing is blocked. Try creating a fresh branch instead."*
|
|
145
|
+
|
|
146
|
+
Non-string values and empty strings are silently ignored. If `hint` is not set, behavior is unchanged (backward-compatible).
|
|
147
|
+
|
|
119
148
|
### `customPoliciesPath`
|
|
120
149
|
|
|
121
150
|
Type: `string` (absolute path)
|
|
@@ -124,6 +153,23 @@ Path to a JavaScript file containing custom hook policies. This is set automatic
|
|
|
124
153
|
|
|
125
154
|
The file is loaded fresh on every hook event - there is no caching. See [Custom Policies](/custom-policies) for authoring details.
|
|
126
155
|
|
|
156
|
+
### Convention-based policies (v0.0.2-beta.7+)
|
|
157
|
+
|
|
158
|
+
In addition to the explicit `customPoliciesPath`, failproofai automatically discovers and loads policy files from `.failproofai/policies/` directories:
|
|
159
|
+
|
|
160
|
+
| Level | Directory | Scope |
|
|
161
|
+
|-------|-----------|-------|
|
|
162
|
+
| Project | `.failproofai/policies/` | Shared with team via version control |
|
|
163
|
+
| User | `~/.failproofai/policies/` | Personal, applies to all projects |
|
|
164
|
+
|
|
165
|
+
**File matching:** Only files matching `*policies.{js,mjs,ts}` are loaded (e.g. `security-policies.mjs`, `workflow-policies.js`). Other files in the directory are ignored.
|
|
166
|
+
|
|
167
|
+
**No config needed:** Convention policies require no entries in `policies-config.json`. Just drop files into the directory and they're picked up on the next hook event.
|
|
168
|
+
|
|
169
|
+
**Union loading:** Both project and user convention directories are scanned. All matching files from both levels are loaded (unlike `customPoliciesPath` which uses first-scope-wins).
|
|
170
|
+
|
|
171
|
+
See [Custom Policies](/custom-policies) for more details and examples.
|
|
172
|
+
|
|
127
173
|
### `llm`
|
|
128
174
|
|
|
129
175
|
Type: `object` (optional)
|
|
@@ -37,7 +37,33 @@ failproofai policies --install --custom ./my-policies.js
|
|
|
37
37
|
|
|
38
38
|
---
|
|
39
39
|
|
|
40
|
-
##
|
|
40
|
+
## Two ways to load custom policies
|
|
41
|
+
|
|
42
|
+
### Option 1: Convention-based (recommended, v0.0.2-beta.7+)
|
|
43
|
+
|
|
44
|
+
Drop `*policies.{js,mjs,ts}` files into `.failproofai/policies/` and they're automatically loaded — no flags or config changes needed. This works like git hooks: drop a file, it just works.
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
# Project level — committed to git, shared with the team
|
|
48
|
+
.failproofai/policies/security-policies.mjs
|
|
49
|
+
.failproofai/policies/workflow-policies.mjs
|
|
50
|
+
|
|
51
|
+
# User level — personal, applies to all projects
|
|
52
|
+
~/.failproofai/policies/my-policies.mjs
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**How it works:**
|
|
56
|
+
- Both project and user directories are scanned (union — not first-scope-wins)
|
|
57
|
+
- Files are loaded alphabetically within each directory. Prefix with `01-`, `02-` to control order
|
|
58
|
+
- Only files matching `*policies.{js,mjs,ts}` are loaded; other files are ignored
|
|
59
|
+
- Each file is loaded independently (fail-open per file)
|
|
60
|
+
- Works alongside explicit `--custom` and built-in policies
|
|
61
|
+
|
|
62
|
+
<Tip>
|
|
63
|
+
Convention policies are the easiest way to share policies across a team. Commit `.failproofai/policies/` to git and every team member gets them automatically.
|
|
64
|
+
</Tip>
|
|
65
|
+
|
|
66
|
+
### Option 2: Explicit file path
|
|
41
67
|
|
|
42
68
|
```bash
|
|
43
69
|
# Install with a custom policies file
|
|
@@ -52,6 +78,14 @@ failproofai policies --uninstall --custom
|
|
|
52
78
|
|
|
53
79
|
The resolved absolute path is stored in `policies-config.json` as `customPoliciesPath`. The file is loaded fresh on every hook event - there is no caching between events.
|
|
54
80
|
|
|
81
|
+
### Using both together
|
|
82
|
+
|
|
83
|
+
Convention policies and the explicit `--custom` file can coexist. Load order:
|
|
84
|
+
|
|
85
|
+
1. Explicit `customPoliciesPath` file (if configured)
|
|
86
|
+
2. Project convention files (`{cwd}/.failproofai/policies/`, alphabetical)
|
|
87
|
+
3. User convention files (`~/.failproofai/policies/`, alphabetical)
|
|
88
|
+
|
|
55
89
|
---
|
|
56
90
|
|
|
57
91
|
## API
|
|
@@ -85,7 +119,11 @@ customPolicies.add({
|
|
|
85
119
|
|
|
86
120
|
`deny(message)` - the message appears to Claude prefixed with `"Blocked by failproofai:"`. A single `deny` short-circuits all further evaluation.
|
|
87
121
|
|
|
88
|
-
`instruct(message)` - the message is appended to Claude's context for the current tool call.
|
|
122
|
+
`instruct(message)` - the message is appended to Claude's context for the current tool call. All `instruct` messages are accumulated and delivered together.
|
|
123
|
+
|
|
124
|
+
<Tip>
|
|
125
|
+
You can append extra guidance to any `deny` or `instruct` message by adding a `hint` field in `policyParams` — no code change needed. This works for custom (`custom/`), project convention (`.failproofai-project/`), and user convention (`.failproofai-user/`) policies too. See [Configuration → hint](/configuration#hint-cross-cutting) for details.
|
|
126
|
+
</Tip>
|
|
89
127
|
|
|
90
128
|
### Informational allow messages (beta)
|
|
91
129
|
|
|
@@ -155,10 +193,12 @@ customPolicies.add({
|
|
|
155
193
|
Policies are evaluated in this order:
|
|
156
194
|
|
|
157
195
|
1. Built-in policies (in definition order)
|
|
158
|
-
2.
|
|
196
|
+
2. Explicit custom policies from `customPoliciesPath` (in `.add()` order)
|
|
197
|
+
3. Convention policies from project `.failproofai/policies/` (files alphabetical, `.add()` order within)
|
|
198
|
+
4. Convention policies from user `~/.failproofai/policies/` (files alphabetical, `.add()` order within)
|
|
159
199
|
|
|
160
200
|
<Note>
|
|
161
|
-
The first `deny` short-circuits all subsequent policies.
|
|
201
|
+
The first `deny` short-circuits all subsequent policies. All `instruct` messages are accumulated and delivered together.
|
|
162
202
|
</Note>
|
|
163
203
|
|
|
164
204
|
---
|
|
@@ -212,11 +252,13 @@ Custom policies are **fail-open**: errors never block built-in policies or crash
|
|
|
212
252
|
|
|
213
253
|
| Failure | Behavior |
|
|
214
254
|
|---------|----------|
|
|
215
|
-
| `customPoliciesPath` not set | No custom policies run; built-ins continue normally |
|
|
255
|
+
| `customPoliciesPath` not set | No explicit custom policies run; convention policies and built-ins continue normally |
|
|
216
256
|
| File not found | Warning logged to `~/.failproofai/hook.log`; built-ins continue |
|
|
217
|
-
| Syntax/import error | Error logged to `~/.failproofai/hook.log`;
|
|
257
|
+
| Syntax/import error (explicit) | Error logged to `~/.failproofai/hook.log`; explicit custom policies skipped |
|
|
258
|
+
| Syntax/import error (convention) | Error logged; that file skipped, other convention files still load |
|
|
218
259
|
| `fn` throws at runtime | Error logged; that hook treated as `allow`; other hooks continue |
|
|
219
260
|
| `fn` takes longer than 10s | Timeout logged; treated as `allow` |
|
|
261
|
+
| Convention directory missing | No convention policies run; no error |
|
|
220
262
|
|
|
221
263
|
<Tip>
|
|
222
264
|
To debug custom policy errors, watch the log file:
|
|
@@ -291,9 +333,25 @@ The `examples/` directory contains ready-to-run policy files:
|
|
|
291
333
|
|------|----------|
|
|
292
334
|
| `examples/policies-basic.js` | Five starter policies covering common agent failure modes |
|
|
293
335
|
| `examples/policies-advanced/index.js` | Advanced patterns: transitive imports, async calls, output scrubbing, and session-end hooks |
|
|
336
|
+
| `examples/convention-policies/security-policies.mjs` | Convention-based security policies (block .env writes, prevent git history rewriting) |
|
|
337
|
+
| `examples/convention-policies/workflow-policies.mjs` | Convention-based workflow policies (test reminders, audit file writes) |
|
|
294
338
|
|
|
295
|
-
|
|
339
|
+
### Using explicit file examples
|
|
296
340
|
|
|
297
341
|
```bash
|
|
298
342
|
failproofai policies --install --custom ./examples/policies-basic.js
|
|
299
343
|
```
|
|
344
|
+
|
|
345
|
+
### Using convention-based examples
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
# Copy to project level
|
|
349
|
+
mkdir -p .failproofai/policies
|
|
350
|
+
cp examples/convention-policies/*.mjs .failproofai/policies/
|
|
351
|
+
|
|
352
|
+
# Or copy to user level
|
|
353
|
+
mkdir -p ~/.failproofai/policies
|
|
354
|
+
cp examples/convention-policies/*.mjs ~/.failproofai/policies/
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
No install command needed — the files are picked up automatically on the next hook event.
|
|
@@ -86,9 +86,9 @@
|
|
|
86
86
|
"icon": "npm"
|
|
87
87
|
},
|
|
88
88
|
{
|
|
89
|
-
"anchor": "
|
|
90
|
-
"href": "https://
|
|
91
|
-
"icon": "
|
|
89
|
+
"anchor": "Slack",
|
|
90
|
+
"href": "https://join.slack.com/t/failproofai/shared_invite/zt-3v63b7k5e-O3NBHmj8X6n9gZSGDx6ggQ",
|
|
91
|
+
"icon": "slack"
|
|
92
92
|
}
|
|
93
93
|
]
|
|
94
94
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* security-policies.mjs — Convention-based security policies
|
|
3
|
+
*
|
|
4
|
+
* Drop this file into .failproofai/policies/ at the project or user level
|
|
5
|
+
* and it will be automatically loaded — no --custom flag needed.
|
|
6
|
+
*
|
|
7
|
+
* Project level: .failproofai/policies/security-policies.mjs
|
|
8
|
+
* User level: ~/.failproofai/policies/security-policies.mjs
|
|
9
|
+
*/
|
|
10
|
+
import { customPolicies, allow, deny } from "failproofai";
|
|
11
|
+
|
|
12
|
+
// Block writes to .env files
|
|
13
|
+
customPolicies.add({
|
|
14
|
+
name: "block-env-writes",
|
|
15
|
+
description: "Prevent Claude from writing to .env files",
|
|
16
|
+
match: { events: ["PreToolUse"] },
|
|
17
|
+
fn: async (ctx) => {
|
|
18
|
+
if (!["Write", "Edit"].includes(ctx.toolName ?? "")) return allow();
|
|
19
|
+
const path = String(ctx.toolInput?.file_path ?? "");
|
|
20
|
+
if (/\.env($|\.)/.test(path)) {
|
|
21
|
+
return deny(`Writing to .env files is blocked: ${path}`);
|
|
22
|
+
}
|
|
23
|
+
return allow();
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Block commands that delete git history
|
|
28
|
+
customPolicies.add({
|
|
29
|
+
name: "block-git-history-rewrite",
|
|
30
|
+
description: "Prevent destructive git history operations",
|
|
31
|
+
match: { events: ["PreToolUse"] },
|
|
32
|
+
fn: async (ctx) => {
|
|
33
|
+
if (ctx.toolName !== "Bash") return allow();
|
|
34
|
+
const cmd = String(ctx.toolInput?.command ?? "");
|
|
35
|
+
if (/git\s+(rebase\s+-i|filter-branch|reflog\s+expire)/.test(cmd)) {
|
|
36
|
+
return deny("Rewriting git history is not allowed — use a revert commit instead");
|
|
37
|
+
}
|
|
38
|
+
return allow();
|
|
39
|
+
},
|
|
40
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* workflow-policies.mjs — Convention-based workflow policies
|
|
3
|
+
*
|
|
4
|
+
* Drop this file into .failproofai/policies/ at the project or user level
|
|
5
|
+
* and it will be automatically loaded — no --custom flag needed.
|
|
6
|
+
*
|
|
7
|
+
* Project level: .failproofai/policies/workflow-policies.mjs
|
|
8
|
+
* User level: ~/.failproofai/policies/workflow-policies.mjs
|
|
9
|
+
*/
|
|
10
|
+
import { customPolicies, allow, instruct } from "failproofai";
|
|
11
|
+
|
|
12
|
+
// Remind to run tests before committing
|
|
13
|
+
customPolicies.add({
|
|
14
|
+
name: "test-before-commit",
|
|
15
|
+
description: "Remind Claude to run tests before git commit",
|
|
16
|
+
match: { events: ["PreToolUse"] },
|
|
17
|
+
fn: async (ctx) => {
|
|
18
|
+
if (ctx.toolName !== "Bash") return allow();
|
|
19
|
+
const cmd = String(ctx.toolInput?.command ?? "");
|
|
20
|
+
if (/git\s+commit/.test(cmd)) {
|
|
21
|
+
return instruct(
|
|
22
|
+
"Before committing, make sure all tests pass. " +
|
|
23
|
+
"Run the test suite first if you haven't already."
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
return allow();
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Log all file writes for audit trail
|
|
31
|
+
customPolicies.add({
|
|
32
|
+
name: "audit-file-writes",
|
|
33
|
+
description: "Log all file write operations",
|
|
34
|
+
match: { events: ["PostToolUse"] },
|
|
35
|
+
fn: async (ctx) => {
|
|
36
|
+
if (!["Write", "Edit"].includes(ctx.toolName ?? "")) return allow();
|
|
37
|
+
const path = ctx.toolInput?.file_path ?? "unknown";
|
|
38
|
+
console.error(`[audit] File written: ${path}`);
|
|
39
|
+
return allow();
|
|
40
|
+
},
|
|
41
|
+
});
|
|
@@ -134,7 +134,7 @@ var HmrTarget = /*#__PURE__*/ function(HmrTarget) {
|
|
|
134
134
|
HmrTarget["Server"] = "server";
|
|
135
135
|
return HmrTarget;
|
|
136
136
|
}({});
|
|
137
|
-
const nextVersion = "16.2.
|
|
137
|
+
const nextVersion = "16.2.3";
|
|
138
138
|
const ArchName = (0, _os.arch)();
|
|
139
139
|
const PlatformName = (0, _os.platform)();
|
|
140
140
|
function infoLog(...args) {
|