@hagicode/hagiscript 0.1.6-dev.47.1.59c65fa → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +259 -134
  2. package/README_cn.md +321 -0
  3. package/package.json +3 -2
package/README.md CHANGED
@@ -1,231 +1,356 @@
1
- # Hagiscript Runtime Guide
1
+ # Hagiscript
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/%40hagicode%2Fhagiscript?logo=npm&color=cb3837)](https://www.npmjs.com/package/@hagicode/hagiscript)
4
4
  [![npm downloads](https://img.shields.io/npm/dm/%40hagicode%2Fhagiscript?logo=npm&color=2d8cf0)](https://www.npmjs.com/package/@hagicode/hagiscript)
5
5
  [![license](https://img.shields.io/badge/license-MIT-ffd43b)](./LICENSE)
6
6
 
7
- `@hagicode/hagiscript` is the runtime management CLI behind the `hagicode-runtime` contract. Use it to install, inspect, update, remove, and operate a managed HagiCode runtime without depending on system Node.js, system PM2, or host-global npm packages.
7
+ `@hagicode/hagiscript` is the scoped npm package foundation for future Hagiscript language tooling. This initial package intentionally keeps runtime behavior small: it exposes version metadata, a baseline runtime-info API, and an executable CLI placeholder that can be built, tested, packed, and published safely.
8
8
 
9
- ## Install
9
+ ## Installation Assumptions
10
10
 
11
- ```bash
12
- npm install -g @hagicode/hagiscript
13
- ```
11
+ - Node.js 20 or newer is required.
12
+ - npm is the package manager for this standalone repository.
13
+ - The npm package name is `@hagicode/hagiscript`.
14
+ - GitHub Actions publishing uses `npm publish --provenance`. Local manual publishing should use plain `npm publish` unless you are inside a supported trusted publishing environment.
14
15
 
15
- Primary entrypoints:
16
+ ## Usage
16
17
 
17
- - `hagiscript`
18
- - `hagicode-runtime` (`hagiscript runtime ...` wrapper)
18
+ Install the package from npm:
19
19
 
20
- Node.js 20 or newer is required to run the package itself.
20
+ ```bash
21
+ npm install @hagicode/hagiscript
22
+ ```
21
23
 
22
- ## Runtime Model
24
+ The installed CLI command remains `hagiscript`.
23
25
 
24
- By default, Hagiscript loads `runtime/manifest.yaml` and manages the runtime under `~/.hagicode/runtime`.
26
+ Run the CLI locally during development:
25
27
 
26
- ```text
27
- <runtime-root>/
28
- program/
29
- bin/
30
- npm/
31
- components/
32
- runtime-data/
33
- config/
34
- logs/
35
- data/
36
- components/
37
- state.json
28
+ ```bash
29
+ npm run dev -- --help
30
+ npm run dev -- info
31
+ npm run dev -- install-node --target .tmp/node-runtime
32
+ npm run dev -- check-node --target .tmp/node-runtime
33
+ npm run dev -- npm-sync --runtime .tmp/node-runtime --manifest manifest.json
38
34
  ```
39
35
 
40
- The split is intentional:
41
-
42
- - `program/` holds managed executables, vendored payloads, wrappers, and the managed npm prefix.
43
- - `runtime-data/` holds mutable config, logs, state, PM2 data, and component-specific writable files.
44
-
45
- The packaged manifest currently manages:
36
+ After building, run the compiled CLI:
46
37
 
47
- - `node` - managed Node.js runtime
48
- - `dotnet` - managed .NET runtime
49
- - `npm-packages` - managed npm prefix, including `pm2`
50
- - `omniroute` - vendored bundled runtime
51
- - `code-server` - vendored bundled runtime
38
+ ```bash
39
+ npm run build
40
+ node dist/cli.js --version
41
+ node dist/cli.js info
42
+ node dist/cli.js install-node --target .tmp/node-runtime
43
+ node dist/cli.js check-node --target .tmp/node-runtime
44
+ node dist/cli.js npm-sync --runtime .tmp/node-runtime --manifest manifest.json
45
+ ```
52
46
 
53
- ## Core Runtime Commands
47
+ ### Managed Node.js Runtime Commands
54
48
 
55
- Install the full runtime:
49
+ `install-node` downloads an official Node.js archive from `https://nodejs.org/dist`, extracts it into the target directory, and verifies both `node` and `npm` before reporting success.
56
50
 
57
51
  ```bash
58
- hagiscript runtime install
52
+ hagiscript install-node --target /opt/hagiscript/node
53
+ hagiscript install-node --target /opt/hagiscript/node20 --version 20
54
+ hagiscript install-node --target /opt/hagiscript/lts --version lts
59
55
  ```
60
56
 
61
- Install selected components only:
57
+ When `--version` is omitted, Hagiscript installs the latest available Node.js 22 release. Supported selectors are `lts`, `latest`, `current`, a major version such as `22`, an exact version such as `22.12.0`, or an exact version with a `v` prefix such as `v22.12.0`.
62
58
 
63
- ```bash
64
- hagiscript runtime install --components node,npm-packages
65
- ```
59
+ The target path must be missing or empty. Hagiscript refuses to install into a non-empty target directory and does not delete existing user files. During installation, temporary staging files are created beside the target directory and cleaned up after success or failure.
66
60
 
67
- Preview planned changes without mutating files:
61
+ Example success output:
68
62
 
69
- ```bash
70
- hagiscript runtime install --dry-run
71
- hagiscript runtime update --check-only
63
+ ```text
64
+ Installing Node.js 22 into /opt/hagiscript/node
65
+ Download progress: 100%
66
+ Node.js runtime installed successfully.
67
+ Target: /opt/hagiscript/node
68
+ Node.js: v22.12.0
69
+ npm: 10.9.0
70
+ node: /opt/hagiscript/node/bin/node
71
+ npm: /opt/hagiscript/node/bin/npm
72
72
  ```
73
73
 
74
- Inspect the canonical runtime state:
74
+ `check-node` validates an existing runtime directory and exits with code `0` only when both `node --version` and `npm --version` succeed.
75
75
 
76
76
  ```bash
77
- hagiscript runtime state
78
- hagiscript runtime state --json
77
+ hagiscript check-node --target /opt/hagiscript/node
79
78
  ```
80
79
 
81
- Update or remove managed components:
80
+ Example valid output:
82
81
 
83
- ```bash
84
- hagiscript runtime update
85
- hagiscript runtime remove --components code-server --purge
82
+ ```text
83
+ Node.js runtime is valid.
84
+ Target: /opt/hagiscript/node
85
+ Node.js: v22.12.0
86
+ npm: 10.9.0
87
+ node: /opt/hagiscript/node/bin/node
88
+ npm: /opt/hagiscript/node/bin/npm
86
89
  ```
87
90
 
88
- Override the runtime root or manifest when needed:
91
+ Example invalid output exits non-zero and includes the failure reason:
89
92
 
90
- ```bash
91
- hagiscript runtime install --runtime-root /srv/hagicode/runtime
92
- hagiscript runtime state --from-manifest /path/to/runtime-manifest.yaml --json
93
+ ```text
94
+ Node.js runtime is invalid.
95
+ Target: /opt/hagiscript/node
96
+ Reason: missing executable
93
97
  ```
94
98
 
95
- If you prefer the runtime-oriented wrapper:
99
+ ### npm Global Package Synchronization
100
+
101
+ `npm-sync` aligns npm global packages inside a HagiScript-managed Node.js runtime with a JSON manifest. By default, it verifies or installs the managed runtime at `~/.hagiscript/node-runtime` and uses that runtime's `npm`; it does not use or mutate npm from the ambient shell `PATH`. Existing automation can keep passing `--runtime` to use an explicit runtime directory.
96
102
 
97
103
  ```bash
98
- hagicode-runtime install --runtime-root /srv/hagicode/runtime
104
+ hagiscript npm-sync --manifest ./manifest.json
105
+ hagiscript npm-sync --runtime /opt/hagiscript/node --manifest ./manifest.json
106
+ hagiscript npm-sync --manifest ./manifest.json --force
107
+ hagiscript npm-sync --manifest ./manifest.json --registry-mirror https://registry.npmmirror.com/
108
+ hagiscript npm-sync --manifest ./manifest.json --registry-mirror https://registry.npmmirror.com/ --mirror-only
109
+ ```
110
+
111
+ Compatibility manifest schema:
112
+
113
+ ```json
114
+ {
115
+ "registryMirror": "https://registry.npmmirror.com/",
116
+ "packages": {
117
+ "<npm-package-name>": {
118
+ "version": "<semver range>",
119
+ "target": "<optional npm install selector>"
120
+ }
121
+ }
122
+ }
99
123
  ```
100
124
 
101
- ## Runtime State and Maintenance
125
+ The required `version` field accepts package.json-style semver ranges such as `^1.2.0`, `>=1.0.0 <2.0.0`, or `1.0.0 || 2.0.0`. The optional `target` field controls the selector used for `npm install -g`; when omitted, Hagiscript installs `<package>@<version>`.
102
126
 
103
- `hagiscript runtime state --json` is the canonical inspection surface for automation. It reports:
127
+ By default, `npm-sync` plans installed packages that already satisfy the requested range as `noop` and skips `npm install -g` for them. Use `--force` to skip that installed-package satisfaction check and re-run sync for matching packages. `--force` does not upgrade packages to the latest version and does not change semver selection; it only turns an otherwise skipped `noop` action into an executable `sync` action.
104
128
 
105
- - resolved runtime root
106
- - `program/` and `runtime-data/` locations
107
- - per-component install status
108
- - per-component runtime data homes
109
- - derived PM2 homes for managed services
110
- - program/data path separation
129
+ The optional top-level `registryMirror` field configures the npm registry used for both inventory and install commands. It must be a non-empty absolute `http:` or `https:` URL. When present, HagiScript first appends `--registry <registryMirror>` to `npm list -g --depth=0 --json` and `npm install -g <package>@<selector>` without changing package selection. If that mirror-backed npm command fails, HagiScript automatically retries the same inventory or install command once against the official npm registry `https://registry.npmjs.org/`. This mirror-first retry scope is intentionally limited to npm inventory and package mutation commands; runtime validation, manifest validation, and package planning do not retry. This is useful for public mirrors such as `https://registry.npmmirror.com/` or enterprise registries such as `https://npm.company.example/repository/npm/`.
111
130
 
112
- Use it before and after maintenance work to confirm the expected component set and writable paths.
131
+ Product-managed tool sync can use the expanded `tools` manifest shape. Mandatory tools are always included using internally pinned versions from `src/runtime/tool-sync-catalog.config.json`: OpenSpec skills (`skills@1.5.1`), OmniRoute (`omniroute@3.6.9`), and code-server (`code-server@4.117.0`). Optional agent CLI sync is enabled explicitly; selected built-in CLIs or custom npm packages are added when provided.
113
132
 
114
- Typical maintenance flow:
133
+ ```json
134
+ {
135
+ "registryMirror": "https://npm.company.example/repository/npm/",
136
+ "tools": {
137
+ "optionalAgentCliSyncEnabled": true,
138
+ "selectedOptionalAgentCliIds": ["codex", "claude-code", "fission-openspec", "opencode"],
139
+ "customAgentClis": [
140
+ {
141
+ "packageName": "@scope/agent-cli",
142
+ "version": "^1.0.0"
143
+ }
144
+ ]
145
+ }
146
+ }
147
+ ```
115
148
 
116
- 1. Check current state: `hagiscript runtime state --json`
117
- 2. Apply changes: `hagiscript runtime install`, `update`, or `remove`
118
- 3. Re-check state to confirm the final layout
119
- 4. Operate services through `hagiscript pm2 ...`
149
+ The first built-in optional agent CLI IDs are `codex` (`@openai/codex@0.125.0`), `claude-code` (`@anthropic-ai/claude-code@2.1.119`), `fission-openspec` (`@fission-ai/openspec@1.3.1`), `qoder` (`@qoder-ai/qodercli@0.1.48`), and `opencode` (`opencode-ai@1.14.24`). These built-in package versions are pinned in `src/runtime/tool-sync-catalog.config.json`. HagiScript validates unknown tool IDs, npm package names, and version selectors before `npm list` or `npm install` runs.
120
150
 
121
- Lifecycle commands print the resolved manifest, managed root, changed component count, skipped entries, and log file path when a log is generated.
151
+ Use `--registry-mirror <url>` when automation needs to override the manifest registry for a single run. Precedence is CLI override first, manifest `registryMirror` second, and npm's default registry behavior third. If neither the CLI nor manifest provides a mirror, HagiScript does not add `--registry` and existing npm defaults, `.npmrc`, or environment configuration continue to apply.
122
152
 
123
- ## Managed PM2 Services
153
+ Use `--mirror-only` when a run must stay on the configured mirror and must not retry against `https://registry.npmjs.org/`. When omitted, automatic official-registry fallback remains enabled by default for mirror-backed npm inventory and install commands.
124
154
 
125
- Hagiscript manages runtime-scoped PM2 services for:
155
+ For simple product-managed requests, optional CLI selections can be provided directly without writing a manifest:
126
156
 
127
- - `omniroute`
128
- - `code-server`
157
+ ```bash
158
+ hagiscript npm-sync --selected-agent-cli codex
159
+ hagiscript npm-sync --selected-agent-cli codex --custom-agent-cli @scope/agent-cli@^1.0.0
160
+ ```
129
161
 
130
- Supported actions:
162
+ Example manifest for openspec and skills tooling:
163
+
164
+ ```json
165
+ {
166
+ "packages": {
167
+ "@openspec/cli": {
168
+ "version": "^1.0.0"
169
+ },
170
+ "@hagicode/skills": {
171
+ "version": ">=0.5.0 <1.0.0",
172
+ "target": "0.5.4"
173
+ }
174
+ }
175
+ }
176
+ ```
131
177
 
132
- - `start`
133
- - `stop`
134
- - `status`
178
+ During execution, Hagiscript validates the manifest and runtime before any npm install command runs, lists global packages with `/opt/hagiscript/node/bin/npm list -g --depth=0 --json`, plans no-op, install, upgrade, downgrade, or sync actions, and then runs `npm install -g <package>@<selector>` only for packages that need changes. With `--force`, packages that already satisfy the requested range are replanned from `noop` to `sync`, so the same selector is installed again to re-sync the existing target.
135
179
 
136
- Examples:
180
+ Example output:
137
181
 
138
- ```bash
139
- hagiscript pm2 omniroute status
140
- hagiscript pm2 omniroute start
141
- hagiscript pm2 code-server stop
182
+ ```text
183
+ Manifest validated: ./manifest.json (2 packages, mode=packages)
184
+ Registry mirror: https://registry.npmmirror.com/
185
+ Fallback policy: auto
186
+ Runtime validated: /opt/hagiscript/node
187
+ node: /opt/hagiscript/node/bin/node (v22.12.0)
188
+ npm: /opt/hagiscript/node/bin/npm (10.9.0)
189
+ Detected global packages: 4
190
+ Plan: @openspec/cli noop installed=1.0.2 required=^1.0.0 selector=@openspec/cli@^1.0.0
191
+ Skip: @openspec/cli already satisfies range
192
+ Plan: @hagicode/skills upgrade installed=0.4.0 required=>=0.5.0 <1.0.0 selector=@hagicode/skills@0.5.4
193
+ Install: @hagicode/skills using @hagicode/skills@0.5.4
194
+ Synced: @hagicode/skills (upgrade)
195
+ npm-sync complete.
196
+ Runtime: /opt/hagiscript/node
197
+ Manifest: ./manifest.json
198
+ Mode: packages
199
+ Registry mirror: https://registry.npmmirror.com/
200
+ Fallback policy: auto
201
+ Fallback used: no
202
+ Packages: 2
203
+ No-op: 1
204
+ Changed: 1
142
205
  ```
143
206
 
144
- The PM2 flow is runtime-scoped:
207
+ Forced re-sync example:
145
208
 
146
- - PM2 is installed into the managed npm prefix, not the host environment.
147
- - Hagiscript resolves the runtime manifest before every PM2 action.
148
- - PM2 runs with the managed Node runtime and managed PATH ordering.
149
- - `PM2_HOME` is derived from the managed runtime layout, so service state stays inside the runtime data boundary.
209
+ ```text
210
+ $ hagiscript npm-sync --manifest ./manifest.json --force
211
+ Plan: @openspec/cli sync installed=1.0.2 required=^1.0.0 selector=@openspec/cli@^1.0.0
212
+ Install: @openspec/cli using @openspec/cli@^1.0.0
213
+ Synced: @openspec/cli (sync)
214
+ ```
150
215
 
151
- This means maintenance scripts should call `hagiscript pm2 ...` instead of a system `pm2` binary.
216
+ When fallback is triggered, HagiScript logs `Fallback used: ...` during execution and records `Fallback detail: ...` in the final summary so CI or desktop automation can see which mirror failed, which official registry retry was used, and whether that retry succeeded.
152
217
 
153
- ## Runtime Environment Contract
218
+ ### Runtime Package Management
154
219
 
155
- Runtime lifecycle scripts and managed services receive a stable environment contract:
220
+ `hagiscript runtime` adds a manifest-driven package manager for the broader `hagicode-runtime` contract. By default it loads `runtime/manifest.yaml` from the installed package, resolves the managed runtime root to `~/.hagicode/runtime`, then splits that managed runtime into a program home and a mutable runtime-data home unless `--runtime-root <path>` overrides the base location for a specific install, deployment mode, or automation run.
156
221
 
157
- - `HAGICODE_RUNTIME_HOME` - runtime program home
158
- - `HAGICODE_RUNTIME_DATA_HOME` - writable runtime data home for the current component
159
- - `PM2_HOME` - PM2 state directory for the current managed service
160
- - `PATH` - rebuilt so managed Node, managed npm, and managed wrappers come first
222
+ ```bash
223
+ hagiscript runtime install
224
+ hagiscript runtime install --components node,npm-packages --dry-run
225
+ hagiscript runtime update --runtime-root /opt/hagicode/runtime --check-only
226
+ hagiscript runtime remove --components code-server --purge
227
+ hagiscript runtime state --json
228
+ ```
161
229
 
162
- This contract is what keeps installs, updates, wrappers, and PM2-managed services aligned to the same runtime root.
230
+ The packaged runtime manifest aligns its default component boundaries with HagiCode Desktop:
163
231
 
164
- ## Manifest Customization
232
+ - Node is governed as a Desktop-aligned Node 22 toolchain component.
233
+ - `.NET` is modeled as a Desktop-aligned 10.0 runtime component.
234
+ - Mutable npm packages, including the managed `pm2` binary, are installed into a managed prefix under the runtime program home instead of the immutable Node payload or host-global npm locations.
235
+ - `code-server` and `omniroute` stay grouped as vendored bundled-runtime components rather than npm-managed packages.
165
236
 
166
- `runtime/manifest.yaml` controls the runtime shape. Common override points:
237
+ The runtime layout is explicit and stable for downstream consumers:
167
238
 
168
- - `paths.runtimeRoot`
169
- - `paths.runtimeHome`
170
- - `paths.runtimeDataRoot`
171
- - `paths.componentDataRoot`
172
- - `paths.defaultPm2Home`
173
- - component `runtimeDataDir`
174
- - service `pm2.appName`
175
- - service `pm2.cwd`
176
- - service `pm2.script`
177
- - service `pm2.args`
178
- - service `pm2.env`
179
- - service `pm2.pm2Home`
239
+ ```text
240
+ <runtime-root>/
241
+ program/
242
+ bin/
243
+ npm/
244
+ components/
245
+ runtime-data/
246
+ config/
247
+ logs/
248
+ data/
249
+ components/
250
+ state.json
251
+ ```
252
+
253
+ `hagiscript runtime state --json` is the canonical contract for install, update, remove, and downstream inspection. It reports the resolved runtime home, runtime data root, per-component runtime data homes, and derived PM2 homes so Desktop, local bootstrap flows, or automation does not need to probe files directly.
180
254
 
181
- For deployment-specific behavior, keep the packaged manifest as the baseline and pass `--from-manifest` with an override manifest rather than mutating the installed package in place.
255
+ Runtime lifecycle scripts and managed PM2 services receive the same public runtime environment contract:
182
256
 
183
- ## Related Runtime Tooling
257
+ - `HAGICODE_RUNTIME_HOME` points to the runtime program home.
258
+ - `HAGICODE_RUNTIME_DATA_HOME` points to the current component's writable runtime data home.
259
+ - `PM2_HOME` defaults to a child directory beneath `HAGICODE_RUNTIME_DATA_HOME`.
260
+ - `PATH` is rebuilt so the managed Node runtime, managed npm prefix, and managed wrappers take precedence over the ambient shell environment.
184
261
 
185
- ### Managed Node Runtime
262
+ ### Managed PM2 Service Commands
186
263
 
187
- Install a standalone managed Node.js runtime:
264
+ `hagiscript pm2` manages the runtime-scoped `omniroute` and `code-server` services through the PM2 binary installed by `hagiscript runtime install`.
188
265
 
189
266
  ```bash
190
- hagiscript install-node --target /opt/hagiscript/node
191
- hagiscript install-node --target /opt/hagiscript/node22 --version 22
267
+ hagiscript pm2 omniroute start
268
+ hagiscript pm2 omniroute status
269
+ hagiscript pm2 code-server stop
192
270
  ```
193
271
 
194
- Validate an existing managed Node.js runtime:
272
+ Each PM2 command resolves the runtime manifest first, loads the canonical runtime homes, derives a component-scoped `PM2_HOME`, and executes the managed PM2 binary from `<runtime-home>/npm`. It does not rely on a system PM2 or a system Node on the ambient shell `PATH`.
195
273
 
196
- ```bash
197
- hagiscript check-node --target /opt/hagiscript/node
198
- ```
274
+ The packaged `runtime/manifest.yaml` can override:
199
275
 
200
- ### Managed npm Package Sync
276
+ - runtime-level `paths.runtimeHome`, `paths.runtimeDataRoot`, `paths.componentDataRoot`, and `paths.defaultPm2Home`
277
+ - component-level `runtimeDataDir`
278
+ - service-level `pm2.appName`, `pm2.cwd`, `pm2.script`, `pm2.args`, `pm2.env`, and `pm2.pm2Home`
201
279
 
202
- Sync npm global packages into a managed runtime instead of the host environment:
280
+ The package also ships a thin `hagicode-runtime` wrapper binary that delegates to `hagiscript runtime ...` for automation that prefers a runtime-oriented entrypoint:
203
281
 
204
282
  ```bash
205
- hagiscript npm-sync --manifest ./manifest.json
206
- hagiscript npm-sync --runtime /opt/hagiscript/node --manifest ./manifest.json
283
+ hagicode-runtime install --runtime-root /srv/hagicode/runtime
207
284
  ```
208
285
 
209
- This is mainly useful when runtime maintenance also needs a controlled agent CLI or package inventory inside the managed runtime.
286
+ Use the library API from ESM consumers:
210
287
 
211
- ## Development
288
+ ```ts
289
+ import { createRuntimeInfo, getPackageMetadata } from "@hagicode/hagiscript";
212
290
 
213
- Run from `repos/hagiscript/`:
291
+ console.log(getPackageMetadata());
292
+ console.log(createRuntimeInfo());
293
+ ```
294
+
295
+ ## Development Commands
296
+
297
+ Run all commands from `repos/hagiscript/`:
214
298
 
215
299
  ```bash
216
300
  npm install
301
+ npm run lint
302
+ npm run format:check
217
303
  npm test
218
304
  npm run build
219
305
  npm run pack:check
220
306
  ```
221
307
 
222
- Useful runtime-focused checks:
308
+ Additional commands:
309
+
310
+ ```bash
311
+ npm run clean
312
+ npm run format
313
+ npm run test:watch
314
+ npm run publish:prepare-dev-version
315
+ npm run publish:verify-release -- v0.1.0
316
+ ```
317
+
318
+ ## Build Outputs
319
+
320
+ `npm run build` compiles TypeScript with strict NodeNext settings into `dist/`. Expected entry points include:
321
+
322
+ - `dist/index.js`
323
+ - `dist/index.d.ts`
324
+ - `dist/index.js.map`
325
+ - `dist/cli.js`
326
+ - `dist/cli.d.ts`
327
+ - `dist/cli.js.map`
328
+
329
+ The package `exports` field points consumers to `dist/index.js` and `dist/index.d.ts`. The published package name is `@hagicode/hagiscript`, and the `bin.hagiscript` entry points to `dist/cli.js`.
330
+
331
+ ## Package Verification
332
+
333
+ `npm run pack:check` runs a dry-run package inspection and fails if required runtime files are missing or source-only files are accidentally included. The published package should contain generated `dist` files and documentation, not raw tests, scripts, coverage, or temporary files.
334
+
335
+ ## Release Automation
336
+
337
+ GitHub Actions provide three automation paths:
338
+
339
+ - `ci.yml` installs dependencies with `npm ci`, then runs tests, build, and package verification.
340
+ - `npm-publish.yml` resolves a unique prerelease version from `main`, stamps both `package.json` and `package-lock.json` with `npm version --no-git-tag-version`, then publishes to the `dev` dist-tag.
341
+ - `npm-publish.yml` also publishes stable GitHub releases tagged as `vX.Y.Z` to the `latest` dist-tag after validating the tag format, rejecting tags older than the repository base version, and stamping the stable version the same way.
342
+ - `release-drafter.yml` keeps a categorized release draft using `.github/release-drafter.yml`.
343
+
344
+ Before the first publish, make sure the npm organization or user scope `hagicode` exists on npm and grant publish access for `@hagicode/hagiscript`. For GitHub Actions releases, configure npm trusted publishing with package `@hagicode/hagiscript`, owner `HagiCode-org`, repository `hagiscript`, and workflow filename `npm-publish.yml`. Do not enter the full workflow path as the filename; leave the npm environment field empty unless the workflow job explicitly declares an environment. If the scope is missing or the workflow identity cannot create packages under it, npm returns `E404 Not Found` during the final `PUT https://registry.npmjs.org/@hagicode%2fhagiscript` publish request.
345
+
346
+ Run the publish prerequisite check before retrying a failed release:
223
347
 
224
348
  ```bash
225
- npm run integration:runtime-management
226
- npm run integration:installed-runtime
349
+ npm run publish:check-prereqs
227
350
  ```
228
351
 
352
+ For local manual releases, run plain `npm publish` after logging in with an npm account that can publish under `@hagicode`.
353
+
229
354
  ## License
230
355
 
231
356
  MIT. See [LICENSE](./LICENSE).
package/README_cn.md ADDED
@@ -0,0 +1,321 @@
1
+ # Hagiscript
2
+
3
+ `@hagicode/hagiscript` 是 Hagiscript 语言工具链的作用域 npm 包基础工程。本次初始化只提供最小运行能力:版本元数据、基础运行时信息 API,以及一个可构建、可测试、可打包、可发布的 CLI 占位入口。
4
+
5
+ ## 安装假设
6
+
7
+ - 需要 Node.js 20 或更高版本。
8
+ - 该独立仓库使用 npm 作为包管理器。
9
+ - npm 包名为 `@hagicode/hagiscript`。
10
+ - GitHub Actions 发布使用 `npm publish --provenance`。本地手动发布时,应直接使用普通 `npm publish`,除非当前环境本身就是受支持的 trusted publishing 环境。
11
+
12
+ ## 使用方式
13
+
14
+ 先从 npm 安装该包:
15
+
16
+ ```bash
17
+ npm install @hagicode/hagiscript
18
+ ```
19
+
20
+ 安装后的 CLI 命令仍然是 `hagiscript`。
21
+
22
+ 开发时运行 CLI:
23
+
24
+ ```bash
25
+ npm run dev -- --help
26
+ npm run dev -- info
27
+ npm run dev -- install-node --target .tmp/node-runtime
28
+ npm run dev -- check-node --target .tmp/node-runtime
29
+ npm run dev -- npm-sync --runtime .tmp/node-runtime --manifest manifest.json
30
+ ```
31
+
32
+ 构建后运行编译产物:
33
+
34
+ ```bash
35
+ npm run build
36
+ node dist/cli.js --version
37
+ node dist/cli.js info
38
+ node dist/cli.js install-node --target .tmp/node-runtime
39
+ node dist/cli.js check-node --target .tmp/node-runtime
40
+ node dist/cli.js npm-sync --runtime .tmp/node-runtime --manifest manifest.json
41
+ ```
42
+
43
+ ### 托管 Node.js 运行时命令
44
+
45
+ `install-node` 会从 `https://nodejs.org/dist` 下载官方 Node.js 归档包,解压到目标目录,并在成功前验证 `node` 与 `npm` 都可执行。
46
+
47
+ ```bash
48
+ hagiscript install-node --target /opt/hagiscript/node
49
+ hagiscript install-node --target /opt/hagiscript/node20 --version 20
50
+ hagiscript install-node --target /opt/hagiscript/lts --version lts
51
+ ```
52
+
53
+ 省略 `--version` 时,Hagiscript 默认安装最新可用的 Node.js 22 版本。支持的选择器包括 `lts`、`latest`、`current`、类似 `22` 的主版本号、类似 `22.12.0` 的精确版本,以及类似 `v22.12.0` 的带 `v` 精确版本。
54
+
55
+ 目标路径必须不存在或为空目录。Hagiscript 会拒绝安装到非空目标目录,也不会删除已有用户文件。安装期间,临时 staging 文件会创建在目标目录旁边,并在成功或失败后清理。
56
+
57
+ 成功输出示例:
58
+
59
+ ```text
60
+ Installing Node.js 22 into /opt/hagiscript/node
61
+ Download progress: 100%
62
+ Node.js runtime installed successfully.
63
+ Target: /opt/hagiscript/node
64
+ Node.js: v22.12.0
65
+ npm: 10.9.0
66
+ node: /opt/hagiscript/node/bin/node
67
+ npm: /opt/hagiscript/node/bin/npm
68
+ ```
69
+
70
+ `check-node` 会验证已有运行时目录;只有 `node --version` 和 `npm --version` 都成功时才以退出码 `0` 结束。
71
+
72
+ ```bash
73
+ hagiscript check-node --target /opt/hagiscript/node
74
+ ```
75
+
76
+ 有效运行时输出示例:
77
+
78
+ ```text
79
+ Node.js runtime is valid.
80
+ Target: /opt/hagiscript/node
81
+ Node.js: v22.12.0
82
+ npm: 10.9.0
83
+ node: /opt/hagiscript/node/bin/node
84
+ npm: /opt/hagiscript/node/bin/npm
85
+ ```
86
+
87
+ 无效运行时会以非零退出码结束,并输出失败原因:
88
+
89
+ ```text
90
+ Node.js runtime is invalid.
91
+ Target: /opt/hagiscript/node
92
+ Reason: missing executable
93
+ ```
94
+
95
+ ### npm 全局包同步
96
+
97
+ `npm-sync` 会根据 JSON manifest,把 HagiScript 托管 Node.js 运行时中的 npm 全局包版本同步到约束范围内。默认情况下,它会验证或安装 `~/.hagiscript/node-runtime`,并使用该运行时内的 `npm`;它不会使用或修改当前 shell `PATH` 中的 npm。已有自动化仍可继续传入 `--runtime` 使用显式运行时目录。
98
+
99
+ ```bash
100
+ hagiscript npm-sync --manifest ./manifest.json
101
+ hagiscript npm-sync --runtime /opt/hagiscript/node --manifest ./manifest.json
102
+ hagiscript npm-sync --manifest ./manifest.json --registry-mirror https://registry.npmmirror.com/
103
+ hagiscript npm-sync --manifest ./manifest.json --registry-mirror https://registry.npmmirror.com/ --mirror-only
104
+ ```
105
+
106
+ 兼容模式 manifest 结构:
107
+
108
+ ```json
109
+ {
110
+ "packages": {
111
+ "<npm-package-name>": {
112
+ "version": "<semver range>",
113
+ "target": "<optional npm install selector>"
114
+ }
115
+ }
116
+ }
117
+ ```
118
+
119
+ 必填的 `version` 字段使用 package.json 风格的 semver 范围,例如 `^1.2.0`、`>=1.0.0 <2.0.0` 或 `1.0.0 || 2.0.0`。可选的 `target` 字段用于指定实际执行 `npm install -g` 时使用的选择器;如果省略,Hagiscript 会安装 `<package>@<version>`。
120
+
121
+ 可选的顶层 `registryMirror` 字段用于指定 npm 检测与安装命令所使用的镜像地址,必须是非空的绝对 `http:` 或 `https:` URL。配置后,Hagiscript 会先对 `npm list -g --depth=0 --json` 和 `npm install -g <package>@<selector>` 追加 `--registry <registryMirror>` 并优先走镜像;如果镜像对应的 npm 命令失败,则会把同一条 inventory 或 install 命令自动重试一次到官方源 `https://registry.npmjs.org/`。这个自动降级只作用于 npm inventory 与包变更命令,不会重试运行时校验、manifest 校验或同步计划计算。
122
+
123
+ 产品托管的工具同步可使用扩展后的 `tools` manifest。必选工具始终会按 `src/runtime/tool-sync-catalog.config.json` 中的内部固定版本纳入同步:OpenSpec skills(`skills@1.5.1`)、OmniRoute(`omniroute@3.6.9`)和 code-server(`code-server@4.117.0`)。可选 agent CLI 同步需要显式启用;如果传入内置 CLI 或自定义 npm 包选择,它们会被加入同步。
124
+
125
+ ```json
126
+ {
127
+ "tools": {
128
+ "optionalAgentCliSyncEnabled": true,
129
+ "selectedOptionalAgentCliIds": ["codex", "claude-code", "fission-openspec", "opencode"],
130
+ "customAgentClis": [
131
+ {
132
+ "packageName": "@scope/agent-cli",
133
+ "version": "^1.0.0"
134
+ }
135
+ ]
136
+ }
137
+ }
138
+ ```
139
+
140
+ 首批内置可选 agent CLI ID 为 `codex`(`@openai/codex@0.125.0`)、`claude-code`(`@anthropic-ai/claude-code@2.1.119`)、`fission-openspec`(`@fission-ai/openspec@1.3.1`)、`qoder`(`@qoder-ai/qodercli@0.1.48`)和 `opencode`(`opencode-ai@1.14.24`)。这些内置包版本固定在 `src/runtime/tool-sync-catalog.config.json` 中。HagiScript 会在执行 `npm list` 或 `npm install` 前校验未知工具 ID、npm 包名和版本选择器。
141
+
142
+ 使用 `--registry-mirror <url>` 可以在单次运行中覆盖 manifest 中的镜像地址,优先级依次为 CLI 覆盖、manifest 的 `registryMirror`、以及 npm 默认注册表行为。如果 CLI 与 manifest 都没有提供镜像,Hagiscript 就不会附加 `--registry`,现有的 npm 默认设置、`.npmrc` 或环境变量行为会保持不变。
143
+
144
+ 如果某次同步必须严格停留在镜像源且不能自动切回官方源,请添加 `--mirror-only`。省略该选项时,只要配置了镜像,Hagiscript 默认就会在镜像失败后自动回退到 `https://registry.npmjs.org/` 一次。
145
+
146
+ 简单的产品托管请求也可以直接通过 CLI 选项传入可选 CLI,而不必先写 manifest:
147
+
148
+ ```bash
149
+ hagiscript npm-sync --selected-agent-cli codex
150
+ hagiscript npm-sync --selected-agent-cli codex --custom-agent-cli @scope/agent-cli@^1.0.0
151
+ ```
152
+
153
+ openspec 和 skills 工具同步示例:
154
+
155
+ ```json
156
+ {
157
+ "packages": {
158
+ "@openspec/cli": {
159
+ "version": "^1.0.0"
160
+ },
161
+ "@hagicode/skills": {
162
+ "version": ">=0.5.0 <1.0.0",
163
+ "target": "0.5.4"
164
+ }
165
+ }
166
+ }
167
+ ```
168
+
169
+ 执行时,Hagiscript 会先验证 manifest 和运行时,再执行任何 npm install 操作;它会用 `/opt/hagiscript/node/bin/npm list -g --depth=0 --json` 检测全局包,生成 no-op、install、upgrade、downgrade 或 sync 计划,然后只对需要变更的包执行 `npm install -g <package>@<selector>`。
170
+
171
+ 输出示例:
172
+
173
+ ```text
174
+ Manifest validated: ./manifest.json (2 packages, mode=packages)
175
+ Registry mirror: https://registry.npmmirror.com/
176
+ Fallback policy: auto
177
+ Runtime validated: /opt/hagiscript/node
178
+ node: /opt/hagiscript/node/bin/node (v22.12.0)
179
+ npm: /opt/hagiscript/node/bin/npm (10.9.0)
180
+ Detected global packages: 4
181
+ Plan: @openspec/cli noop installed=1.0.2 required=^1.0.0 selector=@openspec/cli@^1.0.0
182
+ Skip: @openspec/cli already satisfies range
183
+ Plan: @hagicode/skills upgrade installed=0.4.0 required=>=0.5.0 <1.0.0 selector=@hagicode/skills@0.5.4
184
+ Install: @hagicode/skills using @hagicode/skills@0.5.4
185
+ Synced: @hagicode/skills (upgrade)
186
+ npm-sync complete.
187
+ Runtime: /opt/hagiscript/node
188
+ Manifest: ./manifest.json
189
+ Mode: packages
190
+ Registry mirror: https://registry.npmmirror.com/
191
+ Fallback policy: auto
192
+ Fallback used: no
193
+ Packages: 2
194
+ No-op: 1
195
+ Changed: 1
196
+ ```
197
+
198
+ 如果触发了回退,Hagiscript 会在执行期间输出 `Fallback used: ...`,并在最终摘要中记录 `Fallback detail: ...`,这样 CI 或桌面端自动化就能明确知道哪个镜像失败了、是否切到了官方源,以及官方源重试是否成功。
199
+
200
+ ### Runtime 包管理
201
+
202
+ `hagiscript runtime` 提供了面向 `hagicode-runtime` 的 manifest 驱动包管理能力。默认情况下,它会加载安装包内置的 `runtime/manifest.yaml`,把托管运行时根目录解析为 `~/.hagicode/runtime`,然后在该根目录下拆分出只读程序目录和可写运行时数据目录;如果某次部署或自动化需要独立路径,可通过 `--runtime-root <path>` 覆盖基础位置。
203
+
204
+ ```bash
205
+ hagiscript runtime install
206
+ hagiscript runtime install --components node,npm-packages --dry-run
207
+ hagiscript runtime update --runtime-root /opt/hagicode/runtime --check-only
208
+ hagiscript runtime remove --components code-server --purge
209
+ hagiscript runtime state --json
210
+ ```
211
+
212
+ 默认运行时布局如下:
213
+
214
+ ```text
215
+ <runtime-root>/
216
+ program/
217
+ bin/
218
+ npm/
219
+ components/
220
+ runtime-data/
221
+ config/
222
+ logs/
223
+ data/
224
+ components/
225
+ state.json
226
+ ```
227
+
228
+ `hagiscript runtime state --json` 是安装、更新、删除与下游诊断的标准状态接口。它会输出解析后的运行时程序目录、运行时数据根目录、组件级 `HAGICODE_RUNTIME_DATA_HOME`,以及派生出的 `PM2_HOME`,下游工具不需要再自己探测文件系统。
229
+
230
+ 运行时脚本和 PM2 托管服务会共享同一套公开环境变量约定:
231
+
232
+ - `HAGICODE_RUNTIME_HOME`:运行时程序目录
233
+ - `HAGICODE_RUNTIME_DATA_HOME`:当前组件的可写运行时数据目录
234
+ - `PM2_HOME`:默认位于 `HAGICODE_RUNTIME_DATA_HOME` 下的独立子目录
235
+ - `PATH`:优先注入托管 Node 运行时、托管 npm 前缀和托管 wrapper,再继承当前 shell 的 PATH
236
+
237
+ ### PM2 托管服务命令
238
+
239
+ `hagiscript pm2` 用于管理运行时作用域内的 `omniroute` 和 `code-server` 服务,底层始终调用 `hagiscript runtime install` 安装到托管 npm 前缀中的 PM2。
240
+
241
+ ```bash
242
+ hagiscript pm2 omniroute start
243
+ hagiscript pm2 omniroute status
244
+ hagiscript pm2 code-server stop
245
+ ```
246
+
247
+ 每次 PM2 命令都会先解析运行时 manifest,计算规范化的运行时目录和组件数据目录,再以组件级 `PM2_HOME` 和托管 Node-first PATH 调用 `<runtime-home>/npm` 下的 PM2;它不会依赖系统预装的 PM2 或系统 Node。
248
+
249
+ `runtime/manifest.yaml` 现在支持以下覆盖项:
250
+
251
+ - 运行时级别:`paths.runtimeHome`、`paths.runtimeDataRoot`、`paths.componentDataRoot`、`paths.defaultPm2Home`
252
+ - 组件级别:`runtimeDataDir`
253
+ - 服务级别:`pm2.appName`、`pm2.cwd`、`pm2.script`、`pm2.args`、`pm2.env`、`pm2.pm2Home`
254
+
255
+ 在 ESM 项目中使用库 API:
256
+
257
+ ```ts
258
+ import { createRuntimeInfo, getPackageMetadata } from "@hagicode/hagiscript";
259
+
260
+ console.log(getPackageMetadata());
261
+ console.log(createRuntimeInfo());
262
+ ```
263
+
264
+ ## 开发命令
265
+
266
+ 所有命令都应在 `repos/hagiscript/` 下执行:
267
+
268
+ ```bash
269
+ npm install
270
+ npm run lint
271
+ npm run format:check
272
+ npm test
273
+ npm run build
274
+ npm run pack:check
275
+ ```
276
+
277
+ 其他常用命令:
278
+
279
+ ```bash
280
+ npm run clean
281
+ npm run format
282
+ npm run test:watch
283
+ npm run publish:prepare-dev-version
284
+ npm run publish:verify-release -- v0.1.0
285
+ ```
286
+
287
+ ## 构建输出
288
+
289
+ `npm run build` 会使用严格的 NodeNext TypeScript 配置编译到 `dist/`。预期入口文件包括:
290
+
291
+ - `dist/index.js`
292
+ - `dist/index.d.ts`
293
+ - `dist/index.js.map`
294
+ - `dist/cli.js`
295
+ - `dist/cli.d.ts`
296
+ - `dist/cli.js.map`
297
+
298
+ `package.json` 的 `exports` 字段指向 `dist/index.js` 和 `dist/index.d.ts`。发布到 npm 后的包名是 `@hagicode/hagiscript`,`bin.hagiscript` 指向 `dist/cli.js`。
299
+
300
+ ## 包内容校验
301
+
302
+ `npm run pack:check` 会执行 dry-run 打包检查。如果缺少必要运行文件,或错误包含源码测试、脚本、覆盖率、临时目录等只应存在于开发环境的文件,脚本会失败。
303
+
304
+ ## 发布自动化
305
+
306
+ GitHub Actions 提供三类自动化流程:
307
+
308
+ - `ci.yml` 使用 `npm ci` 安装依赖,并执行测试、构建和包内容校验。
309
+ - `npm-publish.yml` 在 `main` 分支解析唯一预发布版本,用 `npm version --no-git-tag-version` 同步 `package.json` 和 `package-lock.json`,再发布到 `dev` dist-tag。
310
+ - `npm-publish.yml` 也会在非草稿、非 prerelease 的 GitHub Release 发布时,校验 `vX.Y.Z` 标签格式,拒绝早于仓库基础版本的标签,并用同样方式写入稳定版本再发布到 `latest` dist-tag。
311
+ - `release-drafter.yml` 通过 `.github/release-drafter.yml` 维护分类清晰的发布草稿。
312
+
313
+ 首次发布前,需要先确保 npm 上已经存在组织或用户 scope `hagicode`,并且 `@hagicode/hagiscript` 已授权当前发布主体。GitHub Actions 发布时,需要在 npm trusted publishing 中配置:package `@hagicode/hagiscript`、owner `HagiCode-org`、repository `hagiscript`、workflow filename `npm-publish.yml`。不要把 workflow filename 填成完整路径;如果 npm 表单有 environment 字段,除非 workflow job 显式声明了 environment,否则保持为空。如果 scope 不存在,或 workflow 身份无权在该 scope 下创建包,npm 会在最后的 `PUT https://registry.npmjs.org/@hagicode%2fhagiscript` 发布请求中返回 `E404 Not Found`。
314
+
315
+ 重试失败的发布前,先运行发布前置检查:
316
+
317
+ ```bash
318
+ npm run publish:check-prereqs
319
+ ```
320
+
321
+ 本地手动发布时,先登录一个有权发布到 `@hagicode` scope 的 npm 账号,再直接执行普通 `npm publish`。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hagicode/hagiscript",
3
- "version": "0.1.6-dev.47.1.59c65fa",
3
+ "version": "0.1.7",
4
4
  "description": "Scoped npm package foundation for Hagiscript language tooling.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/HagiCode-org/hagiscript#readme",
@@ -27,7 +27,8 @@
27
27
  "dist",
28
28
  "bin",
29
29
  "runtime",
30
- "README.md"
30
+ "README.md",
31
+ "README_cn.md"
31
32
  ],
32
33
  "scripts": {
33
34
  "build": "tsc -p tsconfig.json",