@esoteric-logic/praxis-harness 2.8.0 → 2.9.1
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/auto-format.sh +1 -0
- package/base/hooks/dep-audit.sh +20 -7
- package/base/hooks/session-data-collect.sh +1 -0
- package/base/hooks/settings-hooks.json +0 -13
- package/base/hooks/vault-checkpoint.sh +1 -2
- package/base/lib/kit-check.sh +42 -0
- package/base/lib/output.sh +38 -0
- 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 +6 -9
- package/bin/praxis.js +3 -3
- package/kits/api/install.sh +3 -16
- 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 +127 -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/data/install.sh +6 -19
- package/kits/infrastructure/install.sh +2 -20
- package/kits/security/commands/security-audit.md +1 -1
- package/kits/security/install.sh +5 -18
- package/kits/security/teardown.sh +1 -1
- package/package.json +1 -1
- package/scripts/install-tools.sh +2 -2
- package/scripts/onboard-mcp.sh +3 -18
- 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": [
|
package/base/hooks/dep-audit.sh
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
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 -
|
|
5
|
+
set -uo pipefail
|
|
6
|
+
trap 'exit 0' ERR
|
|
6
7
|
|
|
7
8
|
INPUT=$(cat)
|
|
8
9
|
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // empty' 2>/dev/null)
|
|
@@ -20,28 +21,40 @@ case "$BASENAME" in
|
|
|
20
21
|
package.json)
|
|
21
22
|
ECOSYSTEM="npm"
|
|
22
23
|
if command -v npm &>/dev/null && [[ -f "$DIR/package-lock.json" || -f "$DIR/node_modules/.package-lock.json" ]]; then
|
|
23
|
-
|
|
24
|
+
# npm audit exits non-zero when vulnerabilities exist — capture output regardless
|
|
25
|
+
AUDIT_RESULT=$(cd "$DIR" && npm audit --audit-level=high --json 2>/dev/null) || {
|
|
26
|
+
if [[ -n "$AUDIT_RESULT" ]]; then
|
|
27
|
+
: # non-zero with output = vulnerabilities found (expected)
|
|
28
|
+
else
|
|
29
|
+
echo "DEP-AUDIT (npm): audit command failed" >&2
|
|
30
|
+
fi
|
|
31
|
+
}
|
|
24
32
|
fi
|
|
25
33
|
;;
|
|
26
34
|
go.mod)
|
|
27
35
|
ECOSYSTEM="go"
|
|
28
36
|
if command -v govulncheck &>/dev/null; then
|
|
29
|
-
AUDIT_RESULT=$(cd "$DIR" && govulncheck -json ./... 2>/dev/null ||
|
|
37
|
+
AUDIT_RESULT=$(cd "$DIR" && govulncheck -json ./... 2>/dev/null) || {
|
|
38
|
+
[[ -z "$AUDIT_RESULT" ]] && echo "DEP-AUDIT (go): govulncheck failed" >&2
|
|
39
|
+
}
|
|
30
40
|
elif command -v go &>/dev/null; then
|
|
31
|
-
|
|
32
|
-
AUDIT_RESULT=$(cd "$DIR" && go list -m -json all 2>/dev/null | head -c 5000 || true)
|
|
41
|
+
AUDIT_RESULT=$(cd "$DIR" && go list -m -json all 2>/dev/null | head -c 5000) || AUDIT_RESULT=""
|
|
33
42
|
fi
|
|
34
43
|
;;
|
|
35
44
|
requirements.txt|pyproject.toml)
|
|
36
45
|
ECOSYSTEM="python"
|
|
37
46
|
if command -v pip-audit &>/dev/null; then
|
|
38
|
-
AUDIT_RESULT=$(cd "$DIR" && pip-audit --format=json 2>/dev/null ||
|
|
47
|
+
AUDIT_RESULT=$(cd "$DIR" && pip-audit --format=json 2>/dev/null) || {
|
|
48
|
+
[[ -z "$AUDIT_RESULT" ]] && echo "DEP-AUDIT (python): pip-audit failed" >&2
|
|
49
|
+
}
|
|
39
50
|
fi
|
|
40
51
|
;;
|
|
41
52
|
Cargo.toml)
|
|
42
53
|
ECOSYSTEM="rust"
|
|
43
54
|
if command -v cargo-audit &>/dev/null; then
|
|
44
|
-
AUDIT_RESULT=$(cd "$DIR" && cargo audit --json 2>/dev/null ||
|
|
55
|
+
AUDIT_RESULT=$(cd "$DIR" && cargo audit --json 2>/dev/null) || {
|
|
56
|
+
[[ -z "$AUDIT_RESULT" ]] && echo "DEP-AUDIT (rust): cargo-audit failed" >&2
|
|
57
|
+
}
|
|
45
58
|
fi
|
|
46
59
|
;;
|
|
47
60
|
*)
|
|
@@ -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."
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
# PreCompact hook — writes minimal checkpoint to vault before context compaction.
|
|
3
3
|
# Always exits 0 (advisory, never blocks compaction).
|
|
4
4
|
set -uo pipefail
|
|
5
|
+
trap 'exit 0' ERR
|
|
5
6
|
|
|
6
7
|
CONFIG_FILE="$HOME/.claude/praxis.config.json"
|
|
7
8
|
|
|
@@ -23,8 +24,6 @@ CHECKPOINT_FILE="$PLANS_DIR/$DATE-compact-checkpoint.md"
|
|
|
23
24
|
|
|
24
25
|
BRANCH=$(git --no-pager rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
|
|
25
26
|
LAST_COMMIT=$(git --no-pager log --oneline -1 2>/dev/null || echo "no commits")
|
|
26
|
-
PROJECT_DIR=$(basename "$PWD")
|
|
27
|
-
|
|
28
27
|
STATUS_FILE="$VAULT_PATH/status.md"
|
|
29
28
|
PROGRESS_FILE="$VAULT_PATH/claude-progress.json"
|
|
30
29
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ════════════════════════════════════════════════════════════════
|
|
3
|
+
# Praxis — Shared Kit Install Check
|
|
4
|
+
# Source this file in kit install.sh scripts for consistent
|
|
5
|
+
# tool-checking output and counters.
|
|
6
|
+
#
|
|
7
|
+
# Usage:
|
|
8
|
+
# source "$(dirname "$0")/../../base/lib/kit-check.sh"
|
|
9
|
+
# check "jq" "brew install jq"
|
|
10
|
+
# check "curl" "pre-installed on macOS/Linux"
|
|
11
|
+
# kit_check_summary
|
|
12
|
+
# ════════════════════════════════════════════════════════════════
|
|
13
|
+
|
|
14
|
+
KIT_CHECK_PASS=0
|
|
15
|
+
KIT_CHECK_TOTAL=0
|
|
16
|
+
|
|
17
|
+
check() {
|
|
18
|
+
local cmd="$1"
|
|
19
|
+
local install_hint="$2"
|
|
20
|
+
local optional="${3:-}"
|
|
21
|
+
|
|
22
|
+
KIT_CHECK_TOTAL=$((KIT_CHECK_TOTAL + 1))
|
|
23
|
+
if command -v "$cmd" &>/dev/null; then
|
|
24
|
+
echo " ✓ $cmd found ($(command -v "$cmd"))"
|
|
25
|
+
KIT_CHECK_PASS=$((KIT_CHECK_PASS + 1))
|
|
26
|
+
else
|
|
27
|
+
if [[ "$optional" == "optional" ]]; then
|
|
28
|
+
echo " ⚠ $cmd not found (optional)"
|
|
29
|
+
else
|
|
30
|
+
echo " ✗ $cmd not found"
|
|
31
|
+
fi
|
|
32
|
+
echo " Install: $install_hint"
|
|
33
|
+
fi
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
kit_check_summary() {
|
|
37
|
+
echo ""
|
|
38
|
+
echo " $KIT_CHECK_PASS/$KIT_CHECK_TOTAL tools found"
|
|
39
|
+
if [[ $KIT_CHECK_PASS -lt $KIT_CHECK_TOTAL ]]; then
|
|
40
|
+
echo " ⚠ Some tools missing. Install them before using kit commands."
|
|
41
|
+
fi
|
|
42
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ═══════��════════════════════════════════════════════════════════
|
|
3
|
+
# Praxis — Shared Output Helpers
|
|
4
|
+
# Source this file instead of defining colors/helpers inline.
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# source "$(dirname "$0")/../base/lib/output.sh"
|
|
8
|
+
# # or with absolute path:
|
|
9
|
+
# source "$HOME/.claude/lib/output.sh"
|
|
10
|
+
#
|
|
11
|
+
# Safe to source multiple times — guards against redefinition.
|
|
12
|
+
# ════��═══════════════════════════════════════════════════════════
|
|
13
|
+
|
|
14
|
+
# ─── Colors (skip if already set) ───
|
|
15
|
+
RED="${RED:-\033[0;31m}"
|
|
16
|
+
GREEN="${GREEN:-\033[0;32m}"
|
|
17
|
+
YELLOW="${YELLOW:-\033[0;33m}"
|
|
18
|
+
CYAN="${CYAN:-\033[0;36m}"
|
|
19
|
+
BOLD="${BOLD:-\033[1m}"
|
|
20
|
+
DIM="${DIM:-\033[2m}"
|
|
21
|
+
NC="${NC:-\033[0m}"
|
|
22
|
+
|
|
23
|
+
# ─── Output helpers (skip if already defined) ───
|
|
24
|
+
if ! declare -f ok &>/dev/null; then
|
|
25
|
+
ok() { echo -e " ${GREEN}✓${NC} $1"; }
|
|
26
|
+
fi
|
|
27
|
+
if ! declare -f warn &>/dev/null; then
|
|
28
|
+
warn() { echo -e " ${YELLOW}⚠${NC} $1"; }
|
|
29
|
+
fi
|
|
30
|
+
if ! declare -f fail &>/dev/null; then
|
|
31
|
+
fail() { echo -e " ${RED}✗${NC} $1"; }
|
|
32
|
+
fi
|
|
33
|
+
if ! declare -f step &>/dev/null; then
|
|
34
|
+
step() { echo -e "\n${CYAN}${BOLD}$1${NC}"; }
|
|
35
|
+
fi
|
|
36
|
+
if ! declare -f dim &>/dev/null; then
|
|
37
|
+
dim() { echo -e " ${DIM}$1${NC}"; }
|
|
38
|
+
fi
|
|
@@ -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
|
---
|