dreative 0.5.2 → 0.5.4
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/dist/cli/audit.js +87 -11
- package/dist/cli/audit.test.js +40 -1
- package/dist/cli/docsCheck.js +1 -1
- package/dist/server/index.js +10 -5
- package/dist/shared/artifacts.js +157 -4
- package/dist/shared/artifacts.test.js +101 -0
- package/dist/shared/design.js +212 -26
- package/dist/shared/design.test.js +70 -0
- package/dist/shared/ruleSystem.js +101 -11
- package/dist/shared/ruleSystem.test.js +94 -19
- package/dist/ui/assets/{index-CKwmbx2j.js → index-BQhYTdSa.js} +11 -11
- package/dist/ui/index.html +1 -1
- package/package.json +5 -5
- package/skill/dreative/DESIGN.md +47 -35
- package/skill/dreative/PLAN.md +97 -55
- package/skill/dreative/SKILL.md +35 -12
- package/skill/dreative/recipes/motion-recipes.md +24 -0
- package/skill/dreative/references/ARTIFACTS.md +52 -18
- package/skill/dreative/references/RULES.json +9 -9
- package/skill/dreative/references/TIERS.md +14 -6
- package/skill/dreative/schemas/plan.schema.json +161 -11
- package/skill/dreative/schemas/verify.schema.json +22 -2
- package/skill/dreative/skills/media.md +28 -14
- package/skill/dreative/skills/mobile.md +19 -13
- package/skill/dreative/skills/motion.md +45 -8
|
@@ -33,6 +33,20 @@ function basePlan(tier = "award") {
|
|
|
33
33
|
mechanisms: ["variable-type morph", "depth-stack", "drag-inertia", "mask-dissolve"],
|
|
34
34
|
drivers: ["scroll", "pointer", "time"],
|
|
35
35
|
},
|
|
36
|
+
motionComplexityBudget: {
|
|
37
|
+
heroMoments: [{ sectionId: "hero", reason: "The archival specimen becomes the navigation system and establishes the living-catalog concept." }],
|
|
38
|
+
calmSectionIds: [],
|
|
39
|
+
sharedLanguage: "Archival sheets fold, align, and become structural boundaries across the journey.",
|
|
40
|
+
deviceLimits: "Desktop uses the full pinned chapter while mobile shortens travel and removes continuous rendering.",
|
|
41
|
+
progressiveEnhancement: "Semantic catalog content renders first; masks and synchronized motion enhance it when supported.",
|
|
42
|
+
antiDefaultReview: {
|
|
43
|
+
basicMotionAssessment: "The key specimen changes role and geometry rather than only fading, sliding, or scaling.",
|
|
44
|
+
compositionHandoff: "The specimen edge becomes the next chapter's indexing rail instead of disappearing.",
|
|
45
|
+
visualStateChange: "Loose sheets become navigation, a research surface, and then the closing mark.",
|
|
46
|
+
conceptSpecificity: "The sheet behavior is derived from archival handling and would not fit an unrelated product.",
|
|
47
|
+
memorableMoment: "Dragging the specimen reorganizes the complete catalog into the next chapter.",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
36
50
|
pages: [
|
|
37
51
|
{
|
|
38
52
|
id: "home",
|
|
@@ -45,6 +59,19 @@ function basePlan(tier = "award") {
|
|
|
45
59
|
layoutFamily: "archival-index",
|
|
46
60
|
skills: ["ux", "mobile", "motion", "media"],
|
|
47
61
|
interactions: ["drag specimen"],
|
|
62
|
+
motionTreatment: {
|
|
63
|
+
class: "transformational",
|
|
64
|
+
staticComposition: "A loose archival specimen sits beside the catalog index.",
|
|
65
|
+
startState: "The specimen is centered and isolated as the page's primary subject.",
|
|
66
|
+
endState: "The specimen unfolds into the structural rail for the next catalog chapter.",
|
|
67
|
+
changes: ["The specimen mask expands and its edge becomes the next chapter rail."],
|
|
68
|
+
pinnedElements: [],
|
|
69
|
+
handoff: "The specimen edge persists as the indexing rail in the following composition.",
|
|
70
|
+
purpose: "Turn passive archival viewing into active handling and establish continuity.",
|
|
71
|
+
mechanism: "SVG mask migration synchronized with a GSAP scroll timeline.",
|
|
72
|
+
mobile: "A shorter clip-path handoff preserves the specimen-to-rail transformation.",
|
|
73
|
+
reducedMotion: "Render the specimen already aligned with the rail and use a direct section cut.",
|
|
74
|
+
},
|
|
48
75
|
mobile: "stacked specimen",
|
|
49
76
|
fallback: "static catalog",
|
|
50
77
|
verification: ["Signature responds to input"],
|
|
@@ -59,41 +86,59 @@ function basePlan(tier = "award") {
|
|
|
59
86
|
};
|
|
60
87
|
}
|
|
61
88
|
function verification(...ids) {
|
|
89
|
+
const timelineStates = ["initial", "early", "mid-transition", "final", "handoff", "mobile", "reduced-motion"];
|
|
90
|
+
const timeline = timelineStates.map((timelineState) => ({
|
|
91
|
+
id: `timeline-${timelineState}`,
|
|
92
|
+
criterion: `Captured ${timelineState} visual state`,
|
|
93
|
+
status: "pass",
|
|
94
|
+
evidence: "Captured the production build at the planned visual state.",
|
|
95
|
+
timelineState,
|
|
96
|
+
proof: { timestamp: started, testedUrl: "http://localhost:3000", consoleErrorCount: 0 },
|
|
97
|
+
}));
|
|
62
98
|
return {
|
|
63
99
|
version: 1,
|
|
64
100
|
generatedAt: started,
|
|
65
|
-
evidence:
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
101
|
+
evidence: [
|
|
102
|
+
...timeline,
|
|
103
|
+
...ids.map((id) => ({
|
|
104
|
+
id,
|
|
105
|
+
criterion: id,
|
|
106
|
+
status: "pass",
|
|
107
|
+
evidence: "Captured runtime behavior in the production build.",
|
|
108
|
+
proof: { timestamp: started, testedUrl: "http://localhost:3000", consoleErrorCount: 0 },
|
|
109
|
+
})),
|
|
110
|
+
],
|
|
111
|
+
refinement: {
|
|
112
|
+
inspectedAt: started,
|
|
113
|
+
findings: ["The mid-transition index was too compressed to read."],
|
|
114
|
+
changes: ["Extended the mask handoff and delayed the rail compression."],
|
|
115
|
+
evidenceIds: ["timeline-mid-transition"],
|
|
116
|
+
},
|
|
72
117
|
};
|
|
73
118
|
}
|
|
74
119
|
test("valid default award plan", () => {
|
|
75
120
|
assert.deepEqual(validateRuleControls(basePlan(), registry, reflex, verification()), []);
|
|
76
121
|
});
|
|
77
|
-
test("valid
|
|
122
|
+
test("valid key-asset substitution for a typography-only experience", () => {
|
|
78
123
|
const plan = basePlan();
|
|
79
124
|
plan.ruleExceptions = [
|
|
80
125
|
{
|
|
81
|
-
ruleId: "
|
|
126
|
+
ruleId: "media.keyAssetTreatment",
|
|
82
127
|
decision: "substituted",
|
|
83
128
|
declaredAt: planned,
|
|
84
|
-
reason: "The
|
|
85
|
-
alternative: "A persistent variable-type specimen becomes index, spatial architecture, and interactive control across
|
|
86
|
-
successCriteria: ["The specimen appears in
|
|
87
|
-
evidenceIds: ["
|
|
129
|
+
reason: "The archive contains no raster key imagery; inventing photography would misrepresent the supplied typographic material.",
|
|
130
|
+
alternative: "A persistent variable-type specimen becomes index, spatial architecture, and interactive control across the complete journey.",
|
|
131
|
+
successCriteria: ["The specimen appears in materially different structural roles", "Pointer and scroll input visibly reshape the specimen"],
|
|
132
|
+
evidenceIds: ["type-system-desktop", "type-system-mobile"],
|
|
88
133
|
},
|
|
89
134
|
];
|
|
90
|
-
assert.deepEqual(validateRuleControls(plan, registry, reflex, verification("
|
|
135
|
+
assert.deepEqual(validateRuleControls(plan, registry, reflex, verification("type-system-desktop", "type-system-mobile")), []);
|
|
91
136
|
});
|
|
92
|
-
test("invalid vague
|
|
137
|
+
test("invalid vague creative-rule exception", () => {
|
|
93
138
|
const plan = basePlan();
|
|
94
139
|
plan.ruleExceptions = [
|
|
95
140
|
{
|
|
96
|
-
ruleId: "
|
|
141
|
+
ruleId: "media.keyAssetTreatment",
|
|
97
142
|
decision: "substituted",
|
|
98
143
|
declaredAt: planned,
|
|
99
144
|
reason: "It did not fit",
|
|
@@ -135,11 +180,41 @@ test("valid development plan", () => {
|
|
|
135
180
|
};
|
|
136
181
|
assert.deepEqual(validateRuleControls(plan, registry, reflex, verification()), []);
|
|
137
182
|
});
|
|
138
|
-
test("invalid
|
|
183
|
+
test("invalid decorative-only expressive plan", () => {
|
|
139
184
|
const plan = basePlan();
|
|
140
|
-
plan.
|
|
185
|
+
plan.pages[0].sections[0].motionTreatment = {
|
|
186
|
+
...plan.pages[0].sections[0].motionTreatment,
|
|
187
|
+
class: "decorative",
|
|
188
|
+
changes: ["The image fades upward and scales into view."],
|
|
189
|
+
mechanism: "CSS opacity, translateY, and scale transitions on scroll reveal.",
|
|
190
|
+
};
|
|
141
191
|
const errors = validateRuleControls(plan, registry, reflex, verification());
|
|
142
|
-
assert.ok(errors.some((error) => error.includes("
|
|
192
|
+
assert.ok(errors.some((error) => error.includes("decorative-only")));
|
|
193
|
+
});
|
|
194
|
+
test("expressive plan requires contextual motion budget", () => {
|
|
195
|
+
const plan = basePlan("expressive");
|
|
196
|
+
delete plan.motionComplexityBudget;
|
|
197
|
+
assert.ok(validateRuleControls(plan, registry, reflex, verification()).some((error) => error.includes("motionComplexityBudget")));
|
|
198
|
+
});
|
|
199
|
+
test("award verification requires timeline states and a refinement pass", () => {
|
|
200
|
+
const plan = basePlan();
|
|
201
|
+
const report = {
|
|
202
|
+
version: 1,
|
|
203
|
+
generatedAt: started,
|
|
204
|
+
evidence: [
|
|
205
|
+
{
|
|
206
|
+
id: "initial-only",
|
|
207
|
+
criterion: "Initial state",
|
|
208
|
+
status: "pass",
|
|
209
|
+
evidence: "Captured only the initial frame.",
|
|
210
|
+
timelineState: "initial",
|
|
211
|
+
proof: { timestamp: started, testedUrl: "http://localhost:3000", consoleErrorCount: 0 },
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
};
|
|
215
|
+
const errors = validateRuleControls(plan, registry, reflex, report);
|
|
216
|
+
assert.ok(errors.some((error) => error.includes("mid-transition")));
|
|
217
|
+
assert.ok(errors.some((error) => error.includes("refinement pass")));
|
|
143
218
|
});
|
|
144
219
|
test("valid reflex-font justification", () => {
|
|
145
220
|
const plan = basePlan("premium");
|