@hacksmith/doraval 0.2.11

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 ADDED
@@ -0,0 +1,236 @@
1
+ # doraval
2
+
3
+ The context engineering toolkit for coding agents.
4
+
5
+ Validate skills, plugins, hooks, MCP configs, and memory files across providers — locally or from a Git URL. Works with Claude Code today; Cursor, Codex, and Windsurf coming next.
6
+
7
+ > **Quick start:** [Install Bun](https://bun.sh), then run `bunx jsr @hacksmith/doraval validate .`
8
+ > Node/npm users: `npx jsr @hacksmith/doraval validate .` (Bun still required).
9
+
10
+ ## Features
11
+
12
+ - **Pluggable validators** — Auto-detect and validate skills, plugins, marketplaces, hooks, MCP config, subagents, commands, and memory files
13
+ - **Multi-provider** — Claude Code validators built in; Cursor, Codex, Windsurf planned
14
+ - **Remote validation** — Point at a GitHub URL instead of cloning first
15
+ - **Rubric drift detection** — Measure deviation across trigger phrases, voice, examples, guardrails, and clarity
16
+ - **AI-driven judging** — Qualitative skill assessment via LLM *(coming soon)*
17
+ - **CI-friendly** — JSON output and non-zero exit codes for pipeline integration
18
+
19
+ ## Installation
20
+
21
+ doraval is published on [JSR](https://jsr.io/@hacksmith/doraval) as **`@hacksmith/doraval`**.
22
+
23
+ It is **not** on the npm registry — `npx doraval` and `bunx doraval` will 404.
24
+
25
+ ### 1. Install Bun (required)
26
+
27
+ doraval is a **Bun CLI**. Having Node.js installed is not enough.
28
+
29
+ ```bash
30
+ curl -fsSL https://bun.sh/install | bash # macOS/Linux
31
+ # Windows: https://bun.sh/docs/installation
32
+ ```
33
+
34
+ Requires Bun **v1.2+**.
35
+
36
+ ### 2. Run doraval
37
+
38
+ **One-off (recommended)** — no global install:
39
+
40
+ ```bash
41
+ # Bun users
42
+ bunx jsr @hacksmith/doraval validate .
43
+
44
+ # Node/npm users (still requires Bun — doraval runs on Bun, not Node)
45
+ npx jsr @hacksmith/doraval validate .
46
+ ```
47
+
48
+ Both commands download from JSR and invoke the CLI. The `npx` form is fine if you already use npm; you do **not** need to publish to npm.
49
+
50
+ **Aliases:** subcommands are `validate`, `skill`, `journal`, etc. (there is no separate `dora` binary on your PATH unless you add one — see below).
51
+
52
+ ### `jsr add` is not a global CLI install
53
+
54
+ `npx jsr add @hacksmith/doraval` adds doraval as a **project dependency** in `package.json`. It does **not** put `dora` or `doraval` on your shell PATH. JSR’s npm compatibility layer also omits the `bin` field today, so `node_modules/.bin/doraval` is not created.
55
+
56
+ To **run** the CLI, use `npx jsr @hacksmith/doraval` (no `add`):
57
+
58
+ ```bash
59
+ npx jsr @hacksmith/doraval validate .
60
+ ```
61
+
62
+ **Optional — shorthand on your PATH** (from the project where you ran `jsr add`, or anywhere):
63
+
64
+ ```bash
65
+ # shell alias (add to ~/.zshrc)
66
+ alias dora='npx jsr @hacksmith/doraval'
67
+ alias doraval='npx jsr @hacksmith/doraval'
68
+
69
+ # or an npm script in package.json
70
+ # "doraval": "jsr @hacksmith/doraval"
71
+ ```
72
+
73
+ ### What does *not* work
74
+
75
+ | Command | Why |
76
+ |---------|-----|
77
+ | `npx doraval …` | Package is not on npmjs.org |
78
+ | `bunx doraval …` | Same — looks up npm, not JSR |
79
+ | `npx jsr add @hacksmith/doraval` then `dora` | `add` installs a library dep, not a global binary |
80
+ | `node …` / Deno only | CLI uses Bun APIs (`Bun.file`, etc.) |
81
+
82
+ > [!NOTE]
83
+ > **Node users:** use `npx jsr @hacksmith/doraval` to *fetch* the tool, but install **Bun** first to *run* it. There is no Node-native build today.
84
+
85
+ ## Usage
86
+
87
+ ### `validate` — Auto-detect and validate
88
+
89
+ The main command. Point it at a local directory or a Git URL, and it auto-detects what validators apply.
90
+
91
+ ```bash
92
+ dora validate . # local directory
93
+ dora validate https://github.com/obra/superpowers # remote repo
94
+ dora validate https://github.com/obra/superpowers/tree/main/skills/brainstorming # subdirectory
95
+ ```
96
+
97
+ Filter by provider or specific validator with `--for`:
98
+
99
+ ```bash
100
+ dora validate . --for claude # all Claude validators that match
101
+ dora validate . --for claude:plugin # just the plugin validator
102
+ ```
103
+
104
+ #### Available validators (Claude)
105
+
106
+ | Validator | Detects | What it checks |
107
+ |---|---|---|
108
+ | `claude:skill` | `SKILL.md` | Frontmatter (relaxed name/desc; recommended + directory-derived command), body, supporting files, dynamic injection, substitutions, advanced fields (allowed-tools, context, etc.) |
109
+ | `claude:plugin` | `.claude-plugin/plugin.json` | Manifest fields, component paths, skill/command/agent dirs |
110
+ | `claude:marketplace` | `plugins/` with plugin subdirs | Plugin directory structure, README, LICENSE |
111
+ | `claude:hooks` | `hooks/hooks.json` or `hooks.json` | Valid JSON, known event names |
112
+ | `claude:mcp` | `.mcp.json` | Valid JSON, server definitions |
113
+ | `claude:subagent` | `agents/*.md` | Frontmatter with description, non-empty body (stricter than skills) |
114
+ | `claude:command` | `commands/*.md` | Frontmatter with description, body; supports advanced fields (allowed-tools, context, when_to_use, etc.) |
115
+ | `claude:memory` | `CLAUDE.md` | Non-empty, length limit, @path import resolution |
116
+
117
+ #### Remote URLs
118
+
119
+ `dora validate` accepts GitHub URLs (and any Git URL). It clones the repo to a temp directory, validates, and cleans up. For GitHub repos, it tries `gh` first (handles private repos via your existing auth), then falls back to `git clone`.
120
+
121
+ Supported URL forms:
122
+
123
+ ```bash
124
+ dora validate https://github.com/owner/repo
125
+ dora validate https://github.com/owner/repo/tree/branch
126
+ dora validate https://github.com/owner/repo/tree/main/sub/dir
127
+ dora validate github.com/owner/repo # shorthand
128
+ ```
129
+
130
+ ### `skill validate` — Structural checks (single skill)
131
+
132
+ Validate a single skill directory. This is the original command and continues to work unchanged.
133
+
134
+ ```bash
135
+ dora skill validate ./skills/my-skill/
136
+ ```
137
+
138
+ ```
139
+ doraval skill validate — Structural validation
140
+
141
+ Path: ./skills/my-skill/
142
+
143
+ ✓ YAML frontmatter present and parseable
144
+ ✓ name: "my-skill"
145
+ ✓ description field present
146
+ ✓ Markdown body is non-empty
147
+ ✓ references/ directory exists
148
+ ✓ advanced frontmatter: allowed-tools, context
149
+ ✓ uses dynamic context injection (!`...` or ```! blocks)
150
+
151
+ Result: 0 error(s), 0 warning(s)
152
+ ```
153
+
154
+ > Note: `name` and `description` are recommended (not hard requirements). Missing them produces warnings rather than errors. The directory name usually provides the invocable `/command`.
155
+
156
+ ### `skill drift` — Rubric deviation
157
+
158
+ Measure how far a skill has drifted from known-good rubric standards. Each check maps to a drift category:
159
+
160
+ | Category | What it checks |
161
+ |---|---|
162
+ | **Trigger** | Description or `when_to_use` includes activation phrases (`Use when...`) |
163
+ | **Structure** | Body has numbered steps or checklists |
164
+ | **Voice** | Uses imperative language (`Create`, `Run`, `Ensure`) |
165
+ | **Example** | Contains code blocks |
166
+ | **Guardrail** | Has explicit `MUST` / `MUST NOT` constraints |
167
+ | **Clarity** | Free of ambiguous words (`maybe`, `perhaps`, `consider`) |
168
+
169
+ ```bash
170
+ dora skill drift ./skills/my-skill/
171
+ ```
172
+
173
+ ```
174
+ doraval skill drift — Measuring rubric drift
175
+
176
+ Path: ./skills/my-skill/
177
+
178
+ · Trigger Description includes activation phrases
179
+ · Structure Has step-by-step instructions
180
+ · Voice Uses imperative voice ("Do X" not "You might X")
181
+ ↗ Example No code blocks found — add examples if the skill involves code
182
+ ↗ Guardrail No explicit constraints — add MUST / MUST NOT guardrails
183
+ · Clarity No ambiguous language found
184
+
185
+ 2/6 rubric areas have drifted.
186
+ ```
187
+
188
+ ### `skill judge` — AI-driven assessment
189
+
190
+ > [!WARNING]
191
+ > Not yet implemented. This command will send the skill to an LLM for qualitative review of clarity, completeness, and effectiveness.
192
+
193
+ ```bash
194
+ dora skill judge ./skills/my-skill/
195
+ ```
196
+
197
+ ## Options
198
+
199
+ | Flag | Short | Description |
200
+ |---|---|---|
201
+ | `--format <type>` | `-f` | Output format: `table` (default) or `json` |
202
+ | `--for <spec>` | | Target a provider (`claude`) or specific validator (`claude:plugin`) |
203
+ | `--verbose` | `-v` | Show detailed diagnostics |
204
+ | `--ci` | | Machine-friendly output, non-zero exit on issues |
205
+
206
+ ### CI/CD integration
207
+
208
+ Use `--format json` and `--ci` for pipeline-friendly output:
209
+
210
+ ```bash
211
+ dora validate . --for claude --format json --ci
212
+ dora skill validate ./my-skill/ --format json --ci
213
+ dora skill drift ./my-skill/ --format json --ci
214
+ ```
215
+
216
+ `validate` exits with code `1` when errors are found. Commands write structured JSON to stdout when `--format json` is set — pipe it to `jq` or consume it programmatically.
217
+
218
+ ## `journal` — Decision memory with pushback
219
+
220
+ Record, view, and sync project principles and decisions so that future you (and agents) don't accidentally contradict past choices.
221
+
222
+ The journal lives in a private GitHub repo you control (by convention `yourname/yourname.md`). All config and cache lives under `~/.doraval/`.
223
+
224
+ ```bash
225
+ dora init # Recommended: set up journal + the coding agent dora will use on the fly for rich `add`
226
+ dora journal list # View active principles
227
+ dora journal update # Pull latest from the remote into local cache
228
+ dora journal add "..." # Propose a decision/note (or long rich markdown via --raw-markdown); staged locally; uses configured agent when input is minimal
229
+ dora journal sync # Publish pending entries + refresh cache
230
+ ```
231
+
232
+ `update` is the recommended way to keep your local mirror fresh (e.g. at the start of a session or before `skill drift`).
233
+
234
+ Requires the GitHub CLI (`gh`) for talking to the remote journal repo.
235
+
236
+ See the docs site for full details and rationale.
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+ import { execSync, spawnSync } from 'node:child_process'
3
+ import { fileURLToPath } from 'node:url'
4
+ import { join, dirname } from 'node:path'
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url))
7
+
8
+ try {
9
+ execSync('bun --version', { stdio: 'ignore' })
10
+ } catch {
11
+ console.error(
12
+ 'doraval requires the Bun runtime.\n\n' +
13
+ 'Install Bun (~10s):\n' +
14
+ ' curl -fsSL https://bun.sh/install | bash\n\n' +
15
+ 'Then run:\n' +
16
+ ' bunx doraval'
17
+ )
18
+ process.exit(1)
19
+ }
20
+
21
+ const cli = join(__dirname, 'doraval.js')
22
+
23
+ const result = spawnSync('bun', [cli, ...process.argv.slice(2)], { stdio: 'inherit' })
24
+ if (result.error) {
25
+ console.error('Failed to execute Bun:', result.error.message)
26
+ process.exit(1)
27
+ }
28
+ process.exit(result.status ?? (result.signal ? 128 : 1))