@kurot/cli 3.6.0 → 3.7.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.
@@ -0,0 +1,108 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { createReadStream } from 'node:fs';
3
+ import * as fs from 'node:fs/promises';
4
+ import * as path from 'node:path';
5
+ import { defaultTreeAdapter, parse } from 'parse5';
6
+ import { BuildError } from '../errors.js';
7
+ /**
8
+ * Gives every relative release URL one content-addressed base, including
9
+ * secondary analyzer requests, fonts and assets owned by the HTML template.
10
+ */
11
+ export function versionAssets() {
12
+ return {
13
+ name: 'version release assets',
14
+ async apply(ctx) {
15
+ if (ctx.project.mode !== 'release' || !ctx.project.config.output.versionedAssets) {
16
+ return;
17
+ }
18
+ const outputDir = ctx.project.outputDir;
19
+ const htmlPath = path.join(outputDir, 'index.html');
20
+ const html = await fs.readFile(htmlPath, 'utf8');
21
+ const headEnd = validateHtml(html);
22
+ const version = await hashDirectory(outputDir);
23
+ const prefix = `assets/${version}/`;
24
+ const entries = await fs.readdir(outputDir);
25
+ const staging = await fs.mkdtemp(path.join(outputDir, '.version-assets-'));
26
+ try {
27
+ for (const entry of entries) {
28
+ if (entry === 'index.html' || entry === 'manifest.json') {
29
+ continue;
30
+ }
31
+ await fs.rename(path.join(outputDir, entry), path.join(staging, entry));
32
+ }
33
+ await fs.mkdir(path.join(outputDir, 'assets'));
34
+ await fs.rename(staging, path.join(outputDir, prefix));
35
+ }
36
+ finally {
37
+ await fs.rm(staging, { recursive: true, force: true });
38
+ }
39
+ prefixOutputs(ctx, prefix);
40
+ const manifest = {
41
+ initial: Object.values(ctx.outputs.engine),
42
+ game: [ctx.outputs.skinsScript, ctx.outputs.entryScript].filter(Boolean),
43
+ };
44
+ await fs.writeFile(path.join(outputDir, 'manifest.json'), JSON.stringify(manifest, undefined, '\t') + '\n');
45
+ await fs.writeFile(htmlPath, `${html.slice(0, headEnd)}\n\t<base href="./${prefix}">${html.slice(headEnd)}`);
46
+ },
47
+ };
48
+ }
49
+ function validateHtml(html) {
50
+ const document = parse(html, { sourceCodeLocationInfo: true });
51
+ const root = document.childNodes.find(defaultTreeAdapter.isElementNode);
52
+ const head = root?.childNodes.filter(defaultTreeAdapter.isElementNode).find(node => node.tagName === 'head');
53
+ // HTML parsing can imply a head; insertion requires its authored start tag.
54
+ const headEnd = head?.sourceCodeLocation?.startTag?.endOffset;
55
+ if (headEnd === undefined) {
56
+ throw new BuildError('output.versionedAssets requires an HTML template with a <head> element.');
57
+ }
58
+ const elements = root ? [root] : [];
59
+ while (elements.length > 0) {
60
+ const element = elements.pop();
61
+ if (element.tagName === 'base') {
62
+ throw new BuildError("output.versionedAssets owns the HTML base URL; remove the template's <base> element.");
63
+ }
64
+ elements.push(...element.childNodes.filter(defaultTreeAdapter.isElementNode));
65
+ }
66
+ return headEnd;
67
+ }
68
+ async function hashDirectory(root) {
69
+ const hash = createHash('sha256');
70
+ const files = await listFiles(root);
71
+ for (const relative of files.sort()) {
72
+ const file = path.join(root, relative);
73
+ const stat = await fs.stat(file);
74
+ hash.update(JSON.stringify([relative, stat.size]) + '\n');
75
+ for await (const chunk of createReadStream(file)) {
76
+ hash.update(chunk);
77
+ }
78
+ }
79
+ return hash.digest('hex').slice(0, 32);
80
+ }
81
+ async function listFiles(root, directory = '') {
82
+ const files = [];
83
+ for (const entry of await fs.readdir(path.join(root, directory), { withFileTypes: true })) {
84
+ const relative = path.posix.join(directory, entry.name);
85
+ if (entry.isDirectory()) {
86
+ files.push(...(await listFiles(root, relative)));
87
+ }
88
+ else if (entry.isFile()) {
89
+ files.push(relative);
90
+ }
91
+ else {
92
+ throw new BuildError(`Versioned assets require regular files or directories: ${relative}`);
93
+ }
94
+ }
95
+ return files;
96
+ }
97
+ function prefixOutputs(ctx, prefix) {
98
+ if (ctx.outputs.entryScript) {
99
+ ctx.outputs.entryScript = prefix + ctx.outputs.entryScript;
100
+ }
101
+ if (ctx.outputs.skinsScript) {
102
+ ctx.outputs.skinsScript = prefix + ctx.outputs.skinsScript;
103
+ }
104
+ for (const specifier of Object.keys(ctx.outputs.engine)) {
105
+ ctx.outputs.engine[specifier] = prefix + ctx.outputs.engine[specifier];
106
+ }
107
+ }
108
+ //# sourceMappingURL=version-assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-assets.js","sourceRoot":"","sources":["../../../src/core/plugins/version-assets.ts"],"names":[],"mappings":"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"}
@@ -1,14 +1,9 @@
1
1
  # @kurot/cli — AI context map
2
2
 
3
- CLI 3.6.0 is prepared for publication, not yet published. Latest verified npm
4
- release is 3.5.0. Development installs
5
- published ui-document 0.13.0 with a matching
6
- registry lockfile, without local overrides. Read
7
- [centered flips](../../../docs/centered-flips.md) for transform and adoption contracts.
8
-
9
- Read this before exploring `src/`. [`architecture.md`](./architecture.md)
10
- explains the plugin pipeline. Version `@kurot/cli@3.6.0` is pending publication, runs on Node.js 20+,
11
- and is installed as a project dev dependency.
3
+ `@kurot/cli@3.7.0` is build-time tooling on Node.js >= 20, with ordinary
4
+ ui-document dependency **^0.13.0**. Projects supply their own Core/UI runtime.
5
+ Read [architecture](architecture.md) for the plugin pipeline; the source and
6
+ configuration exports establish current behavior.
12
7
 
13
8
  ## Directory map
14
9
 
@@ -31,32 +26,15 @@ src/
31
26
  └── utils/
32
27
  ```
33
28
 
34
- Project templates are under `templates/game` and `templates/empty`.
35
- The CLI 3.6.0 game template's default KUI skin refresh includes 16 native Skin files,
36
- a Kurot-owned 2× atlas with logical resource-default nine-slice grids, and project palette
37
- colors replace the old EUI assets. Group/List/TabBar and text/image nodes use
38
- native XML composition rather than unused default Skin placeholders. See
39
- [default KUI skins](default-ui-skins.md). Private tools/default-ui-assets generates
40
- the committed assets with registry Atlas; CLI gains no atlas runtime dependency.
41
- The 2× sheet requires Core ^2.5.0; published Core 2.4.0
42
- does not interpret it. Private preview tooling binds checkout Core in an isolated
43
- trial. Publish Core 2.5.0 before CLI 3.6.0.
44
- The CLI 3.6.0 game template includes the looping mascot brand splash; registry
45
- CLI 3.5.0 does not contain that HTML/logo refresh. See game-template.md.
46
- The 3.2.1 game template includes fixed style/locale configuration,
47
- English properties and licensed regular/bold font files. StyleManager finishes
48
- font loading before Main creates Player/Preloader; LocaleManager registers
49
- preload texts before creating the scene. See [game-template.md](game-template.md).
50
- Version 3.3.0 is published with Label preset compilation and
51
- published ui-document 0.11.0. It has no local document-kernel override.
52
- Published version 3.3.1 adds whole-resource dev synchronization, deletion/reconnect
53
- handling and no-store responses. Installed CLI 3.3.0 lacks these fixes; consumers
54
- must update their installed/locked version to receive them.
55
-
56
- ## Native text adoption in 3.4.0
57
-
58
- Version 3.4.0 registers BitmapLabel and RichLabel from published UI
59
- 3.3.0 and consumes document 0.12.0. `kui/validate-text-components.ts` applies
29
+ Project templates are under `templates/game` and `templates/empty`, including
30
+ README/AGENTS entries for installed SDK guides and project commands. The game
31
+ template supplies paired KUI/TS components, default skins, a 2× atlas, palette,
32
+ fonts, translations and splash HTML. See [template startup](game-template.md)
33
+ and [default skins](default-ui-skins.md).
34
+
35
+ ## Native text compilation
36
+
37
+ The compiler registers BitmapLabel and RichLabel through ui-document. `kui/validate-text-components.ts` applies
60
38
  strict shared property/state validation only to these new built-ins, preserving
61
39
  existing CLI-only and custom class contracts. Text flows remain literal arrays;
62
40
  Span data does not create nodes/parts. Only width/height use percent conversion.
@@ -78,11 +56,11 @@ transforms such as `flipX`/`flipY` belong on those children. Overrides use local
78
56
  `property.state` attributes. Storage IDs and runtime mapping metadata are not
79
57
  authored XML fields.
80
58
 
81
- CLI 3.5.0 validates centered-flip booleans on display nodes and named-state
59
+ The compiler validates centered-flip booleans on display nodes and named-state
82
60
  overrides, including CLI-only controls. Malformed values and flags on the
83
61
  nonvisual Skin root fail compilation. Negative scales are preserved.
84
62
 
85
- CLI 3.6.0 requires `@kurot/ui-document@^0.13.0`. Schema-defined strings, including
63
+ The CLI requires `@kurot/ui-document@^0.13.0`. Schema-defined strings, including
86
64
  numeric/boolean-looking text and state text, are literal attributes without
87
65
  backslash type escaping. Old synthetic prefixes become literal characters;
88
66
  do not migrate them silently. Numeric/boolean properties and schema-free
@@ -105,6 +83,10 @@ as the part name. Internal nodes can omit `id`; the declaration augments
105
83
  component classes. The file is development metadata and is excluded from
106
84
  runtime output.
107
85
 
86
+ The generator narrows host `skinParts` through a getter signature,
87
+ preserving Component's accessor kind under `skipLibCheck=false`. Regenerate after
88
+ authored Skin changes; keep generated declarations out of manual edits.
89
+
108
90
  ## Reusable components
109
91
 
110
92
  With `ui.components`, `<Name>.ts` under `sourceDir` pairs with
@@ -125,7 +107,7 @@ manual prefix cannot conflict with `ui.components.namespace`.
125
107
  `--strict` or release policy.
126
108
  - Machine diagnostic modes own stdout: build emits one JSON result; dev emits
127
109
  JSONL lifecycle events.
128
- - Since 3.3.1, dev watches all resource assets even without UI, emits
110
+ - Dev watches all resource assets even without UI, emits
129
111
  resource-change for copy-only batches, retains KUI requirements across mixed
130
112
  batches, and reconciles deletions. Browser refresh remains manual; HTTP is
131
113
  no-store. Per-file staging/rename is not an atomic atlas pair transaction.
@@ -136,9 +118,8 @@ manual prefix cannot conflict with `ui.components.namespace`.
136
118
  - Engine and custom namespace chunks share `ctx.outputs.engine` because the
137
119
  import-map writer treats both as external specifier mappings.
138
120
  - Engine and reusable namespace bundles preserve class names in both modes.
139
- The CLI 3.6.0 development fix also protects self-referencing classes, which
140
- esbuild can rename without minification. Registry CLI 3.5.0 protects release
141
- names only. Theme fallback uses constructor names.
121
+ Self-referencing classes retain stable names in both modes because Theme
122
+ fallback uses constructor names.
142
123
  - The Skin module builder stages output in a temporary directory and installs a
143
124
  bundle only after every Skin succeeds.
144
125
  - `cleanOutput` wipes the active output directory at the start of each build.
@@ -146,11 +127,10 @@ manual prefix cannot conflict with `ui.components.namespace`.
146
127
  - `create` queries the npm registry for current Kurot package versions and falls
147
128
  back to `latest` if the request fails.
148
129
  - Release output is timestamped and `manifest.json` exists only in release.
149
- - The CLI 3.6.0 asset-copy correction omits empty runtime directory trees,
130
+ - Asset copying omits empty runtime directory trees,
150
131
  including skin-only `resource/ui`. Runtime files under UI directories remain
151
132
  eligible; generated theme JSON and the compiled Skin module remain required.
152
- Template copies still preserve empty directories. Registry CLI 3.5.0 does not
153
- include this correction.
133
+ Template copies still preserve empty directories.
154
134
 
155
135
  ## Plugin order
156
136
 
@@ -164,11 +144,19 @@ manual prefix cannot conflict with `ui.components.namespace`.
164
144
  6. compile application source;
165
145
  7. generate HTML;
166
146
  8. write the release manifest;
167
- 9. copy runtime assets.
147
+ 9. copy runtime assets;
148
+ 10. optionally version release assets with `output.versionedAssets`.
168
149
 
169
150
  Do not reorder namespace or source compilation without reviewing externalization
170
151
  in `namespace-external-plugin.ts`.
171
152
 
153
+ Release versioning runs last so the digest covers generated themes, scripts,
154
+ resource bytes and template assets. It keeps index.html/manifest.json at the
155
+ output root and moves all other files under assets/<hash>/. The HTML base URL
156
+ versions document-relative requests; callers that explicitly resolve URLs must
157
+ use document.baseURI. Existing UI Theme must receive an absolute config URL.
158
+ See [release assets](release-assets.md). This option requires CLI >= 3.7.0 within 3.x.
159
+
172
160
  ## Configuration lookup
173
161
 
174
162
  | Task | File |
@@ -198,14 +186,14 @@ pnpm test
198
186
  CLI end-to-end tests bind localhost and may require permission in a restricted
199
187
  execution environment.
200
188
 
201
- ## Resource configuration change in 3.0.0
189
+ ## Resource configuration
202
190
 
203
191
  KUI builds validate object subkeys, resolve resource nine-slice defaults, and
204
192
  watch the manifest during development. See
205
193
  [the resource-default contract](../../ui-document/docs/resource-nine-slice.md)
206
194
  for conversion and compilation boundaries.
207
195
 
208
- ## Label text compilation in 3.1.0
196
+ ## Label text compilation
209
197
 
210
198
  The compiler consumes the shared ui-document catalog and emits Label `textFit`,
211
199
  `minFontSize`, authored `size` and state-size overrides unchanged. Runtime
@@ -215,7 +203,7 @@ within their respective majors. Neither engine is a CLI runtime dependency.
215
203
  See [text compilation](label-text-layout.md) and
216
204
  [native Label text layout](../../ui/docs/label-text-layout.md) for the boundary.
217
205
 
218
- ## Project styles in 3.2.0
206
+ ## Project styles
219
207
 
220
208
  Read [project styles](../../ui-document/docs/project-styles.md). buildSkinsModule
221
209
  reads the optional fixed config/style.json once per build and forwards its numeric
@@ -226,13 +214,11 @@ without migrating files. Fonts are validated but not loaded; the application own
226
214
  font loading and rendering. Build/preview copies resolve references while authored
227
215
  XML retains them. No live runtime palette switching is introduced.
228
216
 
229
- ## Label presets in 3.3.0
217
+ ## Label presets
230
218
 
231
219
  skin-module-builder.ts reads the entire stylesheet once per build and passes it
232
220
  through parseToIR/parseKUISkin. Resolve resource defaults, then Label presets, then colors before
233
221
  native emission; retain XML references and local/state precedence. compileKUI
234
222
  accepts an optional styleSheet. style.json changes already trigger whole-Skin
235
- rebuilds. Invalid presets retain the last successful bundle. The 3.3.0 dependency and
236
- lockfile used published ui-document 0.11.0 without a local override. Current
237
- CLI 3.5.0 development uses published ui-document 0.13.0. textStyle is
223
+ rebuilds. Invalid presets retain the last successful bundle. textStyle is
238
224
  Default-only; individual named-state fields can still override preset properties.
@@ -18,6 +18,7 @@ clean output
18
18
  → generate HTML
19
19
  → write release manifest
20
20
  → copy runtime assets
21
+ → optionally version release assets
21
22
  ```
22
23
 
23
24
  KUI compilation runs first because skin factories can import project namespace
@@ -39,7 +40,7 @@ factory variables, property assignments, semantic layout children, and state
39
40
  property overrides. Document contracts, reusable instances, data bindings, and
40
41
  actions remain `UIDocument` concepts.
41
42
 
42
- CLI 3.6.0 consumes ui-document ^0.13.0, retaining Label text-fitting metadata. The
43
+ CLI 3.7.0 consumes ui-document ^0.13.0, retaining Label text-fitting metadata. The
43
44
  compiler emits `textFit`, `minFontSize`, base font sizes and state overrides;
44
45
  native UI owns measurement and derives drawing sizes after layout validation.
45
46
  See [Label compilation](label-text-layout.md). The application supplies UI
@@ -71,6 +72,13 @@ Development builds preserve application source module structure under
71
72
  `manifest.json`. Static resources retain stable paths because application code
72
73
  addresses them by key or URL.
73
74
 
75
+ With `output.versionedAssets: true`, the final stage hashes the complete output
76
+ and moves runtime files into `assets/<hash>/`. The entry HTML receives a base URL;
77
+ the root release manifest and BuildContext script paths receive the same prefix.
78
+ Relative references inside resources and ESM modules remain intact. This is one
79
+ version for the complete build, rather than independent hashes per resource.
80
+ See [release deployment](release-assets.md) for URL and hosting requirements.
81
+
74
82
  Asset copying creates directories only when an accepted runtime file needs them.
75
83
  KUI source files and source theme JSON are excluded when UI compilation is enabled,
76
84
  so a skin-only `resource/ui` tree is absent from output. Mixed directories retain
@@ -84,7 +92,7 @@ convention-based reusable components. A component change can affect its source
84
92
  namespace, paired skin, generated type declaration, and editor catalog, so that
85
93
  path refreshes all four outputs as one operation. The server preserves the last
86
94
  successful output after an invalid edit.
87
- Since 3.3.1, the resource watcher synchronizes all runtime assets even without UI,
95
+ The resource watcher synchronizes all runtime assets even without UI,
88
96
  and reconciles additions, deletions and directory replacement. Runtime-only
89
97
  changes do not recompile skins. The fixed style.json and default.res.json paths
90
98
  still trigger KUI compilation; font loading remains an application responsibility.
@@ -1,8 +1,6 @@
1
1
  # Default KUI skins
2
2
 
3
- This game-template refresh is included in CLI 3.6.0, pending publication.
4
- Registry CLI 3.5.0 contains the older atlas. The 2× kit requires Core ^2.5.0;
5
- publish Core 2.5.0 before CLI 3.6.0.
3
+ The 2× atlas needs Core >= 2.5.0 within 2.x for source-density metadata.
6
4
  The template owns the XML, textures and project colors; `@kurot/ui`
7
5
  does not ship a bitmap theme or load a stylesheet itself.
8
6
 
@@ -30,14 +28,12 @@ to draw the components, and no runtime light/dark switching is introduced.
30
28
  ## Text and spacing
31
29
 
32
30
  Single-line captions use `multiline="false" verticalAlign="middle"` with the
33
- Core 2.5.0 ink-centering correction. Button label padding is 10 pixels
31
+ native dynamic-text ink centering. Button label padding is 10 pixels
34
32
  above/below; its down state uses 12/8 to retain a deliberate 2-pixel press offset.
35
33
  The icon has the same neutral/down centers. Panel titles also opt into middle
36
34
  alignment. Input text retains Core's stable font baseline while its placeholder
37
35
  uses dynamic visual centering. No language-specific skin offsets are required.
38
- See [Core text alignment](../../core/docs/text-layout.md#visual-centering-and-stable-baselines-core-250).
39
- Published Core 2.4.0 does not contain that correction; the isolated preview uses
40
- checkout Core for both text alignment and source density.
36
+ See [Core text alignment](../../core/docs/text-layout.md#baselines-and-cached-metrics).
41
37
 
42
38
  ## Resources and XML
43
39
 
@@ -72,13 +68,11 @@ automatic scrolling policies and touch/trackpad scrolling. To display bars in a
72
68
  project, edit those parts explicitly.
73
69
 
74
70
  ItemRenderer backgrounds fit the allocated row width without extra horizontal
75
- padding. The checkout Core also fixes fractional WebGL scissor bounds so scaled
76
- Lists retain their right outline. Published Core 2.4.0 lacks that correction;
77
- shrinking the skin or changing its nine-slice grid is not required.
71
+ padding. Core encloses fractional WebGL scissor bounds so scaled Lists retain their
72
+ right outline; use the allocated row geometry without compensating skin offsets.
78
73
 
79
74
  Group, List, TabBar, ViewStack and text/image nodes are composed directly in XML;
80
- their old default-Skin placeholders were not conventional Theme mappings and
81
- are removed. Use `itemRendererSkinName` to choose a List/TabBar row appearance,
75
+ they do not require placeholder default skins. Use `itemRendererSkinName` to choose a List/TabBar row appearance,
82
76
  and wrap the node with Group/Image/Scroller for its surface and viewport.
83
77
 
84
78
  ## Native preview and maintenance
@@ -87,37 +81,31 @@ and wrap the node with Group/Image/Scroller for its surface and viewport.
87
81
  `src/DefaultUI.ts` only connects data and events. The example installs its own
88
82
  project font loader and document dependency; other projects are unchanged.
89
83
 
90
- Core 2.5.0 is published. Until the example adopts it, build Core/CLI for an isolated
91
- source trial. The example's registry lock does not yet contain density support:
84
+ Use the checkout CLI with the example's installed SDKs. From the repository root:
92
85
 
93
86
  ```sh
94
- pnpm --dir packages/core build
95
87
  pnpm --dir packages/cli build
96
- pnpm --dir tools/default-ui-assets preview
88
+ cd examples/game
89
+ node ../../packages/cli/dist/index.js dev
97
90
  ```
98
91
 
99
- The preview tool prints a new directory under docs-internal, with strict dev
100
- and minified release builds. It links the built checkout Core and the example's
101
- installed UI/Game/document packages; it does not edit application installations
102
- or locks. Run the repository CLI dev command in that printed directory and open
103
- the server URL with `?ui=1`. The ordinary game remains available without
92
+ Open the server URL with `?ui=1`; the ordinary scene remains available without
104
93
  that parameter. Try the inputs, switches, ComboBox, tabs, sliders, panel close
105
- button and draggable List. The gallery is rendered by Core/UI from compiled
106
- KUI XML. After explicitly installing the Core 2.5.0 release in the
107
- example, ordinary repository-CLI builds can run directly from examples/game.
94
+ button and draggable List. The gallery uses the example's installed Core/UI
95
+ with compiled KUI XML, without modifying dependencies or locks. In that example
96
+ directory, the same CLI accepts `build` and `build --release` for one-shot builds.
97
+ The private asset tool's isolated source preview remains an optional maintenance
98
+ tool for testing checkout engine changes; it is not required by the installed Core.
108
99
 
109
- CLI 3.6.0 preserves constructor names in development and release
100
+ The CLI preserves constructor names in development and release
110
101
  engine/namespace bundles so Theme lookup also works for self-referencing
111
- classes such as Scroller. Published CLI 3.5.0 lacks the development correction.
102
+ classes such as Scroller.
112
103
 
113
104
  `tools/default-ui-assets` contains editable SVG geometry and the reproducible
114
105
  PNG/atlas generator. It uses registry `@kurot/atlas@0.1.0` only as private
115
106
  repository tooling. CLI and runtime SDKs gain no atlas dependency. See its
116
107
  [maintenance instructions](../../../tools/default-ui-assets/README.md).
117
108
 
118
- Core 2.5.0 must be published before CLI 3.6.0.
119
- UI/Game/document/runtime need no incidental release; existing 1× consumers keep
120
- their behavior. See [density units and adoption](../../core/docs/texture-density.md).
121
- Existing projects keep their own skins, resource keys and startup code. New
122
- scaffolds receive this kit after the supporting Core and CLI publications;
123
- installing a new CLI does not rewrite an existing project's resources.
109
+ Existing projects keep their own skins, resource keys and startup code. Updating
110
+ the installed CLI does not rewrite authored resources. New scaffolds receive
111
+ the template's current kit.
@@ -1,8 +1,7 @@
1
1
  # Development resource watching
2
2
 
3
- Available in published CLI 3.3.1. No configuration or
4
- dependency-range changes are required. Projects must install the new CLI to
5
- receive these behaviors; installed CLI 3.3.0 does not include them.
3
+ `kurot dev` synchronizes runtime assets without additional watcher configuration.
4
+ Browser refresh remains manual.
6
5
 
7
6
  ## Inputs and rebuilds
8
7
 
@@ -1,8 +1,11 @@
1
- # Project styles and languages in the game template
1
+ # Game template startup and project services
2
2
 
3
- Project-owned style/font/language initialization was introduced in CLI 3.2.1
4
- and remains in CLI 3.6.0 (pending publication). Existing projects keep their own startup
5
- code and HTML; the empty template stays minimal.
3
+ The game template owns its style/font/language initialization, HTML, README and
4
+ AGENTS entry. The empty template stays Core-only. New scaffolds receive these
5
+ files; existing projects keep their own authored resources and instructions.
6
+ For UI organization and component/Skin pairing use
7
+ [standard authoring](../../ui/docs/ui-authoring.md) and the
8
+ [ScoreHUD recipe](../../ui/docs/recipes/score-hud.md).
6
9
 
7
10
  ## Files
8
11
 
@@ -30,8 +33,6 @@ Templates do not implement live font/theme/language replacement.
30
33
 
31
34
  ## HTML brand splash
32
35
 
33
- This splash is included in CLI 3.6.0, pending publication; npm CLI 3.5.0 lacks it.
34
-
35
36
  The game template's `web/index.html` presents `web/logo.png` beneath a small
36
37
  "Made with" caption. The mascot makes a gentle entrance, then repeats a playful
37
38
  hop and sway every 3.2 seconds while the entry module loads. Sparkles and a soft
@@ -48,9 +49,8 @@ existing project HTML is project-owned.
48
49
 
49
50
  ## Change fonts and colors
50
51
 
51
- The CLI 3.6.0 [default KUI skins](default-ui-skins.md) use Kurot-owned textures
52
- under resource/assets/ui/kui and a matching color palette. Registry CLI 3.5.0
53
- does not include this skin refresh. Skin state text colors compile from the
52
+ The [default KUI skins](default-ui-skins.md) use Kurot-owned textures under
53
+ resource/assets/ui/kui and a matching color palette. Skin state text colors compile from the
54
54
  project stylesheet; texture colors are baked into the PNG, without live palette
55
55
  switching. Templates inherit project fonts and retain the existing licensed files.
56
56
 
@@ -1,6 +1,6 @@
1
1
  # Label text compilation
2
2
 
3
- CLI 3.6.0 consumes ui-document ^0.13.0 and compiles KUI text-fitting properties
3
+ The CLI consumes ui-document ^0.13.0 and compiles KUI text-fitting properties
4
4
  through the existing UIDocument → SkinIR → ESM factory pipeline. The semantic
5
5
  document format remains version 2.
6
6
 
@@ -34,12 +34,10 @@ introduces build-time text measurement. See the
34
34
 
35
35
  ## Runtime boundary
36
36
 
37
- - The application must install UI `^3.1.0` and Core `^2.1.0` for shrinking.
38
- These are the feature's original API minimums. Installing current UI 3.4.0
39
- requires Core `^2.4.0` for that package's centered-flip contract.
40
- They remain application dependencies; CLI depends on the headless document
41
- package rather than importing the engine into the build process.
42
- - `textFit` is `none` by default or `shrink` for ordinary single-line Labels.
37
+ - Applications supply an accepted Core/UI pair and satisfy the installed UI's
38
+ Core peer. The compiler depends on the headless document kernel.
39
+ - `textFit` is `none` by default or `shrink` for ordinary Labels.
40
+ Supported fitting modes and bounds follow the installed native UI contract.
43
41
  Put a Button's policy on its `labelDisplay` skin part.
44
42
  - `minFontSize` defaults to 12 logical pixels and must be finite and >= 1.
45
43
  A minimum greater than the authored size does not enlarge the text.
@@ -47,20 +45,20 @@ introduces build-time text measurement. See the
47
45
  State removal restores the authored base size before fitting again.
48
46
  - `renderedSize` and `textFitOverflow` are runtime observations; do not author
49
47
  them in KUI XML.
50
- - Multiline Labels keep their base size; EditableText rejects shrinking.
48
+ - EditableText rejects shrinking. Current native Label supports fitting in either
49
+ line mode; `multiline` continues to choose line generation.
51
50
  - Load fonts before measuring text. For late loading, native UI callers use
52
51
  `label.invalidateSize()` after the font becomes ready.
53
52
 
54
- UI 3.1's public Label contract owns the full fitting, overflow, layout and
55
- font-readiness rules. ui-document 0.9's catalog describes the authoring fields.
56
- The build does not rewrite existing skins or apply project translation rules.
53
+ The [native Label contract](../../ui/docs/label-text-layout.md) owns fitting,
54
+ overflow, layout and font-readiness rules. The compiler does not rewrite
55
+ existing skins or apply project translation rules.
57
56
 
58
- ## Migration
57
+ ## Authored line policy
59
58
 
60
- In Core 2.1.0, explicit `multiline="false"` means one unwrapped first line.
59
+ Explicit `multiline="false"` means one unwrapped first line.
61
60
  Remove that flag or set it to true where wrapping is intended. The literal-string
62
61
  XML contract is retained: a backslash followed by `n` stays literal text rather
63
62
  than becoming a hard separator.
64
63
 
65
- Existing EXML projects remain on CLI 1.3.x. The KUI release does not introduce
66
- an EXML migration or resource-format change.
64
+ EXML authoring uses the CLI 1.x line. This KUI compiler does not migrate EXML.
@@ -0,0 +1,76 @@
1
+ # Versioned release assets
2
+
3
+ Enable content-addressed release packaging in `kurot.config.ts`:
4
+
5
+ ```ts
6
+ export default {
7
+ output: { dir: 'bin-debug', versionedAssets: true },
8
+ // Keep the project's other settings.
9
+ };
10
+ ```
11
+
12
+ The option requires CLI >= 3.7.0 within 3.x. It defaults to false and is ignored
13
+ by development/watch builds.
14
+ An index query string does not propagate to requests for resources.
15
+
16
+ ## Output and URLs
17
+
18
+ ```text
19
+ bin-release/web/<timestamp>/
20
+ ├── index.html
21
+ ├── manifest.json
22
+ └── assets/<hash>/
23
+ ├── js/
24
+ ├── resource/
25
+ └── <files copied beside the HTML template>
26
+ ```
27
+
28
+ The hash is the first 32 hexadecimal characters of SHA-256 over sorted output
29
+ paths, file sizes and bytes, including generated HTML, theme JSON and scripts.
30
+ Any changed file changes the complete build's version. Identical builds retain
31
+ their URL; unchanged individual files also get new URLs when another file changes.
32
+ This trades granular cache reuse for one consistent release across all loaders.
33
+
34
+ The CLI inserts `<base href="./assets/<hash>/">` first inside `<head>`. A request
35
+ for `resource/assets/atlas.png` then resolves under the version directory, even
36
+ when the entry is `/game/index.html?launch=...`. Atlas `file` references, bitmap
37
+ font pages, stylesheet fonts, relative imports and direct browser requests use
38
+ that directory without rewriting authored resources or keys. The release manifest
39
+ stays at the root with prefixed script paths. Source maps move with their scripts.
40
+
41
+ Custom templates must have an explicit `<head>` and no `<base>` element. The
42
+ CLI inserts the base at the parsed start tag's source location without
43
+ reserializing the template. Quoted attributes and script/style text are preserved.
44
+ The build rejects symbolic links and other nonregular output files. Relative URLs
45
+ must refer to files inside the build; root-relative URLs, remote URLs, and URLs
46
+ explicitly based on location.href remain outside this mechanism. Applications
47
+ that construct URLs should use document.baseURI for build assets. Relative links
48
+ and forms also inherit the base; use explicit destinations for application navigation.
49
+ If hosting has a CSP base-uri directive, it must allow this same-origin base.
50
+
51
+ ## Theme loading with existing UI
52
+
53
+ UI runtimes that resolve a relative Theme config against location.href need an
54
+ absolute config URL. The game starter uses:
55
+
56
+ ```ts
57
+ const theme = new Theme(new URL('resource/default.thm.json', document.baseURI).href);
58
+ ```
59
+
60
+ Use the same pattern in existing projects. This keeps the theme's `skinsJs`
61
+ import inside the version directory without requiring a UI runtime update.
62
+
63
+ ## Deployment
64
+
65
+ Upload the complete generated directory, including `assets/<hash>/`. Upload new
66
+ asset directories first, then replace root manifest.json and index.html. Keep
67
+ previous version directories available while older sessions may request assets;
68
+ avoid deploy commands that delete those directories immediately. Publish the
69
+ entry at a directory URL ending in `/` or at its actual `index.html` URL.
70
+
71
+ Serve index.html with revalidation, for example `Cache-Control: no-cache`.
72
+ Serve `assets/<hash>/**` with `Cache-Control: public, max-age=31536000, immutable`.
73
+ If a launcher reads root manifest.json, give it revalidation too. These are server
74
+ settings; the CLI writes static files and cannot set response headers. Never
75
+ overwrite files inside an already published hash directory. Rollback replaces
76
+ the root entry files with those of the previous complete release.
@@ -1,12 +1,8 @@
1
1
  # BitmapLabel and RichLabel compilation
2
2
 
3
- Native text compilation was introduced in CLI 3.4.0 with document 0.12.0.
4
- Current CLI 3.6.0 requires published ui-document ^0.13.0 and retains these tags.
5
- Applications rendering these tags
6
- must install UI `^3.3.0` and Core `^2.3.0`; Core 2.3.1 fixes unstyled blank
7
- rich-text line metrics. The CLI does not install or bundle its own Core/UI.
8
- Document format version 2 and existing project configuration are unchanged.
9
- Installing UI 3.4.0 requires Core ^2.4.0 for that package's centered-flip contract.
3
+ The compiler registers native text types through ui-document and generates Skin
4
+ factories. Applications supply an accepted Core/UI pair; the CLI does not bundle
5
+ its own engine. Semantic document format is 2.
10
6
 
11
7
  ```xml
12
8
  <Skin xmlns="https://kurot.dev/ui/1" class="TextSkin" states="disabled">