@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.
- package/base/CLAUDE.md +11 -2
- package/base/configs/ci/lint-stack.yml +19 -109
- package/base/configs/registry.json +1 -5
- package/base/hooks/settings-hooks.json +0 -13
- package/base/hooks/vault-checkpoint.sh +0 -2
- package/base/rules/code-quality.md +56 -0
- package/base/rules/coding.md +15 -110
- package/base/skills/code-excellence.md +69 -0
- package/base/skills/engineering-judgment.md +71 -0
- package/base/skills/px-code-gc/SKILL.md +2 -2
- package/base/skills/px-deepsource-coverage/SKILL.md +48 -0
- package/base/skills/px-deepsource-review/SKILL.md +50 -0
- package/base/skills/px-deepsource-setup/SKILL.md +56 -0
- package/base/skills/px-pre-commit-lint/SKILL.md +1 -2
- package/base/skills/px-scaffold-new/references/repo-CLAUDE-md-template.md +1 -1
- package/base/skills/px-ship/SKILL.md +1 -1
- package/base/skills/px-verify/SKILL.md +2 -2
- package/base/skills/self-verify.md +78 -0
- package/bin/praxis-preflight.sh +1 -1
- package/bin/praxis.js +3 -3
- package/kits/code-quality/KIT.md +55 -0
- package/kits/code-quality/configs/checks-registry.json +35 -0
- package/kits/code-quality/configs/thresholds.json +36 -0
- package/kits/code-quality/hooks/generate-baseline.sh +30 -0
- package/kits/code-quality/hooks/post-commit.sh +28 -0
- package/kits/code-quality/hooks/pre-push.sh +104 -0
- package/kits/code-quality/install.sh +68 -0
- package/kits/code-quality/manifest.json +27 -0
- package/kits/code-quality/skills/over-engineering.md +72 -0
- package/kits/code-quality/skills/performance-review.md +65 -0
- package/kits/code-quality/skills/self-review.md +55 -0
- package/kits/code-quality/skills/structural-review.md +57 -0
- package/kits/code-quality/teardown.sh +21 -0
- package/kits/security/commands/security-audit.md +1 -1
- package/kits/security/install.sh +1 -1
- package/kits/security/teardown.sh +1 -1
- package/package.json +1 -1
- package/scripts/install-tools.sh +2 -2
- package/scripts/test-harness.sh +5 -13
- package/base/configs/linters/.pre-commit-config.yaml +0 -63
- package/base/configs/linters/semgrep.yml +0 -65
- package/base/hooks/post-session-lint.sh +0 -44
- 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 (
|
|
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` |
|
|
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
|
-
#
|
|
1
|
+
# Lint Stack — CI Template
|
|
2
2
|
# Copy to: .github/workflows/lint-stack.yml
|
|
3
|
-
#
|
|
4
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
71
|
-
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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": "
|
|
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."
|
package/base/rules/coding.md
CHANGED
|
@@ -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
|
|
22
|
+
- Prefer MCP tools for current documentation (context7).
|
|
23
|
+
- YAML frontmatter on all markdown files.
|
|
113
24
|
|
|
114
25
|
---
|
|
115
26
|
|
|
116
|
-
##
|
|
27
|
+
## Quality Architecture
|
|
117
28
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
-
|
|
122
|
-
-
|
|
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
|
-
|
|
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
|
|
43
|
+
Single-file:
|
|
133
44
|
- `go vet <file>` / `shellcheck <file>` / `hadolint Dockerfile` / `markdownlint <file>.md`
|
|
134
45
|
|
|
135
|
-
Project-level
|
|
136
|
-
- `
|
|
137
|
-
- `
|
|
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 (
|
|
201
|
-
into
|
|
200
|
+
Remove when static analysis tooling (DeepSource or equivalent) is wired
|
|
201
|
+
into CI and covers all six entropy categories with automated reporting.
|