@ykdz/template 0.0.38 → 0.0.40

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 (220) hide show
  1. package/dist/application.d.ts +1 -52
  2. package/dist/application.js +0 -81
  3. package/dist/cli.js +14 -28
  4. package/dist/input-schemas.d.ts +30 -0
  5. package/dist/input-schemas.js +75 -0
  6. package/dist/main.d.ts +3 -14
  7. package/dist/main.js +496 -378
  8. package/dist/result-schemas.d.ts +222 -0
  9. package/dist/result-schemas.js +74 -0
  10. package/dist/standard-schema.d.ts +3 -0
  11. package/dist/standard-schema.js +29 -0
  12. package/node_modules/@standard-schema/spec/LICENSE +21 -0
  13. package/node_modules/@standard-schema/spec/README.md +198 -0
  14. package/node_modules/@standard-schema/spec/dist/index.cjs +18 -0
  15. package/node_modules/@standard-schema/spec/dist/index.d.cts +119 -0
  16. package/node_modules/@standard-schema/spec/dist/index.d.ts +119 -0
  17. package/node_modules/@standard-schema/spec/dist/index.js +0 -0
  18. package/node_modules/@standard-schema/spec/package.json +52 -0
  19. package/node_modules/@types/node/LICENSE +21 -0
  20. package/node_modules/@types/node/README.md +15 -0
  21. package/node_modules/@types/node/assert/strict.d.ts +111 -0
  22. package/node_modules/@types/node/assert.d.ts +1115 -0
  23. package/node_modules/@types/node/async_hooks.d.ts +619 -0
  24. package/node_modules/@types/node/buffer.buffer.d.ts +477 -0
  25. package/node_modules/@types/node/buffer.d.ts +1941 -0
  26. package/node_modules/@types/node/child_process.d.ts +1480 -0
  27. package/node_modules/@types/node/cluster.d.ts +578 -0
  28. package/node_modules/@types/node/compatibility/iterators.d.ts +21 -0
  29. package/node_modules/@types/node/console.d.ts +453 -0
  30. package/node_modules/@types/node/constants.d.ts +21 -0
  31. package/node_modules/@types/node/crypto.d.ts +5484 -0
  32. package/node_modules/@types/node/dgram.d.ts +715 -0
  33. package/node_modules/@types/node/diagnostics_channel.d.ts +576 -0
  34. package/node_modules/@types/node/dns/promises.d.ts +503 -0
  35. package/node_modules/@types/node/dns.d.ts +923 -0
  36. package/node_modules/@types/node/domain.d.ts +166 -0
  37. package/node_modules/@types/node/events.d.ts +967 -0
  38. package/node_modules/@types/node/fs/promises.d.ts +1354 -0
  39. package/node_modules/@types/node/fs.d.ts +4777 -0
  40. package/node_modules/@types/node/globals.d.ts +170 -0
  41. package/node_modules/@types/node/globals.typedarray.d.ts +41 -0
  42. package/node_modules/@types/node/http.d.ts +2246 -0
  43. package/node_modules/@types/node/http2.d.ts +2882 -0
  44. package/node_modules/@types/node/https.d.ts +585 -0
  45. package/node_modules/@types/node/index.d.ts +101 -0
  46. package/node_modules/@types/node/inspector.d.ts +323 -0
  47. package/node_modules/@types/node/inspector.generated.d.ts +4406 -0
  48. package/node_modules/@types/node/module.d.ts +844 -0
  49. package/node_modules/@types/node/net.d.ts +1197 -0
  50. package/node_modules/@types/node/os.d.ts +507 -0
  51. package/node_modules/@types/node/package.json +140 -0
  52. package/node_modules/@types/node/path.d.ts +200 -0
  53. package/node_modules/@types/node/perf_hooks.d.ts +1054 -0
  54. package/node_modules/@types/node/process.d.ts +2101 -0
  55. package/node_modules/@types/node/punycode.d.ts +117 -0
  56. package/node_modules/@types/node/querystring.d.ts +152 -0
  57. package/node_modules/@types/node/readline/promises.d.ts +161 -0
  58. package/node_modules/@types/node/readline.d.ts +600 -0
  59. package/node_modules/@types/node/repl.d.ts +438 -0
  60. package/node_modules/@types/node/sea.d.ts +162 -0
  61. package/node_modules/@types/node/sqlite.d.ts +1182 -0
  62. package/node_modules/@types/node/stream/consumers.d.ts +45 -0
  63. package/node_modules/@types/node/stream/promises.d.ts +90 -0
  64. package/node_modules/@types/node/stream/web.d.ts +596 -0
  65. package/node_modules/@types/node/stream.d.ts +1707 -0
  66. package/node_modules/@types/node/string_decoder.d.ts +67 -0
  67. package/node_modules/@types/node/test.d.ts +2656 -0
  68. package/node_modules/@types/node/timers/promises.d.ts +108 -0
  69. package/node_modules/@types/node/timers.d.ts +285 -0
  70. package/node_modules/@types/node/tls.d.ts +1314 -0
  71. package/node_modules/@types/node/trace_events.d.ts +197 -0
  72. package/node_modules/@types/node/ts5.6/buffer.buffer.d.ts +473 -0
  73. package/node_modules/@types/node/ts5.6/compatibility/float16array.d.ts +71 -0
  74. package/node_modules/@types/node/ts5.6/globals.typedarray.d.ts +36 -0
  75. package/node_modules/@types/node/ts5.6/index.d.ts +103 -0
  76. package/node_modules/@types/node/ts5.7/compatibility/float16array.d.ts +72 -0
  77. package/node_modules/@types/node/ts5.7/index.d.ts +103 -0
  78. package/node_modules/@types/node/tty.d.ts +209 -0
  79. package/node_modules/@types/node/url.d.ts +1103 -0
  80. package/node_modules/@types/node/util.d.ts +2376 -0
  81. package/node_modules/@types/node/v8.d.ts +1010 -0
  82. package/node_modules/@types/node/vm.d.ts +1160 -0
  83. package/node_modules/@types/node/wasi.d.ts +202 -0
  84. package/node_modules/@types/node/web-globals/abortcontroller.d.ts +34 -0
  85. package/node_modules/@types/node/web-globals/crypto.d.ts +32 -0
  86. package/node_modules/@types/node/web-globals/domexception.d.ts +68 -0
  87. package/node_modules/@types/node/web-globals/events.d.ts +97 -0
  88. package/node_modules/@types/node/web-globals/fetch.d.ts +62 -0
  89. package/node_modules/@types/node/web-globals/navigator.d.ts +25 -0
  90. package/node_modules/@types/node/web-globals/storage.d.ts +24 -0
  91. package/node_modules/@types/node/web-globals/streams.d.ts +22 -0
  92. package/node_modules/@types/node/worker_threads.d.ts +894 -0
  93. package/node_modules/@types/node/zlib.d.ts +768 -0
  94. package/node_modules/@valibot/to-json-schema/LICENSE.md +9 -0
  95. package/node_modules/@valibot/to-json-schema/README.md +475 -0
  96. package/node_modules/@valibot/to-json-schema/dist/index.cjs +800 -0
  97. package/node_modules/@valibot/to-json-schema/dist/index.d.cts +991 -0
  98. package/node_modules/@valibot/to-json-schema/dist/index.d.mts +991 -0
  99. package/node_modules/@valibot/to-json-schema/dist/index.min.cjs +1 -0
  100. package/node_modules/@valibot/to-json-schema/dist/index.min.mjs +1 -0
  101. package/node_modules/@valibot/to-json-schema/dist/index.mjs +795 -0
  102. package/node_modules/@valibot/to-json-schema/package.json +75 -0
  103. package/node_modules/@ykdz/cli-contract/LICENSE +21 -0
  104. package/node_modules/@ykdz/cli-contract/dist/atomic-variant-compiler.d.ts +17 -0
  105. package/node_modules/@ykdz/cli-contract/dist/atomic-variant-compiler.js +55 -0
  106. package/node_modules/@ykdz/cli-contract/dist/cli-contract.d.ts +1164 -0
  107. package/node_modules/@ykdz/cli-contract/dist/cli-contract.js +1408 -0
  108. package/node_modules/@ykdz/cli-contract/dist/cli-execution.d.ts +54 -0
  109. package/node_modules/@ykdz/cli-contract/dist/cli-execution.js +708 -0
  110. package/node_modules/@ykdz/cli-contract/dist/cli-invocation.d.ts +174 -0
  111. package/node_modules/@ykdz/cli-contract/dist/cli-invocation.js +524 -0
  112. package/node_modules/@ykdz/cli-contract/dist/cli-write-error.d.ts +10 -0
  113. package/node_modules/@ykdz/cli-contract/dist/cli-write-error.js +14 -0
  114. package/node_modules/@ykdz/cli-contract/dist/contract-definition-error.d.ts +260 -0
  115. package/node_modules/@ykdz/cli-contract/dist/contract-definition-error.js +130 -0
  116. package/node_modules/@ykdz/cli-contract/dist/contract-execution-error.d.ts +63 -0
  117. package/node_modules/@ykdz/cli-contract/dist/contract-execution-error.js +17 -0
  118. package/node_modules/@ykdz/cli-contract/dist/contract-schema-compiler.d.ts +6 -0
  119. package/node_modules/@ykdz/cli-contract/dist/contract-schema-compiler.js +532 -0
  120. package/node_modules/@ykdz/cli-contract/dist/contract-schema.d.ts +14 -0
  121. package/node_modules/@ykdz/cli-contract/dist/contract-schema.js +1 -0
  122. package/node_modules/@ykdz/cli-contract/dist/description.d.ts +2 -0
  123. package/node_modules/@ykdz/cli-contract/dist/description.js +13 -0
  124. package/node_modules/@ykdz/cli-contract/dist/index.d.ts +8 -0
  125. package/node_modules/@ykdz/cli-contract/dist/index.js +7 -0
  126. package/node_modules/@ykdz/cli-contract/dist/json-value.d.ts +4 -0
  127. package/node_modules/@ykdz/cli-contract/dist/json-value.js +64 -0
  128. package/node_modules/@ykdz/cli-contract/dist/node.d.ts +21 -0
  129. package/node_modules/@ykdz/cli-contract/dist/node.js +109 -0
  130. package/node_modules/@ykdz/cli-contract/dist/outcome-fact.d.ts +162 -0
  131. package/node_modules/@ykdz/cli-contract/dist/outcome-fact.js +113 -0
  132. package/node_modules/@ykdz/cli-contract/dist/outcome-wire.d.ts +53 -0
  133. package/node_modules/@ykdz/cli-contract/dist/outcome-wire.js +189 -0
  134. package/node_modules/@ykdz/cli-contract/dist/stream-variant-compiler.d.ts +16 -0
  135. package/node_modules/@ykdz/cli-contract/dist/stream-variant-compiler.js +45 -0
  136. package/node_modules/@ykdz/cli-contract/package.json +69 -0
  137. package/node_modules/@ykdz/template-builtin-presets/dist/src/foundation.d.ts +20 -0
  138. package/node_modules/@ykdz/template-builtin-presets/dist/src/foundation.js +5 -0
  139. package/node_modules/@ykdz/template-builtin-presets/dist/src/generation-record.d.ts +19 -0
  140. package/node_modules/@ykdz/template-builtin-presets/dist/src/generation-record.js +1 -1
  141. package/node_modules/@ykdz/template-builtin-presets/dist/src/index.d.ts +2 -1
  142. package/node_modules/@ykdz/template-builtin-presets/dist/src/index.js +2 -1
  143. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-cli/definition.js +9 -5
  144. package/node_modules/@ykdz/template-builtin-presets/package.json +2 -1
  145. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/AGENTS.md.template +3 -3
  146. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/artifact.ts +128 -59
  147. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/handoff.ts +80 -8
  148. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/readiness.ts +7 -3
  149. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/cli.ts +9 -19
  150. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/main.ts +144 -60
  151. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/standard-schema.ts +37 -0
  152. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/e2e/journeys/lookup.journey.ts +71 -0
  153. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/integration/command.test.ts +118 -59
  154. package/node_modules/@ykdz/template-core/dist/pnpm-workspace.yaml +2 -1
  155. package/node_modules/@ykdz/template-core/dist/project-blueprint.d.ts +15 -0
  156. package/node_modules/@ykdz/template-core/dist/project-blueprint.js +1 -1
  157. package/node_modules/undici-types/LICENSE +21 -0
  158. package/node_modules/undici-types/README.md +6 -0
  159. package/node_modules/undici-types/agent.d.ts +32 -0
  160. package/node_modules/undici-types/api.d.ts +43 -0
  161. package/node_modules/undici-types/balanced-pool.d.ts +30 -0
  162. package/node_modules/undici-types/cache-interceptor.d.ts +179 -0
  163. package/node_modules/undici-types/cache.d.ts +36 -0
  164. package/node_modules/undici-types/client-stats.d.ts +15 -0
  165. package/node_modules/undici-types/client.d.ts +123 -0
  166. package/node_modules/undici-types/connector.d.ts +36 -0
  167. package/node_modules/undici-types/content-type.d.ts +21 -0
  168. package/node_modules/undici-types/cookies.d.ts +30 -0
  169. package/node_modules/undici-types/diagnostics-channel.d.ts +74 -0
  170. package/node_modules/undici-types/dispatcher.d.ts +279 -0
  171. package/node_modules/undici-types/env-http-proxy-agent.d.ts +22 -0
  172. package/node_modules/undici-types/errors.d.ts +177 -0
  173. package/node_modules/undici-types/eventsource.d.ts +66 -0
  174. package/node_modules/undici-types/fetch.d.ts +211 -0
  175. package/node_modules/undici-types/formdata.d.ts +108 -0
  176. package/node_modules/undici-types/global-dispatcher.d.ts +9 -0
  177. package/node_modules/undici-types/global-origin.d.ts +7 -0
  178. package/node_modules/undici-types/h2c-client.d.ts +73 -0
  179. package/node_modules/undici-types/handlers.d.ts +15 -0
  180. package/node_modules/undici-types/header.d.ts +160 -0
  181. package/node_modules/undici-types/index.d.ts +91 -0
  182. package/node_modules/undici-types/interceptors.d.ts +80 -0
  183. package/node_modules/undici-types/mock-agent.d.ts +68 -0
  184. package/node_modules/undici-types/mock-call-history.d.ts +111 -0
  185. package/node_modules/undici-types/mock-client.d.ts +27 -0
  186. package/node_modules/undici-types/mock-errors.d.ts +12 -0
  187. package/node_modules/undici-types/mock-interceptor.d.ts +94 -0
  188. package/node_modules/undici-types/mock-pool.d.ts +27 -0
  189. package/node_modules/undici-types/package.json +55 -0
  190. package/node_modules/undici-types/patch.d.ts +29 -0
  191. package/node_modules/undici-types/pool-stats.d.ts +19 -0
  192. package/node_modules/undici-types/pool.d.ts +41 -0
  193. package/node_modules/undici-types/proxy-agent.d.ts +29 -0
  194. package/node_modules/undici-types/readable.d.ts +68 -0
  195. package/node_modules/undici-types/retry-agent.d.ts +8 -0
  196. package/node_modules/undici-types/retry-handler.d.ts +125 -0
  197. package/node_modules/undici-types/round-robin-pool.d.ts +41 -0
  198. package/node_modules/undici-types/snapshot-agent.d.ts +109 -0
  199. package/node_modules/undici-types/socks5-proxy-agent.d.ts +25 -0
  200. package/node_modules/undici-types/util.d.ts +18 -0
  201. package/node_modules/undici-types/utility.d.ts +7 -0
  202. package/node_modules/undici-types/webidl.d.ts +347 -0
  203. package/node_modules/undici-types/websocket.d.ts +188 -0
  204. package/package.json +5 -3
  205. package/dist/command-result.d.ts +0 -9
  206. package/dist/command-result.js +0 -231
  207. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/e2e/journeys/greet.journey.ts +0 -46
  208. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/unit/greet.test.ts +0 -15
  209. package/node_modules/commander/LICENSE +0 -22
  210. package/node_modules/commander/Readme.md +0 -1172
  211. package/node_modules/commander/index.js +0 -21
  212. package/node_modules/commander/lib/argument.js +0 -147
  213. package/node_modules/commander/lib/command.js +0 -2790
  214. package/node_modules/commander/lib/error.js +0 -36
  215. package/node_modules/commander/lib/help.js +0 -731
  216. package/node_modules/commander/lib/option.js +0 -377
  217. package/node_modules/commander/lib/suggestSimilar.js +0 -99
  218. package/node_modules/commander/package-support.json +0 -19
  219. package/node_modules/commander/package.json +0 -64
  220. package/node_modules/commander/typings/index.d.ts +0 -1113
@@ -0,0 +1,45 @@
1
+ import { compileContractSchema } from "#/contract-schema-compiler";
2
+ import { isSingleLineText } from "#/description";
3
+ import { deepFreeze } from "#/json-value";
4
+ export function compileStreamRecords(command, definitions, issues) {
5
+ const runtime = {};
6
+ const manifest = {};
7
+ const wire = {};
8
+ for (const [variant, definition] of Object.entries(definitions)) {
9
+ if (!/^[a-z][A-Za-z0-9]*$/.test(variant)) {
10
+ issues.push({
11
+ code: "invalidVariantName",
12
+ command,
13
+ location: "record",
14
+ variant,
15
+ });
16
+ }
17
+ if (!isSingleLineText(definition.description)) {
18
+ issues.push({
19
+ code: "invalidDescription",
20
+ command,
21
+ location: "record",
22
+ variant,
23
+ received: typeof definition.description === "string"
24
+ ? definition.description
25
+ : null,
26
+ });
27
+ }
28
+ const schema = compileContractSchema(definition.schema, { command, location: "record", variant }, issues, isSingleLineText(definition.description)
29
+ ? definition.description
30
+ : undefined);
31
+ runtime[variant] = Object.freeze({
32
+ description: definition.description,
33
+ schema: definition.schema,
34
+ ...("text" in definition ? { text: definition.text } : {}),
35
+ });
36
+ if (schema !== undefined) {
37
+ manifest[variant] = deepFreeze({
38
+ description: definition.description,
39
+ ...schema,
40
+ });
41
+ wire[variant] = deepFreeze(schema.outputSchema);
42
+ }
43
+ }
44
+ return deepFreeze({ runtime, manifest, wire });
45
+ }
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@ykdz/cli-contract",
3
+ "version": "0.2.1",
4
+ "description": "Framework-agnostic, executable CLI contracts for Node.js.",
5
+ "keywords": [
6
+ "cli",
7
+ "contract",
8
+ "nodejs",
9
+ "typescript"
10
+ ],
11
+ "homepage": "https://github.com/YKDZ/cli-contract",
12
+ "bugs": {
13
+ "url": "https://github.com/YKDZ/cli-contract/issues"
14
+ },
15
+ "license": "MIT",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/YKDZ/cli-contract.git"
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "type": "module",
24
+ "imports": {
25
+ "#/*": {
26
+ "types": "./dist/*.d.ts",
27
+ "default": "./dist/*.js"
28
+ }
29
+ },
30
+ "exports": {
31
+ ".": {
32
+ "types": "./dist/index.d.ts",
33
+ "default": "./dist/index.js"
34
+ },
35
+ "./node": {
36
+ "types": "./dist/node.d.ts",
37
+ "default": "./dist/node.js"
38
+ }
39
+ },
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "dependencies": {
44
+ "@standard-schema/spec": "^1.1.0",
45
+ "@types/node": "^24.13.4"
46
+ },
47
+ "devDependencies": {
48
+ "@cli-contract/typescript-config": "0.1.0",
49
+ "@valibot/to-json-schema": "^1.7.1",
50
+ "oxfmt": "^0.67.0",
51
+ "oxlint": "^1.82.0",
52
+ "oxlint-tsgolint": "^7.0.2001",
53
+ "typescript-7": "npm:typescript@^7.0.2",
54
+ "valibot": "^1.5.0",
55
+ "zod": "^4.5.4"
56
+ },
57
+ "engines": {
58
+ "node": ">=24"
59
+ },
60
+ "scripts": {
61
+ "build": "tsc -p tsconfig.build.json --pretty false && node ../../scripts/link-example.ts",
62
+ "format:check": "oxfmt --list-different --config ../../oxfmt.config.ts .",
63
+ "format:write": "oxfmt --write --config ../../oxfmt.config.ts .",
64
+ "lint": "oxlint --quiet --format=unix --config ../../oxlint.config.ts --ignore-pattern node_modules .",
65
+ "lint:fix": "oxlint --format=unix --config ../../oxlint.config.ts . --fix",
66
+ "test": "node --test --conditions=source test/*.test.ts",
67
+ "typecheck": "tsc -p tsconfig.json --noEmit --pretty false"
68
+ }
69
+ }
@@ -210,6 +210,26 @@ export declare function planGeneratedRepositoryPackageAddition(options: {
210
210
  readonly packagePath?: string;
211
211
  readonly linkFrom?: readonly string[];
212
212
  }): GeneratedRepositoryPackageAdditionPlan;
213
+ declare function collectPackageAdditionInput(options: {
214
+ readonly preset: string;
215
+ readonly packageLeafName: string;
216
+ readonly packagePath?: string;
217
+ readonly linkFrom?: readonly string[];
218
+ }): {
219
+ readonly status: "input-invalid";
220
+ readonly issues: readonly PackageAdditionInputIssue[];
221
+ } | {
222
+ readonly status: "valid";
223
+ readonly definition: BuiltInPresetDefinition;
224
+ readonly linkFrom: readonly string[];
225
+ };
226
+ /** 在读取仓库元数据前校验新增包调用参数,供 CLI 输入契约复用。 */
227
+ export declare function validateGeneratedRepositoryPackageAdditionInput(options: Parameters<typeof collectPackageAdditionInput>[0]): {
228
+ readonly status: "valid";
229
+ } | {
230
+ readonly status: "input-invalid";
231
+ readonly issues: readonly PackageAdditionInputIssue[];
232
+ };
213
233
  /**
214
234
  * Command-owned preparation: user input is checked before local metadata or any
215
235
  * Preset default/planner work; all remaining failures are deliberately bounded.
@@ -3363,6 +3363,11 @@ function collectPackageAdditionInput(options) {
3363
3363
  }
3364
3364
  return { status: "valid", definition, linkFrom };
3365
3365
  }
3366
+ /** 在读取仓库元数据前校验新增包调用参数,供 CLI 输入契约复用。 */
3367
+ export function validateGeneratedRepositoryPackageAdditionInput(options) {
3368
+ const result = collectPackageAdditionInput(options);
3369
+ return result.status === "input-invalid" ? result : { status: "valid" };
3370
+ }
3366
3371
  /**
3367
3372
  * Command-owned preparation: user input is checked before local metadata or any
3368
3373
  * Preset default/planner work; all remaining failures are deliberately bounded.
@@ -1,4 +1,5 @@
1
1
  import type { PackageDefinitionId } from "@ykdz/template-core/project-blueprint";
2
+ import * as v from "valibot";
2
3
  export type GeneratedPackagePlanningRecord = {
3
4
  readonly packageDefinitionId: PackageDefinitionId;
4
5
  readonly path: string;
@@ -25,6 +26,24 @@ export type GenerationRecord = {
25
26
  };
26
27
  /** Canonical durable Generation Record contract for a default npm scope. */
27
28
  export declare function isValidDefaultPackageScope(value: string): boolean;
29
+ export declare const generationRecordSchema: v.StrictObjectSchema<{
30
+ readonly schemaVersion: v.LiteralSchema<2, (issue: v.LiteralIssue) => string>;
31
+ readonly repositoryName: v.StringSchema<"repositoryName must be a non-empty string">;
32
+ readonly defaultPackageScope: v.StringSchema<"defaultPackageScope must be a valid npm scope">;
33
+ readonly preset: v.StringSchema<"preset must be a non-empty string">;
34
+ readonly templateVersion: v.LiteralSchema<"0.0.0", "templateVersion must be 0.0.0">;
35
+ readonly toolchain: v.StrictObjectSchema<{
36
+ readonly nodeLtsMajor: v.StringSchema<"toolchain.nodeLtsMajor must be a numeric Node major">;
37
+ readonly packageManagerPin: v.StringSchema<"toolchain.packageManagerPin must be an exact pnpm version pin">;
38
+ }, (issue: v.StrictObjectIssue) => string>;
39
+ readonly packages: v.ArraySchema<v.StrictObjectSchema<{
40
+ readonly packageDefinitionId: v.StringSchema<"packageDefinitionId must use the package-<sha256> format">;
41
+ readonly path: v.StringSchema<"path must be a non-empty string">;
42
+ readonly definitionName: v.StringSchema<"definitionName must be a non-empty string">;
43
+ readonly planningContribution: v.PicklistSchema<["foundationPlan", "planInitialization", "planPackageAddition"], "planningContribution is unsupported">;
44
+ readonly contributionIdentity: v.StringSchema<"contributionIdentity must be a non-empty string">;
45
+ }, (issue: v.StrictObjectIssue) => string>, "packages must be an array">;
46
+ }, (issue: v.StrictObjectIssue) => string>;
28
47
  /** Strictly decodes the durable Record shape before semantic checks run. */
29
48
  export declare function decodeGenerationRecordStructure(value: unknown): GenerationRecord;
30
49
  /** Validates semantic invariants that are independent of a Project Blueprint. */
@@ -23,7 +23,7 @@ const packagePlanningRecordSchema = v.strictObject({
23
23
  planningContribution: v.picklist(["foundationPlan", "planInitialization", "planPackageAddition"], "planningContribution is unsupported"),
24
24
  contributionIdentity: v.string("contributionIdentity must be a non-empty string"),
25
25
  }, (issue) => strictObjectMessage(issue, "package planning fact must be an object"));
26
- const generationRecordSchema = v.strictObject({
26
+ export const generationRecordSchema = v.strictObject({
27
27
  schemaVersion: v.literal(2, (issue) => `Unsupported Generation Record schema version ${String(issue.input)}; expected 2`),
28
28
  repositoryName: v.string("repositoryName must be a non-empty string"),
29
29
  defaultPackageScope: v.string("defaultPackageScope must be a valid npm scope"),
@@ -1,3 +1,4 @@
1
- export { builtInPresetRegistry, createGenerationContext, loadLocalTemplateMetadata, prepareGeneratedRepositoryPackageAddition, validateGeneratedRepositoryInitializationInput, prepareGeneratedRepositoryInitialization, planGeneratedRepositoryInitialization, planGeneratedRepositoryPackageAddition, readRustToolchainChannelFromToml, resolveBuiltInTemplateSource, validateProjectBlueprint, } from "./foundation.ts";
1
+ export { builtInPresetRegistry, createGenerationContext, loadLocalTemplateMetadata, prepareGeneratedRepositoryPackageAddition, validateGeneratedRepositoryInitializationInput, validateGeneratedRepositoryPackageAdditionInput, prepareGeneratedRepositoryInitialization, planGeneratedRepositoryInitialization, planGeneratedRepositoryPackageAddition, readRustToolchainChannelFromToml, resolveBuiltInTemplateSource, validateProjectBlueprint, } from "./foundation.ts";
2
2
  export { templateSources } from "./template-sources.ts";
3
+ export { generationRecordSchema } from "./generation-record.ts";
3
4
  export type { BuiltInPresetDefinition, GeneratedRepositoryPlan, PackageContribution, ProjectBlueprint, BuiltInGenerationContext, LocalTemplateMetadata, InitializationIdentityOverrides, InitializationInputIssue, InitializationInputValidation, InitializationPreparation, PackageAdditionBusinessConflict, PackageAdditionInputIssue, PackageAdditionPreparation, NextStepInstruction, PublicationSetupHandoff, ResolvedInitialization, RustToolchainChannelReading, } from "./foundation.ts";
@@ -1,2 +1,3 @@
1
- export { builtInPresetRegistry, createGenerationContext, loadLocalTemplateMetadata, prepareGeneratedRepositoryPackageAddition, validateGeneratedRepositoryInitializationInput, prepareGeneratedRepositoryInitialization, planGeneratedRepositoryInitialization, planGeneratedRepositoryPackageAddition, readRustToolchainChannelFromToml, resolveBuiltInTemplateSource, validateProjectBlueprint, } from "./foundation.js";
1
+ export { builtInPresetRegistry, createGenerationContext, loadLocalTemplateMetadata, prepareGeneratedRepositoryPackageAddition, validateGeneratedRepositoryInitializationInput, validateGeneratedRepositoryPackageAdditionInput, prepareGeneratedRepositoryInitialization, planGeneratedRepositoryInitialization, planGeneratedRepositoryPackageAddition, readRustToolchainChannelFromToml, resolveBuiltInTemplateSource, validateProjectBlueprint, } from "./foundation.js";
2
2
  export { templateSources } from "./template-sources.js";
3
+ export { generationRecordSchema } from "./generation-record.js";
@@ -91,8 +91,8 @@ function cliContribution(options) {
91
91
  {
92
92
  kind: "copyFile",
93
93
  source: templateSources.tsCli,
94
- from: "test/unit/greet.test.ts",
95
- to: `${definition.path}/test/unit/greet.test.ts`,
94
+ from: "src/standard-schema.ts",
95
+ to: `${definition.path}/src/standard-schema.ts`,
96
96
  },
97
97
  {
98
98
  kind: "copyFile",
@@ -121,8 +121,8 @@ function cliContribution(options) {
121
121
  {
122
122
  kind: "copyFile",
123
123
  source: templateSources.tsCli,
124
- from: "test/e2e/journeys/greet.journey.ts",
125
- to: `${definition.path}/test/e2e/journeys/greet.journey.ts`,
124
+ from: "test/e2e/journeys/lookup.journey.ts",
125
+ to: `${definition.path}/test/e2e/journeys/lookup.journey.ts`,
126
126
  },
127
127
  ];
128
128
  return {
@@ -135,7 +135,11 @@ function cliContribution(options) {
135
135
  type: "module",
136
136
  bin: { [options.packageLeafName]: "./dist/cli.js" },
137
137
  scripts: packageScripts(),
138
- dependencies: { commander: "catalog:" },
138
+ dependencies: {
139
+ "@ykdz/cli-contract": "catalog:",
140
+ "@valibot/to-json-schema": "catalog:",
141
+ valibot: "catalog:",
142
+ },
139
143
  devDependencies: {
140
144
  "@types/node": "catalog:",
141
145
  oxfmt: "catalog:",
@@ -47,11 +47,12 @@
47
47
  "@types/semver": "catalog:",
48
48
  "@types/spdx-expression-parse": "catalog:",
49
49
  "@types/web-bluetooth": "catalog:",
50
+ "@valibot/to-json-schema": "catalog:",
50
51
  "@vikejs/hono": "catalog:",
51
52
  "@vitejs/plugin-vue": "catalog:",
52
53
  "@vue/devtools-api": "catalog:",
53
54
  "@vue/tsconfig": "catalog:",
54
- "commander": "catalog:",
55
+ "@ykdz/cli-contract": "catalog:",
55
56
  "drizzle-kit": "catalog:",
56
57
  "drizzle-orm": "catalog:",
57
58
  "execa": "catalog:",
@@ -6,12 +6,12 @@
6
6
 
7
7
  若这些限制与 Spec、Ticket、ADR 等权威本地文档冲突,应该以权威本地文档为准。
8
8
 
9
- - 开发自动化:非临时维护脚本必须使用 `scripts/**/*.ts` 中可擦除的 TypeScript,而不是 `.mjs` 等 JavaScript 脚本(Node 24 支持原生直接执行);归所属非构建 TypeScript 项目并受 format、lint、typecheck 覆盖,防止腐化;产品 build 不产出这些脚本。普通 Node 自动化使用原生 TypeScript 执行链。
9
+ - 开发自动化:非临时维护脚本必须使用 `scripts/**/*.ts` 中可擦除的 TypeScript,而不是 `.mjs` 等 JavaScript 脚本;归所属非构建 TypeScript 项目并受 format、lint、typecheck 覆盖,防止腐化;产品 build 不产出这些脚本。普通 Node 自动化使用原生 TypeScript 执行链。
10
10
  - 临时脚本:编写临时脚本时,应该将其放到有临时目录语义的位置
11
- - 任务归属:优先使用工具原生配置;直接命令与简单 `&&` 编排写在所属 package manifest;只有自定义类型化行为才新增 TypeScript script
11
+ - 任务归属:优先使用工具原生配置;直接命令与简单 `&&` 编排写在所属 package manifest;只有复杂逻辑才新增 TypeScript script
12
12
  - 包边界:本地文件系统访问留在所属包内;跨包代码与资源通过声明依赖和公开 exports 获取,跨包任务交根 Turbo/pnpm 编排。不要以根目录定位器、跨包物理路径或 `@boundaries-ignore` 绕过边界
13
13
  - 最小充分测试:不要过度编写单元测试,包括为硬删除设计的防回归测试(可以临时存在,但是硬删除完成后必须删除,最好放在可丢弃分支中方便清理)、为文档内容或任何文件编写的存在性测试等,确保测试覆盖且仅覆盖业务逻辑本身的正负项
14
14
  - YAGNI:除非有明确目的,否则不要规划收益不足的安全边界等内容。简单的代码在未来真的遇到新需求时,重构起来远比一个充满防御性冗余设计的复杂系统要容易得多
15
15
  - 正式处理链路:开发、回放和端到端验收应复用生产的正式处理链路与制品,入口和配置可不同;同类流程只保留一份实现,迁移后删除旧链路,局部测试不得冒充全链路验收
16
16
  - 用户界面:不要将任何技术细节泄漏到用户可见的 UI 中
17
- - 完成条件:先通过改动相关的局部门禁,交付前再通过根 `pnpm check`
17
+ - 逐步验收:先通过改动相关的局部门禁,交付前再执行较重的验收任务
@@ -17,11 +17,44 @@ import { pathToFileURL } from "node:url";
17
17
  import { validRange } from "semver";
18
18
  import { list } from "tar";
19
19
 
20
+ import { hasLookupEvidence, hasSchemaEvidence } from "./handoff.ts";
20
21
  import {
21
22
  inspectNpmPublicationReadiness,
22
23
  type NpmPublicationReadiness,
23
24
  } from "./readiness.ts";
24
25
 
26
+ function hasUsageFailure(source: string): boolean {
27
+ try {
28
+ const value: unknown = JSON.parse(source);
29
+ return (
30
+ isObject(value) &&
31
+ value.schemaVersion === "1" &&
32
+ value.kind === "usageFailure" &&
33
+ Array.isArray(value.issues) &&
34
+ value.issues.length > 0
35
+ );
36
+ } catch {
37
+ return false;
38
+ }
39
+ }
40
+
41
+ function hasNotFoundFailure(source: string): boolean {
42
+ try {
43
+ const value: unknown = JSON.parse(source);
44
+ return (
45
+ isObject(value) &&
46
+ value.schemaVersion === "1" &&
47
+ value.command === "lookup" &&
48
+ value.kind === "failure" &&
49
+ value.variant === "notFound" &&
50
+ isObject(value.data) &&
51
+ value.data.name === "missing"
52
+ );
53
+ } catch {
54
+ return false;
55
+ }
56
+ }
57
+
25
58
  type JsonObject = Record<string, unknown>;
26
59
 
27
60
  export type PublicationArtifactFailureCode =
@@ -96,8 +129,13 @@ export type VerifiedPublicationArtifactReceipt = {
96
129
  readonly stdout: string;
97
130
  },
98
131
  {
99
- readonly name: "greet";
100
- readonly args: readonly ["greet", " Ada Lovelace "];
132
+ readonly name: "lookup";
133
+ readonly args: readonly ["lookup", "ada"];
134
+ readonly stdout: string;
135
+ },
136
+ {
137
+ readonly name: "schema";
138
+ readonly args: readonly ["schema"];
101
139
  readonly stdout: string;
102
140
  },
103
141
  ];
@@ -158,6 +196,7 @@ const expectedFiles = [
158
196
  "package/dist/cli-command-identity.js",
159
197
  "package/dist/cli.js",
160
198
  "package/dist/main.js",
199
+ "package/dist/standard-schema.js",
161
200
  "package/package.json",
162
201
  ] as const;
163
202
 
@@ -546,10 +585,15 @@ export function inspectPackedManifestContract(options: {
546
585
  bin[readiness.publication.commandName] === "./dist/cli.js";
547
586
  const exactDependencies =
548
587
  isObject(dependencies) &&
549
- Object.keys(dependencies).length === 1 &&
550
- typeof dependencies.commander === "string" &&
551
- dependencies.commander.length > 0 &&
552
- validRange(dependencies.commander) !== null;
588
+ ["@ykdz/cli-contract", "@valibot/to-json-schema", "valibot"].every(
589
+ (name) =>
590
+ typeof dependencies[name] === "string" &&
591
+ validRange(dependencies[name]) !== null,
592
+ ) &&
593
+ Object.values(dependencies).every(
594
+ (specifier) =>
595
+ typeof specifier === "string" && validRange(specifier) !== null,
596
+ );
553
597
  const validPublishConfig =
554
598
  publishConfig === undefined ||
555
599
  (isObject(publishConfig) &&
@@ -736,7 +780,7 @@ async function smokeCommand(options: {
736
780
  readonly env: NodeJS.ProcessEnv;
737
781
  }): Promise<CommandResult | PublicationArtifactFailure> {
738
782
  const result = await runCommand(options);
739
- return result.exitCode === 0
783
+ return result.exitCode === 0 && result.stderr === ""
740
784
  ? result
741
785
  : commandFailure(
742
786
  "consumer-smoke-failed",
@@ -1032,8 +1076,9 @@ export async function verifyNpmPublicationArtifact(options: {
1032
1076
  }
1033
1077
  const helpArgs = ["--help"] as const;
1034
1078
  const versionArgs = ["--version"] as const;
1035
- const greetArgs = ["greet", " Ada Lovelace "] as const;
1036
- const invalidGreetArgs = ["greet", " "] as const;
1079
+ const lookupArgs = ["lookup", "ada"] as const;
1080
+ const schemaArgs = ["schema"] as const;
1081
+ const invalidLookupArgs = ["lookup", " "] as const;
1037
1082
  const helpCommand = planInstalledBinCommand({
1038
1083
  platform: process.platform,
1039
1084
  binPath,
@@ -1066,81 +1111,104 @@ export async function verifyNpmPublicationArtifact(options: {
1066
1111
  result = { kind: "failed", failure: version };
1067
1112
  return result;
1068
1113
  }
1069
- const greetCommand = planInstalledBinCommand({
1114
+ const lookupCommand = planInstalledBinCommand({
1070
1115
  platform: process.platform,
1071
1116
  binPath,
1072
- args: greetArgs,
1117
+ args: lookupArgs,
1073
1118
  environment: childEnvironment,
1074
1119
  });
1075
- const greet = await smokeCommand({
1076
- executable: greetCommand.executable,
1077
- args: greetCommand.args,
1120
+ const lookup = await smokeCommand({
1121
+ executable: lookupCommand.executable,
1122
+ args: lookupCommand.args,
1078
1123
  cwd: consumerDirectory,
1079
- env: greetCommand.environment,
1124
+ env: lookupCommand.environment,
1080
1125
  });
1081
- if ("code" in greet) {
1082
- result = { kind: "failed", failure: greet };
1083
- return result;
1084
- }
1085
- if (
1086
- !help.stdout.includes(`Usage: ${readiness.publication.commandName}`) ||
1087
- !help.stdout.includes("greet") ||
1088
- version.stdout !== `${readiness.publication.version}\n` ||
1089
- greet.stdout !== "Hello, Ada Lovelace\n"
1090
- ) {
1091
- result = {
1092
- kind: "failed",
1093
- failure: failure(
1094
- "consumer-smoke-failed",
1095
- JSON.stringify({
1096
- help: help.stdout,
1097
- version: version.stdout,
1098
- greet: greet.stdout,
1099
- }),
1100
- "Installed help, exact version, and greet behavior",
1101
- "Correct the packed command identity or behavior and retry.",
1102
- ),
1103
- };
1126
+ if ("code" in lookup) {
1127
+ result = { kind: "failed", failure: lookup };
1104
1128
  return result;
1105
1129
  }
1106
- const invalidGreetCommand = planInstalledBinCommand({
1130
+ const schemaCommand = planInstalledBinCommand({
1107
1131
  platform: process.platform,
1108
1132
  binPath,
1109
- args: invalidGreetArgs,
1133
+ args: schemaArgs,
1110
1134
  environment: childEnvironment,
1111
1135
  });
1112
- const invalidGreet = await runCommand({
1113
- executable: invalidGreetCommand.executable,
1114
- args: invalidGreetCommand.args,
1136
+ const schema = await smokeCommand({
1137
+ executable: schemaCommand.executable,
1138
+ args: schemaCommand.args,
1115
1139
  cwd: consumerDirectory,
1116
- env: invalidGreetCommand.environment,
1140
+ env: schemaCommand.environment,
1117
1141
  });
1142
+ if ("code" in schema) {
1143
+ result = { kind: "failed", failure: schema };
1144
+ return result;
1145
+ }
1118
1146
  if (
1119
- invalidGreet.exitCode !== 1 ||
1120
- invalidGreet.stdout !== "" ||
1121
- !invalidGreet.stderr.startsWith("error: Name must not be empty\n")
1147
+ !help.stdout.includes(readiness.publication.commandName) ||
1148
+ !help.stdout.includes("lookup") ||
1149
+ !help.stdout.includes("schema") ||
1150
+ version.stdout !==
1151
+ `${readiness.publication.commandName} ${readiness.publication.version}\n` ||
1152
+ !hasLookupEvidence(lookup.stdout) ||
1153
+ !hasSchemaEvidence(schema.stdout, readiness.publication.commandName)
1122
1154
  ) {
1123
1155
  result = {
1124
1156
  kind: "failed",
1125
1157
  failure: failure(
1126
1158
  "consumer-smoke-failed",
1127
1159
  JSON.stringify({
1128
- args: invalidGreetArgs,
1129
- exitCode: invalidGreet.exitCode,
1130
- stdout: invalidGreet.stdout,
1131
- stderr: invalidGreet.stderr,
1160
+ help: help.stdout,
1161
+ version: version.stdout,
1162
+ lookup: lookup.stdout,
1132
1163
  }),
1133
- "Installed greet with a blank name to exit 1 with the stable validation error and no stdout",
1134
- "Correct the packed command validation behavior and retry.",
1135
- {
1136
- executable: invalidGreetCommand.executable,
1137
- args: invalidGreetCommand.args,
1138
- exitCode: invalidGreet.exitCode,
1139
- },
1164
+ "安装后的帮助、实际版本、lookup 查询及完整 schema 契约",
1165
+ "修正制品中的命令身份或行为后重试。",
1140
1166
  ),
1141
1167
  };
1142
1168
  return result;
1143
1169
  }
1170
+ for (const scenario of [
1171
+ {
1172
+ args: [...invalidLookupArgs, "--output-format", "text"],
1173
+ exitCode: 2,
1174
+ accepts: hasUsageFailure,
1175
+ },
1176
+ { args: ["lookup", "missing"], exitCode: 1, accepts: hasNotFoundFailure },
1177
+ ]) {
1178
+ const command = planInstalledBinCommand({
1179
+ platform: process.platform,
1180
+ binPath,
1181
+ args: scenario.args,
1182
+ environment: childEnvironment,
1183
+ });
1184
+ const observed = await runCommand({
1185
+ executable: command.executable,
1186
+ args: command.args,
1187
+ cwd: consumerDirectory,
1188
+ env: command.environment,
1189
+ });
1190
+ if (
1191
+ observed.exitCode !== scenario.exitCode ||
1192
+ observed.stdout !== "" ||
1193
+ !scenario.accepts(observed.stderr)
1194
+ ) {
1195
+ result = {
1196
+ kind: "failed",
1197
+ failure: failure(
1198
+ "consumer-smoke-failed",
1199
+ JSON.stringify(observed),
1200
+ "非法输入应退出 2,未找到记录应退出 1;均通过 stderr 返回原生结果。",
1201
+ "修正安装后命令的失败协议并重试。",
1202
+ {
1203
+ executable: command.executable,
1204
+ args: command.args,
1205
+ exitCode: observed.exitCode,
1206
+ },
1207
+ ),
1208
+ };
1209
+ return result;
1210
+ }
1211
+ }
1144
1212
 
1145
1213
  const artifactBytes = await readFile(packedArtifactPath);
1146
1214
  const digest = createHash("sha512").update(artifactBytes).digest();
@@ -1181,7 +1249,8 @@ export async function verifyNpmPublicationArtifact(options: {
1181
1249
  { name: "runtime-import", args: [], stdout: "" },
1182
1250
  { name: "help", args: helpArgs, stdout: help.stdout },
1183
1251
  { name: "version", args: versionArgs, stdout: version.stdout },
1184
- { name: "greet", args: greetArgs, stdout: greet.stdout },
1252
+ { name: "lookup", args: lookupArgs, stdout: lookup.stdout },
1253
+ { name: "schema", args: schemaArgs, stdout: schema.stdout },
1185
1254
  ],
1186
1255
  };
1187
1256
  try {
@@ -287,6 +287,7 @@ const ticket09ReceiptFilePaths = [
287
287
  "package/dist/cli-command-identity.js",
288
288
  "package/dist/cli.js",
289
289
  "package/dist/main.js",
290
+ "package/dist/standard-schema.js",
290
291
  "package/package.json",
291
292
  ] as const;
292
293
 
@@ -315,23 +316,94 @@ function hasCanonicalReceiptFiles(files: Receipt["files"]): boolean {
315
316
  return true;
316
317
  }
317
318
 
319
+ /** 发布消费检查与交接校验共用原生结果的业务判据。 */
320
+ export function hasLookupEvidence(source: string): boolean {
321
+ try {
322
+ const result: unknown = JSON.parse(source);
323
+ return (
324
+ isRecord(result) &&
325
+ result.schemaVersion === "1" &&
326
+ result.command === "lookup" &&
327
+ result.kind === "data" &&
328
+ result.variant === "found" &&
329
+ isRecord(result.data) &&
330
+ result.data.name === "ada" &&
331
+ result.data.title === "Ada Lovelace"
332
+ );
333
+ } catch {
334
+ return false;
335
+ }
336
+ }
337
+
338
+ export function hasSchemaEvidence(
339
+ source: string,
340
+ commandName: string,
341
+ ): boolean {
342
+ try {
343
+ const result: unknown = JSON.parse(source);
344
+ if (
345
+ !isRecord(result) ||
346
+ result.schemaVersion !== "1" ||
347
+ result.command !== "schema" ||
348
+ result.kind !== "data" ||
349
+ result.variant !== "exported" ||
350
+ !isRecord(result.data)
351
+ )
352
+ return false;
353
+ const manifest = result.data.manifest;
354
+ if (
355
+ !isRecord(manifest) ||
356
+ !isRecord(manifest.commands) ||
357
+ typeof manifest.root !== "string"
358
+ )
359
+ return false;
360
+ const root = manifest.commands[manifest.root];
361
+ const lookup = manifest.commands.lookup;
362
+ const schema = manifest.commands.schema;
363
+ return (
364
+ isRecord(root) &&
365
+ root.name === commandName &&
366
+ isRecord(schema) &&
367
+ schema.name === "schema" &&
368
+ isRecord(lookup) &&
369
+ lookup.name === "lookup" &&
370
+ isRecord(lookup.input) &&
371
+ isRecord(lookup.input.inputSchema) &&
372
+ isRecord(lookup.success) &&
373
+ isRecord(lookup.success.variants) &&
374
+ isRecord(lookup.success.variants.found) &&
375
+ lookup.success.variants.found.exitCode === 0 &&
376
+ isRecord(lookup.failures) &&
377
+ isRecord(lookup.failures.notFound) &&
378
+ lookup.failures.notFound.exitCode === 1
379
+ );
380
+ } catch {
381
+ return false;
382
+ }
383
+ }
384
+
318
385
  function hasStableSmokeEvidence(receipt: Receipt): boolean {
319
- const [runtimeImport, help, version, greet] = receipt.smokes;
386
+ const [runtimeImport, help, version, lookup, schema] = receipt.smokes;
320
387
  return (
321
- receipt.smokes.length === 4 &&
388
+ receipt.smokes.length === 5 &&
322
389
  runtimeImport?.name === "runtime-import" &&
323
390
  sameArguments(runtimeImport.args, []) &&
324
391
  runtimeImport.stdout === "" &&
325
392
  help?.name === "help" &&
326
393
  sameArguments(help.args, ["--help"]) &&
327
- help.stdout.includes(`Usage: ${receipt.publication.commandName}`) &&
328
- help.stdout.includes("greet") &&
394
+ help.stdout.includes(receipt.publication.commandName) &&
395
+ help.stdout.includes("lookup") &&
396
+ help.stdout.includes("schema") &&
329
397
  version?.name === "version" &&
330
398
  sameArguments(version.args, ["--version"]) &&
331
- version.stdout === `${receipt.publication.version}\n` &&
332
- greet?.name === "greet" &&
333
- sameArguments(greet.args, ["greet", " Ada Lovelace "]) &&
334
- greet.stdout === "Hello, Ada Lovelace\n"
399
+ version.stdout ===
400
+ `${receipt.publication.commandName} ${receipt.publication.version}\n` &&
401
+ lookup?.name === "lookup" &&
402
+ sameArguments(lookup.args, ["lookup", "ada"]) &&
403
+ hasLookupEvidence(lookup.stdout) &&
404
+ schema?.name === "schema" &&
405
+ sameArguments(schema.args, ["schema"]) &&
406
+ hasSchemaEvidence(schema.stdout, receipt.publication.commandName)
335
407
  );
336
408
  }
337
409