qualia-framework 6.1.0 → 6.2.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 +35 -26
- package/agents/roadmapper.md +1 -1
- package/bin/cli.js +339 -200
- package/bin/erp-retry.js +11 -3
- package/bin/install.js +383 -55
- package/bin/knowledge-flush.js +25 -13
- package/bin/knowledge.js +11 -1
- package/bin/project-snapshot.js +293 -0
- package/bin/qualia-ui.js +13 -2
- package/bin/report-payload.js +137 -0
- package/bin/state.js +8 -1
- package/bin/statusline.js +14 -2
- package/docs/changelog-v6.html +864 -0
- package/docs/ecosystem-operating-model.md +121 -0
- package/docs/erp-contract.md +74 -21
- package/docs/onboarding.html +1 -1
- package/docs/release.md +44 -0
- package/docs/reviews/v6.2.1-revival-audit.md +53 -0
- package/docs/reviews/v6.2.2-memory-erp-audit.md +41 -0
- package/docs/reviews/v6.2.3-erp-id-guard.md +15 -0
- package/guide.md +16 -4
- package/hooks/auto-update.js +14 -7
- package/hooks/branch-guard.js +10 -2
- package/hooks/env-empty-guard.js +10 -1
- package/hooks/git-guardrails.js +10 -1
- package/hooks/migration-guard.js +4 -1
- package/hooks/pre-deploy-gate.js +11 -1
- package/hooks/pre-push.js +42 -162
- package/hooks/session-start.js +22 -14
- package/hooks/stop-session-log.js +11 -3
- package/hooks/supabase-destructive-guard.js +11 -1
- package/hooks/vercel-account-guard.js +12 -3
- package/package.json +3 -2
- package/skills/qualia-map/SKILL.md +1 -1
- package/skills/qualia-milestone/SKILL.md +1 -1
- package/skills/qualia-optimize/SKILL.md +1 -1
- package/skills/qualia-polish/SKILL.md +2 -2
- package/skills/qualia-report/SKILL.md +6 -43
- package/skills/qualia-road/SKILL.md +1 -1
- package/skills/qualia-verify/SKILL.md +1 -1
- package/templates/help.html +1 -1
- package/templates/knowledge/agents.md +3 -3
- package/templates/knowledge/index.md +1 -1
- package/templates/tracking.json +3 -0
- package/templates/work-packet.md +46 -0
- package/tests/bin.test.sh +411 -13
- package/tests/hooks.test.sh +1 -8
- package/tests/install-smoke.test.sh +137 -0
- package/tests/published-install-smoke.test.sh +126 -0
- package/tests/refs.test.sh +42 -0
- package/tests/run-all.sh +1 -0
- package/tests/runner.js +19 -33
- package/tests/state.test.sh +4 -1
- package/hooks/pre-compact.js +0 -127
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Qualia Ecosystem Operating Model
|
|
2
|
+
|
|
3
|
+
The three systems have different jobs:
|
|
4
|
+
|
|
5
|
+
| Layer | System | Owns |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| Execution | Qualia Framework | Planning, building, verifying, shipping, handoff, and reporting inside a project repo. |
|
|
8
|
+
| Knowledge | Qualia Memory | Lessons, client preferences, recurring mistakes, durable research, and reusable patterns. |
|
|
9
|
+
| Operations | Qualia ERP | Live clients, projects, assignments, milestones, reports, invoices, payments, schedules, dashboards, and client portal state. |
|
|
10
|
+
|
|
11
|
+
Short version: **Framework builds. Memory remembers. ERP operates.**
|
|
12
|
+
|
|
13
|
+
## Boundaries
|
|
14
|
+
|
|
15
|
+
- Framework `.planning/` is execution state for agents and local reporting.
|
|
16
|
+
- ERP is the operational source of truth for admin and employee visibility.
|
|
17
|
+
- Memory stores durable knowledge, not live operational status.
|
|
18
|
+
- Read.ai and meeting tools are inputs, not a fourth source of truth.
|
|
19
|
+
|
|
20
|
+
## Safe Flows
|
|
21
|
+
|
|
22
|
+
### ERP to Framework
|
|
23
|
+
|
|
24
|
+
ERP can provide a work packet before a session starts:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
ERP project context
|
|
28
|
+
-> templates/work-packet.md
|
|
29
|
+
-> Claude/Codex session
|
|
30
|
+
-> Framework command
|
|
31
|
+
-> plan/build/verify/report
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The work packet should include project/client IDs, current milestone, open blockers, latest report, assigned employee, approved work, and guardrails. It should not silently change Framework state; the agent still uses `state.js` and `.planning/` for execution.
|
|
35
|
+
|
|
36
|
+
### Framework to ERP
|
|
37
|
+
|
|
38
|
+
Framework reports through `/qualia-report`:
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
Framework session
|
|
42
|
+
-> .planning/reports/report-YYYY-MM-DD.md
|
|
43
|
+
-> POST /api/v1/reports
|
|
44
|
+
-> ERP session report and admin dashboard
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
This is the primary sync. It is explicit, idempotent, and employee-visible.
|
|
48
|
+
|
|
49
|
+
Framework can also export a project-level snapshot for admin visibility:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
qualia-framework project-snapshot --write
|
|
53
|
+
-> .planning/snapshots/project-snapshot-*.json
|
|
54
|
+
-> ERP imports current 0-to-100 progress as a draft/project telemetry record
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Or, when ERP credentials are configured:
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
qualia-framework project-snapshot --upload
|
|
61
|
+
-> POST /api/v1/project-snapshots
|
|
62
|
+
-> ERP updates the canonical project's latest Framework progress metadata
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The snapshot is not a replacement for `/qualia-report`; it is the project-level rollup. It carries shared IDs, current milestone/phase, closed milestones, lifetime counters, deployment counters, and a progress percentage so ERP/admin views can show where a project stands without guessing from names or scraping local files.
|
|
66
|
+
|
|
67
|
+
### Framework Planning Snapshots to ERP
|
|
68
|
+
|
|
69
|
+
If ERP wants `.planning/JOURNEY.md`, `ROADMAP.md`, `STATE.md`, or `tracking.json`, use an explicit import/snapshot workflow. Do not depend on passive git scraping or hook-created bot commits.
|
|
70
|
+
|
|
71
|
+
Acceptable future contract:
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
Framework creates a planning snapshot
|
|
75
|
+
-> .planning/snapshots/project-snapshot-*.json
|
|
76
|
+
-> or POST /api/v1/project-snapshots
|
|
77
|
+
-> GitHub or API upload
|
|
78
|
+
-> ERP imports phases/items as draft operational records
|
|
79
|
+
-> human or approved automation confirms client-visible changes
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Framework tasks remain internal execution units. ERP assignments, deadlines, and client-visible statuses remain ERP-owned.
|
|
83
|
+
|
|
84
|
+
### Framework to Memory
|
|
85
|
+
|
|
86
|
+
Framework promotes durable lessons through `/qualia-learn`, `/qualia-postmortem`, or the knowledge flush:
|
|
87
|
+
|
|
88
|
+
```text
|
|
89
|
+
session report / postmortem / lesson
|
|
90
|
+
-> Memory raw note
|
|
91
|
+
-> wiki concept, client preference, or project lesson
|
|
92
|
+
-> future recall before planning
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Memory to Framework and ERP
|
|
96
|
+
|
|
97
|
+
Memory can provide context and draft suggestions. It must not directly override ERP operational state.
|
|
98
|
+
|
|
99
|
+
```text
|
|
100
|
+
Memory context
|
|
101
|
+
-> draft or planning context
|
|
102
|
+
-> human/approved automation confirms
|
|
103
|
+
-> ERP update or Framework execution
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Shared Identifiers
|
|
107
|
+
|
|
108
|
+
Use these wherever available:
|
|
109
|
+
|
|
110
|
+
| Identifier | Meaning |
|
|
111
|
+
|---|---|
|
|
112
|
+
| `project_id` | Stable Framework/project key, safe across folder renames. |
|
|
113
|
+
| `erp_project_id` | ERP canonical project UUID. |
|
|
114
|
+
| `client_id` | ERP/client canonical UUID. |
|
|
115
|
+
| `team_id` | Qualia/team identity. |
|
|
116
|
+
| `workspace_id` | Tenant/workspace UUID. |
|
|
117
|
+
| `git_remote` | Repository correlation key. |
|
|
118
|
+
| `framework_version` | Framework version that produced a report. |
|
|
119
|
+
| `client_report_id` | Per-project report sequence such as `QS-REPORT-03`. |
|
|
120
|
+
|
|
121
|
+
The less these systems guess from names, the cleaner admin tracking becomes.
|
package/docs/erp-contract.md
CHANGED
|
@@ -15,7 +15,7 @@ Phase and task counters remain framework telemetry. They help agents plan/build/
|
|
|
15
15
|
|
|
16
16
|
## Configuration
|
|
17
17
|
|
|
18
|
-
Stored in `~/.claude/.qualia-config.json`:
|
|
18
|
+
Stored in the active install home, either `~/.claude/.qualia-config.json` or `~/.codex/.qualia-config.json`:
|
|
19
19
|
|
|
20
20
|
```json
|
|
21
21
|
{
|
|
@@ -27,7 +27,7 @@ Stored in `~/.claude/.qualia-config.json`:
|
|
|
27
27
|
}
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
The API key is read from
|
|
30
|
+
The API key is read from `.erp-api-key` in the same install home (file mode 0600).
|
|
31
31
|
|
|
32
32
|
## Endpoints
|
|
33
33
|
|
|
@@ -54,7 +54,10 @@ below).
|
|
|
54
54
|
{
|
|
55
55
|
"project": "client-project-name",
|
|
56
56
|
"project_id": "qs-acme-portal",
|
|
57
|
+
"erp_project_id": "7b5d3b4e-2b8a-4de4-91a1-9b2f3182f5ef",
|
|
58
|
+
"client_id": "5f5a8d8e-8c58-4c30-9b76-13a08f0d0d8a",
|
|
57
59
|
"team_id": "qualia-solutions",
|
|
60
|
+
"workspace_id": "2af02a2d-6f1f-4d43-a6cb-6a1e7e09ac43",
|
|
58
61
|
"git_remote": "github.com/QualiasolutionsCY/acme-portal",
|
|
59
62
|
"client": "Client Name",
|
|
60
63
|
"client_report_id": "QS-REPORT-03",
|
|
@@ -97,8 +100,7 @@ below).
|
|
|
97
100
|
}
|
|
98
101
|
```
|
|
99
102
|
|
|
100
|
-
**`gap_cycles` polymorphism (v3.5+):** in `tracking.json`
|
|
101
|
-
reads from git for passive monitoring) `gap_cycles` is an OBJECT keyed by
|
|
103
|
+
**`gap_cycles` polymorphism (v3.5+):** in local `tracking.json`, `gap_cycles` is an OBJECT keyed by
|
|
102
104
|
phase number — `{"1": 0, "2": 1}`. In the POST `/api/v1/reports` body,
|
|
103
105
|
`/qualia-report` flattens to a NUMBER for the current phase. Receivers must
|
|
104
106
|
accept both shapes: if object, use `gap_cycles[String(phase)] || 0`.
|
|
@@ -171,42 +173,90 @@ Authorization: Bearer <api-key>
|
|
|
171
173
|
}
|
|
172
174
|
```
|
|
173
175
|
|
|
174
|
-
|
|
176
|
+
## Project Snapshot Export
|
|
175
177
|
|
|
176
|
-
|
|
178
|
+
`qualia-framework project-snapshot --write` creates a local project-level rollup at:
|
|
177
179
|
|
|
178
|
-
|
|
180
|
+
```text
|
|
181
|
+
.planning/snapshots/project-snapshot-YYYY-MM-DDTHH-MM-SS-sssZ.json
|
|
179
182
|
```
|
|
183
|
+
|
|
184
|
+
This is the explicit Framework -> ERP import artifact for admin/project dashboards. It is separate from `/qualia-report`: reports describe one work session; snapshots describe where the project stands from kickoff to handoff.
|
|
185
|
+
|
|
186
|
+
`qualia-framework project-snapshot --upload` sends the same JSON to ERP:
|
|
187
|
+
|
|
188
|
+
```http
|
|
189
|
+
POST /api/v1/project-snapshots
|
|
180
190
|
Authorization: Bearer <api-key>
|
|
191
|
+
Content-Type: application/json
|
|
181
192
|
```
|
|
182
193
|
|
|
183
|
-
|
|
194
|
+
ERP resolves `identifiers.erp_project_id` first, then falls back to repo/name matching. A successful import stores the latest snapshot and `framework_progress_percent` on the canonical ERP project's metadata so project dashboards can show current Framework progress.
|
|
195
|
+
|
|
196
|
+
Snapshot shape:
|
|
197
|
+
|
|
184
198
|
```json
|
|
185
199
|
{
|
|
186
|
-
"
|
|
187
|
-
"
|
|
188
|
-
|
|
200
|
+
"snapshot_version": 1,
|
|
201
|
+
"generated_at": "2026-05-21T00:00:00.000Z",
|
|
202
|
+
"source": "qualia-framework",
|
|
203
|
+
"framework_version": "6.2.6",
|
|
204
|
+
"identifiers": {
|
|
205
|
+
"project_id": "qs-acme-portal",
|
|
206
|
+
"team_id": "qualia-solutions",
|
|
207
|
+
"git_remote": "github.com/QualiasolutionsCY/acme-portal",
|
|
208
|
+
"erp_project_id": "7b5d3b4e-2b8a-4de4-91a1-9b2f3182f5ef",
|
|
209
|
+
"client_id": "5f5a8d8e-8c58-4c30-9b76-13a08f0d0d8a"
|
|
210
|
+
},
|
|
211
|
+
"project": {
|
|
212
|
+
"name": "acme-portal",
|
|
213
|
+
"client": "Acme",
|
|
214
|
+
"status": "built",
|
|
215
|
+
"deployed_url": "https://client.vercel.app",
|
|
216
|
+
"progress_percent": 42
|
|
217
|
+
},
|
|
218
|
+
"current": {
|
|
189
219
|
"milestone": 2,
|
|
220
|
+
"milestone_name": "Product",
|
|
190
221
|
"phase": 2,
|
|
222
|
+
"phase_name": "Dashboard",
|
|
191
223
|
"total_phases": 4,
|
|
192
|
-
"
|
|
193
|
-
"
|
|
194
|
-
"
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
224
|
+
"tasks_done": 3,
|
|
225
|
+
"tasks_total": 5,
|
|
226
|
+
"verification": "pending",
|
|
227
|
+
"gap_cycles": 1
|
|
228
|
+
},
|
|
229
|
+
"journey": {
|
|
230
|
+
"total_milestones": 3,
|
|
231
|
+
"milestones": [
|
|
232
|
+
{ "num": 1, "name": "Foundation", "status": "closed" },
|
|
233
|
+
{ "num": 2, "name": "Product", "status": "active" },
|
|
234
|
+
{ "num": 3, "name": "Handoff", "status": "pending" }
|
|
235
|
+
],
|
|
236
|
+
"closed_milestones": []
|
|
237
|
+
},
|
|
238
|
+
"lifetime": {
|
|
239
|
+
"tasks_completed": 12,
|
|
240
|
+
"phases_completed": 4,
|
|
241
|
+
"milestones_completed": 1,
|
|
242
|
+
"total_phases": 4,
|
|
243
|
+
"last_closed_milestone": 1,
|
|
244
|
+
"build_count": 4,
|
|
245
|
+
"deploy_count": 1
|
|
200
246
|
}
|
|
201
247
|
}
|
|
202
248
|
```
|
|
203
249
|
|
|
204
250
|
## Behavior
|
|
205
251
|
|
|
206
|
-
- When `erp.enabled` is `false`, `/qualia-report` skips the upload
|
|
252
|
+
- When `erp.enabled` is `false`, `/qualia-report` skips the upload and prints an info line so the employee knows the report stayed local.
|
|
207
253
|
- When the API key file is missing or empty, the upload is skipped with a warning.
|
|
208
254
|
- Network failures are non-blocking — the report is saved locally regardless.
|
|
209
|
-
-
|
|
255
|
+
- `tracking.json` is **local-only** telemetry as of v6.2 (2026-05-20). Pre-v6.2
|
|
256
|
+
the pre-push hook bot-committed it on every push so the ERP could read it
|
|
257
|
+
from GitHub. That consumer was documented here but never actually implemented
|
|
258
|
+
on the ERP side; the bot commits were pollution. The ERP gets all state from
|
|
259
|
+
`/qualia-report` POSTs to `/api/v1/reports` — which is sufficient.
|
|
210
260
|
- Reports are append-only — no PUT/PATCH/DELETE endpoints exist for
|
|
211
261
|
external callers. Internal idempotent UPSERT on `(project_id,
|
|
212
262
|
client_report_id)` retries is the one exception (see "Idempotent UPSERT
|
|
@@ -239,6 +289,9 @@ Authorization: Bearer <api-key>
|
|
|
239
289
|
| lifetime | object | recommended | Cumulative counters — tasks_completed, phases_completed, milestones_completed, total_phases, last_closed_milestone |
|
|
240
290
|
| project_id | string | recommended (v3.6+) | Stable per-project identifier — preferred dedupe key over `project` slug. Survives directory renames. |
|
|
241
291
|
| team_id | string | recommended (v3.6+) | Installation's team identifier. Composite `(team_id, project_id)` is the canonical project key. |
|
|
292
|
+
| erp_project_id | UUID string | optional | ERP's canonical project UUID when known. Strongest direct link for admin dashboards; `/qualia-report` only sends UUID-shaped values. |
|
|
293
|
+
| client_id | UUID string | optional | ERP/client canonical UUID when known. Lets reports attach to the client without guessing from a display name; slug-like values are omitted to avoid ERP validation failures. |
|
|
294
|
+
| workspace_id | UUID string | optional | Workspace/tenant scope for multi-company or multi-team installs; only UUID-shaped values are sent. |
|
|
242
295
|
| git_remote | string | optional (v3.6+) | e.g. `github.com/QualiasolutionsCY/foo`. Lets the ERP correlate tracking with the source repo. |
|
|
243
296
|
| session_started_at | string | optional (v3.6+) | ISO 8601 — when the current Claude Code session began. |
|
|
244
297
|
| last_pushed_at | string | optional (v3.6+) | ISO 8601 — distinct from `last_updated` (which fires on local writes too). |
|
package/docs/onboarding.html
CHANGED
|
@@ -612,7 +612,7 @@
|
|
|
612
612
|
</section>
|
|
613
613
|
|
|
614
614
|
<footer>
|
|
615
|
-
<span>Qualia Framework v6.
|
|
615
|
+
<span>Qualia Framework v6.2.7 · Plan, build, verify, ship.</span>
|
|
616
616
|
<span><a href="https://github.com/Qualiasolutions/qualia-framework">github.com/Qualiasolutions/qualia-framework</a></span>
|
|
617
617
|
</footer>
|
|
618
618
|
|
package/docs/release.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Release Verification
|
|
2
|
+
|
|
3
|
+
Use this when the repo is ready but `npx qualia-framework@latest install` still needs proof.
|
|
4
|
+
|
|
5
|
+
## Pre-Publish
|
|
6
|
+
|
|
7
|
+
Run from the release branch before merging:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm test
|
|
11
|
+
npm pack --dry-run
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`npm test` proves the source tree and packaged tarball install path. `npm pack --dry-run` proves the files that will be shipped.
|
|
15
|
+
|
|
16
|
+
## Publish
|
|
17
|
+
|
|
18
|
+
Publish only from the versioned main commit:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm whoami
|
|
22
|
+
npm publish --access public
|
|
23
|
+
npm view qualia-framework version
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The final command must print the same version as `package.json`.
|
|
27
|
+
|
|
28
|
+
## Post-Publish
|
|
29
|
+
|
|
30
|
+
After npm `latest` matches the repo, run:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm run test:published-install
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
This smoke uses an isolated `HOME` and npm cache, runs `npx --yes qualia-framework@latest install`, selects target `Both`, and verifies:
|
|
37
|
+
|
|
38
|
+
- Claude `CLAUDE.md` is installed with the OWNER role.
|
|
39
|
+
- Codex `AGENTS.md`, `hooks.json`, `agents/*.toml`, `bin/`, `skills/`, `rules/`, templates, and knowledge files are installed with the OWNER role.
|
|
40
|
+
- Role placeholders are gone.
|
|
41
|
+
- The installed hook set is the current 11-hook set with no `pre-compact.js`.
|
|
42
|
+
- The installed `.qualia-config.json` version matches `package.json`.
|
|
43
|
+
|
|
44
|
+
If this fails because npm latest is behind, the framework is not publicly revived yet even if local tests pass.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Qualia Framework Revival Audit - 2026-05-21
|
|
2
|
+
|
|
3
|
+
Scope: current `qualia-framework` worktree moving from `package.json` version `6.2.0` to `6.2.1`, with emphasis on silent failures, dead references, ERP/report truth, Codex and Claude Code compatibility, token discipline, and the "0 to hero" project road.
|
|
4
|
+
|
|
5
|
+
## Evidence Collected
|
|
6
|
+
|
|
7
|
+
- `npm test` passed all 9 suites after the package-install smoke test was added.
|
|
8
|
+
- `bash tests/refs.test.sh` passed after adding stale-surface guards: 25 checks, 0 failed.
|
|
9
|
+
- `bash tests/skills.test.sh` passed: 168 checks, 0 failed.
|
|
10
|
+
- `bash tests/install-smoke.test.sh` passed: 7 checks, 0 failed.
|
|
11
|
+
- `npm pack --dry-run` succeeded after the version bump and showed `qualia-framework@6.2.1`, 144 package files, 466.7 kB package size, 1.5 MB unpacked.
|
|
12
|
+
- `npm view qualia-framework version` returned `6.1.0`; local package is now `6.2.1`. This means `npx qualia-framework@latest install` does not yet install the local v6.2 contract.
|
|
13
|
+
|
|
14
|
+
## External 2026 Check
|
|
15
|
+
|
|
16
|
+
- Claude Code skills are live-discovered from `~/.claude/skills/`, project `.claude/skills/`, and parent directories; supporting files should be referenced from `SKILL.md` and loaded on demand. Current framework structure matches this pattern.
|
|
17
|
+
- Claude Code hooks remain event-based and include `PreCompact`, but hooks are arbitrary commands and must be reviewed/tested. Removing Qualia's `pre-compact.js` bot commit is compatible because state durability belongs in `state.js`, not git history.
|
|
18
|
+
- Claude Code subagents use separate context windows and should be used when repeated side work would flood the main context. Qualia's dedicated planner, builder, verifier, researcher, roadmapper, and QA agents still match this model.
|
|
19
|
+
- Codex continues to treat `AGENTS.md` as the cross-agent project instruction surface. The framework's root `AGENTS.md` mirror is the right compatibility layer, but installed Codex behavior should be verified with a real `codex` session after publish.
|
|
20
|
+
- MCP's 2026 direction emphasizes production readiness, security boundaries, and controlled user elicitation. Qualia should keep MCP use explicit and avoid tool servers asking for secrets through elicitation.
|
|
21
|
+
|
|
22
|
+
Sources checked:
|
|
23
|
+
- Claude Code skills: https://code.claude.com/docs/en/slash-commands
|
|
24
|
+
- Claude Code hooks: https://code.claude.com/docs/en/hooks
|
|
25
|
+
- Claude Code subagents: https://code.claude.com/docs/en/sub-agents
|
|
26
|
+
- Codex AGENTS.md pointer: https://github.com/openai/codex/blob/main/docs/agents_md.md
|
|
27
|
+
- AGENTS.md format: https://github.com/agentsmd/agents.md
|
|
28
|
+
- MCP 2026 roadmap: https://blog.modelcontextprotocol.io/posts/2026-mcp-roadmap/
|
|
29
|
+
- MCP elicitation: https://modelcontextprotocol.io/specification/2025-11-25/client/elicitation
|
|
30
|
+
|
|
31
|
+
## Fixed In This Pass
|
|
32
|
+
|
|
33
|
+
- README and onboarding version text now reflect `v6.2.0`, not `v6.0.0`.
|
|
34
|
+
- README and guide now say 33 skills and include `/qualia-vibe`.
|
|
35
|
+
- Active docs no longer claim the ERP passively reads `tracking.json` from git.
|
|
36
|
+
- `/qualia-road`, `/qualia-milestone`, and `agents/roadmapper.md` now frame `tracking.json` as local/report telemetry instead of an ERP tree source.
|
|
37
|
+
- `/qualia-verify` no longer repeats the old "silent PASS unless downgraded" wording for `INSUFFICIENT EVIDENCE`; it now states fail-closed behavior directly.
|
|
38
|
+
- `/qualia-polish` no longer says optional Lighthouse/axe gates are skipped silently.
|
|
39
|
+
- `tests/refs.test.sh` now fails on stale active-surface claims: passive ERP tracking, removed pre-compact guidance, stale skill count, stale README version, old `INSUFFICIENT EVIDENCE` wording, and silent optional gate language.
|
|
40
|
+
- `tests/install-smoke.test.sh` now proves the packaged tarball can install into both Claude and Codex targets from an isolated HOME.
|
|
41
|
+
|
|
42
|
+
## Current Verdict
|
|
43
|
+
|
|
44
|
+
The core framework is functional and test-backed, but the public install path is not revived yet because npm latest is still `6.1.0` while this repo is `6.2.1`. Until a verified publish happens, employees using `npx qualia-framework@latest install` do not receive the no-bot-commit contract or the refreshed docs.
|
|
45
|
+
|
|
46
|
+
## Remaining High-Leverage Work
|
|
47
|
+
|
|
48
|
+
1. **Publish drift is the current release blocker.** After full tests, publish a patched release so `@latest` matches the repo. Evidence target: `npm view qualia-framework version` returns the new version.
|
|
49
|
+
2. **Codex install verification should become a test.** The installer already writes `~/.codex/AGENTS.md`, but the next pass should add a non-interactive smoke test that verifies Codex-facing install output contains the role-filled root instructions and no `{{ROLE}}` placeholders.
|
|
50
|
+
3. **Claude hook modernization should be explicit, not opportunistic.** Current Claude Code exposes newer hook events such as `PostToolUseFailure`, `PostToolBatch`, `InstructionsLoaded`, `SessionEnd`, and agent start/stop events. Qualia does not need to wire all of them, but a future phase should decide which are useful for employee/admin experience instead of drifting hook-by-hook.
|
|
51
|
+
4. **ERP employee/admin experience should stay report-driven.** Framework telemetry should enrich `/qualia-report`; the ERP should not depend on git scraping internal `.planning` files. This keeps framework tasks internal and preserves the ERP as the oversight layer.
|
|
52
|
+
5. **Skill count should not grow by default.** The 33-skill surface is already large. Prefer merging or tightening skills before adding new ones unless a new skill removes repeated work that cannot be handled by an existing command.
|
|
53
|
+
6. **Token awareness should be measured in installed surfaces.** The next audit should report installed `CLAUDE.md`/`AGENTS.md` line count, skill description total size, and agent frontmatter count so "lightweight" is a measurable contract, not a claim.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Qualia Framework Memory/ERP Audit - 2026-05-21
|
|
2
|
+
|
|
3
|
+
Source reviewed: `/home/qualia-new/Downloads/qualia-framework-memory-erp-connection.md`.
|
|
4
|
+
|
|
5
|
+
## Useful Model Adopted
|
|
6
|
+
|
|
7
|
+
The note's core model is correct and now has a framework home:
|
|
8
|
+
|
|
9
|
+
- Framework builds.
|
|
10
|
+
- Memory remembers.
|
|
11
|
+
- ERP operates.
|
|
12
|
+
|
|
13
|
+
This became `docs/ecosystem-operating-model.md` so employees and admins have one clear boundary document instead of scattered assumptions.
|
|
14
|
+
|
|
15
|
+
## Correction Applied
|
|
16
|
+
|
|
17
|
+
The note says ERP can sync `.planning/` files from GitHub into project phases/items. That is acceptable only as an explicit import/snapshot workflow. It must not revive the old v6.1 passive `tracking.json` git-scrape story or hook-created bot commits.
|
|
18
|
+
|
|
19
|
+
Current contract:
|
|
20
|
+
|
|
21
|
+
- `/qualia-report` remains the primary Framework -> ERP sync.
|
|
22
|
+
- `.planning` snapshots are allowed only through an explicit future import/API workflow.
|
|
23
|
+
- ERP owns client-visible status, deadlines, assignments, payments, and dashboards.
|
|
24
|
+
- Framework owns local execution state.
|
|
25
|
+
- Memory owns durable knowledge, not live operational truth.
|
|
26
|
+
|
|
27
|
+
## Changes Made
|
|
28
|
+
|
|
29
|
+
- Added `docs/ecosystem-operating-model.md`.
|
|
30
|
+
- Added `templates/work-packet.md` for ERP-approved session context.
|
|
31
|
+
- Added optional `erp_project_id`, `client_id`, and `workspace_id` fields to `templates/tracking.json`.
|
|
32
|
+
- Updated `bin/state.js` so those identifiers survive `state.js init` / re-init.
|
|
33
|
+
- Updated `/qualia-report` payload construction to send those identifiers only when present.
|
|
34
|
+
- Updated `docs/erp-contract.md` with the new optional fields.
|
|
35
|
+
- Updated `/qualia-report` help text to use the safe piped `set-erp-key` command.
|
|
36
|
+
|
|
37
|
+
## Remaining Work
|
|
38
|
+
|
|
39
|
+
1. ERP backend should accept and store `erp_project_id`, `client_id`, and `workspace_id` if it does not already.
|
|
40
|
+
2. ERP can generate `templates/work-packet.md` content or a JSON equivalent for agents.
|
|
41
|
+
3. If planning snapshots are needed, define a real endpoint or import job with approval semantics. Do not depend on passive GitHub scraping.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Qualia Framework ERP ID Guard - 2026-05-21
|
|
2
|
+
|
|
3
|
+
After the v6.2.2 Framework/Memory/ERP patch, the ERP route was checked directly in `/home/qualia-new/Projects/qualia-erp/app/api/v1/reports/route.ts`.
|
|
4
|
+
|
|
5
|
+
Finding:
|
|
6
|
+
|
|
7
|
+
- ERP `client_id` is validated as a UUID and stored as an FK to `clients`.
|
|
8
|
+
- ERP already has an `erp_project_id` column and admin reporting reads it.
|
|
9
|
+
- The v6.2.2 framework example used a slug-like `client_id` (`"acme"`) and `/qualia-report` would send any non-empty `client_id`.
|
|
10
|
+
|
|
11
|
+
Fix:
|
|
12
|
+
|
|
13
|
+
- `/qualia-report` now includes `erp_project_id`, `client_id`, and `workspace_id` only when values are UUID-shaped.
|
|
14
|
+
- Docs now label those IDs as UUIDs.
|
|
15
|
+
- `project_id` and `team_id` remain the slug/string identifiers for framework-level dedupe and reporting.
|
package/guide.md
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
|
-
# Qualia Developer Guide (v6.
|
|
1
|
+
# Qualia Developer Guide (v6.2.7)
|
|
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
|
+
**v6.2.7 is the Codex runtime compatibility patch.** Codex installs now get native `~/.codex/hooks.json`, TOML agents, bin scripts, rules, skills, templates, knowledge, guide, and role config in addition to `AGENTS.md`.
|
|
7
|
+
|
|
8
|
+
**v6.2.5 carries forward.** `qualia-framework project-snapshot --write` creates a single `.planning/snapshots/project-snapshot-*.json` artifact with project identifiers, current milestone/phase, closed milestones, lifetime counters, and a project progress percentage for explicit ERP/admin import.
|
|
9
|
+
|
|
10
|
+
**v6.2.4 carries forward.** The Framework -> ERP report payload now comes from the shipped and tested `report-payload.js` builder, so admin-visible report linking fields are covered by executable tests instead of only prompt prose.
|
|
11
|
+
|
|
12
|
+
**v6.2.3 carries forward.** Framework slugs stay in `project_id`/`team_id`; ERP foreign-key identifiers (`erp_project_id`, `client_id`, `workspace_id`) are sent only when UUID-shaped, so reports do not fail validation because a local slug leaked into an ERP UUID field.
|
|
13
|
+
|
|
14
|
+
**v6.2.2 carries forward.** Framework builds, Memory remembers, ERP operates. ERP work packets can seed Claude/Codex sessions, `/qualia-report` can carry ERP-native IDs, and release verification now has a public `@latest` install smoke.
|
|
15
|
+
|
|
16
|
+
**v6.2.1 carries forward.** Active docs match the v6.2 no-bot-commit model, the explicit `/qualia-report` ERP contract, the current 33-skill surface, and fail-closed `INSUFFICIENT EVIDENCE` behavior. `tests/refs.test.sh` guards those claims.
|
|
17
|
+
|
|
6
18
|
**v6.1.0 ships the design-pivot path you were missing.** New `/qualia-vibe` is fast aesthetic pivot (~3 min): swap design tokens, keep layout. Default proposes ONE direction per `rules/one-opinion.md` (the EventMaster discipline — never give the user a menu). Sub-modes: `--variants N` for the opt-in menu, `--extract URL` reverse-engineers DESIGN.md from a reference site, `--sync` shows code↔DESIGN.md drift and can patch DESIGN.md from code. Slop-detect grew banned fonts (Montserrat/Poppins/Lato/Open Sans) and a `--watch` flag for proactive single-file mode. Several design-surface bugs from v6.0 audit are fixed too (viewport mismatch, slop-detect path resolution in the polish loop, dead `/qualia-design` references, the bounce-easing token that contradicted design-laws).
|
|
7
19
|
|
|
8
|
-
**v6.
|
|
20
|
+
**v6.2.0 removes hook-created bot commits.** `pre-push.js` stamps local `tracking.json` telemetry but no longer commits it. `pre-compact.js` is gone because `state.js` already gives stronger crash safety with atomic writes plus a journal. ERP sync remains explicit through `/qualia-report` POSTs, not passive git scraping.
|
|
9
21
|
|
|
10
22
|
**v5.9.2 carries forward.** `pre-push.js` self-gates against `branch-guard.js` so a blocked push no longer leaves an orphan bot commit. `qualia-report` ERP payload omits empty ISO datetime fields (avoids 422 from the ERP validator).
|
|
11
23
|
|
|
@@ -13,7 +25,7 @@
|
|
|
13
25
|
|
|
14
26
|
**v5.9.0 carries forward.** `tests/refs.test.sh` catches dead command references in user-facing surfaces on every release. `bin/erp-retry.js` is a real persistent retry queue for ERP report uploads. Four structured agents (verifier, plan-checker, roadmapper, qa-browser) run on Sonnet for ~40% per-phase cost cut, while builder/planner/researcher/visual-evaluator stay on Opus where the architectural and vision reasoning lives. The verifier downgrades to FAIL on any `INSUFFICIENT EVIDENCE` line.
|
|
15
27
|
|
|
16
|
-
**Surface
|
|
28
|
+
**Surface is 33 skills.** Use `/qualia-feature` for single-feature work and `/qualia-discuss` in PROJECT MODE for kickoff capture; `/qualia-polish --loop` for the autonomous visual loop; `/qualia-vibe` for fast layout-preserving aesthetic pivots.
|
|
17
29
|
|
|
18
30
|
## The Road
|
|
19
31
|
|
|
@@ -132,7 +144,7 @@ If neither helps, paste the error and ask Claude directly. If Claude can't fix i
|
|
|
132
144
|
- **Story-file plans:** Every task has Why / Acceptance Criteria / Depends on / Validation inline — the plan IS the brief.
|
|
133
145
|
- **Wave execution:** Independent tasks run in parallel. Dependent tasks wait.
|
|
134
146
|
- **Milestone-boundary pauses:** In `--auto` mode, the framework pauses only at real decision points. Everything else runs on rails.
|
|
135
|
-
- **tracking.json:** Updated on
|
|
147
|
+
- **tracking.json:** Updated locally on push. It feeds local statusline, stop-session-log, and `/qualia-report`; the ERP receives explicit report uploads and does not passively scrape this file from git.
|
|
136
148
|
|
|
137
149
|
## Quick Reference
|
|
138
150
|
|
package/hooks/auto-update.js
CHANGED
|
@@ -10,16 +10,23 @@ const { spawnSync } = require("child_process");
|
|
|
10
10
|
|
|
11
11
|
const _traceStart = Date.now();
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
function qualiaHome() {
|
|
14
|
+
if (process.env.QUALIA_HOME) return process.env.QUALIA_HOME;
|
|
15
|
+
const parent = path.basename(path.dirname(__dirname));
|
|
16
|
+
if (parent === ".codex" || parent === ".claude") return path.dirname(__dirname);
|
|
17
|
+
return path.join(os.homedir(), ".claude");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const QUALIA_HOME = qualiaHome();
|
|
21
|
+
const CACHE_FILE = path.join(QUALIA_HOME, ".qualia-last-update-check");
|
|
22
|
+
const CONFIG_FILE = path.join(QUALIA_HOME, ".qualia-config.json");
|
|
23
|
+
const LOCK_FILE = path.join(QUALIA_HOME, ".qualia-updating");
|
|
24
|
+
const NOTIF_FILE = path.join(QUALIA_HOME, ".qualia-update-available.json");
|
|
18
25
|
const MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
19
26
|
|
|
20
27
|
function _trace(hookName, result, extra) {
|
|
21
28
|
try {
|
|
22
|
-
const traceDir = path.join(
|
|
29
|
+
const traceDir = path.join(QUALIA_HOME, ".qualia-traces");
|
|
23
30
|
if (!fs.existsSync(traceDir)) fs.mkdirSync(traceDir, { recursive: true });
|
|
24
31
|
const entry = {
|
|
25
32
|
hook: hookName,
|
|
@@ -111,7 +118,7 @@ try {
|
|
|
111
118
|
// Invalidate the session-start health cache so the next session re-checks
|
|
112
119
|
// whether new critical files shipped in the latest version are installed.
|
|
113
120
|
try {
|
|
114
|
-
fs.unlinkSync(path.join(
|
|
121
|
+
fs.unlinkSync(path.join(QUALIA_HOME, ".qualia-install-health.json"));
|
|
115
122
|
} catch {}
|
|
116
123
|
_trace("auto-update", "allow", { reason: "notification-written", current: cfg.version, latest });
|
|
117
124
|
} else {
|
package/hooks/branch-guard.js
CHANGED
|
@@ -12,11 +12,19 @@ const { spawnSync } = require("child_process");
|
|
|
12
12
|
|
|
13
13
|
const _traceStart = Date.now();
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
function qualiaHome() {
|
|
16
|
+
if (process.env.QUALIA_HOME) return process.env.QUALIA_HOME;
|
|
17
|
+
const parent = path.basename(path.dirname(__dirname));
|
|
18
|
+
if (parent === ".codex" || parent === ".claude") return path.dirname(__dirname);
|
|
19
|
+
return path.join(os.homedir(), ".claude");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const QUALIA_HOME = qualiaHome();
|
|
23
|
+
const CONFIG = path.join(QUALIA_HOME, ".qualia-config.json");
|
|
16
24
|
|
|
17
25
|
function _trace(hookName, result, extra) {
|
|
18
26
|
try {
|
|
19
|
-
const traceDir = path.join(
|
|
27
|
+
const traceDir = path.join(QUALIA_HOME, ".qualia-traces");
|
|
20
28
|
if (!fs.existsSync(traceDir)) fs.mkdirSync(traceDir, { recursive: true });
|
|
21
29
|
const entry = {
|
|
22
30
|
hook: hookName,
|
package/hooks/env-empty-guard.js
CHANGED
|
@@ -9,9 +9,18 @@ const os = require("os");
|
|
|
9
9
|
|
|
10
10
|
const _traceStart = Date.now();
|
|
11
11
|
|
|
12
|
+
function qualiaHome() {
|
|
13
|
+
if (process.env.QUALIA_HOME) return process.env.QUALIA_HOME;
|
|
14
|
+
const parent = path.basename(path.dirname(__dirname));
|
|
15
|
+
if (parent === ".codex" || parent === ".claude") return path.dirname(__dirname);
|
|
16
|
+
return path.join(os.homedir(), ".claude");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const QUALIA_HOME = qualiaHome();
|
|
20
|
+
|
|
12
21
|
function _trace(result, extra) {
|
|
13
22
|
try {
|
|
14
|
-
const traceDir = path.join(
|
|
23
|
+
const traceDir = path.join(QUALIA_HOME, ".qualia-traces");
|
|
15
24
|
if (!fs.existsSync(traceDir)) fs.mkdirSync(traceDir, { recursive: true });
|
|
16
25
|
const entry = {
|
|
17
26
|
hook: "env-empty-guard", result,
|
package/hooks/git-guardrails.js
CHANGED
|
@@ -28,9 +28,18 @@ const { spawnSync } = require("child_process");
|
|
|
28
28
|
|
|
29
29
|
const _traceStart = Date.now();
|
|
30
30
|
|
|
31
|
+
function qualiaHome() {
|
|
32
|
+
if (process.env.QUALIA_HOME) return process.env.QUALIA_HOME;
|
|
33
|
+
const parent = path.basename(path.dirname(__dirname));
|
|
34
|
+
if (parent === ".codex" || parent === ".claude") return path.dirname(__dirname);
|
|
35
|
+
return path.join(os.homedir(), ".claude");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const QUALIA_HOME = qualiaHome();
|
|
39
|
+
|
|
31
40
|
function _trace(result, extra) {
|
|
32
41
|
try {
|
|
33
|
-
const traceDir = path.join(
|
|
42
|
+
const traceDir = path.join(QUALIA_HOME, ".qualia-traces");
|
|
34
43
|
if (!fs.existsSync(traceDir)) fs.mkdirSync(traceDir, { recursive: true });
|
|
35
44
|
const entry = {
|
|
36
45
|
hook: "git-guardrails",
|
package/hooks/migration-guard.js
CHANGED
|
@@ -56,7 +56,10 @@ function _trace(hookName, result, extra) {
|
|
|
56
56
|
try {
|
|
57
57
|
const os = require("os");
|
|
58
58
|
const path = require("path");
|
|
59
|
-
const
|
|
59
|
+
const parent = path.basename(path.dirname(__dirname));
|
|
60
|
+
const qualiaHome = process.env.QUALIA_HOME ||
|
|
61
|
+
(parent === ".codex" || parent === ".claude" ? path.dirname(__dirname) : path.join(os.homedir(), ".claude"));
|
|
62
|
+
const traceDir = path.join(qualiaHome, ".qualia-traces");
|
|
60
63
|
if (!fs.existsSync(traceDir)) fs.mkdirSync(traceDir, { recursive: true });
|
|
61
64
|
const entry = {
|
|
62
65
|
hook: hookName,
|
package/hooks/pre-deploy-gate.js
CHANGED
|
@@ -8,14 +8,24 @@
|
|
|
8
8
|
|
|
9
9
|
const fs = require("fs");
|
|
10
10
|
const path = require("path");
|
|
11
|
+
const os = require("os");
|
|
11
12
|
const { spawnSync } = require("child_process");
|
|
12
13
|
|
|
13
14
|
const _traceStart = Date.now();
|
|
14
15
|
|
|
16
|
+
function qualiaHome() {
|
|
17
|
+
if (process.env.QUALIA_HOME) return process.env.QUALIA_HOME;
|
|
18
|
+
const parent = path.basename(path.dirname(__dirname));
|
|
19
|
+
if (parent === ".codex" || parent === ".claude") return path.dirname(__dirname);
|
|
20
|
+
return path.join(os.homedir(), ".claude");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const QUALIA_HOME = qualiaHome();
|
|
24
|
+
|
|
15
25
|
function _trace(hookName, result, extra) {
|
|
16
26
|
try {
|
|
17
27
|
const os = require("os");
|
|
18
|
-
const traceDir = path.join(
|
|
28
|
+
const traceDir = path.join(QUALIA_HOME, ".qualia-traces");
|
|
19
29
|
if (!fs.existsSync(traceDir)) fs.mkdirSync(traceDir, { recursive: true });
|
|
20
30
|
const entry = {
|
|
21
31
|
hook: hookName,
|