chati-dev 4.3.0 → 4.3.1
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/bin/chati.js +20 -0
- package/framework/agents/build/dev.md +4 -4
- package/framework/agents/discover/brief.md +2 -0
- package/framework/agents/discover/brownfield-wu.md +2 -0
- package/framework/agents/discover/greenfield-wu.md +2 -0
- package/framework/agents/plan/detail.md +2 -0
- package/framework/agents/quality/qa-visual.md +9 -0
- package/framework/config.yaml +3 -3
- package/framework/data/entity-registry.yaml +2 -2
- package/framework/orchestrator/chati-router.js +58 -4
- package/framework/orchestrator/chati.md +1 -0
- package/framework/rules/human-writing-style.md +47 -0
- package/framework/scaffold/motion-premium/README.md +12 -2
- package/framework/scaffold/motion-premium/lib/animations/tokens.ts.template +1 -1
- package/framework/scaffold/motion-premium/scaffold.yaml +4 -0
- package/framework/scaffold/motion-premium-3d/README.md +10 -0
- package/framework/scaffold/motion-premium-3d/scaffold.yaml +3 -0
- package/framework/scripts/visual-qa.js +14 -2
- package/framework/templates/brandbook-html-tmpl.md +1 -1
- package/package.json +3 -2
- package/src/installer/core.js +11 -2
- package/src/orchestrator/cli.js +12 -1
- package/src/orchestrator/session-manager.js +8 -0
package/bin/chati.js
CHANGED
|
@@ -141,6 +141,26 @@ async function main() {
|
|
|
141
141
|
console.log(` Framework sync skipped: ${err.message}`);
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
// 2.6. Re-bundle CLI (Bug 4 part 3, v4.3.1+) — refreshes .chati.dev/_cli/
|
|
145
|
+
// and writes version.json so chati-router.js mismatch detection clears
|
|
146
|
+
// on the next invocation.
|
|
147
|
+
console.log(' Re-bundling CLI...');
|
|
148
|
+
try {
|
|
149
|
+
const { copyCliSource, copyCliDependencies } = await import('../src/installer/core.js');
|
|
150
|
+
const { writeFileSync } = await import('fs');
|
|
151
|
+
const fwDir = resolveFrameworkDir(targetDir);
|
|
152
|
+
const frameworkDir = join(targetDir, fwDir);
|
|
153
|
+
copyCliSource(join(__dirname, '..', 'src'), join(frameworkDir, '_cli'));
|
|
154
|
+
copyCliDependencies(join(__dirname, '..'), join(frameworkDir, '_cli', 'node_modules'));
|
|
155
|
+
writeFileSync(
|
|
156
|
+
join(frameworkDir, '_cli', 'version.json'),
|
|
157
|
+
JSON.stringify({ version: pkg.version, bundled_at: new Date().toISOString() }, null, 2),
|
|
158
|
+
);
|
|
159
|
+
console.log(' CLI re-bundled.');
|
|
160
|
+
} catch (err) {
|
|
161
|
+
console.log(` CLI rebundle skipped: ${err.message}`);
|
|
162
|
+
}
|
|
163
|
+
|
|
144
164
|
// 2.6. Detect tracked framework files and warn user (non-blocking)
|
|
145
165
|
try {
|
|
146
166
|
const { detectTrackedFrameworkFiles } = await import('../src/upgrade/tracked-files-detector.js');
|
|
@@ -105,7 +105,7 @@ The `motion-premium` scaffold preset (`scaffold/motion-premium/`) ships referenc
|
|
|
105
105
|
|
|
106
106
|
**Context**
|
|
107
107
|
|
|
108
|
-
Tailwind v4 is a major shift: the `@theme` block, CSS-first token declaration, Cascade Layers compilation, and arbitrary-value type inference all changed. The change introduced three silent-failure modes that pass `pnpm lint`, `pnpm typecheck`, and `pnpm build` with zero errors. One was caught by QA-Visual pixel inspection; two slipped past it and bit production in
|
|
108
|
+
Tailwind v4 is a major shift: the `@theme` block, CSS-first token declaration, Cascade Layers compilation, and arbitrary-value type inference all changed. The change introduced three silent-failure modes that pass `pnpm lint`, `pnpm typecheck`, and `pnpm build` with zero errors. One was caught by QA-Visual pixel inspection; two slipped past it and bit production in a reference-website case study. All three now have deterministic gates in qa-visual, but dev must avoid them at build time — fixing in code is cheaper than fixing under a correction loop.
|
|
109
109
|
|
|
110
110
|
**Decision**
|
|
111
111
|
|
|
@@ -142,7 +142,7 @@ Prefer the promoted Tailwind utilities (`text-xs..text-hero`, `bg-primary`, etc.
|
|
|
142
142
|
|
|
143
143
|
*Pitfall 2 — Unlayered global CSS defeats every utility.*
|
|
144
144
|
|
|
145
|
-
Tailwind v4 places utilities inside `@layer utilities`. Per CSS Cascade Layers (Cascade Level 5), *unlayered* CSS always wins over any named layer — regardless of selector specificity. A single global reset outside `@layer` silently overrides `mx-auto`, `px-*`, `flex`, everything. This broke container centering for a full day on
|
|
145
|
+
Tailwind v4 places utilities inside `@layer utilities`. Per CSS Cascade Layers (Cascade Level 5), *unlayered* CSS always wins over any named layer — regardless of selector specificity. A single global reset outside `@layer` silently overrides `mx-auto`, `px-*`, `flex`, everything. This broke container centering for a full day on a reference-website (a Tailwind v4 incident encountered in production) and was invisible at 1280px viewport — the x=0 container alignment only became visible at 1920px where lg:px-12 should have added padding but unlayered `* { margin: 0 }` outranked it.
|
|
146
146
|
|
|
147
147
|
WRONG — kills every Tailwind margin/padding utility:
|
|
148
148
|
```css
|
|
@@ -298,7 +298,7 @@ React 19 (stable since late 2024) introduced four patterns that improve ergonomi
|
|
|
298
298
|
|
|
299
299
|
**Context**
|
|
300
300
|
|
|
301
|
-
Lenis (virtualized smooth scroll) + GSAP + ScrollTrigger form the premium animation stack. Initialization order is load-bearing: wrong order produces silent bugs (tab-restore snap, ScrollTrigger positions measured against the native scrollbar instead of Lenis, drifting RAF clocks). The `motion-premium` scaffold encodes all 13 "sauce patterns" learned from
|
|
301
|
+
Lenis (virtualized smooth scroll) + GSAP + ScrollTrigger form the premium animation stack. Initialization order is load-bearing: wrong order produces silent bugs (tab-restore snap, ScrollTrigger positions measured against the native scrollbar instead of Lenis, drifting RAF clocks). The `motion-premium` scaffold encodes all 13 "sauce patterns" learned from a reference-website case study; this ADR names the canonical init sequence dev must preserve.
|
|
302
302
|
|
|
303
303
|
**Decision**
|
|
304
304
|
|
|
@@ -361,7 +361,7 @@ export async function initLenis() {
|
|
|
361
361
|
|
|
362
362
|
**Context**
|
|
363
363
|
|
|
364
|
-
Responsive design done wrong introduces a class of silent bugs that are invisible at 1280px and lethal at 1920px or 1200px. This ADR encodes the 12 principles learned from
|
|
364
|
+
Responsive design done wrong introduces a class of silent bugs that are invisible at 1280px and lethal at 1920px or 1200px. This ADR encodes the 12 principles learned from a reference-website case study. They are non-negotiable for premium UI tasks. Principles 1, 2, 3, 7, 10, and 12 are enforced structurally by the `motion-premium` scaffold; the remaining six are dev discipline that visual-qa validates.
|
|
365
365
|
|
|
366
366
|
**Decision**
|
|
367
367
|
|
|
@@ -559,6 +559,7 @@ domains:
|
|
|
559
559
|
required:
|
|
560
560
|
- constitution.yaml
|
|
561
561
|
- global.yaml
|
|
562
|
+
- rules/human-writing-style.md
|
|
562
563
|
- agents/brief.yaml
|
|
563
564
|
- artifacts/handoffs/greenfield-wu-handoff.md # or brownfield-wu-handoff.md
|
|
564
565
|
```
|
|
@@ -661,6 +662,7 @@ On failure:
|
|
|
661
662
|
6. Negative scope is mandatory - explicitly document what will NOT be built
|
|
662
663
|
7. Adapt question depth to user level (vibecoder = guided, power user = direct)
|
|
663
664
|
8. Maximum 5 interaction rounds before compiling brief draft
|
|
665
|
+
9. Apply `rules/human-writing-style.md` to brief-report.md prose, handoff Layer 1, conversation turns. Exempt: visual_references YAML, brief.yaml frontmatter, brief criteria tables.
|
|
664
666
|
|
|
665
667
|
---
|
|
666
668
|
|
|
@@ -377,6 +377,7 @@ domains:
|
|
|
377
377
|
required:
|
|
378
378
|
- constitution.yaml
|
|
379
379
|
- global.yaml
|
|
380
|
+
- rules/human-writing-style.md
|
|
380
381
|
- agents/brownfield-wu.yaml
|
|
381
382
|
```
|
|
382
383
|
|
|
@@ -474,6 +475,7 @@ On failure:
|
|
|
474
475
|
6. Treat all scout call findings as preliminary (agents will re-run in full mode later)
|
|
475
476
|
7. Preserve the user's terminology when documenting operational context
|
|
476
477
|
8. Flag security-sensitive patterns (hardcoded secrets, exposed endpoints) as CRITICAL
|
|
478
|
+
9. Apply `rules/human-writing-style.md` for all human-facing output (WU report prose, handoff Layer 1, user-facing conversation turns). Exempt: YAML blocks, tables, code, debt registry tables.
|
|
477
479
|
|
|
478
480
|
---
|
|
479
481
|
|
|
@@ -291,6 +291,7 @@ domains:
|
|
|
291
291
|
required:
|
|
292
292
|
- constitution.yaml
|
|
293
293
|
- global.yaml
|
|
294
|
+
- rules/human-writing-style.md
|
|
294
295
|
- agents/greenfield-wu.yaml
|
|
295
296
|
```
|
|
296
297
|
|
|
@@ -443,6 +444,7 @@ On failure:
|
|
|
443
444
|
3. Keep questions focused and progressive (don't ask everything at once)
|
|
444
445
|
4. Adapt question depth to user level (vibecoder = simpler, power user = technical)
|
|
445
446
|
5. Maximum 4 interaction rounds before generating report
|
|
447
|
+
6. Apply `rules/human-writing-style.md` for all human-facing output (WU report prose, handoff Layer 1, user-facing conversation turns). Exempt: YAML blocks, tables, scaffold_signals.
|
|
446
448
|
|
|
447
449
|
---
|
|
448
450
|
|
|
@@ -325,6 +325,7 @@ Rules:
|
|
|
325
325
|
|-------|--------|---------|
|
|
326
326
|
| L0 | `.chati/session.yaml` | Project type, current pipeline position, mode, agent statuses |
|
|
327
327
|
| L1 | `chati.dev/constitution.md` | Protocols, validation thresholds, handoff rules |
|
|
328
|
+
| L1.5 | `chati.dev/rules/human-writing-style.md` | Anti-AI prose rules for human-facing PRD sections |
|
|
328
329
|
| L2 | `artifacts/1-Brief/brief-report.md` | Problems, desired outcomes, constraints, target users |
|
|
329
330
|
| L3 | `artifacts/handoffs/brief-handoff.md` | Brief agent handoff with decisions and open questions |
|
|
330
331
|
|
|
@@ -388,6 +389,7 @@ Beyond self-validation (Protocol 5.1), the Detail agent enforces:
|
|
|
388
389
|
4. **NFR measurability**: Every non-functional requirement must include a measurable threshold (e.g., "response time < 200ms" not "fast response")
|
|
389
390
|
5. **Scope boundaries are bilateral**: Both in-scope AND out-of-scope must be explicitly defined - omitting out-of-scope is a validation failure
|
|
390
391
|
6. **Traceability is bidirectional**: Brief-to-PRD and PRD-to-Brief mappings must both exist with zero orphans in either direction
|
|
392
|
+
7. **Human writing style**: Apply `rules/human-writing-style.md` to Executive Summary, Goals, Target Users, and Scope narrative prose. Exempt: FR/NFR/BR tables, Given-When-Then criteria, Traceability Matrix.
|
|
391
393
|
|
|
392
394
|
---
|
|
393
395
|
|
|
@@ -26,6 +26,15 @@ You are the **QA-Visual Agent**, a specialized quality gate focused exclusively
|
|
|
26
26
|
## Required MCPs
|
|
27
27
|
- browser (Playwright MCP - mandatory, not optional)
|
|
28
28
|
|
|
29
|
+
## Gateway weight (v4.3.1+)
|
|
30
|
+
|
|
31
|
+
QA-Visual operates with two execution paths:
|
|
32
|
+
|
|
33
|
+
- **Strong gateway (default):** real Playwright screenshots. Required for full verdict authority — score reflects what users actually see.
|
|
34
|
+
- **Weak gateway (`gateway: WEAK`):** source-code analysis fallback when Playwright is unavailable (npm package missing OR chromium binary not installed). Score is capped below 90% to prevent fallback-only verdicts from clearing the threshold autonomously. The fallback exists as a backstop, not a primary path. When triggered, the report MUST surface `gateway: WEAK` so the human-in-the-loop knows the verdict is text-based and warrants extra scrutiny before advancing.
|
|
35
|
+
|
|
36
|
+
Action when fallback triggers: emit a recovery instruction in the QA report — `Run: npx playwright install chromium` (binary missing) or `Run: npm install playwright` (package missing). See visual-qa.js error disambiguation (lines ~373-385).
|
|
37
|
+
|
|
29
38
|
---
|
|
30
39
|
|
|
31
40
|
## Mission
|
package/framework/config.yaml
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# chati.dev Configuration
|
|
2
|
-
version: "4.3.
|
|
2
|
+
version: "4.3.1"
|
|
3
3
|
installed_at: "2026-02-07T10:00:00Z"
|
|
4
|
-
updated_at: "2026-04-
|
|
5
|
-
installer_version: "4.3.
|
|
4
|
+
updated_at: "2026-04-29T00:00:00Z"
|
|
5
|
+
installer_version: "4.3.1"
|
|
6
6
|
project_type: greenfield
|
|
7
7
|
language: en
|
|
8
8
|
ides: [claude-code]
|
|
@@ -28,6 +28,51 @@ const ROUTER_ARGS = process.argv.slice(2);
|
|
|
28
28
|
async function findCliModule(projectDir) {
|
|
29
29
|
// Resolve framework dir (.chati.dev/ or chati.dev/ for legacy)
|
|
30
30
|
const fwDir = existsSync(join(projectDir, '.chati.dev')) ? '.chati.dev' : 'chati.dev';
|
|
31
|
+
|
|
32
|
+
// --- VERSION MISMATCH DETECTION (v4.3.1+) ---
|
|
33
|
+
// G8: reset stale state from previous invocations within same process.
|
|
34
|
+
findCliModule._mismatch = null;
|
|
35
|
+
|
|
36
|
+
// Compare canonical version (chati.dev/config.yaml.installer_version) against
|
|
37
|
+
// installed bundle (.chati.dev/_cli/version.json). Pre-v4.3.1 installs lack
|
|
38
|
+
// version.json — silent skip (graceful degradation).
|
|
39
|
+
let installedVersion = null;
|
|
40
|
+
let bundledVersion = null;
|
|
41
|
+
try {
|
|
42
|
+
const configPath = join(projectDir, fwDir, 'config.yaml');
|
|
43
|
+
if (existsSync(configPath)) {
|
|
44
|
+
const raw = readFileSync(configPath, 'utf-8');
|
|
45
|
+
const m = raw.match(/^installer_version:\s*['"]?([^\s'"]+)/m);
|
|
46
|
+
installedVersion = m ? m[1] : null;
|
|
47
|
+
}
|
|
48
|
+
const versionStampPath = join(projectDir, fwDir, '_cli', 'version.json');
|
|
49
|
+
if (existsSync(versionStampPath)) {
|
|
50
|
+
bundledVersion = JSON.parse(readFileSync(versionStampPath, 'utf-8')).version;
|
|
51
|
+
}
|
|
52
|
+
if (installedVersion && bundledVersion && installedVersion !== bundledVersion) {
|
|
53
|
+
// G6: severity-aware warning. Major diff signals breaking schema/behavior changes.
|
|
54
|
+
const installedMajor = parseInt(String(installedVersion).split('.')[0], 10);
|
|
55
|
+
const bundledMajor = parseInt(String(bundledVersion).split('.')[0], 10);
|
|
56
|
+
const majorDiff =
|
|
57
|
+
!Number.isNaN(installedMajor) &&
|
|
58
|
+
!Number.isNaN(bundledMajor) &&
|
|
59
|
+
installedMajor !== bundledMajor;
|
|
60
|
+
const severityNote = majorDiff
|
|
61
|
+
? ' Major version change — review CHANGELOG before upgrading.'
|
|
62
|
+
: '';
|
|
63
|
+
process.stderr.write(
|
|
64
|
+
`[chati] WARNING: CLI bundle version (${bundledVersion}) ` +
|
|
65
|
+
`does not match installed framework (${installedVersion}).${severityNote} ` +
|
|
66
|
+
`Run: npx chati-dev upgrade\n`
|
|
67
|
+
);
|
|
68
|
+
findCliModule._mismatch = {
|
|
69
|
+
bundle: bundledVersion,
|
|
70
|
+
installed: installedVersion,
|
|
71
|
+
major_diff: majorDiff,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
} catch { /* non-critical — proceed to candidates loop */ }
|
|
75
|
+
|
|
31
76
|
const candidates = [
|
|
32
77
|
// PRIMARY: bundled CLI inside framework dir (self-contained install — no npx needed)
|
|
33
78
|
join(projectDir, fwDir, '_cli', 'orchestrator', 'cli.js'),
|
|
@@ -90,9 +135,11 @@ async function routeAdvance(agentName, score) {
|
|
|
90
135
|
|
|
91
136
|
try {
|
|
92
137
|
const cliMod = await findCliModule(PROJECT_DIR);
|
|
138
|
+
if (findCliModule._mismatch) result.version_mismatch = findCliModule._mismatch;
|
|
93
139
|
if (!cliMod) {
|
|
94
140
|
result.ok = false;
|
|
95
141
|
result.error = 'cli_module_not_found';
|
|
142
|
+
result.reason = 'Bundled CLI not found in .chati.dev/_cli/. Reinstall with: npx chati-dev upgrade';
|
|
96
143
|
return result;
|
|
97
144
|
}
|
|
98
145
|
|
|
@@ -174,16 +221,21 @@ function parseFlagArgs(argv) {
|
|
|
174
221
|
*/
|
|
175
222
|
async function dispatchOrchestrate(subCommand, argv) {
|
|
176
223
|
const cliMod = await findCliModule(PROJECT_DIR);
|
|
224
|
+
const mismatch = findCliModule._mismatch;
|
|
177
225
|
if (!cliMod) {
|
|
178
|
-
|
|
226
|
+
const out = {
|
|
179
227
|
ok: false,
|
|
180
228
|
action: 'error',
|
|
181
229
|
error: 'cli_module_not_found',
|
|
182
|
-
reason: 'Bundled CLI not found in .chati.dev/_cli/. Reinstall with: npx chati-dev
|
|
230
|
+
reason: 'Bundled CLI not found in .chati.dev/_cli/. Reinstall with: npx chati-dev upgrade',
|
|
183
231
|
};
|
|
232
|
+
if (mismatch) out.version_mismatch = mismatch;
|
|
233
|
+
return out;
|
|
184
234
|
}
|
|
185
235
|
try {
|
|
186
|
-
|
|
236
|
+
const result = await captureOrchestrate(cliMod, subCommand, argv, PROJECT_DIR);
|
|
237
|
+
if (mismatch && result && typeof result === 'object') result.version_mismatch = mismatch;
|
|
238
|
+
return result;
|
|
187
239
|
} catch (err) {
|
|
188
240
|
return {
|
|
189
241
|
ok: false,
|
|
@@ -327,9 +379,11 @@ async function main() {
|
|
|
327
379
|
// -----------------------------------------------------------------------
|
|
328
380
|
try {
|
|
329
381
|
const cliMod = await findCliModule(PROJECT_DIR);
|
|
382
|
+
if (findCliModule._mismatch) result.version_mismatch = findCliModule._mismatch;
|
|
330
383
|
if (!cliMod) {
|
|
331
384
|
result.action = 'error';
|
|
332
|
-
result.error = 'cli_module_not_found
|
|
385
|
+
result.error = 'cli_module_not_found';
|
|
386
|
+
result.reason = 'Bundled CLI missing in .chati.dev/_cli/. Reinstall with: npx chati-dev upgrade';
|
|
333
387
|
} else {
|
|
334
388
|
result.pipeline = await captureOrchestrate(cliMod, 'next', [], PROJECT_DIR);
|
|
335
389
|
result.action = result.pipeline.action;
|
|
@@ -104,6 +104,7 @@ Parse the JSON output. The `action` field tells you what to do:
|
|
|
104
104
|
| `user_preview` | Action: User Preview |
|
|
105
105
|
| `complete` | Action: Complete |
|
|
106
106
|
| `error` | Display error, suggest `/chati status` |
|
|
107
|
+
| `version_mismatch` (in any response) | "Your CLI bundle is out of date. Run `npx chati-dev upgrade` to fix." Display once per session, then continue. |
|
|
107
108
|
|
|
108
109
|
**Internal: track context bracket from JSON `context_bracket` but DO NOT display it to the user.** The bracket is internal telemetry - users should never see "Context: FRESH (90%)" or framework jargon like "Initiating handoff protocol". Speak in natural language about what you are doing, not the internal state.
|
|
109
110
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Human Writing Style — Anti-AI Guidelines
|
|
2
|
+
|
|
3
|
+
**Scope**: Apply to all human-facing outputs: WU reports, Briefs, PRDs, handoff Layer 1 summaries, conversation turns with the user.
|
|
4
|
+
**Exemption**: Tasks lists, JSON, YAML, code blocks, qa-*.md structured tables, Given-When-Then criteria — do NOT apply.
|
|
5
|
+
|
|
6
|
+
## Rules
|
|
7
|
+
|
|
8
|
+
### 1. No generic opening phrases
|
|
9
|
+
Do not open with "In today's fast-paced world", "In the ever-evolving landscape", "As we navigate", or any variant. Start with the subject matter directly.
|
|
10
|
+
|
|
11
|
+
### 2. No AI-favored filler verbs
|
|
12
|
+
Avoid: delve, leverage, facilitate, utilize, empower, harness. Use: use, help, run, build, drive, enable — only when the simpler word fits.
|
|
13
|
+
|
|
14
|
+
### 3. No rhetorical tricolons
|
|
15
|
+
Avoid: "not only X, but also Y, and Z", "robust, scalable, and maintainable". State the one thing that matters. Cut the rest.
|
|
16
|
+
|
|
17
|
+
### 4. No unnecessary hedging
|
|
18
|
+
Remove: "it's worth noting", "it's important to mention", "it should be noted", "one could argue", "arguably". If it is worth saying, say it directly.
|
|
19
|
+
|
|
20
|
+
### 5. No meta-closings
|
|
21
|
+
Remove: "In conclusion", "To summarize", "Overall", "Ultimately", "In summary". End on the last substantive point.
|
|
22
|
+
|
|
23
|
+
### 6. No sycophancy
|
|
24
|
+
Never open a response with "Great question!", "Excellent point!", "Absolutely!", or any approval of the user's input.
|
|
25
|
+
|
|
26
|
+
### 7. No performative bold
|
|
27
|
+
Do not bold words that carry no additional weight in context. Bold only genuine warnings, field labels, or terms the reader must not miss.
|
|
28
|
+
|
|
29
|
+
### 8. No robotic bullet parallelism
|
|
30
|
+
Bullet lists must not read as machine-generated triplets of the same syntactic form. Vary sentence length and structure. Mix noun phrases with full sentences where it reads better.
|
|
31
|
+
|
|
32
|
+
### 9. No negation-revelation pattern
|
|
33
|
+
Avoid: "This isn't just a dashboard — it's a command center." State what it is. Do not theatricalize via contrast.
|
|
34
|
+
|
|
35
|
+
### 10. No stacked generic adjectives
|
|
36
|
+
Avoid: "comprehensive, robust, scalable solution". Use the adjective only if it is specific and load-bearing. Remove the rest.
|
|
37
|
+
|
|
38
|
+
## Multilingual application
|
|
39
|
+
|
|
40
|
+
Framework supports en/pt/es/fr (Article VII). The English patterns above are EXEMPLARS, not exhaustive enumeration. When producing output in pt-BR / es / fr, apply the SAME PRINCIPLES to language-equivalent forms:
|
|
41
|
+
|
|
42
|
+
- Filler verbs: pt "elucidar / alavancar / facilitar"; es "profundizar / aprovechar / facilitar"; fr "approfondir / exploiter / faciliter"
|
|
43
|
+
- Generic openings: pt "No mundo atual em constante mudança"; es "En el mundo actual"; fr "Dans le monde d'aujourd'hui"
|
|
44
|
+
- Meta-closings: pt "Em conclusão / Em resumo"; es "En conclusión"; fr "En conclusion / Pour conclure"
|
|
45
|
+
- Sycophancy: pt "Ótima pergunta!"; es "¡Excelente pregunta!"; fr "Excellente question !"
|
|
46
|
+
|
|
47
|
+
Agent applies the principle to the target language; do not require literal translation of English examples.
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
# Motion Premium Scaffold — v1.0.0
|
|
2
2
|
|
|
3
|
-
Opinionated premium animation infrastructure for Next.js / React 18+ / Tailwind v4 projects. Ships the 13 non-negotiable sauce patterns + 12 responsive principles proven on reference implementations (
|
|
3
|
+
Opinionated premium animation infrastructure for Next.js / React 18+ / Tailwind v4 projects. Ships the 13 non-negotiable sauce patterns + 12 responsive principles proven on reference implementations (reference-website).
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
After `npm install`, run once to download the chromium browser binary used by QA-Visual screenshots:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx playwright install chromium
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Without this step, QA-Visual falls back to source-code analysis (gateway: WEAK) and skips screenshot-based gates.
|
|
4
14
|
|
|
5
15
|
## What this scaffold gives you
|
|
6
16
|
|
|
@@ -74,7 +84,7 @@ All 15 files listed above match `scaffold.yaml` `files[]` exactly.
|
|
|
74
84
|
- **Scaffold**: `motion-premium@1.0.0`
|
|
75
85
|
- **Requires framework**: chati.dev >= 4.3.0
|
|
76
86
|
- **Requires stack**: Next.js OR React Vite, Tailwind v4+, TypeScript 5+, React 18+, Node 18+
|
|
77
|
-
- **Reference implementation**: `
|
|
87
|
+
- **Reference implementation**: `reference-website` (all 13 sauce patterns verified in production)
|
|
78
88
|
|
|
79
89
|
## Upgrading
|
|
80
90
|
|
|
@@ -102,7 +102,7 @@ export type StaggerKey = keyof typeof STAGGERS;
|
|
|
102
102
|
// SCROLL_TRIGGER_DEFAULTS — common trigger start/end strings
|
|
103
103
|
// The GSAP "top 80%" syntax means: "fire when element's top is at 80% down
|
|
104
104
|
// the viewport". Defaults here encode the weight/timing recommendations
|
|
105
|
-
// from the reference implementation (
|
|
105
|
+
// from the reference implementation (reference-website) — they produce the
|
|
106
106
|
// signature feel of the premium pattern set.
|
|
107
107
|
// -----------------------------------------------------------------------
|
|
108
108
|
export const SCROLL_TRIGGER_DEFAULTS = {
|
|
@@ -27,6 +27,10 @@ stack:
|
|
|
27
27
|
gsap: "^3.12.5"
|
|
28
28
|
"framer-motion": "^11.0.0"
|
|
29
29
|
lenis: "^1.1.0"
|
|
30
|
+
# v4.3.1+: Playwright required for QA-Visual screenshot-based gate.
|
|
31
|
+
# Without it, visual-qa.js falls back to source-code analysis (gateway: WEAK).
|
|
32
|
+
# Run `npx playwright install chromium` once after npm install for the binary.
|
|
33
|
+
playwright: "^1.44.0"
|
|
30
34
|
|
|
31
35
|
# Placeholder resolution — keys reference brand source fields.
|
|
32
36
|
# Resolved once at scaffold apply time (Decision 3: install-time, one-shot).
|
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
React Three Fiber + Three.js scroll-driven 3D layer for premium sites. Extends `motion-premium` — apply that one FIRST (the 2D base), then this one on top.
|
|
4
4
|
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
After `npm install`, run once to download the chromium browser binary used by QA-Visual screenshots:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx playwright install chromium
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
QA-Visual Phase 3c uses real browser screenshots to count `canvas_hosts` and `scene_fallbacks` in the rendered DOM. Without chromium, R3F visual QA is blind.
|
|
14
|
+
|
|
5
15
|
## When to apply
|
|
6
16
|
|
|
7
17
|
Apply when the project brief or Animation Inventory cites **explicit 3D intent**:
|
|
@@ -33,6 +33,9 @@ stack:
|
|
|
33
33
|
# but also declares the dep so a standalone apply (no motion-premium first)
|
|
34
34
|
# still has an accurate peer-dep surface.
|
|
35
35
|
gsap: "^3.12.5"
|
|
36
|
+
# v4.3.1+: Playwright required for QA-Visual canvas_hosts + scene_fallbacks
|
|
37
|
+
# checks (Phase 3c). Without it, R3F visual QA is blind (canvas not screenshotted).
|
|
38
|
+
playwright: "^1.44.0"
|
|
36
39
|
|
|
37
40
|
# Inherits motion-premium's brand placeholders — at apply time the loader
|
|
38
41
|
# resolves identically (brand.ts > brandbook.md > interactive). SceneFallback
|
|
@@ -370,8 +370,20 @@ async function main() {
|
|
|
370
370
|
if (chromium) break;
|
|
371
371
|
} catch { /* try next */ }
|
|
372
372
|
}
|
|
373
|
-
if (!chromium)
|
|
374
|
-
|
|
373
|
+
if (!chromium) {
|
|
374
|
+
// v4.3.1+ G17: disambiguate npm-package-missing from binary-missing for actionable hints
|
|
375
|
+
throw new Error('Playwright npm package missing. Run: npm install playwright');
|
|
376
|
+
}
|
|
377
|
+
let browser;
|
|
378
|
+
try {
|
|
379
|
+
browser = await chromium.launch({ headless: true });
|
|
380
|
+
} catch (e) {
|
|
381
|
+
if (e.message.includes("Executable doesn't exist")
|
|
382
|
+
|| e.message.includes('browserType.launch')) {
|
|
383
|
+
throw new Error('Chromium binary missing. Run: npx playwright install chromium');
|
|
384
|
+
}
|
|
385
|
+
throw e;
|
|
386
|
+
}
|
|
375
387
|
const report = { pages: [], summary: {} };
|
|
376
388
|
|
|
377
389
|
for (const pagePath of pages) {
|
|
@@ -103,5 +103,5 @@ sections must exist and what each must contain.
|
|
|
103
103
|
|
|
104
104
|
## Reference
|
|
105
105
|
|
|
106
|
-
See
|
|
106
|
+
See `<your-project>/docs/brand/brandbook.html` for a production
|
|
107
107
|
example with 14 sections, sticky nav, dark mode toggle, and complete token rendering.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chati-dev",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.1",
|
|
4
4
|
"description": "AI-Powered Multi-Agent Orchestration System - Structured vibe coding for Full Stack Development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"prepublishOnly": "node scripts/sync-framework.js && node scripts/scan-stale.js && node scripts/validate-package.js && node scripts/sign-manifest.js",
|
|
33
33
|
"test": "node --test test/**/*.test.js",
|
|
34
34
|
"lint": "eslint src/ bin/",
|
|
35
|
-
"lint:fix": "eslint src/ bin/ --fix"
|
|
35
|
+
"lint:fix": "eslint src/ bin/ --fix",
|
|
36
|
+
"verify-v431": "npm test && node scripts/scan-stale.js && npm run sync && node scripts/validate-package.js && node test/fixtures/manual-smoke-v430-upgrade.mjs"
|
|
36
37
|
},
|
|
37
38
|
"keywords": [
|
|
38
39
|
"ai",
|
package/src/installer/core.js
CHANGED
|
@@ -147,6 +147,15 @@ export async function installFramework(config) {
|
|
|
147
147
|
join(frameworkDir, '_cli', 'node_modules') // .chati.dev/_cli/node_modules/
|
|
148
148
|
);
|
|
149
149
|
|
|
150
|
+
// v4.3.1+ — Write version stamp so chati-router.js can detect bundle/canonical
|
|
151
|
+
// mismatch on subsequent invocations. Pre-v4.3.1 installs lack this file;
|
|
152
|
+
// mismatch detection silent-skips when it's missing (graceful degradation).
|
|
153
|
+
writeFileSync(
|
|
154
|
+
join(frameworkDir, '_cli', 'version.json'),
|
|
155
|
+
JSON.stringify({ version, bundled_at: new Date().toISOString() }, null, 2),
|
|
156
|
+
'utf-8'
|
|
157
|
+
);
|
|
158
|
+
|
|
150
159
|
// Write config.yaml
|
|
151
160
|
writeFileSync(
|
|
152
161
|
join(frameworkDir, 'config.yaml'),
|
|
@@ -701,7 +710,7 @@ function createDir(dir) {
|
|
|
701
710
|
* Used to bundle the CLI source into the user's .chati.dev/_cli/ folder so
|
|
702
711
|
* the framework runs self-contained (no `npx chati-dev` dependency).
|
|
703
712
|
*/
|
|
704
|
-
function copyCliSource(srcDir, destDir) {
|
|
713
|
+
export function copyCliSource(srcDir, destDir) {
|
|
705
714
|
if (!existsSync(srcDir)) return;
|
|
706
715
|
createDir(destDir);
|
|
707
716
|
const entries = readdirSync(srcDir);
|
|
@@ -748,7 +757,7 @@ function copyDirVerbatim(srcDir, destDir) {
|
|
|
748
757
|
* which works whether the package is hoisted or nested in the user's
|
|
749
758
|
* node_modules (npx cache, npm install, etc.).
|
|
750
759
|
*/
|
|
751
|
-
function copyCliDependencies(pkgDir, destNodeModules) {
|
|
760
|
+
export function copyCliDependencies(pkgDir, destNodeModules) {
|
|
752
761
|
let pkg;
|
|
753
762
|
try {
|
|
754
763
|
pkg = JSON.parse(readFileSync(join(pkgDir, 'package.json'), 'utf-8'));
|
package/src/orchestrator/cli.js
CHANGED
|
@@ -634,6 +634,17 @@ function writeSessionLock(projectDir, currentAgent, stateInfo = {}) {
|
|
|
634
634
|
const localMdPath = join(projectDir, 'CLAUDE.local.md');
|
|
635
635
|
let content = existsSync(localMdPath) ? readFileSync(localMdPath, 'utf-8') : '';
|
|
636
636
|
|
|
637
|
+
// Phase display is authoritatively driven by session.mode on disk. Callers
|
|
638
|
+
// previously passed stateInfo.phase derived from transient intermediate
|
|
639
|
+
// values (the next agent's expected phase before user approval), causing
|
|
640
|
+
// the lock to drift ahead of session.yaml (e.g. show "build" while
|
|
641
|
+
// session.mode was still "plan" awaiting approval).
|
|
642
|
+
let authoritativePhase = null;
|
|
643
|
+
try {
|
|
644
|
+
const { loaded, session } = loadSession(projectDir);
|
|
645
|
+
if (loaded && session?.mode) authoritativePhase = session.mode;
|
|
646
|
+
} catch { /* non-fatal — fall back to stateInfo */ }
|
|
647
|
+
|
|
637
648
|
const lockInner = `## Session Lock -- ACTIVE
|
|
638
649
|
|
|
639
650
|
**Chati.dev session is ACTIVE.** Follow these rules for EVERY message:
|
|
@@ -645,7 +656,7 @@ function writeSessionLock(projectDir, currentAgent, stateInfo = {}) {
|
|
|
645
656
|
|
|
646
657
|
const stateInner = `## Current State
|
|
647
658
|
- **Agent**: ${currentAgent || 'None'}
|
|
648
|
-
- **Phase**: ${stateInfo.phase || 'discover'}
|
|
659
|
+
- **Phase**: ${authoritativePhase || stateInfo.phase || 'discover'}
|
|
649
660
|
- **Pipeline**: ${stateInfo.position ?? 0}/${stateInfo.total ?? '?'} (${stateInfo.progress ?? 0}%)
|
|
650
661
|
- **Mode**: ${stateInfo.mode || 'interactive'}`;
|
|
651
662
|
|
|
@@ -171,6 +171,14 @@ export function migrateSession(session) {
|
|
|
171
171
|
const fromVersion = session.schema_version || null;
|
|
172
172
|
session.schema_version = CURRENT_SCHEMA_VERSION;
|
|
173
173
|
|
|
174
|
+
// Seed required scalar fields absent from pre-v4.3.0 sessions.
|
|
175
|
+
// validateSession() requires version/mode/project_type; older sessions may lack them.
|
|
176
|
+
// Without these guards, upgrade-path catastrophe (data-centralisation E2E 2026-04-28):
|
|
177
|
+
// v3.x install → v4.3.0 migrate adds schema_version: '1.2' but validator fails on missing fields.
|
|
178
|
+
if (!session.version) session.version = '1.0';
|
|
179
|
+
if (!session.mode) session.mode = 'discover';
|
|
180
|
+
if (!session.project_type) session.project_type = session.project?.type || 'greenfield';
|
|
181
|
+
|
|
174
182
|
// Ensure fields added in v1.0 exist
|
|
175
183
|
if (!session.completed_agents) session.completed_agents = [];
|
|
176
184
|
if (!session.agent_results) session.agent_results = {};
|