qualia-framework 4.5.0 → 5.3.0
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/AGENTS.md +24 -0
- package/CLAUDE.md +12 -75
- package/README.md +23 -16
- package/agents/builder.md +9 -21
- package/agents/planner.md +8 -0
- package/agents/verifier.md +8 -0
- package/agents/visual-evaluator.md +132 -0
- package/bin/cli.js +54 -18
- package/bin/install.js +369 -29
- package/bin/qualia-ui.js +208 -1
- package/bin/slop-detect.mjs +5 -0
- package/bin/state.js +34 -1
- package/docs/install-redesign-builder-prompt.md +290 -0
- package/docs/install-redesign-pilot.md +234 -0
- package/docs/playwright-loop-builder-prompt.md +185 -0
- package/docs/playwright-loop-design-notes.md +108 -0
- package/docs/playwright-loop-pilot-results.md +170 -0
- package/docs/playwright-loop-tester-prompt.md +213 -0
- package/docs/polish-loop-supervised-run.md +111 -0
- package/docs/reviews/matt-pocock-skills-analysis.md +300 -0
- package/guide.md +9 -5
- package/hooks/env-empty-guard.js +74 -0
- package/hooks/pre-compact.js +19 -9
- package/hooks/pre-deploy-gate.js +8 -2
- package/hooks/pre-push.js +26 -12
- package/hooks/supabase-destructive-guard.js +62 -0
- package/hooks/vercel-account-guard.js +91 -0
- package/package.json +2 -1
- package/rules/design-brand.md +4 -0
- package/rules/design-laws.md +4 -0
- package/rules/design-product.md +4 -0
- package/rules/design-rubric.md +4 -0
- package/rules/grounding.md +4 -0
- package/skills/qualia-build/SKILL.md +40 -46
- package/skills/qualia-discuss/SKILL.md +51 -68
- package/skills/qualia-handoff/SKILL.md +1 -0
- package/skills/qualia-hook-gen/SKILL.md +206 -0
- package/skills/qualia-issues/SKILL.md +151 -0
- package/skills/qualia-map/SKILL.md +78 -35
- package/skills/qualia-new/REFERENCE.md +139 -0
- package/skills/qualia-new/SKILL.md +45 -121
- package/skills/qualia-optimize/REFERENCE.md +265 -0
- package/skills/qualia-optimize/SKILL.md +92 -232
- package/skills/qualia-plan/SKILL.md +58 -65
- package/skills/qualia-polish-loop/REFERENCE.md +265 -0
- package/skills/qualia-polish-loop/SKILL.md +201 -0
- package/skills/qualia-polish-loop/fixtures/broken.html +117 -0
- package/skills/qualia-polish-loop/fixtures/clean.html +196 -0
- package/skills/qualia-polish-loop/scripts/loop.mjs +323 -0
- package/skills/qualia-polish-loop/scripts/playwright-capture.mjs +206 -0
- package/skills/qualia-polish-loop/scripts/score.mjs +176 -0
- package/skills/qualia-prd/SKILL.md +199 -0
- package/skills/qualia-report/SKILL.md +141 -200
- package/skills/qualia-research/SKILL.md +28 -33
- package/skills/qualia-road/SKILL.md +103 -0
- package/skills/qualia-ship/SKILL.md +1 -0
- package/skills/qualia-task/SKILL.md +1 -1
- package/skills/qualia-test/SKILL.md +50 -2
- package/skills/qualia-triage/SKILL.md +152 -0
- package/skills/qualia-verify/SKILL.md +63 -104
- package/skills/qualia-zoom/SKILL.md +51 -0
- package/skills/zoho-workflow/SKILL.md +1 -1
- package/templates/CONTEXT.md +36 -0
- package/templates/decisions/ADR-template.md +30 -0
- package/tests/bin.test.sh +598 -7
- package/tests/state.test.sh +58 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
# Matt Pocock's Skills — Deep Analysis & Qualia 5.0 Proposal
|
|
2
|
+
|
|
3
|
+
**Source material**
|
|
4
|
+
- Repo: https://github.com/mattpocock/skills (46k stars, #1 on GitHub Trending the day it dropped)
|
|
5
|
+
- Course: https://www.aihero.dev/cohorts/claude-code-for-real-engineers-2026-04
|
|
6
|
+
- Talk: https://www.youtube.com/watch?v=kZ-zzHVUrO4
|
|
7
|
+
|
|
8
|
+
**Author of this analysis:** Synthesized 2026-05-03 from a full read of Matt's CLAUDE.md, CONTEXT.md, and every SKILL.md in `engineering/`, `productivity/`, and `misc/`.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Part 1 — Matt's worldview, distilled
|
|
13
|
+
|
|
14
|
+
Matt is teaching one thing: **the real bottleneck on AI-coding quality is not the model, it's the alignment between human, agent, code, and domain.** Every skill exists to fix one alignment failure.
|
|
15
|
+
|
|
16
|
+
### The four pillars (from his CLAUDE.md)
|
|
17
|
+
|
|
18
|
+
| Pillar | Source | What it fixes |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| **Alignment Before Coding** | Pragmatic Programmer — "no-one knows exactly what they want" | Misalignment is the #1 failure mode. Cure: relentless one-question grilling until every branch of the decision tree is resolved. |
|
|
21
|
+
| **Domain Language Matters** | DDD ubiquitous language | Shared vocabulary reduces tokens, improves agent navigation, prevents "what do you mean by user?" rework. |
|
|
22
|
+
| **Feedback Loops Drive Quality** | Pragmatic Programmer — "the rate of feedback is your speed limit" | Without a fast deterministic pass/fail signal, agents fly blind. Cure: build the loop FIRST, then debug. |
|
|
23
|
+
| **Design Discipline** | Ousterhout — "the best modules are deep" | Daily attention to architecture or entropy wins. Cure: deepening refactors framed in domain language. |
|
|
24
|
+
|
|
25
|
+
### The structural innovations
|
|
26
|
+
|
|
27
|
+
1. **CONTEXT.md as a domain glossary** — not a project README, not a spec. A glossary of terms with **`Avoid`** lists. The agent literally reads "use *milestone*, not *sprint*" and conforms. Reduces token waste from disambiguation rounds.
|
|
28
|
+
2. **ADRs (Architecture Decision Records)** in `docs/adr/` — created sparingly, only for hard-to-reverse, surprising-without-context decisions with real trade-offs. Becomes the load-bearing memory.
|
|
29
|
+
3. **Vertical slices everywhere** — both for issues (each issue = a complete path through schema → API → UI → tests) and for TDD (one test → one impl → repeat). Anti-horizontal as a **rule**.
|
|
30
|
+
4. **Skill descriptions are the API surface** — "the only thing your agent sees." Discriminative descriptions beat clever prose. <1024 chars. Third-person. Always include "Use when {context}".
|
|
31
|
+
5. **Skills under 100 lines** — overflow goes to `REFERENCE.md` / `EXAMPLES.md` / `scripts/` (progressive disclosure).
|
|
32
|
+
6. **`disable-model-invocation: true`** — some skills (e.g. `zoom-out`) are user-fired-only. Prevents auto-firing on weak signals.
|
|
33
|
+
7. **scripts/ co-located with skills** — for deterministic operations. "Trade tokens for reliability" — the script can't hallucinate.
|
|
34
|
+
|
|
35
|
+
### The 21 skills, mapped
|
|
36
|
+
|
|
37
|
+
| Bucket | Skill | One-liner | Maps to (Qualia equivalent) |
|
|
38
|
+
|---|---|---|---|
|
|
39
|
+
| eng | **diagnose** | Build feedback loop FIRST, then reproduce → hypothesize → instrument → fix → regression-test | `qualia-debug` (weaker — doesn't enforce loop-first) |
|
|
40
|
+
| eng | **grill-with-docs** | Interview the user, update CONTEXT.md/ADRs inline as decisions crystallize | `qualia-discuss` (much weaker — no glossary update) |
|
|
41
|
+
| eng | **improve-codebase-architecture** | Find shallow modules, propose deepening refactors, use domain language | `qualia-optimize` (broader but lacks Ousterhout language) |
|
|
42
|
+
| eng | **tdd** | Vertical-slice tracer-bullet loop. ANTI horizontal slicing (writing all tests then all code) | `qualia-test` (lacks the methodology rule) |
|
|
43
|
+
| eng | **to-prd** | Conversation → PRD → GH Issue with `needs-triage` label | `qualia-new` (stays internal; never touches GH issues) |
|
|
44
|
+
| eng | **to-issues** | PRD → independent vertical-slice GH Issues, dependency-ordered | **NO EQUIVALENT** |
|
|
45
|
+
| eng | **triage** | State machine: needs-triage / needs-info / ready-for-agent / ready-for-human / wontfix | **NO EQUIVALENT** (we use tracking.json status fields, not GH labels) |
|
|
46
|
+
| eng | **zoom-out** | "Map this area using the project glossary" — 5-line skill, user-only | **NO EQUIVALENT** |
|
|
47
|
+
| eng | **setup-matt-pocock-skills** | Detect repo state, write `docs/agents/{tracker,labels,domain}.md`, append to CLAUDE.md | `qualia-map` (broader, but doesn't externalize agent config) |
|
|
48
|
+
| prod | **caveman** | 75% token reduction via dropped articles/fillers, fragment sentences, abbreviations, arrows | **NO EQUIVALENT** |
|
|
49
|
+
| prod | **grill-me** | Aggressive one-question-at-a-time interview until decision tree resolves | partial overlap with `qualia-discuss` |
|
|
50
|
+
| prod | **write-a-skill** | Meta-skill for authoring skills — frontmatter rules, file split rules | `qualia-skill-new` (similar) |
|
|
51
|
+
| misc | **git-guardrails** | Block dangerous git commands | partial — we have hooks |
|
|
52
|
+
| misc | **migrate-to-shoehorn** | Codemod-y tool | n/a |
|
|
53
|
+
| misc | **scaffold-exercises** | Course-specific | n/a |
|
|
54
|
+
| misc | **setup-pre-commit** | Husky setup | n/a |
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Part 2 — Where Qualia is already strong
|
|
59
|
+
|
|
60
|
+
We should NOT abandon what's working:
|
|
61
|
+
|
|
62
|
+
1. **Phase/wave/task hierarchy** — Matt has nothing equivalent to `JOURNEY.md → ROADMAP.md → phase plans → tasks with verification contracts`. This is a Qualia advantage.
|
|
63
|
+
2. **Fresh-context subagent spawning** — task-level context isolation prevents rot. Matt mentions subagents conceptually; we do it systematically.
|
|
64
|
+
3. **The verifier loop with goal-backward checks** — `qualia-verify` is sharper than anything Matt ships.
|
|
65
|
+
4. **Design substrate (v4.5.0)** — DESIGN.md + design-laws.md + slop-detect + 8-dimension scoring. Matt has nothing on visual design.
|
|
66
|
+
5. **Smart router (`qualia` skill)** — state-driven next-action recommendation. Matt's flow is more linear.
|
|
67
|
+
6. **The 4 mandatory Handoff deliverables** — client-delivery rigor that doesn't exist in Matt's repo (he targets engineers building in their own repos, not agencies shipping to clients).
|
|
68
|
+
|
|
69
|
+
The combination of Matt's alignment discipline + Qualia's execution machinery is the play.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Part 3 — Qualia 5.0 proposal: 15 changes ranked by ROI
|
|
74
|
+
|
|
75
|
+
### Tier 1 — Adopt these immediately (high ROI, low effort)
|
|
76
|
+
|
|
77
|
+
#### 1. **CONTEXT.md substrate (domain glossary)** — `.planning/CONTEXT.md`
|
|
78
|
+
|
|
79
|
+
The single biggest miss. Every Qualia agent currently re-derives domain terms from PROJECT.md prose. Matt's pattern: a structured glossary with `Avoid` lists.
|
|
80
|
+
|
|
81
|
+
**Format:**
|
|
82
|
+
```markdown
|
|
83
|
+
## Language
|
|
84
|
+
|
|
85
|
+
### Milestone
|
|
86
|
+
A bounded slice of the journey. Always one of: Foundation, MVP, Polish, Handoff.
|
|
87
|
+
**Avoid:** sprint, iteration, release.
|
|
88
|
+
|
|
89
|
+
### Phase
|
|
90
|
+
A unit of work inside a milestone, 2–5 tasks, ends in a verification gate.
|
|
91
|
+
**Avoid:** epic, story, ticket.
|
|
92
|
+
|
|
93
|
+
### Task
|
|
94
|
+
A single commit-sized unit with one verification contract.
|
|
95
|
+
**Avoid:** subtask, chore.
|
|
96
|
+
|
|
97
|
+
## Relationships
|
|
98
|
+
- Project holds many Milestones
|
|
99
|
+
- Milestone holds many Phases
|
|
100
|
+
- Phase holds many Tasks
|
|
101
|
+
- Task carries one Verification Contract
|
|
102
|
+
|
|
103
|
+
## Flagged ambiguities
|
|
104
|
+
- "User" was previously used for both `auth.users` row and customer profile. Now: **AuthUser** (auth row), **Customer** (profile).
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
- Generated by `/qualia-new` from the discovery questioning
|
|
108
|
+
- Loaded **first** by every subagent (before PROJECT.md, before DESIGN.md)
|
|
109
|
+
- Updated inline by `/qualia-discuss` and the new `/qualia-grill`
|
|
110
|
+
- **Expected impact:** ~30% reduction in disambiguation back-and-forth, fewer wrong-assumption rework cycles
|
|
111
|
+
|
|
112
|
+
#### 2. **ADR pattern** — `.planning/decisions/ADR-{N}-{slug}.md`
|
|
113
|
+
|
|
114
|
+
Replace the ad-hoc `phase-{N}-context.md` with structured ADRs. Created **sparingly**: only when the decision is hard-to-reverse, surprising-without-context, AND involves real trade-offs.
|
|
115
|
+
|
|
116
|
+
**Format:**
|
|
117
|
+
```markdown
|
|
118
|
+
# ADR-007 — Use Supabase RLS instead of API-layer auth checks
|
|
119
|
+
Date: 2026-05-03
|
|
120
|
+
Phase: 2
|
|
121
|
+
Status: Accepted
|
|
122
|
+
|
|
123
|
+
## Context
|
|
124
|
+
{why this decision is being made now}
|
|
125
|
+
|
|
126
|
+
## Decision
|
|
127
|
+
{what we are doing}
|
|
128
|
+
|
|
129
|
+
## Consequences
|
|
130
|
+
{what becomes easier; what becomes harder}
|
|
131
|
+
|
|
132
|
+
## Alternatives considered
|
|
133
|
+
{what we rejected and why}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
- Loaded by relevant phases via `@.planning/decisions/ADR-007-*.md`
|
|
137
|
+
- Listed in CONTEXT.md "Flagged ambiguities" when they resolve a term
|
|
138
|
+
|
|
139
|
+
#### 3. **`/qualia-zoom`** — 5-line user-only skill
|
|
140
|
+
|
|
141
|
+
```yaml
|
|
142
|
+
---
|
|
143
|
+
name: qualia-zoom
|
|
144
|
+
description: Zoom out and map the surrounding modules using project glossary terms. Use when you don't know an area of code well or need to orient before editing.
|
|
145
|
+
disable-model-invocation: true
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
I don't know this area well. Go up a layer of abstraction. Give me a map of all relevant modules and callers using the vocabulary in `.planning/CONTEXT.md`.
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Tiny. Used 50× a day in mature projects. Replaces ad-hoc "explain this code" requests with a glossary-anchored response.
|
|
152
|
+
|
|
153
|
+
#### 4. **Caveman mode for subagent spawning** (cost reduction)
|
|
154
|
+
|
|
155
|
+
Add to the prompt-cache template in `rules/grounding.md`:
|
|
156
|
+
|
|
157
|
+
> **Subagent compression**: All in-flight spawned-subagent system prompts use compressed form — drop articles, fillers, pleasantries. Use abbreviations (DB, auth, fn, impl, req, res). Fragment sentences over full clauses. Arrow notation for causality. Suspend compression for security warnings, irreversible action confirmations, and multi-step sequences where brevity risks misinterpretation.
|
|
158
|
+
|
|
159
|
+
The verifier and builder spawn 50+ times per project. ~25% token reduction per spawn. Real money at scale.
|
|
160
|
+
|
|
161
|
+
#### 5. **Tighten skill descriptions** (the API surface)
|
|
162
|
+
|
|
163
|
+
Audit all 74 skills. Each description must:
|
|
164
|
+
- Be ≤ 1024 chars
|
|
165
|
+
- Be in third person
|
|
166
|
+
- Include "Use when {specific context}" with **discriminative** triggers
|
|
167
|
+
- Have **zero overlap** with sibling skills
|
|
168
|
+
|
|
169
|
+
Currently `/qualia`, `/qualia-idk`, `/qualia-resume` all overlap on "lost? what next?" triggers. Wrong-skill-firing happens. Fix it.
|
|
170
|
+
|
|
171
|
+
### Tier 2 — Adopt these next (high ROI, medium effort)
|
|
172
|
+
|
|
173
|
+
#### 6. **`/qualia-grill`** — replace or augment `/qualia-discuss`
|
|
174
|
+
|
|
175
|
+
Aggressive one-question-at-a-time grilling. Walks every branch of the decision tree. Updates CONTEXT.md inline.
|
|
176
|
+
|
|
177
|
+
**Critical rule from Matt's grill-me:** *"For each question, provide your recommended answer."* — the agent isn't just asking, it's proposing. The user accepts, edits, or rejects. Way faster than open-ended interview.
|
|
178
|
+
|
|
179
|
+
Used **before** `/qualia-plan` for high-stakes phases (auth, payments, multi-tenant, anything with regulatory weight).
|
|
180
|
+
|
|
181
|
+
#### 7. **Restructure `/qualia-debug` around feedback-loop-first**
|
|
182
|
+
|
|
183
|
+
Current `qualia-debug` jumps to symptom analysis. Matt's diagnose enforces **build the loop first, then everything else is mechanical**. New phase structure:
|
|
184
|
+
|
|
185
|
+
1. Build a fast deterministic agent-runnable pass/fail signal (failing test > curl > CLI invocation > headless browser > trace replay > minimal harness > property test > bisection > differential > human-in-loop bash). Pick the highest-tier feasible.
|
|
186
|
+
2. Reproduce against the loop
|
|
187
|
+
3. Generate 3–5 ranked falsifiable hypotheses BEFORE testing
|
|
188
|
+
4. Instrument with `[DEBUG-{tag}]` prefixes (cleanup later)
|
|
189
|
+
5. Change one variable at a time
|
|
190
|
+
6. Fix at the correct seam, write regression test there
|
|
191
|
+
7. Cleanup `[DEBUG-*]` markers, verify scenario, document architectural finding answering "what would have prevented this?"
|
|
192
|
+
|
|
193
|
+
#### 8. **`/qualia-deepen`** — split out from `/qualia-optimize`
|
|
194
|
+
|
|
195
|
+
`/qualia-optimize` is currently a kitchen sink (perf + UI + backend + alignment). Pull out architecture-deepening as its own skill that uses Ousterhout's vocabulary explicitly: **depth, locality, leverage, seam, deletion test**.
|
|
196
|
+
|
|
197
|
+
Process:
|
|
198
|
+
1. Read `.planning/CONTEXT.md` glossary first
|
|
199
|
+
2. Walk codebase noting friction points: shallow modules where interface ≈ implementation, modules requiring bouncing across many files for one concept, pure functions extracted only for testability (no locality), tightly-coupled cross-seam leakage
|
|
200
|
+
3. Present candidates with **Files / Problem / Solution / Benefits**
|
|
201
|
+
4. Grilling loop: walk the design tree with the user, update CONTEXT.md/ADRs as decisions crystallize
|
|
202
|
+
|
|
203
|
+
#### 9. **`/qualia-tdd`** — vertical-slice rule enforcement
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
WRONG (horizontal): RED test1-5 → GREEN impl1-5
|
|
207
|
+
RIGHT (vertical): RED→GREEN test1→impl1, test2→impl2, ...
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
One test at a time. Only enough code to pass. Tests describe **behavior through public interface**, never implementation. Never refactor while red.
|
|
211
|
+
|
|
212
|
+
This is the #1 missing engineering discipline in the framework. We have `/qualia-test` (generate tests) but no test-first methodology.
|
|
213
|
+
|
|
214
|
+
#### 10. **Skill file structure cleanup** (progressive disclosure)
|
|
215
|
+
|
|
216
|
+
Audit pass: every SKILL.md must be **<100 lines**. Overflow goes to:
|
|
217
|
+
- `REFERENCE.md` (advanced/rare features)
|
|
218
|
+
- `EXAMPLES.md` (worked examples)
|
|
219
|
+
- `scripts/` (deterministic operations co-located with the skill)
|
|
220
|
+
|
|
221
|
+
Move `bin/state.js` and `bin/qualia-ui.js` from `~/.claude/bin/` into `skills/qualia/scripts/` (or symlink). The script being co-located with the skill means it's discoverable when reading the skill.
|
|
222
|
+
|
|
223
|
+
### Tier 3 — Strategic bets (very high ROI, larger effort)
|
|
224
|
+
|
|
225
|
+
#### 11. **`/qualia-issues`** — externalize work to GitHub
|
|
226
|
+
|
|
227
|
+
Convert the current phase plan into independent vertical-slice GH issues. Each issue:
|
|
228
|
+
- Title describing the slice
|
|
229
|
+
- End-to-end behavior description
|
|
230
|
+
- Acceptance criteria checklist
|
|
231
|
+
- Blocking-dependencies field
|
|
232
|
+
- Label: `needs-triage`
|
|
233
|
+
|
|
234
|
+
This **unlocks the autonomous loop**: other agents (or other Claude sessions, or Codex, or human contributors) can pull issues from the queue. Currently Qualia only runs in the originating session.
|
|
235
|
+
|
|
236
|
+
#### 12. **`/qualia-triage`** — state machine over the issue queue
|
|
237
|
+
|
|
238
|
+
Pulls open issues. Applies labels: `needs-triage` / `needs-info` / `ready-for-agent` / `ready-for-human` / `wontfix`. Routes:
|
|
239
|
+
- `ready-for-agent` → autonomous `/qualia-build` or `/qualia-quick`
|
|
240
|
+
- `ready-for-human` → notification to Fawzi
|
|
241
|
+
- `needs-info` → questions back to reporter
|
|
242
|
+
|
|
243
|
+
Combined with `/qualia-issues`, this is the **Ralph Wiggum loop** Matt teaches: agent pulls from backlog, builds, verifies, ships, picks next. Human-in-loop is optional, not required.
|
|
244
|
+
|
|
245
|
+
#### 13. **AGENTS.md emission** alongside CLAUDE.md
|
|
246
|
+
|
|
247
|
+
`/qualia-new` should write **both** `CLAUDE.md` (Anthropic) and `AGENTS.md` (the cross-vendor open standard now adopted by Codex, Cursor, Continue, Devin, Aider, etc.). Same content, different file. One project, multi-agent compatible. Costs nothing, expands the ecosystem.
|
|
248
|
+
|
|
249
|
+
#### 14. **`/qualia-onboard`** — adapt-to-existing-repo skill
|
|
250
|
+
|
|
251
|
+
Matt's `setup-matt-pocock-skills` is the model. Companion to `/qualia-map`. Detects:
|
|
252
|
+
- Existing issue tracker (GH, GL, Jira, local `.scratch/`)
|
|
253
|
+
- Existing labels — maps them to canonical roles
|
|
254
|
+
- Existing CONTEXT.md / docs/adr / glossary structure
|
|
255
|
+
|
|
256
|
+
Writes `.planning/agents/{tracker.md, labels.md, domain.md}` and appends an `## Agent skills` block to existing CLAUDE.md/AGENTS.md. **Adapts Qualia to the repo's conventions** instead of forcing Qualia conventions on the repo.
|
|
257
|
+
|
|
258
|
+
This is what makes the framework usable on brownfield client projects without ripping their existing process out.
|
|
259
|
+
|
|
260
|
+
#### 15. **`disable-model-invocation` flag adoption**
|
|
261
|
+
|
|
262
|
+
Add to skills that should never auto-fire on a weak trigger: `qualia-zoom`, `qualia-caveman`, anything destructive (`qualia-ship`, `qualia-handoff` arguably). Reduces accidental invocations.
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Part 4 — Sequencing recommendation
|
|
267
|
+
|
|
268
|
+
### Wave 1 (immediate, ~1 day)
|
|
269
|
+
- 1, 2, 3, 4, 5 (CONTEXT.md, ADRs, qualia-zoom, caveman mode, description audit)
|
|
270
|
+
|
|
271
|
+
### Wave 2 (short, ~3 days)
|
|
272
|
+
- 6, 7, 8, 9, 10 (qualia-grill, debug restructure, qualia-deepen, qualia-tdd, file structure cleanup)
|
|
273
|
+
|
|
274
|
+
### Wave 3 (strategic, ~1 week)
|
|
275
|
+
- 11, 12 (qualia-issues, qualia-triage) — these together unlock autonomous operation
|
|
276
|
+
|
|
277
|
+
### Wave 4 (polish, ~2 days)
|
|
278
|
+
- 13, 14, 15 (AGENTS.md, qualia-onboard, disable-model-invocation)
|
|
279
|
+
|
|
280
|
+
### Ship as v5.0
|
|
281
|
+
- New release: "Qualia 5.0 — alignment discipline" — leans into Matt's framing
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## Part 5 — What we should NOT copy
|
|
286
|
+
|
|
287
|
+
- **Matt's flat skill list (no router)**. Our `/qualia` smart router and state machine are better for non-trivial projects.
|
|
288
|
+
- **Matt's lack of design discipline**. Our v4.5.0 design substrate is genuinely ahead. Don't dilute it.
|
|
289
|
+
- **Matt's per-project `.scratch/` dir as default tracker**. We need real GH issues for client work and ERP integration.
|
|
290
|
+
- **Matt's "scaffold-exercises"** etc. — course-specific, not relevant.
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Part 6 — The honest assessment
|
|
295
|
+
|
|
296
|
+
Matt is teaching **alignment as the primary engineering discipline**. The framework currently treats alignment as a one-shot at `/qualia-new` and assumes it holds for the rest of the project. It doesn't. Decisions drift. Terms overload. Hypotheses go untested. Feedback loops degrade.
|
|
297
|
+
|
|
298
|
+
The 15 changes above are not features — they're **rituals** that keep alignment from rotting between phases. That's the x20 unlock. Not more skills. Better-disciplined skills, anchored to a domain glossary, with feedback loops built first.
|
|
299
|
+
|
|
300
|
+
The single highest-ROI change is **#1 (CONTEXT.md)**. If you do nothing else from this list, do that one. Every other change compounds off it.
|
package/guide.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Qualia Developer Guide (
|
|
1
|
+
# Qualia Developer Guide (v5)
|
|
2
2
|
|
|
3
3
|
> Follow the road. Type the commands. The framework handles the rest.
|
|
4
|
-
>
|
|
4
|
+
> `--auto` chains the whole road end-to-end with only two human checkpoints per project.
|
|
5
5
|
|
|
6
6
|
## The Road
|
|
7
7
|
|
|
@@ -24,7 +24,7 @@ For each phase of the current milestone:
|
|
|
24
24
|
Done.
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
## Auto Mode
|
|
27
|
+
## Auto Mode
|
|
28
28
|
|
|
29
29
|
Append `--auto` to `/qualia-new` and the framework chains every step:
|
|
30
30
|
|
|
@@ -58,10 +58,14 @@ Append `--auto` to `/qualia-new` and the framework chains every step:
|
|
|
58
58
|
| | `/qualia-ship` | Deploy to production |
|
|
59
59
|
| | `/qualia-handoff` | Deliver to client (4 mandatory deliverables) |
|
|
60
60
|
| Reporting | `/qualia-report` | Log what you did (mandatory before clock-out) |
|
|
61
|
+
| Zooming in | `/qualia-zoom` | Focus on a single file or function with full context |
|
|
62
|
+
| Issues | `/qualia-issues` | Scan codebase for issues, tech debt, and improvement opportunities |
|
|
63
|
+
| Triage | `/qualia-triage` | Prioritize and categorize a backlog of issues |
|
|
64
|
+
| Road view | `/qualia-road` | View and navigate journey/milestone/phase status |
|
|
61
65
|
| Lost? | `/qualia` | Mechanical next-command router |
|
|
62
66
|
| Confused? | `/qualia-idk` | Diagnostic — scans planning + code, explains what's going on |
|
|
63
67
|
|
|
64
|
-
## Full Journey Hierarchy
|
|
68
|
+
## Full Journey Hierarchy
|
|
65
69
|
|
|
66
70
|
```
|
|
67
71
|
Project
|
|
@@ -109,7 +113,7 @@ If neither helps, paste the error and ask Claude directly. If Claude can't fix i
|
|
|
109
113
|
- **Story-file plans:** Every task has Why / Acceptance Criteria / Depends on / Validation inline — the plan IS the brief.
|
|
110
114
|
- **Wave execution:** Independent tasks run in parallel. Dependent tasks wait.
|
|
111
115
|
- **Milestone-boundary pauses:** In `--auto` mode, the framework pauses only at real decision points. Everything else runs on rails.
|
|
112
|
-
- **tracking.json:** Updated on every push. The ERP reads it automatically.
|
|
116
|
+
- **tracking.json:** Updated on every push. The ERP reads it automatically. Includes `milestone_name` + `milestones[]` so the ERP renders a proper tree instead of a flat list.
|
|
113
117
|
|
|
114
118
|
## Quick Reference
|
|
115
119
|
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// hooks/env-empty-guard.js — block empty env var values on Vercel.
|
|
3
|
+
// PreToolUse hook on `Bash`. Blocks `vercel env add NAME ""` (empty value).
|
|
4
|
+
// Exits 2 to BLOCK, 0 to allow. Escape: QUALIA_ALLOW_EMPTY_ENV=1.
|
|
5
|
+
|
|
6
|
+
const fs = require("fs");
|
|
7
|
+
const path = require("path");
|
|
8
|
+
const os = require("os");
|
|
9
|
+
|
|
10
|
+
const _traceStart = Date.now();
|
|
11
|
+
|
|
12
|
+
function _trace(result, extra) {
|
|
13
|
+
try {
|
|
14
|
+
const traceDir = path.join(os.homedir(), ".claude", ".qualia-traces");
|
|
15
|
+
if (!fs.existsSync(traceDir)) fs.mkdirSync(traceDir, { recursive: true });
|
|
16
|
+
const entry = {
|
|
17
|
+
hook: "env-empty-guard", result,
|
|
18
|
+
timestamp: new Date().toISOString(),
|
|
19
|
+
duration_ms: Date.now() - _traceStart, ...extra,
|
|
20
|
+
};
|
|
21
|
+
const file = path.join(traceDir, `${new Date().toISOString().split("T")[0]}.jsonl`);
|
|
22
|
+
fs.appendFileSync(file, JSON.stringify(entry) + "\n");
|
|
23
|
+
} catch {}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Read hook payload from stdin.
|
|
27
|
+
let payload = "";
|
|
28
|
+
try { if (!process.stdin.isTTY) payload = fs.readFileSync(0, "utf8"); } catch {}
|
|
29
|
+
|
|
30
|
+
let command = "";
|
|
31
|
+
try {
|
|
32
|
+
if (payload) command = (JSON.parse(payload).tool_input || {}).command || "";
|
|
33
|
+
} catch {
|
|
34
|
+
console.error("BLOCKED: env-empty-guard could not parse hook payload.");
|
|
35
|
+
_trace("block", { reason: "parse-error" });
|
|
36
|
+
process.exit(2);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Only act on vercel env commands.
|
|
40
|
+
if (!/\bvercel\s+env\s+(add|pull)\b/.test(command)) {
|
|
41
|
+
_trace("allow", { reason: "no-match" });
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// vercel env pull is always fine.
|
|
46
|
+
if (/\bvercel\s+env\s+pull\b/.test(command)) {
|
|
47
|
+
_trace("allow", { reason: "env-pull" });
|
|
48
|
+
process.exit(0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Detect empty value patterns in vercel env add.
|
|
52
|
+
const emptyPatterns = [
|
|
53
|
+
/\bvercel\s+env\s+add\s+\S+\s+(""|'')\s*$/, // vercel env add KEY "" / ''
|
|
54
|
+
/\bvercel\s+env\s+add\s+\S+=\s*$/, // vercel env add KEY=
|
|
55
|
+
/\bvercel\s+env\b.*\s+""\s*/, // "" anywhere after vercel env
|
|
56
|
+
/\bvercel\s+env\b.*\s+''\s*/, // '' anywhere after vercel env
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
if (emptyPatterns.some((re) => re.test(command))) {
|
|
60
|
+
if (process.env.QUALIA_ALLOW_EMPTY_ENV === "1") {
|
|
61
|
+
process.stderr.write("Warning: Empty env var allowed by QUALIA_ALLOW_EMPTY_ENV=1\n");
|
|
62
|
+
_trace("bypassed", { command_preview: command.slice(0, 80) });
|
|
63
|
+
process.exit(0);
|
|
64
|
+
}
|
|
65
|
+
process.stderr.write(
|
|
66
|
+
`BLOCKED: empty env var value detected in: \`${command}\`. ` +
|
|
67
|
+
"Confirm the value is intentional, then re-run with QUALIA_ALLOW_EMPTY_ENV=1 to bypass.\n"
|
|
68
|
+
);
|
|
69
|
+
_trace("block", { command_preview: command.slice(0, 80) });
|
|
70
|
+
process.exit(2);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
_trace("allow", { command_preview: command.slice(0, 80) });
|
|
74
|
+
process.exit(0);
|
package/hooks/pre-compact.js
CHANGED
|
@@ -26,6 +26,8 @@ const { spawnSync } = require("child_process");
|
|
|
26
26
|
const _traceStart = Date.now();
|
|
27
27
|
|
|
28
28
|
const STATE_FILE = path.join(".planning", "STATE.md");
|
|
29
|
+
const TRACKING_FILE = path.join(".planning", "tracking.json");
|
|
30
|
+
const PLANNING_FILES = [STATE_FILE, TRACKING_FILE];
|
|
29
31
|
const CONFIG_FILE = path.join(os.homedir(), ".claude", ".qualia-config.json");
|
|
30
32
|
|
|
31
33
|
function readCompactConfig() {
|
|
@@ -46,12 +48,18 @@ function git(args, opts = {}) {
|
|
|
46
48
|
});
|
|
47
49
|
}
|
|
48
50
|
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
function planningHasPendingChanges() {
|
|
52
|
+
// v5.0: also stage tracking.json. The CLAUDE.md compaction contract says to
|
|
53
|
+
// preserve tracking.json across compactions, but pre-v5 only committed
|
|
54
|
+
// STATE.md — tracking.json mutations from state.js transitions were lost
|
|
55
|
+
// across compactions, leaving the ERP with stale milestone/phase/tasks data.
|
|
56
|
+
const diff = git(["diff", "--name-only", "--", ...PLANNING_FILES]);
|
|
57
|
+
const diffLines = (diff.stdout || "").split(/\r?\n/);
|
|
58
|
+
if (PLANNING_FILES.some((f) => diffLines.includes(f))) return true;
|
|
52
59
|
|
|
53
|
-
const untracked = git(["ls-files", "--others", "--exclude-standard", "--",
|
|
54
|
-
|
|
60
|
+
const untracked = git(["ls-files", "--others", "--exclude-standard", "--", ...PLANNING_FILES]);
|
|
61
|
+
const untrackedLines = (untracked.stdout || "").split(/\r?\n/);
|
|
62
|
+
return PLANNING_FILES.some((f) => untrackedLines.includes(f));
|
|
55
63
|
}
|
|
56
64
|
|
|
57
65
|
let _commitStatus = null;
|
|
@@ -62,15 +70,17 @@ try {
|
|
|
62
70
|
if (fs.existsSync(STATE_FILE)) {
|
|
63
71
|
console.log("QUALIA: Saving state before compaction...");
|
|
64
72
|
_commitReason = "state-clean";
|
|
65
|
-
// Check if STATE.md has tracked or untracked changes.
|
|
66
|
-
if (
|
|
67
|
-
|
|
73
|
+
// Check if STATE.md or tracking.json has tracked or untracked changes.
|
|
74
|
+
if (planningHasPendingChanges()) {
|
|
75
|
+
// Stage both planning files. `git add` silently no-ops on files that don't exist
|
|
76
|
+
// or have no changes, so passing both is safe even when only one is dirty.
|
|
77
|
+
const addRes = git(["add", ...PLANNING_FILES]);
|
|
68
78
|
const cfg = readCompactConfig();
|
|
69
79
|
const commitArgs = ["commit"];
|
|
70
80
|
if (!cfg.respect_user_hooks) commitArgs.push("--no-verify");
|
|
71
81
|
if (!cfg.respect_gpg_signing) commitArgs.push("--no-gpg-sign");
|
|
72
82
|
commitArgs.push("--author=Qualia Framework <bot@qualia.solutions>");
|
|
73
|
-
commitArgs.push("-m", "state: pre-compaction save");
|
|
83
|
+
commitArgs.push("-m", "state: pre-compaction save (STATE.md + tracking.json)");
|
|
74
84
|
_commitFlags = {
|
|
75
85
|
no_verify: !cfg.respect_user_hooks,
|
|
76
86
|
no_gpg_sign: !cfg.respect_gpg_signing,
|
package/hooks/pre-deploy-gate.js
CHANGED
|
@@ -170,9 +170,15 @@ if (fs.existsSync("tsconfig.json")) {
|
|
|
170
170
|
runGate("TypeScript", "npx", ["tsc", "--noEmit"]);
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
// Lint
|
|
173
|
+
// Lint (with QUALIA_SKIP_LINT=1 escape — for the documented "lint blocks
|
|
174
|
+
// ship" friction when the lint failures are pre-existing or auto-fixer-broken)
|
|
174
175
|
if (hasScript("lint")) {
|
|
175
|
-
|
|
176
|
+
if (process.env.QUALIA_SKIP_LINT === "1") {
|
|
177
|
+
console.log(" ⚠ Lint skipped (QUALIA_SKIP_LINT=1)");
|
|
178
|
+
_trace("pre-deploy-gate", "skip-lint", { reason: "QUALIA_SKIP_LINT=1" });
|
|
179
|
+
} else {
|
|
180
|
+
runGate("Lint", "npm", ["run", "lint"]);
|
|
181
|
+
}
|
|
176
182
|
}
|
|
177
183
|
|
|
178
184
|
// Tests
|
package/hooks/pre-push.js
CHANGED
|
@@ -103,12 +103,21 @@ function commitStamp() {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
function shouldBlock(result) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
106
|
+
// v5.0: tracking.json sync failures are now WARN not BLOCK. Rationale:
|
|
107
|
+
// tracking.json is ERP metadata, not load-bearing for the push itself. A
|
|
108
|
+
// corrupt tracking.json should NEVER prevent a production hotfix. The
|
|
109
|
+
// self-service fix is `git checkout HEAD -- .planning/tracking.json` and
|
|
110
|
+
// gets surfaced in the warning message below.
|
|
111
|
+
// To restore old fail-closed behavior set QUALIA_BLOCK_ON_TRACKING_FAIL=1.
|
|
112
|
+
if (process.env.QUALIA_BLOCK_ON_TRACKING_FAIL === "1") {
|
|
113
|
+
const hardSkips = new Set([
|
|
114
|
+
"tracking-unreadable",
|
|
115
|
+
"git-add-failed",
|
|
116
|
+
"git-commit-failed",
|
|
117
|
+
]);
|
|
118
|
+
return result && hardSkips.has(result.skipped);
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
112
121
|
}
|
|
113
122
|
|
|
114
123
|
function _trace(result, extra) {
|
|
@@ -131,19 +140,24 @@ try {
|
|
|
131
140
|
const result = commitStamp();
|
|
132
141
|
if (shouldBlock(result)) {
|
|
133
142
|
const detail = result.error ? ` ${String(result.error).slice(0, 500)}` : "";
|
|
134
|
-
const msg = `BLOCKED: tracking.json sync failed (${result.skipped}). Fix before pushing.${detail}`;
|
|
143
|
+
const msg = `BLOCKED: tracking.json sync failed (${result.skipped}). Fix before pushing.${detail}\nSelf-service fix: git checkout HEAD -- .planning/tracking.json`;
|
|
135
144
|
console.error(msg);
|
|
136
145
|
console.log(msg);
|
|
137
146
|
_trace("block", result);
|
|
138
147
|
process.exit(2);
|
|
139
148
|
}
|
|
149
|
+
// v5.0: warn-not-block on tracking.json failures. The push proceeds; the user
|
|
150
|
+
// sees a clear message and a self-service fix path. Production hotfixes are
|
|
151
|
+
// never blocked by ERP-metadata corruption.
|
|
152
|
+
if (result && (result.skipped === "tracking-unreadable" || result.skipped === "git-add-failed" || result.skipped === "git-commit-failed")) {
|
|
153
|
+
const detail = result.error ? ` (${String(result.error).slice(0, 200)})` : "";
|
|
154
|
+
console.error(`⚠ tracking.json sync failed: ${result.skipped}${detail}. Push proceeding. Self-service fix: git checkout HEAD -- .planning/tracking.json`);
|
|
155
|
+
}
|
|
140
156
|
_trace("allow", result);
|
|
141
157
|
} catch (err) {
|
|
142
|
-
|
|
143
|
-
console.error(
|
|
144
|
-
|
|
145
|
-
_trace("block", { error: err.message });
|
|
146
|
-
process.exit(2);
|
|
158
|
+
// Exception during commit stamping — warn, don't block (same v5.0 rationale).
|
|
159
|
+
console.error(`⚠ tracking.json sync threw: ${err.message}. Push proceeding. Self-service fix: git checkout HEAD -- .planning/tracking.json`);
|
|
160
|
+
_trace("warn", { error: err.message });
|
|
147
161
|
}
|
|
148
162
|
|
|
149
163
|
process.exit(0);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// hooks/supabase-destructive-guard.js — block destructive Supabase CLI commands.
|
|
3
|
+
// PreToolUse hook on `Bash`. Exits 2 to BLOCK, 0 to allow.
|
|
4
|
+
//
|
|
5
|
+
// Blocked: supabase db reset, supabase db push --force, supabase migration repair.
|
|
6
|
+
// Escape: QUALIA_ALLOW_DESTRUCTIVE=1 (shared with git-guardrails.js).
|
|
7
|
+
// Why: DB wipes left orphan rows requiring full re-wipe (insights friction).
|
|
8
|
+
|
|
9
|
+
const fs = require("fs");
|
|
10
|
+
const path = require("path");
|
|
11
|
+
const os = require("os");
|
|
12
|
+
|
|
13
|
+
const _traceStart = Date.now();
|
|
14
|
+
function _trace(result, extra) {
|
|
15
|
+
try {
|
|
16
|
+
const traceDir = path.join(os.homedir(), ".claude", ".qualia-traces");
|
|
17
|
+
if (!fs.existsSync(traceDir)) fs.mkdirSync(traceDir, { recursive: true });
|
|
18
|
+
const entry = {
|
|
19
|
+
hook: "supabase-destructive-guard", result,
|
|
20
|
+
timestamp: new Date().toISOString(),
|
|
21
|
+
duration_ms: Date.now() - _traceStart, ...extra,
|
|
22
|
+
};
|
|
23
|
+
const file = path.join(traceDir, `${new Date().toISOString().split("T")[0]}.jsonl`);
|
|
24
|
+
fs.appendFileSync(file, JSON.stringify(entry) + "\n");
|
|
25
|
+
} catch {}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const DESTRUCTIVE = [
|
|
29
|
+
/\b(npx\s+)?supabase\s+db\s+reset\b/,
|
|
30
|
+
/\b(npx\s+)?supabase\s+db\s+push\s+.*--force\b/,
|
|
31
|
+
/\b(npx\s+)?supabase\s+migration\s+repair\b/,
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
// Read hook payload from stdin.
|
|
35
|
+
let payload = "";
|
|
36
|
+
try { if (!process.stdin.isTTY) payload = fs.readFileSync(0, "utf8"); } catch {}
|
|
37
|
+
let command = "";
|
|
38
|
+
try { if (payload) command = (JSON.parse(payload).tool_input || {}).command || ""; } catch {}
|
|
39
|
+
|
|
40
|
+
if (!command) { _trace("allow", { reason: "no-command" }); process.exit(0); }
|
|
41
|
+
|
|
42
|
+
const matched = DESTRUCTIVE.find((re) => re.test(command));
|
|
43
|
+
if (!matched) { _trace("allow", {}); process.exit(0); }
|
|
44
|
+
|
|
45
|
+
const preview = command.slice(0, 80);
|
|
46
|
+
|
|
47
|
+
if (process.env.QUALIA_ALLOW_DESTRUCTIVE === "1") {
|
|
48
|
+
console.error("Warning: Destructive Supabase command allowed by QUALIA_ALLOW_DESTRUCTIVE=1");
|
|
49
|
+
_trace("bypassed", { pattern_matched: matched.source, command_preview: preview });
|
|
50
|
+
process.exit(0);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const msg = [
|
|
54
|
+
`BLOCKED: destructive Supabase command: \`${preview}\`.`,
|
|
55
|
+
"This will destroy production data.",
|
|
56
|
+
"Run with QUALIA_ALLOW_DESTRUCTIVE=1 if intentional,",
|
|
57
|
+
"OR use safer alternatives: `supabase db diff` to preview,",
|
|
58
|
+
"`supabase migration new` to add reversible changes.",
|
|
59
|
+
].join(" ");
|
|
60
|
+
console.error(msg);
|
|
61
|
+
_trace("block", { pattern_matched: matched.source, command_preview: preview });
|
|
62
|
+
process.exit(2);
|