@esoteric-logic/praxis-harness 1.1.0 → 1.2.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/README.md +6 -14
- package/base/CLAUDE.md +4 -4
- package/base/commands/context-reset.md +3 -3
- package/base/commands/gsd-verify.md +1 -1
- package/base/commands/simplify.md +15 -0
- package/base/hooks/post-session-lint.sh +39 -0
- package/base/hooks/secret-scan.sh +27 -0
- package/base/hooks/vault-checkpoint.sh +75 -0
- package/base/rules/vault.md +5 -15
- package/base/skills/scaffold-new/SKILL.md +2 -4
- package/base/skills/scaffold-new/references/gitignore-template.txt +0 -1
- package/bin/praxis.js +6 -67
- package/package.json +9 -2
- package/scripts/health-check.sh +3 -11
- package/scripts/update.sh +2 -10
package/README.md
CHANGED
|
@@ -84,7 +84,7 @@ For technical research: `/discover` (structured options evaluation before decisi
|
|
|
84
84
|
|
|
85
85
|
Key additions in this version:
|
|
86
86
|
- **context-management** — context brackets (FRESH/MODERATE/DEPLETED/CRITICAL) adapt behavior to session stage
|
|
87
|
-
- **vault** —
|
|
87
|
+
- **vault** — Obsidian vault integration
|
|
88
88
|
|
|
89
89
|
## Ralph
|
|
90
90
|
|
|
@@ -111,7 +111,7 @@ Ralph is not a replacement for GSD — it runs GSD internally per story. Use GSD
|
|
|
111
111
|
│ GSD → Superpowers → Ralph │
|
|
112
112
|
├────────────────────────────────────────┤
|
|
113
113
|
│ Vault layer │
|
|
114
|
-
│
|
|
114
|
+
│ Obsidian │
|
|
115
115
|
├────────────────────────────────────────┤
|
|
116
116
|
│ Claude Code │
|
|
117
117
|
│ ~/.claude/ + plugins + subagents │
|
|
@@ -131,16 +131,9 @@ More kits coming. See `docs/creating-a-kit.md` to build your own.
|
|
|
131
131
|
|
|
132
132
|
## Vault integration
|
|
133
133
|
|
|
134
|
-
Praxis integrates with
|
|
134
|
+
Praxis integrates with an Obsidian vault for project state, session learnings, and architecture decisions.
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
|---------|-------------|-------------|
|
|
138
|
-
| `obsidian` | Obsidian vault (default) | [Obsidian CLI](https://obsidian.md) |
|
|
139
|
-
| `logseq` | Logseq graph | ripgrep |
|
|
140
|
-
| `plain` | Plain markdown directory (`~/.praxis-vault`) | ripgrep |
|
|
141
|
-
| `custom` | Any directory you choose | ripgrep |
|
|
142
|
-
|
|
143
|
-
The backend and vault path are configured per machine during install:
|
|
136
|
+
The vault path is configured per machine during install:
|
|
144
137
|
|
|
145
138
|
```json
|
|
146
139
|
{
|
|
@@ -151,8 +144,7 @@ The backend and vault path are configured per machine during install:
|
|
|
151
144
|
}
|
|
152
145
|
```
|
|
153
146
|
|
|
154
|
-
|
|
155
|
-
- **logseq/plain/custom**: uses ripgrep for vault search — no extra dependencies
|
|
147
|
+
Requires [Obsidian CLI](https://obsidian.md) (enable in Obsidian Settings > General > Command line interface). Obsidian must be running for vault search.
|
|
156
148
|
|
|
157
149
|
## Updating
|
|
158
150
|
|
|
@@ -185,7 +177,7 @@ The git-clone + `install.sh` path uses symlinks instead of copies, so edits in t
|
|
|
185
177
|
- macOS or Linux
|
|
186
178
|
- Claude Code CLI
|
|
187
179
|
- Node.js 18+
|
|
188
|
-
- Obsidian
|
|
180
|
+
- Obsidian with CLI enabled (for vault integration)
|
|
189
181
|
|
|
190
182
|
## License
|
|
191
183
|
|
package/base/CLAUDE.md
CHANGED
|
@@ -57,7 +57,6 @@ Vault path and backend are machine-specific. Read from `~/.claude/praxis.config.
|
|
|
57
57
|
```json
|
|
58
58
|
{ "vault_path": "/path/to/vault", "vault_backend": "obsidian" }
|
|
59
59
|
```
|
|
60
|
-
Supported backends: `obsidian` (default), `logseq`, `plain`, `custom`.
|
|
61
60
|
If config file is missing: tell the user to run `praxis/install.sh`.
|
|
62
61
|
All `{vault_path}` references in rules and skills resolve from this config.
|
|
63
62
|
|
|
@@ -75,7 +74,7 @@ Context is volatile. Files are permanent. Act accordingly.
|
|
|
75
74
|
## Vault Protocol
|
|
76
75
|
- ALWAYS run a vault search before reading vault files (see vault.md backend table).
|
|
77
76
|
- Obsidian indexes in real-time — no manual update command needed.
|
|
78
|
-
- Link format:
|
|
77
|
+
- Link format: `[[wikilinks]]` for all internal vault references.
|
|
79
78
|
- Detect project from CWD matching `local_path` in `_index.md`.
|
|
80
79
|
|
|
81
80
|
## MCP Servers
|
|
@@ -84,9 +83,10 @@ Registered via `claude mcp add`. Persist globally across sessions.
|
|
|
84
83
|
| Server | Purpose | API Key |
|
|
85
84
|
|--------|---------|---------|
|
|
86
85
|
| context7 | Live library/API docs | None |
|
|
87
|
-
| perplexity | AI web search | `PERPLEXITY_API_KEY` |
|
|
88
86
|
| github | Repo operations, PRs, issues | `GITHUB_PERSONAL_ACCESS_TOKEN` |
|
|
89
87
|
|
|
88
|
+
Optional: `perplexity` (AI web search). Run `bash scripts/onboard-mcp.sh perplexity` to add.
|
|
89
|
+
|
|
90
90
|
Check: `claude mcp list` | Manage: `bash scripts/onboard-mcp.sh [server|all]`
|
|
91
91
|
Missing servers are non-blocking — features degrade gracefully.
|
|
92
92
|
|
|
@@ -135,7 +135,7 @@ Kit manifests live in `~/.claude/kits/<name>/KIT.md`.
|
|
|
135
135
|
| `~/.claude/rules/git-workflow.md` | Commits, branches, identity verification |
|
|
136
136
|
| `~/.claude/rules/security.md` | Secrets, credentials, auth patterns |
|
|
137
137
|
| `~/.claude/rules/communication.md` | Client writing, no AI attribution |
|
|
138
|
-
| `~/.claude/rules/vault.md` | Second brain integration —
|
|
138
|
+
| `~/.claude/rules/vault.md` | Second brain integration — Obsidian vault |
|
|
139
139
|
| `~/.claude/rules/architecture.md` | ADR format, What/So What/Now What, risk docs |
|
|
140
140
|
| `~/.claude/rules/context-management.md` | GSD/Ralph anti-rot, context reset protocol |
|
|
141
141
|
|
|
@@ -15,7 +15,7 @@ You are preparing a clean context reset for the current session.
|
|
|
15
15
|
- Identify: current milestone, last 3 decisions, any STOP conditions or blockers
|
|
16
16
|
|
|
17
17
|
**Step 3 — Write context checkpoint**
|
|
18
|
-
Write a standalone checkpoint file at `{vault_path}/plans/
|
|
18
|
+
Write a standalone checkpoint file at `{vault_path}/plans/{YYYY-MM-DD}-context-checkpoint.md`:
|
|
19
19
|
|
|
20
20
|
```markdown
|
|
21
21
|
---
|
|
@@ -58,7 +58,7 @@ Write a session snapshot to `claude-progress.json`:
|
|
|
58
58
|
Print:
|
|
59
59
|
```
|
|
60
60
|
Context checkpoint saved to:
|
|
61
|
-
Checkpoint: {vault_path}/plans/
|
|
61
|
+
Checkpoint: {vault_path}/plans/{YYYY-MM-DD}-context-checkpoint.md
|
|
62
62
|
Status: {vault_path}/status.md
|
|
63
63
|
Progress: {vault_path}/claude-progress.json
|
|
64
64
|
|
|
@@ -67,6 +67,6 @@ Run /clear to reset context, then paste this bootstrap prompt:
|
|
|
67
67
|
Context reset. Bootstrap:
|
|
68
68
|
1. Read project CLAUDE.md
|
|
69
69
|
2. Read {vault_path}/plans/{current-plan}
|
|
70
|
-
3. Read {vault_path}/plans/
|
|
70
|
+
3. Read {vault_path}/plans/{YYYY-MM-DD}-context-checkpoint.md
|
|
71
71
|
4. Resume from milestone: {milestone-name}
|
|
72
72
|
```
|
|
@@ -32,7 +32,7 @@ If no commands are defined: warn and ask user for the correct commands.
|
|
|
32
32
|
|
|
33
33
|
**Step 3b — UNIFY (mandatory after all milestones verified)**
|
|
34
34
|
After self-review passes, write phase summary:
|
|
35
|
-
- Write `{vault_path}/plans/
|
|
35
|
+
- Write `{vault_path}/plans/{YYYY-MM-DD}_{project-slug}-phase-summary.md`:
|
|
36
36
|
```markdown
|
|
37
37
|
---
|
|
38
38
|
tags: [unify, {project-slug}]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Post-implementation code cleanup. Launches a subagent to find and
|
|
3
|
+
simplify over-abstraction, dead paths, verbosity, and missed idioms in the
|
|
4
|
+
recent diff. Run after implementation, before /verify-app or /ship.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Invoke the code-simplifier skill on the current project's recent changes.
|
|
8
|
+
|
|
9
|
+
Accept an optional scope argument:
|
|
10
|
+
- No argument → `git diff HEAD~1` (default)
|
|
11
|
+
- `staged` → staged changes only
|
|
12
|
+
- `HEAD~N` or SHA → specific range
|
|
13
|
+
|
|
14
|
+
The code-simplifier skill handles all phases: scope detection, subagent launch,
|
|
15
|
+
finding presentation, user-approved edits, and optional [LEARN:simplify] capture.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Stop hook — runs project lint command as an advisory check.
|
|
3
|
+
# Always exits 0 (never blocks session end).
|
|
4
|
+
set -uo pipefail
|
|
5
|
+
|
|
6
|
+
CONFIG_FILE="$HOME/.claude/praxis.config.json"
|
|
7
|
+
|
|
8
|
+
# Find project CLAUDE.md by walking up from CWD
|
|
9
|
+
find_project_claude_md() {
|
|
10
|
+
local dir="$PWD"
|
|
11
|
+
while [[ "$dir" != "/" ]]; do
|
|
12
|
+
if [[ -f "$dir/CLAUDE.md" ]]; then
|
|
13
|
+
echo "$dir/CLAUDE.md"
|
|
14
|
+
return 0
|
|
15
|
+
fi
|
|
16
|
+
dir=$(dirname "$dir")
|
|
17
|
+
done
|
|
18
|
+
return 1
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
CLAUDE_MD=$(find_project_claude_md 2>/dev/null) || exit 0
|
|
22
|
+
|
|
23
|
+
# Extract lint command from ## Commands section
|
|
24
|
+
LINT_CMD=$(awk '/^## Commands/,/^## /{
|
|
25
|
+
if (/^lint:/) { sub(/^lint:[[:space:]]*/, ""); print; exit }
|
|
26
|
+
}' "$CLAUDE_MD" 2>/dev/null)
|
|
27
|
+
|
|
28
|
+
if [[ -z "$LINT_CMD" || "$LINT_CMD" == "#"* ]]; then
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
echo "Running lint: $LINT_CMD" >&2
|
|
33
|
+
if eval "$LINT_CMD" 2>&1 | tail -20 >&2; then
|
|
34
|
+
echo "Lint: PASS" >&2
|
|
35
|
+
else
|
|
36
|
+
echo "Lint: warnings found (advisory only)" >&2
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
exit 0
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# PreToolUse hook — blocks Write/Edit if file contains secret patterns.
|
|
3
|
+
# Exit 0 = allow, Exit 2 = block with message.
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
# Claude Code passes tool input as JSON via stdin for PreToolUse hooks
|
|
7
|
+
INPUT=$(cat)
|
|
8
|
+
|
|
9
|
+
# Extract file_path from the JSON input (works for Write, Edit tools)
|
|
10
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // empty' 2>/dev/null)
|
|
11
|
+
|
|
12
|
+
if [[ -z "$FILE_PATH" || ! -f "$FILE_PATH" ]]; then
|
|
13
|
+
exit 0
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
# Scan the file for secret patterns
|
|
17
|
+
SECRET_PATTERN='(sk-[a-zA-Z0-9]{20,}|ghp_[a-zA-Z0-9]{36,}|pplx-[a-zA-Z0-9]{20,}|AKIA[0-9A-Z]{16}|Bearer [A-Za-z0-9+/]{20,})'
|
|
18
|
+
|
|
19
|
+
if rg -q "$SECRET_PATTERN" "$FILE_PATH" 2>/dev/null; then
|
|
20
|
+
MATCHES=$(rg -n "$SECRET_PATTERN" "$FILE_PATH" 2>/dev/null | head -5)
|
|
21
|
+
echo "BLOCKED: Potential secret detected in $FILE_PATH" >&2
|
|
22
|
+
echo "$MATCHES" >&2
|
|
23
|
+
echo "Remove the secret before proceeding." >&2
|
|
24
|
+
exit 2
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
exit 0
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# PreCompact hook — writes minimal checkpoint to vault before context compaction.
|
|
3
|
+
# Always exits 0 (advisory, never blocks compaction).
|
|
4
|
+
set -uo pipefail
|
|
5
|
+
|
|
6
|
+
CONFIG_FILE="$HOME/.claude/praxis.config.json"
|
|
7
|
+
|
|
8
|
+
if [[ ! -f "$CONFIG_FILE" ]]; then
|
|
9
|
+
exit 0
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
VAULT_PATH=$(jq -r '.vault_path // empty' "$CONFIG_FILE" 2>/dev/null)
|
|
13
|
+
if [[ -z "$VAULT_PATH" || ! -d "$VAULT_PATH" ]]; then
|
|
14
|
+
exit 0
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
PLANS_DIR="$VAULT_PATH/plans"
|
|
18
|
+
mkdir -p "$PLANS_DIR"
|
|
19
|
+
|
|
20
|
+
DATE=$(date +%Y-%m-%d)
|
|
21
|
+
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
|
|
22
|
+
CHECKPOINT_FILE="$PLANS_DIR/$DATE-compact-checkpoint.md"
|
|
23
|
+
|
|
24
|
+
BRANCH=$(git --no-pager rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
|
|
25
|
+
LAST_COMMIT=$(git --no-pager log --oneline -1 2>/dev/null || echo "no commits")
|
|
26
|
+
PROJECT_DIR=$(basename "$PWD")
|
|
27
|
+
|
|
28
|
+
STATUS_FILE="$VAULT_PATH/status.md"
|
|
29
|
+
PROGRESS_FILE="$VAULT_PATH/claude-progress.json"
|
|
30
|
+
|
|
31
|
+
CURRENT_PLAN="none"
|
|
32
|
+
LOOP_POSITION="unknown"
|
|
33
|
+
if [[ -f "$STATUS_FILE" ]]; then
|
|
34
|
+
CURRENT_PLAN=$(grep "^current_plan:" "$STATUS_FILE" | sed 's/current_plan: *//' | head -1)
|
|
35
|
+
LOOP_POSITION=$(grep "^loop_position:" "$STATUS_FILE" | sed 's/loop_position: *//' | head -1)
|
|
36
|
+
[[ -z "$CURRENT_PLAN" ]] && CURRENT_PLAN="none"
|
|
37
|
+
[[ -z "$LOOP_POSITION" ]] && LOOP_POSITION="unknown"
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
RALPH_STORY="inactive"
|
|
41
|
+
if [[ -f "$PROGRESS_FILE" ]]; then
|
|
42
|
+
RALPH_STORY=$(jq -r '.ralph_state.current_story // "inactive"' "$PROGRESS_FILE" 2>/dev/null)
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
cat > "$CHECKPOINT_FILE" <<EOF
|
|
46
|
+
---
|
|
47
|
+
tags: [checkpoint, compact]
|
|
48
|
+
date: $DATE
|
|
49
|
+
source: agent
|
|
50
|
+
---
|
|
51
|
+
# Compact Checkpoint — $TIMESTAMP
|
|
52
|
+
|
|
53
|
+
## Working Directory
|
|
54
|
+
$PWD
|
|
55
|
+
|
|
56
|
+
## Git State
|
|
57
|
+
- Branch: $BRANCH
|
|
58
|
+
- Last commit: $LAST_COMMIT
|
|
59
|
+
|
|
60
|
+
## Active Plan
|
|
61
|
+
$CURRENT_PLAN
|
|
62
|
+
|
|
63
|
+
## GSD Phase
|
|
64
|
+
$LOOP_POSITION
|
|
65
|
+
|
|
66
|
+
## Ralph State
|
|
67
|
+
$RALPH_STORY
|
|
68
|
+
|
|
69
|
+
## Note
|
|
70
|
+
This checkpoint was auto-written by the PreCompact hook.
|
|
71
|
+
Read this file after compaction to restore context.
|
|
72
|
+
EOF
|
|
73
|
+
|
|
74
|
+
echo "Vault checkpoint written: $CHECKPOINT_FILE" >&2
|
|
75
|
+
exit 0
|
package/base/rules/vault.md
CHANGED
|
@@ -3,20 +3,13 @@
|
|
|
3
3
|
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
## Backend
|
|
7
|
-
Read `vault_backend` from `~/.claude/praxis.config.json`. Defaults to `"obsidian"` if absent.
|
|
6
|
+
## Vault Backend
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|---------|---------------|-------------------|-------------|
|
|
11
|
-
| `obsidian` | `obsidian search query="{query}" limit=5` | no-op (real-time indexing) | `[[wikilinks]]` |
|
|
12
|
-
| `logseq` | `rg -l "{query}" {vault_path} --glob "*.md" \| head -5` | no-op | standard markdown links |
|
|
13
|
-
| `plain` | `rg -l "{query}" {vault_path} --glob "*.md" \| head -5` | no-op | standard markdown links |
|
|
14
|
-
| `custom` | `rg -l "{query}" {vault_path} --glob "*.md" \| head -5` | no-op | standard markdown links |
|
|
15
|
-
|
|
16
|
-
**Note:** The Obsidian CLI requires Obsidian to be running. If Obsidian is not running, vault search will fail.
|
|
8
|
+
Vault backend is Obsidian. Search: `obsidian search query="{query}" limit=5`
|
|
17
9
|
Scope searches with `path=` filter: `obsidian search query="{query}" path="01_Projects" limit=5`
|
|
18
10
|
|
|
19
|
-
|
|
11
|
+
**Note:** The Obsidian CLI requires Obsidian to be running. If Obsidian is not running, vault search will fail.
|
|
12
|
+
Use `[[wikilinks]]` for all internal vault references.
|
|
20
13
|
|
|
21
14
|
## Vault Location
|
|
22
15
|
Read vault_path from `~/.claude/praxis.config.json`.
|
|
@@ -51,7 +44,6 @@ Never ask "should I save this?" for the above categories — just save it.
|
|
|
51
44
|
|
|
52
45
|
### No manual index update needed
|
|
53
46
|
- Obsidian indexes vault changes in real-time — no update command required.
|
|
54
|
-
- For all other backends: files are read directly, no indexing needed.
|
|
55
47
|
|
|
56
48
|
---
|
|
57
49
|
|
|
@@ -83,9 +75,7 @@ source: agent | human | meeting
|
|
|
83
75
|
---
|
|
84
76
|
```
|
|
85
77
|
|
|
86
|
-
|
|
87
|
-
- `obsidian` → use `[[wikilinks]]` for all internal vault references
|
|
88
|
-
- `logseq`, `plain`, `custom` → use standard markdown links
|
|
78
|
+
Use `[[wikilinks]]` for all internal vault references.
|
|
89
79
|
|
|
90
80
|
### Bootstrap templates
|
|
91
81
|
If `status.md`, `tasks.md`, or `_index.md` are missing from a project vault directory,
|
|
@@ -140,10 +140,8 @@ Vault indexing is automatic.
|
|
|
140
140
|
|
|
141
141
|
## Phase 7 — Confirm & Open Vault
|
|
142
142
|
|
|
143
|
-
Open the vault in
|
|
144
|
-
- `
|
|
145
|
-
- `logseq` → `open "logseq://graph/{vault_name}"`
|
|
146
|
-
- `plain` / `custom` → print vault path for user to open manually
|
|
143
|
+
Open the vault in Obsidian:
|
|
144
|
+
- `open "obsidian://open?vault=Obsidian"`
|
|
147
145
|
|
|
148
146
|
Print summary table with all created files and bootstrap sequence.
|
|
149
147
|
|
package/bin/praxis.js
CHANGED
|
@@ -107,43 +107,7 @@ async function install() {
|
|
|
107
107
|
const readline = require('readline/promises');
|
|
108
108
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
console.log(' Choose a vault backend:');
|
|
112
|
-
console.log(' [1] Obsidian (default)');
|
|
113
|
-
console.log(' [2] Logseq');
|
|
114
|
-
console.log(' [3] Plain markdown (~/.praxis-vault)');
|
|
115
|
-
console.log(' [4] Custom path');
|
|
116
|
-
console.log('');
|
|
117
|
-
const backendChoice = await rl.question(' Choice [1]: ');
|
|
118
|
-
const choice = (backendChoice || '1').trim();
|
|
119
|
-
|
|
120
|
-
let vaultBackend = 'obsidian';
|
|
121
|
-
let vaultPath = '';
|
|
122
|
-
|
|
123
|
-
switch (choice) {
|
|
124
|
-
case '1':
|
|
125
|
-
vaultBackend = 'obsidian';
|
|
126
|
-
vaultPath = await rl.question(' Obsidian vault path: ');
|
|
127
|
-
break;
|
|
128
|
-
case '2':
|
|
129
|
-
vaultBackend = 'logseq';
|
|
130
|
-
vaultPath = await rl.question(' Logseq vault path: ');
|
|
131
|
-
break;
|
|
132
|
-
case '3':
|
|
133
|
-
vaultBackend = 'plain';
|
|
134
|
-
vaultPath = path.join(os.homedir(), '.praxis-vault');
|
|
135
|
-
fs.mkdirSync(vaultPath, { recursive: true });
|
|
136
|
-
ok('Created ' + vaultPath);
|
|
137
|
-
break;
|
|
138
|
-
case '4':
|
|
139
|
-
vaultBackend = 'custom';
|
|
140
|
-
vaultPath = await rl.question(' Vault path: ');
|
|
141
|
-
break;
|
|
142
|
-
default:
|
|
143
|
-
vaultBackend = 'obsidian';
|
|
144
|
-
vaultPath = await rl.question(' Vault path: ');
|
|
145
|
-
break;
|
|
146
|
-
}
|
|
110
|
+
let vaultPath = await rl.question(' Obsidian vault path: ');
|
|
147
111
|
rl.close();
|
|
148
112
|
|
|
149
113
|
if (vaultPath) {
|
|
@@ -153,7 +117,7 @@ async function install() {
|
|
|
153
117
|
const config = {
|
|
154
118
|
version: '1.1.0',
|
|
155
119
|
vault_path: vaultPath || '',
|
|
156
|
-
vault_backend:
|
|
120
|
+
vault_backend: 'obsidian',
|
|
157
121
|
repo_path: PKG_DIR
|
|
158
122
|
};
|
|
159
123
|
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + '\n');
|
|
@@ -162,22 +126,9 @@ async function install() {
|
|
|
162
126
|
dim('praxis.config.json already exists — skipping');
|
|
163
127
|
}
|
|
164
128
|
|
|
165
|
-
// Tool checks
|
|
129
|
+
// Tool checks
|
|
166
130
|
header('Tool check');
|
|
167
|
-
|
|
168
|
-
if (fs.existsSync(CONFIG_FILE)) {
|
|
169
|
-
try {
|
|
170
|
-
const cfg = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
|
|
171
|
-
vaultBackendForCheck = cfg.vault_backend || 'obsidian';
|
|
172
|
-
} catch {}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const baseTools = ['node', 'claude', 'jq'];
|
|
176
|
-
if (vaultBackendForCheck === 'obsidian') {
|
|
177
|
-
baseTools.push('obsidian');
|
|
178
|
-
} else {
|
|
179
|
-
baseTools.push('rg');
|
|
180
|
-
}
|
|
131
|
+
const baseTools = ['node', 'claude', 'jq', 'obsidian'];
|
|
181
132
|
for (const tool of baseTools) {
|
|
182
133
|
if (toolExists(tool)) {
|
|
183
134
|
ok(tool + ' available');
|
|
@@ -262,21 +213,9 @@ function health() {
|
|
|
262
213
|
} catch { total++; fail('praxis.config.json is invalid JSON'); }
|
|
263
214
|
}
|
|
264
215
|
|
|
265
|
-
// Tools
|
|
216
|
+
// Tools
|
|
266
217
|
console.log('\nTools:');
|
|
267
|
-
|
|
268
|
-
if (fs.existsSync(CONFIG_FILE)) {
|
|
269
|
-
try {
|
|
270
|
-
const cfg = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
|
|
271
|
-
healthBackend = cfg.vault_backend || 'obsidian';
|
|
272
|
-
} catch {}
|
|
273
|
-
}
|
|
274
|
-
const healthTools = ['node', 'claude', 'jq'];
|
|
275
|
-
if (healthBackend === 'obsidian') {
|
|
276
|
-
healthTools.push('obsidian');
|
|
277
|
-
} else {
|
|
278
|
-
healthTools.push('rg');
|
|
279
|
-
}
|
|
218
|
+
const healthTools = ['node', 'claude', 'jq', 'obsidian'];
|
|
280
219
|
for (const tool of healthTools) {
|
|
281
220
|
check(toolExists(tool), tool + ' available');
|
|
282
221
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@esoteric-logic/praxis-harness",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Layered Claude Code harness — workflow discipline, AI-Kits, persistent vault integration",
|
|
5
5
|
"bin": {
|
|
6
6
|
"praxis-harness": "./bin/praxis.js"
|
|
@@ -19,7 +19,14 @@
|
|
|
19
19
|
"type": "git",
|
|
20
20
|
"url": "https://github.com/arcanesme/praxis.git"
|
|
21
21
|
},
|
|
22
|
-
"keywords": [
|
|
22
|
+
"keywords": [
|
|
23
|
+
"claude-code",
|
|
24
|
+
"ai-harness",
|
|
25
|
+
"vault",
|
|
26
|
+
"obsidian",
|
|
27
|
+
"workflow",
|
|
28
|
+
"gsd"
|
|
29
|
+
],
|
|
23
30
|
"author": "arcanesme",
|
|
24
31
|
"license": "MIT",
|
|
25
32
|
"engines": {
|
package/scripts/health-check.sh
CHANGED
|
@@ -88,18 +88,10 @@ if [[ -f "$CONFIG_FILE" ]]; then
|
|
|
88
88
|
fi
|
|
89
89
|
fi
|
|
90
90
|
|
|
91
|
-
# ─── Required tools
|
|
91
|
+
# ─── Required tools ───
|
|
92
92
|
echo ""
|
|
93
93
|
echo "Tools:"
|
|
94
|
-
|
|
95
|
-
if [[ -f "$CONFIG_FILE" ]]; then
|
|
96
|
-
VAULT_BACKEND=$(jq -r '.vault_backend // "obsidian"' "$CONFIG_FILE" 2>/dev/null)
|
|
97
|
-
fi
|
|
98
|
-
if [[ "$VAULT_BACKEND" == "obsidian" ]]; then
|
|
99
|
-
check "command -v obsidian" "Obsidian CLI available"
|
|
100
|
-
else
|
|
101
|
-
check "command -v rg" "ripgrep available"
|
|
102
|
-
fi
|
|
94
|
+
check "command -v obsidian" "Obsidian CLI available"
|
|
103
95
|
check "command -v node" "node available"
|
|
104
96
|
check "command -v claude" "claude available"
|
|
105
97
|
check "command -v jq" "jq available"
|
|
@@ -109,7 +101,7 @@ echo ""
|
|
|
109
101
|
echo "MCP Servers:"
|
|
110
102
|
if command -v claude &>/dev/null; then
|
|
111
103
|
MCP_LIST=$(claude mcp list 2>/dev/null || true)
|
|
112
|
-
for server in context7
|
|
104
|
+
for server in context7 github; do
|
|
113
105
|
TOTAL=$((TOTAL + 1))
|
|
114
106
|
if echo "$MCP_LIST" | grep -q "$server"; then
|
|
115
107
|
echo " ✓ $server registered"
|
package/scripts/update.sh
CHANGED
|
@@ -57,18 +57,10 @@ for kit_dir in "$REPO_PATH"/kits/*/; do
|
|
|
57
57
|
fi
|
|
58
58
|
done
|
|
59
59
|
|
|
60
|
-
# ─── Verify key tools
|
|
60
|
+
# ─── Verify key tools ───
|
|
61
61
|
echo ""
|
|
62
62
|
echo "Verifying tools..."
|
|
63
|
-
|
|
64
|
-
if [[ -f "$CONFIG_FILE" ]]; then
|
|
65
|
-
VAULT_BACKEND=$(jq -r '.vault_backend // "obsidian"' "$CONFIG_FILE" 2>/dev/null)
|
|
66
|
-
fi
|
|
67
|
-
if [[ "$VAULT_BACKEND" == "obsidian" ]]; then
|
|
68
|
-
command -v obsidian &>/dev/null && echo " ✓ Obsidian CLI available" || echo " ✗ Obsidian CLI not found"
|
|
69
|
-
else
|
|
70
|
-
command -v rg &>/dev/null && echo " ✓ ripgrep available" || echo " ✗ ripgrep not found"
|
|
71
|
-
fi
|
|
63
|
+
command -v obsidian &>/dev/null && echo " ✓ Obsidian CLI available" || echo " ✗ Obsidian CLI not found"
|
|
72
64
|
command -v claude &>/dev/null && echo " ✓ claude available" || echo " ✗ claude not found"
|
|
73
65
|
command -v node &>/dev/null && echo " ✓ node available" || echo " ✗ node not found"
|
|
74
66
|
|