@miller-tech/uap 1.183.2 → 1.184.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 +14 -0
- package/dist/bin/cli.js.map +1 -1
- package/dist/cli/hooks.d.ts.map +1 -1
- package/dist/cli/hooks.js +20 -0
- package/dist/cli/hooks.js.map +1 -1
- package/dist/cli/memory.d.ts +14 -0
- package/dist/cli/memory.d.ts.map +1 -1
- package/dist/cli/memory.js +35 -0
- package/dist/cli/memory.js.map +1 -1
- package/dist/cli/principles.d.ts +10 -0
- package/dist/cli/principles.d.ts.map +1 -0
- package/dist/cli/principles.js +138 -0
- package/dist/cli/principles.js.map +1 -0
- package/dist/config/policy-recommendations.d.ts.map +1 -1
- package/dist/config/policy-recommendations.js +17 -0
- package/dist/config/policy-recommendations.js.map +1 -1
- package/dist/config/settings-registry.d.ts +1 -1
- package/dist/config/settings-registry.d.ts.map +1 -1
- package/dist/config/settings-registry.js +24 -0
- package/dist/config/settings-registry.js.map +1 -1
- package/dist/coordination/reactor.d.ts.map +1 -1
- package/dist/coordination/reactor.js +15 -0
- package/dist/coordination/reactor.js.map +1 -1
- package/dist/delivery/convergence-loop.d.ts +7 -1
- package/dist/delivery/convergence-loop.d.ts.map +1 -1
- package/dist/delivery/convergence-loop.js +32 -4
- package/dist/delivery/convergence-loop.js.map +1 -1
- package/dist/delivery/judge.d.ts.map +1 -1
- package/dist/delivery/judge.js +6 -0
- package/dist/delivery/judge.js.map +1 -1
- package/dist/delivery/task-orchestrator.d.ts.map +1 -1
- package/dist/delivery/task-orchestrator.js +8 -1
- package/dist/delivery/task-orchestrator.js.map +1 -1
- package/dist/principles/config.d.ts +10 -0
- package/dist/principles/config.d.ts.map +1 -0
- package/dist/principles/config.js +32 -0
- package/dist/principles/config.js.map +1 -0
- package/dist/principles/index.d.ts +16 -0
- package/dist/principles/index.d.ts.map +1 -0
- package/dist/principles/index.js +34 -0
- package/dist/principles/index.js.map +1 -0
- package/dist/principles/reactor-inject.d.ts +12 -0
- package/dist/principles/reactor-inject.d.ts.map +1 -0
- package/dist/principles/reactor-inject.js +69 -0
- package/dist/principles/reactor-inject.js.map +1 -0
- package/dist/principles/render.d.ts +14 -0
- package/dist/principles/render.d.ts.map +1 -0
- package/dist/principles/render.js +64 -0
- package/dist/principles/render.js.map +1 -0
- package/dist/principles/rules.d.ts +53 -0
- package/dist/principles/rules.d.ts.map +1 -0
- package/dist/principles/rules.js +101 -0
- package/dist/principles/rules.js.map +1 -0
- package/dist/principles/stance.d.ts +54 -0
- package/dist/principles/stance.d.ts.map +1 -0
- package/dist/principles/stance.js +154 -0
- package/dist/principles/stance.js.map +1 -0
- package/dist/types/config.d.ts +46 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +17 -0
- package/dist/types/config.js.map +1 -1
- package/docs/reference/CONFIGURATION_REFERENCE.md +221 -0
- package/docs/reference/PLATFORMS.md +1 -0
- package/package.json +1 -1
- package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
- package/src/policies/schemas/policies/engineering-principles.md +93 -0
- package/templates/hooks/__pycache__/deliver_autoroute.cpython-312.pyc +0 -0
- package/templates/hooks/post-tool-use-read.sh +72 -0
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
|
@@ -26,6 +26,7 @@ uap config wizard # interactive expert configurator (also: uap set
|
|
|
26
26
|
- [Orchestrator & hands-free](#orchestration) — Long-task autonomy: decompose, resume, and loop-to-100%.
|
|
27
27
|
- [Reactor (auto-apply)](#reactor) — Per-prompt injection of the matching experts, skills, and patterns.
|
|
28
28
|
- [Design system](#design) — DESIGN.md interrogation and the hard token gate for UI work.
|
|
29
|
+
- [Engineering principles](#principles) — How code should be written, and the backward-compatibility stance.
|
|
29
30
|
- [Worktree workflow](#worktree) — Branch-per-feature isolation and auto-cleanup.
|
|
30
31
|
- [Inference proxy tuning](#proxy) — Guardrails and context limits for a local model behind the proxy.
|
|
31
32
|
- [Dashboard](#dashboard) — The live analytics server and its mutation token.
|
|
@@ -60,6 +61,18 @@ How local-model sessions are routed through delivery. `deliver` runs builds thro
|
|
|
60
61
|
|
|
61
62
|
**Recommendation:** `deliver` when a local model does the writing (routes it through the verified loop); `advisory` for exploratory work.
|
|
62
63
|
|
|
64
|
+
### `deliver.escalateModel`
|
|
65
|
+
|
|
66
|
+
| | |
|
|
67
|
+
|---|---|
|
|
68
|
+
| **Where** | `.uap.json` |
|
|
69
|
+
| **Type** | string |
|
|
70
|
+
| **Default** | `null` |
|
|
71
|
+
|
|
72
|
+
Stronger model id for deliver escalation ladders: repair passes, the phase-5 escalation tier, and the evaluator fallback. Same role as $UAP_ESCALATE_MODEL but persisted in .uap.json (reproducible).
|
|
73
|
+
|
|
74
|
+
**Recommendation:** Point at your strongest available preset/model (e.g. an Opus cloud id) when the executor is a local model — stuck epics then escalate instead of re-splitting into the same wall.
|
|
75
|
+
|
|
63
76
|
### `UAP_ENFORCE_DELIVERY`
|
|
64
77
|
|
|
65
78
|
| | |
|
|
@@ -100,6 +113,30 @@ Installs the runtime-verify Stop-hook: at end of turn it actually runs the chang
|
|
|
100
113
|
|
|
101
114
|
**Recommendation:** Enable for any project with a runnable artifact — it catches "declared done but never ran". Safe on empty projects (it skips when nothing is runnable).
|
|
102
115
|
|
|
116
|
+
### `delivery.userValidation`
|
|
117
|
+
|
|
118
|
+
| | |
|
|
119
|
+
|---|---|
|
|
120
|
+
| **Where** | `.uap.json` |
|
|
121
|
+
| **Type** | string |
|
|
122
|
+
| **Default** | `block` |
|
|
123
|
+
|
|
124
|
+
User-path validation gate: deliver runs the .uap/user-paths.json critical journeys through the real client (headless browser / HTTP / built CLI) as the terminal gate rung. block = DELIVERED requires them green; advisory = report only; off = disabled.
|
|
125
|
+
|
|
126
|
+
**Recommendation:** Leave on block — it is the only gate that proves the artifact works for a real user, not just that tests pass.
|
|
127
|
+
|
|
128
|
+
### `UAP_USER_VALIDATION`
|
|
129
|
+
|
|
130
|
+
| | |
|
|
131
|
+
|---|---|
|
|
132
|
+
| **Where** | shell env |
|
|
133
|
+
| **Type** | boolean |
|
|
134
|
+
| **Default** | `true` |
|
|
135
|
+
|
|
136
|
+
Runtime downgrade for the user-validation gate: `0` demotes block to advisory for this run only. Persisting `0` is blocked by the self-protect enforcer.
|
|
137
|
+
|
|
138
|
+
**Recommendation:** Leave unset. Use inline `UAP_USER_VALIDATION=0 uap deliver ...` only to unblock a run where the gate itself misfires.
|
|
139
|
+
|
|
103
140
|
### `UAP_VERIFY_ON_STOP`
|
|
104
141
|
|
|
105
142
|
| | |
|
|
@@ -112,6 +149,78 @@ Master switch for the runtime execution gate in the Stop hook. `0` bypasses it.
|
|
|
112
149
|
|
|
113
150
|
**Recommendation:** Leave on (default). Set `0` only to unblock a session where the runtime gate misfires.
|
|
114
151
|
|
|
152
|
+
### `fidelity.mode`
|
|
153
|
+
|
|
154
|
+
| | |
|
|
155
|
+
|---|---|
|
|
156
|
+
| **Where** | `.uap.json` |
|
|
157
|
+
| **Type** | enum (standard \| max) |
|
|
158
|
+
| **Default** | `standard` |
|
|
159
|
+
|
|
160
|
+
Maximum-fidelity mode. `max` flips every verification default to its strongest: raised verifier floor (runtime+integration), acceptance judge required, blocking vision review, and a fail-CLOSED visual gate — a delivery is accepted only when it builds, runs, looks right, and matches the spec. (`UAP_FIDELITY` overrides at runtime.)
|
|
161
|
+
|
|
162
|
+
**Recommendation:** `max` when correctness matters more than speed (UI work, releases, hands-free autonomy). `standard` for fast exploratory iteration.
|
|
163
|
+
|
|
164
|
+
### `UAP_FIDELITY`
|
|
165
|
+
|
|
166
|
+
| | |
|
|
167
|
+
|---|---|
|
|
168
|
+
| **Where** | shell env |
|
|
169
|
+
| **Type** | enum (standard \| max) |
|
|
170
|
+
| **Default** | `standard` |
|
|
171
|
+
|
|
172
|
+
Runtime override of `fidelity.mode`, read from the shell env by verify/deliver and the Python enforcers. Takes precedence over the config value.
|
|
173
|
+
|
|
174
|
+
**Recommendation:** Set inline (`UAP_FIDELITY=max <cmd>`) to force max fidelity for one command without editing config.
|
|
175
|
+
|
|
176
|
+
### `fidelity.visionMinScore`
|
|
177
|
+
|
|
178
|
+
| | |
|
|
179
|
+
|---|---|
|
|
180
|
+
| **Where** | `.uap.json` |
|
|
181
|
+
| **Type** | number |
|
|
182
|
+
| **Default** | `6` |
|
|
183
|
+
|
|
184
|
+
Minimum aesthetic score (0–10) the vision judge must give a rendered UI before it passes under `max` fidelity.
|
|
185
|
+
|
|
186
|
+
**Recommendation:** 6 is a reasonable "looks like a real, polished app" bar. Raise toward 8 for design-critical surfaces; lower to 4 to only catch broken/blank UIs.
|
|
187
|
+
|
|
188
|
+
### `fidelity.visualBaselines`
|
|
189
|
+
|
|
190
|
+
| | |
|
|
191
|
+
|---|---|
|
|
192
|
+
| **Where** | `.uap.json` |
|
|
193
|
+
| **Type** | boolean |
|
|
194
|
+
| **Default** | `true` |
|
|
195
|
+
|
|
196
|
+
Keep approved UI screenshots as regression baselines under `.uap/visual/baseline/` and block on visual drift beyond threshold on later runs.
|
|
197
|
+
|
|
198
|
+
**Recommendation:** Leave on so accepted UIs are pinned against regressions. Disable for throwaway prototypes where every render legitimately differs.
|
|
199
|
+
|
|
200
|
+
### `UAP_VISION_ENDPOINT`
|
|
201
|
+
|
|
202
|
+
| | |
|
|
203
|
+
|---|---|
|
|
204
|
+
| **Where** | `.uap/proxy.env` |
|
|
205
|
+
| **Type** | string |
|
|
206
|
+
| **Default** | `` |
|
|
207
|
+
|
|
208
|
+
Base URL of an OpenAI-compatible, image_url-capable endpoint used for aesthetic screenshot review (e.g. http://127.0.0.1:8080/v1). Defaults to the local model when set by setup.
|
|
209
|
+
|
|
210
|
+
**Recommendation:** Point at your local vision-capable model so aesthetic review runs offline with no per-image cost.
|
|
211
|
+
|
|
212
|
+
### `UAP_VISION_MODEL`
|
|
213
|
+
|
|
214
|
+
| | |
|
|
215
|
+
|---|---|
|
|
216
|
+
| **Where** | `.uap/proxy.env` |
|
|
217
|
+
| **Type** | string |
|
|
218
|
+
| **Default** | `` |
|
|
219
|
+
|
|
220
|
+
Model id sent to the vision endpoint for aesthetic review (e.g. qwen36-35b-a3b-iq4xs).
|
|
221
|
+
|
|
222
|
+
**Recommendation:** Set by `uap setup` to your local vision model. Required for blocking vision review under `max` fidelity.
|
|
223
|
+
|
|
115
224
|
## Model routing
|
|
116
225
|
|
|
117
226
|
<a id="routing"></a>Which model handles planning, execution, and review.
|
|
@@ -482,6 +591,58 @@ Hard-blocks UI edits that hardcode off-token colors or off-scale spacing.
|
|
|
482
591
|
|
|
483
592
|
**Recommendation:** Enable once your DESIGN.md tokens are stable — it keeps the UI on-system automatically.
|
|
484
593
|
|
|
594
|
+
## Engineering principles
|
|
595
|
+
|
|
596
|
+
<a id="principles"></a>How code should be written, and the backward-compatibility stance.
|
|
597
|
+
|
|
598
|
+
### `principles.enabled`
|
|
599
|
+
|
|
600
|
+
| | |
|
|
601
|
+
|---|---|
|
|
602
|
+
| **Where** | `.uap.json` |
|
|
603
|
+
| **Type** | boolean |
|
|
604
|
+
| **Default** | `true` |
|
|
605
|
+
|
|
606
|
+
Applies the engineering principles (simplest sufficient implementation, reuse over reinvention, no stopgaps, prior art first) to generated code.
|
|
607
|
+
|
|
608
|
+
**Recommendation:** Leave on. Turn it off only if your project has its own conflicting house style.
|
|
609
|
+
|
|
610
|
+
### `principles.compat`
|
|
611
|
+
|
|
612
|
+
| | |
|
|
613
|
+
|---|---|
|
|
614
|
+
| **Where** | `.uap.json` |
|
|
615
|
+
| **Type** | enum (ask \| preserve \| remove) |
|
|
616
|
+
| **Default** | `ask` |
|
|
617
|
+
|
|
618
|
+
Backward-compatibility stance. `remove` deletes obsolete paths outright; `preserve` keeps them working and migrates callers; `ask` (default) prompts once per session instead of guessing.
|
|
619
|
+
|
|
620
|
+
**Recommendation:** Leave on `ask` unless the project's answer is settled. `remove` is for side projects — on anything published it tells the agent to delete migration paths.
|
|
621
|
+
|
|
622
|
+
### `principles.maturity`
|
|
623
|
+
|
|
624
|
+
| | |
|
|
625
|
+
|---|---|
|
|
626
|
+
| **Where** | `.uap.json` |
|
|
627
|
+
| **Type** | enum (ask \| greenfield \| production) |
|
|
628
|
+
| **Default** | `ask` |
|
|
629
|
+
|
|
630
|
+
What breaking a caller costs. `production` adds caveats about existing callers and dependency cost; `greenfield` states the rules absolutely.
|
|
631
|
+
|
|
632
|
+
**Recommendation:** Set `production` for anything with real users; `greenfield` for a fresh side project.
|
|
633
|
+
|
|
634
|
+
### `principles.injectDeliver`
|
|
635
|
+
|
|
636
|
+
| | |
|
|
637
|
+
|---|---|
|
|
638
|
+
| **Where** | `.uap.json` |
|
|
639
|
+
| **Type** | boolean |
|
|
640
|
+
| **Default** | `true` |
|
|
641
|
+
|
|
642
|
+
Injects the compact principles block into deliver prompts, so generated code follows them rather than only the agent preamble.
|
|
643
|
+
|
|
644
|
+
**Recommendation:** Leave on. Disable only if you are tight on prompt budget with a small-context model.
|
|
645
|
+
|
|
485
646
|
## Worktree workflow
|
|
486
647
|
|
|
487
648
|
<a id="worktree"></a>Branch-per-feature isolation and auto-cleanup.
|
|
@@ -651,6 +812,66 @@ Dashboard data refresh interval in milliseconds (floor 250).
|
|
|
651
812
|
|
|
652
813
|
**Recommendation:** 2000 is fine; lower for a more live feel at higher CPU cost.
|
|
653
814
|
|
|
815
|
+
### `proxy.dashboard`
|
|
816
|
+
|
|
817
|
+
| | |
|
|
818
|
+
|---|---|
|
|
819
|
+
| **Where** | `.uap.json` |
|
|
820
|
+
| **Type** | boolean |
|
|
821
|
+
| **Default** | `true` |
|
|
822
|
+
|
|
823
|
+
Ride-along dashboard: `uap proxy ensure|start` also starts (or adopts) `uap dashboard serve`, and release/stop tears it down under the same ownership rules — so a session gets monitoring without running a second command. Only takes effect where the proxy itself runs (hooks gate on proxy.autostart).
|
|
824
|
+
|
|
825
|
+
**Recommendation:** Leave on. Turn off if you prefer to run `uap dash serve` yourself, or the port is spoken for.
|
|
826
|
+
|
|
827
|
+
### `UAP_PROXY_DASHBOARD`
|
|
828
|
+
|
|
829
|
+
| | |
|
|
830
|
+
|---|---|
|
|
831
|
+
| **Where** | shell env |
|
|
832
|
+
| **Type** | boolean |
|
|
833
|
+
| **Default** | `true` |
|
|
834
|
+
|
|
835
|
+
Force the ride-along dashboard on (1/on/true) or off (0/off/false). Wins over .uap.json proxy.dashboard.
|
|
836
|
+
|
|
837
|
+
**Recommendation:** Use for one-off overrides; prefer `uap proxy dashboard on|off` for a durable project setting.
|
|
838
|
+
|
|
839
|
+
### `UAP_DASH_PORT`
|
|
840
|
+
|
|
841
|
+
| | |
|
|
842
|
+
|---|---|
|
|
843
|
+
| **Where** | shell env |
|
|
844
|
+
| **Type** | number |
|
|
845
|
+
| **Default** | `3847` |
|
|
846
|
+
|
|
847
|
+
Port the ride-along dashboard binds and is probed on (1-65535). Does not change `uap dash serve --port`.
|
|
848
|
+
|
|
849
|
+
**Recommendation:** Change only on a port clash; keep it consistent across sessions so adoption works.
|
|
850
|
+
|
|
851
|
+
### `UAP_DASH_HOST`
|
|
852
|
+
|
|
853
|
+
| | |
|
|
854
|
+
|---|---|
|
|
855
|
+
| **Where** | shell env |
|
|
856
|
+
| **Type** | string |
|
|
857
|
+
| **Default** | `localhost` |
|
|
858
|
+
|
|
859
|
+
Interface the ride-along dashboard binds. `0.0.0.0` exposes it beyond this machine.
|
|
860
|
+
|
|
861
|
+
**Recommendation:** Keep localhost. Bind wider only behind a trusted network, and set UAP_DASHBOARD_TOKEN when you do.
|
|
862
|
+
|
|
863
|
+
### `UAP_DASH_HEALTH_WAIT_MS`
|
|
864
|
+
|
|
865
|
+
| | |
|
|
866
|
+
|---|---|
|
|
867
|
+
| **Where** | shell env |
|
|
868
|
+
| **Type** | number |
|
|
869
|
+
| **Default** | `10000` |
|
|
870
|
+
|
|
871
|
+
How long `uap proxy ensure` waits for the ride-along dashboard to serve before giving up.
|
|
872
|
+
|
|
873
|
+
**Recommendation:** Lower it if session start feels slow on a cold dashboard; the proxy is unaffected either way.
|
|
874
|
+
|
|
654
875
|
## Token & time optimization
|
|
655
876
|
|
|
656
877
|
<a id="optimization"></a>Context budgets, caching, batching, and parallelism.
|
|
@@ -66,6 +66,7 @@ platform's lifecycle events:
|
|
|
66
66
|
| `pre-tool-use-bash.sh` | PreToolUse (Bash) | Dangerous-command guard — **blocks** force push, `terraform apply`, etc. |
|
|
67
67
|
| `uap-policy-gate.sh` | PreToolUse | DB-driven policy gate (`policies.db` + `.policy-tools/*.py`). |
|
|
68
68
|
| `post-tool-use-edit-write.sh` | PostToolUse (Edit/Write) | Build gate + backup reminder after edits. |
|
|
69
|
+
| `post-tool-use-read.sh` | PostToolUse (Read/Grep/Glob) | Writes `.uap/read_log.state` — the evidence `codebase-read-before-plan` gates on. |
|
|
69
70
|
| `pre-compact.sh` | PreCompact | Flushes a compaction marker to memory. |
|
|
70
71
|
| `post-compact.sh` | PostCompact | Re-injects policy awareness after compaction. |
|
|
71
72
|
| `stop.sh` | Stop | Completion-gate checklist + session cleanup. |
|
package/package.json
CHANGED
|
Binary file
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# engineering-principles
|
|
2
|
+
|
|
3
|
+
**Category**: quality
|
|
4
|
+
**Level**: RECOMMENDED
|
|
5
|
+
**Enforcement Stage**: pre-exec
|
|
6
|
+
**Tags**: quality, simplicity, architecture, dependencies, prior-art
|
|
7
|
+
|
|
8
|
+
## Rule
|
|
9
|
+
|
|
10
|
+
Write code to these principles. Rules 2-8 always apply. Rule 1 depends on a
|
|
11
|
+
stance resolved per project per session — run `uap principles show` to see the
|
|
12
|
+
form in force, and `uap principles ask` to answer it.
|
|
13
|
+
|
|
14
|
+
1. **Backward compatibility — stance-dependent.**
|
|
15
|
+
- `remove`: delete obsolete paths instead of adding compatibility layers,
|
|
16
|
+
fallbacks, or migrations.
|
|
17
|
+
- `preserve`: keep existing paths working and migrate callers before
|
|
18
|
+
removing anything.
|
|
19
|
+
|
|
20
|
+
Under `remove`, these surfaces are still preserved and migrated, never
|
|
21
|
+
deleted, because their callers are not yours to update:
|
|
22
|
+
- the public CLI surface — command names, flags, and their output contracts
|
|
23
|
+
- MCP tool names and input schemas
|
|
24
|
+
- database, config, and on-disk state schemas, including their migrations
|
|
25
|
+
- exported types and public module entry points
|
|
26
|
+
|
|
27
|
+
2. **Choose the simplest implementation that fully meets the current
|
|
28
|
+
requirements.** Avoid speculative abstractions, configuration, and
|
|
29
|
+
indirection.
|
|
30
|
+
|
|
31
|
+
3. **Grow the system in layers.** Start from the smallest version that works end
|
|
32
|
+
to end, and add each new capability on top of a product that already works.
|
|
33
|
+
Never trade a working product for unfinished complexity.
|
|
34
|
+
|
|
35
|
+
4. **Keep components modular and concerns clearly separated.**
|
|
36
|
+
|
|
37
|
+
5. **Prefer established, well-maintained libraries** when they reduce overall
|
|
38
|
+
complexity or improve reliability. Do not reimplement common functionality
|
|
39
|
+
without a clear reason.
|
|
40
|
+
|
|
41
|
+
6. **Lean on the dependencies already in the project** before writing your own
|
|
42
|
+
implementation or adding packages. Do not assume a library lacks a capability
|
|
43
|
+
without checking its documentation and types.
|
|
44
|
+
|
|
45
|
+
7. **Make architectural decisions for the long term.** Do not accept a stopgap
|
|
46
|
+
that only works for now and is meant to be replaced later.
|
|
47
|
+
|
|
48
|
+
8. **Study how established products solve the problem before designing a
|
|
49
|
+
solution.** Adopt their proven patterns and conventions rather than inventing
|
|
50
|
+
an approach from scratch.
|
|
51
|
+
|
|
52
|
+
## Why
|
|
53
|
+
|
|
54
|
+
Adapted from an AGENTS.md distilled from roughly 60B tokens of agent-driven
|
|
55
|
+
coding (x.com/MarcosHernanz/status/2083954734487212511). Its author scopes it to
|
|
56
|
+
side projects — "don't use it in production if you don't want to destroy your
|
|
57
|
+
codebase" — and rule 1 is why: deleting obsolete paths is right when you own
|
|
58
|
+
every caller and destructive when you do not. Rather than adopt or drop rule 1
|
|
59
|
+
wholesale, UAP resolves it per project per session and carves out the surfaces
|
|
60
|
+
other people are bound to.
|
|
61
|
+
|
|
62
|
+
The remaining rules are direction-of-travel guidance, not gates. They are
|
|
63
|
+
RECOMMENDED because a machine cannot tell a speculative abstraction from a
|
|
64
|
+
necessary one, and a blocking check that guesses would cost more than it saves.
|
|
65
|
+
|
|
66
|
+
## Enforcement
|
|
67
|
+
|
|
68
|
+
Advisory. There is no Python enforcer: these are judgment calls, and blocking
|
|
69
|
+
gates in this repo have repeatedly cost more in false positives than they
|
|
70
|
+
prevented. The principles reach the model three other ways:
|
|
71
|
+
|
|
72
|
+
- **Deliver prompts** — the compact form is injected into every convergence-loop
|
|
73
|
+
and orchestrated task prompt, so generated code is held to them rather than
|
|
74
|
+
only the agent's preamble.
|
|
75
|
+
- **Reactor** — while the rule-1 stance is unresolved, the agent is told to ask
|
|
76
|
+
the user once; after that it stays silent.
|
|
77
|
+
- **Judge** — competing candidates are scored on reuse-over-reimplementation and
|
|
78
|
+
absence of stopgaps.
|
|
79
|
+
|
|
80
|
+
Related: pattern P38 (Prior Art First) covers rules 5, 6 and 8 at plan time; the
|
|
81
|
+
`/simplify` and `distill` skills cover rule 2 on existing code.
|
|
82
|
+
|
|
83
|
+
```rules
|
|
84
|
+
- title: "Simplest implementation that meets the requirement"
|
|
85
|
+
keywords: [implement, refactor, design, abstraction, config, indirection]
|
|
86
|
+
antiPatterns: [speculative-abstraction, premature-config, needless-indirection]
|
|
87
|
+
- title: "Reuse before reimplementation"
|
|
88
|
+
keywords: [library, dependency, package, util, helper, from scratch]
|
|
89
|
+
antiPatterns: [reimplemented-common-functionality, unchecked-library-capability]
|
|
90
|
+
- title: "No stopgaps"
|
|
91
|
+
keywords: [temporary, for now, placeholder, replace later, quick fix]
|
|
92
|
+
antiPatterns: [stopgap-architecture, deferred-rewrite]
|
|
93
|
+
```
|
|
Binary file
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# UAP Read Logger — INFORMATIONAL hook
|
|
3
|
+
# Event: PostToolUse (matcher: Read|Grep|Glob)
|
|
4
|
+
# Appends "<epoch>\t<path>" to .uap/read_log.state, which is the evidence the
|
|
5
|
+
# codebase-read-before-plan enforcer checks before allowing a plan to be emitted.
|
|
6
|
+
#
|
|
7
|
+
# Without this hook that enforcer has no writer: the log goes stale, every entry
|
|
8
|
+
# ages past its 30-minute window, and ExitPlanMode is blocked permanently with a
|
|
9
|
+
# remedy ("read the codebase first") that can never be satisfied.
|
|
10
|
+
#
|
|
11
|
+
# Runs on EVERY Read/Grep/Glob — thousands of times a session, in the latency
|
|
12
|
+
# path of each one — so it does its work in bash builtins and forks exactly once
|
|
13
|
+
# (jq, which earns it: the payload shape differs per tool).
|
|
14
|
+
#
|
|
15
|
+
# Always exits 0 (never blocks).
|
|
16
|
+
set -uo pipefail
|
|
17
|
+
|
|
18
|
+
# Drain stdin without forking `cat`. `read -d ''` returns non-zero at EOF while
|
|
19
|
+
# still populating INPUT, so the failure is expected, not an error.
|
|
20
|
+
IFS= read -r -d '' INPUT || true
|
|
21
|
+
[ -n "${INPUT:-}" ] || exit 0
|
|
22
|
+
|
|
23
|
+
# Read passes file_path; Grep/Glob pass path (search root) and/or pattern.
|
|
24
|
+
TARGET=$(jq -r '
|
|
25
|
+
.tool_input.file_path // .tool_input.filePath // .tool_input.path // .tool_input.pattern // empty
|
|
26
|
+
' 2>/dev/null <<< "$INPUT" || true)
|
|
27
|
+
[ -n "$TARGET" ] || exit 0
|
|
28
|
+
|
|
29
|
+
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-.}"
|
|
30
|
+
STATE_DIR="${UAP_STATE_DIR:-${PROJECT_DIR}/.uap}"
|
|
31
|
+
LOG="${STATE_DIR}/read_log.state"
|
|
32
|
+
|
|
33
|
+
[ -d "$STATE_DIR" ] || mkdir -p "$STATE_DIR" 2>/dev/null || exit 0
|
|
34
|
+
|
|
35
|
+
# SECURITY: never append through a symlink. `>>` follows links, so a symlink
|
|
36
|
+
# planted at read_log.state would turn every file read in the session into an
|
|
37
|
+
# append to whatever it points at (~/.bashrc), with partly model-supplied
|
|
38
|
+
# content — an arbitrary-file-write primitive that escapes workdir-scope
|
|
39
|
+
# entirely. Writing the evidence is optional; this is not.
|
|
40
|
+
[ -L "$LOG" ] && exit 0
|
|
41
|
+
|
|
42
|
+
# Store project-relative where possible so entries stay readable across worktrees.
|
|
43
|
+
REL="${TARGET#"$PROJECT_DIR"/}"
|
|
44
|
+
# SECURITY: a record is "<epoch>\t<path>\n" and TARGET is model-supplied — a Grep
|
|
45
|
+
# pattern may legally contain tabs and newlines. Strip the two characters that
|
|
46
|
+
# frame a record so a crafted pattern cannot forge additional log entries (and
|
|
47
|
+
# thereby forge the gate evidence this file exists to provide).
|
|
48
|
+
REL="${REL//$'\t'/ }"
|
|
49
|
+
REL="${REL//$'\n'/ }"
|
|
50
|
+
REL="${REL//$'\r'/ }"
|
|
51
|
+
|
|
52
|
+
printf -v NOW '%(%s)T' -1 # bash builtin; no `date` fork
|
|
53
|
+
printf '%s\t%s\n' "$NOW" "$REL" >> "$LOG" 2>/dev/null || exit 0
|
|
54
|
+
|
|
55
|
+
# Bound the file. The enforcer only ever looks at a 30-minute window, so old
|
|
56
|
+
# lines are dead weight. Sampled rather than checked every call: reading the log
|
|
57
|
+
# on every Read to decide whether to trim costs more than the occasional
|
|
58
|
+
# overshoot, and the consumer filters by timestamp anyway.
|
|
59
|
+
if (( RANDOM % 50 == 0 )); then
|
|
60
|
+
mapfile -t _lines < "$LOG" 2>/dev/null || exit 0
|
|
61
|
+
if (( ${#_lines[@]} > 400 )); then
|
|
62
|
+
# PID-unique temp: several agents share one project, and a shared temp name
|
|
63
|
+
# lets two concurrent trims interleave into one file and lose entries.
|
|
64
|
+
if printf '%s\n' "${_lines[@]: -200}" > "${LOG}.tmp.$$" 2>/dev/null; then
|
|
65
|
+
mv "${LOG}.tmp.$$" "$LOG" 2>/dev/null || rm -f "${LOG}.tmp.$$" 2>/dev/null
|
|
66
|
+
else
|
|
67
|
+
rm -f "${LOG}.tmp.$$" 2>/dev/null
|
|
68
|
+
fi
|
|
69
|
+
fi
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
exit 0
|