@miller-tech/uap 1.147.1 → 1.147.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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/config/policy-recommendations.js +2 -2
- package/dist/config/policy-recommendations.js.map +1 -1
- package/package.json +1 -1
- package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
- package/src/policies/enforcers/local_build_before_push.py +5 -2
- package/src/policies/enforcers/memory_before_plan.py +1 -1
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
- package/src/policies/enforcers/validate_plan_before_build.py +0 -75
- package/src/policies/schemas/policies/validate-plan-before-build.md +0 -28
|
@@ -26,7 +26,7 @@ export const SCENARIOS = [
|
|
|
26
26
|
blurb: 'One person driving a local (llama.cpp/Qwen) model that needs strong guardrails.',
|
|
27
27
|
extra: [
|
|
28
28
|
{ slug: 'codebase-read-before-plan', why: 'weaker models must read before proposing' },
|
|
29
|
-
{ slug: 'validate-plan-
|
|
29
|
+
{ slug: 'validate-plan-on-change', why: 'catch a bad plan before it writes code' },
|
|
30
30
|
{ slug: 'mcp-router-first', why: 'keeps the context window lean for a small model' },
|
|
31
31
|
{ slug: 'local-build-before-push', why: 'never push code that fails to build locally' },
|
|
32
32
|
{ slug: 'ship-loop-gate', why: 'converge to green before shipping' },
|
|
@@ -61,7 +61,7 @@ export const SCENARIOS = [
|
|
|
61
61
|
title: 'High autonomy / hands-free',
|
|
62
62
|
blurb: 'Long unattended builds where the model must not cut corners.',
|
|
63
63
|
extra: [
|
|
64
|
-
{ slug: 'validate-plan-
|
|
64
|
+
{ slug: 'validate-plan-on-change', why: 'a wrong plan wastes an entire autonomous run' },
|
|
65
65
|
{ slug: 'ship-loop-gate', why: 'the run only ends when the work is genuinely done' },
|
|
66
66
|
{ slug: 'artifact-hygiene', why: 'unattended runs must not leave debris' },
|
|
67
67
|
{ slug: 'doc-live-over-report', why: "grade the real system, not the model's optimism" },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policy-recommendations.js","sourceRoot":"","sources":["../../src/config/policy-recommendations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAeH,wDAAwD;AACxD,MAAM,CAAC,MAAM,IAAI,GAAyB;IACxC,EAAE,IAAI,EAAE,mBAAmB,EAAE,GAAG,EAAE,4DAA4D,EAAE;IAChG,EAAE,IAAI,EAAE,sBAAsB,EAAE,GAAG,EAAE,wDAAwD,EAAE;IAC/F,EAAE,IAAI,EAAE,0BAA0B,EAAE,GAAG,EAAE,qDAAqD,EAAE;IAChG,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,4CAA4C,EAAE;IAC5E,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,4CAA4C,EAAE;IACxE,EAAE,IAAI,EAAE,oBAAoB,EAAE,GAAG,EAAE,2DAA2D,EAAE;IAChG,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,+CAA+C,EAAE;CAChF,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAwB;IAC5C;QACE,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,uBAAuB;QAC9B,KAAK,EAAE,iFAAiF;QACxF,KAAK,EAAE;YACL,EAAE,IAAI,EAAE,2BAA2B,EAAE,GAAG,EAAE,0CAA0C,EAAE;YACtF,EAAE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"policy-recommendations.js","sourceRoot":"","sources":["../../src/config/policy-recommendations.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
Binary file
|
|
@@ -25,7 +25,7 @@ import sys
|
|
|
25
25
|
from pathlib import Path
|
|
26
26
|
|
|
27
27
|
sys.path.insert(0, str(Path(__file__).parent))
|
|
28
|
-
from _common import emit, parse_cli,
|
|
28
|
+
from _common import emit, parse_cli, worktree_root, run # noqa: E402
|
|
29
29
|
|
|
30
30
|
MARKER = ".uap/local-build-pass.txt"
|
|
31
31
|
|
|
@@ -80,7 +80,10 @@ def main() -> None:
|
|
|
80
80
|
if os.environ.get("UAP_SKIP_LOCAL_BUILD") == "1":
|
|
81
81
|
emit(True, "UAP_SKIP_LOCAL_BUILD=1 override (justify in commit msg)")
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
# The push happens from the WORKING TREE the op runs in (the worktree when a
|
|
84
|
+
# push runs from inside one), not the pinned main checkout — mirror the
|
|
85
|
+
# expert-review fix so the changed-files diff targets the right branch.
|
|
86
|
+
root = worktree_root()
|
|
84
87
|
|
|
85
88
|
changed = _changed_files(root)
|
|
86
89
|
needs_build = any(
|
|
@@ -11,7 +11,7 @@ sys.path.insert(0, str(Path(__file__).parent))
|
|
|
11
11
|
from _common import arg_str, emit, parse_cli, repo_root # noqa: E402
|
|
12
12
|
|
|
13
13
|
PLAN_OPS = {"ExitPlanMode", "Plan", "TodoWrite", "plan", "design"}
|
|
14
|
-
# Only match standalone words, not compounds like 'validate-plan-
|
|
14
|
+
# Only match standalone words, not compounds like 'validate-plan-on-change'
|
|
15
15
|
PLAN_WORD_RE = re.compile(r"(?<![-\w/])(plan the|design the|architect the|propose a plan|roadmap for)", re.I)
|
|
16
16
|
RECENT_SEC = 300
|
|
17
17
|
|
|
Binary file
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""validate-plan-before-build enforcer.
|
|
3
|
-
|
|
4
|
-
On the first mutating tool call after a plan is marked ready, block and require
|
|
5
|
-
the agent to run the `validate the plan` prompt. State tracked in .uap/plan_state.json.
|
|
6
|
-
"""
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
import json
|
|
9
|
-
import os
|
|
10
|
-
import sys
|
|
11
|
-
import time
|
|
12
|
-
from pathlib import Path
|
|
13
|
-
|
|
14
|
-
sys.path.insert(0, str(Path(__file__).parent))
|
|
15
|
-
from _common import emit, parse_cli # noqa: E402
|
|
16
|
-
|
|
17
|
-
STATE = Path(os.environ.get("UAP_STATE_DIR", ".uap")) / "plan_state.json"
|
|
18
|
-
MUTATING_OPS = {"Edit", "Write", "MultiEdit", "edit", "write", "multiedit"}
|
|
19
|
-
BUILD_BASH_RE = (
|
|
20
|
-
"git commit",
|
|
21
|
-
"git push",
|
|
22
|
-
"kubectl apply",
|
|
23
|
-
"helm upgrade",
|
|
24
|
-
"helm install",
|
|
25
|
-
"terraform apply",
|
|
26
|
-
"npm run build",
|
|
27
|
-
"pnpm build",
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def load_state() -> dict:
|
|
32
|
-
if not STATE.exists():
|
|
33
|
-
return {}
|
|
34
|
-
try:
|
|
35
|
-
return json.loads(STATE.read_text())
|
|
36
|
-
except json.JSONDecodeError:
|
|
37
|
-
return {}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def save_state(s: dict) -> None:
|
|
41
|
-
STATE.parent.mkdir(parents=True, exist_ok=True)
|
|
42
|
-
STATE.write_text(json.dumps(s))
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def main() -> None:
|
|
46
|
-
op, args = parse_cli()
|
|
47
|
-
state = load_state()
|
|
48
|
-
|
|
49
|
-
# Mutating?
|
|
50
|
-
cmd = (args.get("command") or "").lower()
|
|
51
|
-
mutating = op in MUTATING_OPS or any(p in cmd for p in BUILD_BASH_RE)
|
|
52
|
-
if not mutating:
|
|
53
|
-
emit(True, "not a build/mutation op")
|
|
54
|
-
|
|
55
|
-
plan_ready = bool(state.get("plan_ready"))
|
|
56
|
-
validated_at = float(state.get("validated_at", 0))
|
|
57
|
-
ready_at = float(state.get("ready_at", 0))
|
|
58
|
-
|
|
59
|
-
if not plan_ready:
|
|
60
|
-
emit(True, "no active plan-ready marker")
|
|
61
|
-
|
|
62
|
-
if validated_at and validated_at >= ready_at:
|
|
63
|
-
emit(True, "plan validated since marking ready")
|
|
64
|
-
|
|
65
|
-
emit(
|
|
66
|
-
False,
|
|
67
|
-
"validate-plan-before-build: plan is ready but not validated. "
|
|
68
|
-
"Run the prompt `validate the plan` before making changes. "
|
|
69
|
-
"After a pass, write {\"validated_at\": <epoch>} to .uap/plan_state.json.",
|
|
70
|
-
inject_prompt="validate the plan",
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if __name__ == "__main__":
|
|
75
|
-
main()
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# validate-plan-before-build
|
|
2
|
-
|
|
3
|
-
**Category**: workflow
|
|
4
|
-
**Level**: REQUIRED
|
|
5
|
-
**Enforcement Stage**: pre-exec
|
|
6
|
-
**Tags**: planning, validation, accuracy
|
|
7
|
-
|
|
8
|
-
## Rule
|
|
9
|
-
|
|
10
|
-
When a plan is marked ready and the agent is about to begin implementation (first mutating tool call after plan emission: `Edit`, `Write`, `MultiEdit`, `Bash` that modifies state), the agent MUST first execute the prompt `validate the plan` and receive an explicit pass before proceeding.
|
|
11
|
-
|
|
12
|
-
A plan is "ready" when:
|
|
13
|
-
- User approves with "go", "build", "implement", "proceed", "ship it", "complete all", or similar
|
|
14
|
-
- OR the agent emits ExitPlanMode / transitions out of a Plan phase
|
|
15
|
-
|
|
16
|
-
## Why
|
|
17
|
-
|
|
18
|
-
User directive: "when a plan is ready to build, execute prompt 'validate the plan'". Prevents shipping on stale/unvalidated plans — catches last-mile gaps before code changes begin.
|
|
19
|
-
|
|
20
|
-
## Enforcement
|
|
21
|
-
|
|
22
|
-
Python enforcer `validate_plan_before_build.py` tracks plan-ready state in session memory; on first mutating tool call post-ready, blocks and injects the `validate the plan` prompt. Unblocks only after a validation result is recorded.
|
|
23
|
-
|
|
24
|
-
```rules
|
|
25
|
-
- title: "Ready plans require explicit validation"
|
|
26
|
-
keywords: [edit, write, multiedit, implement, build, ship, commit]
|
|
27
|
-
antiPatterns: [unvalidated-plan, skip-validation, plan-stale]
|
|
28
|
-
```
|