@supatent/skills 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,289 @@
1
+ # Schema Reference
2
+
3
+ > **Source of truth:** `packages/cli/src/constants.ts` and `packages/cli/src/types.ts` define the canonical field types, interfaces, and validation rules. `packages/jsonld-schemas/src/registry.ts` defines supported JSON-LD types. Phase 45 CI drift check will verify this file stays in sync with those sources.
4
+
5
+ ## Field Types and Interfaces
6
+
7
+ Every field in a schema has a `type` and an `interface`. The type determines the data format; the interface determines the editing UI.
8
+
9
+ | Type | Interface | Value Format | Notes |
10
+ |------|-----------|-------------|-------|
11
+ | `text` | `textInput` | `string` | Single-line text input |
12
+ | `text` | `textarea` | `string` | Multi-line text area |
13
+ | `number` | `numberInput` | `number` or `null` | Numeric input; `null` represents empty (distinct from `0`) |
14
+ | `image` | `singleImage` | `string` or `null` | Asset slug string (e.g., `"hero-image"`), or legacy object with `assetPath` |
15
+ | `image` | `multiImage` | `string[]` | Array of asset slug strings (e.g., `["hero", "banner"]`) |
16
+ | `markdown` | `markdownEditor` | `string` | Markdown-formatted text |
17
+ | `jsonLd` | `jsonLdEditor` | `object` | JSON-LD object with `@context` and `@type` |
18
+
19
+ **Important:** Each interface is valid only for its corresponding type. Using `textarea` with a `number` type (or any other mismatch) will fail validation.
20
+
21
+ ### Interface-Type Compatibility Map
22
+
23
+ ```
24
+ text -> textInput, textarea
25
+ number -> numberInput
26
+ image -> singleImage, multiImage
27
+ markdown -> markdownEditor
28
+ jsonLd -> jsonLdEditor
29
+ ```
30
+
31
+ ## Schema File Structure
32
+
33
+ Schema files live at `.supatent/schema/{slug}.json`. The complete structure:
34
+
35
+ ```json
36
+ {
37
+ "slug": "blog-post",
38
+ "name": "Blog Post",
39
+ "description": "Articles for the company blog",
40
+ "isSingleton": false,
41
+ "fields": [
42
+ {
43
+ "slug": "title",
44
+ "name": "Title",
45
+ "description": "The post headline",
46
+ "type": "text",
47
+ "interface": "textInput",
48
+ "order": 0
49
+ },
50
+ {
51
+ "slug": "body",
52
+ "name": "Body",
53
+ "type": "markdown",
54
+ "interface": "markdownEditor",
55
+ "order": 1
56
+ }
57
+ ]
58
+ }
59
+ ```
60
+
61
+ ### Property Reference
62
+
63
+ | Property | Required | Type | Description |
64
+ |----------|----------|------|-------------|
65
+ | `slug` | Yes | `string` | Must match filename (without `.json`). Lowercase alphanumeric with hyphens. |
66
+ | `name` | Yes | `string` | Display name. Minimum 1 character. |
67
+ | `description` | No | `string` | Optional description of the schema's purpose. |
68
+ | `isSingleton` | Yes | `boolean` | Whether this schema has exactly one content item per locale. |
69
+ | `fields` | Yes | `array` | Array of field definitions. |
70
+
71
+ ### Field Property Reference
72
+
73
+ | Property | Required | Type | Description |
74
+ |----------|----------|------|-------------|
75
+ | `slug` | Yes | `string` | Unique within the schema. Lowercase alphanumeric with hyphens. |
76
+ | `name` | Yes | `string` | Display name. Minimum 1 character. |
77
+ | `description` | No | `string` | Optional description of the field's purpose. |
78
+ | `type` | Yes | `string` | One of: `text`, `number`, `image`, `markdown`, `jsonLd` |
79
+ | `interface` | Yes | `string` | Must be valid for the field's type (see compatibility map above). |
80
+ | `order` | Yes | `number` | Integer >= 0. Controls display order in the editor. |
81
+
82
+ ## Validation Rules
83
+
84
+ These rules are enforced by `packages/cli/src/lib/validation.ts` using AJV (JSON Schema draft-07).
85
+
86
+ ### Slug Pattern
87
+
88
+ All slugs (schema slugs, field slugs, content item slugs) must match:
89
+
90
+ ```
91
+ ^[a-z0-9]+(?:-[a-z0-9]+)*$
92
+ ```
93
+
94
+ Valid: `blog-post`, `title`, `cover-image`, `my-post-1`
95
+ Invalid: `Blog_Post`, `my post`, `_title`, `post--double`, `-leading`
96
+
97
+ ### Required Schema Properties
98
+
99
+ The top-level object requires: `slug`, `name`, `isSingleton`, `fields`.
100
+
101
+ ### Required Field Properties
102
+
103
+ Each field object requires: `slug`, `name`, `type`, `interface`, `order`.
104
+
105
+ ### Additional Rules
106
+
107
+ - **Slug-filename match:** The `slug` value must match the filename (e.g., `blog-post.json` must have `"slug": "blog-post"`).
108
+ - **Unique field slugs:** No two fields within the same schema can share a slug.
109
+ - **Interface-type compatibility:** The `interface` must be valid for the given `type` (see compatibility map).
110
+ - **Order minimum:** The `order` field must be a number >= 0.
111
+ - **Name minimum length:** Both schema `name` and field `name` must have at least 1 character.
112
+
113
+ ## Singleton vs Collection
114
+
115
+ ### Singleton (`isSingleton: true`)
116
+
117
+ One content item per locale. The content file **must** use slug `"default"`.
118
+
119
+ File path: `.supatent/content/{schemaSlug}/default.{locale}.json`
120
+
121
+ Use for: site settings, homepage hero, footer, navigation, about page, any content that exists as a single instance.
122
+
123
+ Example schemas: `site-settings`, `homepage-hero`, `footer`, `about-page`
124
+
125
+ ### Collection (`isSingleton: false`)
126
+
127
+ Multiple content items, each with its own slug.
128
+
129
+ File path: `.supatent/content/{schemaSlug}/{itemSlug}.{locale}.json`
130
+
131
+ Use for: blog posts, team members, FAQ items, product listings, testimonials, any content with multiple entries.
132
+
133
+ Example schemas: `blog-post`, `team-member`, `faq-item`, `product`
134
+
135
+ ### Decision Guide
136
+
137
+ | Question | Yes -> Singleton | No -> Collection |
138
+ |----------|-----------------|-----------------|
139
+ | Is there only ever one of this? | Singleton | Collection |
140
+ | Would "list all X" make sense? | Collection | Singleton |
141
+ | Does it have its own slug/URL? | Collection | Singleton |
142
+
143
+ ## Content File Structure
144
+
145
+ Content files live at `.supatent/content/{schemaSlug}/{itemSlug}.{locale}.json`.
146
+
147
+ The file is a flat JSON object where keys are field slugs from the schema:
148
+
149
+ ```json
150
+ {
151
+ "title": "My First Blog Post",
152
+ "body": "# Welcome\n\nThis is the post content in **markdown**.",
153
+ "cover-image": "blog-hero",
154
+ "read-time": 5
155
+ }
156
+ ```
157
+
158
+ ### Value Types by Field Type
159
+
160
+ | Field Type | Expected Value | Example |
161
+ |------------|---------------|---------|
162
+ | `text` | `string` | `"Hello world"` |
163
+ | `number` | `number` or `null` | `42` or `null` |
164
+ | `image` (singleImage) | `string` (asset slug) or `null` | `"hero-image"` |
165
+ | `image` (multiImage) | `string[]` (asset slugs) | `["photo-1", "photo-2"]` |
166
+ | `markdown` | `string` | `"# Heading\n\nParagraph"` |
167
+ | `jsonLd` | `object` | `{ "@context": "https://schema.org", "@type": "Article" }` |
168
+
169
+ ### File Naming
170
+
171
+ - Collection: `{itemSlug}.{locale}.json` (e.g., `my-post.en.json`, `my-post.fr.json`)
172
+ - Singleton: `default.{locale}.json` (e.g., `default.en.json`)
173
+ - Locale format: `xx` or `xx-XX` (e.g., `en`, `en-US`, `fr`, `fr-CA`)
174
+
175
+ ### Content Validation Behavior
176
+
177
+ - **Unknown fields** (not in schema) produce errors with "did you mean?" suggestions using Levenshtein distance.
178
+ - **Missing fields** produce errors (required), except `jsonLd` fields which produce warnings.
179
+ - **Wrong value types** produce errors with examples of correct format.
180
+
181
+ ## JSON-LD Types
182
+
183
+ Supatent supports 23 JSON-LD types for structured data, validated by the `@supatent/jsonld-schemas` package. Types are organized by category.
184
+
185
+ To use JSON-LD: add a field with `type: "jsonLd"` and `interface: "jsonLdEditor"`. The content value must include `@context` and `@type`:
186
+
187
+ ```json
188
+ {
189
+ "@context": "https://schema.org",
190
+ "@type": "Article",
191
+ "headline": "My Article Title",
192
+ "author": { "@type": "Person", "name": "Jane Doe" }
193
+ }
194
+ ```
195
+
196
+ ### Commerce
197
+
198
+ | @type | Label | Description |
199
+ |-------|-------|-------------|
200
+ | `Product` | Product | Physical or digital products for sale |
201
+ | `SoftwareApplication` | Software App | Software applications and tools |
202
+ | `VacationRental` | Vacation Rental | Short-term rental properties |
203
+
204
+ ### Content
205
+
206
+ | @type | Label | Description |
207
+ |-------|-------|-------------|
208
+ | `Article` | Article | News articles, blog posts, editorial content |
209
+ | `Recipe` | Recipe | Cooking and food preparation instructions |
210
+ | `FAQPage` | FAQ Page | Frequently asked questions pages |
211
+ | `Review` | Review | Product or service reviews |
212
+ | `DiscussionForumPosting` | Discussion Forum Posting | Forum threads and community posts |
213
+ | `QAPage` | Q&A Page | Question and answer pages |
214
+
215
+ ### Local
216
+
217
+ | @type | Label | Description |
218
+ |-------|-------|-------------|
219
+ | `LocalBusiness` | Local Business | Physical business locations |
220
+ | `Event` | Event | Events, conferences, meetups |
221
+
222
+ ### Education
223
+
224
+ | @type | Label | Description |
225
+ |-------|-------|-------------|
226
+ | `Course` | Course | Educational courses and programs |
227
+ | `Quiz` | Education Q&A | Educational quizzes and assessments |
228
+ | `MathSolver` | Math Solver | Mathematical problem solvers |
229
+
230
+ ### Media
231
+
232
+ | @type | Label | Description |
233
+ |-------|-------|-------------|
234
+ | `VideoObject` | Video | Video content and clips |
235
+ | `Movie` | Movie | Feature films and movies |
236
+ | `ImageMetadata` | Image Metadata | Image licensing and attribution |
237
+
238
+ ### People and Organizations
239
+
240
+ | @type | Label | Description |
241
+ |-------|-------|-------------|
242
+ | `Organization` | Organization | Companies, nonprofits, institutions |
243
+ | `ProfilePage` | Profile Page | Personal or professional profile pages |
244
+ | `EmployerAggregateRating` | Employer Rating | Aggregated employer ratings and reviews |
245
+ | `JobPosting` | Job Posting | Job listings and opportunities |
246
+
247
+ ### Navigation
248
+
249
+ | @type | Label | Description |
250
+ |-------|-------|-------------|
251
+ | `BreadcrumbList` | Breadcrumb List | Site navigation breadcrumbs |
252
+
253
+ ### Data
254
+
255
+ | @type | Label | Description |
256
+ |-------|-------|-------------|
257
+ | `Dataset` | Dataset | Structured data collections |
258
+
259
+ ### JSON-LD Validation
260
+
261
+ - The `@context` field must be `"https://schema.org"`.
262
+ - The `@type` must be one of the 23 supported types listed above.
263
+ - Additional properties are validated against schema.org specifications by the `@supatent/jsonld-schemas` package (deep property checking).
264
+ - Deprecated types generate warnings, not errors.
265
+ - Empty `jsonLd` fields (missing from content) produce warnings rather than errors.
266
+
267
+ ## Naming Conventions
268
+
269
+ ### Schema Slugs
270
+
271
+ Use lowercase-hyphenated: `blog-post`, `site-settings`, `team-member`
272
+
273
+ Do not use: `blogPost`, `Blog_Post`, `BLOG-POST`
274
+
275
+ ### Field Slugs
276
+
277
+ Use lowercase-hyphenated: `cover-image`, `read-time`, `full-name`
278
+
279
+ Do not use: `coverImage`, `cover_image`, `CoverImage`
280
+
281
+ ### Display Names
282
+
283
+ Use Title Case: `"Blog Post"`, `"Cover Image"`, `"Read Time"`
284
+
285
+ ### Content Item Slugs
286
+
287
+ Use lowercase-hyphenated: `my-first-post`, `about-us`, `john-doe`
288
+
289
+ Singleton items always use: `default`
@@ -0,0 +1,345 @@
1
+ # Workflow Reference
2
+
3
+ > **Source of truth:** `packages/cli/src/commands/*.ts` define CLI command behavior and flags. `packages/cli/src/lib/validation.ts` defines error messages. This file documents the content authoring workflow for AI agents operating through the Supatent CLI.
4
+
5
+ ## Content Authoring Flow
6
+
7
+ The standard workflow for creating and managing content:
8
+
9
+ 1. **Initialize** (first time only):
10
+ ```bash
11
+ supatent init
12
+ ```
13
+ Sets up `.supatent/` directory with `config.json` and `credentials.json`.
14
+
15
+ 2. **Pull existing content:**
16
+ ```bash
17
+ supatent pull
18
+ ```
19
+ Downloads schemas, content, and assets from the remote CMS.
20
+
21
+ 3. **Start dev mode** (recommended for continuous work):
22
+ ```bash
23
+ supatent dev
24
+ ```
25
+ Enables bidirectional real-time sync via Convex WebSocket. File changes are automatically validated and pushed.
26
+
27
+ 4. **Create or edit schemas** in `.supatent/schema/` -- see schema-reference.md for field types and validation rules.
28
+
29
+ 5. **Create or edit content** in `.supatent/content/{schemaSlug}/` -- content files are flat JSON objects with field slugs as keys.
30
+
31
+ 6. **Validate** (automatic in dev mode, or manual):
32
+ ```bash
33
+ supatent validate
34
+ ```
35
+
36
+ 7. **Push** (automatic in dev mode, or manual):
37
+ ```bash
38
+ supatent push
39
+ ```
40
+
41
+ 8. **Check status** at any time:
42
+ ```bash
43
+ supatent status
44
+ ```
45
+
46
+ ## CLI Command Reference
47
+
48
+ ### `supatent init`
49
+
50
+ Initialize Supatent in the current directory. Creates `.supatent/` with configuration files.
51
+
52
+ | Flag | Description |
53
+ |------|-------------|
54
+ | `--base-url <url>` | Supatent app URL (default: `https://app.supatent.ai`) |
55
+ | `--api-key <key>` | API key for authentication |
56
+ | `--project <slug>` | Project slug to connect to |
57
+ | `-y, --yes` | Skip confirmation prompts (non-interactive mode) |
58
+
59
+ The init process auto-discovers the Convex HTTP URL via the Next.js discovery endpoint (`GET {baseUrl}/api/v1/discover`).
60
+
61
+ ### `supatent pull`
62
+
63
+ Download schemas, content, and assets from the remote CMS. Uses delta pulling -- only downloads items that have changed since last sync.
64
+
65
+ | Flag | Description |
66
+ |------|-------------|
67
+ | `--schema` | Pull schemas only |
68
+ | `--content` | Pull content only |
69
+ | `--no-assets` | Skip downloading asset binary files |
70
+ | `-f, --force` | Overwrite local changes without confirmation |
71
+ | `-v, --verbose` | Show detailed output |
72
+
73
+ ### `supatent push`
74
+
75
+ Upload local changes to the remote CMS. Validates content before pushing. Uses batch atomic push.
76
+
77
+ | Flag | Description |
78
+ |------|-------------|
79
+ | `--dry-run` | Show what would change without applying |
80
+ | `--schema` | Push schemas only |
81
+ | `--content` | Push content only |
82
+ | `-f, --force` | Overwrite remote conflicts |
83
+ | `-v, --verbose` | Show detailed output |
84
+
85
+ ### `supatent status`
86
+
87
+ Show changes between local files and the remote CMS. Compares checksums to detect additions, modifications, and deletions in both directions.
88
+
89
+ | Flag | Description |
90
+ |------|-------------|
91
+ | `--json` | Output as JSON (machine-readable) |
92
+ | `-v, --verbose` | Show unchanged files too |
93
+
94
+ ### `supatent validate`
95
+
96
+ Validate local schema, content, and asset files against the defined rules. Writes results to `.validation-status.json`.
97
+
98
+ | Flag | Description |
99
+ |------|-------------|
100
+ | `[path]` | Optional path to validate (e.g., `schema/`, `content/`, or a specific file) |
101
+ | `--json` | Output validation results as JSON |
102
+
103
+ ### `supatent dev`
104
+
105
+ Start continuous bidirectional sync with the CMS. Watches for local file changes and subscribes to remote changes via Convex WebSocket.
106
+
107
+ | Flag | Description |
108
+ |------|-------------|
109
+ | `-v, --verbose` | Show detailed output (watcher events, sync operations) |
110
+ | `--no-watch` | Disable local file watching (pull-only mode) |
111
+ | `--no-pull` | Disable remote change pulling (push-only mode) |
112
+
113
+ ### `supatent merge`
114
+
115
+ Resolve conflicts between local and remote versions. Shows diffs and prompts for resolution strategy.
116
+
117
+ | Flag | Description |
118
+ |------|-------------|
119
+ | `--schema <slug>` | Filter conflicts by schema slug |
120
+ | `--content-slug <slug>` | Target specific content item (requires `--schema`) |
121
+ | `--theirs` | Accept all remote changes (non-interactive) |
122
+ | `--mine` | Keep all local changes (non-interactive) |
123
+ | `-v, --verbose` | Show detailed output |
124
+
125
+ ## File Locations
126
+
127
+ All Supatent files live under the `.supatent/` directory in the project root:
128
+
129
+ | Path | Purpose | Git |
130
+ |------|---------|-----|
131
+ | `.supatent/config.json` | Project configuration (base URL, Convex URL, project slug) | Tracked |
132
+ | `.supatent/credentials.json` | API key storage | Gitignored |
133
+ | `.supatent/schema/{slug}.json` | Schema definitions | Tracked |
134
+ | `.supatent/content/{schemaSlug}/{itemSlug}.{locale}.json` | Content items | Tracked |
135
+ | `.supatent/assets/{slug}.{ext}` | Asset binary files | Tracked |
136
+ | `.supatent/assets/{slug}.{locale}.json` | Asset metadata sidecars (alt, title, description) | Tracked |
137
+ | `.supatent/.supatent-lock.json` | Sync state and checksums | Gitignored |
138
+ | `.supatent/.validation-status.json` | Last validation results (for AI agents) | Gitignored |
139
+
140
+ ## Common Validation Errors and Fixes
141
+
142
+ ### Slug Pattern Error
143
+
144
+ **Error:** `root: must match pattern "^[a-z0-9]+(?:-[a-z0-9]+)*$"` or `fields[N].slug: must match pattern`
145
+
146
+ **Cause:** Slug contains invalid characters (uppercase, underscores, spaces, consecutive hyphens, leading/trailing hyphens).
147
+
148
+ **Fix:** Use only lowercase letters, numbers, and single hyphens. Example: `my-field-name`, not `myFieldName` or `my_field`.
149
+
150
+ ### Missing Required Property
151
+
152
+ **Error:** `root: must have required property 'slug'` (or `name`, `isSingleton`, `fields`, `type`, `interface`, `order`)
153
+
154
+ **Cause:** A required property is missing from the schema or field definition.
155
+
156
+ **Fix:** Add the missing property. Required schema properties: `slug`, `name`, `isSingleton`, `fields`. Required field properties: `slug`, `name`, `type`, `interface`, `order`.
157
+
158
+ ### Unknown Field in Content
159
+
160
+ **Error:** `Unknown field 'fieldName' is not defined in the schema`
161
+
162
+ **Cause:** The content file contains a key that does not match any field slug in the schema.
163
+
164
+ **Fix:** Check the schema's field slugs and use the exact slug. The validator suggests close matches (e.g., "Did you mean 'title'?"). Valid fields are listed in the error message.
165
+
166
+ ### Interface Not Valid for Type
167
+
168
+ **Error:** `Field 'fieldSlug': interface 'textarea' is not valid for type 'number'`
169
+
170
+ **Cause:** The field's `interface` is not compatible with its `type`.
171
+
172
+ **Fix:** Use a compatible interface. Valid combinations:
173
+ - `text` -> `textInput`, `textarea`
174
+ - `number` -> `numberInput`
175
+ - `image` -> `singleImage`, `multiImage`
176
+ - `markdown` -> `markdownEditor`
177
+ - `jsonLd` -> `jsonLdEditor`
178
+
179
+ ### Filename-Slug Mismatch
180
+
181
+ **Error:** `Slug 'my-post' doesn't match filename 'blog-post.json'`
182
+
183
+ **Cause:** The `slug` value inside the JSON file does not match the filename (without `.json`).
184
+
185
+ **Fix:** Either change the `slug` property to match the filename, or rename the file to match the slug.
186
+
187
+ ### Duplicate Field Slugs
188
+
189
+ **Error:** `Duplicate field slug: 'title' (appears at index 0 and 2)`
190
+
191
+ **Cause:** Two fields in the same schema have identical slugs.
192
+
193
+ **Fix:** Rename one of the duplicate fields to a unique slug.
194
+
195
+ ### Singleton Slug Error
196
+
197
+ **Error:** `Singleton content file must use slug 'default', got 'my-settings'`
198
+
199
+ **Cause:** A content file for a singleton schema uses a slug other than `"default"`.
200
+
201
+ **Fix:** Rename the content file to `default.{locale}.json` (e.g., `default.en.json`).
202
+
203
+ ### Missing Content Field
204
+
205
+ **Error:** `Field 'body' is missing from content`
206
+
207
+ **Cause:** A field defined in the schema is not present in the content file.
208
+
209
+ **Fix:** Add the missing field to the content file with the correct value type.
210
+
211
+ ### JSON-LD Validation Errors
212
+
213
+ **Error:** `Field 'structured-data': @root: Missing required property "@context"` or `Missing required property "@type"`
214
+
215
+ **Cause:** The JSON-LD object is missing required schema.org properties.
216
+
217
+ **Fix:** Ensure the object includes at minimum:
218
+ ```json
219
+ {
220
+ "@context": "https://schema.org",
221
+ "@type": "Article"
222
+ }
223
+ ```
224
+
225
+ The `@type` must be one of the 23 supported types (see schema-reference.md for the full list). Additional property validation is handled by the `@supatent/jsonld-schemas` package.
226
+
227
+ ## JSON-LD Creation Guidance
228
+
229
+ To add structured data to a schema:
230
+
231
+ 1. **Add a JSON-LD field to the schema:**
232
+ ```json
233
+ {
234
+ "slug": "structured-data",
235
+ "name": "Structured Data",
236
+ "type": "jsonLd",
237
+ "interface": "jsonLdEditor",
238
+ "order": 10
239
+ }
240
+ ```
241
+
242
+ 2. **Add the JSON-LD value in the content file:**
243
+ ```json
244
+ {
245
+ "structured-data": {
246
+ "@context": "https://schema.org",
247
+ "@type": "Article",
248
+ "headline": "My Article Title",
249
+ "author": {
250
+ "@type": "Person",
251
+ "name": "Jane Doe"
252
+ },
253
+ "datePublished": "2026-01-15"
254
+ }
255
+ }
256
+ ```
257
+
258
+ 3. **Requirements:**
259
+ - `@context` must be `"https://schema.org"` (required)
260
+ - `@type` must be one of the 23 supported types (required)
261
+ - Additional properties follow schema.org specifications for that type
262
+ - Deep property validation is handled by `@supatent/jsonld-schemas`
263
+
264
+ 4. **Common patterns:**
265
+ - Blog posts: `@type: "Article"` with `headline`, `author`, `datePublished`
266
+ - Products: `@type: "Product"` with `name`, `description`, `offers`
267
+ - FAQ sections: `@type: "FAQPage"` with `mainEntity` array of `Question` items
268
+ - Business pages: `@type: "LocalBusiness"` with `name`, `address`, `telephone`
269
+
270
+ 5. **Empty JSON-LD fields** produce warnings (not errors) -- they are optional for SEO enhancement.
271
+
272
+ ## Dev Mode Details
273
+
274
+ Dev mode (`supatent dev`) provides continuous bidirectional sync:
275
+
276
+ **Local to Remote (file watcher):**
277
+ - Uses chokidar to watch the `.supatent/` directory for file changes
278
+ - Debounces changes (300ms) to batch rapid edits
279
+ - Auto-validates before pushing -- invalid files are not pushed
280
+ - Updates the lock file after successful push
281
+
282
+ **Remote to Local (Convex WebSocket):**
283
+ - Subscribes to `draftWatch.draftChangeIndicator` reactive query via ConvexClient
284
+ - Receives change events when any draft schema, content, or asset changes remotely
285
+ - Triggers delta-pull on change, checking for conflicts first
286
+ - Updates the lock file after successful pull
287
+
288
+ **Remote checksum cache:** Dev mode caches remote checksums for 5 seconds to reduce API calls during rapid local edits. The cache is invalidated when a remote change event arrives.
289
+
290
+ **If dev mode is not running:** Use `supatent validate` to check files after editing, and `supatent push` when ready to upload.
291
+
292
+ ## Validation Status File
293
+
294
+ The `.validation-status.json` file is written by `supatent validate` and `supatent dev` after each validation run. AI agents should read this file to confirm whether their changes are valid.
295
+
296
+ **Location:** `.supatent/.validation-status.json`
297
+
298
+ **Structure:**
299
+ ```json
300
+ {
301
+ "valid": true,
302
+ "timestamp": "2026-01-15T14:30:00.000Z",
303
+ "trigger": "file-change",
304
+ "summary": {
305
+ "filesChecked": 12,
306
+ "filesValid": 12,
307
+ "filesInvalid": 0,
308
+ "errorCount": 0,
309
+ "warningCount": 2
310
+ },
311
+ "errors": [],
312
+ "warnings": [
313
+ {
314
+ "path": "content/blog/my-post",
315
+ "type": "locale",
316
+ "message": "Missing locales: fr",
317
+ "help": "Create files: my-post.fr.json"
318
+ }
319
+ ],
320
+ "localeCoverage": {
321
+ "expected": ["en", "fr"],
322
+ "stats": [
323
+ {
324
+ "schemaSlug": "blog",
325
+ "totalItems": 5,
326
+ "completeItems": 3
327
+ }
328
+ ]
329
+ }
330
+ }
331
+ ```
332
+
333
+ **Key fields for AI agents:**
334
+ - `valid`: `true` if no errors (warnings are acceptable)
335
+ - `errors[]`: Each error includes `path`, `message`, and `help` (actionable fix instruction)
336
+ - `warnings[]`: Non-blocking issues (locale coverage, empty JSON-LD fields)
337
+ - `trigger`: What caused this validation (`"file-change"`, `"manual"`, or `"startup"`)
338
+
339
+ **Workflow for AI agents:**
340
+ 1. Make changes to schema or content files
341
+ 2. If dev mode is running, wait for auto-validation
342
+ 3. If dev mode is not running, execute `supatent validate`
343
+ 4. Read `.supatent/.validation-status.json`
344
+ 5. If `valid: false`, read `errors[]` and fix each issue using the `help` text
345
+ 6. Repeat until `valid: true`