@esoteric-logic/praxis-harness 2.9.1 → 2.11.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/base/CLAUDE.md +32 -9
- package/base/configs/registry.json +2 -1
- package/base/hooks/on-stop-failure.sh +121 -0
- package/base/hooks/settings-hooks.json +11 -0
- package/base/rules/api-quality.md +25 -0
- package/base/{skills → rules}/code-excellence.md +9 -2
- package/base/rules/css-quality.md +25 -0
- package/base/rules/desktop-protocol.md +64 -0
- package/base/rules/go-quality.md +25 -0
- package/base/rules/java-quality.md +25 -0
- package/base/rules/python-quality.md +25 -0
- package/base/rules/rust-quality.md +25 -0
- package/base/rules/shell-quality.md +26 -0
- package/base/rules/sql-quality.md +25 -0
- package/base/rules/typescript-quality.md +26 -0
- package/package.json +1 -1
- /package/base/{skills → rules}/engineering-judgment.md +0 -0
- /package/base/{skills → rules}/self-verify.md +0 -0
package/base/CLAUDE.md
CHANGED
|
@@ -56,6 +56,13 @@ Vault path and backend are machine-specific. Read from `~/.claude/praxis.config.
|
|
|
56
56
|
If config file is missing: tell the user to run `praxis/install.sh`.
|
|
57
57
|
All `{vault_path}` references in rules and skills resolve from this config.
|
|
58
58
|
|
|
59
|
+
## Model & Context Policy
|
|
60
|
+
- Default model: `claude-opus-4-6` (set `ANTHROPIC_MODEL` in shell profile)
|
|
61
|
+
- Sub-agents spawned by Praxis skills: use `haiku` for polling, search, and lint tasks
|
|
62
|
+
- Compact trigger: when context approaches ceiling, finish the current milestone first
|
|
63
|
+
- Never compact mid-plan — complete the milestone, write phase summary to vault, then compact
|
|
64
|
+
- After compaction: re-bootstrap from § After Compaction below, re-run quality checks fresh
|
|
65
|
+
|
|
59
66
|
## Durable Memory
|
|
60
67
|
Context is volatile. Files are permanent. Act accordingly.
|
|
61
68
|
|
|
@@ -135,27 +142,42 @@ Kit manifests live in `~/.claude/kits/<name>/KIT.md`.
|
|
|
135
142
|
|
|
136
143
|
## Rules Registry — Load on Demand Only
|
|
137
144
|
|
|
138
|
-
### Universal — always active (
|
|
145
|
+
### Universal — always active (12 rules)
|
|
146
|
+
|
|
147
|
+
Quality is a generation-time constraint, not a post-hoc review. The rules below
|
|
148
|
+
are the lens you write through — they shape every line of code produced.
|
|
149
|
+
|
|
139
150
|
| File | Purpose |
|
|
140
151
|
|------|---------|
|
|
141
152
|
| `~/.claude/rules/profile.md` | Who the user is, identities, working style |
|
|
142
153
|
| `~/.claude/rules/execution-loop.md` | SPEC/PLAN/VALIDATE loop enforcement |
|
|
143
154
|
| `~/.claude/rules/coding.md` | Context7 mandate, tool preferences, quality architecture reference |
|
|
144
|
-
| `~/.claude/rules/code-quality.md` |
|
|
155
|
+
| `~/.claude/rules/code-quality.md` | Active constraints — hard limits during generation (30 lines, 3 nesting, 4 params) |
|
|
156
|
+
| `~/.claude/rules/code-excellence.md` | Core principles — simplicity, correctness, naming, error design, dependency hygiene |
|
|
157
|
+
| `~/.claude/rules/engineering-judgment.md` | Meta-reasoning — Five Questions, YAGNI, Rule of Three, reversibility test |
|
|
158
|
+
| `~/.claude/rules/self-verify.md` | Self-verification — 24-check protocol before every commit |
|
|
145
159
|
| `~/.claude/rules/git-workflow.md` | Commits, branches, identity verification, pre-commit checks |
|
|
146
160
|
| `~/.claude/rules/vault.md` | Second brain integration — vault backend, file purposes |
|
|
147
161
|
| `~/.claude/rules/context-management.md` | Context anti-rot, phase scoping, context reset protocol |
|
|
148
162
|
| `~/.claude/rules/memory-boundary.md` | Auto-memory boundary, MEMORY.md cap, dream integration |
|
|
149
163
|
| `~/.claude/rules/security-posture.md` | Sandbox model, credential protection, protected paths |
|
|
150
164
|
|
|
151
|
-
### Skills — loaded at session start
|
|
152
|
-
| File | Purpose |
|
|
153
|
-
|------|---------|
|
|
154
|
-
| `~/.claude/skills/code-excellence.md` | Layer 1: Principles — shapes reasoning about code |
|
|
155
|
-
| `~/.claude/skills/engineering-judgment.md` | Layer 1: Meta-reasoning — principal engineer decision framework |
|
|
156
|
-
| `~/.claude/skills/self-verify.md` | Layer 3: Self-verification protocol — proves correctness before commit |
|
|
157
|
-
|
|
158
165
|
### Scoped — load only when paths match
|
|
166
|
+
|
|
167
|
+
#### Language quality (generation-time constraints per language)
|
|
168
|
+
| File | Loads when |
|
|
169
|
+
|------|------------|
|
|
170
|
+
| `~/.claude/rules/python-quality.md` | `**/*.py` |
|
|
171
|
+
| `~/.claude/rules/typescript-quality.md` | `**/*.ts`, `**/*.tsx` |
|
|
172
|
+
| `~/.claude/rules/shell-quality.md` | `**/*.sh` |
|
|
173
|
+
| `~/.claude/rules/go-quality.md` | `**/*.go` |
|
|
174
|
+
| `~/.claude/rules/rust-quality.md` | `**/*.rs` |
|
|
175
|
+
| `~/.claude/rules/java-quality.md` | `**/*.java` |
|
|
176
|
+
| `~/.claude/rules/css-quality.md` | `**/*.css`, `**/*.scss`, `**/*.less` |
|
|
177
|
+
| `~/.claude/rules/sql-quality.md` | `**/*.sql` |
|
|
178
|
+
| `~/.claude/rules/api-quality.md` | `**/routes/**`, `**/api/**`, `**/controllers/**`, `**/handlers/**` |
|
|
179
|
+
|
|
180
|
+
#### Infrastructure and tooling
|
|
159
181
|
| File | Loads when |
|
|
160
182
|
|------|------------|
|
|
161
183
|
| `~/.claude/rules/azure.md` | `**/*.tf`, `**/*.bicep`, `**/*.azcli` |
|
|
@@ -164,6 +186,7 @@ Kit manifests live in `~/.claude/kits/<name>/KIT.md`.
|
|
|
164
186
|
| `~/.claude/rules/powershell.md` | `**/*.ps1`, `**/*.psm1` |
|
|
165
187
|
| `~/.claude/rules/dependency-freshness.md` | `package.json`, `go.mod`, `requirements.txt`, `Cargo.toml`, `pyproject.toml` |
|
|
166
188
|
| `~/.claude/rules/live-docs-required.md` | Dependency manifests, files importing external packages |
|
|
189
|
+
| `~/.claude/rules/desktop-protocol.md` | Claude Desktop ↔ Claude Code handoff sessions |
|
|
167
190
|
|
|
168
191
|
### Auto-invocable skills (replace former universal rules)
|
|
169
192
|
| Skill | Triggers when |
|
|
@@ -101,7 +101,8 @@
|
|
|
101
101
|
{"path": "base/hooks/file-guard.sh", "event": "PreToolUse", "matcher": "Write|Edit|MultiEdit"},
|
|
102
102
|
{"path": "base/hooks/identity-check.sh", "event": "PreToolUse", "matcher": "Bash"},
|
|
103
103
|
{"path": "base/hooks/credential-guard.sh", "event": "PreToolUse", "matcher": "Bash"},
|
|
104
|
-
{"path": "base/hooks/session-data-collect.sh", "event": "Stop", "matcher": ""}
|
|
104
|
+
{"path": "base/hooks/session-data-collect.sh", "event": "Stop", "matcher": ""},
|
|
105
|
+
{"path": "base/hooks/on-stop-failure.sh", "event": "StopFailure", "matcher": ""}
|
|
105
106
|
],
|
|
106
107
|
"optional": [
|
|
107
108
|
{"path": "base/hooks/recursion-guard.sh", "event": "PreToolUse", "matcher": "", "feature": "recursion-detection"},
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# on-stop-failure.sh — StopFailure hook (Auto mode failure classifier)
|
|
3
|
+
# Reads Claude's stop context, classifies the failure, and either:
|
|
4
|
+
# - Auto-repairs (transient: test fail, lint fail, tool error) → exit 0 (continue)
|
|
5
|
+
# - Escalates to human (boundary/spec/security violation) → exit 1 (halt)
|
|
6
|
+
# Tracks repair attempts per failure fingerprint to prevent infinite loops.
|
|
7
|
+
# Reuses PPID-scoped state pattern from recursion-guard.sh.
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
if ! command -v jq &>/dev/null; then
|
|
11
|
+
echo "on-stop-failure: jq required but not found. Cannot classify failure." >&2
|
|
12
|
+
exit 1
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
# ── Parse input (single jq call) ──
|
|
16
|
+
INPUT=$(cat)
|
|
17
|
+
PARSED=$(echo "$INPUT" | jq -r '[
|
|
18
|
+
(.exit_code // 1 | tostring),
|
|
19
|
+
(.stop_reason // ""),
|
|
20
|
+
(.last_tool_use.name // ""),
|
|
21
|
+
(.last_tool_use.error // "")
|
|
22
|
+
] | join("\t")' 2>/dev/null || echo "1\t\t\t")
|
|
23
|
+
|
|
24
|
+
IFS=$'\t' read -r EXIT_CODE STOP_REASON LAST_TOOL TOOL_ERROR <<< "$PARSED"
|
|
25
|
+
|
|
26
|
+
MAX_REPAIR_ATTEMPTS=3
|
|
27
|
+
MAX_FINGERPRINT_LEN=200
|
|
28
|
+
|
|
29
|
+
# ── Repair attempt tracker (PPID-scoped, same pattern as recursion-guard.sh) ──
|
|
30
|
+
REPAIR_STATE="/tmp/praxis-repair-${PPID}.json"
|
|
31
|
+
if [[ ! -f "$REPAIR_STATE" ]]; then
|
|
32
|
+
echo '{"repair_attempts":0,"last_fingerprint":""}' > "$REPAIR_STATE"
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# Compare raw fingerprint strings — no hash needed for equality checks
|
|
36
|
+
FINGERPRINT="${EXIT_CODE}:${LAST_TOOL}:${STOP_REASON:0:$MAX_FINGERPRINT_LEN}"
|
|
37
|
+
|
|
38
|
+
# Single jq call to read both fields
|
|
39
|
+
STATE_READ=$(jq -r '[(.last_fingerprint // ""), (.repair_attempts // 0 | tostring)] | join("\t")' "$REPAIR_STATE" 2>/dev/null || echo $'\t0')
|
|
40
|
+
IFS=$'\t' read -r LAST_FINGERPRINT CURRENT_ATTEMPTS <<< "$STATE_READ"
|
|
41
|
+
|
|
42
|
+
# Same fingerprint = looping on the same error
|
|
43
|
+
if [[ "$FINGERPRINT" == "$LAST_FINGERPRINT" ]]; then
|
|
44
|
+
CURRENT_ATTEMPTS=$((CURRENT_ATTEMPTS + 1))
|
|
45
|
+
else
|
|
46
|
+
CURRENT_ATTEMPTS=1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Atomic state file update (tmp + mv)
|
|
50
|
+
TMP_STATE="${REPAIR_STATE}.tmp"
|
|
51
|
+
jq -n --argjson attempts "$CURRENT_ATTEMPTS" --arg fp "$FINGERPRINT" \
|
|
52
|
+
'{"repair_attempts": $attempts, "last_fingerprint": $fp}' \
|
|
53
|
+
> "$TMP_STATE" && mv "$TMP_STATE" "$REPAIR_STATE"
|
|
54
|
+
|
|
55
|
+
# ── Hard escalation: too many repair attempts on same failure ──
|
|
56
|
+
if [[ $CURRENT_ATTEMPTS -gt $MAX_REPAIR_ATTEMPTS ]]; then
|
|
57
|
+
echo "AUTO-REPAIR EXHAUSTED: $CURRENT_ATTEMPTS attempts on same failure." >&2
|
|
58
|
+
echo "Failure: exit=$EXIT_CODE tool=$LAST_TOOL" >&2
|
|
59
|
+
echo "Halting — human review required." >&2
|
|
60
|
+
|
|
61
|
+
CONFIG="$HOME/.claude/praxis.config.json"
|
|
62
|
+
if [[ -f "$CONFIG" ]]; then
|
|
63
|
+
VAULT_PATH=$(jq -r '.vault_path // ""' "$CONFIG" 2>/dev/null)
|
|
64
|
+
if [[ -n "$VAULT_PATH" && -d "$VAULT_PATH" ]]; then
|
|
65
|
+
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
66
|
+
ESCALATION_FILE="$VAULT_PATH/notes/escalations.md"
|
|
67
|
+
|
|
68
|
+
if [[ ! -f "$ESCALATION_FILE" ]]; then
|
|
69
|
+
printf -- "---\ntags: [escalation, auto-repair]\ndate: %s\nsource: agent\n---\n\n# Auto-Repair Escalations\n" \
|
|
70
|
+
"$(date +%Y-%m-%d)" > "$ESCALATION_FILE"
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
printf "\n## %s\n- **Failure**: exit=%s tool=%s\n- **Attempts**: %s\n- **Reason**: %s\n- **Status**: HALTED — needs human review\n" \
|
|
74
|
+
"$TIMESTAMP" "$EXIT_CODE" "$LAST_TOOL" "$CURRENT_ATTEMPTS" "${STOP_REASON:0:$MAX_FINGERPRINT_LEN}" \
|
|
75
|
+
>> "$ESCALATION_FILE"
|
|
76
|
+
fi
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
exit 1
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
# ── Hard escalation patterns (single regex, never auto-repair these) ──
|
|
83
|
+
HARD_REGEX="BLOCKED:|secret detected|Protected path|out of scope|permission denied|identity mismatch"
|
|
84
|
+
COMBINED_CONTEXT="$STOP_REASON $TOOL_ERROR"
|
|
85
|
+
|
|
86
|
+
if echo "$COMBINED_CONTEXT" | grep -qiE "$HARD_REGEX"; then
|
|
87
|
+
MATCHED=$(echo "$COMBINED_CONTEXT" | grep -oiE "$HARD_REGEX" | head -1)
|
|
88
|
+
echo "ESCALATING: Hard violation — '$MATCHED' matched." >&2
|
|
89
|
+
echo "Auto-repair suppressed. Human review required." >&2
|
|
90
|
+
exit 1
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# Exit code 2 = guard hard-block (recursion-guard.sh, secret-scan.sh, file-guard.sh convention)
|
|
94
|
+
if [[ "$EXIT_CODE" == "2" ]]; then
|
|
95
|
+
echo "ESCALATING: Exit code 2 = guard hard-block. No auto-repair." >&2
|
|
96
|
+
exit 1
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
# ── Transient failure → emit repair prompt (Auto mode continues) ──
|
|
100
|
+
# Claude Code reads stdout from StopFailure hooks as an injected prompt.
|
|
101
|
+
|
|
102
|
+
cat <<REPAIR
|
|
103
|
+
Auto-repair attempt $CURRENT_ATTEMPTS of $MAX_REPAIR_ATTEMPTS.
|
|
104
|
+
|
|
105
|
+
Failure context:
|
|
106
|
+
- Exit code: $EXIT_CODE
|
|
107
|
+
- Last tool: $LAST_TOOL
|
|
108
|
+
- Stop reason: ${STOP_REASON:0:500}
|
|
109
|
+
- Tool error: ${TOOL_ERROR:0:$MAX_FINGERPRINT_LEN}
|
|
110
|
+
|
|
111
|
+
Instructions:
|
|
112
|
+
1. Read the error above carefully. Identify the root cause from actual output.
|
|
113
|
+
2. Apply the minimum fix required. Do not expand scope.
|
|
114
|
+
3. Re-run validation (tests + lint) after fixing.
|
|
115
|
+
4. If this is attempt $CURRENT_ATTEMPTS of $MAX_REPAIR_ATTEMPTS and the fix is not obvious:
|
|
116
|
+
report What / So What / Now What and halt.
|
|
117
|
+
|
|
118
|
+
Do NOT re-attempt the same approach that just failed.
|
|
119
|
+
REPAIR
|
|
120
|
+
|
|
121
|
+
exit 0
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# API Quality — Generation Constraints
|
|
2
|
+
# Scope: **/routes/**, **/api/**, **/controllers/**, **/handlers/**
|
|
3
|
+
# Active during code generation, not post-hoc review
|
|
4
|
+
|
|
5
|
+
## Invariants — BLOCK on violation
|
|
6
|
+
|
|
7
|
+
- Validate all input before touching business logic — type, range, format, length.
|
|
8
|
+
- Auth and permission checks execute before any data access — never after.
|
|
9
|
+
- Every endpoint has an explicit error response shape — no raw stack traces to callers.
|
|
10
|
+
- No raw database objects in responses — always project to a response type or DTO.
|
|
11
|
+
- Parameterized queries only — never concatenate user input into SQL or query strings.
|
|
12
|
+
- Rate limiting or pagination on any endpoint that returns unbounded collections.
|
|
13
|
+
|
|
14
|
+
## Conventions — WARN on violation
|
|
15
|
+
|
|
16
|
+
- Consistent error response format across all endpoints (status, code, message, details).
|
|
17
|
+
- Idempotency keys on state-changing operations that clients may retry.
|
|
18
|
+
- Request correlation IDs for tracing — propagate through the call chain.
|
|
19
|
+
- CORS, CSRF, and security headers configured explicitly — not inherited from defaults.
|
|
20
|
+
- Separate validation errors (400) from auth errors (401/403) from not-found (404) from server errors (500).
|
|
21
|
+
- Log request context (method, path, status, duration) — never log request bodies containing PII.
|
|
22
|
+
- API versioning strategy declared before first endpoint is written.
|
|
23
|
+
|
|
24
|
+
## Removal Condition
|
|
25
|
+
Remove when an API-specific linter rule engine replaces generation-time constraints.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Code Excellence — Core Principles
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
These principles shape how you reason about code before writing a single character.
|
|
4
|
+
They are not a checklist — they are a worldview. They are always active.
|
|
5
5
|
|
|
6
6
|
## The Prime Directive
|
|
7
7
|
Write code that the next engineer will thank you for.
|
|
@@ -21,6 +21,13 @@ Before adding any abstraction, answer all three:
|
|
|
21
21
|
- Would a new engineer understand the code FASTER with this abstraction than without it?
|
|
22
22
|
If any answer is no — do not add it. Inline the logic.
|
|
23
23
|
|
|
24
|
+
Over-engineering red flags — stop and simplify if you see yourself writing:
|
|
25
|
+
- An interface/factory/strategy with exactly one implementation
|
|
26
|
+
- A wrapper function whose entire body is a single delegating call
|
|
27
|
+
- Unused type parameters, config options no caller sets, plugin systems with one plugin
|
|
28
|
+
- Observer/EventEmitter with 2 listeners, Singleton for a module variable, Builder for 3 fields
|
|
29
|
+
- A function with boolean flags that switch behavior — write two functions instead
|
|
30
|
+
|
|
24
31
|
## On Correctness
|
|
25
32
|
Correctness means the code does exactly what its name promises. Not more. Not less.
|
|
26
33
|
A function named `getUserById` returns a user by ID.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# CSS Quality — Generation Constraints
|
|
2
|
+
# Scope: **/*.css, **/*.scss, **/*.less
|
|
3
|
+
# Active during code generation, not post-hoc review
|
|
4
|
+
|
|
5
|
+
## Invariants — BLOCK on violation
|
|
6
|
+
|
|
7
|
+
- No `!important` — fix the specificity problem instead.
|
|
8
|
+
- No hardcoded color values — use design tokens or CSS custom properties.
|
|
9
|
+
- No `px` for font sizes — use `rem` for scalability and accessibility.
|
|
10
|
+
- No `z-index` without a comment and reference to the project's z-index scale.
|
|
11
|
+
- No layout via `float` — use flexbox or grid.
|
|
12
|
+
|
|
13
|
+
## Conventions — WARN on violation
|
|
14
|
+
|
|
15
|
+
- CSS custom properties (`--var`) for all recurring values: spacing, colors, radii, shadows.
|
|
16
|
+
- Mobile-first media queries (`min-width`) — never desktop-first (`max-width`).
|
|
17
|
+
- Logical properties (`margin-inline`, `padding-block`) over physical (`margin-left`, `padding-top`).
|
|
18
|
+
- `gap` for spacing between flex/grid items — not margin hacks on children.
|
|
19
|
+
- Prefer `clamp()` for fluid typography and spacing over media query breakpoints.
|
|
20
|
+
- `:focus-visible` over `:focus` for keyboard-only focus indicators.
|
|
21
|
+
- `prefers-reduced-motion` media query wrapping any animation or transition.
|
|
22
|
+
- BEM or utility-class convention — never bare tag selectors outside resets.
|
|
23
|
+
|
|
24
|
+
## Removal Condition
|
|
25
|
+
Remove when a CSS-specific linter rule engine replaces generation-time constraints.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Desktop Protocol — Rules
|
|
2
|
+
# Scope: Sessions involving Claude Desktop ↔ Claude Code handoff
|
|
3
|
+
# Defines role boundaries and structured handoff format
|
|
4
|
+
|
|
5
|
+
## Role Boundaries
|
|
6
|
+
|
|
7
|
+
| Surface | Role | Responsible for |
|
|
8
|
+
|---------|------|-----------------|
|
|
9
|
+
| Claude Desktop | Architect / Reviewer | ADR review, security audit, diff validation, prompt engineering |
|
|
10
|
+
| Claude Code | Executor | File writes, git ops, test runs, tool use, vault updates |
|
|
11
|
+
|
|
12
|
+
Desktop generates structured intent. Code executes it.
|
|
13
|
+
Never use Desktop for file writes. Never use Code for open-ended architecture debate.
|
|
14
|
+
|
|
15
|
+
## Handoff Format — Desktop → Code
|
|
16
|
+
|
|
17
|
+
When Desktop completes a review or decision, it emits a structured handoff block.
|
|
18
|
+
Code reads this block as its initial task context.
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
HANDOFF:
|
|
22
|
+
TASK: [one-line description]
|
|
23
|
+
SPEC: [link to vault plan or spec file]
|
|
24
|
+
CONSTRAINTS: [hard limits — what must NOT change]
|
|
25
|
+
ACCEPTANCE: [how to know it's done]
|
|
26
|
+
CONTEXT: [optional — key decisions or rationale from review]
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Code MUST NOT start implementation without at least TASK and ACCEPTANCE filled.
|
|
30
|
+
If SPEC is missing, Code asks before proceeding.
|
|
31
|
+
|
|
32
|
+
## Handoff Format — Code → Desktop
|
|
33
|
+
|
|
34
|
+
When Code completes implementation and wants architectural review:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
REVIEW-REQUEST:
|
|
38
|
+
TASK: [what was implemented]
|
|
39
|
+
DIFF: [git diff summary or branch name]
|
|
40
|
+
SPEC: [link to plan that drove this work]
|
|
41
|
+
QUESTIONS: [specific things to review — not "does this look good"]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Vault Write-Back
|
|
45
|
+
|
|
46
|
+
After Desktop review, append the decision to `{vault_path}/notes/review-decisions.md`:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
## YYYY-MM-DD | [task-slug]
|
|
50
|
+
- **Decision**: APPROVED | CHANGES_REQUESTED | DEFERRED
|
|
51
|
+
- **Rationale**: [1-2 sentences]
|
|
52
|
+
- **Action items**: [if CHANGES_REQUESTED — specific items for Code to address]
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Conventions — WARN on violation
|
|
56
|
+
|
|
57
|
+
- Desktop review decisions that affect architecture go to `{vault_path}/specs/` as ADRs
|
|
58
|
+
- Desktop review decisions that are tactical (naming, style, small refactors) stay in `review-decisions.md`
|
|
59
|
+
- Code must not self-approve architectural changes — route through Desktop review
|
|
60
|
+
- If Desktop is unavailable, Code may proceed but must flag the decision in `status.md` for later review
|
|
61
|
+
|
|
62
|
+
## Removal Condition
|
|
63
|
+
Remove when a unified Claude surface handles both architecture review and code execution
|
|
64
|
+
natively, eliminating the need for explicit handoff protocols.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Go Quality — Generation Constraints
|
|
2
|
+
# Scope: **/*.go
|
|
3
|
+
# Active during code generation, not post-hoc review
|
|
4
|
+
|
|
5
|
+
## Invariants — BLOCK on violation
|
|
6
|
+
|
|
7
|
+
- Every error return checked immediately — no `_` for error values.
|
|
8
|
+
- No `panic` in library code — return errors. Reserve `panic` for truly unrecoverable states in `main`.
|
|
9
|
+
- No `interface{}` or `any` without a comment explaining why a concrete type won't work.
|
|
10
|
+
- Context (`context.Context`) as the first parameter of any function that does I/O or may be cancelled.
|
|
11
|
+
- No goroutine without a clear ownership and shutdown path — leaked goroutines are memory leaks.
|
|
12
|
+
|
|
13
|
+
## Conventions — WARN on violation
|
|
14
|
+
|
|
15
|
+
- Table-driven tests for any function with more than 2 test cases.
|
|
16
|
+
- `errors.Is` / `errors.As` for error comparison — never string matching on `err.Error()`.
|
|
17
|
+
- `fmt.Errorf("context: %w", err)` to wrap errors with context — never lose the original.
|
|
18
|
+
- Named return values only when they clarify the function signature — not as a substitute for declarations.
|
|
19
|
+
- `sync.Mutex` fields placed immediately above the fields they protect, with a comment.
|
|
20
|
+
- `defer` for cleanup — but never defer in a loop body.
|
|
21
|
+
- Prefer `io.Reader` / `io.Writer` interfaces over concrete types in function signatures.
|
|
22
|
+
- Struct field tags (`json`, `db`) on every field of a struct used for serialization.
|
|
23
|
+
|
|
24
|
+
## Removal Condition
|
|
25
|
+
Remove when golangci-lint rules replace generation-time constraints entirely.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Java Quality — Generation Constraints
|
|
2
|
+
# Scope: **/*.java
|
|
3
|
+
# Active during code generation, not post-hoc review
|
|
4
|
+
|
|
5
|
+
## Invariants — BLOCK on violation
|
|
6
|
+
|
|
7
|
+
- No raw types — always use parameterized generics (`List<String>`, not `List`).
|
|
8
|
+
- No empty catch blocks — handle, re-throw with context, or log with severity.
|
|
9
|
+
- No `null` returns from public methods without `@Nullable` annotation and documented behavior.
|
|
10
|
+
- All public API methods have Javadoc with `@param`, `@return`, and `@throws`.
|
|
11
|
+
- Resources (streams, connections) use try-with-resources — never manual `finally` close.
|
|
12
|
+
|
|
13
|
+
## Conventions — WARN on violation
|
|
14
|
+
|
|
15
|
+
- Records over classes for immutable data carriers (Java 16+).
|
|
16
|
+
- `Optional` return type over nullable for methods that may not produce a result.
|
|
17
|
+
- `var` for local variables only when the type is obvious from the right-hand side.
|
|
18
|
+
- `sealed` interfaces/classes for closed hierarchies with pattern matching.
|
|
19
|
+
- Builder pattern only for objects with 5+ fields — constructors or factories for fewer.
|
|
20
|
+
- Prefer `List.of()`, `Map.of()` for immutable collections — not `Collections.unmodifiable*`.
|
|
21
|
+
- `@Override` on every overriding method — let the compiler catch signature drift.
|
|
22
|
+
- Stream operations only when they improve readability — explicit loops for complex logic.
|
|
23
|
+
|
|
24
|
+
## Removal Condition
|
|
25
|
+
Remove when a Java-specific linter rule engine replaces generation-time constraints.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Python Quality — Generation Constraints
|
|
2
|
+
# Scope: **/*.py
|
|
3
|
+
# Active during code generation, not post-hoc review
|
|
4
|
+
|
|
5
|
+
## Invariants — BLOCK on violation
|
|
6
|
+
|
|
7
|
+
- Type hints on every function signature — parameters and return type. No exceptions.
|
|
8
|
+
- No bare `except:` — always catch a specific exception type.
|
|
9
|
+
- No mutable default arguments (`def f(x=[])`) — use `None` and assign inside.
|
|
10
|
+
- No `import *` — explicit imports only.
|
|
11
|
+
- No `type: ignore` without an inline comment explaining why it's safe.
|
|
12
|
+
- f-strings only for string formatting — never `%` or `.format()`.
|
|
13
|
+
|
|
14
|
+
## Conventions — WARN on violation
|
|
15
|
+
|
|
16
|
+
- `dataclass` or `TypedDict` over raw dicts for structured data with 3+ fields.
|
|
17
|
+
- `pathlib.Path` over `os.path` for path manipulation.
|
|
18
|
+
- Context managers (`with`) for all resource handling (files, connections, locks).
|
|
19
|
+
- Comprehensions only when they fit one line — explicit loops otherwise.
|
|
20
|
+
- `enum.Enum` or `Literal` for fixed sets of values — never raw strings.
|
|
21
|
+
- `logging` module over `print()` in anything that isn't a CLI script.
|
|
22
|
+
- Async functions: every `await` in a try/except or the caller handles the exception.
|
|
23
|
+
|
|
24
|
+
## Removal Condition
|
|
25
|
+
Remove when a Python-specific linter rule engine replaces generation-time constraints.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Rust Quality — Generation Constraints
|
|
2
|
+
# Scope: **/*.rs
|
|
3
|
+
# Active during code generation, not post-hoc review
|
|
4
|
+
|
|
5
|
+
## Invariants — BLOCK on violation
|
|
6
|
+
|
|
7
|
+
- No `.unwrap()` or `.expect()` in library code — propagate errors with `?`.
|
|
8
|
+
- No `unsafe` blocks without an inline `// SAFETY:` comment explaining the invariant.
|
|
9
|
+
- No `.clone()` to silence the borrow checker — restructure ownership instead.
|
|
10
|
+
- All public items have doc comments (`///`) — the API is the documentation.
|
|
11
|
+
- Error types implement `std::error::Error` and provide context via `Display`.
|
|
12
|
+
|
|
13
|
+
## Conventions — WARN on violation
|
|
14
|
+
|
|
15
|
+
- `thiserror` for library error types, `anyhow` for application error types.
|
|
16
|
+
- Prefer `&str` over `String` in function parameters — take ownership only when needed.
|
|
17
|
+
- Prefer iterators and combinators over manual loops where they improve readability.
|
|
18
|
+
- `#[must_use]` on functions whose return value should not be silently ignored.
|
|
19
|
+
- Derive `Debug` on all public structs and enums.
|
|
20
|
+
- `#[non_exhaustive]` on public enums that may gain variants.
|
|
21
|
+
- Prefer `impl Trait` in argument position over generic type parameters when the type is used once.
|
|
22
|
+
- Integration tests in `tests/` directory — unit tests in the same file with `#[cfg(test)]`.
|
|
23
|
+
|
|
24
|
+
## Removal Condition
|
|
25
|
+
Remove when clippy rules replace generation-time constraints entirely.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Shell Quality — Generation Constraints
|
|
2
|
+
# Scope: **/*.sh
|
|
3
|
+
# Active during code generation, not post-hoc review
|
|
4
|
+
|
|
5
|
+
## Invariants — BLOCK on violation
|
|
6
|
+
|
|
7
|
+
- Every script starts with `#!/usr/bin/env bash` and `set -euo pipefail`.
|
|
8
|
+
- All variable expansions quoted: `"$VAR"`, never bare `$VAR`.
|
|
9
|
+
- No `eval` — ever. Use arrays for dynamic command construction.
|
|
10
|
+
- `[[ ]]` for conditionals — never `[ ]` (no word splitting, no glob expansion).
|
|
11
|
+
- No inline credentials or tokens — use environment variables.
|
|
12
|
+
- Exit codes: 0 for success, 1 for general failure, 2 for hard block (Praxis convention).
|
|
13
|
+
|
|
14
|
+
## Conventions — WARN on violation
|
|
15
|
+
|
|
16
|
+
- Heredocs or `printf` for multi-line output — never multi-line `echo`.
|
|
17
|
+
- `local` keyword for all variables inside functions.
|
|
18
|
+
- `command -v` for tool detection — never `which`.
|
|
19
|
+
- `mktemp` for temporary files — never hardcoded `/tmp/myfile`.
|
|
20
|
+
- Trap `ERR` or use explicit error handling — don't rely solely on `set -e`.
|
|
21
|
+
- Use `jq` with `--arg` / `--argjson` for JSON — never interpolate variables into JSON strings.
|
|
22
|
+
- Prefer `$(...)` over backticks for command substitution.
|
|
23
|
+
- Group related options into functions — no scripts longer than 100 lines without functions.
|
|
24
|
+
|
|
25
|
+
## Removal Condition
|
|
26
|
+
Remove when a shell-specific linter rule engine replaces generation-time constraints.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# SQL Quality — Generation Constraints
|
|
2
|
+
# Scope: **/*.sql
|
|
3
|
+
# Active during code generation, not post-hoc review
|
|
4
|
+
|
|
5
|
+
## Invariants — BLOCK on violation
|
|
6
|
+
|
|
7
|
+
- Parameterized queries only — never concatenate user input into SQL strings.
|
|
8
|
+
- Every `SELECT` on user-generated data has a `LIMIT` — no unbounded result sets.
|
|
9
|
+
- Every migration is reversible — include both `UP` and `DOWN` in every migration file.
|
|
10
|
+
- No `SELECT *` — explicitly list columns. Schema changes should not silently alter query results.
|
|
11
|
+
- No `DROP TABLE` or `DROP COLUMN` without a preceding data migration or explicit confirmation.
|
|
12
|
+
|
|
13
|
+
## Conventions — WARN on violation
|
|
14
|
+
|
|
15
|
+
- Uppercase SQL keywords (`SELECT`, `FROM`, `WHERE`) — lowercase for identifiers.
|
|
16
|
+
- `snake_case` for all table and column names.
|
|
17
|
+
- Foreign keys have explicit `ON DELETE` and `ON UPDATE` behavior — never rely on defaults.
|
|
18
|
+
- Indexes on all columns used in `WHERE`, `JOIN`, and `ORDER BY` on tables >1000 rows.
|
|
19
|
+
- `NOT NULL` by default — nullable columns require a comment explaining why null is valid.
|
|
20
|
+
- `TIMESTAMP WITH TIME ZONE` for all temporal columns — never naive timestamps.
|
|
21
|
+
- `CHECK` constraints for domain validation at the database level — don't rely solely on application code.
|
|
22
|
+
- CTEs (`WITH`) for readability over nested subqueries beyond 2 levels.
|
|
23
|
+
|
|
24
|
+
## Removal Condition
|
|
25
|
+
Remove when a SQL-specific linter rule engine replaces generation-time constraints.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# TypeScript Quality — Generation Constraints
|
|
2
|
+
# Scope: **/*.ts, **/*.tsx
|
|
3
|
+
# Active during code generation, not post-hoc review
|
|
4
|
+
|
|
5
|
+
## Invariants — BLOCK on violation
|
|
6
|
+
|
|
7
|
+
- No `any` type — ever. Use `unknown` and narrow, or define the actual type.
|
|
8
|
+
- Explicit return types on all exported functions.
|
|
9
|
+
- No non-null assertion (`!`) without an inline comment explaining why it's safe.
|
|
10
|
+
- No `@ts-ignore` or `@ts-expect-error` without an inline comment explaining why.
|
|
11
|
+
- No `as` type assertions unless narrowing from `unknown` — prefer type guards.
|
|
12
|
+
- Strict null checks: handle `null` and `undefined` explicitly, never assume presence.
|
|
13
|
+
|
|
14
|
+
## Conventions — WARN on violation
|
|
15
|
+
|
|
16
|
+
- `const` by default — `let` only when reassignment is necessary. Never `var`.
|
|
17
|
+
- Discriminated unions over optional fields for modeling distinct states.
|
|
18
|
+
- `readonly` on properties that should not be mutated after construction.
|
|
19
|
+
- `interface` for object shapes, `type` for unions, intersections, and computed types.
|
|
20
|
+
- Named exports over default exports — better refactoring support and tree-shaking.
|
|
21
|
+
- `Promise.all` for independent async operations — never sequential awaits for parallel work.
|
|
22
|
+
- Error boundaries in React components that render user-generated or external data.
|
|
23
|
+
- `satisfies` operator over `as` for type validation without widening.
|
|
24
|
+
|
|
25
|
+
## Removal Condition
|
|
26
|
+
Remove when a TypeScript-specific linter rule engine replaces generation-time constraints.
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|