@jarenjs/studio 0.75.0 → 0.83.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/README.md CHANGED
@@ -26,14 +26,19 @@ This package ships in two layers, the suite's convention:
26
26
  (hot-update via `app.setState`) and the drag splitter — which are
27
27
  browser-verified. Mounted live at the website's `#/project`, where `app`
28
28
  files boot, `jslt`/`query` files run against a data file, `contract`
29
- files render their `describe()`/OpenAPI projections, and files are
30
- added, renamed, deleted and opened from templates.
29
+ files render their `describe()`/OpenAPI projections, `fsm`/`dag` files
30
+ mount the Flow editor, and collection models run in private SQLite workers
31
+ with query plans and live results. All ten file kinds can be created,
32
+ renamed, deleted and opened from templates.
31
33
 
32
34
  ## The project document
33
35
 
34
36
  A thin envelope over typed files — the full contract is
35
37
  [PROJECT-FORMAT.md](docs/PROJECT-FORMAT.md).
36
38
 
39
+ `KINDS` lists all ten file kinds; `ADDABLE_KINDS` and `fileSkeleton` supply
40
+ the creation menu and starter text from one shared table.
41
+
37
42
  ```js
38
43
  import { parseProject, validateFile, assembleArtifacts, classifyChange, describe }
39
44
  from '@jarenjs/studio';
@@ -52,6 +57,24 @@ validateFile(project.files[1]); // { valid, kind, total, errors: [{ code, messag
52
57
  assembleArtifacts(project); // the runnable set
53
58
  ```
54
59
 
60
+ Files can import named members from other files: an app's `view`, `actions`
61
+ and `state` can each live in their own editor. The assembler checks references,
62
+ tracks dependencies and writes diagram edits back into their source files.
63
+ Explicit `input`, `model` and `collection` metadata route queries and model
64
+ seeds; the [format](docs/PROJECT-FORMAT.md) specifies ownership and lifetimes.
65
+
66
+ `@jarenjs/studio/author` exposes `createStudioFileAuthor({ client })`: generate
67
+ one file under its authoring profile, validate with the full engine, and repair
68
+ bounded failures before returning a candidate. The website assistant uses this
69
+ path and protects edits made while generation is running. No provider quality
70
+ claim is inferred from the mocked generation tests.
71
+
72
+ `@jarenjs/studio/export` exposes `exportProject(project, assets)` and
73
+ `createProjectZip(files)`. The website's **Offline ZIP** includes a standalone
74
+ runner and the installed runtime dependencies, including SQLite and fonts.
75
+ It runs from a local HTTP server without an install or external network.
76
+ Runtime rows remain transient; explicit seed files travel with the project.
77
+
55
78
  ## Why per-file validation
56
79
 
57
80
  The published `jaren-query` / `jaren-jslt` grammars are *closed*, so a data
@@ -77,6 +100,8 @@ Every subpath a consumer can import, derived from the manifest by
77
100
  | `@jarenjs/studio/schemas/jaren-project.schema.json` | schema | — |
78
101
  | `@jarenjs/studio/styles/studio.css` | asset | — |
79
102
  | `@jarenjs/studio/package.json` | metadata | — |
103
+ | `@jarenjs/studio/author` | JavaScript | declared |
104
+ | `@jarenjs/studio/export` | JavaScript | declared |
80
105
  <!--/fact-->
81
106
 
82
107
  ## Install
@@ -3,24 +3,21 @@
3
3
  * needs to decide reboot-vs-hot-update.
4
4
  *
5
5
  * `assembleArtifacts` composes the project's files into the runnable set.
6
- * This order ships the WHOLE-DOCUMENT contract: a runnable file (`app`,
7
- * `fsm`, `dag`, `model`, `jslt`, `query`, `schema`) is its own artifact;
8
- * `state`/`data` files are inputs, not artifacts. Fragment assembly —
9
- * composing separate `state` + `view` + `actions` files into ONE
10
- * `jaren-app` document (the true HTML/CSS/JS split) — is the model's
11
- * headline enhancement and layers on top without changing this contract.
6
+ * A runnable file can import named members from other project files;
7
+ * `sourceFiles` records the complete dependency chain. `state`/`data`
8
+ * files are inputs, not standalone artifacts.
12
9
  *
13
10
  * `classifyChange` is the load-bearing UX datum: a `state`-only edit must
14
11
  * HOT-DISPATCH into a running app (no reboot, the user keeps scroll and
15
12
  * inputs), while a `view`/`actions` change must reboot. It compares a
16
- * STRUCTURAL key (an app's `view`, `actions` and `subs`) via the suite's own
13
+ * STRUCTURAL key (all app members except `state`) via the suite's own
17
14
  * `semanticKey` — the collision-free identity, not the memo-grade
18
15
  * `contentKey` fingerprint: a classification decides whether a running
19
16
  * app reboots, so a fingerprint collision would read a changed document
20
17
  * as unchanged. The artifacts are parsed JSON, so the identity is total.
21
18
  */
22
19
  /**
23
- * Compose the project's files into runnable artifacts (whole-document).
20
+ * Compose the project's files into runnable artifacts, resolving imports.
24
21
  * @param {any} project - a normalized project (from `parseProject`)
25
22
  * @returns {{ artifacts: Array<{ name: string, kind: string, role: string,
26
23
  * doc: any, sourceFiles: string[] }>, errors: Array<{ file: string, message: string }> }}
@@ -0,0 +1,27 @@
1
+ export declare const AUTHORABLE_KINDS: readonly string[];
2
+ /** @param {{ client: any, operators?: any, maxRepairs?: number }} options */
3
+ export declare function createStudioFileAuthor(options: {
4
+ client: any;
5
+ operators?: any;
6
+ maxRepairs?: number;
7
+ }): {
8
+ /** @param {{ project: any, name: string, kind?: string, prompt: string }} request
9
+ * @param {{ signal?: AbortSignal }} [hooks] */
10
+ author(request: {
11
+ project: any;
12
+ name: string;
13
+ kind?: string;
14
+ prompt: string;
15
+ }, hooks?: {
16
+ signal?: AbortSignal;
17
+ }): Promise<{
18
+ errors: any[];
19
+ raw: string;
20
+ attempts: number;
21
+ } | {
22
+ value: any;
23
+ raw: string;
24
+ attempts: number;
25
+ file: any;
26
+ }>;
27
+ };
@@ -83,7 +83,9 @@ export declare function createStudioComponent(options?: {
83
83
  } | {
84
84
  class?: undefined;
85
85
  $if: ((string | (string | {
86
- name: string;
86
+ name: {
87
+ $default: string[];
88
+ };
87
89
  props: string;
88
90
  })[] | {
89
91
  class: string;
@@ -111,6 +113,33 @@ export declare function createStudioComponent(options?: {
111
113
  })[];
112
114
  $eq?: undefined;
113
115
  })[];
116
+ })[] | (string | (string | {
117
+ class: string;
118
+ type: string;
119
+ 'aria-pressed': {
120
+ $if: string[];
121
+ };
122
+ on: {
123
+ click: string;
124
+ };
125
+ })[] | (string | {
126
+ class: string;
127
+ type: string;
128
+ on: {
129
+ click: string;
130
+ };
131
+ })[] | (string | any[] | {
132
+ class: string;
133
+ role: string;
134
+ 'aria-label': string;
135
+ })[] | (string | {
136
+ $apply: string;
137
+ }[] | (string | {
138
+ class: string;
139
+ })[] | {
140
+ class: string;
141
+ })[] | {
142
+ class: string;
114
143
  })[] | (string | (string | {
115
144
  class: string;
116
145
  rows: number;
@@ -158,6 +187,21 @@ export declare function createStudioComponent(options?: {
158
187
  role: string;
159
188
  })[])[];
160
189
  class?: undefined;
190
+ } | {
191
+ $if: (string | (string | {
192
+ class: string;
193
+ $if?: undefined;
194
+ } | {
195
+ $if: (string | {}[])[];
196
+ class?: undefined;
197
+ } | {
198
+ $if: (string | {}[])[];
199
+ class?: undefined;
200
+ } | {
201
+ $if: (string | {}[])[];
202
+ class?: undefined;
203
+ })[])[];
204
+ class?: undefined;
161
205
  } | {
162
206
  $if: (string | (string | {
163
207
  $apply: string;
@@ -166,33 +210,6 @@ export declare function createStudioComponent(options?: {
166
210
  role: string;
167
211
  })[])[];
168
212
  class?: undefined;
169
- })[] | (string | (string | {
170
- class: string;
171
- type: string;
172
- 'aria-pressed': {
173
- $if: string[];
174
- };
175
- on: {
176
- click: string;
177
- };
178
- })[] | (string | {
179
- class: string;
180
- type: string;
181
- on: {
182
- click: string;
183
- };
184
- })[] | (string | any[] | {
185
- class: string;
186
- role: string;
187
- 'aria-label': string;
188
- })[] | (string | {
189
- $apply: string;
190
- }[] | (string | {
191
- class: string;
192
- })[] | {
193
- class: string;
194
- })[] | {
195
- class: string;
196
213
  })[] | {
197
214
  class: string;
198
215
  'data-mode': string;
@@ -231,8 +248,8 @@ export declare function createStudioComponent(options?: {
231
248
  };
232
249
  };
233
250
  } | {
234
- class?: undefined;
235
251
  type?: undefined;
252
+ class?: undefined;
236
253
  title?: undefined;
237
254
  on?: undefined;
238
255
  $if: (string | (string | {
@@ -81,7 +81,9 @@ export declare const projectRules: ({
81
81
  } | {
82
82
  class?: undefined;
83
83
  $if: ((string | (string | {
84
- name: string;
84
+ name: {
85
+ $default: string[];
86
+ };
85
87
  props: string;
86
88
  })[] | {
87
89
  class: string;
@@ -109,6 +111,33 @@ export declare const projectRules: ({
109
111
  })[];
110
112
  $eq?: undefined;
111
113
  })[];
114
+ })[] | (string | (string | {
115
+ class: string;
116
+ type: string;
117
+ 'aria-pressed': {
118
+ $if: string[];
119
+ };
120
+ on: {
121
+ click: string;
122
+ };
123
+ })[] | (string | {
124
+ class: string;
125
+ type: string;
126
+ on: {
127
+ click: string;
128
+ };
129
+ })[] | (string | any[] | {
130
+ class: string;
131
+ role: string;
132
+ 'aria-label': string;
133
+ })[] | (string | {
134
+ $apply: string;
135
+ }[] | (string | {
136
+ class: string;
137
+ })[] | {
138
+ class: string;
139
+ })[] | {
140
+ class: string;
112
141
  })[] | (string | (string | {
113
142
  class: string;
114
143
  rows: number;
@@ -156,6 +185,21 @@ export declare const projectRules: ({
156
185
  role: string;
157
186
  })[])[];
158
187
  class?: undefined;
188
+ } | {
189
+ $if: (string | (string | {
190
+ class: string;
191
+ $if?: undefined;
192
+ } | {
193
+ $if: (string | {}[])[];
194
+ class?: undefined;
195
+ } | {
196
+ $if: (string | {}[])[];
197
+ class?: undefined;
198
+ } | {
199
+ $if: (string | {}[])[];
200
+ class?: undefined;
201
+ })[])[];
202
+ class?: undefined;
159
203
  } | {
160
204
  $if: (string | (string | {
161
205
  $apply: string;
@@ -164,33 +208,6 @@ export declare const projectRules: ({
164
208
  role: string;
165
209
  })[])[];
166
210
  class?: undefined;
167
- })[] | (string | (string | {
168
- class: string;
169
- type: string;
170
- 'aria-pressed': {
171
- $if: string[];
172
- };
173
- on: {
174
- click: string;
175
- };
176
- })[] | (string | {
177
- class: string;
178
- type: string;
179
- on: {
180
- click: string;
181
- };
182
- })[] | (string | any[] | {
183
- class: string;
184
- role: string;
185
- 'aria-label': string;
186
- })[] | (string | {
187
- $apply: string;
188
- }[] | (string | {
189
- class: string;
190
- })[] | {
191
- class: string;
192
- })[] | {
193
- class: string;
194
211
  })[] | {
195
212
  class: string;
196
213
  'data-mode': string;
@@ -14,6 +14,7 @@ import { CodedError } from '@jarenjs/core/errors';
14
14
  export declare const STUDIO_CODES: Readonly<{
15
15
  JS0001: "the project document is invalid";
16
16
  JS0002: "a file name is duplicated in the project";
17
+ JS0003: "a project file reference cannot be resolved";
17
18
  }>;
18
19
  /** A studio-envelope error. */
19
20
  export declare class StudioError extends CodedError {
@@ -0,0 +1,5 @@
1
+ /** ZIP method 0 (stored), UTF-8 names, fixed DOS epoch, no ZIP64.
2
+ * @param {Record<string, string | Uint8Array>} files @returns {Uint8Array} */
3
+ export declare function createProjectZip(files: Record<string, string | Uint8Array>): Uint8Array;
4
+ /** @param {any} project @param {Record<string, string | Uint8Array>} assets */
5
+ export declare function exportProject(project: any, assets: Record<string, string | Uint8Array>): Uint8Array<ArrayBufferLike>;
@@ -16,3 +16,5 @@ export { KINDS, LAYOUT_DEFAULT, parseProject, fileOf } from './project.js';
16
16
  export { validateFile } from './validate.js';
17
17
  export { assembleArtifacts, classifyChange, describe } from './assemble.js';
18
18
  export { STUDIO_CODES, StudioError } from './errors.js';
19
+ export { resolveProjectFile, projectFileContext, renameProjectFile, writeProjectArtifact } from './resolve.js';
20
+ export { ADDABLE_KINDS, fileSkeleton } from './skeletons.js';
@@ -0,0 +1,27 @@
1
+ /** Resolve one file and its transitive sources. Imported members must be
2
+ * absent locally; a typo, cycle or collision is a refusal, never a fallback.
3
+ * @param {any} project @param {string} name
4
+ * @returns {{ doc: any, sourceFiles: string[] }} */
5
+ export declare function resolveProjectFile(project: any, name: string): {
6
+ doc: any;
7
+ sourceFiles: string[];
8
+ };
9
+ /** Resolve a query/transform/validation input or a worker store route.
10
+ * Explicit references never fall back when broken. Multiple models require
11
+ * a choice; adding an unrelated model cannot silently reroute a query.
12
+ * @param {any} project @param {any} file
13
+ * @returns {{ input: any, model: any, collection: string | null }} */
14
+ export declare function projectFileContext(project: any, file: any): {
15
+ input: any;
16
+ model: any;
17
+ collection: string | null;
18
+ };
19
+ /** Rename references together with their target, preserving every other
20
+ * file member. A delete deliberately leaves references visibly broken.
21
+ * @param {any[]} files @param {string} before @param {string} after */
22
+ export declare function renameProjectFile(files: any[], before: string, after: string): any[];
23
+ /** Write an assembled artifact back into its source files. Imported
24
+ * members stay in their own files; conflicting writes to a shared source
25
+ * are refused atomically. Unchanged files keep their identity and text.
26
+ * @param {any} project @param {string} name @param {any} doc */
27
+ export declare function writeProjectArtifact(project: any, name: string, doc: any): any;
@@ -0,0 +1,6 @@
1
+ /** Creation kinds derive from the valid starter table and are shared by
2
+ * the component menu, website host and assistant. */
3
+ export declare const ADDABLE_KINDS: readonly string[];
4
+ /** The starter text for a freshly added file of `kind`, or null if the
5
+ * kind is not addable. */
6
+ export declare function fileSkeleton(kind: any): any;
@@ -11,7 +11,7 @@
11
11
  * so host-registered operators ($npv, $sqrt) validate and a
12
12
  * real error comes back as its own coded `JQ`/`JT` code with
13
13
  * a docPath — the closed grammar would reject the operators;
14
- * - `fsm` / `dag` / `model` → their published grammar (structural);
14
+ * - `fsm` / `dag` / `model` → their grammar plus compiler/planner checks;
15
15
  * - `contract` → COMPILED by `compileContract`, so a refusal comes back
16
16
  * as its stable `JC00xx` code with the docPath of the
17
17
  * member at fault — richer than the grammar alone;
@@ -39,8 +39,9 @@ strip reads.
39
39
  | `query` | a query document | **compiled** by the engine with the operator registry |
40
40
  | `state` / `data` | any JSON value (an input) | structural JSON only |
41
41
  | `schema` | a JSON Schema | must be an object/boolean and compile |
42
- | `fsm` / `dag` | a `jaren-fsm` / `jaren-dag` machine | its published flow grammar |
43
- | `model` | a `jaren-model` store definition | the `jaren-model` grammar |
42
+ | `fsm` / `dag` | a `jaren-fsm` / `jaren-dag` machine | its grammar and compiler; named tasks are checked without execution |
43
+ | `model` | a `jaren-model` store definition | its grammar, normalization and SQLite collection/entity planning |
44
+ | `contract` | a `jaren-contract` document | `compileContract`, with coded diagnostics |
44
45
 
45
46
  **Why per-file, not one composed schema.** The published `jaren-query` /
46
47
  `jaren-jslt` grammars are *closed* — their operator vocabulary is
@@ -56,15 +57,74 @@ design, not a compromise. A host embeds its own vocabulary with
56
57
 
57
58
  ## Assembly — files → runnable artifacts
58
59
 
59
- `assembleArtifacts(project)` composes the files into the runnable set. v0.1
60
- ships the **whole-document** contract: a runnable file (`app`, `fsm`,
61
- `dag`, `model`, `jslt`, `query`, `schema`) is its own artifact
62
- (`{ name, kind, role, doc, sourceFiles }`); `state`/`data` files are
63
- inputs, not artifacts. **Fragment assembly** composing separate `state`
64
- + `view` + `actions` files into ONE `jaren-app` document (the true
65
- HTML/CSS/JS split) is the model's headline enhancement and layers on
66
- top without changing this contract (a future `sourceFiles` will list more
67
- than one name).
60
+ `assembleArtifacts(project)` returns `{ artifacts, errors }`. Each runnable
61
+ file (`app`, `fsm`, `dag`, `model`, `jslt`, `query`, `schema`, `contract`)
62
+ produces `{ name, kind, role, doc, sourceFiles }`; `state`/`data` are inputs.
63
+ Assembly resolves JSON and references; `describe(project)` additionally
64
+ validates assembled documents and reports each file's errors.
65
+
66
+ A file can supply absent top-level members through `imports`, an object
67
+ mapping member names to exact project filenames. For example:
68
+
69
+ ```json
70
+ {
71
+ "name": "app.json", "kind": "app", "text": "{}",
72
+ "imports": { "view": "app.view", "actions": "app.actions", "state": "app.state" }
73
+ }
74
+ ```
75
+
76
+ Each source's entire JSON value becomes the destination member. Sources may
77
+ themselves import members. The allowed destination members are:
78
+
79
+ | Destination kind | Importable members |
80
+ |---|---|
81
+ | `app` | `view`, `actions`, `state`, `subs` |
82
+ | `fsm` | `states`, `transitions`, `initial` |
83
+ | `dag` | `nodes`, `edges`, `output` |
84
+ | `model` | `collections`, `entities` |
85
+
86
+ `resolveProjectFile(project, name)` returns `{ doc, sourceFiles }`, with
87
+ dependencies in traversal order, deduplicated. Missing sources, cycles,
88
+ unsupported members and a member supplied both locally and by import raise
89
+ `JS0003`. Source files are never mutated. `renameProjectFile` updates all
90
+ references atomically. `writeProjectArtifact` writes edits back into their
91
+ source files, preserving untouched text and refusing conflicting writes to a
92
+ shared source. Deletion leaves dependent files with explicit reference errors.
93
+
94
+ The website keeps an app visible while editing a fragment directly imported
95
+ by exactly one app. Imported state changes hot-update that app; structural
96
+ changes reboot it. Ambiguous owners require selecting the intended app.
97
+
98
+ ## Input and model routing
99
+
100
+ Optional file members `input`, `model` and `collection` select execution inputs.
101
+ `input` names a `data` or `state` file; absent it, pure runners use the first
102
+ `data` file, then the first `state` file, then JSON null. `model` explicitly
103
+ names a model file for a query. It never implicitly selects the first store.
104
+ `collection` chooses a collection; a model with exactly one collection can
105
+ omit it. `projectFileContext` resolves these references and refuses wrong
106
+ kinds or missing names. The IDE exposes selectors beside the editor.
107
+
108
+ The website runs collection models in private in-memory SQLite workers, one
109
+ owner per model filename. Queries referencing that model share its rows;
110
+ other models and the separate data page do not. Switching files stops the
111
+ view's live subscription but retains the worker. Committing a changed model
112
+ or seed recreates its store; deleting a model, replacing a project or
113
+ destroying the app releases its worker. Invalid drafts retain the committed
114
+ stage. Runtime rows are transient and are not saved or shared.
115
+
116
+ A model's **explicit** `input` is a seed object mapping collection names to
117
+ arrays of documents, inserted before the first query. No implicit data file
118
+ seeds a store. The stage supports inserts, deletes, query results, SQL plans
119
+ and live query results. Entity-only models validate and can be authored, but
120
+ the website's execution controls currently require a collection.
121
+
122
+ FSM and DAG files mount the Flow diagram editor, including palette,
123
+ inspector, undo/redo and run controls. Diagram edits write back through
124
+ assembly. FSM effects are recorded, not dispatched to host services; only
125
+ the editor's registered local DAG tasks execute. Teardown cancels pending
126
+ runs and ignores late completions. The standalone `#/flow` route remains
127
+ available using the same editor.
68
128
 
69
129
  ## `layout` is frozen
70
130
 
@@ -80,14 +140,25 @@ vertically in `top`; pointer cancellation restores the previous ratio.
80
140
  **Download** exports the complete `jaren-project` envelope, including every
81
141
  file and the active file/layout, and works for projects without an app.
82
142
  **App JSON** separately exports the designated app document and reports
83
- when none exists. A runnable offline folder/ZIP is a future export format.
143
+ when none exists, resolving any imported members first. **Offline ZIP**
144
+ exports a standalone runner, `project.json`, every original file's text, and
145
+ bundled runtime, fonts and SQLite assets. Unzip and serve the directory over
146
+ localhost (the included README gives a Python command); no package install
147
+ or internet connection is required. Runtime versions come from the exporting
148
+ build and are recorded in `runtime/versions.json`. Authored external asset
149
+ URLs remain external. Live rows and host credentials are excluded.
150
+
151
+ The headless `@jarenjs/studio/export` entry accepts the host's runtime asset
152
+ bytes and produces a deterministic ZIP. It refuses unsafe archive paths;
153
+ source filenames are represented in `project.json` and mapped to numbered
154
+ files, so arbitrary project names cannot escape the archive directory.
84
155
 
85
156
  ## `classifyChange` — reboot vs. hot-update
86
157
 
87
158
  `classifyChange(prev, next)` reports, **per artifact**, whether a change
88
159
  is `structural`, `state-only`, or `none`. A change of artifact kind is
89
160
  structural even when the JSON text stays the same. It compares an app's
90
- `view`, `actions` and `subs` (other artifacts' whole documents) via the
161
+ entire document except `state` (other artifacts' whole documents) via the
91
162
  suite's collision-free `semanticKey`; a remaining document change is
92
163
  `state-only`. Every filename, including `__proto__`, is an own member of
93
164
  the result map.
@@ -98,13 +169,14 @@ widget, is deliberate.
98
169
 
99
170
  ## Errors
100
171
 
101
- Only the envelope raises a coded `StudioError`; a single file's grammar
102
- problem is reported by `validateFile`, never thrown.
172
+ Envelope and reference operations raise coded `StudioError`s. `validateFile`
173
+ and `describe` report file problems as diagnostics.
103
174
 
104
175
  | code | meaning |
105
176
  |---|---|
106
177
  | `JS0001` | the project document is invalid (bad JSON, or fails the envelope schema) |
107
178
  | `JS0002` | a file name is duplicated in the project |
179
+ | `JS0003` | an import or execution reference cannot be resolved, or an artifact write conflicts |
108
180
 
109
181
  ## Status
110
182
 
@@ -114,13 +186,16 @@ debounced editor with its typing buffer, the run stage, the three layout
114
186
  modes with a drag splitter, the phone pane switcher, save/load/share, and
115
187
  an assistant that can list, read, write and run a project's files.
116
188
 
117
- Still open, and tracked with their constraints in
118
- [ROADMAP.md](../../../docs/ROADMAP.md): the `fsm`/`dag`/`model` kinds
119
- validate but have no editor or runner, so they cannot be added from the
120
- IDE; fragment assembly (one artifact from several files) is unbuilt;
121
- the assistant authors files as free-form tool arguments rather than under
122
- constrained decoding; and a runnable offline `.zip` eject is unbuilt.
189
+ The creation menu and assistant share the engine's ten-kind vocabulary and
190
+ valid starter files. `@jarenjs/studio/author` uses one authoring profile per
191
+ file, then the full file validation gate with bounded repair rounds. The
192
+ website's `jaren_project_author` tool rejects stale publication if the project
193
+ changed during generation, returning the candidate for recovery. Generic
194
+ JSON/schema/contract files and imported destinations use broad JSON profiles;
195
+ their acceptance still depends on the full local validation gate. The exact
196
+ `jaren_project_write` tool remains available for supplied text.
197
+
123
198
  The stage displays the nested app's latest boot/runtime failure and clears
124
- it on restart. Syntax highlighting stays a
125
- non-goal the editor is a plain `<textarea>` so the whole IDE remains a
126
- JSLT document with no imperative chrome.
199
+ it on restart. Remaining constraints live in
200
+ [ROADMAP.md](../../../docs/ROADMAP.md). The editor remains a plain
201
+ `<textarea>` with no syntax highlighting or imperative editor chrome.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jarenjs/studio",
3
3
  "private": false,
4
- "version": "0.75.0",
4
+ "version": "0.83.2",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
7
7
  "types": "./dist/types/index.d.ts",
@@ -17,7 +17,15 @@
17
17
  },
18
18
  "./schemas/*": "./schemas/*",
19
19
  "./styles/studio.css": "./styles/studio.css",
20
- "./package.json": "./package.json"
20
+ "./package.json": "./package.json",
21
+ "./author": {
22
+ "types": "./dist/types/author.d.ts",
23
+ "default": "./src/author.js"
24
+ },
25
+ "./export": {
26
+ "types": "./dist/types/export.d.ts",
27
+ "default": "./src/export.js"
28
+ }
21
29
  },
22
30
  "files": [
23
31
  "dist/types/",
@@ -59,12 +67,13 @@
59
67
  "prepack": "npm run build:types"
60
68
  },
61
69
  "dependencies": {
62
- "@jarenjs/core": "^0.75.0",
63
- "@jarenjs/validate": "^0.75.0",
64
- "@jarenjs/json": "^0.75.0",
65
- "@jarenjs/app": "^0.75.0",
66
- "@jarenjs/flow": "^0.75.0",
67
- "@jarenjs/db": "^0.75.0",
68
- "@jarenjs/contract": "^0.75.0"
70
+ "@jarenjs/core": "^0.83.2",
71
+ "@jarenjs/validate": "^0.83.2",
72
+ "@jarenjs/json": "^0.83.2",
73
+ "@jarenjs/app": "^0.83.2",
74
+ "@jarenjs/flow": "^0.83.2",
75
+ "@jarenjs/db": "^0.83.2",
76
+ "@jarenjs/contract": "^0.83.2",
77
+ "@jarenjs/ai": "^0.83.2"
69
78
  }
70
79
  }