@esoteric-logic/praxis-harness 2.8.0 → 2.9.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 (43) hide show
  1. package/base/CLAUDE.md +11 -2
  2. package/base/configs/ci/lint-stack.yml +19 -109
  3. package/base/configs/registry.json +1 -5
  4. package/base/hooks/settings-hooks.json +0 -13
  5. package/base/hooks/vault-checkpoint.sh +0 -2
  6. package/base/rules/code-quality.md +56 -0
  7. package/base/rules/coding.md +15 -110
  8. package/base/skills/code-excellence.md +69 -0
  9. package/base/skills/engineering-judgment.md +71 -0
  10. package/base/skills/px-code-gc/SKILL.md +2 -2
  11. package/base/skills/px-deepsource-coverage/SKILL.md +48 -0
  12. package/base/skills/px-deepsource-review/SKILL.md +50 -0
  13. package/base/skills/px-deepsource-setup/SKILL.md +56 -0
  14. package/base/skills/px-pre-commit-lint/SKILL.md +1 -2
  15. package/base/skills/px-scaffold-new/references/repo-CLAUDE-md-template.md +1 -1
  16. package/base/skills/px-ship/SKILL.md +1 -1
  17. package/base/skills/px-verify/SKILL.md +2 -2
  18. package/base/skills/self-verify.md +78 -0
  19. package/bin/praxis-preflight.sh +1 -1
  20. package/bin/praxis.js +3 -3
  21. package/kits/code-quality/KIT.md +55 -0
  22. package/kits/code-quality/configs/checks-registry.json +35 -0
  23. package/kits/code-quality/configs/thresholds.json +36 -0
  24. package/kits/code-quality/hooks/generate-baseline.sh +30 -0
  25. package/kits/code-quality/hooks/post-commit.sh +28 -0
  26. package/kits/code-quality/hooks/pre-push.sh +104 -0
  27. package/kits/code-quality/install.sh +68 -0
  28. package/kits/code-quality/manifest.json +27 -0
  29. package/kits/code-quality/skills/over-engineering.md +72 -0
  30. package/kits/code-quality/skills/performance-review.md +65 -0
  31. package/kits/code-quality/skills/self-review.md +55 -0
  32. package/kits/code-quality/skills/structural-review.md +57 -0
  33. package/kits/code-quality/teardown.sh +21 -0
  34. package/kits/security/commands/security-audit.md +1 -1
  35. package/kits/security/install.sh +1 -1
  36. package/kits/security/teardown.sh +1 -1
  37. package/package.json +1 -1
  38. package/scripts/install-tools.sh +2 -2
  39. package/scripts/test-harness.sh +5 -13
  40. package/base/configs/linters/.pre-commit-config.yaml +0 -63
  41. package/base/configs/linters/semgrep.yml +0 -65
  42. package/base/hooks/post-session-lint.sh +0 -44
  43. package/base/hooks/quality-check.sh +0 -202
package/base/CLAUDE.md CHANGED
@@ -128,24 +128,33 @@ Kits activate via `/px-kit:<n>` slash command. Kits are idempotent — double-ac
128
128
  | infrastructure | `/px-kit:infrastructure` | Terraform → Azure → GitHub Actions → compliance |
129
129
  | api | `/px-kit:api` | RESTful conventions → OpenAPI specs → contract testing |
130
130
  | security | `/px-kit:security` | Threat modeling → IAM review → OWASP audit |
131
+ | code-quality | `/px-kit:code-quality` | SAST + secrets + SCA + IaC gate → AI review (over-engineering, smells, structure) |
131
132
  | data | `/px-kit:data` | Schema design → migration planning → query optimization |
132
133
 
133
134
  Kit manifests live in `~/.claude/kits/<name>/KIT.md`.
134
135
 
135
136
  ## Rules Registry — Load on Demand Only
136
137
 
137
- ### Universal — always active (8 rules)
138
+ ### Universal — always active (9 rules)
138
139
  | File | Purpose |
139
140
  |------|---------|
140
141
  | `~/.claude/rules/profile.md` | Who the user is, identities, working style |
141
142
  | `~/.claude/rules/execution-loop.md` | SPEC/PLAN/VALIDATE loop enforcement |
142
- | `~/.claude/rules/coding.md` | Code quality, security, complexity thresholds, Context7 mandate |
143
+ | `~/.claude/rules/coding.md` | Context7 mandate, tool preferences, quality architecture reference |
144
+ | `~/.claude/rules/code-quality.md` | Layer 2: Active constraints — hard limits during generation |
143
145
  | `~/.claude/rules/git-workflow.md` | Commits, branches, identity verification, pre-commit checks |
144
146
  | `~/.claude/rules/vault.md` | Second brain integration — vault backend, file purposes |
145
147
  | `~/.claude/rules/context-management.md` | Context anti-rot, phase scoping, context reset protocol |
146
148
  | `~/.claude/rules/memory-boundary.md` | Auto-memory boundary, MEMORY.md cap, dream integration |
147
149
  | `~/.claude/rules/security-posture.md` | Sandbox model, credential protection, protected paths |
148
150
 
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
+
149
158
  ### Scoped — load only when paths match
150
159
  | File | Loads when |
151
160
  |------|------------|
@@ -1,7 +1,7 @@
1
- # Polyglot Lint Stack — 3-Layer CI Template
1
+ # Lint Stack — CI Template
2
2
  # Copy to: .github/workflows/lint-stack.yml
3
- # Conditional: each tool runs only if its language files exist in the repo.
4
- # Pin actions to SHA update hashes when upgrading versions.
3
+ # DeepSource handles comprehensive analysis via GitHub app integration.
4
+ # This workflow provides basic file hygiene checks only.
5
5
 
6
6
  name: Lint Stack
7
7
  on:
@@ -10,117 +10,27 @@ on:
10
10
 
11
11
  permissions:
12
12
  contents: read
13
- pull-requests: write
14
13
 
15
14
  jobs:
16
- # ─────────────────────────────────────────────
17
- # LAYER 1: Fast Feedback (~10s per tool)
18
- # ─────────────────────────────────────────────
19
- lint:
20
- name: L1 — Lint + Format
15
+ hygiene:
16
+ name: File Hygiene
21
17
  runs-on: ubuntu-latest
22
18
  steps:
23
19
  - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
24
20
 
25
- # Python Ruff
26
- - name: Ruff check
27
- if: hashFiles('**/*.py') != ''
28
- uses: astral-sh/ruff-action@9700c1666704e06e2cf8f9046755e3dfc6297e40 # v3.2.1
29
- with:
30
- args: "check"
31
- - name: Ruff format check
32
- if: hashFiles('**/*.py') != ''
33
- uses: astral-sh/ruff-action@9700c1666704e06e2cf8f9046755e3dfc6297e40 # v3.2.1
34
- with:
35
- args: "format --check"
36
-
37
- # JS/TS — Biome
38
- - name: Setup Biome
39
- if: hashFiles('**/*.js', '**/*.ts', '**/*.jsx', '**/*.tsx') != ''
40
- uses: biomejs/setup-biome@1cbe33ead22c7a2fded3b52fa2893611c815c3d2 # v2.5.0
41
- - name: Biome CI
42
- if: hashFiles('**/*.js', '**/*.ts', '**/*.jsx', '**/*.tsx') != ''
43
- run: biome ci .
44
-
45
- # Go — golangci-lint
46
- - name: golangci-lint
47
- if: hashFiles('go.mod') != ''
48
- uses: golangci/golangci-lint-action@1481404843c368bc19ca9406f87d6e0fc97bdcfd # v7.0.0
49
- with:
50
- version: v2.1
51
-
52
- # Rust — Clippy
53
- - name: Setup Rust toolchain
54
- if: hashFiles('Cargo.toml') != ''
55
- uses: dtolnay/rust-toolchain@56f84321dbccf38fb67ce29ab63e4754056677e0 # stable
56
- with:
57
- toolchain: stable
58
- components: clippy, rustfmt
59
- - name: Clippy
60
- if: hashFiles('Cargo.toml') != ''
61
- run: cargo clippy --all-targets --all-features -- -D warnings
62
- - name: rustfmt check
63
- if: hashFiles('Cargo.toml') != ''
64
- run: cargo fmt --all -- --check
65
-
66
- # Shell — ShellCheck
67
- - name: ShellCheck
68
- if: hashFiles('**/*.sh') != ''
21
+ - name: Check for merge conflict markers
69
22
  run: |
70
- sudo apt-get install -y shellcheck
71
- find . -name '*.sh' -not -path './node_modules/*' -not -path './vendor/*' | xargs shellcheck -s bash
72
-
73
- # ─────────────────────────────────────────────
74
- # LAYER 2: Quality Gates (~2min)
75
- # ─────────────────────────────────────────────
76
- security-scan:
77
- name: L2 — Semgrep
78
- runs-on: ubuntu-latest
79
- needs: lint
80
- steps:
81
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
82
- - uses: semgrep/semgrep-action@713efdd345ae26c72e79b5b32927be8e0e6bab83 # v1
83
- with:
84
- config: >-
85
- p/default
86
- p/secrets
87
- p/owasp-top-ten
88
- env:
89
- SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
23
+ if git grep -rn '<<<<<<< \|>>>>>>> ' -- ':!*.yml' ':!*.yaml'; then
24
+ echo "::error::Merge conflict markers found"
25
+ exit 1
26
+ fi
90
27
 
91
- # Uncomment to add SonarQube quality gate (requires self-hosted server)
92
- # sonarqube:
93
- # name: L2 SonarQube
94
- # runs-on: ubuntu-latest
95
- # needs: lint
96
- # steps:
97
- # - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
98
- # with:
99
- # fetch-depth: 0
100
- # - uses: SonarSource/sonarqube-scan-action@0e1a25e90571a34e2ec5c72ee40ba45cc73a1e6e # v4
101
- # env:
102
- # SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
103
- # SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
104
- # - uses: SonarSource/sonarqube-quality-gate-action@dc2f7b0dd95544cd550de3066f25f47e3fc20894 # v1.1.0
105
- # timeout-minutes: 5
106
- # env:
107
- # SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
108
-
109
- # ─────────────────────────────────────────────
110
- # LAYER 3: AI Review (~2min, optional)
111
- # ─────────────────────────────────────────────
112
- # Uncomment to enable AI-powered PR review.
113
- # Requires OPENAI_API_KEY secret or self-hosted Ollama.
114
- #
115
- # ai-review:
116
- # name: L3 — AI Review
117
- # runs-on: ubuntu-latest
118
- # needs: [security-scan]
119
- # steps:
120
- # - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
121
- # - uses: Codium-ai/pr-agent@main
122
- # env:
123
- # OPENAI_KEY: ${{ secrets.OPENAI_API_KEY }}
124
- # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
125
- # with:
126
- # command: review
28
+ - name: Check for large files
29
+ run: |
30
+ find . -type f -size +500k \
31
+ -not -path './.git/*' \
32
+ -not -path './node_modules/*' \
33
+ -not -path './vendor/*' \
34
+ -not -path './.terraform/*' | head -20 | while read -r f; do
35
+ echo "::warning file=$f::File exceeds 500KB"
36
+ done
@@ -26,16 +26,13 @@
26
26
  {"name": "gh", "minVersion": "2.0.0", "install": "brew install gh"}
27
27
  ],
28
28
  "optional": [
29
- {"name": "trufflehog", "feature": "secret-scanning", "install": "brew install trufflehog"},
30
- {"name": "gitleaks", "feature": "secret-scanning", "install": "brew install gitleaks"},
29
+ {"name": "deepsource", "feature": "code-analysis", "install": "curl -fsSL https://cli.deepsource.com/install | sh"},
31
30
  {"name": "osv-scanner", "feature": "dep-audit", "install": "go install github.com/google/osv-scanner/cmd/osv-scanner@latest"},
32
31
  {"name": "pip-audit", "feature": "dep-audit-python", "install": "pip install pip-audit"},
33
32
  {"name": "docker", "feature": "docker-sandbox", "install": "brew install --cask docker"},
34
33
  {"name": "biome", "feature": "lint-js", "install": "npm install -g @biomejs/biome"},
35
34
  {"name": "ruff", "feature": "lint-python", "install": "pip install ruff"},
36
- {"name": "semgrep", "feature": "security-scan", "install": "pip install semgrep"},
37
35
  {"name": "markdownlint", "feature": "lint-markdown", "install": "npm install -g markdownlint-cli"},
38
- {"name": "pre-commit", "feature": "pre-commit-hooks", "install": "pip install pre-commit"},
39
36
  {"name": "golangci-lint", "feature": "lint-go", "install": "brew install golangci-lint"},
40
37
  {"name": "rustfmt", "feature": "format-rust", "install": "rustup component add rustfmt"},
41
38
  {"name": "clippy", "feature": "lint-rust", "install": "rustup component add clippy"}
@@ -104,7 +101,6 @@
104
101
  {"path": "base/hooks/file-guard.sh", "event": "PreToolUse", "matcher": "Write|Edit|MultiEdit"},
105
102
  {"path": "base/hooks/identity-check.sh", "event": "PreToolUse", "matcher": "Bash"},
106
103
  {"path": "base/hooks/credential-guard.sh", "event": "PreToolUse", "matcher": "Bash"},
107
- {"path": "base/hooks/quality-check.sh", "event": "PostToolUse", "matcher": "Write|Edit|MultiEdit"},
108
104
  {"path": "base/hooks/session-data-collect.sh", "event": "Stop", "matcher": ""}
109
105
  ],
110
106
  "optional": [
@@ -39,15 +39,6 @@
39
39
  }
40
40
  ],
41
41
  "PostToolUse": [
42
- {
43
- "matcher": "Write|Edit|MultiEdit",
44
- "hooks": [
45
- {
46
- "type": "command",
47
- "command": "bash ~/.claude/hooks/quality-check.sh"
48
- }
49
- ]
50
- },
51
42
  {
52
43
  "matcher": "Write|Edit|MultiEdit",
53
44
  "hooks": [
@@ -62,10 +53,6 @@
62
53
  {
63
54
  "matcher": "",
64
55
  "hooks": [
65
- {
66
- "type": "command",
67
- "command": "bash ~/.claude/hooks/post-session-lint.sh"
68
- },
69
56
  {
70
57
  "type": "prompt",
71
58
  "prompt": "Run the project test suite. Read CLAUDE.md ## Commands for the test command. If no test command defined, respond {ok:true}. Run tests. If all pass: respond {ok:true}. If tests fail: respond {ok:false, reason:'Tests failing: <summary>'}. Do not fix — only report."
@@ -23,8 +23,6 @@ CHECKPOINT_FILE="$PLANS_DIR/$DATE-compact-checkpoint.md"
23
23
 
24
24
  BRANCH=$(git --no-pager rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
25
25
  LAST_COMMIT=$(git --no-pager log --oneline -1 2>/dev/null || echo "no commits")
26
- PROJECT_DIR=$(basename "$PWD")
27
-
28
26
  STATUS_FILE="$VAULT_PATH/status.md"
29
27
  PROGRESS_FILE="$VAULT_PATH/claude-progress.json"
30
28
 
@@ -0,0 +1,56 @@
1
+ # Code Quality — Active Constraints
2
+
3
+ These rules are active during code generation. They are not reviewed after writing —
4
+ they shape what gets written in the first place.
5
+
6
+ ## Before writing any function
7
+ State in a single-line comment what this function does.
8
+ If you cannot write the comment in one sentence, split the function first.
9
+ The function name must be derivable from that comment.
10
+
11
+ ## Hard limits — never violate without explicit documented exception
12
+ - No function exceeds 30 lines of logic (blank lines and comments excluded)
13
+ - No block nesting deeper than 3 levels
14
+ - No function with more than 4 parameters — use an options/config object beyond 4
15
+ - No class with more than 5 public methods — split the class first
16
+ - No file with more than 300 lines — split the module first
17
+ - No `TODO` or `FIXME` committed — resolve inline or create a tracked issue with link in comment
18
+
19
+ ## Before introducing any abstraction (interface, base class, factory, wrapper)
20
+ Identify exactly 2 or more existing concrete use cases that require it.
21
+ They must exist in the current codebase, not in anticipated future requirements.
22
+ If only 1 use case exists, inline the logic and do not create the abstraction.
23
+
24
+ ## Before adding any new dependency
25
+ - Verify the standard library does not provide equivalent functionality
26
+ - Verify the package has had a commit within the last 6 months
27
+ - Pin to exact version in package manifest
28
+ - Add a comment above the import explaining why this dependency was chosen over alternatives
29
+
30
+ ## On every new public function or method
31
+ Write the JSDoc/docstring before writing the implementation.
32
+ The docstring must include: what it does, what each parameter is, what it returns, what it throws.
33
+ If you cannot write the docstring, you do not yet understand what you are building.
34
+
35
+ ## On error handling — no exceptions
36
+ - Every async function has explicit error handling (try/catch or .catch() or Result type)
37
+ - Every function that receives external input validates type, range, and format before use
38
+ - Every thrown error has a message that identifies: what failed, why it failed, what the caller should do
39
+ - Errors are never caught and silently ignored — log at minimum, re-throw if unhandled
40
+
41
+ ## On tests
42
+ - New public functions require tests before the PR is considered complete
43
+ - Tests assert behavior (outputs and side effects), not implementation (which internal functions were called)
44
+ - Each test covers exactly one scenario — no multi-scenario tests
45
+ - Test files mirror source file structure — `src/auth/login.ts` → `tests/auth/login.test.ts`
46
+
47
+ ## On comments
48
+ Write comments that explain WHY, not WHAT.
49
+ Delete any comment that restates what the code already says.
50
+ Write comments that capture: non-obvious decisions, external constraints, known limitations.
51
+
52
+ ## On naming
53
+ - No single-letter variables except loop indices (`i`, `j`, `k`) in tight loops of ≤5 lines
54
+ - No abbreviations unless they are universally understood domain terms (`id`, `url`, `api`)
55
+ - No generic names: `data`, `info`, `temp`, `result`, `obj`, `val`, `res`, `thing`, `stuff`
56
+ - Rename before committing. Names do not get "cleaned up later."
@@ -1,6 +1,5 @@
1
1
  # Coding — Universal Rules
2
2
  <!-- Universal — applies to ALL code regardless of language or stack -->
3
- <!-- Merged from coding.md + code-quality.md -->
4
3
 
5
4
  ---
6
5
 
@@ -9,132 +8,44 @@
9
8
  ### Documentation lookup before implementation
10
9
  - Before implementing anything that uses an external library, framework, or API:
11
10
  use Context7 to get current docs. Training data has a cutoff. Context7 does not.
12
- - Append "use context7" to any prompt involving a library not personally verified as current.
13
11
  - Never suggest a method, constructor, or API signature from memory for a library
14
12
  that releases frequently. Look it up first via Context7.
15
13
  - If Context7 is unavailable: state that docs could not be verified and flag the
16
14
  specific method/API as "unverified against current version."
17
15
 
18
- ### Error handling
19
- - Never silently swallow exceptions. Every catch block must either re-throw,
20
- log with context, or return a typed error.
21
- - No empty catch blocks. No fallback defaults unless explicitly asked.
22
- - Error messages MUST include context: request params, response body, status codes.
23
- - Use structured logging fields, not string interpolation.
24
- - External calls: retries with exponential backoff + warnings, then raise last error.
25
- - Validate response shape, not just status code — a 200 with error body is a silent failure.
26
- - Every function that can fail must have an explicit failure path.
27
- - Validate inputs at the boundary. Never assume callers pass correct data.
28
-
29
- ### No hardcoded values
30
- - No credentials, tokens, connection strings, or API keys inline. Ever.
31
- Use environment variables, Key Vault references, or parameter files.
32
- - No hardcoded paths specific to one machine. Use relative paths or env-derived roots.
33
- - No magic numbers without a named constant and a comment explaining the value.
34
-
35
- ### State and side effects
36
- - Pure functions where possible. If a function mutates state, its name must signal that.
37
- - Never mutate input parameters. Return new values.
38
- - Write pure functions — only modify return values, never inputs or global state.
39
-
40
- ### Typing
41
- - Strict typing everywhere: function signatures, variables, collections.
42
- - No implicit `any` or untyped parameters in typed languages.
43
-
44
- ### No flag parameters
45
- - Never write a function with a boolean/enum parameter that switches behavior.
46
- Write separate named functions instead.
47
-
48
- ### Dead code
49
- - Delete dead code. Do not comment it out.
50
- Commented-out code belongs in git history, not in files.
51
- - Check if logic already exists before writing new code: `rg` to search first.
52
-
53
- ---
54
-
55
- ## Conventions — WARN on violation
56
-
57
- ### Code structure
58
- - Functions do one thing. If you are writing "and" in a function description,
59
- split it into two functions.
60
- - Prefer functional programming in greenfield code; classes only for connectors/interfaces.
61
- Follow existing project conventions in established codebases.
62
- - All imports at the top of the file.
63
- - Follow DRY, KISS, YAGNI.
64
-
65
- ### Naming
66
- - Variable names describe what they contain: `subscriptionIds` not `ids`,
67
- `retryDelayMs` not `delay`.
68
- - Functions: verb-noun format. Name signals intent and side effects.
69
-
70
- ### Testing
71
- - Write tests for ALL new code in production paths.
72
- - Spike/prototype carve-out: skip tests only if explicitly marked spike/prototype.
73
- Flag test debt in `status.md` under `## Test Debt`.
74
- - Run tests before marking any task complete.
75
- - Mock external dependencies only — never mock the code under test.
76
- - Test edge cases and error paths, not just happy paths.
77
- - If existing tests break: fix them. Do not claim they are unrelated.
78
- - Never say "this should work" — demonstrate it with output, log line, or test result.
79
-
80
- ### Dependency management
81
- Before adding any new package:
82
- 1. Search first — check if functionality exists in codebase or stdlib (`rg`).
83
- 2. Evaluate: maintenance status, last publish, open issues, bus factor.
84
- 3. Minimize surface area — implement yourself if you only need one function.
85
- 4. Pin versions — exact versions in lockfiles. No floating ranges in production deps.
86
- 5. New production dependency requires explicit approval.
87
-
88
- ### Documentation
89
- - Comments explain WHY, not WHAT. If the comment describes what the code does,
90
- rewrite the code to be self-describing instead.
91
- - Update docs and comments when changing logic. Stale comments actively mislead.
92
- - Code is primary documentation — clear naming, types, docstrings.
93
- - YAML frontmatter on all markdown files:
94
- ```yaml
95
- ---
96
- created: YYYY-MM-DD
97
- status: draft|active|completed
98
- tags: [relevant, tags]
99
- source: agent
100
- ---
101
- ```
102
-
103
- ### Scripts
104
- - Scripts that modify resources must have a dry-run or preview step before live run.
105
-
106
16
  ### Tool preferences
107
17
  - Use Read/Edit/Write tools instead of cat/sed/echo.
108
18
  - Use `rg` (ripgrep) for searching code, not grep.
109
19
  - Use `git --no-pager` for all git commands.
110
20
  - Use subagents for context-heavy research and code review.
111
21
  - Non-interactive commands only — no interactive prompts.
112
- - Prefer MCP tools for current documentation (context7, Playwright).
22
+ - Prefer MCP tools for current documentation (context7).
23
+ - YAML frontmatter on all markdown files.
113
24
 
114
25
  ---
115
26
 
116
- ## Linter Delegation
27
+ ## Quality Architecture
117
28
 
118
- Style, formatting, import ordering, complexity thresholds, and security patterns
119
- are enforced by automated tooling (golangci-lint, shellcheck, hadolint, tflint,
120
- semgrep). Rules files cover ONLY:
121
- - Architecture decisions tooling cannot express
122
- - Permission boundaries and file-group scoping
123
- - Error learning from real session failures
124
- - Verification command references
29
+ Code quality is enforced proactively, not reactively:
30
+ - **Layer 1 (Principles)**: `code-excellence.md`, `engineering-judgment.md` shape reasoning
31
+ - **Layer 2 (Constraints)**: `code-quality.md` hard limits during generation
32
+ - **Layer 3 (Verification)**: `/px-self-verify` — prove correctness before commit
33
+ - **Safety net**: DeepSource (cloud) — comprehensive analysis on push
125
34
 
126
- Do NOT duplicate in CLAUDE.md what hooks already enforce.
35
+ Detailed rules: error handling, naming, testing, dependencies, simplicity, and
36
+ judgment live in those files. This file covers only what they do not:
37
+ Context7 mandate, tool preferences, and verification commands.
127
38
 
128
39
  ---
129
40
 
130
41
  ## Verification Commands
131
42
 
132
- Single-file (matches PostToolUse hooks):
43
+ Single-file:
133
44
  - `go vet <file>` / `shellcheck <file>` / `hadolint Dockerfile` / `markdownlint <file>.md`
134
45
 
135
- Project-level (matches pre-commit + /verify):
136
- - `golangci-lint run`
137
- - `semgrep --config=auto --error .`
46
+ Project-level:
47
+ - `deepsource issues --path <file>` — query DeepSource findings
48
+ - `deepsource repo status` — repo analysis status
138
49
  - `govulncheck ./...`
139
50
  - `trivy config .`
140
51
 
@@ -147,12 +58,6 @@ git diff --staged | grep -iE "(password|secret|token|key)\s*=\s*['\"][^'\"$]"
147
58
 
148
59
  # Find TODO/FIXME left in staged files
149
60
  git diff --staged | grep -E "(TODO|FIXME|HACK|XXX)"
150
-
151
- # Find commented-out code blocks (language-agnostic)
152
- git diff --staged | grep -E "^\+\s*(#|//|--|\*)\s*(def |function |class |var |const |let )"
153
-
154
- # Check for untyped any in TypeScript staged files
155
- git diff --staged -- '*.ts' | grep -E ": any"
156
61
  ```
157
62
 
158
63
  ---
@@ -0,0 +1,69 @@
1
+ # Code Excellence — Core Principles
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.
5
+
6
+ ## The Prime Directive
7
+ Write code that the next engineer will thank you for.
8
+ That engineer is you, six months from now, at 2am with a production incident.
9
+ Optimize for that moment.
10
+
11
+ ## On Simplicity
12
+ The simplest solution that correctly solves the stated problem is always right.
13
+ Not the solution that solves the *anticipated* problem.
14
+ Not the solution that would *scale* if requirements changed.
15
+ Not the solution that demonstrates *skill*.
16
+ The solution to the problem in front of you, right now.
17
+
18
+ Before adding any abstraction, answer all three:
19
+ - Does this abstraction already have 2+ concrete use cases that exist TODAY?
20
+ - If removed, does anything break that exists today?
21
+ - Would a new engineer understand the code FASTER with this abstraction than without it?
22
+ If any answer is no — do not add it. Inline the logic.
23
+
24
+ ## On Correctness
25
+ Correctness means the code does exactly what its name promises. Not more. Not less.
26
+ A function named `getUserById` returns a user by ID.
27
+ It does not log. It does not cache. It does not validate sessions. It does not send metrics.
28
+ If it does those things, rename it or split it.
29
+ Side effects that aren't in the name are the leading cause of bugs that take hours to find.
30
+
31
+ ## On Naming
32
+ Names are the primary interface between code and the human reading it.
33
+ A name that requires a comment to explain has failed.
34
+ - Functions are named for what they DO (verb phrase): `validateEmailFormat`, `fetchOrderById`
35
+ - Variables are named for what they CONTAIN (noun phrase): `userRecord`, `retryCount`
36
+ - Booleans are named as assertions: `isValid`, `hasPermission`, `canRetry`
37
+ - Avoid: `data`, `info`, `temp`, `result`, `obj`, `val`, `x`
38
+ If you cannot name something clearly, you do not understand it well enough to write it yet.
39
+
40
+ ## On Error Handling
41
+ Every function that can fail has two paths: success and failure. Both are designed.
42
+ Neither is an afterthought.
43
+ - Errors are never swallowed silently. Silent failures are the worst kind.
44
+ - Error messages tell the caller what happened AND what to do about it.
45
+ - Errors surface at the right level — don't catch what you can't handle.
46
+ - External input is always validated before use. Always.
47
+
48
+ ## On Tests
49
+ Tests are the second consumer of your API. If the test is hard to write, the API is wrong.
50
+ Test behavior, not implementation:
51
+ - WRONG: "calls the repository with the user id"
52
+ - RIGHT: "returns null when the user does not exist in the database"
53
+ The test name is documentation. Write it first. Then write the code that makes it pass.
54
+ A test that can never fail is not a test — it's a ceremony.
55
+
56
+ ## On Dependencies
57
+ Every dependency is a liability you will maintain forever.
58
+ Before adding one, answer:
59
+ - Can this be done in 10 lines with the standard library?
60
+ - Has this package had a commit in the last 6 months?
61
+ - Do you understand it well enough to debug it without its documentation?
62
+ If any answer is no — find an alternative or write it yourself.
63
+
64
+ ## On Comments
65
+ Comments explain WHY, not WHAT. The code explains what.
66
+ A comment that says `// increment counter` above `counter++` is noise.
67
+ A comment that says `// retry three times because the upstream API returns 503 on cold start`
68
+ is knowledge that cannot be inferred from the code alone.
69
+ Delete the first kind. Write more of the second kind.
@@ -0,0 +1,71 @@
1
+ # Engineering Judgment — Reasoning About Hard Decisions
2
+
3
+ This skill provides a framework for reasoning through non-obvious engineering decisions.
4
+ Apply it before writing anything that feels complex, uncertain, or requires a tradeoff.
5
+
6
+ ## The Five Questions (ask before writing anything non-trivial)
7
+
8
+ **1. What is the exact problem I'm solving?**
9
+ Write it in one sentence. Not the category of problem — the specific problem.
10
+ "Users need to reset passwords" is not specific enough.
11
+ "Users who forget their password need to verify identity via email and create a new one" is.
12
+ If you cannot write the sentence, stop and clarify before writing code.
13
+
14
+ **2. What is the simplest thing that could possibly work?**
15
+ Start there. Always. Complexity is additive — you can always add it later.
16
+ Complexity is almost never removable once it exists, because people build on top of it.
17
+ A direct implementation that solves today's problem beats a flexible framework
18
+ that solves tomorrow's hypothetical problems.
19
+
20
+ **3. What will break when requirements change?**
21
+ Identify the parts of your design that are tightly coupled to current requirements.
22
+ Isolate those parts behind boundaries (functions, modules, interfaces).
23
+ Do not protect everything — just the things that are genuinely likely to change.
24
+ Protecting stable things is overhead. Protecting volatile things is architecture.
25
+
26
+ **4. Who reads this code next?**
27
+ They have your codebase, no Slack history, no memory of your decisions, and a deadline.
28
+ What do they absolutely need to understand?
29
+ - What this code does: conveyed by naming
30
+ - Why it exists: conveyed by comments
31
+ - How to change it safely: conveyed by tests
32
+ Make sure all three are present. Everything else is optional.
33
+
34
+ **5. What would you cut if you had to ship in half the time?**
35
+ Cut it now. If the answer is "nothing," your scope is already minimal.
36
+ If the answer is "the caching layer" or "the plugin system" or "the admin dashboard,"
37
+ those things are not part of the core problem. Ship the core. Add the rest when needed.
38
+
39
+ ## The YAGNI Test
40
+ "You Aren't Gonna Need It" is not pessimism — it's empirical engineering.
41
+ Studies consistently show that 70%+ of speculative features are never used.
42
+ Every hour on YAGNI code is an hour not spent on things users actually need.
43
+ Apply it ruthlessly to: abstractions, configuration, generalization, future-proofing.
44
+
45
+ ## When to Refactor
46
+ Refactor when ONE of these is true:
47
+ 1. You are adding a feature and the existing structure makes it harder
48
+ 2. You have seen the same pattern 3 times and can now name it correctly
49
+ Not before. Premature refactoring creates abstractions that don't fit the actual problem
50
+ discovered later. The Rule of Three exists for good reason — once is an instance,
51
+ twice is coincidence, three times is a pattern worth naming.
52
+
53
+ ## On Technical Debt
54
+ Not all debt is bad. Deliberate shortcuts with known payoff timelines are engineering
55
+ decisions. Document them: what was cut, why, and when it should be paid back.
56
+ The only debt worth preventing is accidental complexity — code that is harder than
57
+ it needs to be because no one asked "can we simplify this?"
58
+
59
+ ## The Reversibility Test
60
+ Before any significant decision, ask: how hard is this to undo?
61
+ - Easy to undo → move fast, decide now
62
+ - Hard to undo → move deliberately, decide with evidence
63
+ Two-way doors get opened quickly. One-way doors require the Five Questions above.
64
+
65
+ ## On Code Review
66
+ When reviewing code (your own or others), ask these in order:
67
+ 1. Does it correctly solve the stated problem?
68
+ 2. Is it as simple as it could be while remaining correct?
69
+ 3. Will the next engineer understand it?
70
+ 4. Are the failure paths handled?
71
+ If all four pass, approve. Style differences below this threshold are preferences, not correctness.
@@ -197,5 +197,5 @@ Do NOT auto-remediate. Always ask first.
197
197
  ---
198
198
 
199
199
  ## Removal Condition
200
- Remove when static analysis tooling (Semgrep, SonarQube, or equivalent) is wired
201
- into the pre-commit hook and covers all six entropy categories with automated reporting.
200
+ Remove when static analysis tooling (DeepSource or equivalent) is wired
201
+ into CI and covers all six entropy categories with automated reporting.