@miller-tech/uap 1.40.1 → 1.42.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/dist/.tsbuildinfo +1 -1
- package/dist/bin/cli.js +17 -0
- package/dist/bin/cli.js.map +1 -1
- package/dist/cli/deliver-defaults.d.ts +23 -0
- package/dist/cli/deliver-defaults.d.ts.map +1 -0
- package/dist/cli/deliver-defaults.js +121 -0
- package/dist/cli/deliver-defaults.js.map +1 -0
- package/dist/cli/hooks.d.ts.map +1 -1
- package/dist/cli/hooks.js +50 -2
- package/dist/cli/hooks.js.map +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +29 -0
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/react.d.ts +25 -0
- package/dist/cli/react.d.ts.map +1 -0
- package/dist/cli/react.js +59 -0
- package/dist/cli/react.js.map +1 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +19 -0
- package/dist/cli/setup.js.map +1 -1
- package/dist/coordination/reactor.d.ts +38 -0
- package/dist/coordination/reactor.d.ts.map +1 -0
- package/dist/coordination/reactor.js +124 -0
- package/dist/coordination/reactor.js.map +1 -0
- package/dist/mcp-router/server.d.ts +2 -1
- package/dist/mcp-router/server.d.ts.map +1 -1
- package/dist/mcp-router/server.js +5 -2
- package/dist/mcp-router/server.js.map +1 -1
- package/dist/mcp-router/tools/react.d.ts +58 -0
- package/dist/mcp-router/tools/react.d.ts.map +1 -0
- package/dist/mcp-router/tools/react.js +57 -0
- package/dist/mcp-router/tools/react.js.map +1 -0
- package/dist/memory/model-router.d.ts +1 -1
- package/dist/memory/model-router.d.ts.map +1 -1
- package/dist/memory/model-router.js +27 -1
- package/dist/memory/model-router.js.map +1 -1
- package/dist/models/openai-compat-client.d.ts.map +1 -1
- package/dist/models/openai-compat-client.js +5 -0
- package/dist/models/openai-compat-client.js.map +1 -1
- package/dist/models/types.d.ts +8 -0
- package/dist/models/types.d.ts.map +1 -1
- package/dist/models/types.js +22 -0
- package/dist/models/types.js.map +1 -1
- package/dist/policies/policy-tools.d.ts +7 -0
- package/dist/policies/policy-tools.d.ts.map +1 -1
- package/dist/policies/policy-tools.js +24 -2
- package/dist/policies/policy-tools.js.map +1 -1
- package/dist/types/config.d.ts +12 -0
- package/dist/types/config.d.ts.map +1 -1
- package/docs/design/UAP_REACTOR.md +170 -0
- package/package.json +3 -1
- package/src/policies/enforcers/7ebbc721-7540-4e9f-879a-770e0213a09b_architecture_review.py +101 -0
- package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
- package/src/policies/enforcers/_common.py +100 -0
- package/src/policies/enforcers/artifact_hygiene.py +52 -0
- package/src/policies/enforcers/cluster_routing.py +63 -0
- package/src/policies/enforcers/codebase_read_before_plan.py +52 -0
- package/src/policies/enforcers/coord_overlap.py +81 -0
- package/src/policies/enforcers/delivery_enforcement.py +97 -0
- package/src/policies/enforcers/doc_live_over_report.py +50 -0
- package/src/policies/enforcers/expert_review_required.py +135 -0
- package/src/policies/enforcers/iac_parity.py +53 -0
- package/src/policies/enforcers/mcp_router_first.py +37 -0
- package/src/policies/enforcers/memory_before_plan.py +61 -0
- package/src/policies/enforcers/parallel_reads.py +50 -0
- package/src/policies/enforcers/rtk_wrap.py +44 -0
- package/src/policies/enforcers/schema_diff_gate.py +80 -0
- package/src/policies/enforcers/session_memory_write.py +52 -0
- package/src/policies/enforcers/task_required.py +131 -0
- package/src/policies/enforcers/test_gate.py +58 -0
- package/src/policies/enforcers/validate_plan_before_build.py +75 -0
- package/src/policies/enforcers/worktree_required.py +57 -0
- package/src/policies/schemas/policies/architecture-review.md +51 -0
- package/src/policies/schemas/policies/artifact-hygiene.md +29 -0
- package/src/policies/schemas/policies/cluster-routing.md +31 -0
- package/src/policies/schemas/policies/codebase-read-before-plan.md +30 -0
- package/src/policies/schemas/policies/coord-overlap.md +24 -0
- package/src/policies/schemas/policies/delivery-enforcement.md +45 -0
- package/src/policies/schemas/policies/doc-live-over-report.md +32 -0
- package/src/policies/schemas/policies/expert-review-required.md +60 -0
- package/src/policies/schemas/policies/iac-parity.md +31 -0
- package/src/policies/schemas/policies/mandatory-testing-deployment.md +147 -0
- package/src/policies/schemas/policies/mcp-router-first.md +24 -0
- package/src/policies/schemas/policies/memory-before-plan.md +24 -0
- package/src/policies/schemas/policies/merge-deploy-monitor-verify.md +145 -0
- package/src/policies/schemas/policies/parallel-reads.md +24 -0
- package/src/policies/schemas/policies/rtk-wrap.md +26 -0
- package/src/policies/schemas/policies/schema-diff-gate.md +30 -0
- package/src/policies/schemas/policies/session-memory-write.md +24 -0
- package/src/policies/schemas/policies/task-required.md +49 -0
- package/src/policies/schemas/policies/test-gate.md +24 -0
- package/src/policies/schemas/policies/validate-plan-before-build.md +28 -0
- package/src/policies/schemas/policies/worktree-required.md +28 -0
- package/templates/hooks/uap-policy-gate.sh +5 -0
- package/templates/hooks/uap-reactor-prompt.sh +44 -0
- package/templates/hooks/uap-schema-post.sh +26 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Policy: Merge, Deploy, Monitor, Verify
|
|
2
|
+
|
|
3
|
+
**ID**: `policy-merge-deploy-monitor-verify`
|
|
4
|
+
**Name**: Merge, Deploy, Monitor, Verify Before Done
|
|
5
|
+
**Category**: completion
|
|
6
|
+
**Level**: REQUIRED
|
|
7
|
+
**Enforcement Stage**: review
|
|
8
|
+
**Version**: 1.0
|
|
9
|
+
|
|
10
|
+
## Purpose
|
|
11
|
+
|
|
12
|
+
This policy enforces that a change is NOT DONE until it has been merged, rolled out via the designated pipeline, observed healthy in the target environment for a defined monitoring window, and verified with captured evidence to behave correctly end-to-end. Local "build green + tests pass" is necessary but not sufficient — DONE requires evidence from the deployed system, not just CI.
|
|
13
|
+
|
|
14
|
+
## Rules
|
|
15
|
+
|
|
16
|
+
```rules
|
|
17
|
+
- title: "Merge Gate"
|
|
18
|
+
keywords: ["done", "complete", "finish", "close", "resolve", "shipped"]
|
|
19
|
+
antiPatterns: ["direct push to master", "no pr", "skip review", "force merge", "ci failing", "merged with red ci"]
|
|
20
|
+
|
|
21
|
+
- title: "Deploy Gate"
|
|
22
|
+
keywords: ["done", "complete", "deploy", "release", "ship", "rollout"]
|
|
23
|
+
antiPatterns: ["manual deploy", "ad-hoc cluster command", "hand-edited resource", "deploy skipped", "deployment failed", "pipeline bypassed", "out-of-band rollout"]
|
|
24
|
+
|
|
25
|
+
- title: "Monitor Gate"
|
|
26
|
+
keywords: ["done", "complete", "monitor", "observe", "verify health"]
|
|
27
|
+
antiPatterns: ["no monitoring window", "skip observation", "no dashboard checked", "alerts not reviewed", "ignored error rate", "skipped post-deploy check"]
|
|
28
|
+
|
|
29
|
+
- title: "Verify Gate"
|
|
30
|
+
keywords: ["done", "complete", "verify", "confirm", "validate behavior"]
|
|
31
|
+
antiPatterns: ["unverified", "tests passed so done", "ci is enough", "no end-to-end check", "no evidence captured", "happy path only", "negative case skipped"]
|
|
32
|
+
|
|
33
|
+
- title: "Evidence Capture"
|
|
34
|
+
keywords: ["close task", "mark done", "complete task", "resolve task"]
|
|
35
|
+
antiPatterns: ["no merge sha", "no deploy url", "no monitoring evidence", "no verification output", "missing screenshot", "missing log excerpt"]
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Enforcement Behavior
|
|
39
|
+
|
|
40
|
+
### When Triggered
|
|
41
|
+
|
|
42
|
+
This policy is enforced during the **review stage** when:
|
|
43
|
+
|
|
44
|
+
- Task status is being changed to DONE, COMPLETE, CLOSED, or RESOLVED
|
|
45
|
+
- A pull request is being declared "shipped"
|
|
46
|
+
- An incident or change request is being closed
|
|
47
|
+
- Work is being declared finished in any form
|
|
48
|
+
|
|
49
|
+
### Required Actions Before Completion
|
|
50
|
+
|
|
51
|
+
1. **Merge Gate**
|
|
52
|
+
- Change merged via reviewed PR from a feature/worktree branch into the integration branch
|
|
53
|
+
- All CI required checks green on the merge commit (build, tests, lint, type-check)
|
|
54
|
+
- At least one approving review (or self-review with explicit documented justification for trivial changes)
|
|
55
|
+
- Merge commit SHA recorded
|
|
56
|
+
|
|
57
|
+
2. **Deploy Gate**
|
|
58
|
+
- Designated automated deployment pipeline executed end-to-end without error
|
|
59
|
+
- Application changes: artifact published and rollout completed in target environment(s) (staging through production, as scoped)
|
|
60
|
+
- Infrastructure changes: IaC pipeline succeeded (composes with `definition-of-done-iac`)
|
|
61
|
+
- Pipeline run URL recorded
|
|
62
|
+
- Manual deploys, ad-hoc cluster commands, and hand-edited cloud resources are FORBIDDEN as the deploy path
|
|
63
|
+
|
|
64
|
+
3. **Monitor Gate**
|
|
65
|
+
- Minimum post-deploy observation window elapsed:
|
|
66
|
+
- 15 minutes for low-risk changes
|
|
67
|
+
- 1 hour for service/infrastructure changes
|
|
68
|
+
- 24 hours for high-blast-radius changes (auth, payments, data migrations, schema changes, traffic routing)
|
|
69
|
+
- Health signals reviewed and clean during the window:
|
|
70
|
+
- Error rate (no new error classes, no rate increase above baseline)
|
|
71
|
+
- Latency (p50/p95/p99 within SLO)
|
|
72
|
+
- Saturation (CPU/memory/connections within healthy bounds)
|
|
73
|
+
- Logs (no new ERROR/FATAL lines tied to the change)
|
|
74
|
+
- Alerts (no new alerts firing related to the change)
|
|
75
|
+
- Dashboard/log links recorded
|
|
76
|
+
- Any degraded signal blocks DONE until rolled back or rolled forward with a fix
|
|
77
|
+
|
|
78
|
+
4. **Verify Gate**
|
|
79
|
+
- The specific behavior introduced/fixed is exercised end-to-end against the deployed environment
|
|
80
|
+
- Verification method matches change type:
|
|
81
|
+
- API/backend: live request against deployed endpoint with expected response asserted
|
|
82
|
+
- UI/frontend: interactive walkthrough of golden path AND the specific edge case
|
|
83
|
+
- Infrastructure: cluster/cloud CLI query confirming the resource exists and behaves as designed
|
|
84
|
+
- Data/schema: query confirming migrated data is shaped correctly and reads/writes succeed
|
|
85
|
+
- At least one negative case explicitly checked (the failure mode the change prevents does not occur)
|
|
86
|
+
- Evidence captured: response body, screenshot, command output, or log excerpt
|
|
87
|
+
- CI green is NOT verification — verification requires evidence from the deployed system
|
|
88
|
+
|
|
89
|
+
### Verification Checklist
|
|
90
|
+
|
|
91
|
+
Before marking work as DONE, verify and attach:
|
|
92
|
+
|
|
93
|
+
- [ ] Merge commit SHA and PR URL recorded
|
|
94
|
+
- [ ] Deployment pipeline run URL recorded
|
|
95
|
+
- [ ] Target environment(s) reached and recorded (e.g. staging, production)
|
|
96
|
+
- [ ] Monitoring window start/end timestamps recorded
|
|
97
|
+
- [ ] Dashboard/log links reviewed during the window and attached
|
|
98
|
+
- [ ] Health signals (error rate, latency, saturation, logs, alerts) all clean
|
|
99
|
+
- [ ] Verification evidence captured (command output, response body, screenshot)
|
|
100
|
+
- [ ] Negative case checked and the prevented failure mode confirmed absent
|
|
101
|
+
- [ ] No new alerts fired during or after the observation window
|
|
102
|
+
|
|
103
|
+
### Anti-Patterns to Avoid
|
|
104
|
+
|
|
105
|
+
DO NOT mark tasks as DONE when:
|
|
106
|
+
|
|
107
|
+
- The PR has been merged but the rollout hasn't run yet ("merged != deployed")
|
|
108
|
+
- The rollout succeeded but no one observed the system afterwards ("deployed != working")
|
|
109
|
+
- CI is green but the deployed environment was never exercised ("CI != production")
|
|
110
|
+
- The monitoring window was skipped because "it's a small change"
|
|
111
|
+
- Verification consisted of "the tests cover it" — tests cover code paths, not deployed behavior
|
|
112
|
+
- Only the happy path was verified and the negative case was skipped
|
|
113
|
+
- "No alerts fired" was used as proof of health when no alerts exist for the changed surface area
|
|
114
|
+
- The deploy/monitor/verify gates were deferred to "next sprint" or "ops can check later"
|
|
115
|
+
- Evidence was claimed but not actually captured or attached
|
|
116
|
+
|
|
117
|
+
## Implementation Notes
|
|
118
|
+
|
|
119
|
+
This policy should be enforced by:
|
|
120
|
+
|
|
121
|
+
1. **Task management gate** — block status transitions to DONE/CLOSED until evidence fields are populated
|
|
122
|
+
2. **PR merge bots** — require deployment status checks before allowing merge to be marked "shipped"
|
|
123
|
+
3. **CI/CD pipelines** — emit deployment and verification webhooks that the policy gate consumes
|
|
124
|
+
4. **Policy gate system (`uap-policy check`)** — validate before allowing completion commands
|
|
125
|
+
|
|
126
|
+
## Default Status
|
|
127
|
+
|
|
128
|
+
**Default: ON**
|
|
129
|
+
**Level: REQUIRED**
|
|
130
|
+
|
|
131
|
+
This policy is on by default for all UAP-managed projects. Disable only with explicit project-level override and documented justification (e.g. local-only experiments, scratch projects).
|
|
132
|
+
|
|
133
|
+
## Related Policies
|
|
134
|
+
|
|
135
|
+
- `policy-completion-gate` — Local completion gates (tests, build, lint, version bump, worktree)
|
|
136
|
+
- `policy-mandatory-testing-deployment` — Test creation and quality requirements
|
|
137
|
+
- `policy-definition-of-done-iac` — IaC-specific deploy + cluster verify requirements
|
|
138
|
+
- `policy-iac-pipeline-enforcement` — Pipeline-only deploy path for infrastructure
|
|
139
|
+
|
|
140
|
+
The local completion gate gets a change ready to ship. This policy ensures the change actually shipped, stayed healthy, and demonstrably works in the environment that matters.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
_Last Updated: 2026-05-04_
|
|
145
|
+
_Author: Miller Tech UAP System_
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# parallel-reads
|
|
2
|
+
|
|
3
|
+
**Category**: custom
|
|
4
|
+
**Level**: RECOMMENDED
|
|
5
|
+
**Enforcement Stage**: pre-exec
|
|
6
|
+
**Tags**: performance, parallelism, exploration
|
|
7
|
+
|
|
8
|
+
## Rule
|
|
9
|
+
|
|
10
|
+
Two or more independent read-only operations (`Read`, `Grep`, `Glob`, non-mutating `Bash`, `WebFetch`) with no data dependency MUST be dispatched in a single tool-call batch.
|
|
11
|
+
|
|
12
|
+
## Why
|
|
13
|
+
|
|
14
|
+
Serial fan-out multiplies wall-clock by N on every exploration. Claude Code supports parallel tool calls in one message. Measured speed-up on codebase surveys: 2–5×.
|
|
15
|
+
|
|
16
|
+
## Enforcement
|
|
17
|
+
|
|
18
|
+
Python enforcer `parallel_reads.py` (post-exec sampler) detects serial read patterns within a tight time window and warns on the next message.
|
|
19
|
+
|
|
20
|
+
```rules
|
|
21
|
+
- title: "Batch independent reads"
|
|
22
|
+
keywords: [read, grep, glob, webfetch, inspect]
|
|
23
|
+
antiPatterns: [serial-read, one-by-one, sequential-survey]
|
|
24
|
+
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# rtk-wrap
|
|
2
|
+
|
|
3
|
+
**Category**: custom
|
|
4
|
+
**Level**: REQUIRED
|
|
5
|
+
**Enforcement Stage**: pre-exec
|
|
6
|
+
**Tags**: rtk, tokens, efficiency
|
|
7
|
+
|
|
8
|
+
## Rule
|
|
9
|
+
|
|
10
|
+
These commands MUST be invoked via `rtk` wrapper, not directly: `git`, `kubectl`, `docker`, `docker-compose`, `npm`, `pnpm`, `yarn`, `helm`, `terraform`.
|
|
11
|
+
|
|
12
|
+
Exception: `rtk` meta-commands (`rtk gain`, `rtk discover`, `rtk proxy`, `rtk --version`).
|
|
13
|
+
|
|
14
|
+
## Why
|
|
15
|
+
|
|
16
|
+
RTK delivers 60–90% token reduction on dev ops (`~/.claude/RTK.md`). Missing the wrap = proportional context waste.
|
|
17
|
+
|
|
18
|
+
## Enforcement
|
|
19
|
+
|
|
20
|
+
Python enforcer `rtk_wrap.py` inspects the Bash command string and blocks if a wrapped binary is invoked without the `rtk ` prefix.
|
|
21
|
+
|
|
22
|
+
```rules
|
|
23
|
+
- title: "Wrap heavy CLIs with rtk"
|
|
24
|
+
keywords: [bash, shell, git, kubectl, docker, npm, pnpm, yarn, helm, terraform]
|
|
25
|
+
antiPatterns: [raw-kubectl, raw-git, raw-docker, raw-npm]
|
|
26
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# schema-diff-gate
|
|
2
|
+
|
|
3
|
+
**Category**: infrastructure
|
|
4
|
+
**Level**: REQUIRED
|
|
5
|
+
**Enforcement Stage**: pre-exec
|
|
6
|
+
**Tags**: postgres, cnpg, pgdog, migrations, schema, spock, redis
|
|
7
|
+
|
|
8
|
+
## Rule
|
|
9
|
+
|
|
10
|
+
Changes to DB schema, connection pooler config, or replication topology MUST pass `uap schema-diff` before commit:
|
|
11
|
+
|
|
12
|
+
- `migrations/**/*.sql`
|
|
13
|
+
- `infra/postgres-spock/**`
|
|
14
|
+
- `infra/helm_charts/**/pgdog*`
|
|
15
|
+
- CNPG `Cluster` spec (pool sizes, instance count, connection limits)
|
|
16
|
+
- Redis Sentinel / Envoy HA-write proxy configs
|
|
17
|
+
|
|
18
|
+
## Why
|
|
19
|
+
|
|
20
|
+
Branch `fix/zitadel-pgdog-capacity-v2` exists because a prior capacity change escaped review. PgDog connection limits cascade into Zitadel auth outages. Pre-commit gating prevents "v2 hotfix" cycles.
|
|
21
|
+
|
|
22
|
+
## Enforcement
|
|
23
|
+
|
|
24
|
+
Python enforcer `schema_diff_gate.py` runs `uap schema-diff` (or checks recent successful run in memory ≤1h) when the diff touches the listed paths.
|
|
25
|
+
|
|
26
|
+
```rules
|
|
27
|
+
- title: "Schema/capacity changes must pass schema-diff"
|
|
28
|
+
keywords: [migration, schema, pgdog, cnpg, spock, postgres, redis, sentinel, envoy, pool]
|
|
29
|
+
antiPatterns: [ALTER TABLE, max_connections, pool_size, instances:, replicas:]
|
|
30
|
+
```
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# session-memory-write
|
|
2
|
+
|
|
3
|
+
**Category**: workflow
|
|
4
|
+
**Level**: REQUIRED
|
|
5
|
+
**Enforcement Stage**: post-exec
|
|
6
|
+
**Tags**: memory, session, uap
|
|
7
|
+
|
|
8
|
+
## Rule
|
|
9
|
+
|
|
10
|
+
A session that changed code (Edit/Write/MultiEdit occurred) MUST insert at least one `session_memories` row with `type IN ('decision','lesson','pattern')` before terminating.
|
|
11
|
+
|
|
12
|
+
## Why
|
|
13
|
+
|
|
14
|
+
Session-end logs show most sessions end with no memory write even when code changed. Lessons evaporate. UAP's memory system only works if write-back happens.
|
|
15
|
+
|
|
16
|
+
## Enforcement
|
|
17
|
+
|
|
18
|
+
Python enforcer `session_memory_write.py` runs on session-end hook: if code_changed=true, verify a matching row exists in `agents/data/memory/short_term.db`.
|
|
19
|
+
|
|
20
|
+
```rules
|
|
21
|
+
- title: "Close the learning loop on code sessions"
|
|
22
|
+
keywords: [session-end, stop, terminate, finish]
|
|
23
|
+
antiPatterns: [no-memory-write, skip-lesson]
|
|
24
|
+
```
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# task-required
|
|
2
|
+
|
|
3
|
+
**Category**: workflow
|
|
4
|
+
**Level**: REQUIRED
|
|
5
|
+
**Enforcement Stage**: pre-exec
|
|
6
|
+
**Tags**: uap, task, workflow, enforcement
|
|
7
|
+
|
|
8
|
+
## Rule
|
|
9
|
+
|
|
10
|
+
A UAP task MUST be `in_progress` before any mutating work. When no row in
|
|
11
|
+
`.uap/tasks/tasks.db` has `status='in_progress'`, the enforcer blocks:
|
|
12
|
+
|
|
13
|
+
- `Edit` / `Write` / `MultiEdit` on non-exempt paths
|
|
14
|
+
- Bash ship actions: `git commit`, `git push`, `gh pr create`
|
|
15
|
+
|
|
16
|
+
Exempt path prefixes (no task required): `.claude/`, `.cursor/`, `.opencode/`,
|
|
17
|
+
`.codex/`, `.forge/`, `.uap/`, `.policy-tools/`, `src/policies/`, `scripts/`,
|
|
18
|
+
`docs/`.
|
|
19
|
+
|
|
20
|
+
To proceed: `uap task create --type <task|bug|feature> --title "<desc>"` then
|
|
21
|
+
`uap task update <id> --status in_progress` (or `uap task claim <id>`).
|
|
22
|
+
|
|
23
|
+
## Why
|
|
24
|
+
|
|
25
|
+
The UAP compliance protocol's "create a task before work" step has historically
|
|
26
|
+
been delivered as SessionStart text injection — advisory guidance the agent can
|
|
27
|
+
silently skip. Observed in practice: a full multi-PR session completed with zero
|
|
28
|
+
`uap task create` calls because nothing enforced it.
|
|
29
|
+
|
|
30
|
+
A `pre-exec` policy enforcer makes the task requirement a hard gate rather than a
|
|
31
|
+
suggestion, so UAP task tracking is guaranteed rather than best-effort. This is
|
|
32
|
+
the task-tracking analogue of `worktree-required`.
|
|
33
|
+
|
|
34
|
+
## Enforcement
|
|
35
|
+
|
|
36
|
+
Python enforcer `task_required.py` resolves the primary worktree root via
|
|
37
|
+
`git rev-parse --git-common-dir` (so it works from linked worktrees), reads
|
|
38
|
+
`.uap/tasks/tasks.db`, and blocks when `COUNT(*) WHERE status='in_progress'` is
|
|
39
|
+
zero.
|
|
40
|
+
|
|
41
|
+
Fail-open: if UAP task tracking is not initialised (no `tasks.db`) or the DB is
|
|
42
|
+
unreadable, the operation is allowed — non-UAP repositories are unaffected.
|
|
43
|
+
Override for one-off meta-work: `UAP_NO_TASK=1`.
|
|
44
|
+
|
|
45
|
+
```rules
|
|
46
|
+
- title: "A UAP task must be in_progress before mutating work"
|
|
47
|
+
keywords: [edit, write, multiedit, bash, git commit, git push, gh pr create]
|
|
48
|
+
antiPatterns: [no-task, untracked-work, skip-task-create]
|
|
49
|
+
```
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# test-gate
|
|
2
|
+
|
|
3
|
+
**Category**: quality
|
|
4
|
+
**Level**: REQUIRED
|
|
5
|
+
**Enforcement Stage**: review
|
|
6
|
+
**Tags**: testing, pr, quality
|
|
7
|
+
|
|
8
|
+
## Rule
|
|
9
|
+
|
|
10
|
+
At PR-ready time, every changed service under `services/**` or `apps/**` MUST have a corresponding test delta (`tests/**` or `<service>/**/*.test.*`, `*_test.py`, `*.spec.ts`).
|
|
11
|
+
|
|
12
|
+
## Why
|
|
13
|
+
|
|
14
|
+
Session-end logs show `Tests: false` far more often than `true`. Review-stage gating ensures shipping code without tests is an explicit override, not the default.
|
|
15
|
+
|
|
16
|
+
## Enforcement
|
|
17
|
+
|
|
18
|
+
Python enforcer `test_gate.py` diffs `git diff --name-only origin/main...HEAD` against test-path regexes; blocks PR signoff if any changed service lacks a test file in the same PR.
|
|
19
|
+
|
|
20
|
+
```rules
|
|
21
|
+
- title: "Changed services require test deltas"
|
|
22
|
+
keywords: [pr, commit, merge, review, signoff]
|
|
23
|
+
antiPatterns: [no-tests, skip-tests, tests-later]
|
|
24
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# worktree-required
|
|
2
|
+
|
|
3
|
+
**Category**: workflow
|
|
4
|
+
**Level**: REQUIRED
|
|
5
|
+
**Enforcement Stage**: pre-exec
|
|
6
|
+
**Tags**: git, worktree, isolation, uap
|
|
7
|
+
|
|
8
|
+
## Rule
|
|
9
|
+
|
|
10
|
+
All `Edit`, `Write`, `MultiEdit` calls on tracked files MUST occur inside a UAP worktree at `.worktrees/NNN-<slug>/`. Exemptions:
|
|
11
|
+
|
|
12
|
+
- Harness config under `.claude/`, `.cursor/`, `.opencode/`, `.codex/`, `.uap/`
|
|
13
|
+
- New files under `src/policies/`, `scripts/`, `docs/`
|
|
14
|
+
- Explicit override: user says "work directly" or `--no-worktree`
|
|
15
|
+
|
|
16
|
+
## Why
|
|
17
|
+
|
|
18
|
+
CLAUDE.md v2.3.0 mandates worktrees; the existing hook warns but doesn't block. Formalizing closes the gap — protects in-flight user edits from agent collisions.
|
|
19
|
+
|
|
20
|
+
## Enforcement
|
|
21
|
+
|
|
22
|
+
Python enforcer `worktree_required.py` checks whether the target file path is under `.worktrees/` and whether the session has an active worktree slug.
|
|
23
|
+
|
|
24
|
+
```rules
|
|
25
|
+
- title: "File edits must occur in a worktree"
|
|
26
|
+
keywords: [edit, write, multiedit, create-file, modify-file]
|
|
27
|
+
antiPatterns: [primary-checkout, no-worktree, direct-main]
|
|
28
|
+
```
|
|
@@ -30,6 +30,11 @@ export UAP_REPO_ROOT="$MAIN_ROOT"
|
|
|
30
30
|
# actual WORKING TREE, not the (possibly bare) MAIN_ROOT. Expose the current checkout
|
|
31
31
|
# so _common.worktree_root() targets the worktree when an op runs from inside one.
|
|
32
32
|
export UAP_WORKTREE_ROOT="$CHECKOUT_ROOT"
|
|
33
|
+
# Delivery enforcement defaults to BLOCK for UAP-managed projects: substantive
|
|
34
|
+
# source edits must route through `uap deliver` (verified completion against the
|
|
35
|
+
# gates). The `:-` preserves any explicit operator/CI override (advisory|block).
|
|
36
|
+
# Escape hatches still apply: UAP_DELIVER_ACTIVE=1 (inside deliver) / UAP_DELIVER_BYPASS=1.
|
|
37
|
+
export UAP_ENFORCE_DELIVERY="${UAP_ENFORCE_DELIVERY:-block}"
|
|
33
38
|
cd "$MAIN_ROOT"
|
|
34
39
|
|
|
35
40
|
TOOL="$(printf '%s' "$PAYLOAD" | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d.get("tool_name") or d.get("tool") or "")' 2>/dev/null || true)"
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# UAP Reactor Hook (UserPromptSubmit) — dynamic capability auto-apply.
|
|
3
|
+
# Generalizes pattern-rag-prompt.sh: instead of patterns only, it calls the
|
|
4
|
+
# full `uap react` resolver (experts + skills + patterns, confidence-gated) and
|
|
5
|
+
# injects the result as additionalContext so the model sees it before replying.
|
|
6
|
+
# Fails safely — never blocks the agent (always exits 0).
|
|
7
|
+
#
|
|
8
|
+
# Works across Claude Code / Factory / Cursor (all share the UserPromptSubmit
|
|
9
|
+
# event + the hookSpecificOutput.additionalContext output shape).
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-${FACTORY_PROJECT_DIR:-${CURSOR_PROJECT_DIR:-$(pwd)}}}"
|
|
13
|
+
|
|
14
|
+
# Read the harness payload and extract the user's prompt.
|
|
15
|
+
INPUT=$(cat)
|
|
16
|
+
PROMPT=$(printf '%s' "$INPUT" | python3 -c "import json,sys
|
|
17
|
+
try: print(json.load(sys.stdin).get('prompt',''))
|
|
18
|
+
except Exception: pass" 2>/dev/null || true)
|
|
19
|
+
|
|
20
|
+
# Skip trivial prompts — not worth a resolver round-trip.
|
|
21
|
+
[ "${#PROMPT}" -lt 12 ] && exit 0
|
|
22
|
+
|
|
23
|
+
# Resolve the uap binary (UAP_BIN override allows testing against a local build).
|
|
24
|
+
UAP_BIN="${UAP_BIN:-$(command -v uap 2>/dev/null || true)}"
|
|
25
|
+
[ -z "$UAP_BIN" ] && exit 0
|
|
26
|
+
|
|
27
|
+
# Build the reactor payload and call `uap react`.
|
|
28
|
+
PAYLOAD=$(UAP_PROMPT="$PROMPT" UAP_CWD="$PROJECT_DIR" python3 -c "import json,os
|
|
29
|
+
print(json.dumps({'event':'user-prompt','promptText':os.environ['UAP_PROMPT'],'cwd':os.environ['UAP_CWD']}))" 2>/dev/null || true)
|
|
30
|
+
[ -z "$PAYLOAD" ] && exit 0
|
|
31
|
+
|
|
32
|
+
RESULT=$(printf '%s' "$PAYLOAD" | $UAP_BIN react 2>/dev/null || true)
|
|
33
|
+
[ -z "$RESULT" ] && exit 0
|
|
34
|
+
|
|
35
|
+
INJECT=$(printf '%s' "$RESULT" | python3 -c "import json,sys
|
|
36
|
+
try: print(json.load(sys.stdin).get('inject',''))
|
|
37
|
+
except Exception: pass" 2>/dev/null || true)
|
|
38
|
+
[ -z "$INJECT" ] && exit 0
|
|
39
|
+
|
|
40
|
+
# Emit the harness additionalContext block.
|
|
41
|
+
UAP_INJECT="$INJECT" python3 -c "import json,os
|
|
42
|
+
print(json.dumps({'hookSpecificOutput':{'hookEventName':'UserPromptSubmit','additionalContext':os.environ['UAP_INJECT']}}))"
|
|
43
|
+
|
|
44
|
+
exit 0
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# UAP Schema-Change Reminder (PostToolUse) — enforce gap-fill.
|
|
3
|
+
# Fires when a schema/contract file is edited, reminding the agent to run
|
|
4
|
+
# `uap schema-diff` and re-verify API/consumer contracts before finalizing
|
|
5
|
+
# (the CLAUDE.md "Schema Diff Gate", auto-triggered).
|
|
6
|
+
# Advisory only — never blocks (always exits 0).
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
INPUT=$(cat)
|
|
10
|
+
FILE=$(printf '%s' "$INPUT" | python3 -c "import json,sys
|
|
11
|
+
try:
|
|
12
|
+
d = json.load(sys.stdin)
|
|
13
|
+
ti = d.get('tool_input') or d.get('args') or {}
|
|
14
|
+
print(ti.get('file_path') or ti.get('path') or '')
|
|
15
|
+
except Exception:
|
|
16
|
+
pass" 2>/dev/null || true)
|
|
17
|
+
|
|
18
|
+
[ -z "$FILE" ] && exit 0
|
|
19
|
+
|
|
20
|
+
case "$FILE" in
|
|
21
|
+
*.schema.ts|*schema*.ts|*/types.ts|*.proto|*.graphql|*.gql|*openapi*|*swagger*|*.avsc|*.prisma)
|
|
22
|
+
echo "[uap schema-gate] '$FILE' looks like a schema/contract file. Run \`uap schema-diff\` and re-verify API/consumer contracts before finalizing this change." >&2
|
|
23
|
+
;;
|
|
24
|
+
esac
|
|
25
|
+
|
|
26
|
+
exit 0
|