@esoteric-logic/praxis-harness 2.10.0 → 2.12.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.
Files changed (57) hide show
  1. package/base/CLAUDE.md +37 -9
  2. package/base/hooks/auto-format.sh +1 -1
  3. package/base/hooks/dep-audit.sh +1 -1
  4. package/base/hooks/file-guard.sh +3 -3
  5. package/base/hooks/recursion-guard.sh +7 -1
  6. package/base/hooks/session-data-collect.sh +1 -1
  7. package/base/hooks/vault-checkpoint.sh +5 -5
  8. package/base/rules/api-quality.md +25 -0
  9. package/base/{skills → rules}/code-excellence.md +31 -2
  10. package/base/rules/coding.md +16 -0
  11. package/base/rules/css-quality.md +25 -0
  12. package/base/rules/go-quality.md +25 -0
  13. package/base/rules/java-quality.md +25 -0
  14. package/base/rules/observable-code.md +87 -0
  15. package/base/rules/python-quality.md +25 -0
  16. package/base/rules/refactor-triggers.md +59 -0
  17. package/base/rules/rust-quality.md +25 -0
  18. package/base/rules/shell-quality.md +26 -0
  19. package/base/rules/sql-quality.md +25 -0
  20. package/base/rules/typescript-quality.md +26 -0
  21. package/base/rules/writing-quality.md +122 -0
  22. package/base/skills/px-complexity-audit/SKILL.md +118 -0
  23. package/base/skills/px-discover/SKILL.md +4 -1
  24. package/base/skills/px-discuss/SKILL.md +4 -1
  25. package/base/skills/px-doc-lint/SKILL.md +107 -0
  26. package/base/skills/px-prose-review/SKILL.md +96 -0
  27. package/base/skills/px-quality-gate/SKILL.md +182 -0
  28. package/base/skills/px-risk/SKILL.md +4 -1
  29. package/base/skills/px-scaffold-new/SKILL.md +16 -14
  30. package/base/skills/px-session-retro/SKILL.md +1 -1
  31. package/base/skills/px-spec/SKILL.md +6 -2
  32. package/base/skills/px-verify/SKILL.md +2 -1
  33. package/bin/praxis.js +27 -6
  34. package/kits/api/install.sh +1 -1
  35. package/kits/api/teardown.sh +1 -1
  36. package/kits/code-quality/hooks/generate-baseline.sh +1 -1
  37. package/kits/code-quality/hooks/post-commit.sh +3 -2
  38. package/kits/code-quality/hooks/pre-push.sh +15 -15
  39. package/kits/code-quality/install.sh +1 -1
  40. package/kits/code-quality/teardown.sh +3 -3
  41. package/kits/data/install.sh +1 -1
  42. package/kits/data/teardown.sh +1 -1
  43. package/kits/infrastructure/install.sh +1 -1
  44. package/kits/infrastructure/teardown.sh +1 -1
  45. package/kits/security/install.sh +1 -1
  46. package/kits/security/teardown.sh +1 -1
  47. package/kits/web-designer/install.sh +1 -1
  48. package/kits/web-designer/teardown.sh +1 -1
  49. package/package.json +1 -1
  50. package/scripts/health-check.sh +21 -15
  51. package/scripts/install-tools.sh +5 -5
  52. package/scripts/lint-harness.sh +1 -1
  53. package/scripts/onboard-mcp.sh +1 -1
  54. package/scripts/test-harness.sh +1 -1
  55. package/scripts/update.sh +1 -1
  56. /package/base/{skills → rules}/engineering-judgment.md +0 -0
  57. /package/base/{skills → rules}/self-verify.md +0 -0
package/base/CLAUDE.md CHANGED
@@ -125,6 +125,9 @@ Missing servers are non-blocking — features degrade gracefully.
125
125
  - Commit with wrong git identity
126
126
  - Write a file with unreplaced {placeholders}
127
127
  - Use vault search when Obsidian is not running (obsidian backend requires Obsidian open)
128
+ - Mix refactoring and feature changes in one commit — commit refactor separately
129
+ - Copy-paste 3+ lines instead of extracting a shared function
130
+ - Use `console.log`/`fmt.Println`/`print()` for production logging — use the structured logger
128
131
 
129
132
  ## AI-Kit Registry
130
133
  Kits activate via `/px-kit:<n>` slash command. Kits are idempotent — double-activate is a no-op.
@@ -142,27 +145,44 @@ Kit manifests live in `~/.claude/kits/<name>/KIT.md`.
142
145
 
143
146
  ## Rules Registry — Load on Demand Only
144
147
 
145
- ### Universal — always active (9 rules)
148
+ ### Universal — always active (14 rules)
149
+
150
+ Quality is a generation-time constraint, not a post-hoc review. The rules below
151
+ are the lens you write through — they shape every line of code produced.
152
+
146
153
  | File | Purpose |
147
154
  |------|---------|
148
155
  | `~/.claude/rules/profile.md` | Who the user is, identities, working style |
149
156
  | `~/.claude/rules/execution-loop.md` | SPEC/PLAN/VALIDATE loop enforcement |
150
157
  | `~/.claude/rules/coding.md` | Context7 mandate, tool preferences, quality architecture reference |
151
- | `~/.claude/rules/code-quality.md` | Layer 2: Active constraints — hard limits during generation |
158
+ | `~/.claude/rules/code-quality.md` | Active constraints — hard limits during generation (30 lines, 3 nesting, 4 params) |
159
+ | `~/.claude/rules/code-excellence.md` | Core principles — simplicity, correctness, naming, error design, dependency hygiene |
160
+ | `~/.claude/rules/engineering-judgment.md` | Meta-reasoning — Five Questions, YAGNI, Rule of Three, reversibility test |
161
+ | `~/.claude/rules/self-verify.md` | Self-verification — 24-check protocol before every commit |
152
162
  | `~/.claude/rules/git-workflow.md` | Commits, branches, identity verification, pre-commit checks |
153
163
  | `~/.claude/rules/vault.md` | Second brain integration — vault backend, file purposes |
154
164
  | `~/.claude/rules/context-management.md` | Context anti-rot, phase scoping, context reset protocol |
155
165
  | `~/.claude/rules/memory-boundary.md` | Auto-memory boundary, MEMORY.md cap, dream integration |
156
166
  | `~/.claude/rules/security-posture.md` | Sandbox model, credential protection, protected paths |
157
-
158
- ### Skills loaded at session start
159
- | File | Purpose |
160
- |------|---------|
161
- | `~/.claude/skills/code-excellence.md` | Layer 1: Principles — shapes reasoning about code |
162
- | `~/.claude/skills/engineering-judgment.md` | Layer 1: Meta-reasoning — principal engineer decision framework |
163
- | `~/.claude/skills/self-verify.md` | Layer 3: Self-verification protocol — proves correctness before commit |
167
+ | `~/.claude/rules/writing-quality.md` | Prose constraints — sentence limits, fluff kill list, doc templates, voice rules |
168
+ | `~/.claude/rules/refactor-triggers.md` | Pre-check protocol, commit refactor separately, QUALITY: comment convention |
164
169
 
165
170
  ### Scoped — load only when paths match
171
+
172
+ #### Language quality (generation-time constraints per language)
173
+ | File | Loads when |
174
+ |------|------------|
175
+ | `~/.claude/rules/python-quality.md` | `**/*.py` |
176
+ | `~/.claude/rules/typescript-quality.md` | `**/*.ts`, `**/*.tsx` |
177
+ | `~/.claude/rules/shell-quality.md` | `**/*.sh` |
178
+ | `~/.claude/rules/go-quality.md` | `**/*.go` |
179
+ | `~/.claude/rules/rust-quality.md` | `**/*.rs` |
180
+ | `~/.claude/rules/java-quality.md` | `**/*.java` |
181
+ | `~/.claude/rules/css-quality.md` | `**/*.css`, `**/*.scss`, `**/*.less` |
182
+ | `~/.claude/rules/sql-quality.md` | `**/*.sql` |
183
+ | `~/.claude/rules/api-quality.md` | `**/routes/**`, `**/api/**`, `**/controllers/**`, `**/handlers/**` |
184
+
185
+ #### Infrastructure and tooling
166
186
  | File | Loads when |
167
187
  |------|------------|
168
188
  | `~/.claude/rules/azure.md` | `**/*.tf`, `**/*.bicep`, `**/*.azcli` |
@@ -173,11 +193,19 @@ Kit manifests live in `~/.claude/kits/<name>/KIT.md`.
173
193
  | `~/.claude/rules/live-docs-required.md` | Dependency manifests, files importing external packages |
174
194
  | `~/.claude/rules/desktop-protocol.md` | Claude Desktop ↔ Claude Code handoff sessions |
175
195
 
196
+ #### Application observability
197
+
198
+ | File | Loads when |
199
+ |------|------------|
200
+ | `~/.claude/rules/observable-code.md` | `**/services/**`, `**/handlers/**`, `**/workers/**`, `**/middleware/**`, `**/cmd/**` |
201
+
176
202
  ### Auto-invocable skills (replace former universal rules)
177
203
  | Skill | Triggers when |
178
204
  |-------|--------------|
179
205
  | `px-communication-standards` | Writing client-facing docs, proposals, status reports, commits, PRs |
180
206
  | `px-architecture-patterns` | Writing ADRs, specs, system design, risk docs, blocker reports |
207
+ | `px-quality-gate` | Auto inside /px-verify (Step 1 item 5b) and before /px-ship — blocks on BLOCK findings |
208
+ | `px-doc-lint` | Fast structural markdown check inside px-quality-gate for staged *.md files |
181
209
 
182
210
  ## Judgment & Research Commands
183
211
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bash
2
2
  # PostToolUse hook — auto-formats files after edit.
3
3
  # Always exits 0 (advisory, never blocks).
4
- set -uo pipefail
4
+ set -euo pipefail
5
5
  trap 'exit 0' ERR
6
6
 
7
7
  INPUT=$(cat)
@@ -2,7 +2,7 @@
2
2
  # dep-audit.sh — PostToolUse:Write|Edit|MultiEdit hook
3
3
  # Runs dependency vulnerability checks when manifest files are modified.
4
4
  # Always exits 0 (advisory only — PostToolUse cannot hard-block).
5
- set -uo pipefail
5
+ set -euo pipefail
6
6
  trap 'exit 0' ERR
7
7
 
8
8
  INPUT=$(cat)
@@ -6,7 +6,7 @@ set -euo pipefail
6
6
  INPUT=$(cat)
7
7
  FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // empty')
8
8
 
9
- if [ -z "$FILE_PATH" ]; then
9
+ if [[ -z "$FILE_PATH" ]]; then
10
10
  exit 0
11
11
  fi
12
12
 
@@ -29,7 +29,7 @@ for pattern in "${PROTECTED_PATTERNS[@]}"; do
29
29
  done
30
30
 
31
31
  # Check project-level protected files from CLAUDE.md if it exists
32
- if [ -f "CLAUDE.md" ]; then
32
+ if [[ -f "CLAUDE.md" ]]; then
33
33
  # Extract paths from ## Protected Files section
34
34
  IN_SECTION=false
35
35
  while IFS= read -r line; do
@@ -42,7 +42,7 @@ if [ -f "CLAUDE.md" ]; then
42
42
  fi
43
43
  if $IN_SECTION && echo "$line" | grep -qE "^- "; then
44
44
  PROTECTED=$(echo "$line" | sed 's/^- //' | sed 's/ *#.*//' | xargs)
45
- if [ -n "$PROTECTED" ] && echo "$FILE_PATH" | grep -qE "$PROTECTED"; then
45
+ if [[ -n "$PROTECTED" ]] && echo "$FILE_PATH" | grep -qE "$PROTECTED"; then
46
46
  echo "BLOCKED: $FILE_PATH matches project-protected pattern '$PROTECTED'. Explain the intended change."
47
47
  exit 2
48
48
  fi
@@ -50,7 +50,13 @@ KEY="${KEY:0:300}"
50
50
 
51
51
  # ── Increment counter ──
52
52
  # Use a hash of the key for safe JSON field names
53
- KEY_HASH=$(echo -n "$KEY" | md5 2>/dev/null || echo -n "$KEY" | md5sum 2>/dev/null | cut -d' ' -f1 || echo "fallback")
53
+ if command -v md5sum &>/dev/null; then
54
+ KEY_HASH=$(echo -n "$KEY" | md5sum | cut -d' ' -f1)
55
+ elif command -v md5 &>/dev/null; then
56
+ KEY_HASH=$(echo -n "$KEY" | md5 -q)
57
+ else
58
+ KEY_HASH="${KEY:0:32}"
59
+ fi
54
60
 
55
61
  COUNT=$(jq -r --arg cat "$CATEGORY" --arg key "$KEY_HASH" \
56
62
  '.[$cat][$key] // 0' "$STATE_FILE" 2>/dev/null || echo "0")
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bash
2
2
  # Stop hook — collects structured session data and stages it for the Stop prompt.
3
3
  # Always exits 0 (advisory, never blocks session end).
4
- set -uo pipefail
4
+ set -euo pipefail
5
5
  trap 'exit 0' ERR
6
6
 
7
7
  CONFIG_FILE="$HOME/.claude/praxis.config.json"
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bash
2
2
  # PreCompact hook — writes minimal checkpoint to vault before context compaction.
3
3
  # Always exits 0 (advisory, never blocks compaction).
4
- set -uo pipefail
4
+ set -euo pipefail
5
5
  trap 'exit 0' ERR
6
6
 
7
7
  CONFIG_FILE="$HOME/.claude/praxis.config.json"
@@ -19,7 +19,7 @@ PLANS_DIR="$VAULT_PATH/plans"
19
19
  mkdir -p "$PLANS_DIR"
20
20
 
21
21
  DATE=$(date +%Y-%m-%d)
22
- TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
22
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
23
23
  CHECKPOINT_FILE="$PLANS_DIR/$DATE-compact-checkpoint.md"
24
24
 
25
25
  BRANCH=$(git --no-pager rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
@@ -40,16 +40,16 @@ fi
40
40
  LINT_STATE="unknown"
41
41
  TEST_STATE="unknown"
42
42
 
43
- if [ -f "go.mod" ] && command -v golangci-lint &>/dev/null; then
43
+ if [[ -f "go.mod" ]] && command -v golangci-lint &>/dev/null; then
44
44
  LINT_COUNT=$(golangci-lint run ./... 2>&1 | grep -c "^" || true)
45
- if [ "$LINT_COUNT" -eq 0 ]; then
45
+ if [[ "$LINT_COUNT" -eq 0 ]]; then
46
46
  LINT_STATE="clean"
47
47
  else
48
48
  LINT_STATE="$LINT_COUNT findings"
49
49
  fi
50
50
  fi
51
51
 
52
- if [ -f "go.mod" ] && command -v go &>/dev/null; then
52
+ if [[ -f "go.mod" ]] && command -v go &>/dev/null; then
53
53
  if go test ./... -short 2>&1 | grep -q "^ok"; then
54
54
  TEST_STATE="passing"
55
55
  else
@@ -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
- Load this skill at the start of every session. These principles shape how you reason about
4
- code before writing a single character. They are not a checklist — they are a worldview.
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.
@@ -67,3 +74,25 @@ A comment that says `// increment counter` above `counter++` is noise.
67
74
  A comment that says `// retry three times because the upstream API returns 503 on cold start`
68
75
  is knowledge that cannot be inferred from the code alone.
69
76
  Delete the first kind. Write more of the second kind.
77
+
78
+ ---
79
+
80
+ ## Reference Codebases — What Excellence Looks Like
81
+
82
+ When you need a reference for what excellent code looks like, use these:
83
+
84
+ | Domain | Reference | What to study |
85
+ | ------ | --------- | ------------- |
86
+ | C / systems | SQLite source (`sqlite.org/src`) | Discipline: 590x test-to-source ratio, 100% branch coverage, zero external deps |
87
+ | C / network | Redis `src/ae.c`, `src/dict.c` | Naming, readability, data structures that document themselves |
88
+ | Go | Go standard library (`pkg.go.dev/std`) | Idiomatic naming, error design, interface sizing — one method where possible |
89
+ | Rust | `rustc_errors` crate | Error message design: what failed, where, what to do next |
90
+ | Error messages | Elm compiler output | Kindest, most actionable errors in any compiled language |
91
+ | API design | Stripe API (`docs.stripe.com`) | Naming consistency, versioning discipline, error schema |
92
+ | Documentation | Go stdlib `net/http` package docs | Every exported symbol explained by what it does for the caller |
93
+
94
+ When uncertain if code is good enough: "Would this survive a review from the SQLite team?"
95
+ If the answer is no — simplify first.
96
+
97
+ The SQLite standard: every line has a reason. Every function has one job.
98
+ Every error has a message a human can act on.
@@ -13,6 +13,22 @@
13
13
  - If Context7 is unavailable: state that docs could not be verified and flag the
14
14
  specific method/API as "unverified against current version."
15
15
 
16
+ ### Import-trigger protocol
17
+
18
+ Any commit diff that adds a new `import`, `require`, `using`, or `use` statement for an
19
+ external package must have a corresponding Context7 lookup in the same session.
20
+
21
+ Language-specific patterns matched:
22
+
23
+ - JavaScript/TypeScript: `import ... from`, `require(...)`
24
+ - Python: `import ...`, `from ... import`
25
+ - Go: `import "..."` or `import (...)`
26
+ - Rust: `use ...::...`
27
+ - Java/C#: `import ...`, `using ...`
28
+
29
+ Every new external import requires a Context7 verification before the gate clears.
30
+ Internal packages (same repo, same module) are excluded.
31
+
16
32
  ### Tool preferences
17
33
  - Use Read/Edit/Write tools instead of cat/sed/echo.
18
34
  - Use `rg` (ripgrep) for searching code, not grep.
@@ -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,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,87 @@
1
+ # Observable Code — Instrumentation Constraints
2
+ # Scope: **/services/**, **/handlers/**, **/workers/**, **/middleware/**, **/cmd/**
3
+ # Active during code generation for service-layer code
4
+ # Cross-reference: api-quality.md covers request-level logging and correlation IDs.
5
+ # This rule covers application-level observability: structured logging, metrics, traces.
6
+
7
+ Code is not production-ready if it cannot be debugged without attaching a debugger.
8
+ Observable code tells you what happened, when, and why — from logs, metrics, and traces alone.
9
+
10
+ ## Invariants — BLOCK on violation
11
+
12
+ ### Structured logging only
13
+ - All log statements use structured format (key-value pairs, not string interpolation)
14
+ - No `fmt.Println` / `console.log` / `print()` in production code paths — use the structured logger
15
+ - Log at the point of failure, not at the catch site (log once, propagate)
16
+
17
+ ### Log levels are semantic
18
+ - ERROR: something failed and a human needs to know immediately
19
+ - WARN: something unexpected happened but the system recovered
20
+ - INFO: a significant state transition (service started, job completed, user authenticated)
21
+ - DEBUG: internal detail useful during development — must not appear in production by default
22
+
23
+ ### Structured log format — mandatory fields
24
+ ```json
25
+ {
26
+ "timestamp": "ISO-8601 UTC",
27
+ "level": "error|warn|info|debug",
28
+ "service": "service-name",
29
+ "correlation_id": "request or trace identifier",
30
+ "message": "what happened — actionable, not generic",
31
+ "context": { "relevant_key": "relevant_value" }
32
+ }
33
+ ```
34
+
35
+ ### What NOT to log
36
+ - Passwords, tokens, secrets, full credit card numbers
37
+ - Full request/response bodies in production (may contain PII)
38
+ - DEBUG logs in production services (log level must be configurable)
39
+ - The same event more than once in the same request path
40
+
41
+ ### External call discipline
42
+ - Every external call (HTTP, DB, queue) has a timeout
43
+ - Every external call logs duration on completion
44
+ - Failed external calls log: target, duration, error type, and whether retry will occur
45
+
46
+ ## Conventions — WARN on violation
47
+
48
+ ### Metrics naming
49
+ Format: `{service}_{subsystem}_{name}_{unit}`
50
+ All lowercase, underscores as separators.
51
+
52
+ Mandatory metrics per service:
53
+ - `{service}_requests_total` — counter, labeled by method and status code
54
+ - `{service}_errors_total` — counter, labeled by error type
55
+ - `{service}_latency_seconds` — histogram, labeled by operation
56
+ - `{service}_active_connections` or `{service}_queue_depth` — gauge (if applicable)
57
+
58
+ GOOD: `auth_login_attempts_total`, `cache_hit_ratio`, `queue_messages_pending`
59
+ BAD: `loginAttempts`, `CacheHitRatio`, `queue-messages-pending`
60
+
61
+ ### Trace spans (OpenTelemetry)
62
+ Span naming: `{service}/{operation}` — lowercase, slash separator
63
+ GOOD: `auth/validate-token`, `db/query-users`, `cache/get`
64
+ BAD: `validateToken`, `DB Query`, `GET /users`
65
+
66
+ Mandatory span attributes:
67
+ - `service.name`
68
+ - `http.method` and `http.status_code` for HTTP operations
69
+ - `db.system` and `db.operation` for database calls
70
+ - `error.type` and `error.message` on error spans
71
+
72
+ ### Health endpoints
73
+ - Liveness: `/healthz` — "is the process alive?"
74
+ - Readiness: `/readyz` — "can the process serve traffic?"
75
+ - Both return structured JSON with component status
76
+
77
+ ### The Observability Contract
78
+ An error is only production-observable if ALL three are true:
79
+ 1. It appears in structured logs with correlation_id and context
80
+ 2. It increments an error metric labeled by error type
81
+ 3. It is captured in a trace span with error attributes
82
+
83
+ If only one or two are true: the code is not fully observable. Fix before shipping.
84
+
85
+ ## Removal Condition
86
+ Remove when an observability linter or OpenTelemetry SDK auto-instrumentation
87
+ replaces these generation-time constraints entirely.
@@ -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,59 @@
1
+ # Refactor Triggers — Pre-Check Protocol
2
+ # Scope: All code modifications
3
+ # Always active during code generation
4
+ # Cross-reference: code-quality.md defines the hard limits (30 lines, 3 nesting,
5
+ # 4 params, 300-line files, no TODO/FIXME). This file defines WHEN and HOW
6
+ # to refactor — not the thresholds themselves.
7
+
8
+ ## Invariants — BLOCK on violation
9
+
10
+ ### Before touching any existing file
11
+ Check the file against `code-quality.md` hard limits before adding code.
12
+ If the file already violates limits:
13
+ 1. Do NOT add new code to it
14
+ 2. Refactor the file to compliance first
15
+ 3. THEN make the intended change
16
+ 4. Commit the refactor separately from the feature
17
+
18
+ This is mandatory. Adding to an already-broken file compounds debt exponentially.
19
+
20
+ ### Commit refactor separately from feature
21
+ - Refactoring commits use `refactor(scope):` prefix
22
+ - Feature commits use `feat(scope):` prefix
23
+ - Never mix structural changes and behavior changes in one commit
24
+ - Rationale: reviewers cannot distinguish "moved code" from "changed behavior" in a mixed diff
25
+
26
+ ### Copy-paste detection
27
+ If you find yourself copying 3+ lines from elsewhere in the same codebase: stop.
28
+ Extract a shared function in a common location.
29
+ Duplication is the root of divergent behavior bugs.
30
+
31
+ ## Conventions — WARN on violation
32
+
33
+ ### The QUALITY comment convention
34
+ When you encounter a known violation in code you are NOT tasked with fixing:
35
+ ```
36
+ // QUALITY: function exceeds 30 lines — refactor tracked in #123
37
+ ```
38
+
39
+ Rules for QUALITY comments:
40
+ - QUALITY: is the ONLY allowed debt marker. `TODO`, `FIXME`, and `HACK` are banned (see `code-quality.md`).
41
+ - Every QUALITY comment MUST include a tracking reference (issue number, ADR, or ticket).
42
+ - QUALITY comments are allowed in commits — unlike TODO/FIXME which are not.
43
+ - A QUALITY comment is NOT a license to defer indefinitely. It is a documented acknowledgment.
44
+
45
+ ### Refactor vs rewrite decision gate
46
+ - **Refactor** (preferred): same behavior, improved structure. Small, safe, incremental.
47
+ - **Rewrite**: new behavior or complete structural replacement.
48
+
49
+ If >50% of a file needs changing during a feature task:
50
+ 1. Stop. Do not incrementally refactor to the point of a full rewrite.
51
+ 2. File an issue for the rewrite.
52
+ 3. Complete the minimum viable refactor for the current feature.
53
+ 4. Propose the rewrite as a separate milestone with its own plan.
54
+
55
+ Never rewrite during a feature task without an explicit plan.
56
+
57
+ ## Removal Condition
58
+ Remove when automated refactoring tools (e.g., language-specific AST transforms)
59
+ handle pre-check validation and commit separation automatically.
@@ -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.