arcane-os 0.51.2 → 0.52.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.52.1
4
+
5
+ - Preserve an authored host `index.html` at `/` independently of application
6
+ entry and offline selection. Root import-map/PWA generation no longer aliases
7
+ that public homepage to the app entry. Existing app-only roots retain their
8
+ launcher behavior; excluded homepage content and assets stay outside the
9
+ application's managed documents and offline inventory.
10
+ - Source development follows root-file creation/removal without a descriptor
11
+ edit, serves an unselected host root unchanged, and avoids stale conditional
12
+ responses when generated aliases change within one HTTP second. Ordinary
13
+ selected routes, startup entry, manifest identity and worker lifecycle remain
14
+ unchanged.
15
+ - Packaged authored roots carry optional generated `app.rootDocument` metadata
16
+ so preview serves them at `/`; older and app-only packages retain their
17
+ existing redirects and queries. Worker directory navigation uses only indexes
18
+ already selected in its current offline inventory, with exact-query priority.
19
+ No dependency, configuration option, saved-data migration or cache reset is
20
+ introduced. Consumers regenerate their normal public SDK outputs after update.
21
+
22
+ ## 0.52.0
23
+
24
+ - Add optional `package.documents` to select managed application HTML separately
25
+ from files retained by `include` and `exclude`. The schema-1 projection uses
26
+ top-level `documents`. The entry is always first, `[]` selects the entry only,
27
+ and omission preserves automatic discovery. Secondary paths retain existing
28
+ deterministic ordering while the authored declaration remains unchanged.
29
+ - Use that selection across ordinary inspection, import-map generation,
30
+ development serving, packaging and PWA document processing. Explicitly
31
+ unselected HTML originals retain their content, including iframe-referenced
32
+ documents, while remaining included, served, packaged and offline-eligible
33
+ under the existing resource selection. HTML-import components and shared
34
+ runtime resources retain their existing processing. No dependency, migration,
35
+ default selection change or extra CLI flag is introduced.
36
+
3
37
  ## 0.51.2
4
38
 
5
39
  - Forward caller-selected `temperature` through the focused TWiN Cloud
package/README.md CHANGED
@@ -20,7 +20,7 @@ selected SDK projection or an explicit live SDK source mount. Both profiles
20
20
  share the theme, packaging, event, cancellation,
21
21
  and browser run contracts while retaining their selected application layout.
22
22
 
23
- This checkout defines the `0.51.2` SDK contract. Applications pin one exact npm
23
+ This checkout defines the `0.52.1` SDK contract. Applications pin one exact npm
24
24
  version and lockfile; registry state is deliberately not baked into application
25
25
  artifacts.
26
26
 
@@ -145,6 +145,19 @@ one metadata task; unchanged files reuse their parsed selection. Shared runtime
145
145
  requests do not wait for that refresh. Full offline inventories are enumerated
146
146
  only for worker/offline-manifest requests, with separate state for each selected
147
147
  app snapshot so an older inventory cannot overwrite newer generated metadata.
148
+
149
+ Authored host-root `index.html` presence is refreshed independently of descriptor
150
+ edits. Development serves that host index at `/` instead of redirecting to the
151
+ app entry and suppresses the root PWA alias. An index outside the selected app
152
+ mapping uses an unchanged exact-root response; `/index.html` and other resource
153
+ URLs retain their existing selection rules. A selected index keeps its existing
154
+ document classification. This broadens no app or offline inventory and adds no
155
+ managed maps or bootstrap. With no host index, the app-entry redirect remains.
156
+ A worker serves a directory's cached index body only when that index is already
157
+ in its current offline selection; otherwise the host owns the unchanged request.
158
+ The selected app launch and installation identity remain independent of this
159
+ host-root navigation.
160
+
148
161
  Changed resource requests return the complete current saved source without
149
162
  packaging, copying files into `dist`, or restarting the server. Conditional
150
163
  requests for unchanged resources return `304`. Enabled PWAs check on page load
@@ -253,9 +266,12 @@ separate. See the [complete output contract](reference/protocols.md#app-selected
253
266
 
254
267
  Packaging keeps standalone app files at the release root and places an explicitly
255
268
  nested app beneath `apps/<id>/`. It preserves every shared route destination.
256
- When selected content supplies no root `index.html`, the SDK generates one that
257
- opens the selected app entry. Authored document bases, app URLs, relative module
258
- imports and shared runtime paths therefore resolve through the same layout in
269
+ A selected authored output-root `index.html` is preserved and suppresses the
270
+ deployment-root PWA navigation alias. When selected content supplies no root
271
+ index, the SDK generates a launcher and retains the selected app-entry alias;
272
+ an excluded source-host index does not alter that package result. Authored
273
+ document bases, app URLs, relative module imports and shared runtime paths
274
+ therefore resolve through the same layout in
259
275
  source development and packaged delivery. Packaging consumes the saved source
260
276
  and managed import maps; use `arcane import-map` to refresh those maps, or the
261
277
  ordinary `arcane dev` startup that performs that refresh.
@@ -266,6 +282,13 @@ entry, or `./apps/hello-world/index.html` for a nested app. Its complete `files`
266
282
  inventory follows the selected layout and includes the root `index.html`.
267
283
  Packaged browser serving opens `app.start`; a previously generated flat release without `app.start` retains
268
284
  its `app.entry` launch path.
285
+ Only selected records supplying an authored output-root index add the optional
286
+ generated `app.rootDocument: "./index.html"` release field. Preview serves that
287
+ document at `/` without inferring ownership from HTML content. When the field is
288
+ absent, older releases and generated-launcher packages retain their existing
289
+ `302` root redirect to `app.start` or the older `app.entry` fallback, preserving
290
+ the request query. This release fact adds no app configuration or API option and
291
+ does not change `app.start`.
269
292
 
270
293
  The authored schema-2 descriptor is canonical for new apps and projects an
271
294
  exact schema-1 `arcane-package.json` for current consumers. Existing Arcane
@@ -197,19 +197,24 @@ npm exec -- arcane doctor --workspace . --arcane-root "../Arcane OS"
197
197
 
198
198
  ### Overview
199
199
 
200
- Refreshes one selected application's browser runtime map, generates
201
- its standard browser import map, discovers every directly navigable
202
- `.html`/`.htm` document admitted by the selected descriptor's existing
203
- include/exclude rules, and prepares the map artifact plus those managed documents
204
- before writing them in order. A directly navigable entry document declares exactly
205
- one `<meta name="arcane-app-id" content="<selected-id>">`; an unmarked secondary
206
- document may instead carry an active `<base>`.
207
- Wrong or duplicate explicit app identity fails. The renderer then requires one
208
- path-correct base for every selected document. Included HTML files with neither
209
- the identity marker nor an active base are component fragments: they remain
210
- package files and are not rewritten with a document-level import map.
211
- Packaging and development use the same discovery owner. Packaging consumes
212
- the saved managed import maps in directly navigable source pages.
200
+ Refreshes one selected application's browser runtime map, generates its standard
201
+ browser import map, and prepares the map artifact plus the selected managed
202
+ `.html`/`.htm` documents before writing them in order. Optional
203
+ `package.documents` in `arcane-app.json` selects literal app-root-relative HTML
204
+ paths that are already included and not excluded. The entry is always first;
205
+ `[]` selects only the entry. Omitting the field retains automatic selection of
206
+ the entry and included secondary pages with an active `<base>`. An app identity
207
+ meta tag does not select a page. The renderer requires one path-correct active
208
+ base for each selected document.
209
+
210
+ The schema-1 package projection carries this field as `documents`, preserving
211
+ the distinction between omission and `[]`. With explicit selection, other
212
+ included HTML documents keep their exact content, including originals referenced
213
+ through iframes. Selection does not change serving, packaging or offline resource
214
+ membership; component processing and shared runtime-resource traversal retain
215
+ their existing behavior. Inspection, packaging and development use the same
216
+ [document-selection contract](protocols.md#application-document-selection).
217
+ Packaging consumes the saved managed import maps in selected source pages.
213
218
 
214
219
  ```text
215
220
  arcane import-map [--workspace <directory>] [--app <id>]
@@ -240,6 +245,12 @@ files remain unchanged. The same layout applies to `arcane dev` and
240
245
  `arcane package`. Generated and offline app files are committed; GitHub Actions
241
246
  consume those committed files. See [root generated output](pwa.md#root-generated-output).
242
247
 
248
+ An existing authored source-host `index.html` suppresses the generated `/`
249
+ navigation alias even when the page is outside the application or offline
250
+ selection. It is not automatically added to either inventory or given managed
251
+ maps or PWA bootstrap. The selected app entry and installation identity remain
252
+ unchanged; see [authored host roots](pwa.md#authored-host-root-and-app-entry).
253
+
243
254
  The supported physical layout preserves its route count and ordered include
244
255
  list. External and modern integrated physical routes require `components`, `css`,
245
256
  `dependencies`, `entities`, `img`, `modules`, and `sdk`; a physical workspace
@@ -279,11 +290,12 @@ Success returns the normal selected-workspace wrapper:
279
290
  }
280
291
  ```
281
292
 
282
- For the direct CLI command, `documentPaths` contains the configured entry first
283
- and every other descriptor-selected HTML/HTM document afterward in
284
- deterministic order. The generated artifact is written first, followed by the
285
- selected documents. A write failure or cancellation can leave earlier writes
286
- in place; the operation does not restore them automatically. After successful
293
+ For the direct CLI command, `documentPaths` contains the configured entry first.
294
+ Other selected paths follow in deterministic lexical order without duplicates.
295
+ The authored `documents` declaration remains as supplied, including `[]`.
296
+ The generated artifact is written first, followed by the selected documents.
297
+ A write failure or cancellation can leave earlier writes in place; the operation
298
+ does not restore them automatically. After successful
287
299
  writes, an observer failure preserves delivery with
288
300
  `eventDelivery.status === 'degraded'` and `ARCANE_EVENT_DELIVERY_FAILED`; it
289
301
  does not roll back complete application content.
@@ -367,6 +379,16 @@ not package the app or produce `dist` output. With PWA enabled, the server
367
379
  generates the installation and offline manifests directly; see
368
380
  [PWA development and versioning](pwa.md#development-and-hosting).
369
381
 
382
+ The startup URL remains the selected app entry. At `/`, the server serves an
383
+ existing authored host-root `index.html` and suppresses the app-entry redirect
384
+ and PWA alias. A root outside the selected app mapping is served unchanged only
385
+ through this exact-root route; `/index.html` and other resource URLs retain their
386
+ existing selection rules. A selected root follows its existing document
387
+ classification. Root presence does not expand either inventory or cause
388
+ bootstrap injection. With no host index, the app-entry redirect remains.
389
+ Root-file creation or removal is reflected in subsequent root-navigation and
390
+ generated-PWA requests without a restart or a descriptor edit.
391
+
370
392
  The command reports acceptance before bind/start work, emits the final URL,
371
393
  owns the server until cancellation, and restores failure to the process exit.
372
394
  The default host is `127.0.0.1`. `--public` selects `0.0.0.0` (all IPv4
@@ -544,8 +566,11 @@ defaulting to `dist/<id>/`, and preserves the prior output until the replacement
544
566
  is complete. It consumes saved source and managed
545
567
  import maps, keeps standalone app files at the output root, and retains the
546
568
  configured shared route destinations. Explicit multi-app workspaces retain
547
- their selected app beneath `apps/<id>/`. When selected shared content supplies no root
548
- `index.html`, the SDK generates one that opens the selected app entry.
569
+ their selected app beneath `apps/<id>/`. A selected authored output-root
570
+ `index.html` is preserved and suppresses the deployment-root PWA navigation
571
+ alias. When selected content supplies no root index, the SDK generates a launcher
572
+ and retains the app-entry alias. An excluded source-host root does not change
573
+ that package selection.
549
574
  Source document bases and resource URLs therefore retain their development
550
575
  layout. Packaging does not run tests or checks automatically.
551
576
 
@@ -578,6 +603,10 @@ The result includes the release root, manifest, and complete selected inventory.
578
603
  the package launch URL in `app.start`: `./index.html` for a root app with that
579
604
  entry, or `./apps/hello-world/index.html` for a nested app. The complete file
580
605
  inventory follows the selected layout and includes the root `index.html`.
606
+ Only selected records supplying an authored output-root index add
607
+ `app.rootDocument: "./index.html"`. This optional generated release fact selects
608
+ root-document serving in preview; it is not an app configuration or CLI option
609
+ and does not change `app.start`.
581
610
  `--dry-run` plans the package without refreshing source, running tests, or
582
611
  replacing output.
583
612
 
@@ -743,6 +772,11 @@ For `--target browser`, starts the existing release in the app's configured
743
772
  does not package, rebuild, test, check, or verify that release automatically.
744
773
  It opens the release manifest's `app.start` URL. Older flat releases without
745
774
  that field continue to open their `app.entry` path.
775
+ Requests to `/` serve the explicit `app.rootDocument` when that generated
776
+ release field is present. With no field, including older releases and app-only
777
+ packages with a generated launcher, `/` retains its `302` redirect to
778
+ `app.start` or the older `app.entry` fallback, preserving the request query.
779
+ Preview does not infer root ownership from HTML content.
746
780
  The preview always uses HTTPS with the workspace certificate pair. Supply
747
781
  `--cert <file> --key <file>` together to use another pair; see
748
782
  [development HTTPS setup](#development-https-setup).
@@ -51,16 +51,12 @@ App-scoped managed browser imports have three supported control-plane entrypoint
51
51
  uses `arcane import-map`; Node callers use
52
52
  `executeOperation('import-map', options)` or
53
53
  `createToolchain(defaults).importMap(options)`. These are three routes to the
54
- same app-scoped operation, not three import-map formats. Each route discovers
55
- the selected descriptor's directly navigable admitted `.html`/`.htm` documents
56
- through the package include/exclude rules and writes one canonical map to the
57
- artifact plus every such document. The current marker is exactly one matching
58
- `meta[name="arcane-app-id"]`; an unmarked secondary page with an active `base`
59
- remains admitted under the current secondary-document rule. Wrong or duplicate
60
- explicit identity fails, and the selected page then must pass exact path-relative
61
- base validation.
62
- Included HTML with neither signal is a component fragment and remains a
63
- complete package file.
54
+ same app-scoped operation, not three import-map formats. Each route uses the
55
+ [application document selection](#application-document-selection) shared by
56
+ inspection, development and packaging, and writes one canonical map to the
57
+ artifact plus every selected document. Each selected page retains the existing
58
+ path-relative base requirement. Included component fragments remain complete
59
+ package files and keep their existing component processing.
64
60
  Public lowercase runtime subpaths resolve directly to canonical runtime-module
65
61
  namespaces from both Node package exports and managed browser keys. These
66
62
  include `arcane-os/preference-store`, `arcane-os/speech-playback`,
@@ -98,6 +94,48 @@ materializes the complete required SDK runtime,
98
94
  browser-runtime, and managed-import-map closure inside that app's own artifact.
99
95
  No application polls for SDK changes.
100
96
 
97
+ ## Application document selection
98
+
99
+ An authored schema-2 `arcane-app.json` may select the HTML pages that receive
100
+ application-document processing through `package.documents`:
101
+
102
+ ```json
103
+ {
104
+ "package": {
105
+ "entry": "index.html",
106
+ "include": ["index.html", "pages", "originals", "modules", "css"],
107
+ "documents": ["index.html", "pages/viewer.html"]
108
+ }
109
+ }
110
+ ```
111
+
112
+ This is a package excerpt. Each `documents` member is a literal app-root-relative
113
+ `.html` or `.htm` file path, not a directory or glob. Every selected document
114
+ must already be present in the app's included, non-excluded files. The entry is
115
+ always selected first, followed by the other selected paths in deterministic
116
+ lexical order without duplicates. An empty list selects only the entry. The
117
+ authored `documents` declaration remains as supplied, including `[]`.
118
+
119
+ Omitting `documents` preserves automatic discovery: the SDK selects the entry
120
+ and included secondary HTML pages with an active `<base>`. A
121
+ `meta[name="arcane-app-id"]` marker does not select a page. Selected pages retain
122
+ the existing requirement for one path-correct active base.
123
+
124
+ The schema-1 `arcane-package.json` field is `documents` at the top level.
125
+ Descriptor projection and synthesis preserve an omitted property as omitted
126
+ and an authored empty list as `[]`. Package-only applications may author that
127
+ schema-1 field directly. Ordinary inspect, import-map, dev and package operations
128
+ use the same declaration; there is no document-selection CLI flag.
129
+
130
+ Document selection controls application-document scanning, base handling,
131
+ managed import maps and PWA injection. It does not change `include`/`exclude`,
132
+ serving, package membership or offline resource selection. With an explicit
133
+ list, other included HTML documents retain their exact content, even when a
134
+ selected page references them through an iframe. They remain available as
135
+ included resources without receiving application-document processing.
136
+ Component processing and shared runtime-resource traversal retain their existing
137
+ behavior. Offline inclusion still follows the app's PWA resource selection.
138
+
101
139
  ## App-selected package output
102
140
 
103
141
  An app may set `"outputDirectory": "ai"` in its schema-1
@@ -213,15 +251,34 @@ The declared application ID remains unchanged. `appsRoot: "apps"` continues
213
251
  to discover `apps/<id>` and supports the existing integrated and multi-app
214
252
  layouts. Entries and include/exclude paths remain relative to the application.
215
253
 
216
- Root HTML uses `<base href="./">`; nested navigable documents use their actual
217
- depth back to the workspace. Managed bare imports remain the public interface;
218
- their targets follow the selected npm routes. `arcane import-map` generates
219
- enabled static PWA records at the app root, so normal static hosting needs no
254
+ SDK-managed root HTML uses `<base href="./">`; nested navigable documents use
255
+ their actual depth back to the workspace. Managed bare imports remain the
256
+ public interface; their targets follow the selected npm routes. `arcane import-map`
257
+ generates enabled static PWA records at the app root, so normal static hosting needs no
220
258
  SDK request handler or runtime copy. Managed refresh, development serving,
221
259
  inspection, dry run and packaging add no nested `apps/<id>/` navigation pages,
222
260
  redirects, or duplicate PWA worker/inventory files. There is no output-retention
223
261
  switch for those retired records.
224
262
 
263
+ An authored source-host `index.html` suppresses the root app-entry redirect and
264
+ generated PWA navigation alias even when that file is outside the application's
265
+ include or offline selection. Development serves that host index at `/`. An
266
+ index outside the selected app mapping uses an unchanged exact-root response;
267
+ `/index.html` and other resource URLs retain their existing selection rules.
268
+ A selected index follows the existing document classification. Root presence
269
+ adds no page, assets, managed maps, or PWA bootstrap to the application. With no
270
+ host index, development retains the app-entry redirect. In a package, only a
271
+ selected authored output-root index suppresses the alias; an absent or excluded
272
+ root retains the generated launcher and app-entry alias. Selected records that
273
+ supply an authored output-root index add the optional generated release field
274
+ `app.rootDocument: "./index.html"`. Preview serves that document at `/`; absence
275
+ retains the existing `302` to `app.start` or the older `app.entry` fallback with
276
+ the request query preserved. This is a release fact, not an app setting or HTML
277
+ content inference, and `app.start` remains unchanged. The worker can answer a
278
+ directory navigation from an index only when that index already belongs to its
279
+ current offline selection and has a cached response; otherwise the unchanged
280
+ request remains host-owned. See [authored host roots](pwa.md#authored-host-root-and-app-entry).
281
+
225
282
  Application identity, stored data, the existing default installation ID and an
226
283
  authored `pwa.manifest.id` remain unchanged. Authored resources continue to
227
284
  follow the app's include/exclude selection; generation does not delete existing
@@ -58,6 +58,27 @@ previous source identity while its start URL and scope move to the root. An
58
58
  authored `manifest.id` remains authoritative. Packaged default identity remains
59
59
  `./`. App identity and saved application data remain unchanged.
60
60
 
61
+ ### Application pages and preserved HTML resources
62
+
63
+ Optional `package.documents` in `arcane-app.json` selects the app-root-relative
64
+ `.html`/`.htm` pages that receive managed import maps and PWA links/bootstrap.
65
+ Its schema-1 projection is `arcane-package.json`'s top-level `documents`.
66
+ For example, `"documents": ["index.html"]` selects the entry while other
67
+ included HTML documents retain their exact content. The entry is always selected;
68
+ `[]` also selects only the entry. Omitting the property preserves automatic
69
+ discovery of the entry and included secondary pages with an active `<base>`.
70
+ Selected pages retain the existing path-correct base requirement.
71
+
72
+ This declaration does not add or remove resources from `package.include`,
73
+ `package.exclude`, serving, packaging or the offline inventory. Included
74
+ originals remain available and can be cached under the normal offline selection,
75
+ including when a selected page displays them in an iframe. With an explicit
76
+ list, those unselected documents are not scanned as application pages or given
77
+ managed import maps, base handling or PWA injection. HTML-import components and
78
+ shared runtime-resource traversal keep their existing processing. See
79
+ [application document selection](protocols.md#application-document-selection)
80
+ for ordering and the complete declaration contract.
81
+
61
82
  ### Root generated output
62
83
 
63
84
  For a standalone application, `appsRoot: "."` places the app at its repository
@@ -81,6 +102,38 @@ committed files rather than generating them. Actual multi-app workspaces keep
81
102
  their explicit `appsRoot: "apps"` layout. This source/package contract does not
82
103
  establish any particular installed application's browser lifecycle.
83
104
 
105
+ ### Authored host root and app entry
106
+
107
+ An authored `index.html` at the source host root keeps `/` separate from the
108
+ selected application entry. Root import-map generation and development PWA
109
+ generation omit the `/`-to-entry navigation alias whenever that file exists,
110
+ including when it is outside `package.include` or the offline selection.
111
+ Development serving answers `/` with that host index. An index outside the app's
112
+ selected source mapping is served unchanged through this exact-root route;
113
+ `/index.html` and other resource URLs retain their existing selection rules.
114
+ A selected index follows its existing managed-document classification. Root
115
+ presence alone adds no page or assets to the application or offline inventory
116
+ and adds no managed maps or PWA bootstrap. The host owns a root response outside
117
+ the worker's selected offline resources. With no host index, development retains
118
+ its app-entry redirect.
119
+
120
+ Packaging considers the selected output instead of unrelated source-host files.
121
+ A selected authored output-root `index.html` is preserved and suppresses the
122
+ deployment-root navigation alias. When selected content supplies no output-root
123
+ index, the package retains its generated launcher and app-entry alias. An
124
+ authored source root excluded from the package does not replace that launcher.
125
+ Only when selected records supply an authored output-root index does packaging
126
+ write `app.rootDocument: "./index.html"` in `ARCANE_APP_RELEASE.json`.
127
+ Packaged preview uses that generated field to serve the authored document at
128
+ `/`; it does not inspect HTML to infer root ownership. Without the field,
129
+ including older releases and generated-launcher packages, preview retains its
130
+ `302` redirect to `app.start` (or the older `app.entry` fallback), preserving the
131
+ request query. The startup URL remains the selected app launch URL.
132
+
133
+ This behavior requires no new setting. The application entry, default install
134
+ start URL, manifest identity and scope, worker registration scope, cache
135
+ identity, and saved application data keep their existing contracts.
136
+
84
137
  ### Offline resource selection
85
138
 
86
139
  `offline.include` and `offline.exclude` select literal paths or directory
@@ -136,16 +189,18 @@ their app and SDK versions match. It is not a content measurement.
136
189
 
137
190
  The package owns its selected inventory once, after any app adapter finishes.
138
191
  It follows actual resource references to include meaningful query variants.
139
- Generated application pages receive a manifest link and an `async` module
192
+ Selected application pages receive a manifest link and an `async` module
140
193
  marked `data-arcane-pwa`. Existing application scripts retain their order.
141
194
  PWA registration does not wait for models, storage, preferences or page rendering.
142
195
  The same bootstrap starts one initially hidden `pwa-install.html` component with
143
196
  the generated manifest's app name. Component loading and worker registration
144
197
  proceed independently.
145
198
 
146
- All SDK browser-resource delivery removes only SDK-owned `arcaneVersion` fields
147
- from actual local resource references, including the managed import map. Authored
148
- fields such as `v`, encoded and repeated fields, empty query segments, fragments,
199
+ SDK processing of selected application pages, components and runtime resources
200
+ removes only SDK-owned `arcaneVersion` fields from actual local resource references,
201
+ including the managed import map. Explicitly unselected HTML documents keep their
202
+ exact content. Authored fields such as `v`, encoded and repeated fields, empty
203
+ query segments, fragments,
149
204
  source spelling and unrelated payloads are preserved. The offline
150
205
  manifest carries release information. Non-PWA and native packaging use the same
151
206
  [clean local resource URLs](asset-versioning.md). Native packaging does not
@@ -179,9 +234,9 @@ If `package.pwa.offline.include` is nonempty, the resource must also
179
234
  match that offline selection and must not match `offline.exclude`. Adding a
180
235
  path only to the offline selection does not add it to the app's resources.
181
236
  The running source server reads changed app descriptors before the next app,
182
- root-navigation or generated-PWA request. Include/exclude rules, the entry and
183
- PWA settings share the current selection; no restart or package projection
184
- write is needed. Edits to selected source files are picked up by the next due
237
+ root-navigation or generated-PWA request. Include/exclude rules, the entry,
238
+ document selection and PWA settings share the current selection; no restart or
239
+ package projection write is needed. Edits to selected source files are picked up by the next due
185
240
  page-load check while the server remains running.
186
241
 
187
242
  For an enabled application, `arcane dev` serves the generated PWA files at the
@@ -281,8 +336,10 @@ therefore matters even when an offline cache exists. Updating files in place
281
336
  while installation fetches them is not an atomic release snapshot; the host owns
282
337
  consistent deployment of the selected output.
283
338
 
284
- An offline navigation alias redirects to its selected entry page, preserving the
285
- document URL used to resolve relative modules and styles.
339
+ Where an app-entry navigation alias remains, it redirects to the selected entry
340
+ page, preserving the document URL used to resolve relative modules and styles.
341
+ An authored host root suppresses that alias as described above; merely retaining
342
+ an old cached root resource does not add it to the current offline selection.
286
343
 
287
344
  For a same-origin navigation to a selected static `.html` or `.htm` document,
288
345
  the worker can reuse that document's cached body while leaving the complete
@@ -296,6 +353,14 @@ document. This does not change query matching for assets, API calls, ordinary
296
353
  fetch requests, unselected documents or other origins. Cache refresh and the
297
354
  Update prompt keep their existing lifecycle.
298
355
 
356
+ For a same-origin directory navigation without an app-entry alias, the worker
357
+ can likewise reuse that directory's `index.html` body only when the index is
358
+ already in the current offline selection and has a retained cached response.
359
+ The directory URL and its query remain unchanged, including beneath a deployment
360
+ subpath. An exact query-specific selected resource takes precedence. Otherwise,
361
+ the original request passes to the host unchanged. This adds no page or asset to
362
+ the inventory and does not save a host response over the selected index.
363
+
299
364
  Browser storage eviction can remove an offline cache. A missing release cache
300
365
  entry falls back to the network, so offline availability still depends on the
301
366
  browser retaining the selected resources.
@@ -779,12 +779,22 @@ async inspectApp({workspaceRoot, appId, signal}={})
779
779
  ```
780
780
 
781
781
  Import it from `arcane-os` or `arcane-os/packager`. The result includes the
782
- configured `entry`, `include`, and `exclude` values plus `browserDocuments`, the
783
- entry-first ordered `.html`/`.htm` paths selected by the same package traversal
784
- used by import-map refresh and packaging. Current pages declare exactly one
785
- matching `meta[name="arcane-app-id"]`; unmarked pages with an active `base`
786
- remain selected for patch compatibility. Included HTML with neither signal is
787
- retained as a package fragment rather than rewritten as a document.
782
+ configured `entry`, `include`, and `exclude` values, the optional `documents`
783
+ declaration when authored, and `browserDocuments`, the entry-first ordered
784
+ `.html`/`.htm` paths shared by import-map refresh, development and packaging.
785
+ `package.documents` in an authored descriptor, or `documents` in a schema-1
786
+ package, selects literal app-root-relative paths already included and not
787
+ excluded. Other selected paths follow the entry in deterministic lexical order
788
+ without duplicates. The authored `documents` declaration remains as supplied,
789
+ including `[]`, which selects only the entry. Omitting the property retains
790
+ automatic discovery of the entry and included secondary pages with an active `<base>`. App identity
791
+ meta tags do not select documents.
792
+
793
+ Selected pages retain their existing base requirements. Explicit selection
794
+ leaves other included HTML documents unchanged, including iframe-referenced
795
+ originals, while preserving package, serving and offline resource membership.
796
+ Component processing and shared runtime-resource traversal retain their existing
797
+ behavior. See [application document selection](protocols.md#application-document-selection).
788
798
 
789
799
  `entry` and each app browser document's `path` stay relative to the app
790
800
  directory. Each browser document also reports `packagePath`, the emitted path
@@ -872,7 +882,14 @@ generates one that opens the selected app page. The result
872
882
  contains `outputRoot`, `manifest`, and the complete `files` inventory.
873
883
  `manifest.app.entry` stays app-relative, while `manifest.app.start`
874
884
  is the package launch URL, such as `./index.html` for a root app or
875
- `./apps/hello-world/index.html` for a nested app. Release
885
+ `./apps/hello-world/index.html` for a nested app. Only when selected records
886
+ supply an authored output-root index does the release add
887
+ `manifest.app.rootDocument: "./index.html"`. Preview serves that explicit
888
+ document at `/`; without the field, older releases and generated-launcher
889
+ packages retain the `302` redirect to `app.start` or the older `app.entry`
890
+ fallback with the request query preserved. This generated release fact adds no
891
+ app configuration or API option, changes no `app.start`, and requires no HTML
892
+ content inference. Release
876
893
  schema `1`, kind `arcane-app-release`, and packager identity
877
894
  `arcane-app-packager-v1` remain unchanged. A dry run returns the planned output
878
895
  and file inventory without writing source or output.
@@ -2111,6 +2128,11 @@ async function useprojectNativeDescriptor(...arguments_) {
2111
2128
 
2112
2129
  Projects a schema-2 descriptor into the compatible schema-1 application package contract.
2113
2130
 
2131
+ Optional `package.documents` becomes top-level `documents`. Omission stays
2132
+ omitted and an authored empty list stays `[]`, so projection preserves automatic
2133
+ discovery versus entry-only selection. See
2134
+ [application document selection](protocols.md#application-document-selection).
2135
+
2114
2136
  ### Signature and result
2115
2137
 
2116
2138
  ```text
@@ -4277,9 +4299,9 @@ async function usedevelopApplication(...arguments_) {
4277
4299
 
4278
4300
  Dispatches one named headless SDK operation with normalized acceptance, events, cancellation, and failure.
4279
4301
 
4280
- The exact command `'import-map'` dispatches one app-scoped refresh
4281
- across directly navigable `.html`/`.htm` documents selected by the descriptor's
4282
- existing include/exclude rules, excluding component fragments, and returns
4302
+ The exact command `'import-map'` dispatches one app-scoped refresh across the
4303
+ `.html`/`.htm` documents selected by
4304
+ [`package.documents` or automatic discovery](protocols.md#application-document-selection), and returns
4283
4305
  `{workspaceRoot, workspaceMode, appId,
4284
4306
  importMap}`. The `importMap` value reports the generated imports and complete
4285
4307
  ordered `documentPaths`. This route mutates the map artifact and selected managed HTML
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arcane-os",
3
- "version": "0.51.2",
3
+ "version": "0.52.1",
4
4
  "description": "Arcane OS JavaScript SDK, project-local CLI, browser runtime, and repository-portable application packager.",
5
5
  "type": "module",
6
6
  "main": "./src/index.mjs",
@@ -38,6 +38,11 @@
38
38
  "required": ["entry", "strategy", "include", "exclude", "shared"],
39
39
  "properties": {
40
40
  "entry": { "$ref": "#/$defs/relativePath" },
41
+ "documents": {
42
+ "type": "array",
43
+ "description": "Application-relative HTML/HTM pages managed by import-map and PWA processing. Entry is always first; an empty list selects entry only. Omission preserves automatic discovery. File inclusion and serving remain controlled by include/exclude.",
44
+ "items": { "allOf": [{ "$ref": "#/$defs/relativePath" }, { "pattern": "\\.[Hh][Tt][Mm][Ll]?$" }] }
45
+ },
41
46
  "strategy": { "enum": ["static", "adapter"] },
42
47
  "localAIModelPolicy": { "$ref": "#/$defs/localAIModelPolicy" },
43
48
  "pwa": { "$ref": "#/$defs/pwa" },
@@ -34,6 +34,16 @@
34
34
  "entry": {
35
35
  "$ref": "#/$defs/relativePath"
36
36
  },
37
+ "documents": {
38
+ "type": "array",
39
+ "description": "Application-relative HTML/HTM pages managed by import-map and PWA processing. Entry is always first; an empty list selects entry only. Omission preserves automatic discovery. File inclusion and serving remain controlled by include/exclude.",
40
+ "items": {
41
+ "allOf": [
42
+ { "$ref": "#/$defs/relativePath" },
43
+ { "pattern": "\\.[Hh][Tt][Mm][Ll]?$" }
44
+ ]
45
+ }
46
+ },
37
47
  "outputDirectory": {
38
48
  "$ref": "#/$defs/relativePath",
39
49
  "description": "Final package directory relative to the workspace, with no appended app ID. Omission preserves dist/<id>. This directory is replaced when packaging succeeds; source layout and app identity remain unchanged."
@@ -12,6 +12,7 @@ import {
12
12
  } from './constants.mjs';
13
13
  import {
14
14
  normalizeRelativePath,
15
+ normalizeAppDocuments,
15
16
  parseSemver,
16
17
  validateAppConfig as validateAppPackageConfig
17
18
  } from './packager/core.mjs';
@@ -110,9 +111,10 @@ function validateLocalAIModelPolicy(value,label){
110
111
 
111
112
  function validatePackage(value,appId){
112
113
  assertOnlyKeys(value,new Set([
113
- 'entry','strategy','include','exclude','shared','adapter','localAIModelPolicy','pwa'
114
+ 'entry','strategy','include','exclude','shared','adapter','localAIModelPolicy','pwa','documents'
114
115
  ]),'descriptor.package');
115
116
  const entry=normalizeRelativePath(value.entry,'descriptor.package.entry');
117
+ const documents=normalizeAppDocuments(value.documents,'descriptor.package.documents');
116
118
  if(!['static','adapter'].includes(value.strategy))fail('descriptor.package.strategy must be static or adapter.');
117
119
  const include=relativePaths(value.include,'descriptor.package.include',{required:true});
118
120
  const exclude=relativePaths(value.exclude??[],'descriptor.package.exclude');
@@ -134,6 +136,7 @@ function validatePackage(value,appId){
134
136
  }
135
137
  return completeValue({
136
138
  entry,
139
+ ...(documents===undefined?{}:{documents}),
137
140
  strategy:value.strategy,
138
141
  include,
139
142
  exclude,
@@ -317,6 +320,7 @@ export function projectPackageManifest(descriptor){
317
320
  displayName:value.displayName,
318
321
  version:value.version,
319
322
  entry:value.package.entry,
323
+ ...(value.package.documents===undefined?{}:{documents:[...value.package.documents]}),
320
324
  strategy:value.package.strategy,
321
325
  ...(hasAuthoredSecurity?{security:{
322
326
  connectOrigins:[...value.security.connectOrigins],
@@ -381,6 +385,7 @@ function synthesizedDescriptor(packageManifest,nativeDescriptor){
381
385
  publisher:{id:'publisher-undeclared',name:'Publisher not declared'},
382
386
  package:{
383
387
  entry:packageManifest.entry,
388
+ ...(packageManifest.documents===undefined?{}:{documents:[...packageManifest.documents]}),
384
389
  strategy:packageManifest.strategy,
385
390
  ...(packageManifest.localAIModelPolicy?{localAIModelPolicy:packageManifest.localAIModelPolicy}:{}),
386
391
  ...(packageManifest.pwa===undefined?{}:{pwa:packageManifest.pwa}),