@synopackageland/cli 0.15.1 → 0.15.3

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,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.15.3 (2026-10-18)
4
+
5
+ - Pin templates and SDK fixtures/examples to 0.15.2, including UI 0.12.0 scaffolds, concise UI copy/tokens and delegate DTO contract checks.
6
+ - Add the SDK 0.15.2 executor/lifecycle digest entry using Go 1.26.9; retain every earlier entry unchanged. All six digests match 0.15.1, so upgrading from 0.15.1 adds no administrator reapproval requirement. Apps upgrading from 0.15.0 retain the one-time approval introduced in SDK 0.15.1.
7
+ - Include CLI-5 shared OFF_GLOSSARY rules and CLI-6 command failure exit codes from CLI 0.15.2. CLI 0.15.2 was already published with templates 0.15.1; use 0.15.3 for the coordinated SDK/templates release.
8
+
9
+ 繁中摘要:templates/SDK pins 同步 0.15.2,帶入 UI 0.12.0、精簡文案/token 與 DTO 契約檢查;保留 CLI-5 詞彙規則及 CLI-6 正確退出碼。新增 SDK 0.15.2 digest 表項,六個 digest 均與 0.15.1 相同,保留全部舊 pins;從 0.15.1 升級不新增重新核准要求,從 0.15.0 升級仍需完成一次管理員核准。CLI 0.15.2 已先發佈,因此本次協同發版使用 CLI 0.15.3。
10
+
11
+ ## 0.15.2 (2026-10-18)
12
+
13
+ - Preserve command-set process exit codes instead of resetting them to 0 after CLI dispatch. `ctl` failures now reach scripts and CI with their documented exit codes; successful commands still exit 0 and uncaught exceptions exit 1.
14
+ - Add subprocess regression coverage for `ctl` exit codes 0–8, confirmation before writes, and failures from `check`, `build`, `inspect`, `status` and `test`. Document the existing `ctl` exit-code contract and informational discovery/session results.
15
+ - CLI-only patch: templates and SDK fixtures/examples remain pinned to 0.15.1; executor/lifecycle digests are unchanged.
16
+
17
+ 繁中摘要:修正 CLI 在子指令完成後把退出碼覆寫成 0 的問題,讓 `ctl` 失敗正確傳遞至腳本與 CI;成功仍為 0,未捕捉例外仍為 1。新增實際子行程測試,涵蓋 `ctl` 的 0–8 退出碼、寫入確認及其他主要指令的失敗;README 記錄既有退出碼與 discovery/session 資訊結果。此次僅更新 CLI,templates/SDK 維持 0.15.1,executor/lifecycle digest 不變。
18
+
3
19
  ## 0.15.1 (2026-10-18)
4
20
 
5
21
  - Require explicit `DSM_E2E_SSH` for e2e tunnels and use `dsm` as the default saved-profile target; set `DSM_E2E_TARGET` to reuse an earlier target name. Anonymize internal NAS fixtures and documentation.
package/README.md CHANGED
@@ -68,6 +68,19 @@ templates checkout and `SYNOPKGLAND_SDK_DIR` to an SDK checkout; SPKs built with
68
68
  packs the local SDK into its frontend (`npm install --install-links`) without building it: run
69
69
  `npm ci && npm run build` in `$SYNOPKGLAND_SDK_DIR/ts` first, and again after SDK changes.
70
70
 
71
+ To check the CLI's DSM terminology rules against templates without a new templates release:
72
+
73
+ ```sh
74
+ SYNOPKGLAND_TEMPLATES_DIR=/path/to/templates npm run test:glossary
75
+ ```
76
+
77
+ This compares `OFF_GLOSSARY` and the Italian sentence rule, including regex sources and
78
+ flags. It supports declaration-only rules with read-only use in `glossaryProblems`;
79
+ post-declaration mutations, aliases and other unsupported rule uses fail the check instead of
80
+ comparing a partial snapshot. The command also fails on drift or missing source. It needs a checkout because templates
81
+ 0.15.1 does not publish `scripts/test/i18n.test.mjs`. The npm gate runs this check when
82
+ `SYNOPKGLAND_TEMPLATES_DIR` is set; otherwise it explicitly reports that the drift check was skipped.
83
+
71
84
  ## Capabilities
72
85
 
73
86
  Add them with `init --with …` or later with `synopkgland add <capability…>`.
@@ -260,6 +273,37 @@ commands and their schemas. Run the listed alias/command with typed flags,
260
273
  `--help` and `--dry-run`; writes require `--yes`. There is no mutable current
261
274
  context. Use `--host a,b` or `--all-hosts` for bounded parallel operations.
262
275
 
276
+ `ctl` preserves these process exit codes, including with `--json`:
277
+
278
+ | Exit code | Meaning and examples |
279
+ | --- | --- |
280
+ | 0 | Command completed successfully (including help and `--dry-run`). |
281
+ | 1 | Unexpected internal error (`CTL_INTERNAL`), or an uncaught CLI exception. |
282
+ | 2 | Authentication/session failure: `CTL_NOT_AUTHENTICATED`, `CTL_AUTH_FAILED`, `CTL_CREDENTIAL_MISMATCH`, or unavailable OS credential storage. |
283
+ | 3 | Invalid parameters, schema validation or unknown names: `CTL_PARAMS_INVALID`, `CTL_ARGUMENT_INVALID`, `CTL_APP_UNKNOWN`, `CTL_COMMAND_UNKNOWN`. |
284
+ | 4 | Permission refusal that fails the command: `CTL_PERMISSION_DENIED`, `CTL_INVENTORY_DENIED`. |
285
+ | 5 | App/contract failure that fails the command: `CTL_APP_ERROR`, `CTL_RESPONSE_INVALID`, `CTL_JOB_FAILED`. |
286
+ | 6 | Network/HTTP failure or uncertain completion: `CTL_NETWORK`, `CTL_HTTP_ERROR`, `CTL_JOB_TIMEOUT`, `CTL_LOGOUT_FAILED`. |
287
+ | 7 | Confirmation required (`CTL_CONFIRM_REQUIRED`): a write/destructive command or host removal without confirmation; no business operation runs. |
288
+ | 8 | A multi-host command has at least one failed host (including when all hosts fail); inspect each host's error. |
289
+
290
+ For example, `synopkgland ctl studio drafts create --host nas --json` without
291
+ `--yes` returns `ok:false` with `CTL_CONFIRM_REQUIRED` and exits 7 once discovery
292
+ and parameter validation succeed. Missing sessions fail earlier with exit 2.
293
+ Discovery catches per-App description errors and excludes those Apps from its
294
+ results. For example, a changed pinned description (`CTL_DESCRIPTION_CHANGED`)
295
+ or an invalid descriptor (`CTL_DESCRIPTOR_INVALID`) appears in
296
+ `ctl list --host nas --refresh --json` under `data.diagnostics`; the listing still
297
+ returns `ok:true` and exits 0, even if no Apps remain. These diagnostic codes do
298
+ not become process exit codes 4 or 5. Attempting to execute an excluded App with
299
+ `--refresh` instead returns `ok:false`, `CTL_APP_UNKNOWN` and exit 3 because the
300
+ App is absent from discovery results; no business operation runs.
301
+
302
+ `ctl host list/show` can also succeed while reporting `authenticated:false` and
303
+ exit 0. Check discovery `apps`/`diagnostics` and session fields as well as the exit
304
+ code when deciding whether an App is ready.
305
+ After a network or job timeout, query the App's state before retrying a write.
306
+
263
307
  Read `synopkgland skill show ctl` for the AI workflow, batch discovery approval,
264
308
  cache refresh, host removal/revocation and explicit `ctl.commands` authoring.
265
309
  API descriptions are private SPK files named `synopkgland-api.json`, served
package/dist/bin.js CHANGED
@@ -3,9 +3,8 @@ import { loadDotEnv } from "./load-env.js";
3
3
  import { runCli } from "./cli.js";
4
4
  loadDotEnv();
5
5
  // Package deployment is explicit; this CLI does not publish releases.
6
- runCli(process.argv).then(() => 0).then((status) => {
7
- process.exitCode = status;
8
- }).catch((error) => {
6
+ // Successful completion leaves Node's default 0 or the command's exitCode intact.
7
+ runCli(process.argv).catch((error) => {
9
8
  console.error(error instanceof Error ? error.message : String(error));
10
9
  process.exit(1);
11
10
  });
package/dist/cli.d.ts CHANGED
@@ -1 +1,2 @@
1
+ /** Resolves after dispatch; commands may set process.exitCode. Rejections are failures. */
1
2
  export declare function runCli(argv: string[]): Promise<void>;
package/dist/cli.js CHANGED
@@ -275,6 +275,7 @@ async function containerBuild(project, arches, options) {
275
275
  return commitOutputs(options.outDir ? resolve(options.outDir) : project.root, (stage) => forEachArch(arches ?? CONTAINER_ARCH_FAMILIES, jobs, async (arch) => (await build(arch, join(stage, `${packageId}-${arch}.spk`)))
276
276
  .outputPath));
277
277
  }
278
+ /** Resolves after dispatch; commands may set process.exitCode. Rejections are failures. */
278
279
  export async function runCli(argv) {
279
280
  if (argv[2] === "ctl") {
280
281
  const { runCtl } = await import("./ctl/cli.js");
@@ -20,5 +20,16 @@
20
20
  "armv7": "cafc97c89f5645c14a8cf31d6d9f258394ed6f2d086478a7aebd04d57c274b4e"
21
21
  },
22
22
  "goToolchain": "go1.26.9"
23
+ },
24
+ "0.15.2": {
25
+ "x86_64": "4f47fb43f6e60dbad064afb0bbec96dd009fa046670e2c4b590b128a855cb404",
26
+ "aarch64": "c903b09ad657a838f0c62b6688e65e9094572b22b969770fca92fcc3640a5364",
27
+ "armv7": "8178d90de7ea720530bb9496e50ed118086b0e57382d84675aadc68f482d219f",
28
+ "lifecycle": {
29
+ "x86_64": "d65500c4f04713a32b45d360059281391acfa5e00ee24895fdd2de7b82735372",
30
+ "aarch64": "94f6cd119186ff482b8aea56541dd1f9d53c147566bc1efdca6f5a1c86198331",
31
+ "armv7": "cafc97c89f5645c14a8cf31d6d9f258394ed6f2d086478a7aebd04d57c274b4e"
32
+ },
33
+ "goToolchain": "go1.26.9"
23
34
  }
24
35
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synopackageland/cli",
3
- "version": "0.15.1",
3
+ "version": "0.15.3",
4
4
  "description": "Syno Package Land Developer Kit CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -19,6 +19,7 @@
19
19
  "scripts": {
20
20
  "build": "rm -rf dist && tsc",
21
21
  "test": "npm run build && node --import tsx --test test/*.test.ts test/ctl/*.test.ts",
22
+ "test:glossary": "node --test scripts/test/glossary-drift.test.mjs",
22
23
  "test:scripts": "node --test scripts/test/gate.test.mjs scripts/test/release.test.mjs scripts/test/pack-docker.test.mjs scripts/test/npm-pack.test.mjs scripts/test/executor-bump.test.mjs scripts/test/smoke-exports.test.mjs scripts/test/executor-digests.test.mjs scripts/test/parallel.test.mjs scripts/test/scaffold-matrix.test.mjs scripts/test/frontend-deps.test.mjs scripts/test/docker-gate.test.mjs scripts/test/gate-plan.test.mjs scripts/test/gates.test.mjs",
23
24
  "gates": "bash scripts/ci/gates.sh",
24
25
  "gates:fast": "bash scripts/ci/gates.sh --fast",
@@ -26,7 +27,7 @@
26
27
  },
27
28
  "dependencies": {
28
29
  "@napi-rs/keyring": "^2.1.1",
29
- "@synopackageland/templates": "0.15.1",
30
+ "@synopackageland/templates": "0.15.2",
30
31
  "ajv": "^8.17.1",
31
32
  "commander": "^13.1.0",
32
33
  "json-canonicalize": "^3.0.1",
@@ -23,7 +23,7 @@ compose:
23
23
  network: {egress: isolated}
24
24
  # Private package binds are rejected by DSM build; keep compatible upstream named volumes.
25
25
  identity_gateway:
26
- sdk: 0.15.1
26
+ sdk: 0.15.2
27
27
  mode: none
28
28
  access: dsm-users
29
29
  listen: {http: 28000}
@@ -151,7 +151,7 @@ declared availability readiness, LAN isolation/egress, protected grant lifecycle
151
151
  ACLs, two-user visibility and clean install/upgrade/reboot/stop/uninstall before
152
152
  calling the package supported on a NAS. No NAS is accessed by the build gate.
153
153
 
154
- The unified Compose contract requires SDK, CLI and templates 0.15.1. Use the published, matching versions together; the legacy packaging route and bridge publish mode are removed.
154
+ The unified Compose contract uses SDK/templates 0.15.2 with CLI 0.15.3. Use the published, matching versions together; the legacy packaging route and bridge publish mode are removed.
155
155
 
156
156
  Primary override files, and each included override set, must share a directory. Cross-directory override bases are rejected before loader I/O. Included implicit .env files are confined, inventoried and preserved; symlinks are rejected.
157
157
 
@@ -40,8 +40,8 @@ rootOps 與 delegate 已共用管理員 PasswordConfirm 核准的 protected exec
40
40
  backend 寫 `runtime: python|node|rust`(`runtime: go` 等同 `kind: go`)。CGI 是 SDK 的 Go runtime(`bridge/cmd/runtime`),它驗證 DSM session、entry 與 `permissions.json` 後,以套件帳號(不是 root)每個請求啟動一次 App。App 放在 ui 以外的目錄,打包成 `target/app/`,build 寫入 `bridge.json`(spec/bridge/v1)並把它與 `permissions.json` 的 sha256 編進 runtime。
41
41
 
42
42
  ```yaml
43
- backend: {runtime: python, dir: app, entry: main.py, sdk: 0.15.1}
44
- backend: {runtime: node, dir: app, entry: main.mjs, sdk: 0.15.1, node: {package: Node.js_v20}}
43
+ backend: {runtime: python, dir: app, entry: main.py, sdk: 0.15.2}
44
+ backend: {runtime: node, dir: app, entry: main.mjs, sdk: 0.15.2, node: {package: Node.js_v20}}
45
45
  backend: {runtime: rust, dir: app, entry: hello, methods: [hello.greet]}
46
46
  ```
47
47