@miller-tech/uap 1.184.1 → 1.184.2

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.
@@ -194,43 +194,52 @@ the next tool call.
194
194
 
195
195
  ## Changing an enforcer's code
196
196
 
197
- Two things trip people up here, and both fail *silently* — the source looks
198
- fixed while the gate keeps enforcing the old behaviour.
197
+ Three things trip people up here, and all of them fail *silently* — the source
198
+ looks fixed, `uap policy install` prints success, and the gate goes on
199
+ enforcing the old behaviour.
199
200
 
200
201
  **1. The gate does not run `src/policies/enforcers/*.py`.** It runs
201
202
  `.policy-tools/<policyId>_<toolName>.py`, a separate materialized copy (plus a
202
203
  snapshot in the `code` column of `policies.db`). Editing the source changes
203
- nothing on its own — re-run `uap policy install <slug>` to refresh the
204
- executable copy:
204
+ nothing on its own — the executable copy has to be refreshed by
205
+ `uap policy install <slug>`.
206
+
207
+ **2. `uap policy install` reads the enforcer from the RUNNING PACKAGE, not from
208
+ your repo.** `resolvePolicyDir()` resolves `src/policies/enforcers/` relative to
209
+ the installed package first, and only falls back to `process.cwd()` — deliberately,
210
+ so that `uap` works in projects that are not this repo. When `uap` is the global
211
+ install, editing this repo's enforcer and running `uap policy install` copies the
212
+ **global package's** version, and the message still says
213
+ "attached enforcer … from src/policies/enforcers/…".
214
+
215
+ So an enforcer change reaches the running gate only after the package the `uap`
216
+ binary comes from contains it:
205
217
 
206
218
  ```bash
219
+ which uap # /usr/local/bin/uap -> the global install?
220
+ uap --version # does it match this repo's package.json?
221
+
222
+ npm i -g . # from the repo, after the fix is merged
207
223
  uap policy install workdir-scope
208
224
  grep -l _my_new_function .policy-tools/*workdir_scope.py # verify it took
209
225
  ```
210
226
 
211
- **2. Run that install from the MAIN checkout, not a worktree.** The policy gate
212
- anchors runtime state `policies.db` and `.policy-tools/` to `MAIN_ROOT`, so
213
- that every worktree enforces the same policies. `uap policy install` run from
214
- inside a worktree gets this wrong in *both* directions, while still printing
215
- success:
216
-
217
- - it **reads** the enforcer source from the main checkout (not the worktree's
218
- edited copy), and
219
- - it **writes** the materialized copy into a worktree-local `.policy-tools/`
220
- that the gate never reads.
227
+ That last `grep` is the only real confirmation. A byte-size comparison against
228
+ the enforcer source works too: a mismatch means the copy came from somewhere else.
221
229
 
222
- So the install is a no-op for enforcement, and it is silent about it: the
223
- edited enforcer is verified by the test suite (which reads the worktree source)
224
- while the running gate still executes the old code. Verified 2026-08-03 by
225
- comparing the materialized copy against both sources it matched the main
226
- checkout byte for byte.
230
+ **3. Run the install from the MAIN checkout, not a worktree.** The gate anchors
231
+ runtime state `policies.db` and `.policy-tools/` to `MAIN_ROOT`, so every
232
+ worktree enforces the same policies. Run from inside a worktree, the install
233
+ writes a worktree-local `.policy-tools/` that the gate never reads.
227
234
 
228
- So an enforcer fix is two separate steps in two different directories:
235
+ Put together, an enforcer fix is three steps in two directories:
229
236
 
230
237
  - edit the enforcer **in your worktree**, so the change ships in the PR;
231
- - after it merges, run `uap policy install <slug>` **from the main checkout** to
232
- refresh the runtime copy.
238
+ - after it merges, update the package the `uap` binary resolves to
239
+ (`npm i -g .` from the main checkout, or install the published version);
240
+ - run `uap policy install <slug>` **from the main checkout**, and verify the
241
+ materialized copy actually changed.
233
242
 
234
243
  Note that `enforcement-self-protect` blocks agent writes to `src/policies/**`
235
- outright, with no model-reachable bypass. An agent cannot make either change
236
- enforcer edits are an operator action by design.
244
+ outright, with no model-reachable bypass. An agent cannot make any of these
245
+ changes — enforcer edits are an operator action by design.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miller-tech/uap",
3
- "version": "1.184.1",
3
+ "version": "1.184.2",
4
4
  "description": "Autonomous AI agent memory system with CLAUDE.md protocol enforcement",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",