@unoverse-platform/studio 0.1.108 → 0.1.110

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.
Files changed (41) hide show
  1. package/README.md +1 -1
  2. package/bin/studio.mjs +3 -3
  3. package/local/authoring.ts +2 -2
  4. package/local/catalog.ts +8 -4
  5. package/local/design-home.d.mts +2 -0
  6. package/local/design-home.mjs +11 -0
  7. package/local/plugin.ts +51 -22
  8. package/local/sample-identity/brand.yaml +1 -1
  9. package/local/sample-identity/organisation.yaml +1 -1
  10. package/local/sample-identity/purpose.yaml +1 -1
  11. package/local/sample-identity/story.yaml +1 -1
  12. package/local/scaffold.mjs +20 -4
  13. package/local/source.ts +13 -7
  14. package/package.json +1 -1
  15. package/screens/DesignSystemView.tsx +1 -1
  16. package/screens/EmptyLibrary.tsx +1 -1
  17. package/screens/PromptBlocksView.tsx +1 -1
  18. package/src/App.tsx +5 -5
  19. package/vendor/base/src/definitions/load/assets.ts +2 -2
  20. package/vendor/base/src/definitions/registry/catalog.ts +1 -1
  21. package/vendor/base/src/definitions/registry/homes.ts +15 -5
  22. package/vendor/base/src/definitions/registry/objects.ts +1 -1
  23. package/vendor/base/src/definitions/registry/orgDocuments.ts +2 -2
  24. package/vendor/base/src/definitions/registry/orgPack.ts +3 -2
  25. package/vendor/base/src/definitions/registry/pipelines.ts +1 -1
  26. package/vendor/base/src/definitions/theme.ts +5 -6
  27. package/vendor/base/src/items/baseVersion.ts +1 -1
  28. package/vendor/base/src/items/collect.ts +1 -1
  29. package/vendor/base/src/lint/design/file.mjs +2 -2
  30. package/vendor/base/src/lint/design/index.d.mts +6 -0
  31. package/vendor/base/src/lint/design/index.mjs +45 -17
  32. package/vendor/base/src/lint/design/vocabulary.mjs +2 -2
  33. package/vendor/base/src/lint/nodes/blocks.mjs +3 -3
  34. package/vendor/base/src/lint/nodes/node.mjs +1 -1
  35. package/vendor/base/src/lint/objects/index.d.mts +6 -0
  36. package/vendor/base/src/lint/objects/index.mjs +27 -6
  37. package/vendor/base/src/lint/prompts/index.d.mts +6 -0
  38. package/vendor/base/src/lint/prompts/index.mjs +8 -3
  39. package/vendor/base/src/paths.ts +65 -20
  40. package/vendor/base/src/plugins/discovery.ts +1 -1
  41. package/vendor/base/src/plugins/loader.ts +5 -7
@@ -14,6 +14,12 @@ import * as path from "path";
14
14
  import { fileURLToPath } from "url";
15
15
  import { existsSync, renameSync } from "fs";
16
16
 
17
+ /**
18
+ * Where the marketplace package keeps the tier, relative to the repo that holds it. Also the
19
+ * platform repo's marker (findHome), so it is declared before anything resolves.
20
+ */
21
+ const MARKETPLACE_IN_REPO = path.join("packages", "marketplace", "definitions");
22
+
17
23
  /**
18
24
  * Find the content home when nobody said.
19
25
  *
@@ -27,11 +33,17 @@ function findHome(): string {
27
33
 
28
34
  let dir = path.dirname(fileURLToPath(import.meta.url));
29
35
  for (;;) {
30
- // The in-repo home. Checked for `design` as well as the folder itself, so a stray
31
- // directory of the same name elsewhere cannot claim it. (`nodes` was the marker until
32
- // 2026-09-08, when nodes moved under design/marketplace with every other kind.)
36
+ // The in-repo home: `apps/unoverse` in a repo that also carries the marketplace tier
37
+ // (`packages/marketplace/definitions`), so a stray `apps/unoverse` elsewhere cannot
38
+ // claim it. The marker was `apps/unoverse/design` until 2026-10-04, when the design tree
39
+ // was retired (orgs live in their own repos, the tier in the marketplace package, the
40
+ // editor schemas on the docs site); `nodes` was the marker before 2026-09-08.
41
+ //
42
+ // NEITHER MARKER IS IN AN IMAGE. `.dockerignore` excludes the marketplace tier exactly
43
+ // as it excluded the design tree, so a deployed universe finds nothing here and falls
44
+ // back below, as it always has.
33
45
  const candidate = path.join(dir, "apps/unoverse");
34
- if (existsSync(path.join(candidate, "design"))) return candidate;
46
+ if (existsSync(path.join(dir, MARKETPLACE_IN_REPO)) && existsSync(candidate)) return candidate;
35
47
  const parent = path.dirname(dir);
36
48
  if (parent === dir) break;
37
49
  dir = parent;
@@ -41,8 +53,9 @@ function findHome(): string {
41
53
  // produced the silent-wrong-path failures, so say so instead: every export below becomes
42
54
  // a path under cwd, and anything reading them will fail somewhere obvious.
43
55
  console.warn(
44
- "[unoverse:base] UNOVERSE_HOME is not set and no apps/unoverse was found above this package. " +
45
- "Falling back to the working directory; set UNOVERSE_HOME to the folder holding design/.",
56
+ "[unoverse:base] UNOVERSE_HOME is not set and no platform repo (apps/unoverse beside " +
57
+ "packages/marketplace/definitions) was found above this package. Falling back to the " +
58
+ "working directory; set UNOVERSE_HOME to the content home.",
46
59
  );
47
60
  return process.cwd();
48
61
  }
@@ -51,9 +64,13 @@ let HOME = findHome();
51
64
 
52
65
  /** Everything the runtime reads off disk, in one place. */
53
66
  export interface Paths {
54
- /** Node packages: the marketplace tier's nodes, under design/marketplace/nodes. */
67
+ /** Node packages: the marketplace tier's nodes, `<marketplace>/nodes`. */
55
68
  nodes: string;
56
- /** Design data: components, templates, styles. */
69
+ /**
70
+ * The design tree, `<home>/design`: one folder per org in a workspace that keeps orgs this
71
+ * way. ABSENT in the platform repo (retired 2026-10-04) and on a deployed universe, and every
72
+ * reader takes an absent tree as "no org tier here", never as an error.
73
+ */
57
74
  design: string;
58
75
  /** Authored agent skills (SKILL.md). */
59
76
  skills: string;
@@ -63,7 +80,13 @@ export interface Paths {
63
80
  plugins: string;
64
81
  /** LEGACY: the pre-migration node package folders. Usually absent. */
65
82
  packages: string;
66
- /** LEGACY: the pre-migration marketplace folder. Usually absent. */
83
+ /**
84
+ * THE MARKETPLACE TIER on disk: components, atoms, templates, styles, objects, pipelines,
85
+ * skills, blocks and nodes. In the monorepo it is `packages/marketplace/definitions`, the
86
+ * folder the marketplace package publishes, authored where it ships. Absent anywhere else
87
+ * (a deployed universe, a developer's project), where the tier comes from installed rows
88
+ * or the installed package instead. Every reader of the tier starts here.
89
+ */
67
90
  marketplace: string;
68
91
  /**
69
92
  * AN ORG'S OWN REPO (UNO-88). When set, the home IS this one org: its folders at the root,
@@ -100,19 +123,40 @@ export function designDir(root: string): string {
100
123
  return design;
101
124
  }
102
125
 
126
+ /**
127
+ * Find the marketplace tier for a home: `packages/marketplace/definitions` in the repo that
128
+ * holds the home, which is the home itself or the nearest folder above it carrying one.
129
+ *
130
+ * ANCHORED ON THE FOLDER, like findHome, never on a depth. A home with no such folder above
131
+ * it (a deployed universe, a developer's project, a test's scratch home) gets the path it
132
+ * would have inside the home itself, which does not exist, so the tier there resolves from
133
+ * installed rows or the installed package exactly as it did when the tier lived elsewhere.
134
+ */
135
+ function findMarketplace(home: string): string {
136
+ for (let dir = home; ; ) {
137
+ const candidate = path.join(dir, MARKETPLACE_IN_REPO);
138
+ if (existsSync(candidate)) return candidate;
139
+ const parent = path.dirname(dir);
140
+ if (parent === dir) break;
141
+ dir = parent;
142
+ }
143
+ return path.join(home, MARKETPLACE_IN_REPO);
144
+ }
145
+
103
146
  function derive(home: string): Paths {
147
+ const marketplace = findMarketplace(home);
104
148
  return {
105
149
  design: designDir(home),
106
- // THE MARKETPLACE TIER, and it lives under design/ with every other kind.
150
+ // THE MARKETPLACE TIER, ONE ROOT FOR EVERY KIND (`marketplace` below).
107
151
  //
108
- // Skills and blocks were authored in a `prompts/` folder beside design/, left from
109
- // before components, templates, atoms and styles took their marketplace home under
110
- // `design/marketplace/`. Two roots for one tier is what let a surface read half of
111
- // it and look right. There is one authoring root now: `design/`. Nodes were the
112
- // last kind outside it, at `nodes/` beside design/, until 2026-09-08.
113
- nodes: path.join(designDir(home), "marketplace/nodes"),
114
- skills: path.join(designDir(home), "marketplace/skills"),
115
- promptBlocks: path.join(designDir(home), "marketplace/blocks"),
152
+ // Skills and blocks were authored in a `prompts/` folder beside design/, and nodes in
153
+ // `nodes/` beside it until 2026-09-08. Two roots for one tier is what let a surface
154
+ // read half of it and look right. The tier was then authored under
155
+ // `design/marketplace/` and copied into the marketplace package on every release; it
156
+ // is authored in the package now, so there is one copy and it is the one that ships.
157
+ nodes: path.join(marketplace, "nodes"),
158
+ skills: path.join(marketplace, "skills"),
159
+ promptBlocks: path.join(marketplace, "blocks"),
116
160
  plugins: path.join(home, "plugins"),
117
161
  // DELIBERATELY under the home, not at the repo root.
118
162
  //
@@ -121,7 +165,7 @@ function derive(home: string): Paths {
121
165
  // the @unoverse-platform scope with an entry point, so it found THIS package and
122
166
  // returned ["@unoverse-platform/base"] — the runtime being offered as a node.
123
167
  packages: path.join(home, "packages"),
124
- marketplace: path.join(home, "packages-marketplace"),
168
+ marketplace,
125
169
  };
126
170
  }
127
171
 
@@ -156,6 +200,8 @@ export const NODES_HOME = paths.nodes;
156
200
  export const DESIGN_HOME = paths.design;
157
201
  export const SKILLS_HOME = paths.skills;
158
202
  export const PROMPT_BLOCKS_HOME = paths.promptBlocks;
203
+ /** The marketplace tier on disk (`Paths.marketplace`). */
204
+ export const MARKETPLACE_HOME = paths.marketplace;
159
205
  /**
160
206
  * Where INSTALLED items are written so the loaders can read them (items/hydrate.ts).
161
207
  *
@@ -190,4 +236,3 @@ export function databaseOnly(): boolean {
190
236
  }
191
237
  export const PLUGINS_DIR = paths.plugins;
192
238
  export const PACKAGES_PATH = paths.packages;
193
- export const MARKETPLACE_PATH = paths.marketplace;
@@ -39,7 +39,7 @@ function scanPluginDir(dir: string, scopes: string[]): string[] {
39
39
  return plugins;
40
40
  }
41
41
 
42
- /** The marketplace tier's node packages (apps/unoverse/design/marketplace/nodes). */
42
+ /** The marketplace tier's node packages (packages/marketplace/definitions/nodes). */
43
43
  export function discoverNodesHome(): string[] {
44
44
  return scanPluginDir(NODES_HOME, ["@unoverse-platform/"]);
45
45
  }
@@ -7,7 +7,7 @@ import * as path from "path";
7
7
  import { execSync } from "child_process";
8
8
  import { pathToFileURL } from "url";
9
9
  import { getNodeRegistry, getPluginNodeMap, deleteNode } from "../registry.js";
10
- import { PACKAGES_PATH, MARKETPLACE_PATH, PLUGINS_DIR, NODES_HOME } from "../paths.js";
10
+ import { PACKAGES_PATH, PLUGINS_DIR, NODES_HOME } from "../paths.js";
11
11
 
12
12
  /**
13
13
  * Resolve a package directory's entry file from its package.json.
@@ -87,18 +87,16 @@ export async function loadPlugin(pluginName: string, api: any): Promise<string[]
87
87
 
88
88
  try {
89
89
  const shortName = pluginName.replace(/@[^/]+\//, "");
90
- // Resolution order: the in-Unoverse node home wins, then legacy /packages,
91
- // then /packages-marketplace, then the bare npm specifier.
90
+ // Resolution order: the in-Unoverse node home wins, then legacy /packages, then the
91
+ // bare npm specifier. (A `packages-marketplace` folder was searched third until the
92
+ // marketplace tier took that setting's name; no checkout or image had one.)
92
93
  const homePath = path.join(NODES_HOME, shortName);
93
94
  const pkgPath = path.join(PACKAGES_PATH, shortName);
94
- const mktPath = path.join(MARKETPLACE_PATH, shortName);
95
95
  const resolvedPath = fs.existsSync(homePath)
96
96
  ? homePath
97
97
  : fs.existsSync(pkgPath)
98
98
  ? pkgPath
99
- : fs.existsSync(mktPath)
100
- ? mktPath
101
- : pluginName;
99
+ : pluginName;
102
100
 
103
101
  const pkg = await importPluginModule(resolvedPath);
104
102
  const plugin = pkg.default || pkg;