@miller-tech/uap 1.221.0 → 2.0.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 +19 -9
- package/config/exl3-profiles/qwen38-27b-exl3.env +68 -0
- package/config/llama-profiles/qwen38-27b-dflash2.env +6 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/benchmarks/paired/adapter.d.ts +15 -0
- package/dist/benchmarks/paired/adapter.d.ts.map +1 -1
- package/dist/benchmarks/paired/adapter.js +22 -1
- package/dist/benchmarks/paired/adapter.js.map +1 -1
- package/dist/bin/cli.js +20 -24
- package/dist/bin/cli.js.map +1 -1
- package/dist/cli/deliver.d.ts +34 -0
- package/dist/cli/deliver.d.ts.map +1 -1
- package/dist/cli/deliver.js +147 -20
- package/dist/cli/deliver.js.map +1 -1
- package/dist/cli/guided-setup.d.ts.map +1 -1
- package/dist/cli/guided-setup.js +15 -0
- package/dist/cli/guided-setup.js.map +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +3 -0
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/plan.d.ts.map +1 -1
- package/dist/cli/plan.js +8 -2
- package/dist/cli/plan.js.map +1 -1
- package/dist/cli/policy.d.ts.map +1 -1
- package/dist/cli/policy.js +104 -2
- package/dist/cli/policy.js.map +1 -1
- package/dist/cli/quality.d.ts +11 -0
- package/dist/cli/quality.d.ts.map +1 -0
- package/dist/cli/quality.js +213 -0
- package/dist/cli/quality.js.map +1 -0
- package/dist/cli/wizard-config.d.ts.map +1 -1
- package/dist/cli/wizard-config.js +19 -9
- package/dist/cli/wizard-config.js.map +1 -1
- package/dist/cli/worktree.d.ts.map +1 -1
- package/dist/cli/worktree.js +8 -1
- package/dist/cli/worktree.js.map +1 -1
- package/dist/dashboard/savings.d.ts +1 -4
- package/dist/dashboard/savings.d.ts.map +1 -1
- package/dist/dashboard/savings.js +2 -52
- package/dist/dashboard/savings.js.map +1 -1
- package/dist/delivery/acceptance-judge.d.ts +10 -0
- package/dist/delivery/acceptance-judge.d.ts.map +1 -1
- package/dist/delivery/acceptance-judge.js +45 -3
- package/dist/delivery/acceptance-judge.js.map +1 -1
- package/dist/delivery/agentic-executor.d.ts +12 -1
- package/dist/delivery/agentic-executor.d.ts.map +1 -1
- package/dist/delivery/agentic-executor.js +25 -5
- package/dist/delivery/agentic-executor.js.map +1 -1
- package/dist/delivery/bash-sweep.d.ts +12 -0
- package/dist/delivery/bash-sweep.d.ts.map +1 -1
- package/dist/delivery/bash-sweep.js +8 -1
- package/dist/delivery/bash-sweep.js.map +1 -1
- package/dist/delivery/convergence-loop.d.ts.map +1 -1
- package/dist/delivery/convergence-loop.js +6 -4
- package/dist/delivery/convergence-loop.js.map +1 -1
- package/dist/delivery/execution-gate.d.ts +1 -1
- package/dist/delivery/execution-gate.d.ts.map +1 -1
- package/dist/delivery/execution-gate.js +248 -5
- package/dist/delivery/execution-gate.js.map +1 -1
- package/dist/delivery/snapshot.d.ts +16 -0
- package/dist/delivery/snapshot.d.ts.map +1 -1
- package/dist/delivery/snapshot.js +113 -2
- package/dist/delivery/snapshot.js.map +1 -1
- package/dist/delivery/user-validation.d.ts.map +1 -1
- package/dist/delivery/user-validation.js +55 -10
- package/dist/delivery/user-validation.js.map +1 -1
- package/dist/delivery/verifier-ladder.d.ts +24 -0
- package/dist/delivery/verifier-ladder.d.ts.map +1 -1
- package/dist/delivery/verifier-ladder.js +119 -2
- package/dist/delivery/verifier-ladder.js.map +1 -1
- package/dist/delivery/visual-gate.d.ts +24 -0
- package/dist/delivery/visual-gate.d.ts.map +1 -1
- package/dist/delivery/visual-gate.js +70 -9
- package/dist/delivery/visual-gate.js.map +1 -1
- package/dist/generators/claude-md.js +17 -4
- package/dist/generators/claude-md.js.map +1 -1
- package/dist/policies/liveness.d.ts +105 -0
- package/dist/policies/liveness.d.ts.map +1 -0
- package/dist/policies/liveness.js +251 -0
- package/dist/policies/liveness.js.map +1 -0
- package/dist/policies/policy-memory.d.ts.map +1 -1
- package/dist/policies/policy-memory.js +3 -4
- package/dist/policies/policy-memory.js.map +1 -1
- package/dist/quality/baseline.d.ts +29 -0
- package/dist/quality/baseline.d.ts.map +1 -0
- package/dist/quality/baseline.js +79 -0
- package/dist/quality/baseline.js.map +1 -0
- package/dist/quality/complexity.d.ts +38 -0
- package/dist/quality/complexity.d.ts.map +1 -0
- package/dist/quality/complexity.js +239 -0
- package/dist/quality/complexity.js.map +1 -0
- package/dist/quality/config.d.ts +40 -0
- package/dist/quality/config.d.ts.map +1 -0
- package/dist/quality/config.js +77 -0
- package/dist/quality/config.js.map +1 -0
- package/dist/quality/crap.d.ts +11 -0
- package/dist/quality/crap.d.ts.map +1 -0
- package/dist/quality/crap.js +54 -0
- package/dist/quality/crap.js.map +1 -0
- package/dist/quality/languages.d.ts +25 -0
- package/dist/quality/languages.d.ts.map +1 -0
- package/dist/quality/languages.js +150 -0
- package/dist/quality/languages.js.map +1 -0
- package/dist/quality/report.d.ts +38 -0
- package/dist/quality/report.d.ts.map +1 -0
- package/dist/quality/report.js +251 -0
- package/dist/quality/report.js.map +1 -0
- package/dist/quality/scanner.d.ts +32 -0
- package/dist/quality/scanner.d.ts.map +1 -0
- package/dist/quality/scanner.js +127 -0
- package/dist/quality/scanner.js.map +1 -0
- package/dist/quality/tools.d.ts +28 -0
- package/dist/quality/tools.d.ts.map +1 -0
- package/dist/quality/tools.js +189 -0
- package/dist/quality/tools.js.map +1 -0
- package/dist/types/config.d.ts +148 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +35 -0
- package/dist/types/config.js.map +1 -1
- package/docs/ATTRIBUTION.md +0 -1
- package/docs/INDEX.md +38 -4
- package/docs/analysis/MARKET_POSITION.md +179 -0
- package/docs/architecture/OVERVIEW.md +82 -18
- package/docs/architecture/PROTOCOL.md +1 -1
- package/docs/benchmarks/PAIRED_FINDINGS.md +106 -0
- package/docs/benchmarks/PAIRED_HARNESS.md +16 -0
- package/docs/benchmarks/README.md +59 -0
- package/docs/design/UAP_REACTOR.md +0 -1
- package/docs/getting-started/INSTALLATION.md +1 -1
- package/docs/guides/AUTOMATIC.md +0 -14
- package/docs/guides/AUTOMATIC_FEATURES.md +1 -9
- package/docs/guides/COORDINATION.md +1 -1
- package/docs/guides/DELIVERY_PIPELINE.md +5 -0
- package/docs/guides/DEPLOY_BATCHING.md +1 -1
- package/docs/guides/DROIDS_AND_SKILLS.md +1 -1
- package/docs/guides/LOCAL_MODELS.md +6 -1
- package/docs/guides/MCP_ROUTER.md +1 -1
- package/docs/guides/MEMORY.md +1 -1
- package/docs/guides/MULTI_MODEL.md +1 -1
- package/docs/guides/ORCHESTRATOR.md +1 -1
- package/docs/guides/POLICIES.md +19 -3
- package/docs/guides/QWEN38_EXL3.md +114 -0
- package/docs/guides/WORKTREE_WORKFLOW.md +45 -1
- package/docs/integrations/MCP_ROUTER.md +1 -4
- package/docs/plans/deliver-hardening-plan-2026-07-13.md +173 -0
- package/docs/plans/deliver-hardening-review-response-2026-07-13.md +180 -0
- package/docs/plans/k3-uap-uplift-validation.md +216 -0
- package/docs/plans/qwen38-uap-retest-plan.md +196 -0
- package/docs/reference/API.md +1 -1
- package/docs/reference/CLI.md +49 -14
- package/docs/reference/COMPARISON.md +248 -0
- package/docs/reference/CONFIGURATION.md +1 -3
- package/docs/reference/DATABASE_SCHEMA.md +1 -1
- package/docs/reference/FEATURES.md +3 -3
- package/docs/reference/PATTERNS.md +1 -1
- package/docs/reference/PLATFORMS.md +1 -1
- package/package.json +2 -2
- package/scripts/maintenance/update-skills.py +0 -22
- package/scripts/maintenance/verify-compliance.sh +3 -3
- package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
- package/src/policies/enforcers/__pycache__/quality_metrics_gate.cpython-312.pyc +0 -0
- package/src/policies/enforcers/adr_guard.py +0 -0
- package/src/policies/enforcers/bearer_lockdown.py +0 -0
- package/src/policies/enforcers/branch_freshness.py +0 -0
- package/src/policies/enforcers/design_token_gate.py +0 -0
- package/src/policies/enforcers/enforcement_self_protect.py +70 -0
- package/src/policies/enforcers/expert_review_required.py +22 -0
- package/src/policies/enforcers/iac_plan_destruction_check.py +0 -0
- package/src/policies/enforcers/quality_metrics_gate.py +447 -0
- package/src/policies/enforcers/ship_loop_gate.py +0 -0
- package/src/policies/enforcers/validate_plan_on_change.py +0 -0
- package/src/policies/enforcers/visual_verification.py +0 -0
- package/src/policies/enforcers/workdir_scope.py +0 -0
- package/src/policies/schemas/policies/expert-review-required.md +9 -1
- package/src/policies/schemas/policies/quality-metrics-gate.md +74 -0
- package/templates/CLAUDE.template.md +1 -1
- package/templates/hooks/__pycache__/deliver_autoroute.cpython-312.pyc +0 -0
- package/templates/hooks/pre-tool-use-bash.sh +50 -3
- package/templates/hooks/pre-tool-use-edit-write.sh +31 -0
- package/templates/hooks/session-start.sh +15 -0
- package/templates/hooks/uap-policy-gate.sh +187 -5
- package/templates/stryker.config.json +14 -0
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
- package/tools/agents/scripts/anthropic_proxy.py +254 -28
- package/tools/agents/tests/run_acceptance.py +0 -0
- package/tools/agents/tests/test_client_disconnect.py +0 -0
- package/tools/agents/tests/test_cycle_break_exploration.py +0 -0
- package/tools/agents/tests/test_deferral_break.py +0 -0
- package/tools/agents/tests/test_delivery_enforcement_all_langs.py +0 -0
- package/tools/agents/tests/test_delivery_enforcement_exemptions.py +0 -0
- package/tools/agents/tests/test_delivery_enforcement_filepath.py +0 -0
- package/tools/agents/tests/test_delivery_enforcement_web_and_bash.py +0 -0
- package/tools/agents/tests/test_delivery_enforcement_worktree.py +0 -0
- package/tools/agents/tests/test_delivery_enforcement_write_complexity.py +0 -0
- package/tools/agents/tests/test_disconnect_watcher.py +0 -0
- package/tools/agents/tests/test_doubling_break.py +0 -0
- package/tools/agents/tests/test_empty_maxtokens_recovery.py +0 -0
- package/tools/agents/tests/test_empty_tool_loop_break.py +0 -0
- package/tools/agents/tests/test_enforcement_self_protect.py +90 -0
- package/tools/agents/tests/test_enforcer_escape_hatches.py +0 -0
- package/tools/agents/tests/test_error_loop_break.py +0 -0
- package/tools/agents/tests/test_expert_review_pr_scope.py +13 -5
- package/tools/agents/tests/test_fastpath_config.py +0 -0
- package/tools/agents/tests/test_finalize_suppression.py +0 -0
- package/tools/agents/tests/test_gate_evidence.py +0 -0
- package/tools/agents/tests/test_gate_failclosed_indirection.py +0 -0
- package/tools/agents/tests/test_gate_integrity.py +0 -0
- package/tools/agents/tests/test_live_deliver_kill.py +0 -0
- package/tools/agents/tests/test_malformed_unclosed_think.py +0 -0
- package/tools/agents/tests/test_mandate_beats_recon.py +0 -0
- package/tools/agents/tests/test_mandate_deliver.py +0 -0
- package/tools/agents/tests/test_non_stream_resp_log.py +0 -0
- package/tools/agents/tests/test_output_token_ceilings.py +0 -0
- package/tools/agents/tests/test_overflow_truncate_count_tokens.py +0 -0
- package/tools/agents/tests/test_path_containment.py +0 -0
- package/tools/agents/tests/test_path_normalizer_hardened.py +0 -0
- package/tools/agents/tests/test_repeat_call_guard.py +0 -0
- package/tools/agents/tests/test_repeat_guard.py +0 -0
- package/tools/agents/tests/test_session_admission.py +0 -0
- package/tools/agents/tests/test_stream_heartbeat.py +0 -0
- package/tools/agents/tests/test_stream_thinking_deltas.py +405 -0
- package/tools/agents/tests/test_stuck_break_hard.py +0 -0
- package/tools/agents/tests/test_stuck_break_reattach.py +0 -0
- package/tools/agents/tests/test_turn_count_breaker_periodic.py +0 -0
- package/tools/agents/tests/test_upstream_chokepoint.py +0 -0
- package/tools/agents/tests/test_upstream_model_aliases.py +0 -0
- package/tools/agents/tests/test_validate_plan_gate.py +0 -0
- package/tools/agents/tests/test_vision_passthrough.py +0 -0
- package/tools/agents/tests/test_workdir_scope_enforcer.py +0 -0
- package/dist/cli/rtk.d.ts +0 -34
- package/dist/cli/rtk.d.ts.map +0 -1
- package/dist/cli/rtk.js +0 -401
- package/dist/cli/rtk.js.map +0 -1
- package/docs/integrations/RTK.md +0 -113
- package/scripts/setup/install-rtk.sh +0 -184
- package/src/policies/enforcers/rtk_wrap.py +0 -205
- package/src/policies/schemas/policies/rtk-wrap.md +0 -50
- package/tools/agents/tests/test_rtk_wrap.py +0 -151
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@miller-tech/uap",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Autonomous AI agent memory system with CLAUDE.md protocol enforcement",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"start": "node dist/bin/cli.js",
|
|
22
22
|
"test": "vitest",
|
|
23
23
|
"test:ci": "vitest run",
|
|
24
|
-
"test:enforcers": "UAP_PROXY_ENV_AUTOLOAD=0 python3 -m unittest tools.agents.tests.test_enforcement_self_protect tools.agents.tests.test_conditional_destructive_verbs tools.agents.tests.test_live_deliver_kill tools.agents.tests.test_schema_diff_gate tools.agents.tests.test_schema_diff_inline tools.agents.tests.test_stream_telemetry tools.agents.tests.test_project_telemetry_events tools.agents.tests.test_workdir_scope_enforcer tools.agents.tests.test_gate_evidence tools.agents.tests.test_repeat_call_guard tools.agents.tests.test_repeat_guard tools.agents.tests.test_gate_integrity tools.agents.tests.test_gate_failclosed_indirection tools.agents.tests.test_gate_failclosed_schema_diff tools.agents.tests.
|
|
24
|
+
"test:enforcers": "UAP_PROXY_ENV_AUTOLOAD=0 python3 -m unittest tools.agents.tests.test_enforcement_self_protect tools.agents.tests.test_conditional_destructive_verbs tools.agents.tests.test_live_deliver_kill tools.agents.tests.test_schema_diff_gate tools.agents.tests.test_schema_diff_inline tools.agents.tests.test_stream_telemetry tools.agents.tests.test_project_telemetry_events tools.agents.tests.test_workdir_scope_enforcer tools.agents.tests.test_gate_evidence tools.agents.tests.test_repeat_call_guard tools.agents.tests.test_repeat_guard tools.agents.tests.test_gate_integrity tools.agents.tests.test_gate_failclosed_indirection tools.agents.tests.test_gate_failclosed_schema_diff tools.agents.tests.test_expert_review_pr_scope tools.agents.tests.test_path_containment tools.agents.tests.test_path_normalizer_hardened tools.agents.tests.test_sandbox_tool_strip tools.agents.tests.test_proxy_env_loader tools.agents.tests.test_stream_required_tool tools.agents.tests.test_tool_call_wrapper_profiles tools.agents.tests.test_tool_convert_cache tools.agents.tests.test_doubling_break tools.agents.tests.test_error_loop_ignores_correctives tools.agents.tests.test_attractor_detection tools.agents.tests.test_client_disconnect tools.agents.tests.test_confidence_escalation tools.agents.tests.test_coordination_ban tools.agents.tests.test_coordination_early_ban tools.agents.tests.test_cycle_break_exploration tools.agents.tests.test_deferral_break tools.agents.tests.test_deliver_autoroute tools.agents.tests.test_delivery_enforcement_all_langs tools.agents.tests.test_delivery_enforcement_exemptions tools.agents.tests.test_delivery_enforcement_filepath tools.agents.tests.test_delivery_enforcement_write_complexity tools.agents.tests.test_fastpath_config tools.agents.tests.test_delivery_enforcement_web_and_bash tools.agents.tests.test_disconnect_watcher tools.agents.tests.test_empty_maxtokens_recovery tools.agents.tests.test_empty_tool_loop_break tools.agents.tests.test_enforcer_escape_hatches tools.agents.tests.test_error_loop_break tools.agents.tests.test_finalize_suppression tools.agents.tests.test_malformed_unclosed_think tools.agents.tests.test_mandate_beats_recon tools.agents.tests.test_mandate_deliver tools.agents.tests.test_overflow_truncate_count_tokens tools.agents.tests.test_passthrough_oauth tools.agents.tests.test_project_telemetry tools.agents.tests.test_proxy_auth_headers tools.agents.tests.test_prune_preserve_force_write tools.agents.tests.test_recon_deliver_gate tools.agents.tests.test_session_admission tools.agents.tests.test_stream_heartbeat tools.agents.tests.test_stuck_break_reattach tools.agents.tests.test_stuck_break_hard tools.agents.tests.test_turn_count_breaker_periodic tools.agents.tests.test_upstream_chokepoint tools.agents.tests.test_vision_passthrough tools.agents.tests.test_worktree_required tools.agents.tests.test_enforcer_suite_coverage tools.agents.tests.test_validate_plan_gate tools.agents.tests.test_validate_plan_inside_project tools.agents.tests.test_anthropic_proxy_streaming tools.agents.tests.test_non_stream_resp_log tools.agents.tests.test_delivery_enforcement_worktree tools.agents.tests.test_output_token_ceilings tools.agents.tests.test_tool_narrowing_core tools.agents.tests.test_models_context_window tools.agents.tests.test_thinking_template_kwargs tools.agents.tests.test_cycle_break_wait_poll tools.agents.tests.test_upstream_model_aliases tools.agents.tests.test_stream_thinking_deltas",
|
|
25
25
|
"test:coverage": "vitest --coverage",
|
|
26
26
|
"bench": "vitest --config vitest.bench.config.ts",
|
|
27
27
|
"lint": "eslint src --ext .ts",
|
|
@@ -28,27 +28,6 @@ skills_to_update = {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
def add_rtk_header(content, skill_name):
|
|
32
|
-
rtk_addition = f"""---
|
|
33
|
-
name: {skill_name}
|
|
34
|
-
version: "2.0.0"
|
|
35
|
-
compatibility: CLAUDE.md v2.3.0+
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
> **RTK Integration**: Supports `@hooks-session-start.md`, `@PreCompact.md`
|
|
39
|
-
|
|
40
|
-
"""
|
|
41
|
-
if content.startswith("---"):
|
|
42
|
-
end_frontmatter = content.find("---", 3)
|
|
43
|
-
if end_frontmatter > 0:
|
|
44
|
-
return (
|
|
45
|
-
content[: end_frontmatter + 3]
|
|
46
|
-
+ rtk_addition
|
|
47
|
-
+ content[end_frontmatter + 3 :]
|
|
48
|
-
)
|
|
49
|
-
return rtk_addition + content
|
|
50
|
-
|
|
51
|
-
|
|
52
31
|
def add_decision_loop_ref(content, skill_name):
|
|
53
32
|
decision_loop = f"""
|
|
54
33
|
## Protocol Integration
|
|
@@ -117,7 +96,6 @@ def update_skill_file(skill_dir, skill_name):
|
|
|
117
96
|
content = f.read()
|
|
118
97
|
|
|
119
98
|
original_content = content
|
|
120
|
-
content = add_rtk_header(content, skill_name)
|
|
121
99
|
content = add_decision_loop_ref(content, skill_name)
|
|
122
100
|
content = add_uam_compliance(content)
|
|
123
101
|
|
|
@@ -79,12 +79,12 @@ else
|
|
|
79
79
|
echo "✗ Pattern Router MISSING"
|
|
80
80
|
fi
|
|
81
81
|
|
|
82
|
-
# 10.
|
|
82
|
+
# 10. Session-hook includes
|
|
83
83
|
if grep -q "@hooks-session-start.md\|@PreCompact.md" CLAUDE.md; then
|
|
84
84
|
score=$((score + 1))
|
|
85
|
-
echo "✓
|
|
85
|
+
echo "✓ Session-hook includes (@hooks-session-start, @PreCompact)"
|
|
86
86
|
else
|
|
87
|
-
echo "✗
|
|
87
|
+
echo "✗ Session-hook includes MISSING"
|
|
88
88
|
fi
|
|
89
89
|
|
|
90
90
|
# 11. Verifier loop enforcement (min 3 runs)
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -39,6 +39,11 @@ PROTECTED_MARKERS = (
|
|
|
39
39
|
"/.policy-tools/",
|
|
40
40
|
"/src/policies/",
|
|
41
41
|
"/policies/", # the policy-definition markdown dir
|
|
42
|
+
# The policies DB the gates read. Compliance artifact paths are carved out
|
|
43
|
+
# below, so without this the enforcement registry itself was the soft spot:
|
|
44
|
+
# rewrite the DB and every downstream gate grades a forgery (the pay2u
|
|
45
|
+
# inversion the operator patch fixed out-of-tree).
|
|
46
|
+
"/agents/data/memory/policies.db",
|
|
42
47
|
"/.uap.json",
|
|
43
48
|
"/.uap/",
|
|
44
49
|
"anthropic-proxy.env",
|
|
@@ -62,6 +67,10 @@ BYPASS_PATTERNS = (
|
|
|
62
67
|
# agent writes its own command strings, so an inline form waives its own
|
|
63
68
|
# review. Refuse it here so the attempt is visible rather than silent.
|
|
64
69
|
re.compile(r"UAP_NO_REVIEW\s*=\s*['\"]?1", re.I),
|
|
70
|
+
# quality-metrics gate hatch, same operator-only shape: the enforcer reads
|
|
71
|
+
# the launch env, so the only agent-reachable move is PERSISTING the flag
|
|
72
|
+
# (rc files, proxy env) — which is exactly what this pattern refuses.
|
|
73
|
+
re.compile(r"UAP_QUALITY_GATE_OFF\s*=\s*['\"]?1", re.I),
|
|
65
74
|
re.compile(r"UAP_USER_VALIDATION\s*=\s*['\"]?0", re.I),
|
|
66
75
|
# Single-flight is a DATA-SAFETY control, not a policy preference: deliver
|
|
67
76
|
# runs each candidate in a git worktree, and two runs against one repo are
|
|
@@ -246,8 +255,33 @@ PROTECTED_TARGETS = (
|
|
|
246
255
|
# (test_gate_evidence), which asserts that exact append stays allowed.
|
|
247
256
|
# Guarding it needs a rule that tells `>>` from `>`; blocking the queue's
|
|
248
257
|
# own writes to protect it is not that rule.
|
|
258
|
+
#
|
|
259
|
+
# The policies DB the gates READ. The inversion this closes: compliance
|
|
260
|
+
# artifact paths (.uap/reviews/) were agent-locked while the DB that
|
|
261
|
+
# decides what is enforced sat unprotected — an agent could delete or
|
|
262
|
+
# rewrite the policy registry instead of complying with it (pay2u operator
|
|
263
|
+
# patch uap-policy-fix-APPLY.sh, upstreamed here). The CLI's own writes go
|
|
264
|
+
# through the `uap policy` process, not agent Edit/Write tools, so policy
|
|
265
|
+
# management is unaffected; what this refuses is the agent deleting or
|
|
266
|
+
# editing the DB directly.
|
|
267
|
+
"agents/data/memory/policies.db",
|
|
249
268
|
".uap.json",
|
|
250
269
|
"anthropic-proxy.env",
|
|
270
|
+
# F3 (deliver-hardening 2026-07-13): the signed operator-override file.
|
|
271
|
+
# Edit/Write to it is already refused via the "/.uap/" marker, but the
|
|
272
|
+
# destructive check treats every redirect alike and this directory is
|
|
273
|
+
# otherwise permissive — `echo '{deliverBypass:true…}' >
|
|
274
|
+
# .uap/operator-overrides.json` would self-mint the bypass the file exists
|
|
275
|
+
# to restrict to the operator. Only an out-of-band operator writes it; the
|
|
276
|
+
# hook additionally verifies uid/mode/expiresAt before honoring it.
|
|
277
|
+
".uap/operator-overrides.json",
|
|
278
|
+
# F1: the liveness cache the gate's degrade consult trusts. A forged entry
|
|
279
|
+
# ({healthy:false, degradable:true}) would downgrade a BLOCKING policy to
|
|
280
|
+
# advisory — exactly the sabotage the degrade guard exists to refuse — so
|
|
281
|
+
# the cache must be as unwritable as the verdicts it carries. Legitimate
|
|
282
|
+
# writes go through `uap policy liveness`/`status`, whose command text
|
|
283
|
+
# never names the file (same shape as the policies.db guard).
|
|
284
|
+
".uap/policy-liveness.json",
|
|
251
285
|
)
|
|
252
286
|
|
|
253
287
|
_SEGMENT_SPLIT = re.compile(r"(?:\|\||&&|[;\n|&])")
|
|
@@ -525,6 +559,37 @@ def _kills_live_deliver_run(command: str, root) -> str:
|
|
|
525
559
|
return ""
|
|
526
560
|
|
|
527
561
|
|
|
562
|
+
# The two files the gate's TRUST decisions rest on: the signed operator
|
|
563
|
+
# override and the liveness cache the degrade consult reads. They get a rule
|
|
564
|
+
# the rest of the protected surface does not (deliver-hardening security
|
|
565
|
+
# review, 2026-07-13): an INTERPRETER-MEDIATED write —
|
|
566
|
+
# python3 -c 'import json; json.dump({...}, open(".uap/operator-overrides.json","w"))'
|
|
567
|
+
# carries no destructive verb, no shell redirect and no UAP_* bypass text, so
|
|
568
|
+
# every other scan here walks straight past it — yet a successful write used
|
|
569
|
+
# to mint a full bypass. The hook now also requires these files ROOT-owned
|
|
570
|
+
# before trusting them, which is the load-bearing fix; this rule is the
|
|
571
|
+
# defense-in-depth that stops the write from landing at all. Root ownership
|
|
572
|
+
# is what makes this narrow list sufficient — anything else the agent writes
|
|
573
|
+
# is distrusted on READ, so it need not be write-blocked here.
|
|
574
|
+
_TRUST_ANCHORS = (".uap/operator-overrides.json", ".uap/policy-liveness.json")
|
|
575
|
+
_INTERPRETER_RE = re.compile(r"(?:^|[\s;|&('\"`])(?:python\d*(?:\.\d+)?|perl|ruby|node)(?:\s|$)")
|
|
576
|
+
# A write primitive in interpreter code: open(…, "w"/"a"/"x"/"+"), or a
|
|
577
|
+
# mutating method call. Reads (open without a mode, json.load, print) match
|
|
578
|
+
# neither and stay allowed.
|
|
579
|
+
_INTERPRETER_WRITE_RE = re.compile(
|
|
580
|
+
r"open\s*\([^)]*[\"'][wax+]|"
|
|
581
|
+
r"\.\s*(?:write\w*|writelines|dump|rename|replace|unlink|remove|removedirs|"
|
|
582
|
+
r"chmod|chown|rmtree|move|copy\w*)\s*\(")
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
def _interpreter_write_to_anchor(command: str) -> bool:
|
|
586
|
+
"""True when an interpreter command names a trust anchor with write intent."""
|
|
587
|
+
lowered = command.lower()
|
|
588
|
+
if not any(anchor in lowered for anchor in _TRUST_ANCHORS):
|
|
589
|
+
return False
|
|
590
|
+
return bool(_INTERPRETER_RE.search(command) and _INTERPRETER_WRITE_RE.search(command))
|
|
591
|
+
|
|
592
|
+
|
|
528
593
|
def _direct_destructive(command: str) -> bool:
|
|
529
594
|
"""Destructive op naming a protected path, judged per command segment."""
|
|
530
595
|
cd_into_protected = False
|
|
@@ -586,6 +651,11 @@ def _bash_destructive(command: str, _depth: int = 0) -> bool:
|
|
|
586
651
|
return False
|
|
587
652
|
if _direct_destructive(command):
|
|
588
653
|
return True
|
|
654
|
+
# Checked at EVERY depth (an interpreter write inside `bash -c "..."` is
|
|
655
|
+
# still one) and BEFORE the intent gate below — that gate reads shell
|
|
656
|
+
# verbs, and an interpreter-mediated write to a trust anchor carries none.
|
|
657
|
+
if _interpreter_write_to_anchor(command):
|
|
658
|
+
return True
|
|
589
659
|
if _depth < 2: # bounded: `bash -c "bash -c ..."`
|
|
590
660
|
for inner in _inner_commands(command):
|
|
591
661
|
if _bash_destructive(inner, _depth + 1):
|
|
@@ -63,6 +63,9 @@ GH_API_SHIP_RE = re.compile(
|
|
|
63
63
|
)
|
|
64
64
|
GIT_VALUE_OPTIONS = frozenset({"-C", "-c", "--git-dir", "--work-tree", "--namespace"})
|
|
65
65
|
WRAPPER_VERBS = frozenset({
|
|
66
|
+
# "rtk" stays even though UAP no longer integrates the rtk CLI: the binary
|
|
67
|
+
# can still exist on operator machines, and without the unwrap, forms like
|
|
68
|
+
# `rtk git -C /repo push` would slip past the ship gate (fail-open).
|
|
66
69
|
"rtk", "env", "nohup", "sudo", "time", "command", "timeout", "stdbuf",
|
|
67
70
|
})
|
|
68
71
|
_SEGMENT_SPLIT = re.compile(r"(?:\|\||&&|[;\n|&])")
|
|
@@ -481,6 +484,25 @@ def main() -> None:
|
|
|
481
484
|
"Override: UAP_NO_REVIEW=1.",
|
|
482
485
|
)
|
|
483
486
|
|
|
487
|
+
# Quality-metrics fusion: when the review artifact carries a `quality`
|
|
488
|
+
# block (written from `uap quality check --json` by the
|
|
489
|
+
# parallel-expert-review flow), a failing machine report vetoes the
|
|
490
|
+
# approval — reviewers adjudicate the numbers, they cannot outvote them.
|
|
491
|
+
# Absent block -> fail-open (repos without .uap/quality-metrics.json and
|
|
492
|
+
# pre-existing artifacts keep working).
|
|
493
|
+
quality = data.get("quality") if isinstance(data, dict) else None
|
|
494
|
+
if isinstance(quality, dict) and quality.get("pass") is False:
|
|
495
|
+
blocking = quality.get("blocking")
|
|
496
|
+
detail = f" ({blocking} blocking violation(s))" if isinstance(blocking, int) else ""
|
|
497
|
+
emit(
|
|
498
|
+
False,
|
|
499
|
+
f"expert-review-required: the review's quality gate FAILED{detail}. "
|
|
500
|
+
"Run `uap quality check`, fix the blocking violations (or regenerate the "
|
|
501
|
+
"baseline deliberately with `uap quality baseline --update`), refresh the "
|
|
502
|
+
"artifact's quality block, and re-record the review. "
|
|
503
|
+
"Override: UAP_NO_REVIEW=1.",
|
|
504
|
+
)
|
|
505
|
+
|
|
484
506
|
emit(
|
|
485
507
|
True,
|
|
486
508
|
f"expert-review satisfied (.uap/reviews/{slug}.json"
|
|
File without changes
|