qualia-framework 4.0.3 → 4.1.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/README.md +10 -8
- package/agents/builder.md +12 -2
- package/agents/plan-checker.md +26 -4
- package/agents/planner.md +33 -4
- package/agents/qa-browser.md +5 -1
- package/agents/research-synthesizer.md +2 -0
- package/agents/researcher.md +4 -0
- package/agents/roadmapper.md +11 -5
- package/agents/verifier.md +22 -3
- package/bin/cli.js +121 -4
- package/bin/install.js +13 -2
- package/bin/state.js +52 -2
- package/bin/statusline.js +78 -41
- package/docs/erp-contract.md +37 -2
- package/docs/research/2026-04-21-command-quality-deep-research.md +128 -0
- package/docs/research/2026-04-21-industry-best-practices.md +255 -0
- package/package.json +1 -1
- package/rules/grounding.md +110 -0
- package/skills/qualia-build/SKILL.md +20 -9
- package/skills/qualia-debug/SKILL.md +141 -49
- package/skills/qualia-design/SKILL.md +52 -5
- package/skills/qualia-new/SKILL.md +18 -3
- package/skills/qualia-plan/SKILL.md +11 -8
- package/skills/qualia-report/SKILL.md +141 -60
- package/skills/qualia-review/SKILL.md +36 -16
- package/skills/qualia-skill-new/SKILL.md +1 -1
- package/skills/qualia-verify/SKILL.md +5 -1
- package/templates/tracking.json +1 -0
- package/tests/runner.js +98 -0
package/bin/statusline.js
CHANGED
|
@@ -153,7 +153,21 @@ try {
|
|
|
153
153
|
} catch {}
|
|
154
154
|
} catch {}
|
|
155
155
|
|
|
156
|
+
// ─── Pill-style badge helper ─────────────────────────────
|
|
157
|
+
// Renders text as an inline pill with a solid background color, similar to
|
|
158
|
+
// Claude Code's native worktree tag. Pads with a leading+trailing space so
|
|
159
|
+
// the background band has visual weight.
|
|
160
|
+
function pill(text, rgb) {
|
|
161
|
+
const [r, g, b] = rgb;
|
|
162
|
+
const bg = `\x1b[48;2;${r};${g};${b}m`;
|
|
163
|
+
const fg = `\x1b[38;2;240;250;255m`;
|
|
164
|
+
const bold = `\x1b[1m`;
|
|
165
|
+
return `${bg}${fg}${bold} ${text} ${RESET}`;
|
|
166
|
+
}
|
|
167
|
+
|
|
156
168
|
// ─── Phase info from .planning/tracking.json ─────────────
|
|
169
|
+
// Rendered as a pill at the start of line 1 — teal for normal, red when blockers > 0.
|
|
170
|
+
// Every segment is optional — missing data is skipped, never rendered as a placeholder.
|
|
157
171
|
let PHASE_INFO = "";
|
|
158
172
|
try {
|
|
159
173
|
const trackingPath = path.join(DIR, ".planning", "tracking.json");
|
|
@@ -162,16 +176,53 @@ try {
|
|
|
162
176
|
const phase = Number(tracking.phase || 0) || 0;
|
|
163
177
|
const total = Number(tracking.total_phases || 0) || 0;
|
|
164
178
|
const status = String(tracking.status || "");
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
179
|
+
const milestone = Number(tracking.milestone || 0) || 0;
|
|
180
|
+
const milestoneName = String(tracking.milestone_name || "");
|
|
181
|
+
const tasksDone = Number(tracking.tasks_done || 0) || 0;
|
|
182
|
+
const tasksTotal = Number(tracking.tasks_total || 0) || 0;
|
|
183
|
+
const blockers = Array.isArray(tracking.blockers) ? tracking.blockers.length : 0;
|
|
184
|
+
|
|
185
|
+
const parts = [];
|
|
186
|
+
|
|
187
|
+
if (milestone > 0) {
|
|
188
|
+
let mStr = `M${milestone}`;
|
|
189
|
+
if (milestoneName) {
|
|
190
|
+
const shortName = milestoneName.length > 14 ? milestoneName.slice(0, 13) + "…" : milestoneName;
|
|
191
|
+
mStr += `·${shortName}`;
|
|
192
|
+
}
|
|
193
|
+
parts.push(mStr);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (total > 0) parts.push(`P${phase}/${total}`);
|
|
197
|
+
if (tasksTotal > 0) parts.push(`T${tasksDone}/${tasksTotal}`);
|
|
198
|
+
if (status) parts.push(status);
|
|
199
|
+
|
|
200
|
+
let badgeText = parts.join(" · ");
|
|
201
|
+
if (blockers > 0) badgeText += badgeText ? ` · !${blockers}` : `!${blockers}`;
|
|
202
|
+
|
|
203
|
+
if (badgeText) {
|
|
204
|
+
// Red pill when blockers present, teal otherwise
|
|
205
|
+
const bg = blockers > 0 ? [153, 27, 27] : [0, 130, 135];
|
|
206
|
+
PHASE_INFO = pill(`⬢ ${badgeText}`, bg);
|
|
171
207
|
}
|
|
172
208
|
}
|
|
173
209
|
} catch {}
|
|
174
210
|
|
|
211
|
+
// ─── Framework-dev badge ────────────────────────────────
|
|
212
|
+
// When editing the Qualia framework itself (detected by presence of the
|
|
213
|
+
// skills/ dir + qualia-ui.js), show a FRAMEWORK DEV pill even though
|
|
214
|
+
// there's no tracking.json. Gives the same "you're in Qualia mode" signal
|
|
215
|
+
// during framework work.
|
|
216
|
+
let FRAMEWORK_BADGE = "";
|
|
217
|
+
try {
|
|
218
|
+
const isFramework =
|
|
219
|
+
fs.existsSync(path.join(DIR, "skills", "qualia-plan", "SKILL.md")) &&
|
|
220
|
+
fs.existsSync(path.join(DIR, "bin", "qualia-ui.js"));
|
|
221
|
+
if (isFramework) {
|
|
222
|
+
FRAMEWORK_BADGE = pill("⬢ FRAMEWORK DEV", [120, 60, 140]);
|
|
223
|
+
}
|
|
224
|
+
} catch {}
|
|
225
|
+
|
|
175
226
|
// ─── Memory count ────────────────────────────────────────
|
|
176
227
|
let MEMORY_COUNT = 0;
|
|
177
228
|
try {
|
|
@@ -186,36 +237,22 @@ try {
|
|
|
186
237
|
}
|
|
187
238
|
} catch {}
|
|
188
239
|
|
|
189
|
-
// ───
|
|
190
|
-
|
|
240
|
+
// ─── Qualia identity: first name of the installed employee ─────────
|
|
241
|
+
// Read from ~/.claude/.qualia-config.json. Used as the "signature" at the
|
|
242
|
+
// end of line 2. Gracefully degrades to empty string if the config is
|
|
243
|
+
// missing (pre-install, broken install, or running outside a Qualia env).
|
|
244
|
+
let QUALIA_FIRST_NAME = "";
|
|
191
245
|
try {
|
|
192
|
-
const
|
|
193
|
-
if (fs.existsSync(
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
for (const matcher of event) {
|
|
199
|
-
if (matcher.hooks && Array.isArray(matcher.hooks)) {
|
|
200
|
-
HOOKS_COUNT += matcher.hooks.length;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
246
|
+
const configPath = path.join(HOME, ".claude", ".qualia-config.json");
|
|
247
|
+
if (fs.existsSync(configPath)) {
|
|
248
|
+
const cfg = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
249
|
+
const fullName = String(cfg.installed_by || "").trim();
|
|
250
|
+
if (fullName) {
|
|
251
|
+
QUALIA_FIRST_NAME = fullName.split(/\s+/)[0] || "";
|
|
205
252
|
}
|
|
206
253
|
}
|
|
207
254
|
} catch {}
|
|
208
255
|
|
|
209
|
-
// ─── Skills count ────────────────────────────────────────
|
|
210
|
-
let SKILLS_COUNT = 0;
|
|
211
|
-
try {
|
|
212
|
-
const skillsDir = path.join(HOME, ".claude", "skills");
|
|
213
|
-
if (fs.existsSync(skillsDir)) {
|
|
214
|
-
const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
|
|
215
|
-
SKILLS_COUNT = entries.filter(e => e.isDirectory() || e.name.endsWith(".md")).length;
|
|
216
|
-
}
|
|
217
|
-
} catch {}
|
|
218
|
-
|
|
219
256
|
// ─── Duration ────────────────────────────────────────────
|
|
220
257
|
let DUR = "0s";
|
|
221
258
|
try {
|
|
@@ -232,11 +269,14 @@ try {
|
|
|
232
269
|
COST_FMT = `$${COST.toFixed(2)}`;
|
|
233
270
|
} catch {}
|
|
234
271
|
|
|
235
|
-
// ─── Line 1: Project + Git + Agent + Worktree +
|
|
272
|
+
// ─── Line 1: Pill badge + Project + Git + Agent + Worktree + Memory + Identity ──
|
|
273
|
+
// Leading pill (phase info or framework-dev) — one of these at most, phase wins.
|
|
236
274
|
let LINE1 = "";
|
|
237
275
|
try {
|
|
238
276
|
const dirBase = path.basename(DIR) || DIR;
|
|
239
|
-
|
|
277
|
+
const leadingBadge = PHASE_INFO || FRAMEWORK_BADGE;
|
|
278
|
+
if (leadingBadge) LINE1 += `${leadingBadge} `;
|
|
279
|
+
LINE1 += `${TEAL}⬢${RESET} ${WHITE}${dirBase}${RESET}`;
|
|
240
280
|
if (BRANCH) {
|
|
241
281
|
if (CHANGES > 0) {
|
|
242
282
|
LINE1 += ` ${DIM}on${RESET} ${TEAL_GLOW}${BRANCH}${RESET} ${YELLOW}~${CHANGES}${RESET}`;
|
|
@@ -246,14 +286,11 @@ try {
|
|
|
246
286
|
}
|
|
247
287
|
if (AGENT) LINE1 += ` ${DIM}│${RESET} ${TEAL}⚡${AGENT}${RESET}`;
|
|
248
288
|
if (WORKTREE) LINE1 += ` ${DIM}│${RESET} ${TEAL_DIM}⎇ ${WORKTREE}${RESET}`;
|
|
249
|
-
if (
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
if (
|
|
253
|
-
|
|
254
|
-
if (SKILLS_COUNT > 0) contextParts.push(`${DIM}skills${RESET} ${TEAL_DIM}${SKILLS_COUNT}${RESET}`);
|
|
255
|
-
if (contextParts.length > 0) {
|
|
256
|
-
LINE1 += ` ${DIM}│${RESET} ${contextParts.join(` ${DIM}·${RESET} `)}`;
|
|
289
|
+
if (MEMORY_COUNT > 0) {
|
|
290
|
+
LINE1 += ` ${DIM}│${RESET} ${DIM}mem${RESET} ${TEAL}${MEMORY_COUNT}${RESET}`;
|
|
291
|
+
}
|
|
292
|
+
if (QUALIA_FIRST_NAME) {
|
|
293
|
+
LINE1 += ` ${DIM}│${RESET} ${TEAL}⬢${RESET} ${TEAL_GLOW}Qualia member${RESET}${DIM}:${RESET} ${WHITE}${QUALIA_FIRST_NAME}${RESET}`;
|
|
257
294
|
}
|
|
258
295
|
} catch {
|
|
259
296
|
LINE1 = `${TEAL}⬢${RESET} ${WHITE}qualia${RESET}`;
|
package/docs/erp-contract.md
CHANGED
|
@@ -28,8 +28,16 @@ Upload a session report.
|
|
|
28
28
|
```
|
|
29
29
|
Authorization: Bearer <api-key>
|
|
30
30
|
Content-Type: application/json
|
|
31
|
+
Idempotency-Key: <uuid> # optional; 24h replay window — see below
|
|
31
32
|
```
|
|
32
33
|
|
|
34
|
+
**Idempotency-Key behavior (v3.6+):**
|
|
35
|
+
When present, must be a valid UUID. Replays of the same key within 24h return
|
|
36
|
+
the original `report_id` with `Idempotent-Replay: true` response header and
|
|
37
|
+
200 status — no new row is created. Invalid UUID format returns 400.
|
|
38
|
+
Independent of `client_report_id` UPSERT (both can be used together; see
|
|
39
|
+
below).
|
|
40
|
+
|
|
33
41
|
**Request Body:**
|
|
34
42
|
```json
|
|
35
43
|
{
|
|
@@ -38,6 +46,7 @@ Content-Type: application/json
|
|
|
38
46
|
"team_id": "qualia-solutions",
|
|
39
47
|
"git_remote": "github.com/QualiasolutionsCY/acme-portal",
|
|
40
48
|
"client": "Client Name",
|
|
49
|
+
"client_report_id": "QS-REPORT-03",
|
|
41
50
|
"milestone": 2,
|
|
42
51
|
"milestone_name": "Core Product",
|
|
43
52
|
"milestones": [
|
|
@@ -87,11 +96,27 @@ accept both shapes: if object, use `gap_cycles[String(phase)] || 0`.
|
|
|
87
96
|
```json
|
|
88
97
|
{
|
|
89
98
|
"ok": true,
|
|
90
|
-
"report_id": "
|
|
99
|
+
"report_id": "QS-REPORT-03",
|
|
91
100
|
"message": "Report received"
|
|
92
101
|
}
|
|
93
102
|
```
|
|
94
103
|
|
|
104
|
+
`report_id` semantics:
|
|
105
|
+
- **v4.0.4+ payloads** (`client_report_id` present): ERP echoes the
|
|
106
|
+
`client_report_id` string back as `report_id` for display consistency.
|
|
107
|
+
Example: request sends `client_report_id: "QS-REPORT-03"` → response
|
|
108
|
+
returns `report_id: "QS-REPORT-03"`.
|
|
109
|
+
- **Legacy payloads** (no `client_report_id`): ERP returns its internal UUID
|
|
110
|
+
(e.g. `"a5304d8b-a5ac-4e22-b0c0-fed5f50299bb"`) as `report_id`.
|
|
111
|
+
|
|
112
|
+
**Idempotent UPSERT on retry (v4.0.4+):**
|
|
113
|
+
When BOTH `project_id` and `client_report_id` are present, the ERP treats
|
|
114
|
+
`(project_id, client_report_id)` as a unique key and UPSERTs. Retries after
|
|
115
|
+
a transient failure produce the same row and return the same `report_id`
|
|
116
|
+
— no duplicate. This is stronger than the 24h Idempotency-Key window (which
|
|
117
|
+
is exact-replay only) because `client_report_id` uniqueness is enforced
|
|
118
|
+
permanently.
|
|
119
|
+
|
|
95
120
|
**Response (401 Unauthorized):**
|
|
96
121
|
```json
|
|
97
122
|
{
|
|
@@ -171,7 +196,15 @@ Authorization: Bearer <api-key>
|
|
|
171
196
|
- When the API key file is missing or empty, the upload is skipped with a warning.
|
|
172
197
|
- Network failures are non-blocking — the report is saved locally regardless.
|
|
173
198
|
- The ERP reads `tracking.json` directly from git for real-time status (no API call needed for passive monitoring).
|
|
174
|
-
- Reports are append-only — no
|
|
199
|
+
- Reports are append-only — no PUT/PATCH/DELETE endpoints exist for
|
|
200
|
+
external callers. Internal idempotent UPSERT on `(project_id,
|
|
201
|
+
client_report_id)` retries is the one exception (see "Idempotent UPSERT
|
|
202
|
+
on retry" above).
|
|
203
|
+
- **`dry_run` retention (v4.0.4+):** The ERP deletes rows where
|
|
204
|
+
`dry_run = true AND submitted_at < now() - 7 days` via a daily cron at
|
|
205
|
+
03:00 UTC. Production report views (list, project tree, email digests)
|
|
206
|
+
exclude `dry_run = true` rows at read time by default. Admins can opt in
|
|
207
|
+
via `includeDryRun: true` on the server-action readers for diagnostics.
|
|
175
208
|
- `tracking.json` includes `milestone` and `lifetime` fields (added in v3.4). These survive across milestone resets and `state.js init` calls. For aggregate reporting, use `lifetime.total_phases` + current `total_phases` for the grand total across all milestones.
|
|
176
209
|
- Backward compatibility: if `lifetime` is absent in tracking.json, treat all counters as 0 and `milestone` as 1.
|
|
177
210
|
|
|
@@ -195,6 +228,8 @@ Authorization: Bearer <api-key>
|
|
|
195
228
|
| last_pushed_at | string | optional (v3.6+) | ISO 8601 — distinct from `last_updated` (which fires on local writes too). |
|
|
196
229
|
| build_count | number | optional (v3.6+) | Lifetime build counter. |
|
|
197
230
|
| deploy_count | number | optional (v3.6+) | Lifetime deploy counter. |
|
|
231
|
+
| client_report_id | string | recommended (v4.0.4+) | Client-side sequential identifier: `QS-REPORT-01`, `QS-REPORT-02`, … per-project. Stable across retries. Preferred dedupe key over the ERP-generated `report_id`; safe to adopt as the ERP's primary report key. |
|
|
232
|
+
| dry_run | boolean | optional (v4.0.4+) | `true` marks a synthetic ping (from `qualia-framework erp-ping`). Receivers should filter these out of production report views. |
|
|
198
233
|
|
|
199
234
|
All other fields are optional but recommended for complete reporting.
|
|
200
235
|
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Qualia Framework — Command Quality & Build Workflow Deep Research
|
|
2
|
+
**Date:** 2026-04-21
|
|
3
|
+
**Scope:** design, debug, optimize, review + plan/build/verify workflow + 8 subagent prompts
|
|
4
|
+
**Method:** 4 parallel Opus agents, each auditing one dimension, synthesized by framework owner
|
|
5
|
+
|
|
6
|
+
## Executive Summary
|
|
7
|
+
|
|
8
|
+
The framework's biggest accuracy leak is **evidence-free claims**: 3 of 4 diagnostic commands (design, debug, review) do not require file:line citations for findings, so the model hallucinates specifics under pressure. The biggest speed leak is **serial work that should be parallel**: qualia-design and qualia-review list `Agent` in allowed-tools but never spawn, so large codebases get processed in a single context window; the plan-checker revision loop serially re-spawns the planner for issues (frontmatter, wave assignment) that can be fixed mechanically.
|
|
9
|
+
|
|
10
|
+
The single highest-leverage change is a shared **Grounding Protocol** + **Rubric Library** referenced from every skill and agent — it eliminates ~60% of the determinism defects at once.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Top 15 Improvements — Ranked by Impact × Ease
|
|
15
|
+
|
|
16
|
+
| # | Change | Impact | Effort | Where |
|
|
17
|
+
|---|--------|--------|--------|-------|
|
|
18
|
+
| 1 | Add shared Grounding Protocol (cite-or-say-INSUFFICIENT-EVIDENCE) to all agents | 🔥 Accuracy | 30 min | `rules/grounding.md` + import into 8 agent files |
|
|
19
|
+
| 2 | Add deterministic severity formula (CRITICAL=8/HIGH=4/MED=2/LOW=1; score = max(1, 5−⌊Σ/8⌋)) to qualia-review | 🔥 Accuracy | 45 min | `skills/qualia-review/SKILL.md:124` |
|
|
20
|
+
| 3 | Pre-inline PROJECT.md into verifier prompt (currently missing) | 🔥 Accuracy | 10 min | `skills/qualia-verify/SKILL.md:42` |
|
|
21
|
+
| 4 | Make qualia-build spawn wave tasks in parallel explicitly ("all Agent() calls in SAME response") | ⚡ Speed | 30 min | `skills/qualia-build/SKILL.md:65` |
|
|
22
|
+
| 5 | Convert qualia-debug from interactive (4 questions) to investigative (parse $ARGUMENTS, run diagnostic greps) | 🔥 Accuracy | 2 hrs | `skills/qualia-debug/SKILL.md:39-44` |
|
|
23
|
+
| 6 | Add structured Output Contract (DONE/BLOCKED/PARTIAL prefix) to builder.md | ⚡ Speed + 🔥 Accuracy | 20 min | `agents/builder.md:14` |
|
|
24
|
+
| 7 | Mechanical-fix bypass in plan-checker (skip planner re-spawn for frontmatter/wave issues) | ⚡ Speed | 4 hrs | `skills/qualia-plan/SKILL.md:129-153` |
|
|
25
|
+
| 8 | Make wave assignment deterministic: file-based dependency graph, topological sort (not "tasks with no dependencies") | 🔥 Accuracy | 3 hrs | `agents/planner.md:33` |
|
|
26
|
+
| 9 | Add Rule 8 to plan-checker: "Validation must test behavior, not file-existence only" (stops stubs passing) | 🔥 Accuracy | 30 min | `agents/plan-checker.md` after Rule 7 |
|
|
27
|
+
| 10 | Split qualia-design/review into parallel agent fan-out for large file sets (5+ files) | ⚡ Speed | 3 hrs | `skills/qualia-design/SKILL.md`, `skills/qualia-review/SKILL.md` |
|
|
28
|
+
| 11 | Add wave-context summary (adjacent task titles + files) to builder prompt — stops semantic drift across parallel tasks | 🔥 Accuracy | 1 hr | `skills/qualia-build/SKILL.md:82` |
|
|
29
|
+
| 12 | Fix `grep -qL` bug in qualia-review API auth check (backwards logic) | 🔥 Accuracy | 15 min | `skills/qualia-review/SKILL.md:59-61` |
|
|
30
|
+
| 13 | Add tool budgets: researcher (8 external calls), verifier (25 bash calls), debug (10 reads) | ⚡ Speed | 45 min | `agents/researcher.md`, `agents/verifier.md`, `skills/qualia-debug` |
|
|
31
|
+
| 14 | Standardize input contracts across 8 agents with `<variable>` typed blocks (only plan-checker does this today) | 🔥 Accuracy | 2 hrs | All 8 agent files |
|
|
32
|
+
| 15 | Drop full `next build` from qualia-review; read existing `.next/` or skip with warning | ⚡ Speed | 20 min | `skills/qualia-review/SKILL.md:98` |
|
|
33
|
+
|
|
34
|
+
**Total effort for #1–#15:** ~20 hours of focused work → framework-wide accuracy and speed step-change.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Per-Command Scores (before changes)
|
|
39
|
+
|
|
40
|
+
| Command | Score | Weakest Dimension |
|
|
41
|
+
|---------|-------|-------------------|
|
|
42
|
+
| qualia-debug | 4/10 | Interactive-by-default (4 mandatory questions), no output file, cheat sheets instead of diagnostic commands |
|
|
43
|
+
| qualia-design | 6/10 | No critique output contract, `Agent` listed but never spawned, tsc-only verification |
|
|
44
|
+
| qualia-review | 7/10 | Serial bash scans, latent `grep -qL` bug, no parallelism |
|
|
45
|
+
| qualia-optimize | 8/10 | Strongest — uses agent fan-out, severity labels, OPTIMIZE.md output. Loses points on inline `find`/`grep` in Step 6 + no `--fix` dry-run |
|
|
46
|
+
|
|
47
|
+
## Per-Agent Scores (before changes)
|
|
48
|
+
|
|
49
|
+
| Agent | Overall | Biggest Gap |
|
|
50
|
+
|-------|---------|-------------|
|
|
51
|
+
| plan-checker | 9.5/10 | No tool budget |
|
|
52
|
+
| verifier | 9.0/10 | No frontend gate on design verification (runs 40 greps on backend phases) |
|
|
53
|
+
| planner | 8.5/10 | Prose input contract, no failure-mode handling |
|
|
54
|
+
| builder | 8.5/10 | No structured output contract |
|
|
55
|
+
| researcher | 8.5/10 | Unbounded WebSearch loops |
|
|
56
|
+
| qa-browser | 8.5/10 | Probes for dev server URL instead of receiving it; no fallback when Playwright unavailable |
|
|
57
|
+
| roadmapper | 8.5/10 | `full_detail` is a ghost parameter — referenced but not declared |
|
|
58
|
+
| research-synthesizer | 8.0/10 | No evidence requirement on milestone suggestions |
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Rubrics to Ship as `rules/rubrics.md`
|
|
63
|
+
|
|
64
|
+
**Severity (with deterministic category score):**
|
|
65
|
+
```
|
|
66
|
+
CRITICAL = 8 | HIGH = 4 | MEDIUM = 2 | LOW = 1
|
|
67
|
+
weighted_sum = Σ(count_i × weight_i)
|
|
68
|
+
category_score = max(1, 5 − ⌊weighted_sum / 8⌋)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Design Quality (1–5 per dimension, any <3 = mandatory fix):**
|
|
72
|
+
Typography / Color / Spacing / States / Responsiveness / Accessibility — each with objective criteria (see `skills/qualia-design` comment thread for full matrix).
|
|
73
|
+
|
|
74
|
+
**Task-Done:**
|
|
75
|
+
- Compiles (`tsc --noEmit` = 0)
|
|
76
|
+
- No stubs (`grep -c "TODO|FIXME|placeholder" touched_files` = 0)
|
|
77
|
+
- Wired (every export imported somewhere)
|
|
78
|
+
- Each acceptance criterion has a passing validation command
|
|
79
|
+
- Committed (git log matches task title)
|
|
80
|
+
|
|
81
|
+
**Evidence Citation Format:**
|
|
82
|
+
```
|
|
83
|
+
file:line — "quoted code" — {assessment}
|
|
84
|
+
```
|
|
85
|
+
Claims missing this format are rejected. If evidence cannot be found: `INSUFFICIENT EVIDENCE: searched {files} with {commands}`.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Grounding Protocol (paste into every agent)
|
|
90
|
+
|
|
91
|
+
```markdown
|
|
92
|
+
## Grounding Protocol (MANDATORY)
|
|
93
|
+
1. Every factual claim requires `file:line — "quoted code"`. No exception.
|
|
94
|
+
2. No hedging: "seems / probably / might" → verified or INSUFFICIENT EVIDENCE.
|
|
95
|
+
3. Findings without file:line are discarded.
|
|
96
|
+
4. Scores without evidence on the next line = 0.
|
|
97
|
+
5. Severity requires quoting the matching Severity Rubric criterion.
|
|
98
|
+
6. Output shape is a contract — missing sections = protocol violation.
|
|
99
|
+
7. Stop at tool budget. Return what you found, not what you wish.
|
|
100
|
+
8. Precondition: verify every @file exists before work; HALT if missing.
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 3 Architectural Changes (bigger, keep for later)
|
|
106
|
+
|
|
107
|
+
1. **Pre-Build Context Packet** — assemble one JSON with PROJECT.md + DESIGN.md + plan + wave-context before spawning builders. Eliminates per-builder file reads.
|
|
108
|
+
2. **Intra-Wave Verification** — run each task's Validation contracts immediately after its builder completes, before next wave starts. Catches failure at task granularity, not phase.
|
|
109
|
+
3. **Plan Cache** — cache parsed project identity in `.planning/.project-cache.json`; invalidate on PROJECT.md change. Saves ~30% planner context on multi-phase `--auto` runs.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Missing Agents Worth Adding (ranked)
|
|
114
|
+
|
|
115
|
+
1. **`migrator.md`** — generates + validates Supabase migrations. Current gap: builder writes raw SQL ad-hoc, migration guard catches only obvious patterns.
|
|
116
|
+
2. **`dependency-auditor.md`** — pre-build peer-dependency / vulnerability check. Current gap: builder hits `npm install` conflicts mid-phase and wastes context debugging.
|
|
117
|
+
3. **`rollback.md`** — on verify FAIL, bisect to last-good commit instead of always patching forward. Current gap: gap-closure plans build on broken code.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Anti-Patterns to Kill
|
|
122
|
+
|
|
123
|
+
- `find` inside skills (use Glob) — qualia-optimize:302, qualia-review multiple places
|
|
124
|
+
- `Agent` in allowed-tools but never spawned — qualia-design, qualia-debug, qualia-review
|
|
125
|
+
- Interactive question gates in one-shot commands — qualia-debug
|
|
126
|
+
- Full `next build` as part of a "scan" — qualia-review:98
|
|
127
|
+
- Vague "investigate the codebase" with no tool budget — qualia-debug, researcher
|
|
128
|
+
- "seems / probably / might" language anywhere in agent output
|