@miller-tech/uap 1.186.3 → 1.187.3
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/dist/.tsbuildinfo +1 -1
- package/dist/bin/cli.js +4 -0
- package/dist/bin/cli.js.map +1 -1
- package/dist/cli/deliver.d.ts +100 -0
- package/dist/cli/deliver.d.ts.map +1 -1
- package/dist/cli/deliver.js +507 -20
- package/dist/cli/deliver.js.map +1 -1
- package/dist/coordination/reactor.d.ts.map +1 -1
- package/dist/coordination/reactor.js +28 -5
- package/dist/coordination/reactor.js.map +1 -1
- package/dist/delivery/agentic-executor.d.ts +3 -3
- package/dist/delivery/agentic-executor.d.ts.map +1 -1
- package/dist/delivery/agentic-executor.js +74 -4
- package/dist/delivery/agentic-executor.js.map +1 -1
- package/dist/delivery/convergence-loop.d.ts +6 -0
- package/dist/delivery/convergence-loop.d.ts.map +1 -1
- package/dist/delivery/convergence-loop.js +31 -0
- package/dist/delivery/convergence-loop.js.map +1 -1
- package/dist/delivery/edit-match.d.ts.map +1 -1
- package/dist/delivery/edit-match.js +19 -1
- package/dist/delivery/edit-match.js.map +1 -1
- package/dist/delivery/epic-controller.d.ts +6 -0
- package/dist/delivery/epic-controller.d.ts.map +1 -1
- package/dist/delivery/epic-controller.js +10 -0
- package/dist/delivery/epic-controller.js.map +1 -1
- package/dist/delivery/epic-mission.d.ts.map +1 -1
- package/dist/delivery/epic-mission.js +3 -0
- package/dist/delivery/epic-mission.js.map +1 -1
- package/dist/delivery/verifier-ladder.d.ts +99 -6
- package/dist/delivery/verifier-ladder.d.ts.map +1 -1
- package/dist/delivery/verifier-ladder.js +208 -25
- package/dist/delivery/verifier-ladder.js.map +1 -1
- package/dist/mcp-router/tools/deliver.d.ts.map +1 -1
- package/dist/mcp-router/tools/deliver.js +17 -0
- package/dist/mcp-router/tools/deliver.js.map +1 -1
- package/dist/models/long-fetch.d.ts +19 -0
- package/dist/models/long-fetch.d.ts.map +1 -1
- package/dist/models/long-fetch.js +47 -0
- package/dist/models/long-fetch.js.map +1 -1
- package/dist/telemetry/tool-failure.d.ts +9 -0
- package/dist/telemetry/tool-failure.d.ts.map +1 -1
- package/dist/telemetry/tool-failure.js +4 -0
- package/dist/telemetry/tool-failure.js.map +1 -1
- package/docs/reference/CLI.md +13 -2
- package/docs/reference/CONFIGURATION.md +2 -0
- package/package.json +2 -2
- package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
- package/src/policies/enforcers/enforcement_infra_protect.py +68 -5
- package/src/policies/enforcers/enforcement_self_protect.py +36 -0
- package/templates/hooks/__pycache__/deliver_autoroute.cpython-312.pyc +0 -0
- package/templates/hooks/pre-tool-use-bash.sh +10 -2
- package/templates/hooks/uap-policy-gate.sh +4 -1
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
|
@@ -18,6 +18,16 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { Agent } from 'undici';
|
|
20
20
|
const globalFetch = (url, init) => globalThis.fetch(url, init);
|
|
21
|
+
/**
|
|
22
|
+
* Marks a failure as "the model endpoint is not reachable".
|
|
23
|
+
*
|
|
24
|
+
* A greppable prefix rather than an Error subclass because it has to survive
|
|
25
|
+
* being stringified into an executor error string and read back by the
|
|
26
|
+
* convergence loop, which never sees the original Error object. Lives here, in
|
|
27
|
+
* the transport module, so both the executor that raises it and the loop that
|
|
28
|
+
* consumes it can import it without a cycle.
|
|
29
|
+
*/
|
|
30
|
+
export const ENDPOINT_UNREACHABLE = 'ENDPOINT_UNREACHABLE';
|
|
21
31
|
const DEFAULT_MODEL_HTTP_TIMEOUT_MS = 30 * 60 * 1000;
|
|
22
32
|
const CONNECT_TIMEOUT_MS = 30_000;
|
|
23
33
|
const DEFAULT_RETRIES = 2;
|
|
@@ -51,6 +61,43 @@ const TRANSIENT_CODES = new Set([
|
|
|
51
61
|
'UND_ERR_CONNECT_TIMEOUT',
|
|
52
62
|
'UND_ERR_SOCKET',
|
|
53
63
|
]);
|
|
64
|
+
/**
|
|
65
|
+
* Codes that mean the connection could never be ESTABLISHED — nothing is
|
|
66
|
+
* listening, or the name does not resolve.
|
|
67
|
+
*
|
|
68
|
+
* Deliberately a strict subset of TRANSIENT_CODES, and deliberately NOT reused
|
|
69
|
+
* from it. The transient set answers "is a retry safe?", which is a different
|
|
70
|
+
* question from "is the endpoint dead?", and most of it means *reachable but
|
|
71
|
+
* flaky or slow*: ECONNRESET/EPIPE/UND_ERR_SOCKET are a dropped connection
|
|
72
|
+
* under load, and UND_ERR_*_TIMEOUT is a model still thinking past the
|
|
73
|
+
* 30-minute ceiling. Treating those as "unreachable" would kill a long,
|
|
74
|
+
* healthy run and tell the operator to go restart a proxy that is fine.
|
|
75
|
+
*/
|
|
76
|
+
const UNREACHABLE_CODES = new Set([
|
|
77
|
+
'ECONNREFUSED',
|
|
78
|
+
'ENOTFOUND',
|
|
79
|
+
'EAI_AGAIN',
|
|
80
|
+
'UND_ERR_CONNECT_TIMEOUT',
|
|
81
|
+
]);
|
|
82
|
+
/**
|
|
83
|
+
* True only when the endpoint could not be reached at all.
|
|
84
|
+
*
|
|
85
|
+
* Note the asymmetry with `isTransientNetworkError`: a bare
|
|
86
|
+
* `TypeError: fetch failed` with no cause code is NOT enough here. It is
|
|
87
|
+
* retryable (safe), but it does not say the listener is gone, and this
|
|
88
|
+
* predicate gates an abort.
|
|
89
|
+
*/
|
|
90
|
+
export function isEndpointUnreachable(err) {
|
|
91
|
+
if (!(err instanceof Error))
|
|
92
|
+
return false;
|
|
93
|
+
if (err.name === 'AbortError')
|
|
94
|
+
return false;
|
|
95
|
+
const cause = err.cause;
|
|
96
|
+
if (cause?.code && UNREACHABLE_CODES.has(cause.code))
|
|
97
|
+
return true;
|
|
98
|
+
const direct = err.code;
|
|
99
|
+
return Boolean(direct && UNREACHABLE_CODES.has(direct));
|
|
100
|
+
}
|
|
54
101
|
/** True for network-level failures worth retrying (never HTTP responses). */
|
|
55
102
|
export function isTransientNetworkError(err) {
|
|
56
103
|
if (!(err instanceof Error))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"long-fetch.js","sourceRoot":"","sources":["../../src/models/long-fetch.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"long-fetch.js","sourceRoot":"","sources":["../../src/models/long-fetch.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,6 +21,15 @@
|
|
|
21
21
|
export type ToolOutcomeClass =
|
|
22
22
|
/** Call succeeded with no caveat. */
|
|
23
23
|
'ok'
|
|
24
|
+
/**
|
|
25
|
+
* The call was accepted but changed NOTHING — a write or edit whose result
|
|
26
|
+
* already matched the file. Neither a success nor a failure: the tool did
|
|
27
|
+
* exactly what it was told, and the turn made no progress. It gets its own
|
|
28
|
+
* class because folding it into `ok` is what the no-op guards exist to stop —
|
|
29
|
+
* the corpus would report edit tooling as healthy precisely while a run is
|
|
30
|
+
* spinning on repeated no-op edits.
|
|
31
|
+
*/
|
|
32
|
+
| 'no-op'
|
|
24
33
|
/** Succeeded, but only via the whitespace-tolerant edit rung (anchor drift). */
|
|
25
34
|
| 'ok-tolerant'
|
|
26
35
|
/** `old_string` matched nothing. The dominant edit-tool failure. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-failure.d.ts","sourceRoot":"","sources":["../../src/telemetry/tool-failure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;GAGG;AACH,MAAM,MAAM,gBAAgB;AAC1B,qCAAqC;AACnC,IAAI;AACN,gFAAgF;GAC9E,aAAa;AACf,oEAAoE;GAClE,WAAW;AACb,sEAAsE;GACpE,gBAAgB;AAClB,oDAAoD;GAClD,eAAe;AACjB,sCAAsC;GACpC,gBAAgB;AAClB,qCAAqC;GACnC,aAAa;AACf,wEAAwE;GACtE,gBAAgB;AAClB,uEAAuE;GACrE,cAAc;AAChB,4CAA4C;GAC1C,iBAAiB;AACnB,gDAAgD;GAC9C,gBAAgB;AAClB,qCAAqC;GACnC,SAAS;AACX,kDAAkD;GAChD,cAAc;AAChB,iFAAiF;GAC/E,SAAS;AACX,uEAAuE;GACrE,iBAAiB;AACnB,gDAAgD;GAC9C,aAAa,CAAC;AAElB,kFAAkF;AAClF,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;AAoB1F,wBAAgB,cAAc,CAAC,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAE3D;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,
|
|
1
|
+
{"version":3,"file":"tool-failure.d.ts","sourceRoot":"","sources":["../../src/telemetry/tool-failure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;GAGG;AACH,MAAM,MAAM,gBAAgB;AAC1B,qCAAqC;AACnC,IAAI;AACN;;;;;;;GAOG;GACD,OAAO;AACT,gFAAgF;GAC9E,aAAa;AACf,oEAAoE;GAClE,WAAW;AACb,sEAAsE;GACpE,gBAAgB;AAClB,oDAAoD;GAClD,eAAe;AACjB,sCAAsC;GACpC,gBAAgB;AAClB,qCAAqC;GACnC,aAAa;AACf,wEAAwE;GACtE,gBAAgB;AAClB,uEAAuE;GACrE,cAAc;AAChB,4CAA4C;GAC1C,iBAAiB;AACnB,gDAAgD;GAC9C,gBAAgB;AAClB,qCAAqC;GACnC,SAAS;AACX,kDAAkD;GAChD,cAAc;AAChB,iFAAiF;GAC/E,SAAS;AACX,uEAAuE;GACrE,iBAAiB;AACnB,gDAAgD;GAC9C,aAAa,CAAC;AAElB,kFAAkF;AAClF,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;AAoB1F,wBAAgB,cAAc,CAAC,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAE3D;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAoDjF;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAc/D"}
|
|
@@ -66,6 +66,10 @@ export function classifyToolResult(tool, result) {
|
|
|
66
66
|
return lower.startsWith('error:') ? 'other-error' : 'ok';
|
|
67
67
|
}
|
|
68
68
|
if (!lower.startsWith('error:')) {
|
|
69
|
+
// Checked BEFORE the tolerant note: a no-op reached through the tolerant
|
|
70
|
+
// rung still changed nothing, and "no progress" is the more important fact.
|
|
71
|
+
if (lower.startsWith('no-op:'))
|
|
72
|
+
return 'no-op';
|
|
69
73
|
// Success paths. The tolerant-match note is a success WITH a signal: the
|
|
70
74
|
// model's anchors are drifting, which predicts future misses.
|
|
71
75
|
if (lower.includes('did not match byte-for-byte'))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-failure.js","sourceRoot":"","sources":["../../src/telemetry/tool-failure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"tool-failure.js","sourceRoot":"","sources":["../../src/telemetry/tool-failure.ts"],"names":[],"mappings":"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"}
|
package/docs/reference/CLI.md
CHANGED
|
@@ -398,8 +398,12 @@ uap deliver --await-run --await-timeout 45 # one poll, then report and return
|
|
|
398
398
|
|
|
399
399
|
Exit codes for `--await-run` are distinct because three of the four outcomes are
|
|
400
400
|
not failures: **0** delivered · **1** the mission ended badly · **3** nothing was
|
|
401
|
-
running
|
|
402
|
-
|
|
401
|
+
running *on this root* · **4** still running — the wait gave up, the mission did
|
|
402
|
+
not.
|
|
403
|
+
|
|
404
|
+
A **3** normally means "safe to launch". The exception is a launch that was just
|
|
405
|
+
refused because an *overlapping* root holds the run: follow that root instead —
|
|
406
|
+
this one has nothing in flight and will keep answering 3.
|
|
403
407
|
|
|
404
408
|
A `4` carries a `progress` object so consecutive polls can be compared. Always
|
|
405
409
|
present: `heartbeatAgeSec`, `wedgeAfterSec`, `health`. Present only when the run
|
|
@@ -417,6 +421,13 @@ asserted:
|
|
|
417
421
|
- `"wedged"` — silent past `UAP_DELIVER_WEDGE_TIMEOUT` (default 1800s, shared
|
|
418
422
|
with the autoroute hook) and may be stuck.
|
|
419
423
|
|
|
424
|
+
Single-flight is a property of the **subtree**, not of the lock path. A run also
|
|
425
|
+
exits early when an older live run holds an *overlapping* (nested or identical)
|
|
426
|
+
project root: `repo` and `repo/src/ext` edit the same files even though their
|
|
427
|
+
`.uap/deliver.lock` paths differ. The refusal names the holder's root — follow
|
|
428
|
+
*that* root, because following your own reports nothing in flight. Live runs
|
|
429
|
+
register in `~/.uap/active-runs` (redirect with `UAP_ACTIVE_RUNS_DIR`).
|
|
430
|
+
|
|
420
431
|
A wedged **lock** holder is reclaimed by the next launch. A resumed run holds no
|
|
421
432
|
lock, so relaunching there does not reclaim it — it starts a second mission on
|
|
422
433
|
the same tree; keep following instead. Never kill a deliver run by hand: that
|
|
@@ -81,6 +81,8 @@ Top level: `version`, `project`, `memory`, `worktree`, `costOptimization`,
|
|
|
81
81
|
| `UAP_DELIVER_AUTO` | `0` disables auto-deliver | enabled |
|
|
82
82
|
| `UAP_DELIVER_UNTIL_DELIVERED` | `0` disables loop-until-delivered | enabled |
|
|
83
83
|
| `UAP_DELIVER_SANDBOX` | Deliver sandbox root path | — |
|
|
84
|
+
| `UAP_ACTIVE_RUNS_DIR` | Registry of live deliver runs, used for cross-root (nested-project) single-flight | `~/.uap/active-runs` |
|
|
85
|
+
| `UAP_DELIVER_NO_LOCK` | `1` disables the per-project lock **and** the overlapping-root check; the run also becomes invisible to other runs' checks | enabled |
|
|
84
86
|
| `UAP_HALO_TRACE` | `1` enables HALO tracing | off |
|
|
85
87
|
| `UAP_HALO_TRACE_PATH` | HALO trace output file | `.uap/halo/traces.jsonl` |
|
|
86
88
|
| `UAP_HALO_PROJECT_ID` | HALO project id | `uap` |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@miller-tech/uap",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.187.3",
|
|
4
4
|
"description": "Autonomous AI agent memory system with CLAUDE.md protocol enforcement",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"install:web": "bash scripts/setup/install-web.sh",
|
|
32
32
|
"install:desktop": "bash scripts/setup/install-desktop.sh",
|
|
33
33
|
"install:cloakbrowser": "tsx scripts/setup/install-cloakbrowser.ts",
|
|
34
|
-
"postinstall": "echo '\n
|
|
34
|
+
"postinstall": "echo '\n✨ Run: npx @miller-tech/uap init --interactive'",
|
|
35
35
|
"version:patch": "bash scripts/version-bump.sh patch",
|
|
36
36
|
"version:minor": "bash scripts/version-bump.sh minor",
|
|
37
37
|
"version:major": "bash scripts/version-bump.sh major",
|
|
Binary file
|
|
@@ -246,6 +246,18 @@ def _laundered_infra_kill(cmd: str) -> bool:
|
|
|
246
246
|
# exists to prevent. delivery_enforcement._deliver_lock_holder() has taken the
|
|
247
247
|
# same precaution since the PID-reuse incident; this must not diverge from it.
|
|
248
248
|
_PID_TOKEN_RE = re.compile(r"(?<![\w.])(-?\d{1,10})(?![\w.-])")
|
|
249
|
+
# The label both deliver paths agree on, so the caller has one thing to compare.
|
|
250
|
+
DELIVER_LABEL = "the deliver run in progress"
|
|
251
|
+
|
|
252
|
+
# A deliver PROCESS, by argv. Deliberately separate from _STACK_ARGV_RE: a
|
|
253
|
+
# deliver run is protected for a different reason than llama-server, and gets a
|
|
254
|
+
# different remedy, so the two must not be told apart by string-matching the
|
|
255
|
+
# combined pattern's output.
|
|
256
|
+
_DELIVER_ARGV_RE = re.compile(
|
|
257
|
+
r"(\buap\s+deliver\b|(?:cli\.js|uap)\s+(?:\S+\s+)*deliver\b)",
|
|
258
|
+
re.IGNORECASE,
|
|
259
|
+
)
|
|
260
|
+
|
|
249
261
|
_STACK_ARGV_RE = re.compile(
|
|
250
262
|
r"(llama-server|anthropic_proxy|nomic-embed"
|
|
251
263
|
r"|\buap\s+deliver\b|(?:cli\.js|uap)\s+(?:\S+\s+)*deliver\b)",
|
|
@@ -276,7 +288,7 @@ def _lock_holder_pids() -> dict[str, str]:
|
|
|
276
288
|
continue
|
|
277
289
|
m = re.match(r"\s*(\d+)", text)
|
|
278
290
|
if m:
|
|
279
|
-
holders[str(int(m.group(1)))] =
|
|
291
|
+
holders[str(int(m.group(1)))] = DELIVER_LABEL
|
|
280
292
|
return holders
|
|
281
293
|
|
|
282
294
|
|
|
@@ -293,14 +305,61 @@ def _identify_pid(pid: str, holders: dict[str, str]) -> str | None:
|
|
|
293
305
|
return None # dead: a stale lock protects nothing
|
|
294
306
|
m = _STACK_ARGV_RE.search(argv)
|
|
295
307
|
if pid in holders:
|
|
296
|
-
# Confirm identity too — a recycled PID must not inherit the claim.
|
|
297
|
-
|
|
298
|
-
|
|
308
|
+
# Confirm identity too — a recycled PID must not inherit the claim. The
|
|
309
|
+
# claim is "this is the deliver run", so confirm it with the DELIVER
|
|
310
|
+
# pattern: checking the combined stack pattern let a stale lock whose
|
|
311
|
+
# PID had been recycled by llama-server inherit the deliver label, and
|
|
312
|
+
# with it a remedy that does not apply to the stack.
|
|
313
|
+
if _DELIVER_ARGV_RE.search(argv):
|
|
314
|
+
return holders[pid]
|
|
315
|
+
return m.group(1).lower() if m else None
|
|
316
|
+
if not m:
|
|
317
|
+
return None
|
|
318
|
+
# Canonicalise a deliver match to the SAME label the lock-holder path uses.
|
|
319
|
+
# Without this the caller fell through to the inference-stack message, which
|
|
320
|
+
# told the operator that killing their own mission "ends your own session"
|
|
321
|
+
# and pointed at llama-server / the proxy — none of which is true. The
|
|
322
|
+
# lock-holder path only fires when the lock is under THIS repo, so any
|
|
323
|
+
# deliver launched against another project (the usual case) got the wrong
|
|
324
|
+
# message and the wrong remedy.
|
|
325
|
+
if _DELIVER_ARGV_RE.search(argv):
|
|
326
|
+
return DELIVER_LABEL
|
|
327
|
+
return m.group(1).lower()
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
_PROBE_RE = re.compile(r"\bkill\b\s+(?:-0\b|-s\s+0\b|-s\s+SIGNULL\b)", re.IGNORECASE)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def _only_liveness_probes(text: str) -> bool:
|
|
334
|
+
"""True when EVERY kill in `text` is `kill -0` / `kill -s 0` — a probe.
|
|
335
|
+
|
|
336
|
+
Signal 0 performs error checking only: it tests whether the PID exists and
|
|
337
|
+
is signalable, and delivers nothing. Refusing it protects nothing and denies
|
|
338
|
+
the cheapest way to ask "is that run still alive?".
|
|
339
|
+
|
|
340
|
+
Scoped per STATEMENT, and deliberately so. Testing the whole command instead
|
|
341
|
+
let one probe anywhere switch rule 9 off for every PID in the text, so
|
|
342
|
+
`kill -0 $P && kill -9 $P` — the canonical "kill it if it is alive" idiom,
|
|
343
|
+
and the `if kill -0 …; then kill -9 …; fi` form — reached the stack. Rule 9
|
|
344
|
+
is the ONLY guard on a bare-PID kill (rules 1-8 all need pkill/killall, a
|
|
345
|
+
service name, a -f pattern or a lookup verb), so a whole-text exemption
|
|
346
|
+
turned this module's one un-spell-around-able rule into a text rule whose
|
|
347
|
+
password was two characters. Measured before the fix: all four laundering
|
|
348
|
+
spellings were allowed.
|
|
349
|
+
"""
|
|
350
|
+
kills = [
|
|
351
|
+
seg for seg in _STATEMENT_SPLIT_RE.split(text) if _KILL_VERB_RE.search(seg)
|
|
352
|
+
]
|
|
353
|
+
if not kills:
|
|
354
|
+
return False
|
|
355
|
+
return all(_PROBE_RE.search(seg) for seg in kills)
|
|
299
356
|
|
|
300
357
|
|
|
301
358
|
def _protected_pid_hit(text: str) -> tuple[str, str] | None:
|
|
302
359
|
if not (_KILL_VERB_RE.search(text) and _PID_TOKEN_RE.search(text)):
|
|
303
360
|
return None
|
|
361
|
+
if _only_liveness_probes(text):
|
|
362
|
+
return None
|
|
304
363
|
holders = _lock_holder_pids()
|
|
305
364
|
seen: set[str] = set()
|
|
306
365
|
for m in _PID_TOKEN_RE.finditer(text):
|
|
@@ -325,6 +384,10 @@ DELIVER_PID_REASON = (
|
|
|
325
384
|
"call the deliver tool with follow:true, which answers within about a "
|
|
326
385
|
"minute; a 'STILL RUNNING' answer is normal and means keep polling, not "
|
|
327
386
|
"fail. From a shell, `uap deliver --await-run` blocks until the run ends. "
|
|
387
|
+
"If it genuinely must stop, do NOT kill it: request the COOPERATIVE stop "
|
|
388
|
+
"(the dashboard's Cancel, or `touch <projectRoot>/.uap/deliver-runs/<runId>/STOP`) — "
|
|
389
|
+
"the loop observes it at the next turn boundary and exits with its work "
|
|
390
|
+
"checkpointed and the lock released, which a signal does not. "
|
|
328
391
|
"Operator override: set UAP_INFRA_PROTECT_OFF=1 in the launch environment "
|
|
329
392
|
"(not inline on the command)."
|
|
330
393
|
)
|
|
@@ -438,7 +501,7 @@ def main() -> None:
|
|
|
438
501
|
hit = _protected_pid_hit(text)
|
|
439
502
|
if hit:
|
|
440
503
|
pid, what = hit
|
|
441
|
-
if what ==
|
|
504
|
+
if what == DELIVER_LABEL:
|
|
442
505
|
emit(False, DELIVER_PID_REASON.format(pid=pid) + label)
|
|
443
506
|
emit(False, STACK_PID_REASON.format(what=what, pid=pid) + label)
|
|
444
507
|
emit(True, "no infra-destructive pattern")
|
|
@@ -75,7 +75,27 @@ BYPASS_PATTERNS = (
|
|
|
75
75
|
# not an override — it is an off switch, the same reasoning as every entry
|
|
76
76
|
# above it.
|
|
77
77
|
re.compile(r"UAP_DELIVER_NO_LOCK\s*=\s*['\"]?1", re.I),
|
|
78
|
+
# The gateless-root refusal exists BECAUSE an agent-driven launch does not
|
|
79
|
+
# honour a warning: the warning shipped, fired, named the right root, and
|
|
80
|
+
# the run went ahead at the gateless root anyway, then spent 34 minutes
|
|
81
|
+
# taking a crate from 1 failing test to 3 while reporting "100% of gates".
|
|
82
|
+
# A hatch the constrained party can write into its own command line is not
|
|
83
|
+
# an override, it is an off switch — same reasoning as every entry above.
|
|
84
|
+
# The CLI-flag spelling is just as self-grantable, but it is matched
|
|
85
|
+
# separately below: a bare flag NAME appears in ordinary prose (docs,
|
|
86
|
+
# commit messages, `grep`), so scanning the raw command for it refused
|
|
87
|
+
# honest work. It runs against `scannable_command`, which blanks quoted
|
|
88
|
+
# blobs, instead.
|
|
89
|
+
re.compile(r"UAP_ALLOW_GATELESS_ROOT\s*=\s*['\"]?1", re.I),
|
|
78
90
|
)
|
|
91
|
+
|
|
92
|
+
# The gateless-root override in its CLI-flag spelling. Anchored on both sides
|
|
93
|
+
# so a longer option that merely starts the same way does not collide, and
|
|
94
|
+
# case-sensitive because commander does not accept an upper-case spelling.
|
|
95
|
+
GATELESS_FLAG_RE = re.compile(r"(?:^|\s)--allow-gateless-root(?:[=\s]|$)")
|
|
96
|
+
# Only a deliver invocation can be bypassed by the flag. `\b` keeps this off
|
|
97
|
+
# `src/delivery/`, which merely starts with the same letters.
|
|
98
|
+
DELIVER_INVOCATION_RE = re.compile(r"\bdeliver\b")
|
|
79
99
|
# Destructive ops against the enforcer/policy surface.
|
|
80
100
|
#
|
|
81
101
|
# HONEST SCOPE: this is a NUDGE, not a boundary. An agent that can write a file
|
|
@@ -419,6 +439,22 @@ def main() -> None:
|
|
|
419
439
|
|
|
420
440
|
if op in {"Bash", "bash"}:
|
|
421
441
|
cmd = args.get("command") or ""
|
|
442
|
+
# The flag form is checked against the SCANNABLE command, not the raw
|
|
443
|
+
# one: `scannable_command` blanks multi-word quoted blobs, so a commit
|
|
444
|
+
# message or a `uap memory store "..."` that merely NAMES the switch is
|
|
445
|
+
# not refused, while text handed to a shell is left intact and still
|
|
446
|
+
# caught. It must ALSO look like a deliver invocation — the flag does
|
|
447
|
+
# nothing anywhere else, so refusing `rg -- <flag> src/` bought no
|
|
448
|
+
# security and blocked someone auditing the switch.
|
|
449
|
+
_scannable = scannable_command(cmd)
|
|
450
|
+
if GATELESS_FLAG_RE.search(_scannable) and DELIVER_INVOCATION_RE.search(_scannable):
|
|
451
|
+
emit(
|
|
452
|
+
False,
|
|
453
|
+
"BLOCKED: setting a delivery-enforcement bypass/advisory flag is "
|
|
454
|
+
"not allowed for the agent. Route your change through the "
|
|
455
|
+
"`deliver` tool instead of disabling the gate. "
|
|
456
|
+
"(Operator-only override: UAP_SELF_PROTECT_OFF=1.)",
|
|
457
|
+
)
|
|
422
458
|
for pat in BYPASS_PATTERNS:
|
|
423
459
|
if pat.search(cmd):
|
|
424
460
|
emit(
|
|
Binary file
|
|
@@ -122,8 +122,16 @@ if echo "$CMD" | grep -qE '\bgit\s+reset\s+--hard\b|\bgit\s+clean\s+-[a-z]*f'; t
|
|
|
122
122
|
fi
|
|
123
123
|
|
|
124
124
|
# ─── Manual Version Edit Protection ─────────────────────────────
|
|
125
|
-
# Block direct edits to package.json version field via sed/awk
|
|
126
|
-
|
|
125
|
+
# Block direct edits to package.json version field via sed/awk/jq.
|
|
126
|
+
#
|
|
127
|
+
# Scoped to a single shell STATEMENT. Matching across the whole command line
|
|
128
|
+
# meant any sed/awk anywhere plus `package.json` and `version` anywhere later
|
|
129
|
+
# tripped it, so reading the version alongside unrelated text munging was
|
|
130
|
+
# refused: `curl ... | sed 's/^/x/'; node -p "require('./package.json').version"`
|
|
131
|
+
# That is a READ. Splitting on ; && || | and newline keeps every real edit
|
|
132
|
+
# (each has sed/awk/jq and package.json inside one statement) and drops the
|
|
133
|
+
# cross-statement coincidence. Verified against both corpora before and after.
|
|
134
|
+
if printf '%s' "$CMD" | tr ';|&\n' '\n\n\n\n' | grep -qE "(sed|awk).*package\.json.*(version|\"version\")|((sed|awk).*version.*package\.json)|(jq.*\.version.*package\.json)"; then
|
|
127
135
|
echo "BLOCKED [semver-versioning]: Manual package.json version edits are prohibited. Use: npm run version:patch, version:minor, or version:major. See policies/semver-versioning.md" >&2
|
|
128
136
|
exit 2
|
|
129
137
|
fi
|
|
@@ -169,7 +169,10 @@ if not hit and cmd:
|
|
|
169
169
|
break
|
|
170
170
|
bypass = re.search(
|
|
171
171
|
r"UAP_DELIVER_BYPASS\s*=\s*[\x27\"]?1|UAP_ENFORCE_DELIVERY\s*=\s*[\x27\"]?(advisory|off|0|false|no)"
|
|
172
|
-
r"|UAP_SELF_PROTECT_OFF\s*=\s*[\x27\"]?1|UAP_NO_WORKTREE\s*=\s*[\x27\"]?1
|
|
172
|
+
r"|UAP_SELF_PROTECT_OFF\s*=\s*[\x27\"]?1|UAP_NO_WORKTREE\s*=\s*[\x27\"]?1"
|
|
173
|
+
r"|UAP_WORKDIR_SCOPE_OFF\s*=\s*[\x27\"]?1|UAP_USER_VALIDATION\s*=\s*[\x27\"]?0"
|
|
174
|
+
r"|UAP_DELIVER_NO_LOCK\s*=\s*[\x27\"]?1|UAP_NO_REVIEW\s*=\s*[\x27\"]?1"
|
|
175
|
+
r"|UAP_INFRA_PROTECT_OFF\s*=\s*[\x27\"]?1|UAP_ALLOW_GATELESS_ROOT\s*=\s*[\x27\"]?1",
|
|
173
176
|
cmd, re.I)
|
|
174
177
|
print("1" if (hit or bypass) else "0")
|
|
175
178
|
' 2>/dev/null || echo 1)"
|