@esoteric-logic/praxis-harness 2.0.1 → 2.0.3

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.
@@ -1,12 +1,6 @@
1
1
  ---
2
2
  name: architecture-patterns
3
- description: >
4
- Architecture decision and design documentation standards. Auto-triggers when
5
- writing ADRs, technical specs, risk register entries, system design documents,
6
- or any decision that affects system design, network topology, identity model,
7
- data residency, security posture, or compliance scope. Also triggers when
8
- writing status updates, blocker reports, or spec summaries that require
9
- What/So What/Now What structure.
3
+ description: "Architecture decision and design documentation standards. Auto-triggers when writing ADRs, technical specs, risk register entries, system design documents, or any decision that affects system design, network topology, identity model, data residency, security posture, or compliance scope. Also triggers when writing status updates, blocker reports, or spec summaries that require What/So What/Now What structure."
10
4
  ---
11
5
 
12
6
  # Architecture Patterns
@@ -1,10 +1,7 @@
1
1
  ---
2
2
  name: code-gc
3
3
  disable-model-invocation: true
4
- description: Detect code entropy in the current repo. Dead code, test debt, stale
5
- TODOs, oversized functions, commented-out blocks, unused deps. Two modes:
6
- lightweight (called by session-retro) and full audit (manual /code-gc).
7
- Never auto-deletes or auto-fixes. Side-effect skill — never auto-triggers.
4
+ description: "Detect code entropy in the current repo: dead code, test debt, stale TODOs, oversized functions, commented-out blocks, unused deps. Two modes: lightweight (called by session-retro) and full audit (manual /code-gc). Never auto-deletes or auto-fixes."
8
5
  ---
9
6
 
10
7
  # code-gc Skill
@@ -1,12 +1,6 @@
1
1
  ---
2
2
  name: communication-standards
3
- description: >
4
- Client-facing writing standards. Auto-triggers when writing proposals,
5
- status reports, executive summaries, SOWs, deliverable documents, or any
6
- content targeting a non-technical audience. Also triggers when writing
7
- git commit messages, PR descriptions, or any text where AI attribution
8
- must be avoided. Covers executive-summary-first rule, What/So What/Now What
9
- structure, proposal format, audience calibration, and no-AI-attribution policy.
3
+ description: "Client-facing writing standards. Auto-triggers when writing proposals, status reports, executive summaries, SOWs, deliverable documents, or any content targeting a non-technical audience. Also triggers when writing git commit messages, PR descriptions, or any text where AI attribution must be avoided. Covers executive-summary-first rule, What/So What/Now What structure, proposal format, audience calibration, and no-AI-attribution policy."
10
4
  ---
11
5
 
12
6
  # Communication Standards
@@ -1,10 +1,6 @@
1
1
  ---
2
2
  name: context7-lookup
3
- description: >
4
- Enforces the docs-first mandate from coding.md. Before implementing with
5
- any external library, framework, or API, use Context7 to retrieve current
6
- documentation. Activates when code references an external package, imports
7
- a third-party library, or calls an API that releases frequently.
3
+ description: "Enforces the docs-first mandate from coding.md. Before implementing with any external library, framework, or API, use Context7 to retrieve current documentation. Activates when code references an external package, imports a third-party library, or calls an API that releases frequently."
8
4
  ---
9
5
 
10
6
  # context7-lookup Skill
@@ -1,10 +1,6 @@
1
1
  ---
2
2
  name: managing-git-identities
3
- description: >
4
- Guides setup and troubleshooting of multiple Git identities
5
- (SSH keys, commit author, GitHub CLI auth, includeIf directory
6
- routing). Activates when user discusses git accounts, commit
7
- identity mismatch, SSH key management, or gh auth switching.
3
+ description: "Guides setup and troubleshooting of multiple Git identities (SSH keys, commit author, GitHub CLI auth, includeIf directory routing). Activates when user discusses git accounts, commit identity mismatch, SSH key management, or gh auth switching."
8
4
  ---
9
5
 
10
6
  ## Two Independent Problems
@@ -1,10 +1,7 @@
1
1
  ---
2
2
  name: plan-writer
3
3
  disable-model-invocation: true
4
- description: >
5
- Writes a dated work plan to the vault plans/ directory. Creates the plan
6
- file with YAML frontmatter, milestones, and acceptance criteria. Updates
7
- status.md current_plan field. Called by /plan and /discuss workflows.
4
+ description: "Writes a dated work plan to the vault plans/ directory. Creates the plan file with YAML frontmatter, milestones, and acceptance criteria. Updates status.md current_plan field. Called by /plan and /discuss workflows."
8
5
  ---
9
6
 
10
7
  # plan-writer Skill
@@ -1,10 +1,7 @@
1
1
  ---
2
2
  name: pre-commit-lint
3
3
  disable-model-invocation: true
4
- description: Generate a stack-aware pre-commit hook script for a repo. Use when setting
5
- up a new repo, when asked to "install pre-commit checks", "add linting to commits",
6
- or "wire pre-commit-lint". Also invoked by scaffold-new Phase 5.5.
7
- NOT invoked at commit time — generates a shell script that runs at commit time.
4
+ description: "Generate a stack-aware pre-commit hook script for a repo. Use when setting up a new repo, when asked to install pre-commit checks, add linting to commits, or wire pre-commit-lint. Also invoked by scaffold-new Phase 5.5. NOT invoked at commit time — generates a shell script that runs at commit time."
8
5
  ---
9
6
 
10
7
  # pre-commit-lint Skill
@@ -1,8 +1,7 @@
1
1
  ---
2
2
  name: review
3
3
  disable-model-invocation: true
4
- description: Manual code review trigger. Launches a subagent to review a diff for
5
- bugs, security, and convention violations. Use independently of Praxis phases.
4
+ description: "Manual code review trigger. Launches a subagent to review a diff for bugs, security, and convention violations. Use independently of Praxis phases."
6
5
  ---
7
6
 
8
7
  # review Skill
@@ -1,9 +1,7 @@
1
1
  ---
2
2
  name: scaffold-exist
3
3
  disable-model-invocation: true
4
- description: Scaffold an existing project into the full harness. Invoke with /scaffold-exist only.
5
- Adds missing harness files to projects that predate the scaffold standard.
6
- Non-destructive — never overwrites without confirmation. Side-effect skill — never auto-triggers.
4
+ description: "Scaffold an existing project into the full harness. Invoke with /scaffold-exist only. Adds missing harness files to projects that predate the scaffold standard. Non-destructive — never overwrites without confirmation. Side-effect skill — never auto-triggers."
7
5
  ---
8
6
 
9
7
  # scaffold-exist Skill
@@ -1,9 +1,7 @@
1
1
  ---
2
2
  name: scaffold-new
3
3
  disable-model-invocation: true
4
- description: Scaffold a brand new project into the full harness. Invoke with /scaffold-new only.
5
- Creates repo CLAUDE.md, vault subtree, git identity verification, gitignore,
6
- pre-commit hook, and Project Registry entry. Side-effect skill — never auto-triggers.
4
+ description: "Scaffold a brand new project into the full harness. Invoke with /scaffold-new only. Creates repo CLAUDE.md, vault subtree, git identity verification, gitignore, pre-commit hook, and Project Registry entry. Side-effect skill — never auto-triggers."
7
5
  ---
8
6
 
9
7
  # scaffold-new Skill
@@ -1,10 +1,6 @@
1
1
  ---
2
2
  name: secret-scan
3
- description: >
4
- Canonical secret scanning skill. Scans files for credential patterns
5
- (API keys, tokens, connection strings). Called by pre-commit-lint and
6
- ship workflows. Also usable standalone for repo-wide audits. Replaces
7
- all inline secret scan regex instances with a single authoritative source.
3
+ description: "Canonical secret scanning skill. Scans files for credential patterns (API keys, tokens, connection strings). Called by pre-commit-lint and ship workflows. Also usable standalone for repo-wide audits. Replaces all inline secret scan regex instances with a single authoritative source."
8
4
  ---
9
5
 
10
6
  # secret-scan Skill
@@ -1,9 +1,7 @@
1
1
  ---
2
2
  name: session-retro
3
3
  disable-model-invocation: true
4
- description: End-of-session retrospective. Invoke manually with /session-retro only.
5
- Writes [LEARN:tag] entries, proposes rule updates, updates claude-progress.json,
6
- triggers vault-gc lightweight check. Side-effect skill — never auto-triggers.
4
+ description: "End-of-session retrospective. Invoke manually with /session-retro only. Writes [LEARN:tag] entries, proposes rule updates, updates claude-progress.json, triggers vault-gc lightweight check. Side-effect skill — never auto-triggers."
7
5
  ---
8
6
 
9
7
  # session-retro Skill
@@ -1,9 +1,7 @@
1
1
  ---
2
2
  name: simplify
3
3
  disable-model-invocation: true
4
- description: Post-implementation code simplification. Launches a subagent to review
5
- recent changes for unnecessary complexity, over-abstraction, and opportunities to
6
- simplify. Runs after any implementation phase. Side-effect skill — never auto-triggers.
4
+ description: "Post-implementation code simplification. Launches a subagent to review recent changes for unnecessary complexity, over-abstraction, and opportunities to simplify. Runs after any implementation phase. Side-effect skill — never auto-triggers."
7
5
  ---
8
6
 
9
7
  # simplify Skill
@@ -1,10 +1,7 @@
1
1
  ---
2
2
  name: status-update
3
3
  disable-model-invocation: true
4
- description: >
5
- Atomic update to vault status.md. Ensures consistent format, enforces
6
- the 100-line limit, and archives resolved items. Called at milestone
7
- boundaries, session end, and phase transitions.
4
+ description: "Atomic update to vault status.md. Ensures consistent format, enforces the 100-line limit, and archives resolved items. Called at milestone boundaries, session end, and phase transitions."
8
5
  ---
9
6
 
10
7
  # status-update Skill
@@ -1,9 +1,7 @@
1
1
  ---
2
2
  name: vault-gc
3
3
  disable-model-invocation: true
4
- description: Audit vault health and detect entropy. Invoke manually with /vault-gc
5
- only. Two modes — full audit (manual) and lightweight staleness check (called
6
- inline by session-retro). Never auto-deletes. Side-effect skill — never auto-triggers.
4
+ description: "Audit vault health and detect entropy. Invoke manually with /vault-gc only. Two modes — full audit (manual) and lightweight staleness check (called inline by session-retro). Never auto-deletes. Side-effect skill — never auto-triggers."
7
5
  ---
8
6
 
9
7
  # vault-gc Skill
@@ -1,10 +1,7 @@
1
1
  ---
2
2
  name: verify-app
3
3
  disable-model-invocation: true
4
- description: End-to-end application verification. Launches a subagent to run the full
5
- test suite, check build, verify runtime behavior, and confirm acceptance criteria.
6
- Use after implementation to catch integration issues that unit tests miss.
7
- Side-effect skill — never auto-triggers.
4
+ description: "End-to-end application verification. Launches a subagent to run the full test suite, check build, verify runtime behavior, and confirm acceptance criteria. Use after implementation to catch integration issues that unit tests miss. Side-effect skill — never auto-triggers."
8
5
  ---
9
6
 
10
7
  # verify-app Skill
package/bin/praxis.js CHANGED
@@ -37,7 +37,7 @@ async function install() {
37
37
  header('Praxis Harness v' + VERSION);
38
38
 
39
39
  // Ensure ~/.claude/ structure
40
- for (const sub of ['rules', 'commands', 'skills']) {
40
+ for (const sub of ['rules', 'skills', 'hooks']) {
41
41
  fs.mkdirSync(path.join(CLAUDE_DIR, sub), { recursive: true });
42
42
  }
43
43
 
@@ -59,17 +59,6 @@ async function install() {
59
59
  ok(count + ' rules installed');
60
60
  }
61
61
 
62
- // Copy base/commands/* → ~/.claude/commands/
63
- const cmdsDir = path.join(PKG_DIR, 'base', 'commands');
64
- if (fs.existsSync(cmdsDir)) {
65
- let count = 0;
66
- for (const f of fs.readdirSync(cmdsDir)) {
67
- copyFile(path.join(cmdsDir, f), path.join(CLAUDE_DIR, 'commands', f));
68
- count++;
69
- }
70
- ok(count + ' commands installed');
71
- }
72
-
73
62
  // Copy base/skills/* → ~/.claude/skills/
74
63
  const skillsDir = path.join(PKG_DIR, 'base', 'skills');
75
64
  if (fs.existsSync(skillsDir)) {
@@ -87,6 +76,35 @@ async function install() {
87
76
  ok(count + ' skills installed');
88
77
  }
89
78
 
79
+ // Copy base/hooks/*.sh → ~/.claude/hooks/
80
+ const hooksDir = path.join(PKG_DIR, 'base', 'hooks');
81
+ if (fs.existsSync(hooksDir)) {
82
+ let count = 0;
83
+ for (const f of fs.readdirSync(hooksDir)) {
84
+ if (f.endsWith('.sh')) {
85
+ copyFile(path.join(hooksDir, f), path.join(CLAUDE_DIR, 'hooks', f));
86
+ // Make executable
87
+ fs.chmodSync(path.join(CLAUDE_DIR, 'hooks', f), 0o755);
88
+ count++;
89
+ }
90
+ }
91
+ ok(count + ' hooks installed');
92
+
93
+ // Merge hooks configuration into settings.json
94
+ const hooksConfig = path.join(hooksDir, 'settings-hooks.json');
95
+ const settingsFile = path.join(CLAUDE_DIR, 'settings.json');
96
+ if (fs.existsSync(hooksConfig)) {
97
+ const hooksCfg = JSON.parse(fs.readFileSync(hooksConfig, 'utf8'));
98
+ let settings = {};
99
+ if (fs.existsSync(settingsFile)) {
100
+ try { settings = JSON.parse(fs.readFileSync(settingsFile, 'utf8')); } catch {}
101
+ }
102
+ Object.assign(settings, hooksCfg);
103
+ fs.writeFileSync(settingsFile, JSON.stringify(settings, null, 2) + '\n');
104
+ ok('hooks configuration merged into settings.json');
105
+ }
106
+ }
107
+
90
108
  // Copy kits/ → ~/.claude/kits/
91
109
  const kitsDir = path.join(PKG_DIR, 'kits');
92
110
  if (fs.existsSync(kitsDir)) {
@@ -94,11 +112,29 @@ async function install() {
94
112
  ok('kits installed');
95
113
  }
96
114
 
97
- // Orphan cleanup: obsidian.md renamed to vault.md
98
- const legacyObsidian = path.join(CLAUDE_DIR, 'rules', 'obsidian.md');
99
- if (fs.existsSync(legacyObsidian)) {
100
- fs.unlinkSync(legacyObsidian);
101
- ok('Removed legacy obsidian.md (renamed to vault.md)');
115
+ // Orphan cleanup: deleted rules and legacy files
116
+ const orphans = [
117
+ 'obsidian.md', 'code-quality.md', 'security.md',
118
+ 'communication.md', 'architecture.md'
119
+ ];
120
+ for (const f of orphans) {
121
+ const target = path.join(CLAUDE_DIR, 'rules', f);
122
+ if (fs.existsSync(target)) {
123
+ fs.unlinkSync(target);
124
+ dim('removed legacy ' + f);
125
+ }
126
+ }
127
+
128
+ // Orphan cleanup: old commands directory (v1.x)
129
+ const oldCmdsDir = path.join(CLAUDE_DIR, 'commands');
130
+ if (fs.existsSync(oldCmdsDir)) {
131
+ const files = fs.readdirSync(oldCmdsDir);
132
+ if (files.length > 0) {
133
+ for (const f of files) {
134
+ fs.unlinkSync(path.join(oldCmdsDir, f));
135
+ }
136
+ dim('cleaned up ' + files.length + ' legacy command files');
137
+ }
102
138
  }
103
139
 
104
140
  // Vault configuration
@@ -115,7 +151,7 @@ async function install() {
115
151
  }
116
152
 
117
153
  const config = {
118
- version: '1.1.0',
154
+ version: VERSION,
119
155
  vault_path: vaultPath || '',
120
156
  vault_backend: 'obsidian',
121
157
  repo_path: PKG_DIR
@@ -140,7 +176,7 @@ async function install() {
140
176
  // Summary
141
177
  header('Install complete');
142
178
  console.log(' Files copied to ' + CLAUDE_DIR);
143
- console.log(' Run: npx praxis-harness health');
179
+ console.log(' Run: npx @esoteric-logic/praxis-harness health');
144
180
  console.log('');
145
181
  }
146
182
 
@@ -177,15 +213,6 @@ function health() {
177
213
  }
178
214
  }
179
215
 
180
- // Commands
181
- console.log('\nCommands:');
182
- const cmdsDir = path.join(PKG_DIR, 'base', 'commands');
183
- if (fs.existsSync(cmdsDir)) {
184
- for (const f of fs.readdirSync(cmdsDir)) {
185
- check(fs.existsSync(path.join(CLAUDE_DIR, 'commands', f)), 'commands/' + f + ' installed');
186
- }
187
- }
188
-
189
216
  // Skills
190
217
  console.log('\nSkills:');
191
218
  const skillsDir = path.join(PKG_DIR, 'base', 'skills');
@@ -195,6 +222,18 @@ function health() {
195
222
  }
196
223
  }
197
224
 
225
+ // Hooks
226
+ console.log('\nHooks:');
227
+ const hooksDir = path.join(PKG_DIR, 'base', 'hooks');
228
+ if (fs.existsSync(hooksDir)) {
229
+ for (const f of fs.readdirSync(hooksDir)) {
230
+ if (f.endsWith('.sh')) {
231
+ check(fs.existsSync(path.join(CLAUDE_DIR, 'hooks', f)), 'hooks/' + f + ' installed');
232
+ }
233
+ }
234
+ }
235
+ check(fs.existsSync(path.join(CLAUDE_DIR, 'settings.json')), 'settings.json with hooks configured');
236
+
198
237
  // Kits
199
238
  console.log('\nKits:');
200
239
  check(fs.existsSync(path.join(CLAUDE_DIR, 'kits')), 'kits directory installed');
@@ -236,34 +275,26 @@ function health() {
236
275
  function uninstall() {
237
276
  header('Uninstalling Praxis Harness');
238
277
 
239
- // Remove files that came from base/
278
+ // Remove CLAUDE.md
240
279
  const claudeMd = path.join(CLAUDE_DIR, 'CLAUDE.md');
241
280
  if (fs.existsSync(claudeMd)) { fs.unlinkSync(claudeMd); ok('CLAUDE.md removed'); }
242
281
 
243
- // Remove rules from base/rules/
282
+ // Remove rules
244
283
  const rulesDir = path.join(PKG_DIR, 'base', 'rules');
245
284
  if (fs.existsSync(rulesDir)) {
246
285
  for (const f of fs.readdirSync(rulesDir)) {
247
286
  const target = path.join(CLAUDE_DIR, 'rules', f);
248
287
  if (fs.existsSync(target)) fs.unlinkSync(target);
249
288
  }
250
- // Also remove legacy obsidian.md if present
251
- const legacyRule = path.join(CLAUDE_DIR, 'rules', 'obsidian.md');
252
- if (fs.existsSync(legacyRule)) fs.unlinkSync(legacyRule);
253
- ok('rules removed');
254
- }
255
-
256
- // Remove commands from base/commands/
257
- const cmdsDir = path.join(PKG_DIR, 'base', 'commands');
258
- if (fs.existsSync(cmdsDir)) {
259
- for (const f of fs.readdirSync(cmdsDir)) {
260
- const target = path.join(CLAUDE_DIR, 'commands', f);
289
+ // Also remove legacy files
290
+ for (const f of ['obsidian.md', 'code-quality.md', 'security.md', 'communication.md', 'architecture.md']) {
291
+ const target = path.join(CLAUDE_DIR, 'rules', f);
261
292
  if (fs.existsSync(target)) fs.unlinkSync(target);
262
293
  }
263
- ok('commands removed');
294
+ ok('rules removed');
264
295
  }
265
296
 
266
- // Remove skills from base/skills/
297
+ // Remove skills
267
298
  const skillsDir = path.join(PKG_DIR, 'base', 'skills');
268
299
  if (fs.existsSync(skillsDir)) {
269
300
  for (const entry of fs.readdirSync(skillsDir)) {
@@ -275,6 +306,17 @@ function uninstall() {
275
306
  ok('skills removed');
276
307
  }
277
308
 
309
+ // Remove hooks
310
+ const hooksDir = path.join(CLAUDE_DIR, 'hooks');
311
+ if (fs.existsSync(hooksDir)) {
312
+ for (const f of fs.readdirSync(hooksDir)) {
313
+ if (f.endsWith('.sh')) {
314
+ fs.unlinkSync(path.join(hooksDir, f));
315
+ }
316
+ }
317
+ ok('hooks removed');
318
+ }
319
+
278
320
  // Remove kits
279
321
  const kitsTarget = path.join(CLAUDE_DIR, 'kits');
280
322
  if (fs.existsSync(kitsTarget)) {
@@ -282,6 +324,13 @@ function uninstall() {
282
324
  ok('kits removed');
283
325
  }
284
326
 
327
+ // Remove legacy commands directory
328
+ const oldCmdsDir = path.join(CLAUDE_DIR, 'commands');
329
+ if (fs.existsSync(oldCmdsDir)) {
330
+ fs.rmSync(oldCmdsDir, { recursive: true, force: true });
331
+ ok('legacy commands directory removed');
332
+ }
333
+
285
334
  header('Uninstall complete');
286
335
  dim('Config file preserved: ' + CONFIG_FILE);
287
336
  dim('Run: rm ' + CONFIG_FILE + ' to remove config');
@@ -294,10 +343,10 @@ function printHelp() {
294
343
  console.log(`
295
344
  praxis-harness v${VERSION}
296
345
 
297
- Usage: npx praxis-harness [command]
346
+ Usage: npx @esoteric-logic/praxis-harness [command]
298
347
 
299
348
  Commands:
300
- install Copy rules, commands, skills, and kits to ~/.claude/ (default)
349
+ install Copy rules, skills, hooks, and kits to ~/.claude/ (default)
301
350
  update Re-copy from latest npm package version
302
351
  health Verify install integrity
303
352
  uninstall Remove Praxis-owned files from ~/.claude/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@esoteric-logic/praxis-harness",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
4
4
  "description": "Layered Claude Code harness — workflow discipline, AI-Kits, persistent vault integration",
5
5
  "bin": {
6
6
  "praxis-harness": "./bin/praxis.js"