@miller-tech/uap 1.83.0 → 1.84.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miller-tech/uap",
3
- "version": "1.83.0",
3
+ "version": "1.84.0",
4
4
  "description": "Autonomous AI agent memory system with CLAUDE.md protocol enforcement",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -65,18 +65,21 @@ def _is_local_model_session() -> bool:
65
65
  return any(h in base for h in ("127.0.0.1", "localhost", "0.0.0.0", "::1"))
66
66
 
67
67
 
68
- # #2: a plain local-model session cannot effectively route through deliver and
69
- # deadlocks under block mode (it can read but never write -> recon loop, observed
70
- # live). Downgrade block->advisory for local sessions so the model can write
71
- # directly; the local proxy already guards it. Set UAP_DELIVER_LOCAL_ADVISORY=0
72
- # to keep strict block for local sessions too.
73
- _LOCAL_ADVISORY = os.environ.get("UAP_DELIVER_LOCAL_ADVISORY", "on").lower() not in {
74
- "0",
75
- "off",
76
- "false",
77
- "no",
78
- "",
79
- }
68
+ # #2/#3a: how a LOCAL-model session is handled under block mode. A plain local
69
+ # session deadlocks under strict block (can read, never write -> recon loop,
70
+ # observed live). UAP_DELIVER_LOCAL_MODE selects the resolution:
71
+ # advisory (default) -> allow direct writes (fast; the proxy guards the model)
72
+ # deliver -> keep the block + route:deliver so the change is driven
73
+ # through `uap deliver` (VERIFIED path; pairs with
74
+ # UAP_DELIVER_AUTOROUTE)
75
+ # block -> strict block (no relaxation)
76
+ # Back-compat: UAP_DELIVER_LOCAL_ADVISORY=0 maps to "block".
77
+ def _local_mode() -> str:
78
+ m = os.environ.get("UAP_DELIVER_LOCAL_MODE", "").lower()
79
+ if m in {"advisory", "deliver", "block"}:
80
+ return m
81
+ adv = os.environ.get("UAP_DELIVER_LOCAL_ADVISORY", "on").lower()
82
+ return "advisory" if adv not in {"0", "off", "false", "no", ""} else "block"
80
83
 
81
84
 
82
85
  def main() -> None:
@@ -124,8 +127,11 @@ def main() -> None:
124
127
  )
125
128
 
126
129
  mode = os.environ.get("UAP_ENFORCE_DELIVERY", "block").lower()
127
- if mode == "block" and _LOCAL_ADVISORY and _is_local_model_session():
128
- mode = "advisory" # #2: unblock plain local-model sessions
130
+ if mode == "block" and _is_local_model_session():
131
+ # #3a: route-through-deliver keeps the block (route:deliver -> autoroute
132
+ # drives the verified deliver loop); advisory unblocks direct writes.
133
+ if _local_mode() == "advisory":
134
+ mode = "advisory"
129
135
  if mode == "block":
130
136
  # R1: emit a machine-actionable routing signal so a capable harness can
131
137
  # auto-route the blocked change INTO `uap deliver` instead of leaving the
@@ -103,3 +103,32 @@ class LocalAdvisoryTest(unittest.TestCase):
103
103
  def test_cloud_session_still_blocks(self):
104
104
  rc, out = self._run({"ANTHROPIC_BASE_URL":"https://api.anthropic.com"})
105
105
  self.assertEqual(rc, 2)
106
+
107
+
108
+ class LocalModeTest(unittest.TestCase):
109
+ def _run(self, env):
110
+ with _tf.TemporaryDirectory() as td:
111
+ root = _Path(td); (root/".git").mkdir()
112
+ f = root/"src"/"a.ts"; f.parent.mkdir(parents=True); f.write_text("x")
113
+ e = dict(_os.environ); e["UAP_REPO_ROOT"]=str(root)
114
+ for k in ("ANTHROPIC_BASE_URL","UAP_DELIVER_LOCAL_ADVISORY","UAP_DELIVER_LOCAL_MODE","UAP_DELIVER_ACTIVE"): e.pop(k, None)
115
+ e.update(env)
116
+ p = _sp.run([_sys.executable, str(_ENF), "--operation","Write","--args",_json.dumps({"file_path":str(f)})], capture_output=True, text=True, env=e)
117
+ return p.returncode, _json.loads(p.stdout) if p.stdout.strip() else {}
118
+
119
+ def test_local_mode_deliver_routes_through_deliver(self):
120
+ rc, out = self._run({"ANTHROPIC_BASE_URL":"http://127.0.0.1:4000","UAP_DELIVER_LOCAL_MODE":"deliver"})
121
+ self.assertEqual(rc, 2)
122
+ self.assertEqual(out.get("route"), "deliver")
123
+
124
+ def test_local_mode_advisory_allows(self):
125
+ rc, out = self._run({"ANTHROPIC_BASE_URL":"http://127.0.0.1:4000","UAP_DELIVER_LOCAL_MODE":"advisory"})
126
+ self.assertEqual(rc, 0); self.assertTrue(out["allowed"])
127
+
128
+ def test_local_mode_block_strict(self):
129
+ rc, out = self._run({"ANTHROPIC_BASE_URL":"http://127.0.0.1:4000","UAP_DELIVER_LOCAL_MODE":"block"})
130
+ self.assertEqual(rc, 2)
131
+
132
+ def test_default_is_advisory(self):
133
+ rc, out = self._run({"ANTHROPIC_BASE_URL":"http://127.0.0.1:4000"})
134
+ self.assertEqual(rc, 0)