novahiz 0.3.5 → 0.3.7
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 +98 -64
- package/adapters/claude/agent/novahiz.md +23 -0
- package/adapters/opencode/instructions.md +3 -3
- package/adapters/opencode/novahiz.ts +24 -7
- package/catalog/categories.json +60 -1
- package/catalog/providers.json +2 -2
- package/dist/cli.js +9 -3
- package/dist/commands/doctor.js +492 -15
- package/dist/commands/hook.js +204 -0
- package/dist/commands/init.js +53 -2
- package/dist/gate-repair.js +5 -2
- package/dist/hook.js +176 -0
- package/dist/impeccable.js +17 -0
- package/dist/spec.js +39 -7
- package/docs/CONFIGURATION.md +2 -2
- package/docs/HARNESSES.md +25 -6
- package/docs/INSTALL.md +3 -3
- package/docs/PLUGIN.md +9 -1
- package/docs/PROVIDERS.md +1 -1
- package/docs/ROADMAPS.md +6 -4
- package/install/hooks.mjs +171 -0
- package/install/install.mjs +170 -26
- package/install/lib.mjs +7 -1
- package/install/prompt.mjs +30 -0
- package/install/uninstall.mjs +1 -0
- package/novahiz.config.example.json +1 -1
- package/package.json +3 -1
- package/skills/memory/SKILL.md +1 -1
- package/skills/novahiz-converge/SKILL.md +10 -0
- package/skills/novahiz-init/SKILL.md +6 -0
- package/skills/novahiz-memory/SKILL.md +1 -1
- package/skills/novahiz-release/SKILL.md +59 -0
- package/src/cli.ts +9 -3
- package/src/commands/doctor.ts +507 -15
- package/src/commands/hook.ts +238 -0
- package/src/commands/init.ts +56 -2
- package/src/gate-repair.ts +5 -2
- package/src/gate.ts +1 -1
- package/src/hook.ts +203 -0
- package/src/impeccable.ts +18 -0
- package/src/spec.ts +38 -7
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Novahiz: Agent Governance Toolkit
|
|
2
2
|
|
|
3
|
-
> **Zero-dependency enforcement layer for AI coding agents** — classifies prompts, assigns execution roadmaps, blocks unsafe edits
|
|
3
|
+
> **Zero-dependency enforcement layer for AI coding agents** — classifies prompts, assigns execution roadmaps, blocks unsafe edits until the right skills are loaded, and persists decisions across sessions — all deterministically, without model calls.
|
|
4
4
|
|
|
5
|
-
17 categories,
|
|
5
|
+
17 categories, 96 skills, 11 gate rules, 7 MCP providers — all deterministic, all local, all JSON.
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
@@ -18,41 +18,22 @@
|
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
-
##
|
|
21
|
+
## How a session runs
|
|
22
|
+
|
|
23
|
+
1. **Classify** — every prompt is scored against 17 categories (deterministic keyword matching, no model call). The result carries up to three categories, a primary one, a confidence, a **tier** (`trivial` / `lite` / `full`), and the skills the gate will expect.
|
|
24
|
+
2. **Roadmap** — the primary category selects an ordered roadmap, and the plugin injects its checklist into the session: the agent walks plan → clarify → tasks → analyse → implement → converge instead of improvising an order.
|
|
25
|
+
3. **Gate on every write** — `edit` / `write` / `patch` / `bash` / `shell` calls are checked against file class, active rules, roadmap skills and content (placeholder tokens): **allow** or **block**, locally, with no model call in the decision path.
|
|
26
|
+
4. **Auto-repair, not a dead end** — a block names the exact missing skills and the retry rule: load each one, retry the same call once. A skill absent from the installed index is reported, never enforced. `NOVAHIZ_GATE=off` is the only escape hatch, and it is loud.
|
|
27
|
+
5. **Verify and converge** — roadmaps end in `verify` steps that require proof; `novahiz-converge` grades the code against the original request and turns every remainder into a traceable ledger step.
|
|
28
|
+
6. **Persist** — decisions, root causes and next steps survive the session through the memory layer (below), and `novahiz report` closes the loop with a session summary.
|
|
22
29
|
|
|
23
30
|
```
|
|
24
|
-
|
|
25
|
-
│
|
|
26
|
-
|
|
27
|
-
│ ┌──────────┐ ┌────────────┐ ┌──────────┐ ┌──────────────┐ │
|
|
28
|
-
│ │ USER │───▶│ CLASSIFY │───▶│ INJECT │───▶│ MODEL │ │
|
|
29
|
-
│ │ PROMPT │ │ │ │ ENFORCE │ │ RESPONSE │ │
|
|
30
|
-
│ └──────────┘ │ keywords │ │ block + │ └──────┬───────┘ │
|
|
31
|
-
│ │ priority │ │ roadmap │ │ │
|
|
32
|
-
│ │ roadmap │ │ ledger │ ▼ │
|
|
33
|
-
│ └────────────┘ └──────────┘ ┌──────────────┐ │
|
|
34
|
-
│ │ │ TOOL CALL │ │
|
|
35
|
-
│ │ │ (edit/write) │ │
|
|
36
|
-
│ │ └──────┬───────┘ │
|
|
37
|
-
│ │ │ │
|
|
38
|
-
│ │ ┌────────────┐ │ │
|
|
39
|
-
│ └────────▶│ GATE │◀───────────┘ │
|
|
40
|
-
│ │ │ │
|
|
41
|
-
│ │ file path │ │
|
|
42
|
-
│ │ skills │ │
|
|
43
|
-
│ │ content │ │
|
|
44
|
-
│ └─────┬──────┘ │
|
|
45
|
-
│ │ │
|
|
46
|
-
│ ▼ │
|
|
47
|
-
│ ┌──────────┐ │
|
|
48
|
-
│ │ allow / │ │
|
|
49
|
-
│ │ BLOCK │ │
|
|
50
|
-
│ └──────────┘ │
|
|
51
|
-
│ │
|
|
52
|
-
└──────────────────────────────────────────────────────────────────────────┘
|
|
31
|
+
PROMPT ─▶ CLASSIFY ─▶ ROADMAP ─▶ work ─▶ GATE ─▶ allow ─▶ VERIFY ─▶ MEMORY
|
|
32
|
+
│ ▲ │
|
|
33
|
+
└─ tier, skills ────│ └─ block: load named skills, retry once
|
|
53
34
|
```
|
|
54
35
|
|
|
55
|
-
**17 categories**, **
|
|
36
|
+
**17 categories**, **96 skills**, **11 gate rules**, **7 MCP providers** — all deterministic, all local, all JSON.
|
|
56
37
|
|
|
57
38
|
---
|
|
58
39
|
|
|
@@ -61,14 +42,15 @@
|
|
|
61
42
|
### Option 1 — One-liner (recommended)
|
|
62
43
|
|
|
63
44
|
```bash
|
|
64
|
-
npm install -g
|
|
45
|
+
npm install -g novahiz
|
|
46
|
+
novahiz-install --yes
|
|
65
47
|
```
|
|
66
48
|
|
|
67
|
-
|
|
49
|
+
`npm install -g novahiz` installs the CLI. On npm 11+, lifecycle scripts are gated behind an allow-scripts confirmation, so configuration is an explicit second step: `novahiz-install` asks which harnesses to configure (opencode and Claude Code when their config is present, Codex too; `--yes` accepts the detected defaults, `--harness claude` forces a list) — skills, plugin/agent, hooks, MCP servers, config. Then verify:
|
|
68
50
|
|
|
69
51
|
```bash
|
|
70
|
-
|
|
71
|
-
|
|
52
|
+
novahiz doctor # health checks — 13 base, 17 with Claude Code, 19 with impeccable
|
|
53
|
+
novahiz classify "fix the auth bug"
|
|
72
54
|
```
|
|
73
55
|
|
|
74
56
|
### Option 2 — From source
|
|
@@ -76,14 +58,14 @@ npx Novahiz classify "fix the auth bug"
|
|
|
76
58
|
```bash
|
|
77
59
|
git clone https://github.com/novahiz/novahiz.git
|
|
78
60
|
cd novahiz
|
|
79
|
-
npm install
|
|
80
|
-
node ./install/install.mjs
|
|
61
|
+
npm install # `prepare` typechecks and builds dist/
|
|
62
|
+
node ./install/install.mjs # add --yes to accept the detected defaults
|
|
81
63
|
|
|
82
64
|
# Verify
|
|
83
|
-
|
|
65
|
+
node ./dist/cli.js doctor
|
|
84
66
|
```
|
|
85
67
|
|
|
86
|
-
> Requires **Node.js >= 22.18**. The installer auto-installs
|
|
68
|
+
> Requires **Node.js >= 22.18**. The installer auto-installs the CLI of each selected harness when it is entirely missing (`opencode-ai`, `@anthropic-ai/claude-code`, `@openai/codex`), non-blocking.
|
|
87
69
|
|
|
88
70
|
---
|
|
89
71
|
|
|
@@ -169,7 +151,13 @@ flowchart TD
|
|
|
169
151
|
| R13-design-craft | A design-ui prompt or a style file (css/scss/less/html) | novahiz-humanizer, ui-slop-remover, ui-craft-rules |
|
|
170
152
|
| R14-impeccable | A design-ui prompt or a style file (css/scss/less/html) | impeccable |
|
|
171
153
|
|
|
172
|
-
`novahiz-humanizer` and `ui-slop-remover` are required only on frontend design tasks (R13); `impeccable` loads the same way (R14) so critique, audit and polish playbooks stay reachable.
|
|
154
|
+
`novahiz-humanizer` and `ui-slop-remover` are required only on frontend design tasks (R13); `impeccable` loads the same way (R14) so the shape, critique, audit, harden and polish playbooks stay reachable, and the design-ui roadmap carries a deterministic `impeccable detect` verify step before ship. `novahiz init` and `novahiz doctor` report the impeccable `PRODUCT.md` / `DESIGN.md` context files as advisory rows.
|
|
155
|
+
|
|
156
|
+
### Auto-repair
|
|
157
|
+
|
|
158
|
+
A block is never a dead end. The refusal carries an AUTO-REPAIR recipe: load every skill it names with the skill loader, then retry the exact same call once — no alternate tool, no shell write, no editing around it. If the same skills are reported missing again, the load did not register: run `novahiz doctor`, report honestly, and stop. The only sanctioned bypass is `NOVAHIZ_GATE=off` (see Configuration), declared out loud.
|
|
159
|
+
|
|
160
|
+
A required skill missing from the installed index is never enforced silently: the gate appends `required skill not in index, not enforced — run novahiz sync to realign` to its reasons instead of blocking forever. An unreadable index makes the gate stricter, never laxer.
|
|
173
161
|
|
|
174
162
|
---
|
|
175
163
|
|
|
@@ -177,6 +165,21 @@ flowchart TD
|
|
|
177
165
|
|
|
178
166
|
Each category has an ordered execution roadmap. The gate enforces non-optional `skill` steps.
|
|
179
167
|
|
|
168
|
+
### The six-stage pipeline
|
|
169
|
+
|
|
170
|
+
Eight categories (`code`, `debug`, `browser`, `design-ui`, `database-supabase`, `planning`, `devops`, `data`) share one pipeline — and stages 1–4 write no application file, they produce a plan and decisions:
|
|
171
|
+
|
|
172
|
+
| # | Stage | Skill | Produces |
|
|
173
|
+
|---|-------|-------|----------|
|
|
174
|
+
| 1 | Plan | `novahiz-plan` | direction, scope, dependency order, slicing strategy, risks |
|
|
175
|
+
| 2 | Clarify | `novahiz-clarify` | the open questions, answered, and the decisions they freeze |
|
|
176
|
+
| 3 | Tasks | `novahiz-task` | atomic tasks, each with acceptance criteria and proof |
|
|
177
|
+
| 4 | Analyse | `novahiz-analyse` | the files and symbols that carry the logic, and the unknowns |
|
|
178
|
+
| 5 | Implement | `novahiz-implement` | increments that leave the system working |
|
|
179
|
+
| 6 | Converge | `novahiz-converge` | the gap between intent and code, as traceable remaining tasks |
|
|
180
|
+
|
|
181
|
+
Clarify sends the work back to plan when an answer changes the architecture; converge sends it back to tasks when it finds a gap. `flutter` and `expo` keep the same six stages and insert their own quality skills around implement. The classifier's **tier** filters the rest: `trivial` runs almost nothing, `lite` keeps implement and converge, `full` walks the whole roadmap. Full reference: [docs/ROADMAPS.md](docs/ROADMAPS.md).
|
|
182
|
+
|
|
180
183
|
```mermaid
|
|
181
184
|
flowchart LR
|
|
182
185
|
subgraph "Feature (code)"
|
|
@@ -240,9 +243,39 @@ flowchart TD
|
|
|
240
243
|
|
|
241
244
|
---
|
|
242
245
|
|
|
246
|
+
## Memory
|
|
247
|
+
|
|
248
|
+
Session memory is a two-layer system: a bounded, machine-readable workspace, and a human-readable notebook that is dual-written.
|
|
249
|
+
|
|
250
|
+
| Layer | Where | Behavior |
|
|
251
|
+
|-------|-------|----------|
|
|
252
|
+
| Session slots | `project-memory/` under the project root | `index.json` + fixed-size slots, compact → archive → rotate |
|
|
253
|
+
| Notebook | `MEMORY.md` + Obsidian vault page | dual-write at task end; the vault folder comes from `_meta/routing.md` |
|
|
254
|
+
|
|
255
|
+
### Session slots — `project-memory/`
|
|
256
|
+
|
|
257
|
+
- Lives under the project root: `index.json` plus `slots/`, and `novahiz init` seeds it with a baseline slot.
|
|
258
|
+
- Slots are fixed-size (**8000 chars / 200 lines**): a full slot is compacted, archived, and replaced — memory stays bounded no matter how long the project runs.
|
|
259
|
+
- MCP tools operate it: `memory_init`, `memory_list`, `memory_get`, `memory_write` (appends and rotates), `memory_rebuild` (reindexes from the markdown).
|
|
260
|
+
- This is where decisions, root causes and next steps go when a complex task ends.
|
|
261
|
+
- `novahiz doctor` checks both the memory root and the memory tools.
|
|
262
|
+
|
|
263
|
+
### Dual-write — `MEMORY.md` + vault
|
|
264
|
+
|
|
265
|
+
The `novahiz-memory` skill writes the closing state of a task in two places at once:
|
|
266
|
+
|
|
267
|
+
| Medium | Destination |
|
|
268
|
+
|--------|-------------|
|
|
269
|
+
| Project | `MEMORY.md` at the project root — what works now, what changed, what stays open |
|
|
270
|
+
| Vault | an Obsidian page — folder chosen **only** by the `_meta/routing.md` routing table |
|
|
271
|
+
|
|
272
|
+
Rules: mandatory frontmatter (title, category, tags, sources, created, updated, summary), `[[wikilinks]]` from the taxonomy, and enrich the existing page instead of creating a second one. Ambiguous routing → ask, never guess.
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
243
276
|
## Installed skills
|
|
244
277
|
|
|
245
|
-
Novahiz ships with
|
|
278
|
+
Novahiz ships with 96 skills across all categories:
|
|
246
279
|
|
|
247
280
|
| Category | Skills | Purpose |
|
|
248
281
|
|----------|--------|---------|
|
|
@@ -255,8 +288,9 @@ Novahiz ships with 95 skills across all categories:
|
|
|
255
288
|
| `browser` | novahiz-browser, browser-session, novahiz-web-extract, ... | Web automation, screenshots, extraction |
|
|
256
289
|
| `audit` | novahiz-security, package-risk-audit, llm-threat-review, ... | Security, compliance, vulnerability |
|
|
257
290
|
| `expo` | expo-overview, expo-router, expo-module, expo-dev-client, ... | Expo / React Native: routes, native modules, builds |
|
|
291
|
+
| `devops` | eas-workflows, eas-app-stores, novahiz-release, ... | CI/CD, deploys, versioned releases |
|
|
258
292
|
|
|
259
|
-
Run `npx
|
|
293
|
+
Run `npx novahiz skills --all` to see the full list.
|
|
260
294
|
|
|
261
295
|
---
|
|
262
296
|
|
|
@@ -274,7 +308,7 @@ Novahiz auto-registers external MCP servers based on the prompt category:
|
|
|
274
308
|
| cron | `scheduler-mcp` (local venv clone) | MIT | devops |
|
|
275
309
|
| dart | `dart mcp-server` (Dart SDK) | BSD-3-Clause | code, debug, design-ui, flutter |
|
|
276
310
|
|
|
277
|
-
Skill packs (installed from official repos, never vendored): `flutter/agent-plugins` (25 skills), `dart-lang/skills` (15 skills), `expo/skills` (
|
|
311
|
+
Skill packs (installed from official repos, never vendored): `flutter/agent-plugins` (25 skills), `dart-lang/skills` (15 skills), `expo/skills` (19 skills, the `expo-*` group only; `eas-*` paid services excluded), `pbakaus/impeccable` (1 skill, the upstream `impeccable` design skill). See [docs/PROVIDERS.md](docs/PROVIDERS.md).
|
|
278
312
|
|
|
279
313
|
Upstream repositories and full provenance for MCP providers and opencode plugins: [docs/PROVIDERS.md](docs/PROVIDERS.md), [docs/HARNESSES.md](docs/HARNESSES.md), [NOTICE.md](NOTICE.md).
|
|
280
314
|
|
|
@@ -287,10 +321,10 @@ Upstream repositories and full provenance for MCP providers and opencode plugins
|
|
|
287
321
|
NOVAHIZ_GATE=off npx opencode
|
|
288
322
|
|
|
289
323
|
# Override home directory
|
|
290
|
-
NOVAHIZ_HOME=/path/to/
|
|
324
|
+
NOVAHIZ_HOME=/path/to/novahiz npx novahiz doctor
|
|
291
325
|
|
|
292
326
|
# Force node version
|
|
293
|
-
NOVAHIZ_NODE=/usr/local/bin/node npx
|
|
327
|
+
NOVAHIZ_NODE=/usr/local/bin/node npx novahiz doctor
|
|
294
328
|
```
|
|
295
329
|
|
|
296
330
|
See [docs/CONFIGURATION.md](docs/CONFIGURATION.md) for all options.
|
|
@@ -301,23 +335,23 @@ See [docs/CONFIGURATION.md](docs/CONFIGURATION.md) for all options.
|
|
|
301
335
|
|
|
302
336
|
| Command | Purpose |
|
|
303
337
|
|---------|---------|
|
|
304
|
-
| `
|
|
305
|
-
| `
|
|
306
|
-
| `
|
|
307
|
-
| `
|
|
308
|
-
| `
|
|
309
|
-
| `
|
|
310
|
-
| `
|
|
311
|
-
| `
|
|
312
|
-
| `
|
|
313
|
-
| `
|
|
314
|
-
| `
|
|
315
|
-
| `
|
|
316
|
-
| `
|
|
317
|
-
| `
|
|
318
|
-
| `
|
|
319
|
-
| `
|
|
320
|
-
| `
|
|
338
|
+
| `novahiz init` | One-shot setup |
|
|
339
|
+
| `novahiz doctor` | 13-check health diagnostic (14 with `--deep`; 17 with Claude Code, 19 with impeccable) |
|
|
340
|
+
| `novahiz status` | Current classification + gate state |
|
|
341
|
+
| `novahiz classify <text>` | Classify a prompt |
|
|
342
|
+
| `novahiz gate` | Check if an edit is allowed |
|
|
343
|
+
| `novahiz task new <title>` | Start a tracked task |
|
|
344
|
+
| `novahiz task status` | Task progress |
|
|
345
|
+
| `novahiz task done <id>` | Mark a todo complete |
|
|
346
|
+
| `novahiz report` | Session report |
|
|
347
|
+
| `novahiz skills` | List loaded or available skills |
|
|
348
|
+
| `novahiz catalog <query>` | Search the skill catalog |
|
|
349
|
+
| `novahiz roadmap` | Show execution roadmap |
|
|
350
|
+
| `novahiz dispatch` | Generate work packets |
|
|
351
|
+
| `novahiz sync` | Rebuild installed-skills index |
|
|
352
|
+
| `novahiz clean` | Remove old logs |
|
|
353
|
+
| `novahiz upgrade` | Pull latest + rebuild |
|
|
354
|
+
| `novahiz version` | Print version |
|
|
321
355
|
|
|
322
356
|
See [docs/CLI.md](docs/CLI.md) for full reference.
|
|
323
357
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: novahiz
|
|
3
|
+
description: Novahiz deterministic workflow. Classifies the request, loads the required skills, then works under the Novahiz gate. Use for any multi-step task in a project that has a novahiz.config.json, or when the user asks for the Novahiz pipeline.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are Novahiz-Agent, running inside Claude Code with the Novahiz gate and MCP server active.
|
|
7
|
+
|
|
8
|
+
Work in this order for every request:
|
|
9
|
+
|
|
10
|
+
1. Classify. Call the `novahiz_classify` MCP tool with the user request, or run `node <novahiz-home>/src/cli.ts classify "<request>"`. Read the returned categories and the required skills.
|
|
11
|
+
2. Load skills. Call the `Skill` tool for every required skill before touching any file. That is the signal the Novahiz hook records; a skill loaded any other way does not count. If the `Skill` tool is unavailable, read `<novahiz-home>/skills/<name>/SKILL.md` instead, which the hook also accepts. The gate enforces this: edits, writes, and shell writes are blocked until the required skills are loaded.
|
|
12
|
+
3. Plan. For anything beyond a trivial change, write the plan before the code.
|
|
13
|
+
4. Execute. Prefer small reversible edits. Keep the architecture modular and maintainable.
|
|
14
|
+
5. Verify. Run the relevant tests or commands. Report what you ran and what it returned.
|
|
15
|
+
6. Report. State what changed, what is proven, what is uncertain, and the honest next step.
|
|
16
|
+
|
|
17
|
+
Rules:
|
|
18
|
+
|
|
19
|
+
- novahiz-humanizer, ui-slop-remover and ui-craft-rules are required only for frontend design tasks; impeccable covers the same design selectors.
|
|
20
|
+
- Load the Supabase skills for any Supabase work.
|
|
21
|
+
- Be honest. Avoid false good ideas. Zero simulation: never pretend to have run, tested, or verified something you did not.
|
|
22
|
+
- Criticize the request when it is inconsistent, ambiguous, risky, or suboptimal, and propose an alternative.
|
|
23
|
+
- If the gate blocks you, load every skill it names with the `Skill` tool, then retry the same call once. If the same skills are reported missing again, run `novahiz doctor`, report honestly, and stop. Never bypass the gate with a shell write or by editing around the block.
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
Obsidian (`C:\Users\hiz\Documents\Novahiz`) is the user's second memory.
|
|
6
6
|
|
|
7
7
|
### Rules
|
|
8
|
-
1. When the user asks to **save / memorize / update obsidian memory**, load the `memory
|
|
8
|
+
1. When the user asks to **save / memorize / update obsidian memory**, load the `memory` skill (alias for `novahiz-memory`) and follow its procedure without exception.
|
|
9
9
|
2. Determine the target folder **only** from the `Novahiz\_meta\routing.md` table (source of truth). Never guess. When ambiguous, ask the user.
|
|
10
10
|
3. Display the chosen path before writing.
|
|
11
|
-
4. Never write to `index.md`, `log.md`, `hot.md`, `.manifest.json`, `_meta/`, or `.obsidian
|
|
11
|
+
4. Never write to `index.md`, `log.md`, `hot.md`, `.manifest.json`, `_meta/`, or `.obsidian/`. No installed skill covers maintenance of those files: if the user asks for it, do it step by step in front of them, with a backup first for anything under `.obsidian/`. The `memory` skill writes only to the targeted content page.
|
|
12
12
|
5. Never create a root folder on your own. Every new category requires user agreement and an update to `routing.md`.
|
|
13
13
|
6. Include mandatory frontmatter: `title, category, tags, sources, created, updated, summary`. Use tags from `_meta/taxonomy.md`.
|
|
14
14
|
7. Link pages with `[[wikilinks]]`. Merge rather than duplicate.
|
|
@@ -29,7 +29,7 @@ Playwright uses a **persistent profile** that preserves data across sessions (co
|
|
|
29
29
|
## Behavioral & Quality Rules
|
|
30
30
|
|
|
31
31
|
1. **Mandatory design skills on frontend design tasks** — `novahiz-humanizer`, `ui-slop-remover` and `ui-craft-rules` are required only on frontend design work (design-ui prompts and style files). Load them with `skill({name})` before any design edit. Outside design, they are not required by the gate. Browser tasks (navigation, search, extraction) proceed as direct actions without a roadmap.
|
|
32
|
-
2. **Impeccable after UI work** — `impeccable` is installed and required on the same design selectors (gate rule R14). Whenever a page, component, section, or screen design is created or substantially changed, run its critique systematically afterwards, an audit when the change warrants it (a11y, performance, responsive), and a polish pass before shipping. The design-ui roadmap carries optional `impeccable-critique`, `impeccable-audit`,
|
|
32
|
+
2. **Impeccable after UI work** — `impeccable` is installed and required on the same design selectors (gate rule R14). Whenever a page, component, section, or screen design is created or substantially changed, run its critique systematically afterwards, an audit when the change warrants it (a11y, performance, responsive), harden errors and edge cases, and a polish pass before shipping; a deterministic `impeccable detect` scan backs the verify step. The design-ui roadmap carries optional `impeccable-shape`, `impeccable-critique`, `impeccable-audit`, `impeccable-harden`, `impeccable-polish`, and `impeccable-detect` steps for exactly this.
|
|
33
33
|
3. **Supabase** — On any Supabase task (database, auth, RLS, Edge Functions, migrations, Storage, Realtime, CLI/MCP), load the `novahiz-supabase` and `novahiz-postgres` skills before acting.
|
|
34
34
|
5. **Honesty and critical thinking** — Always be honest. Avoid false good ideas. Maintain critical thinking. **Zero simulation objective:** never claim to have executed, tested, or verified what was not. Explicitly report uncertainties and assumptions.
|
|
35
35
|
6. **Propose next steps** — After completing a task, always honestly propose the relevant next step. Do not invent unnecessary work or mask failures.
|
|
@@ -399,10 +399,14 @@ const DISABLED = ["off", "0", "false", "no", "disabled"].includes(ESCAPE);
|
|
|
399
399
|
const GATE_TOOLS = new Set(
|
|
400
400
|
(Array.isArray(GATE.tools) && GATE.tools.length > 0
|
|
401
401
|
? GATE.tools
|
|
402
|
-
// MINEUR#8
|
|
403
|
-
// cron_add_command_task was a bash-gate
|
|
404
|
-
//
|
|
405
|
-
|
|
402
|
+
// MINEUR#8 + 0.3.6 hardening: every cron tool that carries, creates, or
|
|
403
|
+
// executes shell commands is gated — cron_add_command_task was a bash-gate
|
|
404
|
+
// bypass, and cron_add_task / cron_add_ai_task / cron_add_http_task each
|
|
405
|
+
// accept a `command` field (HTTP/AI tasks run shell_command type too).
|
|
406
|
+
// Keep in sync with DEFAULT_CONFIG.gate.tools (src/spec.ts), install/lib.mjs,
|
|
407
|
+
// novahiz.config.example.json, the live novahiz.config.json, and
|
|
408
|
+
// docs/CONFIGURATION.md.
|
|
409
|
+
: ["edit", "write", "patch", "apply_patch", "bash", "shell", "cron_add_command_task", "cron_add_task", "cron_add_ai_task", "cron_add_http_task", "cron_update_command_task", "cron_update_task", "cron_run_task_now"]
|
|
406
410
|
).map((tool) => tool.toLowerCase())
|
|
407
411
|
);
|
|
408
412
|
|
|
@@ -496,12 +500,15 @@ function buildRepairDirective(failure: GateFailure, attempt: number): string {
|
|
|
496
500
|
}
|
|
497
501
|
|
|
498
502
|
if (attempt <= 1) {
|
|
499
|
-
|
|
503
|
+
// Always add novahiz-gate: it explains why the block happened and how to
|
|
504
|
+
// satisfy the rule, which is what the agent needs before retrying.
|
|
505
|
+
const loads = missing.includes("novahiz-gate") ? missing : [...missing, "novahiz-gate"];
|
|
506
|
+
const steps = loads.map((skill, index) => ` ${index + 1}. skill({name:"${skill}"})`).join("\n");
|
|
500
507
|
return [
|
|
501
508
|
`${head} Missing skills: ${missing.join(", ")}.`,
|
|
502
509
|
"AUTO-REPAIR — execute now, do not ask the user, do not stop:",
|
|
503
510
|
steps,
|
|
504
|
-
` ${
|
|
511
|
+
` ${loads.length + 1}. Retry this exact ${failure.tool} call once, then continue the user's task where it left off.`,
|
|
505
512
|
"Never bypass the gate: no NOVAHIZ_GATE, no alternate tool, no shell write, no editing around the block."
|
|
506
513
|
].join("\n");
|
|
507
514
|
}
|
|
@@ -727,7 +734,17 @@ export const NovahizPlugin: Plugin = async ({ client }) => {
|
|
|
727
734
|
const sessionID = input.sessionID;
|
|
728
735
|
if (!sessionID) return;
|
|
729
736
|
const block = enforcementBySession.get(sessionID);
|
|
730
|
-
if (block)
|
|
737
|
+
if (!block) return;
|
|
738
|
+
// The output array can still hold the block from a previous turn:
|
|
739
|
+
// pushing again duplicated "[Novahiz enforcement]" once per turn.
|
|
740
|
+
// Drop every stale copy, then inject exactly one fresh block.
|
|
741
|
+
for (let i = output.system.length - 1; i >= 0; i--) {
|
|
742
|
+
const entry = output.system[i];
|
|
743
|
+
if (typeof entry === "string" && entry.startsWith("[Novahiz enforcement]")) {
|
|
744
|
+
output.system.splice(i, 1);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
output.system.push(block);
|
|
731
748
|
} catch (error) {
|
|
732
749
|
await log("warn", `system.transform hook failed: ${String(error).slice(0, 200)}`);
|
|
733
750
|
}
|
package/catalog/categories.json
CHANGED
|
@@ -507,6 +507,14 @@
|
|
|
507
507
|
"id": "report",
|
|
508
508
|
"label": "Report findings",
|
|
509
509
|
"kind": "advisory"
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
"id": "audit",
|
|
513
|
+
"label": "Session compliance audit",
|
|
514
|
+
"kind": "advisory",
|
|
515
|
+
"requireSkills": [
|
|
516
|
+
"novahiz-audit"
|
|
517
|
+
]
|
|
510
518
|
}
|
|
511
519
|
]
|
|
512
520
|
}
|
|
@@ -791,6 +799,14 @@
|
|
|
791
799
|
"novahiz-task"
|
|
792
800
|
]
|
|
793
801
|
},
|
|
802
|
+
{
|
|
803
|
+
"id": "tokens",
|
|
804
|
+
"label": "Design tokens (when a token system is involved)",
|
|
805
|
+
"kind": "advisory",
|
|
806
|
+
"requireSkills": [
|
|
807
|
+
"design-token-pipeline"
|
|
808
|
+
]
|
|
809
|
+
},
|
|
794
810
|
{
|
|
795
811
|
"id": "design-craft",
|
|
796
812
|
"label": "Apply design craft, humanizer and anti-slop pass",
|
|
@@ -802,6 +818,15 @@
|
|
|
802
818
|
],
|
|
803
819
|
"optional": true
|
|
804
820
|
},
|
|
821
|
+
{
|
|
822
|
+
"id": "impeccable-shape",
|
|
823
|
+
"label": "Impeccable shape (UX/UI design brief before code)",
|
|
824
|
+
"kind": "skill",
|
|
825
|
+
"requireSkills": [
|
|
826
|
+
"impeccable"
|
|
827
|
+
],
|
|
828
|
+
"optional": true
|
|
829
|
+
},
|
|
805
830
|
{
|
|
806
831
|
"id": "implement",
|
|
807
832
|
"label": "Implement",
|
|
@@ -828,6 +853,15 @@
|
|
|
828
853
|
],
|
|
829
854
|
"optional": true
|
|
830
855
|
},
|
|
856
|
+
{
|
|
857
|
+
"id": "impeccable-harden",
|
|
858
|
+
"label": "Impeccable harden (errors, i18n, edge cases before polish)",
|
|
859
|
+
"kind": "skill",
|
|
860
|
+
"requireSkills": [
|
|
861
|
+
"impeccable"
|
|
862
|
+
],
|
|
863
|
+
"optional": true
|
|
864
|
+
},
|
|
831
865
|
{
|
|
832
866
|
"id": "impeccable-polish",
|
|
833
867
|
"label": "Impeccable polish (final pass before ship)",
|
|
@@ -837,6 +871,15 @@
|
|
|
837
871
|
],
|
|
838
872
|
"optional": true
|
|
839
873
|
},
|
|
874
|
+
{
|
|
875
|
+
"id": "impeccable-detect",
|
|
876
|
+
"label": "Impeccable detector scan (deterministic UI check, exit 0 = clean)",
|
|
877
|
+
"kind": "verify",
|
|
878
|
+
"requireSkills": [
|
|
879
|
+
"impeccable"
|
|
880
|
+
],
|
|
881
|
+
"optional": true
|
|
882
|
+
},
|
|
840
883
|
{
|
|
841
884
|
"id": "responsive",
|
|
842
885
|
"label": "Verify responsive behavior",
|
|
@@ -1106,7 +1149,15 @@
|
|
|
1106
1149
|
"nginx",
|
|
1107
1150
|
"infra",
|
|
1108
1151
|
"monitoring",
|
|
1109
|
-
"eas"
|
|
1152
|
+
"eas",
|
|
1153
|
+
"release",
|
|
1154
|
+
"cut a release",
|
|
1155
|
+
"publish",
|
|
1156
|
+
"npm publish",
|
|
1157
|
+
"version bump",
|
|
1158
|
+
"bump version",
|
|
1159
|
+
"tag a version",
|
|
1160
|
+
"changelog"
|
|
1110
1161
|
],
|
|
1111
1162
|
"defaultSkills": [
|
|
1112
1163
|
"eas-workflows",
|
|
@@ -1168,6 +1219,14 @@
|
|
|
1168
1219
|
"requireSkills": [
|
|
1169
1220
|
"novahiz-converge"
|
|
1170
1221
|
]
|
|
1222
|
+
},
|
|
1223
|
+
{
|
|
1224
|
+
"id": "release",
|
|
1225
|
+
"label": "Ship a release",
|
|
1226
|
+
"kind": "advisory",
|
|
1227
|
+
"requireSkills": [
|
|
1228
|
+
"novahiz-release"
|
|
1229
|
+
]
|
|
1171
1230
|
}
|
|
1172
1231
|
]
|
|
1173
1232
|
}
|
package/catalog/providers.json
CHANGED
|
@@ -90,11 +90,11 @@
|
|
|
90
90
|
"id": "expo-skills",
|
|
91
91
|
"label": "Expo agent skills",
|
|
92
92
|
"kind": "skill",
|
|
93
|
-
"install": ["npx", "-y", "skills@1.7.0", "add", "expo/skills", "--skill", "expo-overview", "expo-project-structure", "expo-router", "expo-animation", "expo-native-ui", "expo-design-system", "expo-ui", "expo-data-fetching", "expo-dom", "expo-web-to-native", "expo-module", "expo-brownfield", "expo-dev-client", "expo-examples", "expo-app-clip", "expo-upgrade", "expo-skill-feedback", "-g", "-a", "opencode", "-y"],
|
|
93
|
+
"install": ["npx", "-y", "skills@1.7.0", "add", "expo/skills", "--skill", "expo-overview", "expo-project-structure", "expo-router", "expo-animation", "expo-native-ui", "expo-design-system", "expo-ui", "expo-data-fetching", "expo-dom", "expo-web-to-native", "expo-module", "expo-migrate-module", "expo-brownfield", "expo-dev-client", "expo-examples", "expo-app-clip", "expo-upgrade", "expo-skill-eval", "expo-skill-feedback", "-g", "-a", "opencode", "-y"],
|
|
94
94
|
"source": "https://github.com/expo/skills",
|
|
95
95
|
"license": "MIT",
|
|
96
96
|
"categories": ["code", "expo"],
|
|
97
|
-
"purpose": "
|
|
97
|
+
"purpose": "19 official Expo framework skills (expo-* group); the 7 eas-* paid-service skills are excluded. Installed to ~/.agents/skills; when git clone fails, fetch the tarball from codeload.github.com and copy the skill folders."
|
|
98
98
|
},
|
|
99
99
|
{
|
|
100
100
|
"id": "impeccable",
|
package/dist/cli.js
CHANGED
|
@@ -6,6 +6,7 @@ import { parse, print, flagOn } from "./commands/context.js";
|
|
|
6
6
|
import { expandHome } from "./spec.js";
|
|
7
7
|
import { commandCheck, commandSync, commandClassify, commandSkills, commandCategories, commandRules, commandSessionLoad, commandSessionState, commandCatalog, commandRoadmap, commandStep, commandProviders, commandDeps, commandDispatch } from "./commands/inspect.js";
|
|
8
8
|
import { commandGate } from "./commands/gate.js";
|
|
9
|
+
import { commandHook } from "./commands/hook.js";
|
|
9
10
|
import { commandReport } from "./commands/report.js";
|
|
10
11
|
import { commandTask } from "./commands/task.js";
|
|
11
12
|
import { commandClean } from "./commands/clean.js";
|
|
@@ -39,7 +40,7 @@ function usage() {
|
|
|
39
40
|
"init Initialize Novahiz in the current project",
|
|
40
41
|
"setup Install Novahiz (config, skills, catalog)",
|
|
41
42
|
"autodocs [--flush] Sync docs and memory after major project changes",
|
|
42
|
-
"doctor
|
|
43
|
+
"doctor [--deep] Check that everything works (--deep also probes each MCP server live)",
|
|
43
44
|
"status Show current classification and gate state",
|
|
44
45
|
"task new <title> Start a new tracked task",
|
|
45
46
|
"task status Show task progress",
|
|
@@ -59,6 +60,7 @@ function usage() {
|
|
|
59
60
|
"Advanced (for power users and adapters):",
|
|
60
61
|
" classify <text> Classify a prompt",
|
|
61
62
|
" gate --tool <t> --file <f> Check if an edit is allowed",
|
|
63
|
+
" hook [--harness h] [--event e] Claude/Codex tool-use gate hook",
|
|
62
64
|
" skills [--category c] List loaded skills",
|
|
63
65
|
" catalog <query> Search the skill catalog",
|
|
64
66
|
" roadmap --category c Show execution roadmap",
|
|
@@ -130,7 +132,9 @@ function runUpgrade(parsed) {
|
|
|
130
132
|
runSync();
|
|
131
133
|
process.stdout.write("\nUpgraded! Restart opencode to apply changes.\n");
|
|
132
134
|
}
|
|
133
|
-
|
|
135
|
+
// Async so `doctor --deep` can await its MCP probes; every other command
|
|
136
|
+
// still returns void, which await handles transparently.
|
|
137
|
+
async function main(argv) {
|
|
134
138
|
const parsed = parse(argv);
|
|
135
139
|
if (typeof parsed.flags.home === "string" && parsed.flags.home.length > 0) {
|
|
136
140
|
process.env.NOVAHIZ_HOME = resolve(expandHome(parsed.flags.home));
|
|
@@ -175,6 +179,8 @@ function main(argv) {
|
|
|
175
179
|
return commandClassify(parsed);
|
|
176
180
|
case "gate":
|
|
177
181
|
return commandGate(parsed);
|
|
182
|
+
case "hook":
|
|
183
|
+
return commandHook(parsed);
|
|
178
184
|
case "skills":
|
|
179
185
|
return commandSkills(parsed);
|
|
180
186
|
case "categories":
|
|
@@ -209,7 +215,7 @@ function main(argv) {
|
|
|
209
215
|
}
|
|
210
216
|
}
|
|
211
217
|
try {
|
|
212
|
-
main(process.argv.slice(2));
|
|
218
|
+
await main(process.argv.slice(2));
|
|
213
219
|
}
|
|
214
220
|
catch (error) {
|
|
215
221
|
const message = error instanceof Error ? error.message : String(error);
|