@devfellowship/components 3.2.0 → 3.2.2
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.js +362 -360
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -47,415 +47,417 @@ import Ajv2020 from "ajv/dist/2020.js";
|
|
|
47
47
|
import addFormats from "ajv-formats";
|
|
48
48
|
import chalk2 from "chalk";
|
|
49
49
|
|
|
50
|
-
//
|
|
51
|
-
var
|
|
52
|
-
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
53
|
-
$id: "https://raw.githubusercontent.com/devfellowship/dfl-ux-paths/main/schema/v1.json",
|
|
54
|
-
title: "DFL UX Paths v1",
|
|
55
|
-
description: "Versioned per-app user-flow JSON schema for migration-gap analysis and dead-code detection. Accepts schema_version 1.0.0, 1.1.0, 1.2.0 and 1.3.0 (all additive \u2014 v1.1 adds optional navigation/prereq/test_metadata fields; v1.2 adds optional source_ref (screen\u2192repo file) and screenshots[] (per platform\xD7orientation), and documents `route` as the canonical shared route nomenclature for 1:1 cross-app mapping; v1.3 adds optional source (build|spec), phases[], and phase/description on screen and flow, so the format can also describe a product that has not been built yet. Backward compatible \u2014 v1.0/v1.1/v1.2 files still validate).",
|
|
56
|
-
$comment: "schema v1.2 \u2014 additive over v1.1. New optional screen fields: source_ref { component_file, file_path_chain? } links a screen to the repo file(s) that render it (Figma-Code-Connect style); screenshots[] { platform, orientation, viewport?, url, captured_at? } captures rendered images per platform\xD7orientation for vision-first comparison. `screen.id` is the STICKY 1:1 JOIN KEY across apps \u2014 comparators pair screens by shared id. `route` is the canonical shared route nomenclature (e.g. studio/project/:id/editor) letting two apps map 1:1 by the same name even when their real URLs differ. Draft 2020-12. The file `$id` is intentionally unchanged across additive bumps so consumers pinned to the canonical URL keep working. || schema v1.3 \u2014 additive over v1.2, and the first bump aimed at files authored BEFORE the code exists. `source: \"spec\"` says so explicitly: routes are proposed nomenclature, app_version carries the zero-sha `init` emits, and the absence of source_ref/screenshots/base_url is correct rather than incomplete. `phases[]` declares the app's delivery-phase vocabulary once; `screen.phase` / `flow.phase` reference a phase id. That pair is what lets a viewer render committed scope differently from work the requirement explicitly parks (`phases[].optional: true`) instead of showing one undifferentiated blob \u2014 the distinction a client reads as 'what am I actually getting'. `screen.description` / `flow.description` carry the prose a spec needs and a generated-from-code file usually does not.",
|
|
57
|
-
type: "object",
|
|
58
|
-
required: ["schema_version", "app_id", "app_version", "screens", "flows"],
|
|
59
|
-
additionalProperties: false,
|
|
60
|
-
properties: {
|
|
61
|
-
schema_version: {
|
|
62
|
-
type: "string",
|
|
63
|
-
enum: ["1.0.0", "1.1.0", "1.2.0", "1.3.0"],
|
|
64
|
-
description: "Version of the dfl-ux-paths schema this file conforms to. v1.1.0 adds optional navigation_path, prerequisites, test_metadata, and richer flow step objects. v1.2.0 adds optional screen.source_ref (screen\u2192repo file link) and screen.screenshots[] (per platform\xD7orientation), and documents `route` as the canonical shared route nomenclature for 1:1 cross-app mapping. v1.3.0 adds optional spec-first authoring fields: top-level `source` (build|spec) and `phases[]`, plus optional `phase`/`description` on screens and flows."
|
|
50
|
+
// node_modules/@devfellowship/ux-paths-spec/dist/schema.generated.js
|
|
51
|
+
var SCHEMA_V1 = {
|
|
52
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
53
|
+
"$id": "https://raw.githubusercontent.com/devfellowship/dfl-ux-paths/main/schema/v1.json",
|
|
54
|
+
"title": "DFL UX Paths v1",
|
|
55
|
+
"description": "Versioned per-app user-flow JSON schema for migration-gap analysis and dead-code detection. Accepts schema_version 1.0.0, 1.1.0, 1.2.0 and 1.3.0 (all additive \u2014 v1.1 adds optional navigation/prereq/test_metadata fields; v1.2 adds optional source_ref (screen\u2192repo file) and screenshots[] (per platform\xD7orientation), and documents `route` as the canonical shared route nomenclature for 1:1 cross-app mapping; v1.3 adds optional source (build|spec), phases[], and phase/description on screen and flow, so the format can also describe a product that has not been built yet. Backward compatible \u2014 v1.0/v1.1/v1.2 files still validate).",
|
|
56
|
+
"$comment": "schema v1.2 \u2014 additive over v1.1. New optional screen fields: source_ref { component_file, file_path_chain? } links a screen to the repo file(s) that render it (Figma-Code-Connect style); screenshots[] { platform, orientation, viewport?, url, captured_at? } captures rendered images per platform\xD7orientation for vision-first comparison. `screen.id` is the STICKY 1:1 JOIN KEY across apps \u2014 comparators pair screens by shared id. `route` is the canonical shared route nomenclature (e.g. studio/project/:id/editor) letting two apps map 1:1 by the same name even when their real URLs differ. Draft 2020-12. The file `$id` is intentionally unchanged across additive bumps so consumers pinned to the canonical URL keep working. || schema v1.3 \u2014 additive over v1.2, and the first bump aimed at files authored BEFORE the code exists. `source: \"spec\"` says so explicitly: routes are proposed nomenclature, app_version carries the zero-sha `init` emits, and the absence of source_ref/screenshots/base_url is correct rather than incomplete. `phases[]` declares the app's delivery-phase vocabulary once; `screen.phase` / `flow.phase` reference a phase id. That pair is what lets a viewer render committed scope differently from work the requirement explicitly parks (`phases[].optional: true`) instead of showing one undifferentiated blob \u2014 the distinction a client reads as 'what am I actually getting'. `screen.description` / `flow.description` carry the prose a spec needs and a generated-from-code file usually does not.",
|
|
57
|
+
"type": "object",
|
|
58
|
+
"required": ["schema_version", "app_id", "app_version", "screens", "flows"],
|
|
59
|
+
"additionalProperties": false,
|
|
60
|
+
"properties": {
|
|
61
|
+
"schema_version": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"enum": ["1.0.0", "1.1.0", "1.2.0", "1.3.0"],
|
|
64
|
+
"description": "Version of the dfl-ux-paths schema this file conforms to. v1.1.0 adds optional navigation_path, prerequisites, test_metadata, and richer flow step objects. v1.2.0 adds optional screen.source_ref (screen\u2192repo file link) and screen.screenshots[] (per platform\xD7orientation), and documents `route` as the canonical shared route nomenclature for 1:1 cross-app mapping. v1.3.0 adds optional spec-first authoring fields: top-level `source` (build|spec) and `phases[]`, plus optional `phase`/`description` on screens and flows."
|
|
65
65
|
},
|
|
66
|
-
app_id: {
|
|
67
|
-
type: "string",
|
|
68
|
-
minLength: 1,
|
|
69
|
-
description: "Stable identifier for the app (e.g. 'dfl-learn-mobile')."
|
|
66
|
+
"app_id": {
|
|
67
|
+
"type": "string",
|
|
68
|
+
"minLength": 1,
|
|
69
|
+
"description": "Stable identifier for the app (e.g. 'dfl-learn-mobile')."
|
|
70
70
|
},
|
|
71
|
-
app_version: {
|
|
72
|
-
type: "string",
|
|
73
|
-
pattern: "^\\d{4}-\\d{2}-\\d{2}-[0-9a-f]{4,40}$",
|
|
74
|
-
description: 'App build identifier in the form YYYY-MM-DD-<git-sha-short>. A file authored before any build exists uses the zero-sha form `YYYY-MM-DD-0000000` that `dfl-ux-paths init` already emits, and should also set `source: "spec"`.'
|
|
71
|
+
"app_version": {
|
|
72
|
+
"type": "string",
|
|
73
|
+
"pattern": "^\\d{4}-\\d{2}-\\d{2}-[0-9a-f]{4,40}$",
|
|
74
|
+
"description": 'App build identifier in the form YYYY-MM-DD-<git-sha-short>. A file authored before any build exists uses the zero-sha form `YYYY-MM-DD-0000000` that `dfl-ux-paths init` already emits, and should also set `source: "spec"`.'
|
|
75
75
|
},
|
|
76
|
-
source: {
|
|
77
|
-
type: "string",
|
|
78
|
-
enum: ["build", "spec"],
|
|
79
|
-
description: "v1.3 \u2014 provenance of this file. 'build' (the assumed default when omitted) means it was derived from a shipped build, so `route` values are real and source_ref/screenshots are meaningful. 'spec' means it was authored from a requirement document before the code exists: routes are PROPOSED nomenclature, app_version carries a zero-sha, and the absence of source_ref/screenshots/test_metadata.base_url is expected rather than a gap. Optional, additive."
|
|
76
|
+
"source": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"enum": ["build", "spec"],
|
|
79
|
+
"description": "v1.3 \u2014 provenance of this file. 'build' (the assumed default when omitted) means it was derived from a shipped build, so `route` values are real and source_ref/screenshots are meaningful. 'spec' means it was authored from a requirement document before the code exists: routes are PROPOSED nomenclature, app_version carries a zero-sha, and the absence of source_ref/screenshots/test_metadata.base_url is expected rather than a gap. Optional, additive."
|
|
80
80
|
},
|
|
81
|
-
phases: {
|
|
82
|
-
type: "array",
|
|
83
|
-
items: { $ref: "#/$defs/phase" },
|
|
84
|
-
description: "v1.3 \u2014 the app's delivery-phase vocabulary, declared once and referenced by `screen.phase` / `flow.phase`. Phase ids are free-form on purpose (every product names its phases differently). Mark a phase `optional: true` when the requirement explicitly parks it outside committed scope. Optional, additive."
|
|
81
|
+
"phases": {
|
|
82
|
+
"type": "array",
|
|
83
|
+
"items": { "$ref": "#/$defs/phase" },
|
|
84
|
+
"description": "v1.3 \u2014 the app's delivery-phase vocabulary, declared once and referenced by `screen.phase` / `flow.phase`. Phase ids are free-form on purpose (every product names its phases differently). Mark a phase `optional: true` when the requirement explicitly parks it outside committed scope. Optional, additive."
|
|
85
85
|
},
|
|
86
|
-
generated_at: {
|
|
87
|
-
type: "string",
|
|
88
|
-
format: "date-time",
|
|
89
|
-
description: "ISO-8601 timestamp when this snapshot was generated."
|
|
86
|
+
"generated_at": {
|
|
87
|
+
"type": "string",
|
|
88
|
+
"format": "date-time",
|
|
89
|
+
"description": "ISO-8601 timestamp when this snapshot was generated."
|
|
90
90
|
},
|
|
91
|
-
tech_stack: {
|
|
92
|
-
type: "array",
|
|
93
|
-
items: { type: "string" },
|
|
94
|
-
description: "List of tech-stack tags (e.g. 'react-native', 'expo', 'powersync')."
|
|
91
|
+
"tech_stack": {
|
|
92
|
+
"type": "array",
|
|
93
|
+
"items": { "type": "string" },
|
|
94
|
+
"description": "List of tech-stack tags (e.g. 'react-native', 'expo', 'powersync')."
|
|
95
95
|
},
|
|
96
|
-
test_metadata: {
|
|
97
|
-
$ref: "#/$defs/testMetadata",
|
|
98
|
-
description: "v1.1 \u2014 app-level metadata used by e2e-user-persona / Playwright skills to bootstrap a session (auth strategy, default viewport, base URL)."
|
|
96
|
+
"test_metadata": {
|
|
97
|
+
"$ref": "#/$defs/testMetadata",
|
|
98
|
+
"description": "v1.1 \u2014 app-level metadata used by e2e-user-persona / Playwright skills to bootstrap a session (auth strategy, default viewport, base URL)."
|
|
99
99
|
},
|
|
100
|
-
screens: {
|
|
101
|
-
type: "array",
|
|
102
|
-
items: { $ref: "#/$defs/screen" }
|
|
100
|
+
"screens": {
|
|
101
|
+
"type": "array",
|
|
102
|
+
"items": { "$ref": "#/$defs/screen" }
|
|
103
103
|
},
|
|
104
|
-
flows: {
|
|
105
|
-
type: "array",
|
|
106
|
-
items: { $ref: "#/$defs/flow" }
|
|
104
|
+
"flows": {
|
|
105
|
+
"type": "array",
|
|
106
|
+
"items": { "$ref": "#/$defs/flow" }
|
|
107
107
|
},
|
|
108
|
-
dead_code: {
|
|
109
|
-
type: "array",
|
|
110
|
-
items: { $ref: "#/$defs/deadCodeEntry" }
|
|
108
|
+
"dead_code": {
|
|
109
|
+
"type": "array",
|
|
110
|
+
"items": { "$ref": "#/$defs/deadCodeEntry" }
|
|
111
111
|
}
|
|
112
112
|
},
|
|
113
|
-
$defs: {
|
|
114
|
-
phase: {
|
|
115
|
-
type: "object",
|
|
116
|
-
required: ["id"],
|
|
117
|
-
additionalProperties: false,
|
|
118
|
-
description: "v1.3 \u2014 one entry in the app's delivery-phase vocabulary.",
|
|
119
|
-
properties: {
|
|
120
|
-
id: {
|
|
121
|
-
type: "string",
|
|
122
|
-
minLength: 1,
|
|
123
|
-
description: "Stable phase id referenced by `screen.phase` / `flow.phase` (e.g. 'alpha', 'beta', 'mvp', 'optional')."
|
|
124
|
-
},
|
|
125
|
-
label: {
|
|
126
|
-
type: "string",
|
|
127
|
-
description: "Human-readable phase name."
|
|
128
|
-
},
|
|
129
|
-
description: {
|
|
130
|
-
type: "string",
|
|
131
|
-
description: "What this phase covers \u2014 ideally quoting the source requirement rather than paraphrasing it."
|
|
132
|
-
},
|
|
133
|
-
optional: {
|
|
134
|
-
type: "boolean",
|
|
135
|
-
description: "True when the requirement explicitly parks this phase outside committed scope (e.g. 'eventual landing, not in MVP'). Viewers and generated Mermaid MUST render it as visually distinct from in-scope work, so a reader never mistakes parked work for a commitment."
|
|
113
|
+
"$defs": {
|
|
114
|
+
"phase": {
|
|
115
|
+
"type": "object",
|
|
116
|
+
"required": ["id"],
|
|
117
|
+
"additionalProperties": false,
|
|
118
|
+
"description": "v1.3 \u2014 one entry in the app's delivery-phase vocabulary.",
|
|
119
|
+
"properties": {
|
|
120
|
+
"id": {
|
|
121
|
+
"type": "string",
|
|
122
|
+
"minLength": 1,
|
|
123
|
+
"description": "Stable phase id referenced by `screen.phase` / `flow.phase` (e.g. 'alpha', 'beta', 'mvp', 'optional')."
|
|
124
|
+
},
|
|
125
|
+
"label": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"description": "Human-readable phase name."
|
|
128
|
+
},
|
|
129
|
+
"description": {
|
|
130
|
+
"type": "string",
|
|
131
|
+
"description": "What this phase covers \u2014 ideally quoting the source requirement rather than paraphrasing it."
|
|
132
|
+
},
|
|
133
|
+
"optional": {
|
|
134
|
+
"type": "boolean",
|
|
135
|
+
"description": "True when the requirement explicitly parks this phase outside committed scope (e.g. 'eventual landing, not in MVP'). Viewers and generated Mermaid MUST render it as visually distinct from in-scope work, so a reader never mistakes parked work for a commitment."
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
},
|
|
139
|
-
screen: {
|
|
140
|
-
type: "object",
|
|
141
|
-
required: ["id", "name"],
|
|
142
|
-
additionalProperties: false,
|
|
143
|
-
properties: {
|
|
144
|
-
id: {
|
|
145
|
-
type: "string",
|
|
146
|
-
minLength: 1,
|
|
147
|
-
description: "Stable screen identifier (snake_case recommended). REQUIRED. This is the STICKY 1:1 JOIN KEY across apps: cross-app comparators (web \u2194 mobile, old build \u2194 new build) pair screens by shared `id`. Treat it as a contract \u2014 keep ids stable across versions and identical across apps you intend to map 1:1, or diffs/parity comparisons break."
|
|
148
|
-
},
|
|
149
|
-
name: {
|
|
150
|
-
type: "string",
|
|
151
|
-
minLength: 1,
|
|
152
|
-
description: "Human-readable screen name."
|
|
153
|
-
},
|
|
154
|
-
route: {
|
|
155
|
-
type: "string",
|
|
156
|
-
description: "v1.2 \u2014 canonical SHARED route nomenclature for 1:1 cross-app mapping (e.g. 'studio/project/:id/editor'). Lets two apps (web \u2194 mobile) map by the same route name even when their real URLs/deep-links differ. Also doubles as the screen's route/path/deep-link when the app uses a single URL scheme. Use ':param' for dynamic segments. Optional, additive."
|
|
157
|
-
},
|
|
158
|
-
description: {
|
|
159
|
-
type: "string",
|
|
160
|
-
description: "v1.3 \u2014 free-form prose describing this screen. For a spec-first file the description IS the requirement, so keep it faithful to the source document. Optional, additive."
|
|
161
|
-
},
|
|
162
|
-
phase: {
|
|
163
|
-
type: "string",
|
|
164
|
-
minLength: 1,
|
|
165
|
-
description: "v1.3 \u2014 id of the phase (from top-level `phases[]`) this screen belongs to. Optional, additive."
|
|
166
|
-
},
|
|
167
|
-
source_ref: {
|
|
168
|
-
$ref: "#/$defs/sourceRef",
|
|
169
|
-
description: "v1.2 \u2014 link from this screen to the repo file(s) that render it (route/page/modal component). Figma-Code-Connect style. Optional, additive \u2014 populated by the route\u2192file resolver (bin/resolve-routes.mjs) or by hand."
|
|
170
|
-
},
|
|
171
|
-
screenshots: {
|
|
172
|
-
type: "array",
|
|
173
|
-
items: { $ref: "#/$defs/screenshot" },
|
|
174
|
-
description: "v1.2 \u2014 rendered screenshots of this screen, one entry per platform\xD7orientation(\xD7viewport). URLs are committed (e.g. S3 via supabase-upload) so humans AND agents view the same image for vision-first comparison. Optional, additive."
|
|
175
|
-
},
|
|
176
|
-
components: {
|
|
177
|
-
type: "array",
|
|
178
|
-
items: { type: "string" },
|
|
179
|
-
description: "Component identifiers rendered on this screen."
|
|
180
|
-
},
|
|
181
|
-
api_calls: {
|
|
182
|
-
type: "array",
|
|
183
|
-
items: { type: "string" },
|
|
184
|
-
description: "API endpoints or RPC calls invoked from this screen."
|
|
185
|
-
},
|
|
186
|
-
actions: {
|
|
187
|
-
type: "array",
|
|
188
|
-
items: { $ref: "#/$defs/action" }
|
|
189
|
-
},
|
|
190
|
-
navigation_path: {
|
|
191
|
-
type: "array",
|
|
192
|
-
items: { $ref: "#/$defs/navigationStep" },
|
|
193
|
-
description: "v1.1 \u2014 ordered
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
139
|
+
"screen": {
|
|
140
|
+
"type": "object",
|
|
141
|
+
"required": ["id", "name"],
|
|
142
|
+
"additionalProperties": false,
|
|
143
|
+
"properties": {
|
|
144
|
+
"id": {
|
|
145
|
+
"type": "string",
|
|
146
|
+
"minLength": 1,
|
|
147
|
+
"description": "Stable screen identifier (snake_case recommended). REQUIRED. This is the STICKY 1:1 JOIN KEY across apps: cross-app comparators (web \u2194 mobile, old build \u2194 new build) pair screens by shared `id`. Treat it as a contract \u2014 keep ids stable across versions and identical across apps you intend to map 1:1, or diffs/parity comparisons break."
|
|
148
|
+
},
|
|
149
|
+
"name": {
|
|
150
|
+
"type": "string",
|
|
151
|
+
"minLength": 1,
|
|
152
|
+
"description": "Human-readable screen name."
|
|
153
|
+
},
|
|
154
|
+
"route": {
|
|
155
|
+
"type": "string",
|
|
156
|
+
"description": "v1.2 \u2014 canonical SHARED route nomenclature for 1:1 cross-app mapping (e.g. 'studio/project/:id/editor'). Lets two apps (web \u2194 mobile) map by the same route name even when their real URLs/deep-links differ. Also doubles as the screen's route/path/deep-link when the app uses a single URL scheme. Use ':param' for dynamic segments. Optional, additive."
|
|
157
|
+
},
|
|
158
|
+
"description": {
|
|
159
|
+
"type": "string",
|
|
160
|
+
"description": "v1.3 \u2014 free-form prose describing this screen. For a spec-first file the description IS the requirement, so keep it faithful to the source document. Optional, additive."
|
|
161
|
+
},
|
|
162
|
+
"phase": {
|
|
163
|
+
"type": "string",
|
|
164
|
+
"minLength": 1,
|
|
165
|
+
"description": "v1.3 \u2014 id of the phase (from top-level `phases[]`) this screen belongs to. Optional, additive."
|
|
166
|
+
},
|
|
167
|
+
"source_ref": {
|
|
168
|
+
"$ref": "#/$defs/sourceRef",
|
|
169
|
+
"description": "v1.2 \u2014 link from this screen to the repo file(s) that render it (route/page/modal component). Figma-Code-Connect style. Optional, additive \u2014 populated by the route\u2192file resolver (bin/resolve-routes.mjs) or by hand."
|
|
170
|
+
},
|
|
171
|
+
"screenshots": {
|
|
172
|
+
"type": "array",
|
|
173
|
+
"items": { "$ref": "#/$defs/screenshot" },
|
|
174
|
+
"description": "v1.2 \u2014 rendered screenshots of this screen, one entry per platform\xD7orientation(\xD7viewport). URLs are committed (e.g. S3 via supabase-upload) so humans AND agents view the same image for vision-first comparison. Optional, additive."
|
|
175
|
+
},
|
|
176
|
+
"components": {
|
|
177
|
+
"type": "array",
|
|
178
|
+
"items": { "type": "string" },
|
|
179
|
+
"description": "Component identifiers rendered on this screen."
|
|
180
|
+
},
|
|
181
|
+
"api_calls": {
|
|
182
|
+
"type": "array",
|
|
183
|
+
"items": { "type": "string" },
|
|
184
|
+
"description": "API endpoints or RPC calls invoked from this screen."
|
|
185
|
+
},
|
|
186
|
+
"actions": {
|
|
187
|
+
"type": "array",
|
|
188
|
+
"items": { "$ref": "#/$defs/action" }
|
|
189
|
+
},
|
|
190
|
+
"navigation_path": {
|
|
191
|
+
"type": "array",
|
|
192
|
+
"items": { "$ref": "#/$defs/navigationStep" },
|
|
193
|
+
"description": "v1.1 \u2014 the ordered SEQUENCE of UI actions that reaches this screen from the app entrypoint. A runner executes EVERY entry, in array order, and the screen is reached only after the last one. Entry N+1 is the step that follows entry N; it is never an alternative selector for it, and a runner must not stop at the first selector that matches. Used by e2e-user-persona to auto-generate persona scripts instead of LLM-driven discovery.",
|
|
194
|
+
"$comment": "This field is a SEQUENCE, not a fallback list. Tainan settled it on 2026-08-13. The v1.1 wording described BOTH structures in one paragraph \u2014 'ordered list of actions to navigate to this screen' and, two sentences later, 'the runner tries them in order and the first matching selector wins' \u2014 and the JSON shape is identical under either reading, so the same document validated while two implementations disagreed about what it meant. Only the sequence reading survives. Alternative selectors for a SINGLE step are not expressible in v1: a screen that needs them wants a new field in a later version, not a second entry here."
|
|
195
|
+
},
|
|
196
|
+
"prerequisites": {
|
|
197
|
+
"$ref": "#/$defs/prerequisites",
|
|
198
|
+
"description": "v1.1 \u2014 preconditions that must hold for this screen to be reachable / functional."
|
|
198
199
|
}
|
|
199
200
|
}
|
|
200
201
|
},
|
|
201
|
-
sourceRef: {
|
|
202
|
-
type: "object",
|
|
203
|
-
required: ["component_file"],
|
|
204
|
-
additionalProperties: false,
|
|
205
|
-
description: "v1.2 \u2014 points a screen at the repo file(s) that render it.",
|
|
206
|
-
properties: {
|
|
207
|
-
component_file: {
|
|
208
|
-
type: "string",
|
|
209
|
-
minLength: 1,
|
|
210
|
-
description: "Repo-relative path to the route/page/modal component that renders this screen (e.g. 'app/studio/[id]/editor.tsx' for Expo Router, 'app/studio/[id]/editor/page.tsx' for Next app-router). This is what the route\u2192file resolver emits."
|
|
211
|
-
},
|
|
212
|
-
file_path_chain: {
|
|
213
|
-
type: "array",
|
|
214
|
-
items: { type: "string" },
|
|
215
|
-
minItems: 1,
|
|
216
|
-
description: "Optional \u2014 ordered repo-relative paths from the app entry (e.g. 'App.tsx' / 'app/_layout.tsx') down to the component, giving the 'tree' from app root to this screen's renderer."
|
|
202
|
+
"sourceRef": {
|
|
203
|
+
"type": "object",
|
|
204
|
+
"required": ["component_file"],
|
|
205
|
+
"additionalProperties": false,
|
|
206
|
+
"description": "v1.2 \u2014 points a screen at the repo file(s) that render it.",
|
|
207
|
+
"properties": {
|
|
208
|
+
"component_file": {
|
|
209
|
+
"type": "string",
|
|
210
|
+
"minLength": 1,
|
|
211
|
+
"description": "Repo-relative path to the route/page/modal component that renders this screen (e.g. 'app/studio/[id]/editor.tsx' for Expo Router, 'app/studio/[id]/editor/page.tsx' for Next app-router). This is what the route\u2192file resolver emits."
|
|
212
|
+
},
|
|
213
|
+
"file_path_chain": {
|
|
214
|
+
"type": "array",
|
|
215
|
+
"items": { "type": "string" },
|
|
216
|
+
"minItems": 1,
|
|
217
|
+
"description": "Optional \u2014 ordered repo-relative paths from the app entry (e.g. 'App.tsx' / 'app/_layout.tsx') down to the component, giving the 'tree' from app root to this screen's renderer."
|
|
217
218
|
}
|
|
218
219
|
}
|
|
219
220
|
},
|
|
220
|
-
screenshot: {
|
|
221
|
-
type: "object",
|
|
222
|
-
required: ["platform", "orientation", "url"],
|
|
223
|
-
additionalProperties: false,
|
|
224
|
-
description: "v1.2 \u2014 one rendered screenshot of a screen, keyed by platform\xD7orientation(\xD7viewport).",
|
|
225
|
-
properties: {
|
|
226
|
-
platform: {
|
|
227
|
-
type: "string",
|
|
228
|
-
enum: ["web", "mobile"],
|
|
229
|
-
description: "Rendering platform the screenshot was captured on."
|
|
230
|
-
},
|
|
231
|
-
orientation: {
|
|
232
|
-
type: "string",
|
|
233
|
-
enum: ["portrait", "landscape"],
|
|
234
|
-
description: "Device/viewport orientation."
|
|
235
|
-
},
|
|
236
|
-
viewport: {
|
|
237
|
-
type: "string",
|
|
238
|
-
description: "Optional viewport dimensions string, e.g. '375x812' or '1440x900'."
|
|
239
|
-
},
|
|
240
|
-
url: {
|
|
241
|
-
type: "string",
|
|
242
|
-
format: "uri",
|
|
243
|
-
description: "Public URL of the committed screenshot (e.g. S3 via supabase-upload)."
|
|
244
|
-
},
|
|
245
|
-
captured_at: {
|
|
246
|
-
type: "string",
|
|
247
|
-
format: "date-time",
|
|
248
|
-
description: "Optional ISO-8601 timestamp when the screenshot was captured."
|
|
221
|
+
"screenshot": {
|
|
222
|
+
"type": "object",
|
|
223
|
+
"required": ["platform", "orientation", "url"],
|
|
224
|
+
"additionalProperties": false,
|
|
225
|
+
"description": "v1.2 \u2014 one rendered screenshot of a screen, keyed by platform\xD7orientation(\xD7viewport).",
|
|
226
|
+
"properties": {
|
|
227
|
+
"platform": {
|
|
228
|
+
"type": "string",
|
|
229
|
+
"enum": ["web", "mobile"],
|
|
230
|
+
"description": "Rendering platform the screenshot was captured on."
|
|
231
|
+
},
|
|
232
|
+
"orientation": {
|
|
233
|
+
"type": "string",
|
|
234
|
+
"enum": ["portrait", "landscape"],
|
|
235
|
+
"description": "Device/viewport orientation."
|
|
236
|
+
},
|
|
237
|
+
"viewport": {
|
|
238
|
+
"type": "string",
|
|
239
|
+
"description": "Optional viewport dimensions string, e.g. '375x812' or '1440x900'."
|
|
240
|
+
},
|
|
241
|
+
"url": {
|
|
242
|
+
"type": "string",
|
|
243
|
+
"format": "uri",
|
|
244
|
+
"description": "Public URL of the committed screenshot (e.g. S3 via supabase-upload)."
|
|
245
|
+
},
|
|
246
|
+
"captured_at": {
|
|
247
|
+
"type": "string",
|
|
248
|
+
"format": "date-time",
|
|
249
|
+
"description": "Optional ISO-8601 timestamp when the screenshot was captured."
|
|
249
250
|
}
|
|
250
251
|
}
|
|
251
252
|
},
|
|
252
|
-
action: {
|
|
253
|
-
type: "object",
|
|
254
|
-
required: ["id", "label"],
|
|
255
|
-
additionalProperties: false,
|
|
256
|
-
properties: {
|
|
257
|
-
id: {
|
|
258
|
-
type: "string",
|
|
259
|
-
minLength: 1
|
|
260
|
-
},
|
|
261
|
-
label: {
|
|
262
|
-
type: "string",
|
|
263
|
-
minLength: 1
|
|
264
|
-
},
|
|
265
|
-
next_screen: {
|
|
266
|
-
type: "string",
|
|
267
|
-
description: "Screen id the user lands on after this action."
|
|
268
|
-
},
|
|
269
|
-
side_effect: {
|
|
270
|
-
type: "string",
|
|
271
|
-
description: "Free-form description of side effect (mutation, analytics, etc.)."
|
|
253
|
+
"action": {
|
|
254
|
+
"type": "object",
|
|
255
|
+
"required": ["id", "label"],
|
|
256
|
+
"additionalProperties": false,
|
|
257
|
+
"properties": {
|
|
258
|
+
"id": {
|
|
259
|
+
"type": "string",
|
|
260
|
+
"minLength": 1
|
|
261
|
+
},
|
|
262
|
+
"label": {
|
|
263
|
+
"type": "string",
|
|
264
|
+
"minLength": 1
|
|
265
|
+
},
|
|
266
|
+
"next_screen": {
|
|
267
|
+
"type": "string",
|
|
268
|
+
"description": "Screen id the user lands on after this action."
|
|
269
|
+
},
|
|
270
|
+
"side_effect": {
|
|
271
|
+
"type": "string",
|
|
272
|
+
"description": "Free-form description of side effect (mutation, analytics, etc.)."
|
|
272
273
|
}
|
|
273
274
|
}
|
|
274
275
|
},
|
|
275
|
-
flow: {
|
|
276
|
-
type: "object",
|
|
277
|
-
required: ["name", "start", "steps"],
|
|
278
|
-
additionalProperties: false,
|
|
279
|
-
properties: {
|
|
280
|
-
name: {
|
|
281
|
-
type: "string",
|
|
282
|
-
minLength: 1
|
|
283
|
-
},
|
|
284
|
-
description: {
|
|
285
|
-
type: "string",
|
|
286
|
-
description: "v1.3 \u2014 free-form prose describing what this flow accomplishes and why it matters. Optional, additive."
|
|
287
|
-
},
|
|
288
|
-
phase: {
|
|
289
|
-
type: "string",
|
|
290
|
-
minLength: 1,
|
|
291
|
-
description: "v1.3 \u2014 id of the phase (from top-level `phases[]`) this flow belongs to. Optional, additive."
|
|
292
|
-
},
|
|
293
|
-
start: {
|
|
294
|
-
type: "string",
|
|
295
|
-
minLength: 1,
|
|
296
|
-
description: "Screen id where the flow starts."
|
|
297
|
-
},
|
|
298
|
-
steps: {
|
|
299
|
-
type: "array",
|
|
300
|
-
items: {
|
|
301
|
-
oneOf: [
|
|
276
|
+
"flow": {
|
|
277
|
+
"type": "object",
|
|
278
|
+
"required": ["name", "start", "steps"],
|
|
279
|
+
"additionalProperties": false,
|
|
280
|
+
"properties": {
|
|
281
|
+
"name": {
|
|
282
|
+
"type": "string",
|
|
283
|
+
"minLength": 1
|
|
284
|
+
},
|
|
285
|
+
"description": {
|
|
286
|
+
"type": "string",
|
|
287
|
+
"description": "v1.3 \u2014 free-form prose describing what this flow accomplishes and why it matters. Optional, additive."
|
|
288
|
+
},
|
|
289
|
+
"phase": {
|
|
290
|
+
"type": "string",
|
|
291
|
+
"minLength": 1,
|
|
292
|
+
"description": "v1.3 \u2014 id of the phase (from top-level `phases[]`) this flow belongs to. Optional, additive."
|
|
293
|
+
},
|
|
294
|
+
"start": {
|
|
295
|
+
"type": "string",
|
|
296
|
+
"minLength": 1,
|
|
297
|
+
"description": "Screen id where the flow starts."
|
|
298
|
+
},
|
|
299
|
+
"steps": {
|
|
300
|
+
"type": "array",
|
|
301
|
+
"items": {
|
|
302
|
+
"oneOf": [
|
|
302
303
|
{
|
|
303
|
-
type: "string",
|
|
304
|
-
description: "v1.0 \u2014 screen id traversed in this flow."
|
|
304
|
+
"type": "string",
|
|
305
|
+
"description": "v1.0 \u2014 screen id traversed in this flow."
|
|
305
306
|
},
|
|
306
307
|
{
|
|
307
|
-
$ref: "#/$defs/flowStepObject"
|
|
308
|
+
"$ref": "#/$defs/flowStepObject"
|
|
308
309
|
}
|
|
309
310
|
]
|
|
310
311
|
},
|
|
311
|
-
description: "Ordered list of flow steps. v1.0 accepts plain screen ids (strings); v1.1 additionally accepts step objects with action/selector/target_screen for executable scripts. Mixed arrays are allowed during migration."
|
|
312
|
+
"description": "Ordered list of flow steps. v1.0 accepts plain screen ids (strings); v1.1 additionally accepts step objects with action/selector/target_screen for executable scripts. Mixed arrays are allowed during migration."
|
|
312
313
|
},
|
|
313
|
-
actions: {
|
|
314
|
-
type: "array",
|
|
315
|
-
items: { type: "string" },
|
|
316
|
-
description: "Ordered list of action ids exercised during this flow."
|
|
314
|
+
"actions": {
|
|
315
|
+
"type": "array",
|
|
316
|
+
"items": { "type": "string" },
|
|
317
|
+
"description": "Ordered list of action ids exercised during this flow."
|
|
317
318
|
},
|
|
318
|
-
tested_by: {
|
|
319
|
-
type: "array",
|
|
320
|
-
items: { type: "string" },
|
|
321
|
-
description: "References to tests (file paths, test names) that cover this flow."
|
|
319
|
+
"tested_by": {
|
|
320
|
+
"type": "array",
|
|
321
|
+
"items": { "type": "string" },
|
|
322
|
+
"description": "References to tests (file paths, test names) that cover this flow."
|
|
322
323
|
}
|
|
323
324
|
}
|
|
324
325
|
},
|
|
325
|
-
flowStepObject: {
|
|
326
|
-
type: "object",
|
|
327
|
-
required: ["screen"],
|
|
328
|
-
additionalProperties: false,
|
|
329
|
-
properties: {
|
|
330
|
-
screen: {
|
|
331
|
-
type: "string",
|
|
332
|
-
minLength: 1,
|
|
333
|
-
description: "Screen id where this step is executed."
|
|
334
|
-
},
|
|
335
|
-
action: {
|
|
336
|
-
type: "string",
|
|
337
|
-
description: "Action verb (tap, type, scroll, swipe, navigate, wait, assert, etc.)."
|
|
338
|
-
},
|
|
339
|
-
selector: {
|
|
340
|
-
type: "string",
|
|
341
|
-
description: "Playwright-compatible selector (e.g. 'text=Next', 'role=button[name=Save]', 'css=[data-testid=foo]')."
|
|
342
|
-
},
|
|
343
|
-
value: {
|
|
344
|
-
type: "string",
|
|
345
|
-
description: "Optional value to type / select / assert."
|
|
346
|
-
},
|
|
347
|
-
target_screen: {
|
|
348
|
-
type: "string",
|
|
349
|
-
description: "Screen id the user lands on after this step."
|
|
350
|
-
},
|
|
351
|
-
wait_for_target: {
|
|
352
|
-
type: "string",
|
|
353
|
-
description: "Selector / condition to wait for to confirm the target screen rendered."
|
|
354
|
-
},
|
|
355
|
-
note: {
|
|
356
|
-
type: "string",
|
|
357
|
-
description: "Free-form annotation for humans / debugging."
|
|
326
|
+
"flowStepObject": {
|
|
327
|
+
"type": "object",
|
|
328
|
+
"required": ["screen"],
|
|
329
|
+
"additionalProperties": false,
|
|
330
|
+
"properties": {
|
|
331
|
+
"screen": {
|
|
332
|
+
"type": "string",
|
|
333
|
+
"minLength": 1,
|
|
334
|
+
"description": "Screen id where this step is executed."
|
|
335
|
+
},
|
|
336
|
+
"action": {
|
|
337
|
+
"type": "string",
|
|
338
|
+
"description": "Action verb (tap, type, scroll, swipe, navigate, wait, assert, etc.)."
|
|
339
|
+
},
|
|
340
|
+
"selector": {
|
|
341
|
+
"type": "string",
|
|
342
|
+
"description": "Playwright-compatible selector (e.g. 'text=Next', 'role=button[name=Save]', 'css=[data-testid=foo]')."
|
|
343
|
+
},
|
|
344
|
+
"value": {
|
|
345
|
+
"type": "string",
|
|
346
|
+
"description": "Optional value to type / select / assert."
|
|
347
|
+
},
|
|
348
|
+
"target_screen": {
|
|
349
|
+
"type": "string",
|
|
350
|
+
"description": "Screen id the user lands on after this step."
|
|
351
|
+
},
|
|
352
|
+
"wait_for_target": {
|
|
353
|
+
"type": "string",
|
|
354
|
+
"description": "Selector / condition to wait for to confirm the target screen rendered."
|
|
355
|
+
},
|
|
356
|
+
"note": {
|
|
357
|
+
"type": "string",
|
|
358
|
+
"description": "Free-form annotation for humans / debugging."
|
|
358
359
|
}
|
|
359
360
|
}
|
|
360
361
|
},
|
|
361
|
-
navigationStep: {
|
|
362
|
-
type: "object",
|
|
363
|
-
required: ["selector", "action"],
|
|
364
|
-
additionalProperties: false,
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
362
|
+
"navigationStep": {
|
|
363
|
+
"type": "object",
|
|
364
|
+
"required": ["selector", "action"],
|
|
365
|
+
"additionalProperties": false,
|
|
366
|
+
"description": "v1.1 \u2014 ONE step of a screen's `navigation_path`. The steps form a sequence: every step runs, in array order. A step is not an alternative to the step before it.",
|
|
367
|
+
"properties": {
|
|
368
|
+
"selector": {
|
|
369
|
+
"type": "string",
|
|
370
|
+
"minLength": 1,
|
|
371
|
+
"description": "Playwright-compatible selector (e.g. 'text=Studio', 'role=tab[name=Studio]', 'css=[data-testid=studio-tab]')."
|
|
372
|
+
},
|
|
373
|
+
"action": {
|
|
374
|
+
"type": "string",
|
|
375
|
+
"enum": ["tap", "click", "type", "scroll", "swipe", "navigate", "wait", "assert"],
|
|
376
|
+
"description": "Interaction primitive to execute."
|
|
377
|
+
},
|
|
378
|
+
"value": {
|
|
379
|
+
"type": "string",
|
|
380
|
+
"description": "Optional value for type/select/assert."
|
|
381
|
+
},
|
|
382
|
+
"wait_for": {
|
|
383
|
+
"type": "string",
|
|
384
|
+
"description": "Selector / condition to wait for after performing the action to confirm success."
|
|
385
|
+
},
|
|
386
|
+
"note": {
|
|
387
|
+
"type": "string",
|
|
388
|
+
"description": "Free-form annotation."
|
|
387
389
|
}
|
|
388
390
|
}
|
|
389
391
|
},
|
|
390
|
-
prerequisites: {
|
|
391
|
-
type: "object",
|
|
392
|
-
additionalProperties: false,
|
|
393
|
-
properties: {
|
|
394
|
-
auth_required: {
|
|
395
|
-
type: "boolean",
|
|
396
|
-
description: "True if a logged-in user session is required to reach this screen."
|
|
397
|
-
},
|
|
398
|
-
auth_role: {
|
|
399
|
-
type: "string",
|
|
400
|
-
description: "Optional \u2014 specific role required (e.g. 'admin', 'instructor'). Omit for any authenticated user."
|
|
401
|
-
},
|
|
402
|
-
data_required: {
|
|
403
|
-
type: "array",
|
|
404
|
-
items: { type: "string" },
|
|
405
|
-
description: "Free-form descriptions of DB/state preconditions (e.g. 'lesson_studio.projects has >= 0 rows')."
|
|
406
|
-
},
|
|
407
|
-
preconditions_in_app: {
|
|
408
|
-
type: "array",
|
|
409
|
-
items: { type: "string" },
|
|
410
|
-
description: "Free-form descriptions of in-app preconditions (feature flag enabled, onboarding complete, etc.)."
|
|
411
|
-
},
|
|
412
|
-
feature_flags: {
|
|
413
|
-
type: "array",
|
|
414
|
-
items: { type: "string" },
|
|
415
|
-
description: "Feature flag identifiers that must be enabled."
|
|
392
|
+
"prerequisites": {
|
|
393
|
+
"type": "object",
|
|
394
|
+
"additionalProperties": false,
|
|
395
|
+
"properties": {
|
|
396
|
+
"auth_required": {
|
|
397
|
+
"type": "boolean",
|
|
398
|
+
"description": "True if a logged-in user session is required to reach this screen."
|
|
399
|
+
},
|
|
400
|
+
"auth_role": {
|
|
401
|
+
"type": "string",
|
|
402
|
+
"description": "Optional \u2014 specific role required (e.g. 'admin', 'instructor'). Omit for any authenticated user."
|
|
403
|
+
},
|
|
404
|
+
"data_required": {
|
|
405
|
+
"type": "array",
|
|
406
|
+
"items": { "type": "string" },
|
|
407
|
+
"description": "Free-form descriptions of DB/state preconditions (e.g. 'lesson_studio.projects has >= 0 rows')."
|
|
408
|
+
},
|
|
409
|
+
"preconditions_in_app": {
|
|
410
|
+
"type": "array",
|
|
411
|
+
"items": { "type": "string" },
|
|
412
|
+
"description": "Free-form descriptions of in-app preconditions (feature flag enabled, onboarding complete, etc.)."
|
|
413
|
+
},
|
|
414
|
+
"feature_flags": {
|
|
415
|
+
"type": "array",
|
|
416
|
+
"items": { "type": "string" },
|
|
417
|
+
"description": "Feature flag identifiers that must be enabled."
|
|
416
418
|
}
|
|
417
419
|
}
|
|
418
420
|
},
|
|
419
|
-
testMetadata: {
|
|
420
|
-
type: "object",
|
|
421
|
-
additionalProperties: false,
|
|
422
|
-
properties: {
|
|
423
|
-
auth_strategy: {
|
|
424
|
-
type: "string",
|
|
425
|
-
description: "Brief description of how to authenticate (e.g. 'supabase-anon + CLAUDE_SMOKE creds', 'magic-link', 'oauth google')."
|
|
426
|
-
},
|
|
427
|
-
default_viewport: {
|
|
428
|
-
type: "string",
|
|
429
|
-
enum: ["mobile", "tablet", "desktop", "responsive"],
|
|
430
|
-
description: "Hint for test runners \u2014 preferred viewport for this app."
|
|
431
|
-
},
|
|
432
|
-
base_url: {
|
|
433
|
-
type: "string",
|
|
434
|
-
format: "uri",
|
|
435
|
-
description: "Production / smoke-target base URL (e.g. 'https://mobile.devfellowship.com/')."
|
|
436
|
-
},
|
|
437
|
-
test_user_secret_path: {
|
|
438
|
-
type: "string",
|
|
439
|
-
description: "Infisical path to credentials suitable for smoke tests (e.g. '/shared/CLAUDE_SMOKE_USERNAME')."
|
|
440
|
-
},
|
|
441
|
-
notes: {
|
|
442
|
-
type: "string",
|
|
443
|
-
description: "Free-form notes for test authors / persona-script generators."
|
|
421
|
+
"testMetadata": {
|
|
422
|
+
"type": "object",
|
|
423
|
+
"additionalProperties": false,
|
|
424
|
+
"properties": {
|
|
425
|
+
"auth_strategy": {
|
|
426
|
+
"type": "string",
|
|
427
|
+
"description": "Brief description of how to authenticate (e.g. 'supabase-anon + CLAUDE_SMOKE creds', 'magic-link', 'oauth google')."
|
|
428
|
+
},
|
|
429
|
+
"default_viewport": {
|
|
430
|
+
"type": "string",
|
|
431
|
+
"enum": ["mobile", "tablet", "desktop", "responsive"],
|
|
432
|
+
"description": "Hint for test runners \u2014 preferred viewport for this app."
|
|
433
|
+
},
|
|
434
|
+
"base_url": {
|
|
435
|
+
"type": "string",
|
|
436
|
+
"format": "uri",
|
|
437
|
+
"description": "Production / smoke-target base URL (e.g. 'https://mobile.devfellowship.com/')."
|
|
438
|
+
},
|
|
439
|
+
"test_user_secret_path": {
|
|
440
|
+
"type": "string",
|
|
441
|
+
"description": "Infisical path to credentials suitable for smoke tests (e.g. '/shared/CLAUDE_SMOKE_USERNAME')."
|
|
442
|
+
},
|
|
443
|
+
"notes": {
|
|
444
|
+
"type": "string",
|
|
445
|
+
"description": "Free-form notes for test authors / persona-script generators."
|
|
444
446
|
}
|
|
445
447
|
}
|
|
446
448
|
},
|
|
447
|
-
deadCodeEntry: {
|
|
448
|
-
type: "object",
|
|
449
|
-
required: ["component", "reason"],
|
|
450
|
-
additionalProperties: false,
|
|
451
|
-
properties: {
|
|
452
|
-
component: {
|
|
453
|
-
type: "string",
|
|
454
|
-
minLength: 1
|
|
455
|
-
},
|
|
456
|
-
reason: {
|
|
457
|
-
type: "string",
|
|
458
|
-
minLength: 1
|
|
449
|
+
"deadCodeEntry": {
|
|
450
|
+
"type": "object",
|
|
451
|
+
"required": ["component", "reason"],
|
|
452
|
+
"additionalProperties": false,
|
|
453
|
+
"properties": {
|
|
454
|
+
"component": {
|
|
455
|
+
"type": "string",
|
|
456
|
+
"minLength": 1
|
|
457
|
+
},
|
|
458
|
+
"reason": {
|
|
459
|
+
"type": "string",
|
|
460
|
+
"minLength": 1
|
|
459
461
|
}
|
|
460
462
|
}
|
|
461
463
|
}
|
|
@@ -464,7 +466,7 @@ var v1_schema_default = {
|
|
|
464
466
|
|
|
465
467
|
// src/cli/ux-paths/lib/load-schema.ts
|
|
466
468
|
async function loadSchemaV1() {
|
|
467
|
-
return
|
|
469
|
+
return SCHEMA_V1;
|
|
468
470
|
}
|
|
469
471
|
|
|
470
472
|
// src/cli/ux-paths/commands/validate.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devfellowship/components",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.2",
|
|
4
4
|
"description": "DFL Design System — UI components, hooks, utils and providers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -117,6 +117,7 @@
|
|
|
117
117
|
"vitest": "^3.2.4"
|
|
118
118
|
},
|
|
119
119
|
"dependencies": {
|
|
120
|
+
"@devfellowship/ux-paths-spec": "^1.3.1",
|
|
120
121
|
"@radix-ui/react-accordion": "^1.2.0",
|
|
121
122
|
"@radix-ui/react-alert-dialog": "^1.1.1",
|
|
122
123
|
"@radix-ui/react-aspect-ratio": "^1.1.8",
|