@synap-core/workspace-templates 0.9.4 → 0.11.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.
package/dist/index.d.ts CHANGED
@@ -138,6 +138,28 @@ interface TemplateEntityLink {
138
138
  type: string;
139
139
  label?: string;
140
140
  }
141
+ /**
142
+ * A domain-level relation TYPE definition — a `relation_defs` row, the workspace's
143
+ * relation vocabulary. Distinct from {@link TemplateEntityLink}, which is a
144
+ * profile→profile EDGE (and only carries `type` + `label`). A relation def stands
145
+ * alone: it has no source/target profile pairing and it carries the rich metadata
146
+ * (`description`, `isDirectional`, `uiHints`) that the entity-link path drops.
147
+ *
148
+ * Mirrors `DefaultRelationDef` in synap-backend
149
+ * `packages/database/src/utils/default-relation-defs.ts` VERBATIM — the door
150
+ * find-or-creates a `relation_defs` row from each entry (idempotent by
151
+ * `slug` within the workspace), which is `ensureDefaultRelationDefs`'s body.
152
+ */
153
+ interface TemplateRelationDef {
154
+ slug: string;
155
+ displayName: string;
156
+ description?: string;
157
+ isDirectional?: boolean;
158
+ uiHints?: {
159
+ category?: "workflow" | "social" | "reference" | "hierarchy";
160
+ inverseLabel?: string;
161
+ };
162
+ }
141
163
  interface TemplateSeedEntity {
142
164
  profileSlug: string;
143
165
  title: string;
@@ -352,6 +374,22 @@ interface TemplateAutomation {
352
374
  };
353
375
  status?: "draft" | "active" | "paused";
354
376
  }
377
+ interface TemplateCommandDerivedInput {
378
+ name: string;
379
+ label?: string;
380
+ /** Mirrors `DerivedInput.type` (text | number | entity | view | choice). */
381
+ type?: string;
382
+ }
383
+ interface TemplateCommand {
384
+ title: string;
385
+ promptTemplate: string;
386
+ derivedInputs?: TemplateCommandDerivedInput[];
387
+ /** text | proposal | view */
388
+ outputMode?: string;
389
+ canCreateViews?: boolean;
390
+ /** read_only | propose_writes */
391
+ permissionsProfile?: string;
392
+ }
355
393
  interface TemplateActionPlacement {
356
394
  /** Entity kind whose detail surface this action appears on. */
357
395
  profileSlug: string;
@@ -417,43 +455,37 @@ interface TemplateExtendsRef {
417
455
  * PACKAGE_DEPENDENCY_KINDS — the dependency-kind vocabulary, declared ONCE.
418
456
  *
419
457
  * This tuple exists so consumers can IMPORT the vocabulary instead of
420
- * hand-copying it. `TemplateDependency` is currently mirrored by hand in six
421
- * other places, four of which carry a comment promising they match "VERBATIM so
422
- * the wire shape never drifts" — a comment doing a type's job. A comment cannot
423
- * fail a build; an import can. Those mirrors live in repos this package does not
424
- * own, so this tuple does not fix them by existing — it makes the fix possible:
458
+ * hand-copying it. `TemplateDependency` is mirrored by hand in several other
459
+ * places — a comment cannot fail a build, an import can, but these mirrors live
460
+ * in repos this package does not own, so they must match this list EXACTLY:
425
461
  *
426
- * - marketplace `types.ts:102`
427
- * - onboarding `workspace-templates.ts:27`
428
- * - synap-backend `package-definition.ts:204` (exports its own
429
- * `PackageDependencyKind` — the closest peer)
430
- * - hub-protocol REST `rest/packages.ts:140` (zod enum)
431
- * - browser `InstallPackageDialog.tsx:262`
432
- * - control-plane-api `routes/packages.ts:436` (zod enum)
462
+ * - marketplace `features/marketplace/src/types.ts`
463
+ * - onboarding `features/onboarding/src/{templates/workspace-templates,components/WorkspacePreview}.ts(x)`
464
+ * - browser `InstallPackageDialog.tsx`
465
+ * - synap-backend `package-definition.ts` (`PackageDependencyKind`)
466
+ * - hub-protocol REST `rest/packages.ts` (zod enum)
467
+ * - control-plane-api `db/schema/packages.ts` (`TemplateDependency` type)
468
+ * + `routes/packages.ts` (`DEPENDENCY_KINDS` zod enum)
433
469
  *
434
- * ⚠️ `'automation'` IS RETIRED VOCABULARY, deliberately still listed here.
435
- * CP migration `0049_package_vocabulary` retired the `automation` package
436
- * category in favour of `workflow` ("workflow — a triggered/sequenced run
437
- * (absorbs 'automation' + 'playbook')", `PACKAGE_TYPES` in CP
438
- * `db/schema/packages.ts`). A dependency's `kind` names the TYPE of package it
439
- * points at, so this vocabulary should track `PACKAGE_TYPES` — meaning the live
440
- * spelling is `workflow`, not `automation`.
470
+ * These are the 7 literals the wire accepts, in lockstep with the CP publish
471
+ * enum (`DEPENDENCY_KINDS = [...PACKAGE_TYPES, "automation"]`, CP
472
+ * `routes/packages.ts`), the hub install enum (`rest/packages.ts`), and the
473
+ * backend resolver's `PackageDependencyKind` (`@synap/database`).
441
474
  *
442
- * It is NOT renamed here, on purpose. This is latent, not live: 0/21 templates
443
- * declare any `kind` other than the default `'workspace'`. And all four wire
444
- * enums (CP + hub zod, above) still accept `'automation'` and do NOT accept
445
- * `'workflow'` — so emitting `'workflow'` today would be rejected with a 400 at
446
- * both doors, and dropping `'automation'` from this tuple would make any
447
- * consumer that derives a zod enum from it start rejecting a value the wire
448
- * still legally accepts (a published third-party package may carry it; CP's own
449
- * schema permits it). Narrowing must therefore follow the wire, not lead it.
475
+ * Resolver behaviour (backend `package-dependency-resolver.ts`):
476
+ * - `workspace` → resolve+install; the ONLY kind that may `compose`.
477
+ * - `capability` / `cell` → resolve+install, always `require`d (presence).
478
+ * - `skill` / `workflow` / `view` / `automation` → ACCEPTED and `require`d
479
+ * present, surfaced as `required-absent` (non-fatal) — no standalone by-slug
480
+ * applier on the pod yet; when one grows, give the kind its own branch.
450
481
  *
451
- * ORDERED FIX (each step deployable alone, no flag day):
452
- * 1. Widen the CP + hub zod enums to accept BOTH `'automation'` and `'workflow'`.
453
- * 2. Add `'workflow'` here; mark `'automation'` deprecated; migrate any authored use.
454
- * 3. Once no payload carries `'automation'`, drop it from the wire enums and this tuple.
482
+ * `'automation'` is legacy vocabulary: CP migration `0049_package_vocabulary`
483
+ * renamed the `automation` package category → `workflow` (which absorbs
484
+ * automation + playbook, `PACKAGE_TYPES` in CP `db/schema/packages.ts`). It
485
+ * stays accepted on the wire — and therefore in this tuple — for back-compat
486
+ * with dependencies published before the rename.
455
487
  */
456
- declare const PACKAGE_DEPENDENCY_KINDS: readonly ["workspace", "capability", "automation"];
488
+ declare const PACKAGE_DEPENDENCY_KINDS: readonly ["workspace", "capability", "skill", "workflow", "view", "cell", "automation"];
457
489
  /** What a `TemplateDependency` points at. Derived — never re-declare the list. */
458
490
  type PackageDependencyKind = (typeof PACKAGE_DEPENDENCY_KINDS)[number];
459
491
  interface TemplateDependency {
@@ -461,8 +493,8 @@ interface TemplateDependency {
461
493
  slug: string;
462
494
  /**
463
495
  * What the dependency is. Default `'workspace'`. Only `'workspace'`
464
- * dependencies can be `compose`d; `'capability'`/`'automation'` are always
465
- * `require`d present without merging.
496
+ * dependencies can be `compose`d; every other kind is always `require`d
497
+ * present without merging.
466
498
  */
467
499
  kind?: PackageDependencyKind;
468
500
  /**
@@ -537,6 +569,19 @@ interface WorkspaceYaml {
537
569
  views?: TemplateView[];
538
570
  /** Schema-level links between entity types */
539
571
  entityLinks?: TemplateEntityLink[];
572
+ /**
573
+ * Domain-level relation TYPE vocabulary seeded into the workspace's
574
+ * `relation_defs`. Distinct from `entityLinks` (profile→profile edges): a
575
+ * relation def stands alone and carries `description`/`isDirectional`/`uiHints`.
576
+ * The `base` template carries the universal defaults. See {@link TemplateRelationDef}.
577
+ */
578
+ relationDefs?: TemplateRelationDef[];
579
+ /**
580
+ * Workspace-scoped intelligence commands (prompt-template "Default Command
581
+ * Pack") seeded with the workspace. The `base` template carries the universal
582
+ * pack. See {@link TemplateCommand}.
583
+ */
584
+ commands?: TemplateCommand[];
540
585
  /** Initial data to seed on workspace creation */
541
586
  seedEntities?: TemplateSeedEntity[];
542
587
  /** Relations between seed entities, created on provisioning */
@@ -630,6 +675,19 @@ declare function listPublicTemplates(): WorkspaceYaml[];
630
675
  * in the consumers; this door only merges arrays they already fetched.
631
676
  */
632
677
 
678
+ /**
679
+ * A lightweight, QUERY-TIME summary of one sub-object a package carries (a cell
680
+ * today; the shape generalizes to views/automations without change). Rides the
681
+ * catalog LIST projection so a surface can match/surface a sub-item WITHOUT the
682
+ * full `definition` — it carries `key + name` only, never the sub-object's code.
683
+ * `kind` is DERIVED (in the CP SELECT, from which sub-array the row came from),
684
+ * never a stored taxonomy.
685
+ */
686
+ interface PackageItemSummary {
687
+ kind: string;
688
+ key: string;
689
+ name: string;
690
+ }
633
691
  /**
634
692
  * A bundled template — the canonical `WorkspaceYaml` this package ships. Callers
635
693
  * pass `listPublicTemplates()` (18) or `listWorkspaceTemplates()` (21); the door
@@ -665,6 +723,13 @@ interface RemoteEntry {
665
723
  * never "unknown-so-hide".
666
724
  */
667
725
  isPrivate?: boolean;
726
+ /**
727
+ * Lightweight computed summary of the row's sub-objects (cells), carried on the
728
+ * LIST projection so a surface can surface a matching sub-item without the full
729
+ * `definition`. `undefined` on sources that don't compute it (bundled) — treated
730
+ * as "no known sub-items". See `PackageItemSummary`.
731
+ */
732
+ items?: PackageItemSummary[];
668
733
  /**
669
734
  * The CP `definition` jsonb — opaque install payload. The door reads only
670
735
  * `definition.sourcePackage.version` (the winner signal). Absent on browse rows
@@ -724,6 +789,11 @@ interface CpPackageRow {
724
789
  icon?: string | null;
725
790
  /** Present only on `/mine` rows. `false` ⇒ private. Browse rows omit it. */
726
791
  isPublic?: boolean;
792
+ /**
793
+ * Computed sub-object summary from `GET /api/packages` / `/mine` (query-time,
794
+ * not a stored column). Carries `key + name` per cell; never the cell code.
795
+ */
796
+ items?: PackageItemSummary[];
727
797
  }
728
798
  /**
729
799
  * Map a CP list row into the merge door's `RemoteEntry`. THE canonical mapping —
@@ -749,6 +819,12 @@ interface CatalogEntryBase {
749
819
  icon?: string | null;
750
820
  /** `true` ⇒ not publicly listed (internal bundled template, or private CP row). */
751
821
  isPrivate: boolean;
822
+ /**
823
+ * The entry's sub-object summary (cells). Always present (defaults to `[]`) so a
824
+ * consumer can match sub-items uniformly. Bundled workspace templates carry no
825
+ * cells → `[]` (honest); a remote row carries its CP-computed `items`.
826
+ */
827
+ items: PackageItemSummary[];
752
828
  }
753
829
  /** A catalog entry backed by a bundled template. Install via `toWorkspaceDefinition()` / `toPackageDefinition()` on `template`. */
754
830
  interface BundledCatalogEntry extends CatalogEntryBase {
@@ -977,9 +1053,11 @@ declare function layerTemplateGraph(input: LayerTemplateGraphInput): Composition
977
1053
  * Cross-template CONCEPT guard — catches vocabulary forks between templates.
978
1054
  *
979
1055
  * WHY THIS EXISTS (read before weakening or deleting it):
980
- * `business-developer.yaml` introduced workspace-scoped `crm-lead`/`crm-client`
981
- * for the same real-world concept that `foundation.yaml`/`crm.yaml` declare as
982
- * pod-wide shared `lead`/`client`. Nothing failed. Three reasons:
1056
+ * `business-developer.yaml` once introduced workspace-scoped
1057
+ * `crm-lead`/`crm-client` for the same real-world concept that
1058
+ * `foundation.yaml`/`crm.yaml` declare as pod-wide shared `lead`/`client` (that
1059
+ * fork has since been collapsed back onto the shared slugs). Nothing failed at
1060
+ * the time. Three reasons:
983
1061
  *
984
1062
  * 1. `build.mjs`'s `validate()` runs PER FILE, inside the read loop, so it
985
1063
  * structurally cannot see that another template already owns `lead`.
@@ -1017,6 +1095,13 @@ interface ConceptViolation {
1017
1095
  * list cannot rot into a graveyard.
1018
1096
  *
1019
1097
  * Key = the two colliding profile slugs, sorted, joined by "|".
1098
+ *
1099
+ * Currently EMPTY, and that is the healthy state. The two entries this list was
1100
+ * born for — `crm-lead|lead` and `client|crm-client` — were RESOLVED rather
1101
+ * than kept: business-developer.yaml now re-declares the shared `lead`/`client`
1102
+ * roles and carries its business-development fields as workspace-overlay
1103
+ * PROPERTIES. One concept, one slug, workspace-specific fields. Rule 3 below
1104
+ * would have failed CI had the entries been left behind.
1020
1105
  */
1021
1106
  declare const DECLARED_DIVERGENCES: Record<string, string>;
1022
1107
  /**
@@ -1029,7 +1114,14 @@ declare const DECLARED_DIVERGENCES: Record<string, string>;
1029
1114
  * is honest: no guard can know they mean the same thing.
1030
1115
  */
1031
1116
  declare function conceptTerm(semanticSlug: string): string;
1032
- declare function findConceptViolations(templates?: Record<string, WorkspaceYaml>): ConceptViolation[];
1117
+ declare function findConceptViolations(templates?: Record<string, WorkspaceYaml>,
1118
+ /**
1119
+ * The declared-divergence allowlist to enforce against. Defaults to the real
1120
+ * one; injectable so the escape-hatch semantics (rule 1 suppression, rule 3
1121
+ * staleness) stay testable now that the shipped list is empty — previously
1122
+ * those tests could only be written because a live entry happened to exist.
1123
+ */
1124
+ declaredDivergences?: Record<string, string>): ConceptViolation[];
1033
1125
  declare function formatConceptViolations(violations: ConceptViolation[]): string;
1034
1126
 
1035
1127
  /**
@@ -1262,18 +1354,18 @@ declare function validateTemplate(tpl: WorkspaceYaml, opts?: ValidateOptions): V
1262
1354
  * Until then: keep the constant arrays below identical to `@synap/database`
1263
1355
  * `schema/automations.ts`.
1264
1356
  */
1265
- /** The 21 node types — `AutomationNodeBase.type` union (schema/automations.ts). */
1266
- declare const FLOW_NODE_TYPES: readonly ["trigger", "command", "condition", "delay", "output", "loop", "transform", "fetch", "query", "entity_read", "related_entities", "guard", "compute", "select", "claim", "messages_query", "switch", "skill", "capability", "sub_automation", "playbook_run"];
1357
+ /** The 23 node types — `AutomationNodeBase.type` union (schema/automations.ts). */
1358
+ declare const FLOW_NODE_TYPES: readonly ["trigger", "command", "condition", "delay", "output", "loop", "transform", "fetch", "query", "entity_read", "related_entities", "guard", "compute", "select", "claim", "messages_query", "runs_query", "proposals_query", "switch", "skill", "capability", "sub_automation", "playbook_run"];
1267
1359
  /** The 11 output types — `OutputNodeDef.data.outputType` (schema/automations.ts). */
1268
1360
  declare const FLOW_OUTPUT_TYPES: readonly ["notification", "entity_create", "entity_update", "facet_attach", "facet_update", "facet_detach", "relation_create", "webhook", "channel_message", "session_update", "set_state"];
1269
1361
  /**
1270
1362
  * The known `config.channelType` values for a `channel_message` output. Mirrors
1271
1363
  * the executor's channel_message resolution (automation-executor.ts). The output
1272
- * channel is CONTEXT-DERIVED — a channel_message is valid with `channelId`, OR
1273
- * `channelEntityRef` (an entity-id expression → that entity's internal channel),
1274
- * OR a `channelType` from this set, OR NOTHING (the executor defaults a targetless
1275
- * channel_message to the automation's own run channel). A `channelType` that is
1276
- * PRESENT but not one of these is still a typo → still an error.
1364
+ * channel is now CONTEXT-DERIVED — a channel_message is valid with `channelId`,
1365
+ * OR `channelEntityRef` (an entity-id expression → that entity's internal
1366
+ * channel), OR a `channelType` from this set, OR NOTHING (the executor defaults a
1367
+ * targetless channel_message to the automation's own run channel). A `channelType`
1368
+ * that is PRESENT but not one of these is still a typo → still an error.
1277
1369
  */
1278
1370
  declare const CHANNEL_MESSAGE_CHANNEL_TYPES: readonly ["personal_thread", "proactive", "subjectEntity"];
1279
1371
  interface FlowValidationError {
@@ -1390,6 +1482,19 @@ interface WorkspaceDefinitionInput {
1390
1482
  seedEntities: NonNullable<WorkspaceYaml['seedEntities']>;
1391
1483
  suggestedRelations?: WorkspaceYaml['suggestedRelations'];
1392
1484
  displayTemplates?: WorkspaceYaml['displayTemplates'];
1485
+ /**
1486
+ * Domain-level relation TYPE vocabulary — the door find-or-creates a
1487
+ * `relation_defs` row per entry (idempotent by slug within the workspace). NOT
1488
+ * `entityLinks` (those are profile→profile edges and drop the rich metadata).
1489
+ * Carried verbatim; the authored form IS the wire form.
1490
+ */
1491
+ relationDefs?: WorkspaceYaml['relationDefs'];
1492
+ /**
1493
+ * Workspace intelligence commands — the door find-or-creates an
1494
+ * `intelligence_commands` row per entry (idempotent by title). Carried
1495
+ * verbatim; the authored form IS the wire form.
1496
+ */
1497
+ commands?: WorkspaceYaml['commands'];
1393
1498
  layoutConfig: WorkspaceYaml['layout'] | undefined;
1394
1499
  bentoViewName?: string;
1395
1500
  /**
@@ -1494,6 +1599,10 @@ interface PackageDefinitionOutput {
1494
1599
  suggestedRelations?: WorkspaceYaml['suggestedRelations'];
1495
1600
  displayTemplates?: WorkspaceYaml['displayTemplates'];
1496
1601
  entityLinks?: WorkspaceYaml['entityLinks'];
1602
+ /** Relation-type vocabulary — carried verbatim (authored form IS the wire form). */
1603
+ relationDefs?: WorkspaceYaml['relationDefs'];
1604
+ /** Intelligence commands — carried verbatim (authored form IS the wire form). */
1605
+ commands?: WorkspaceYaml['commands'];
1497
1606
  /** WIDGET half of the authored bento union — mapped by the pod via `widgetType`. */
1498
1607
  bentoLayout?: BentoWidgetBlockWire[];
1499
1608
  /**