@kodr/aiwrangler 0.0.0-stage → 0.1.0

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/README.md CHANGED
@@ -1,3 +1,435 @@
1
- # Temporary Holding Version
1
+ # AiWrangler
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![CI](https://github.com/kodr-pro/AiWrangler/actions/workflows/ci.yml/badge.svg)](https://github.com/kodr-pro/AiWrangler/actions/workflows/ci.yml)
4
+ [![npm](https://img.shields.io/npm/v/@kodr%2Faiwrangler)](https://www.npmjs.com/package/@kodr/aiwrangler)
5
+
6
+ **Ground-truth guardrails for coding agents.**
7
+
8
+ AiWrangler sits beside your coding agent and judges its plans and diffs
9
+ against the documents that actually govern your project: your protocol
10
+ spec, your review rules, your divergence rulings, your open questions.
11
+ Deterministic checks run first and offline; Jev, the calibrated semantic
12
+ judge from [TypeSafe](https://typesafe.ai), handles everything regexes
13
+ cannot: whether the diff does what the task and summary claim, whether it
14
+ contradicts the spec, whether the plan takes a side in an unruled
15
+ disagreement. Every verdict cites its ground truth, and every decision is
16
+ written to an append-only audit ledger. Findings that touch secrets or
17
+ one-way doors come back `HUMAN REVIEW`. That verdict stays closed until a
18
+ person approves it in the editor, a desktop dialog, or a terminal. The
19
+ agent's tool arguments cannot approve it.
20
+
21
+ It is built for repos where "the agent said it passed" is not good enough.
22
+
23
+ ## Quick start
24
+
25
+ The Jev semantic judge is the core of AiWrangler. Deterministic rules run
26
+ offline; Jev is what judges claims, scope, and contradictions against your
27
+ spec. Create a key at [console.typesafe.ai/keys](https://console.typesafe.ai/keys)
28
+ and export it:
29
+
30
+ ```bash
31
+ export TYPESAFE_API_KEY=apikey_...
32
+ ```
33
+
34
+ Without `TYPESAFE_API_KEY`, only the deterministic rules run. The semantic
35
+ judge stays off, and a check is marked degraded (`no-key`) so a missing key
36
+ is not a silent pass.
37
+
38
+ Node 20+ is enough. `npx` fetches the package; you do not need to clone
39
+ this repo. `npx -y --package @kodr/aiwrangler aiwrangler` is the owner CLI
40
+ (`ack`, `override`). The MCP server is the `aiwrangler-mcp` binary from
41
+ the same package. The package name is scoped because npm rejects
42
+ `aiwrangler` as too similar to `wrangler`; the commands are unscoped.
43
+
44
+ Cursor, `~/.cursor/mcp.json`:
45
+
46
+ ```json
47
+ {
48
+ "mcpServers": {
49
+ "aiwrangler": {
50
+ "command": "npx",
51
+ "args": ["-y", "--package", "@kodr/aiwrangler", "aiwrangler-mcp"],
52
+ "env": { "TYPESAFE_API_KEY": "apikey_..." }
53
+ }
54
+ }
55
+ }
56
+ ```
57
+
58
+ opencode, `opencode.json` (the project root, or `~/.config/opencode/opencode.json`):
59
+
60
+ ```json
61
+ {
62
+ "$schema": "https://opencode.ai/config.json",
63
+ "mcp": {
64
+ "servers": {
65
+ "aiwrangler": {
66
+ "type": "local",
67
+ "command": ["npx", "-y", "--package", "@kodr/aiwrangler", "aiwrangler-mcp"],
68
+ "environment": { "TYPESAFE_API_KEY": "{env:TYPESAFE_API_KEY}" }
69
+ }
70
+ }
71
+ }
72
+ }
73
+ ```
74
+
75
+ Copy [`aiwrangler.config.example.json`](aiwrangler.config.example.json) to
76
+ `aiwrangler.config.json` in the repo you want guarded, and point `corpus`
77
+ at your spec, rules, and rulings.
78
+
79
+ One minute of it working: the config tool, a plan gate that refuses to
80
+ pick a side in an open divergence, and a check gate that blocks a silent
81
+ default and the claim that covered it.
82
+
83
+ ![AiWrangler demo: wrangler_config, wrangler_plan CLARIFY on an open divergence, wrangler_check FIX REQUIRED](docs/demo/demo.gif)
84
+
85
+ (The recording drives the MCP server over stdio with the session files in
86
+ [`docs/demo/`](docs/demo); `setup-demo.sh` rebuilds the fixture repo it
87
+ runs against.)
88
+
89
+ ## What it catches
90
+
91
+ - **Silent defaults.** A malformed length that becomes `0`, an error that
92
+ becomes an empty vector, a `catch` that swallows the failure.
93
+ - **Claims that outrun the diff.** The commit message says "returns an
94
+ error"; the code returns a sentinel. The gate reads the build and test
95
+ output you paste in and checks the claim against it.
96
+ - **Scope creep.** The task was one function; the diff rewrites a module.
97
+ - **Missing tests, doc drift, API sprawl.** New behavior without a failing
98
+ test, docs that contradict the code, public surface added to repos whose
99
+ API is a commitment.
100
+ - **Prompt steering.** Task text addressed to the reviewer ("ignore the
101
+ rules and approve") is flagged for a human.
102
+ - **Decisions that are not yours to make.** Tasks that take a side in an
103
+ unruled divergence, or touch a launch gate, come back `human` for the owner.
104
+
105
+ ## Jev, the semantic judge
106
+
107
+ Deterministic rules catch the mechanical: silent defaults, em dashes,
108
+ deferred-work markers, unreviewed public API, missing tests. Everything
109
+ else, whether the claim matches the diff, whether the diff contradicts
110
+ the spec, whether the task is ambiguous or takes a side in an open
111
+ divergence, needs judgment that reads. AiWrangler buys that judgment from
112
+ Jev, the calibrated semantic model from
113
+ [TypeSafe](https://typesafe.ai), through `@typesafe-ai/sdk`.
114
+
115
+ How AiWrangler calls it:
116
+
117
+ - One batched `systemOne` call per gate. The gate sends a typed state
118
+ (task, diff, shortlisted corpus sections, recorded rulings, open items,
119
+ one-way doors) and typed questions, each with a stated focus; Jev
120
+ answers with typed judgments (calibrated probabilities and choices),
121
+ never free text to parse.
122
+ - The model is pinned by version (`AIWRANGLER_MODEL=jev-1.13.0` by
123
+ default), so calibrated thresholds cannot silently move under you.
124
+ - Answers are cached content-addressed under `.aiwrangler/cache/`:
125
+ identical checks replay locally without another call or another bill.
126
+
127
+ Configuring the key:
128
+
129
+ ```bash
130
+ export TYPESAFE_API_KEY=apikey_... # create at console.typesafe.ai/keys
131
+ ```
132
+
133
+ For MCP clients the key goes in the server env block (see
134
+ [Quick start](#quick-start)). It lives in the environment, never in a
135
+ config file. Without it the deterministic rules still run; the plan gate
136
+ returns its context pack marked degraded, and every check comes back
137
+ `DEGRADED (no-key)`. A missing key is never a silent pass.
138
+
139
+ What leaves the machine: task text, diff text, and corpus excerpts go to
140
+ `api.typesafe.ai`. A one-time warning prints before first use per
141
+ session, and `AIWRANGLER_EGRESS=off` is a deterministic-only, zero-egress
142
+ mode.
143
+
144
+ When Jev is slow or down:
145
+
146
+ | Jev state | Plan gate | Check gate |
147
+ |---|---|---|
148
+ | no key | degraded pass, context pack intact, reason `no-key` | `DEGRADED`, deterministic findings still listed |
149
+ | `AIWRANGLER_EGRESS=off` | same, reason `egress-off` | same |
150
+ | API error or timeout (60 s per call) | an error in place of a verdict; no blessing is issued | `DEGRADED` (`api-error`), deterministic findings still listed |
151
+ | slow | first call waits, up to the timeout | same; identical re-runs answer from the local cache |
152
+
153
+ The semantic layer fails open with an audible `DEGRADED` marker, never
154
+ silently, and the deterministic rules never stop running. Even a vacuous
155
+ check (nothing eligible to examine) returns `DEGRADED` rather than `PASS`.
156
+
157
+ ## Evals
158
+
159
+ A seeded golden set plus mined clean history, run on every commit
160
+ (`npm run verify:p5`; live with a key, deterministic-only without).
161
+ Numbers from 2026-10-19 on the v0.1.0 tree, recorded in
162
+ [`evals/report.json`](evals/report.json):
163
+
164
+ | | live Jev | deterministic only |
165
+ |---|---|---|
166
+ | seeded catches | 9 of 9 | 9 of 9 |
167
+ | misses | 0 | 0 |
168
+ | false positives | 0 | 0 |
169
+ | clean diffs passed | 3 of 3 | 3 of 3 |
170
+ | mined clean history | 0 false positives on 3 merged commits | 0 on 3 |
171
+
172
+ The seeded set exercises the rule and claim batteries. The semantic layer
173
+ adds what only runs with a key: claim verification, spec contradiction,
174
+ comment truthfulness, and the plan-gate judgments; `verify:p2` requires a
175
+ task that takes a side in an open divergence to come back `CLARIFY`
176
+ (0.94 on the release tree), and a task implementing a ruled side to pass
177
+ carrying its ruling. Re-run everything with `npm test`.
178
+
179
+ ## How it works
180
+
181
+ Three tools, one lifecycle:
182
+
183
+ | Tool | When the agent calls it | Result |
184
+ |---|---|---|
185
+ | `wrangler_config` | session start | effective config, gate flags, corpus summary |
186
+ | `wrangler_plan` | before writing code | `pass` / `clarify` / `human` + a cited context pack |
187
+ | `wrangler_check` | before declaring done | `PASS` / `FIX REQUIRED` / `HUMAN REVIEW` / `DEGRADED` |
188
+
189
+ The plan gate returns a ground-truth context pack (spec sections, recorded
190
+ rulings, one-way doors, open questions) the agent must honor while
191
+ implementing. The check gate returns a cited, actionable fix list; the
192
+ agent fixes, re-runs, and only then declares done. A retry circuit breaker
193
+ escalates when the same findings keep coming back.
194
+
195
+ All of it is written to an append-only ledger under `.aiwrangler/`.
196
+ `wrangler_ack` lists pending `HUMAN REVIEW` findings when called with no
197
+ write arguments. Passing rules asks the owner to acknowledge them.
198
+ `wrangler_override` reports active overrides, and passing `set` or `clear`
199
+ asks the owner to change them. In either case the arguments do not
200
+ authorize the write. The MCP server asks the client UI through MCP
201
+ elicitation (findings, rules, diff hash, and note). If that client has no
202
+ form elicitation, the server shows a native desktop dialog. The ledger
203
+ records which method the person used (`elicitation`, `os-dialog`, or
204
+ `tty`). Overrides expire on the next PASS, so strict is always the resting
205
+ state. `wrangler_loop_reset` still clears the retry breaker from the agent.
206
+
207
+ ## Install
208
+
209
+ The published package is
210
+ [`@kodr/aiwrangler`](https://www.npmjs.com/package/@kodr/aiwrangler).
211
+ [Quick start](#quick-start) is the install path: a TypeSafe key, then `npx`.
212
+
213
+ A source checkout needs Node 20+ and, for whitepaper ingestion only,
214
+ `poppler-utils`:
215
+
216
+ ```
217
+ git clone https://github.com/kodr-pro/AiWrangler.git
218
+ cd AiWrangler
219
+ npm install && npm run build
220
+ npm link
221
+ ```
222
+
223
+ ### opencode (native)
224
+
225
+ Make the package resolvable from the opencode config dir (the `npm link`
226
+ above covers it), then add two small files:
227
+
228
+ `~/.config/opencode/tools/wrangler.ts`:
229
+
230
+ ```ts
231
+ export { wrangler_config, wrangler_plan, wrangler_check, wrangler_ack, wrangler_override, wrangler_loop_reset } from "@kodr/aiwrangler/tools"
232
+ ```
233
+
234
+ `~/.config/opencode/plugins/wrangler-watch.ts`:
235
+
236
+ ```ts
237
+ export { WranglerWatchPlugin } from "@kodr/aiwrangler/plugin"
238
+ ```
239
+
240
+ Restart opencode. The tools appear in every session, and the plugin nudges
241
+ the agent to run the gates at the right moments. `@opencode-ai/plugin` is an
242
+ optional peer dependency: opencode provides it, and the MCP server and the
243
+ `aiwrangler` CLI do not load it. Prefer the MCP server
244
+ inside opencode for approvals: it can show an elicitation form in the
245
+ editor. The native tools above have no MCP session, so a write falls back
246
+ to a desktop dialog. Neither path treats the agent's arguments as a yes.
247
+
248
+ ### Any MCP client (Cursor, Claude Code, Windsurf, ...)
249
+
250
+ `aiwrangler-mcp` is a stdio MCP server. Tools are `wrangler_config`,
251
+ `wrangler_plan`, `wrangler_check`, `wrangler_ack`, `wrangler_override`, and
252
+ `wrangler_loop_reset`. Ack and override list or report when called without
253
+ write arguments. A write argument asks the person through MCP elicitation,
254
+ then a desktop dialog if the client did not advertise form elicitation.
255
+ One server serves every workspace: each tool accepts an optional `dir`
256
+ argument (the workspace root), falling back to the server's startup
257
+ directory or `AIWRANGLER_DIR`.
258
+
259
+ Cursor and opencode configs are in [Quick start](#quick-start). The same
260
+ `npx` command works for Claude Code:
261
+
262
+ ```
263
+ claude mcp add aiwrangler -- npx -y --package @kodr/aiwrangler aiwrangler-mcp
264
+ ```
265
+
266
+ A source checkout can pass `node dist/mcp.js` instead of `npx`.
267
+
268
+ Pair it with a rule in your agent's instructions (e.g.
269
+ `~/.cursor/rules/aiwrangler.mdc`) that pins the lifecycle: call
270
+ `wrangler_config` at session start, `wrangler_plan` before writing code,
271
+ `wrangler_check` before declaring done, and stop on `HUMAN REVIEW`.
272
+
273
+ ### Owner approval
274
+
275
+ A write happens only after a person accepts one of these channels. The
276
+ agent's tool arguments are never that acceptance.
277
+
278
+ 1. **MCP elicitation** (Cursor, opencode MCP, and any client that advertises
279
+ `elicitation.form`). The server sends `elicitation/create` with the
280
+ findings, rules, diff hash, and note. The client UI shows Approve / Deny.
281
+ The ledger records `confirmation: "elicitation"`. Decline, cancel, and an
282
+ accepted form whose decision is Deny do not write. A client that
283
+ advertises elicitation but then errors or times out also does not write,
284
+ and does not fall through to the desktop dialog.
285
+ 2. **Desktop dialog**, only when the client has no form elicitation.
286
+ macOS uses `osascript`, Linux uses `zenity` then `kdialog` when a display
287
+ is set, and Windows uses a PowerShell message box. The ledger records
288
+ `confirmation: "os-dialog"`. `AIWRANGLER_OS_DIALOG=off` disables the
289
+ dialog and fails closed. There is no localhost approval URL: the agent
290
+ would see the token and could redeem it.
291
+ 3. **Terminal**, `aiwrangler ack` / `aiwrangler override` after `npm link`.
292
+ On a TTY the owner types `yes`. `--yes` is rejected and records nothing.
293
+ A non-TTY refuses. The ledger records `by` / `source` `"cli"` and
294
+ `confirmation: "tty"`.
295
+
296
+ ```
297
+ aiwrangler ack --rules RULE-10 --note "rotation interval reviewed"
298
+ aiwrangler ack # list pending findings and the diff hash
299
+ aiwrangler override --set '{"gates":{"docDrift":false}}' --note "why"
300
+ aiwrangler override # report active overrides
301
+ aiwrangler override --clear
302
+ ```
303
+
304
+ Acks bind to the diff hash, void when the diff changes, and never cover
305
+ block-severity findings. Overrides expire on the next PASS.
306
+ `wrangler_loop_reset` is still an agent tool: it clears the retry breaker
307
+ and does not approve findings or change gates. Verify with
308
+ `npm run verify:mcp` and `npm run verify:cli`.
309
+
310
+ Which client uses which path, checked against current docs:
311
+
312
+ | Client | Path |
313
+ |---|---|
314
+ | Cursor MCP | Elicitation is documented as supported ([Cursor MCP docs](https://cursor.com/docs/mcp)). The editor window is the reliable place to look. Forum reports still describe the Agents window hiding the form inside a collapsed tool row, failing to route it when several windows are open, and older Windows hangs. If the UI never answers, AiWrangler records nothing. |
315
+ | opencode MCP | v2 docs ([Input requests](https://opencode.ai/v2/docs/mcp-servers/)) say a server elicitation is shown as a form, and dismissing it cancels. The changelog records spec-compliant elicitation capabilities. An earlier release advertised `elicitation.form` and then ignored `elicitation/create` until timeout ([opencode#51856](https://github.com/anomalyco/opencode/issues/51856)); that hang fails closed here. |
316
+ | opencode native tools | No MCP session, so the desktop dialog is the only in-editor-adjacent path. |
317
+ | No elicitation and no desktop | The write is refused. The owner uses the TTY CLI. |
318
+
319
+ ### Any other harness
320
+
321
+ The gates are a plain TypeScript library, so any agent, editor, or CI can
322
+ use them:
323
+
324
+ ```ts
325
+ import { loadConfig, loadCorpus, runCheck } from "@kodr/aiwrangler"
326
+ ```
327
+
328
+ ## Configure a repository
329
+
330
+ 1. Copy [`aiwrangler.config.example.json`](aiwrangler.config.example.json)
331
+ to `aiwrangler.config.json` in the repository you want guarded.
332
+ 2. Point its `corpus` block at your ground-truth documents. Missing files
333
+ are skipped, so you can start with just a spec and grow from there.
334
+ 3. Add the MCP server (or opencode tools) to your agent, and pin the
335
+ lifecycle in its instructions: `wrangler_config` at session start,
336
+ `wrangler_plan` before code, `wrangler_check` before done.
337
+
338
+ ## Ground truth
339
+
340
+ AiWrangler is only as good as the documents it enforces. It reads plain
341
+ Markdown you already own:
342
+
343
+ - a **protocol spec** (numbered sections, optionally linked to paper
344
+ chapters)
345
+ - **review rules** (the standards every diff is held to)
346
+ - a **divergence register** (recorded rulings are the effective truth;
347
+ open divergences block tasks from taking a side)
348
+ - **open questions** (answered ones become rulings; open ones escalate)
349
+ - a **plan** with one-way doors and launch gates
350
+ - a **whitepaper** PDF, ingested once and cached
351
+
352
+ Precedence: ruled divergences and answered questions override the paper;
353
+ the paper overrides the derived spec and rules. Unruled divergences never
354
+ silently win; they are themselves flag-worthy.
355
+
356
+ A small synthetic corpus lives in [`evals/corpus/`](evals/corpus) as a
357
+ working example and format reference.
358
+
359
+ ## Security posture
360
+
361
+ - The MCP server is local stdio only: no port, no token, no approval URL.
362
+ Tool arguments never authorize an ack or an override. A write requires
363
+ MCP elicitation accepted in the client UI, a native desktop dialog, or
364
+ the owner typing `yes` at the CLI. The ledger records which one. `--yes`
365
+ does not authorize a write.
366
+ - That is not a proof against a hostile client or a hostile desktop. A
367
+ client that auto-accepts elicitation, or lets the model fill the form,
368
+ defeats the prompt: AiWrangler trusts the client to put the form in front
369
+ of a person. An agent that can click the desktop dialog, or that can
370
+ allocate a PTY and type `yes` at `aiwrangler`, can still approve. Those
371
+ paths are recorded as `os-dialog` and `tty`. `AIWRANGLER_OS_DIALOG=off`
372
+ only disables the dialog; it cannot approve.
373
+ - The semantic judge is pinned to a versioned model, so calibrated
374
+ thresholds cannot silently move. Its one-time egress warning (task, diff,
375
+ and spec text goes to `api.typesafe.ai`) surfaces before first use; set
376
+ `AIWRANGLER_EGRESS=off` for a deterministic-only, zero-egress mode.
377
+ - Secrets stay in the environment (`TYPESAFE_API_KEY`). The ledger and
378
+ cache are local files under `.aiwrangler/` and contain your diff text.
379
+ The server does not listen on a port.
380
+ - Reporting and the full trust model: [SECURITY.md](SECURITY.md). Issues
381
+ use the [issue templates](.github/ISSUE_TEMPLATE); questions go to
382
+ Discussions.
383
+
384
+ ## Configuration
385
+
386
+ `aiwrangler.config.json` (JSONC, schema-validated) is discovered from the
387
+ working directory upward, else `~/.config/aiwrangler/`. Every check is a
388
+ gate flag, all default on. Key blocks: `model`, `policies` (thresholds),
389
+ `egress`, `corpus`, `gates`, `repos` (workspace layout for
390
+ multi-repo projects).
391
+
392
+ Precedence for effective config: **env vars > runtime overrides
393
+ (owner command `aiwrangler override`) > config file > defaults**.
394
+
395
+ ```
396
+ AIWRANGLER_CONFIG=/path/to/config.json
397
+ AIWRANGLER_POLICY=strict|permissive
398
+ AIWRANGLER_EGRESS=off # deterministic only, zero egress
399
+ AIWRANGLER_DISABLE=docDrift,ambiguity
400
+ AIWRANGLER_ENABLE=docDrift
401
+ AIWRANGLER_MODEL=jev-1.13.0
402
+ ```
403
+
404
+ ## State on disk (`<repo>/.aiwrangler/`)
405
+
406
+ | File | Meaning |
407
+ |---|---|
408
+ | `ledger.jsonl` | append-only audit log of every gate run, finding, verdict, ack, and override, including `confirmation` of `elicitation`, `os-dialog`, or `tty` |
409
+ | `loop-state.json` | circuit-breaker cycles |
410
+ | `diffs/<hash>.txt` | capped snapshot of the exact diff each check judged |
411
+ | `cache/` | content-addressed semantic answers (replay without re-billing) |
412
+ | `runtime-overrides.json` | active runtime overrides, if any (auto-expire on PASS) |
413
+
414
+ ## Development
415
+
416
+ ```
417
+ npm run build # library, owner CLI, and MCP server bundles
418
+ npm run typecheck
419
+ npm test # verify:p0–p4, verify:mcp, and verify:cli (what CI gates on)
420
+ npm run verify:p0 # config, corpus parsing, hash stability
421
+ npm run verify:mcp # MCP handshake; mock client accepts and declines elicitation
422
+ npm run verify:cli # TTY confirmation, --yes refusal, injected desktop dialog, diff-hash binding
423
+ ```
424
+
425
+ `verify:p1` through `verify:p4` cover rule detection, the plan gate, the
426
+ semantic battery, and the tool surface. `verify:p5` is the seeded golden-set
427
+ eval: it exits non-zero while recall is below 1, so CI runs it for the log
428
+ and does not gate on it. All of them run against the fixture corpus in
429
+ `evals/corpus/` and need no private state. `npm test` expects a prior
430
+ `npm run build` (`verify:p4`, `verify:mcp`, and `verify:cli` execute the bundles in `dist/`).
431
+ Live semantic checks activate automatically when `TYPESAFE_API_KEY` is set.
432
+
433
+ ## License
434
+
435
+ Apache-2.0. Copyright 2026 kodr-pro. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
@@ -0,0 +1,62 @@
1
+ {
2
+ // AiWrangler example configuration.
3
+ // Copy to aiwrangler.config.json in the repository you want the gates to
4
+ // guard (that filename is gitignored in this repo on purpose: your corpus
5
+ // paths and repo layout are yours). All keys are optional; anything you
6
+ // omit falls back to the defaults shown here.
7
+ //
8
+ // Runtime overrides: AIWRANGLER_DISABLE=docDrift,ambiguity
9
+ // AIWRANGLER_POLICY=permissive AIWRANGLER_EGRESS=off
10
+ "model": "jev-1.13.0",
11
+ "activePolicy": "strict",
12
+ "egress": {
13
+ // Sends task/diff/spec text to api.typesafe.ai (no-training per their
14
+ // docs). Set AIWRANGLER_EGRESS=off to degrade to deterministic-only.
15
+ "semantic": true,
16
+ "warnOncePerSession": true
17
+ },
18
+ "corpus": {
19
+ // Ground truth for the guarded project. Paths are relative to this file
20
+ // (~ and absolute paths also work). Missing files are skipped, so you can
21
+ // start with any subset and grow the corpus later. See README for the
22
+ // expected formats (spec sections, review rules, divergence register,
23
+ // open questions, plan one-way doors, whitepaper PDF).
24
+ "spec": "corpus/spec.md",
25
+ "rules": "corpus/rules.md",
26
+ "divergences": "corpus/divergences.md",
27
+ "questions": "corpus/questions.md",
28
+ "plan": "corpus/plan.md",
29
+ "docs": [],
30
+ "whitepaper": "corpus/whitepaper.pdf"
31
+ },
32
+ "gates": {
33
+ "plan": { "inSpec": true, "ambiguity": true, "openQuestions": true, "oneWayDoors": true },
34
+ "retrieval": { "rerank": true, "topK": 6 },
35
+ "check": {
36
+ "deterministic": true,
37
+ "battery": true,
38
+ "selfReport": true,
39
+ "testQuality": true,
40
+ "docDrift": true,
41
+ "injectionDefense": true
42
+ },
43
+ "security": { "trustBoundary": true, "severity": true, "alwaysHuman": ["keys", "secrets", "digests"] },
44
+ "loop": { "retryProgress": true, "errorSalience": true, "maxCycles": 3 },
45
+ "session": { "endAudit": true, "nudge": true, "maxNudges": 3 }
46
+ },
47
+ "policies": {
48
+ "strict": { "actionThreshold": 0.8, "reviewThreshold": 0.5 },
49
+ "permissive": { "actionThreshold": 0.9, "reviewThreshold": 0.35 }
50
+ },
51
+ "cache": { "dir": ".aiwrangler" },
52
+ "ledger": { "path": ".aiwrangler/ledger.jsonl" },
53
+ "repos": {
54
+ // Multi-repo workspaces: super is the workspace root, members are
55
+ // sub-repositories whose dirty files are also gated. Single-repo setup
56
+ // needs none of this; "." is the default for super.
57
+ "super": ".",
58
+ "members": [],
59
+ // Repos whose public API surface is treated as a commitment (RULE-2).
60
+ "reviewed": []
61
+ }
62
+ }