@decantr/essence-spec 1.0.1 → 1.0.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decantr/essence-spec",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Essence schemas, validation, migration, and TypeScript types for Decantr",
5
5
  "author": "Decantr AI",
6
6
  "license": "MIT",
@@ -157,7 +157,12 @@
157
157
  "shell_override": { "oneOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }] },
158
158
  "layout": { "type": "array", "items": { "$ref": "#/$defs/LayoutItem" }, "minItems": 1 },
159
159
  "dna_overrides": { "$ref": "#/$defs/DNAOverrides" },
160
- "surface": { "type": "string" }
160
+ "surface": { "type": "string" },
161
+ "directives": {
162
+ "type": "array",
163
+ "description": "Execution-level directives for this page — short imperative guidance that belongs in the pack contract (not the narrative doc). Each entry is one actionable rule the cold LLM should obey when implementing this route. Examples: '3-step checkout flow (Shipping → Payment → Review)', 'Auth bypass: accept any credentials and redirect to /shop', 'Skeleton placeholders render with d-annotation[data-loading]'.",
164
+ "items": { "type": "string", "minLength": 1 }
165
+ }
161
166
  }
162
167
  },
163
168
  "BlueprintSection": {
@@ -171,7 +176,46 @@
171
176
  "features": { "type": "array", "items": { "type": "string" } },
172
177
  "description": { "type": "string", "minLength": 1 },
173
178
  "pages": { "type": "array", "items": { "$ref": "#/$defs/BlueprintPage" }, "minItems": 1 },
174
- "dna_overrides": { "$ref": "#/$defs/DNAOverrides" }
179
+ "dna_overrides": { "$ref": "#/$defs/DNAOverrides" },
180
+ "navigation_items": {
181
+ "type": "array",
182
+ "description": "Items to render in the shell's primary navigation for this section. Provides the contract so LLMs don't have to improvise sidebar/top-nav lists.",
183
+ "items": { "$ref": "#/$defs/SectionNavigationItem" }
184
+ },
185
+ "directives": {
186
+ "type": "array",
187
+ "description": "Execution-level directives for this section — short imperative rules the cold LLM should obey when implementing any page in this section. Belongs in the pack contract (not the narrative doc). Examples: 'Header is 52px, use d-interactive[data-size=sm] for all action buttons', 'Dev mode: localStorage flag `decantr_authenticated` gates protected routes', 'Hotkey chords bind keyboard only — never render them as visible nav labels'.",
188
+ "items": { "type": "string", "minLength": 1 }
189
+ }
190
+ }
191
+ },
192
+ "SectionNavigationItem": {
193
+ "type": "object",
194
+ "required": ["label", "route"],
195
+ "additionalProperties": false,
196
+ "properties": {
197
+ "label": { "type": "string", "minLength": 1 },
198
+ "route": { "type": "string", "minLength": 1, "description": "Route path (e.g., '/agents')." },
199
+ "icon": {
200
+ "type": "string",
201
+ "minLength": 1,
202
+ "description": "Icon identifier. Typically a Lucide icon name in kebab-case."
203
+ },
204
+ "hotkey": {
205
+ "type": "string",
206
+ "minLength": 1,
207
+ "description": "Keyboard shortcut used to invoke this item (matches a hotkey key string)."
208
+ },
209
+ "active_match": {
210
+ "type": "string",
211
+ "minLength": 1,
212
+ "description": "Regex or path prefix the shell uses to decide if this item is 'active' for the current route. Defaults to exact match of `route`."
213
+ },
214
+ "badge": {
215
+ "type": "string",
216
+ "minLength": 1,
217
+ "description": "Optional short badge label (e.g., 'beta', '3') rendered on the item."
218
+ }
175
219
  }
176
220
  },
177
221
  "RouteEntry": {
@@ -265,7 +309,13 @@
265
309
  "additionalProperties": false,
266
310
  "properties": {
267
311
  "hotkeys": { "type": "array", "items": { "$ref": "#/$defs/NavigationHotkey" } },
268
- "command_palette": { "type": "boolean" }
312
+ "command_palette": {
313
+ "oneOf": [
314
+ { "type": "boolean" },
315
+ { "$ref": "#/$defs/CommandPaletteContract" }
316
+ ]
317
+ },
318
+ "hotkey_semantics": { "$ref": "#/$defs/HotkeySemantics" }
269
319
  }
270
320
  },
271
321
  "NavigationHotkey": {
@@ -276,7 +326,75 @@
276
326
  "key": { "type": "string", "minLength": 1 },
277
327
  "label": { "type": "string", "minLength": 1 },
278
328
  "route": { "type": "string", "minLength": 1 },
279
- "action": { "type": "string", "minLength": 1 }
329
+ "action": { "type": "string", "minLength": 1 },
330
+ "semantics": { "$ref": "#/$defs/HotkeySemantics" }
331
+ }
332
+ },
333
+ "CommandPaletteContract": {
334
+ "type": "object",
335
+ "additionalProperties": false,
336
+ "description": "Structured contract for the command palette. When present, LLMs should match exactly instead of improvising trigger/styling.",
337
+ "properties": {
338
+ "trigger": {
339
+ "type": "string",
340
+ "minLength": 1,
341
+ "description": "Keyboard shortcut that opens the palette. Platform-neutral form (e.g., 'Cmd+K' implies Cmd on Mac and Ctrl elsewhere)."
342
+ },
343
+ "placeholder": {
344
+ "type": "string",
345
+ "description": "Placeholder text shown in the palette's search input."
346
+ },
347
+ "width": {
348
+ "type": "string",
349
+ "description": "Preferred width (CSS length, e.g., '640px' or '40rem')."
350
+ },
351
+ "styling": {
352
+ "type": "string",
353
+ "enum": ["modal", "sheet", "inline", "fullscreen"],
354
+ "description": "Visual presentation mode. 'modal' = centered dialog, 'sheet' = slide-over, 'inline' = inline dropdown, 'fullscreen' = full-viewport (typical mobile default)."
355
+ },
356
+ "commands": {
357
+ "type": "array",
358
+ "description": "Command vocabulary. If omitted, LLMs may seed a minimal default from declared routes.",
359
+ "items": {
360
+ "type": "object",
361
+ "required": ["id", "label"],
362
+ "additionalProperties": false,
363
+ "properties": {
364
+ "id": { "type": "string", "minLength": 1 },
365
+ "label": { "type": "string", "minLength": 1 },
366
+ "section": { "type": "string", "minLength": 1 },
367
+ "hotkey": { "type": "string", "minLength": 1 },
368
+ "action": { "type": "string", "minLength": 1 },
369
+ "route": { "type": "string", "minLength": 1 }
370
+ }
371
+ }
372
+ }
373
+ }
374
+ },
375
+ "HotkeySemantics": {
376
+ "type": "object",
377
+ "additionalProperties": false,
378
+ "description": "Behavioral directives for hotkey handlers. Declared once globally in NavigationHints.hotkey_semantics OR per-hotkey on NavigationHotkey.semantics (per-key wins).",
379
+ "properties": {
380
+ "chord_window_ms": {
381
+ "type": "integer",
382
+ "minimum": 100,
383
+ "maximum": 5000,
384
+ "description": "For chord hotkeys (e.g., 'g a'), the max ms between keystrokes before the chord resets. Typical value: 900."
385
+ },
386
+ "input_guard": {
387
+ "type": "boolean",
388
+ "description": "If true (default): hotkeys do NOT fire while focus is inside an editable element (input, textarea, contenteditable). Avoids keyboard-conflict with user typing."
389
+ },
390
+ "modifier_suppression": {
391
+ "type": "boolean",
392
+ "description": "If true (default): hotkeys do NOT fire when a modifier (Meta/Ctrl/Alt) is held unless the hotkey itself declares the modifier in its key string."
393
+ },
394
+ "match_case": {
395
+ "type": "boolean",
396
+ "description": "If true: hotkey key matching is case-sensitive (distinguishes 'g' from 'G'). Default: false — uppercase letter implies Shift modifier."
397
+ }
280
398
  }
281
399
  },
282
400
  "Impression": {