@rashidee/co2 1.2.5
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/dist/index.js +25449 -0
- package/drizzle/0000_remarkable_charles_xavier.sql +210 -0
- package/drizzle/0001_wise_wolf_cub.sql +13 -0
- package/drizzle/0002_secret_spyke.sql +16 -0
- package/drizzle/0003_workspace_config_singleton.sql +16 -0
- package/drizzle/0004_terminal_claim_v120.sql +11 -0
- package/drizzle/0005_brainstorm_v124.sql +10 -0
- package/drizzle/0006_project_v140.sql +6 -0
- package/drizzle/0007_prd_wizard_v124.sql +14 -0
- package/drizzle/0008_workflow_artifact_v126.sql +24 -0
- package/drizzle/0009_project_import_v150.sql +7 -0
- package/drizzle/0010_quality_v151.sql +3 -0
- package/drizzle/meta/0000_snapshot.json +1335 -0
- package/drizzle/meta/0001_snapshot.json +1416 -0
- package/drizzle/meta/0002_snapshot.json +1510 -0
- package/drizzle/meta/_journal.json +83 -0
- package/package.json +41 -0
- package/plugin/.claude-plugin/marketplace.json +36 -0
- package/plugin/.claude-plugin/plugin.json +22 -0
- package/plugin/README.md +625 -0
- package/plugin/SKILLS.md +350 -0
- package/plugin/co2.svg +5 -0
- package/plugin/commands/brainstorm-loop.md +129 -0
- package/plugin/skills/conductor-defect/SKILL.md +898 -0
- package/plugin/skills/conductor-feature-develop/SKILL.md +1383 -0
- package/plugin/skills/conductor-feature-develop/references/implementation-domain-template.md +131 -0
- package/plugin/skills/conductor-feature-develop/references/implementation-master-template.md +89 -0
- package/plugin/skills/conductor-feature-develop/references/playwright-setup.md +224 -0
- package/plugin/skills/conductor-feature-prepare/SKILL.md +604 -0
- package/plugin/skills/depgen-k8s/SKILL.md +468 -0
- package/plugin/skills/depgen-k8s/references/dockerfile-laravel.md +197 -0
- package/plugin/skills/depgen-k8s/references/dockerfile-nodejs.md +163 -0
- package/plugin/skills/depgen-k8s/references/dockerfile-spring-boot.md +174 -0
- package/plugin/skills/depgen-k8s/references/k8s-patterns.md +869 -0
- package/plugin/skills/mockgen-shadcn/SKILL.md +1067 -0
- package/plugin/skills/mockgen-shadcn/references/admin-layout-template.md +1467 -0
- package/plugin/skills/mockgen-shadcn/references/mockup-hub-template.md +498 -0
- package/plugin/skills/mockgen-shadcn/references/mockup-index-template.md +216 -0
- package/plugin/skills/mockgen-tailwind/SKILL.md +904 -0
- package/plugin/skills/mockgen-tailwind/references/admin-layout-template.md +720 -0
- package/plugin/skills/mockgen-tailwind/references/mockup-hub-template.md +498 -0
- package/plugin/skills/mockgen-tailwind/references/mockup-index-template.md +190 -0
- package/plugin/skills/modelgen-nosql/SKILL.md +617 -0
- package/plugin/skills/modelgen-nosql/references/model-extraction-methodology.md +497 -0
- package/plugin/skills/modelgen-nosql/references/nosql-design-guide.md +258 -0
- package/plugin/skills/modelgen-relational/SKILL.md +707 -0
- package/plugin/skills/modelgen-relational/references/model-extraction-methodology.md +499 -0
- package/plugin/skills/specgen-flutter-riverpod/SKILL.md +898 -0
- package/plugin/skills/specgen-flutter-riverpod/references/component-patterns.md +971 -0
- package/plugin/skills/specgen-flutter-riverpod/references/notification-patterns.md +457 -0
- package/plugin/skills/specgen-flutter-riverpod/references/routing-patterns.md +362 -0
- package/plugin/skills/specgen-flutter-riverpod/references/security-patterns.md +709 -0
- package/plugin/skills/specgen-flutter-riverpod/references/spec-template.md +1566 -0
- package/plugin/skills/specgen-flutter-riverpod/references/state-patterns.md +518 -0
- package/plugin/skills/specgen-flutter-riverpod/references/storage-patterns.md +370 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/SKILL.md +984 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/batch-patterns.md +359 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/messaging-patterns.md +468 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/modulith-patterns.md +461 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/reporting-patterns.md +803 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/security-patterns.md +501 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/spec-template.md +1268 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/web-patterns.md +301 -0
- package/plugin/skills/specgen-node-cli-web/SKILL.md +561 -0
- package/plugin/skills/specgen-node-cli-web/references/auth-patterns.md +293 -0
- package/plugin/skills/specgen-node-cli-web/references/cli-packaging-patterns.md +250 -0
- package/plugin/skills/specgen-node-cli-web/references/server-patterns.md +247 -0
- package/plugin/skills/specgen-node-cli-web/references/spec-template.md +401 -0
- package/plugin/skills/specgen-node-cli-web/references/testing-patterns.md +174 -0
- package/plugin/skills/specgen-react-mui/SKILL.md +789 -0
- package/plugin/skills/specgen-react-mui/references/component-patterns.md +1077 -0
- package/plugin/skills/specgen-react-mui/references/reporting-patterns.md +1998 -0
- package/plugin/skills/specgen-react-mui/references/routing-patterns.md +461 -0
- package/plugin/skills/specgen-react-mui/references/security-patterns.md +599 -0
- package/plugin/skills/specgen-react-mui/references/spec-template.md +1030 -0
- package/plugin/skills/specgen-react-mui/references/state-patterns.md +327 -0
- package/plugin/skills/specgen-react-tailwind/SKILL.md +859 -0
- package/plugin/skills/specgen-react-tailwind/references/component-patterns.md +1212 -0
- package/plugin/skills/specgen-react-tailwind/references/reporting-patterns.md +1529 -0
- package/plugin/skills/specgen-react-tailwind/references/routing-patterns.md +669 -0
- package/plugin/skills/specgen-react-tailwind/references/security-patterns.md +656 -0
- package/plugin/skills/specgen-react-tailwind/references/spec-template.md +1237 -0
- package/plugin/skills/specgen-react-tailwind/references/state-patterns.md +327 -0
- package/plugin/skills/specgen-sdk-java/SKILL.md +933 -0
- package/plugin/skills/specgen-sdk-java/references/api-extraction-patterns.md +247 -0
- package/plugin/skills/specgen-sdk-java/references/http-client-patterns.md +495 -0
- package/plugin/skills/specgen-sdk-java/references/packaging-patterns.md +366 -0
- package/plugin/skills/specgen-sdk-java/references/spec-template.md +956 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/SKILL.md +1284 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/batch-patterns.md +1224 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/jasper-patterns.md +1638 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/messaging-patterns.md +512 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/modulith-patterns.md +354 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/security-patterns.md +551 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/spec-template.md +2502 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/web-patterns.md +503 -0
- package/plugin/skills/specgen-spring-jpa-restapi/SKILL.md +990 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/batch-patterns.md +1224 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/messaging-patterns.md +512 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/modulith-patterns.md +279 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/reporting-patterns.md +1536 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/restapi-patterns.md +722 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/security-patterns.md +351 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/spec-template.md +553 -0
- package/plugin/skills/specgen-ts-cli/SKILL.md +861 -0
- package/plugin/skills/specgen-ts-cli/references/async-patterns.md +1101 -0
- package/plugin/skills/specgen-ts-cli/references/command-patterns.md +383 -0
- package/plugin/skills/specgen-ts-cli/references/config-patterns.md +430 -0
- package/plugin/skills/specgen-ts-cli/references/database-patterns.md +750 -0
- package/plugin/skills/specgen-ts-cli/references/packaging-patterns.md +426 -0
- package/plugin/skills/specgen-ts-cli/references/spec-template.md +1391 -0
- package/plugin/skills/specgen-ts-cli/references/testing-patterns.md +909 -0
- package/plugin/skills/testgen-functional/SKILL.md +1381 -0
- package/plugin/skills/tracegen-matrix/SKILL.md +243 -0
- package/plugin/skills/util-preparek8senv/SKILL.md +422 -0
- package/plugin/skills/util-projectinit/SKILL.md +307 -0
- package/plugin/skills/util-projectinit/reference/brainstorm-loop.md +129 -0
- package/plugin/skills/util-projectinit/reference/brainstorm-protocol.md +144 -0
- package/plugin/skills/util-projectinit/reference/brainstorm-setup-guide.md +153 -0
- package/plugin/skills/util-projectinit/reference/brainstorm-template-appdev.md +87 -0
- package/plugin/skills/util-projectinit/reference/co2-context-generation-guide.md +761 -0
- package/plugin/skills/util-projectsync/SKILL.md +501 -0
- package/plugin/skills/util-updprd/SKILL.md +324 -0
- package/plugin/skills/util-usanalyzer/SKILL.md +307 -0
- package/plugin/skills/util-ustagger/SKILL.md +154 -0
- package/static/assets/abnfDiagram-VRR7QNED-DvPuwyCV.js +1 -0
- package/static/assets/arc-DRKw7sjs.js +1 -0
- package/static/assets/architectureDiagram-ZJ3FMSHR-CaNcxUbC.js +36 -0
- package/static/assets/blockDiagram-677ZJIJ3-Demd4AOK.js +132 -0
- package/static/assets/c4Diagram-LMCZKHZV-PVKUfc2x.js +10 -0
- package/static/assets/channel-C2nVbuwv.js +1 -0
- package/static/assets/chunk-2Q5K7J3B-CExf8ww_.js +1 -0
- package/static/assets/chunk-32BRIVSS-CFPaoONF.js +1 -0
- package/static/assets/chunk-5VM5RSS4-DE2esM67.js +15 -0
- package/static/assets/chunk-EX3LRPZG-SON_YdDG.js +231 -0
- package/static/assets/chunk-JWPE2WC7-Qxah8LNr.js +1 -0
- package/static/assets/chunk-MOJQB5TN-BcWGQV3j.js +88 -0
- package/static/assets/chunk-RYQCIY6F-DkDj-OR5.js +1 -0
- package/static/assets/chunk-V7JOEXUC-BlI1Mrah.js +206 -0
- package/static/assets/chunk-VR4S4FIN-Agf__duj.js +1 -0
- package/static/assets/chunk-XXDRQBXY-B5CfAh85.js +1 -0
- package/static/assets/classDiagram-OUVF2IWQ-DXJIljsR.js +1 -0
- package/static/assets/classDiagram-v2-EOCWNBFH-DXJIljsR.js +1 -0
- package/static/assets/cose-bilkent-JH36ORCC-DO0cQkcy.js +1 -0
- package/static/assets/cynefin-VYW2F7L2-CfOnsnXc.js +178 -0
- package/static/assets/cynefinDiagram-TSTJHNR4-BJ8tULAv.js +62 -0
- package/static/assets/cytoscape.esm-DTSO7Bv0.js +331 -0
- package/static/assets/dagre-VKFMJZFB-DfjwzHqP.js +4 -0
- package/static/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/static/assets/diagram-FQU43EPY-CndSOIIM.js +3 -0
- package/static/assets/diagram-G47NLZAW-Czf5hN0Z.js +24 -0
- package/static/assets/diagram-NH7WQ7WH-COAyojGh.js +24 -0
- package/static/assets/diagram-OA4YK3LP-H8PoiN2m.js +30 -0
- package/static/assets/diagram-WEI45ONY-DzcaVzjp.js +41 -0
- package/static/assets/ebnfDiagram-CCIWWBDH-DPazGYLJ.js +1 -0
- package/static/assets/erDiagram-Q63AITRT-Bo-fubgF.js +85 -0
- package/static/assets/flowDiagram-23GEKE2U-CSvxUDwh.js +156 -0
- package/static/assets/ganttDiagram-NO4QXBWP-DnBveWX6.js +292 -0
- package/static/assets/gitGraphDiagram-IHSO6WYX-B3rVL8c-.js +106 -0
- package/static/assets/graph-C9eacEi8.js +1 -0
- package/static/assets/index-LZSQkLE2.css +41 -0
- package/static/assets/index-y7XDSgMG.js +495 -0
- package/static/assets/infoDiagram-FWYZ7A6U-CvWV9yy2.js +2 -0
- package/static/assets/init-Gi6I4Gst.js +1 -0
- package/static/assets/ishikawaDiagram-FXEZZL3T-DF28a1N6.js +70 -0
- package/static/assets/journeyDiagram-5HDEW3XC-CB6CugYk.js +139 -0
- package/static/assets/kanban-definition-HUTT4EX6-ResSLF6d.js +89 -0
- package/static/assets/katex-C5jXJg4s.js +257 -0
- package/static/assets/layout-DEXfKzaS.js +1 -0
- package/static/assets/linear-CLO--ryk.js +1 -0
- package/static/assets/map-Czzmt4hB.js +1 -0
- package/static/assets/mindmap-definition-LN4V7U3C-BvW3EbxX.js +96 -0
- package/static/assets/ordinal-Cboi1Yqb.js +1 -0
- package/static/assets/pegDiagram-2B236MQR-BHCgqrrM.js +1 -0
- package/static/assets/pieDiagram-ENE6RG2P-DVmCQ5FA.js +39 -0
- package/static/assets/quadrantDiagram-ABIIQ3AL-B3e5KR52.js +7 -0
- package/static/assets/railroadDiagram-RFXS5EU6-Csv5ysLc.js +1 -0
- package/static/assets/requirementDiagram-TGXJPOKE-DOMVzvnB.js +84 -0
- package/static/assets/sankeyDiagram-HTMAVEWB-B1dcTOvy.js +40 -0
- package/static/assets/sequenceDiagram-DBY2YBRQ-BY414yeO.js +162 -0
- package/static/assets/sizeCapture-X5ZJPWSS-CuJfrfBN.js +1 -0
- package/static/assets/stateDiagram-2N3HPSRC-FX4rJkzV.js +1 -0
- package/static/assets/stateDiagram-v2-6OUMAXLB-BVufbO_H.js +1 -0
- package/static/assets/swimlanes-5IMT3BWC-Sfy58mmv.js +2 -0
- package/static/assets/swimlanesDiagram-G3AALYLV-wDCDw08H.js +8 -0
- package/static/assets/timeline-definition-FHXFAJF6-CmV7by8p.js +120 -0
- package/static/assets/vennDiagram-L72KCM5P-FqIyFZFt.js +34 -0
- package/static/assets/wardleyDiagram-EHGQE667-BZ06O45i.js +78 -0
- package/static/assets/xychartDiagram-FW5EYKEG-BOkffR06.js +7 -0
- package/static/index.html +24 -0
|
@@ -0,0 +1,861 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: specgen-ts-cli
|
|
3
|
+
model: claude-opus-4-8
|
|
4
|
+
effort: high
|
|
5
|
+
description: >
|
|
6
|
+
Generate a detailed specification document for building a distributable Node.js CLI
|
|
7
|
+
application written in TypeScript. Uses Commander.js for command parsing, tsup for
|
|
8
|
+
bundling, and @yao-pkg/pkg for cross-platform binary packaging (Windows, macOS, Linux).
|
|
9
|
+
Interactive prompts (Inquirer.js), persistent user config (conf), project-level config
|
|
10
|
+
(cosmiconfig), shell execution (execa), HTTP client (got), plugin system, and
|
|
11
|
+
auto-update checking are configurable based on application needs.
|
|
12
|
+
Standardized input: application name (mandatory), version (mandatory), command (optional).
|
|
13
|
+
Use this skill whenever the user asks to create a spec, specification, blueprint, or
|
|
14
|
+
technical design document for a new CLI tool, command-line application, terminal tool,
|
|
15
|
+
or developer tool. Also trigger when the user says things like "spec out a new CLI",
|
|
16
|
+
"design a TypeScript CLI", "write a technical spec for my CLI tool",
|
|
17
|
+
"scaffold spec for a Node CLI", or any request describing a command-line application.
|
|
18
|
+
Even if the user only mentions a subset (e.g., "CLI with config file support" or
|
|
19
|
+
"distributable Node tool"), this skill likely applies — ask and confirm.
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
# TypeScript CLI Application Specification Generator
|
|
23
|
+
|
|
24
|
+
This skill generates a comprehensive specification document (Markdown) that serves as a
|
|
25
|
+
blueprint for building a distributable Node.js CLI application in TypeScript. The spec is
|
|
26
|
+
intended to be followed by a developer or coding agent to produce a fully functional,
|
|
27
|
+
packageable CLI tool.
|
|
28
|
+
|
|
29
|
+
The specification does NOT generate code. It produces a detailed, opinionated technical
|
|
30
|
+
document describing every layer of the application — from `package.json` configuration to
|
|
31
|
+
command action handlers to binary packaging — so that implementation becomes a mechanical
|
|
32
|
+
exercise.
|
|
33
|
+
|
|
34
|
+
## Technology Stack
|
|
35
|
+
|
|
36
|
+
### Core Stack (Always Included)
|
|
37
|
+
|
|
38
|
+
These are the fixed versions the spec targets. Do not deviate unless the user explicitly
|
|
39
|
+
requests different versions.
|
|
40
|
+
|
|
41
|
+
| Component | Version |
|
|
42
|
+
|-----------------|----------|
|
|
43
|
+
| Node.js | 22.x LTS |
|
|
44
|
+
| TypeScript | 5.x |
|
|
45
|
+
| Commander.js | 12.x |
|
|
46
|
+
| tsup | 8.x |
|
|
47
|
+
| Zod | 3.x |
|
|
48
|
+
| Chalk | 5.x |
|
|
49
|
+
| Ora | 8.x |
|
|
50
|
+
|
|
51
|
+
> **Note:** Chalk 5.x and Ora 8.x are ESM-only packages. The project uses
|
|
52
|
+
> `"type": "module"` in `package.json` and targets ESM output from tsup.
|
|
53
|
+
> All imports use the `.js` extension suffix even for TypeScript source files.
|
|
54
|
+
|
|
55
|
+
### Optional Integration Versions
|
|
56
|
+
|
|
57
|
+
Include in the version table only when the corresponding integration is selected.
|
|
58
|
+
|
|
59
|
+
| Component | Version | When Selected |
|
|
60
|
+
|------------------------|---------|-------------------------|
|
|
61
|
+
| @inquirer/prompts | 7.x | Prompts = yes |
|
|
62
|
+
| conf | 13.x | User Config = yes |
|
|
63
|
+
| cosmiconfig | 9.x | Project Config = yes |
|
|
64
|
+
| better-sqlite3 | 11.x | Local Database = yes |
|
|
65
|
+
| drizzle-orm | 0.36.x | Local Database = yes |
|
|
66
|
+
| env-paths | 3.x | Local Database = yes |
|
|
67
|
+
| drizzle-kit | 0.28.x | Local Database = yes (dev) |
|
|
68
|
+
| execa | 9.x | Shell Execution = yes |
|
|
69
|
+
| got | 14.x | HTTP Client = yes |
|
|
70
|
+
| update-notifier | 7.x | Auto-update = yes |
|
|
71
|
+
| @yao-pkg/pkg | 5.x | Binary Packaging = yes |
|
|
72
|
+
| cli-table3 | 0.6.x | Table Output = yes |
|
|
73
|
+
| boxen | 8.x | Banner/Box UI = yes |
|
|
74
|
+
| glob | 11.x | File Operations = yes |
|
|
75
|
+
|
|
76
|
+
> **Async patterns (Polling, Inline Batch, Background Daemon) use no additional
|
|
77
|
+
> npm packages** — they are implemented entirely with Node.js built-ins
|
|
78
|
+
> (`setTimeout`, `process.kill`, `child_process.spawn`) and the packages already
|
|
79
|
+
> in the core stack (ora for progress, chalk for output). The async pattern type
|
|
80
|
+
> is detected from PRD.md NFRs and user stories; no new dependency version rows
|
|
81
|
+
> are needed.
|
|
82
|
+
|
|
83
|
+
## Core Dependencies (package.json)
|
|
84
|
+
|
|
85
|
+
The spec must include these in the `dependencies` configuration section (always):
|
|
86
|
+
|
|
87
|
+
- `commander` — CLI argument parsing and command routing
|
|
88
|
+
- `chalk` — Terminal colour output (ESM-only, v5+)
|
|
89
|
+
- `ora` — Spinner / progress indicators
|
|
90
|
+
- `zod` — Schema validation for config, arguments, and API payloads
|
|
91
|
+
|
|
92
|
+
Always in `devDependencies`:
|
|
93
|
+
- `typescript` — TypeScript compiler
|
|
94
|
+
- `tsup` — TypeScript bundler (esbuild-based, handles ESM, shebang injection)
|
|
95
|
+
- `vitest` — Unit and integration testing
|
|
96
|
+
- `@types/node` — Node.js type declarations
|
|
97
|
+
- `tsx` — TypeScript execution for scripts and development
|
|
98
|
+
- `eslint` + `@typescript-eslint/eslint-plugin` — Linting
|
|
99
|
+
|
|
100
|
+
### Conditional Dependencies
|
|
101
|
+
|
|
102
|
+
**If Prompts = yes:**
|
|
103
|
+
- `@inquirer/prompts` — Modern interactive prompts (officially maintained Inquirer v9+)
|
|
104
|
+
|
|
105
|
+
**If User Config = yes:**
|
|
106
|
+
- `conf` — Persistent user-level configuration stored in OS config directory
|
|
107
|
+
|
|
108
|
+
**If Project Config = yes:**
|
|
109
|
+
- `cosmiconfig` — Project-level config file loading (supports `.json`, `.yaml`, `.js`, `package.json`)
|
|
110
|
+
|
|
111
|
+
**If Local Database = yes:**
|
|
112
|
+
- `better-sqlite3` — Synchronous SQLite driver (no async complexity in CLI context)
|
|
113
|
+
- `drizzle-orm` — TypeScript-first ORM with schema-as-code and type-safe query builder
|
|
114
|
+
- `env-paths` — OS-correct data directory resolution (macOS / Linux / Windows)
|
|
115
|
+
- `@types/better-sqlite3` — TypeScript type declarations (devDependency)
|
|
116
|
+
- `drizzle-kit` — Migration generator and Drizzle Studio (devDependency)
|
|
117
|
+
|
|
118
|
+
**If Shell Execution = yes:**
|
|
119
|
+
- `execa` — Child process execution with better ergonomics and ESM support
|
|
120
|
+
|
|
121
|
+
**If HTTP Client = yes:**
|
|
122
|
+
- `got` — HTTP client with TypeScript-first design (ESM-only, v14+)
|
|
123
|
+
|
|
124
|
+
**If Auto-update = yes:**
|
|
125
|
+
- `update-notifier` — Non-blocking update checks against npm registry
|
|
126
|
+
|
|
127
|
+
**If Binary Packaging = yes (devDependency):**
|
|
128
|
+
- `@yao-pkg/pkg` — Compiles Node.js application into standalone executables
|
|
129
|
+
|
|
130
|
+
**If Table Output = yes:**
|
|
131
|
+
- `cli-table3` — Tabular terminal output with borders and alignment
|
|
132
|
+
|
|
133
|
+
**If Banner/Box UI = yes:**
|
|
134
|
+
- `boxen` — Bordered terminal box output (ESM-only)
|
|
135
|
+
|
|
136
|
+
**If File Operations = yes:**
|
|
137
|
+
- `glob` — File system globbing with ESM support
|
|
138
|
+
|
|
139
|
+
## When the Skill Triggers
|
|
140
|
+
|
|
141
|
+
Generate the spec when the user provides an **application name** and **version** that
|
|
142
|
+
corresponds to one of the custom applications defined in `CLAUDE.md`. The skill
|
|
143
|
+
reads all required inputs from the project's context files — no interactive Q&A is needed
|
|
144
|
+
for the core inputs.
|
|
145
|
+
|
|
146
|
+
The user invokes this skill by specifying the target application and version, for example:
|
|
147
|
+
- `/specgen-ts-cli my_tool v0.1.0`
|
|
148
|
+
- `/specgen-ts-cli my_tool v0.1.0 command:deploy`
|
|
149
|
+
- `/specgen-ts-cli "My Tool" v0.1.0`
|
|
150
|
+
|
|
151
|
+
The skill then locates the matching context folder and reads all input files automatically.
|
|
152
|
+
|
|
153
|
+
## Version Gate
|
|
154
|
+
|
|
155
|
+
Before starting any work, resolve the application folder first (see Input Resolution below), then check `CHANGELOG.md` in the application folder (`<app_folder>/CHANGELOG.md`):
|
|
156
|
+
|
|
157
|
+
1. If `<app_folder>/CHANGELOG.md` does not exist, skip this check (first-ever execution for this application).
|
|
158
|
+
2. If `<app_folder>/CHANGELOG.md` exists, scan all `## vX.Y.Z` headings and determine the **highest version** using semantic versioning comparison.
|
|
159
|
+
3. Compare the requested version against the highest version:
|
|
160
|
+
- If requested version **>=** highest version: proceed normally.
|
|
161
|
+
- If requested version **<** highest version: **STOP immediately**. Print: `"Version {requested} is lower than the current application version {highest} recorded in <app_folder>/CHANGELOG.md. Execution rejected."` Do NOT proceed with any work.
|
|
162
|
+
|
|
163
|
+
## Input Resolution
|
|
164
|
+
|
|
165
|
+
This skill uses standardized input resolution. Provide:
|
|
166
|
+
|
|
167
|
+
| Argument | Required | Example | Description |
|
|
168
|
+
|-------------------|----------|-------------------|---------------------------------------------|
|
|
169
|
+
| `<application>` | Yes | `my_tool` | Application name to locate the context folder |
|
|
170
|
+
| `<version>` | Yes | `v0.1.0` | Version to scope processing |
|
|
171
|
+
| `command:<name>` | No | `command:deploy` | Limit generation to a single command spec |
|
|
172
|
+
|
|
173
|
+
### Application Folder Resolution
|
|
174
|
+
|
|
175
|
+
The application name is matched against root-level application folders:
|
|
176
|
+
1. Strip any leading `<number>_` prefix from folder names (e.g., `1_my_tool` → `my_tool`)
|
|
177
|
+
2. Match case-insensitively against the provided application name
|
|
178
|
+
3. Accept snake_case, kebab-case, or title-case input (all match the same folder)
|
|
179
|
+
4. If no match found, list available applications and stop
|
|
180
|
+
|
|
181
|
+
### Auto-Resolved Paths
|
|
182
|
+
|
|
183
|
+
| File | Resolved Path |
|
|
184
|
+
|----------------|----------------------------------------|
|
|
185
|
+
| PRD.md | `<app_folder>/context/PRD.md` |
|
|
186
|
+
| Command Models | `<app_folder>/context/model/` |
|
|
187
|
+
| Output | `<app_folder>/context/specification/` |
|
|
188
|
+
|
|
189
|
+
### Version Filtering
|
|
190
|
+
|
|
191
|
+
When a version is provided, only include user stories, NFRs, and constraints from versions
|
|
192
|
+
<= the provided version. For example, if `v0.3.0` is specified:
|
|
193
|
+
- Include items tagged `[v0.1.0]`, `[v0.2.0]`, `[v0.3.0]`
|
|
194
|
+
- Exclude items tagged `[v0.4.0]` or later
|
|
195
|
+
- Version comparison uses semantic versioning order
|
|
196
|
+
|
|
197
|
+
### Command Filtering
|
|
198
|
+
|
|
199
|
+
When `command:<name>` is provided:
|
|
200
|
+
- Only generate the `SPEC.md` for that specific command
|
|
201
|
+
- Other existing command spec files remain untouched
|
|
202
|
+
- `SPECIFICATION.md` (root) gets a partial update — only that command's TOC entry is
|
|
203
|
+
added or updated; all other entries are preserved as-is
|
|
204
|
+
|
|
205
|
+
## Gathering Input
|
|
206
|
+
|
|
207
|
+
The specification is driven by **four input sources** read from the project's context files.
|
|
208
|
+
The skill does NOT ask the user for prompts, config, packaging, or other choices — it
|
|
209
|
+
**determines** these automatically from the context.
|
|
210
|
+
|
|
211
|
+
### Input 1: Application Name (from CLAUDE.md)
|
|
212
|
+
|
|
213
|
+
From CLAUDE.md (already loaded in context), locate the target application under the
|
|
214
|
+
**Custom Applications** section. Extract:
|
|
215
|
+
|
|
216
|
+
- **Application name**: The section heading (e.g., "My Tool", "Deploy CLI")
|
|
217
|
+
- **Binary name**: The kebab-case executable name (e.g., `my-tool`, `deploy`)
|
|
218
|
+
- **Application description**: The description paragraph below the heading
|
|
219
|
+
- **Target audiences**: The "Used by" or "Consumers" list
|
|
220
|
+
- **Dependencies**: The "Depends on" list — primary source for determining optional components
|
|
221
|
+
|
|
222
|
+
The application name is used to derive:
|
|
223
|
+
- **Package name**: kebab-case of the application name with `@scope/` prefix if scoped
|
|
224
|
+
- **Binary name**: The `bin` entry in `package.json`
|
|
225
|
+
- **Main TypeScript namespace**: PascalCase (e.g., `MyTool`)
|
|
226
|
+
|
|
227
|
+
### Input 2: User Stories (from PRD.md)
|
|
228
|
+
|
|
229
|
+
Read `<app_folder>/context/PRD.md`. This file contains all user stories organized by
|
|
230
|
+
command. Extract:
|
|
231
|
+
|
|
232
|
+
- **Commands**: Each `## Command: <name>` or `### <CommandName>` section
|
|
233
|
+
- **User stories per command**: Tagged items like `[USCLI00101] As a user, I want to...`
|
|
234
|
+
These define the functional requirements for each command's action handler and prompts
|
|
235
|
+
|
|
236
|
+
The user stories directly inform:
|
|
237
|
+
- Which arguments and options each command exposes
|
|
238
|
+
- What interactive prompts are shown (if any)
|
|
239
|
+
- What output the command produces (table, JSON, plain text)
|
|
240
|
+
- Which service methods are called
|
|
241
|
+
|
|
242
|
+
**Important:** Items with strikethrough (`~~text~~`) are deprecated. List them in the
|
|
243
|
+
"Removed / Replaced" subsection of the traceability table. Carry version tags through
|
|
244
|
+
to the generated specification's traceability section.
|
|
245
|
+
|
|
246
|
+
### Input 3: Non-Functional Requirements (from PRD.md)
|
|
247
|
+
|
|
248
|
+
Within the same `PRD.md`, each command has a `### Non Functional Requirement` section
|
|
249
|
+
with tagged items like `[NFRCLI0120]`. These inform:
|
|
250
|
+
|
|
251
|
+
- Output format requirements (JSON, table, plain text, `--output` flag)
|
|
252
|
+
- Performance constraints (timeout, caching)
|
|
253
|
+
- Security requirements (credential storage, token handling)
|
|
254
|
+
- Platform constraints (Windows compatibility, PATH requirements)
|
|
255
|
+
|
|
256
|
+
### Input 4: Command Model (from model/ folder)
|
|
257
|
+
|
|
258
|
+
Read `<app_folder>/context/model/MODEL.md` first as the index, then read the individual
|
|
259
|
+
command model files in each command subfolder.
|
|
260
|
+
|
|
261
|
+
**MODEL.md** provides:
|
|
262
|
+
- Summary table of all commands with argument/option counts
|
|
263
|
+
- Links to each command's detailed model files
|
|
264
|
+
|
|
265
|
+
**Per-command files** (e.g., `model/deploy/model.md`):
|
|
266
|
+
- Complete argument definitions with types and descriptions
|
|
267
|
+
- Option definitions with flags, types, defaults
|
|
268
|
+
- Config keys read or written by this command
|
|
269
|
+
- External services or APIs called
|
|
270
|
+
|
|
271
|
+
The command model directly maps to:
|
|
272
|
+
- `Command` argument and option declarations in Commander.js
|
|
273
|
+
- Zod schemas for config validation
|
|
274
|
+
- Service interface method signatures
|
|
275
|
+
- `--help` text content
|
|
276
|
+
|
|
277
|
+
## PRD.md Extended Sections
|
|
278
|
+
|
|
279
|
+
Before determining optional components, check PRD.md for the following extended sections:
|
|
280
|
+
|
|
281
|
+
### Architecture Principle Extraction
|
|
282
|
+
|
|
283
|
+
If PRD.md contains an `# Architecture Principle` section, extract patterns that affect CLI decisions:
|
|
284
|
+
|
|
285
|
+
| Pattern to Extract | How It Influences the Specification |
|
|
286
|
+
|---|---|
|
|
287
|
+
| "Container based deployment" | Include Dockerfile section; favor environment variables over config files |
|
|
288
|
+
| "Event-driven" | CLI may need webhook listeners or polling patterns |
|
|
289
|
+
| Async patterns (polling, batch, daemon) | Inform command handler async strategies |
|
|
290
|
+
|
|
291
|
+
If the section is absent, proceed with existing detection.
|
|
292
|
+
|
|
293
|
+
### High Level Process Flow Extraction
|
|
294
|
+
|
|
295
|
+
If PRD.md contains a `# High Level Process Flow` section:
|
|
296
|
+
1. Process flows describing CLI-initiated operations inform command action handler sequences
|
|
297
|
+
2. Each flow step can emit a spinner/progress update
|
|
298
|
+
3. Error handling chains follow the flow's error paths
|
|
299
|
+
|
|
300
|
+
If the section is absent, derive command flow from user stories only (existing behavior).
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Determining Optional Components
|
|
305
|
+
|
|
306
|
+
Instead of asking the user, the skill determines optional components by analyzing the
|
|
307
|
+
dependencies and requirements in `CLAUDE.md` and cross-referencing with `PRD.md` NFRs.
|
|
308
|
+
|
|
309
|
+
### Prompts Detection
|
|
310
|
+
|
|
311
|
+
| Content Pattern | Prompts Selection |
|
|
312
|
+
|---|---|
|
|
313
|
+
| NFRs mention "interactive", "ask user", "prompt for", "wizard" | Prompts = yes |
|
|
314
|
+
| User stories describe `--interactive` mode or guided setup | Prompts = yes |
|
|
315
|
+
| User stories describe `init`, `setup`, `configure` commands | Prompts = yes |
|
|
316
|
+
| All inputs are non-interactive flags | Prompts = no |
|
|
317
|
+
|
|
318
|
+
### User Config Detection
|
|
319
|
+
|
|
320
|
+
| Content Pattern | User Config Selection |
|
|
321
|
+
|---|---|
|
|
322
|
+
| NFRs mention "remember", "save preference", "user setting", "persist" | User Config = yes |
|
|
323
|
+
| Commands like `config set`, `config get`, `login`, `logout` exist | User Config = yes |
|
|
324
|
+
| NFRs mention "API key", "token storage", "credential" | User Config = yes |
|
|
325
|
+
| No persistent state needed | User Config = no |
|
|
326
|
+
|
|
327
|
+
### Project Config Detection
|
|
328
|
+
|
|
329
|
+
| Content Pattern | Project Config Selection |
|
|
330
|
+
|---|---|
|
|
331
|
+
| NFRs mention "project configuration", "workspace config", "per-project" | Project Config = yes |
|
|
332
|
+
| A config file like `.mytoolrc`, `mytool.config.js`, or `package.json#mytool` is referenced | Project Config = yes |
|
|
333
|
+
| Tool operates at project/workspace level | Project Config = yes |
|
|
334
|
+
| Tool is purely global/user-scoped | Project Config = no |
|
|
335
|
+
|
|
336
|
+
### Local Database Detection
|
|
337
|
+
|
|
338
|
+
| Content Pattern | Local Database Selection |
|
|
339
|
+
|---|---|
|
|
340
|
+
| NFRs mention "run history", "execution log", "audit trail", "activity log" | Local Database = yes |
|
|
341
|
+
| NFRs mention "cache", "local cache", "offline", "sync state", "last sync" | Local Database = yes |
|
|
342
|
+
| User stories describe `history`, `log`, `list runs`, `show recent` commands | Local Database = yes |
|
|
343
|
+
| User stories describe tracking multiple entities of the same type locally | Local Database = yes |
|
|
344
|
+
| NFRs mention "retain for X days", "auto-prune", "retention policy" | Local Database = yes |
|
|
345
|
+
| Data needs filtering, sorting, or aggregation beyond a simple list | Local Database = yes |
|
|
346
|
+
| All persistent data fits in simple key-value pairs (use `conf` instead) | Local Database = no |
|
|
347
|
+
|
|
348
|
+
> **Local Database vs `conf`:** If the data has multiple rows, grows over time, needs
|
|
349
|
+
> querying, or involves relationships — use SQLite. If it is a handful of user
|
|
350
|
+
> preferences or a single token — use `conf`.
|
|
351
|
+
|
|
352
|
+
### Shell Execution Detection
|
|
353
|
+
|
|
354
|
+
| Content Pattern | Shell Execution Selection |
|
|
355
|
+
|---|---|
|
|
356
|
+
| NFRs mention "run command", "execute", "spawn", "shell", "subprocess" | Shell Execution = yes |
|
|
357
|
+
| Commands orchestrate other CLI tools (git, docker, npm, etc.) | Shell Execution = yes |
|
|
358
|
+
| Build/deploy commands that invoke external binaries | Shell Execution = yes |
|
|
359
|
+
|
|
360
|
+
### HTTP Client Detection
|
|
361
|
+
|
|
362
|
+
| Content Pattern | HTTP Client Selection |
|
|
363
|
+
|---|---|
|
|
364
|
+
| CLAUDE.md "Depends on" references any REST API or web service | HTTP Client = yes |
|
|
365
|
+
| NFRs mention "API call", "webhook", "REST", "HTTP", "fetch" | HTTP Client = yes |
|
|
366
|
+
| Commands interact with cloud providers, registries, or dashboards | HTTP Client = yes |
|
|
367
|
+
|
|
368
|
+
### Auto-Update Detection
|
|
369
|
+
|
|
370
|
+
| Content Pattern | Auto-Update Selection |
|
|
371
|
+
|---|---|
|
|
372
|
+
| NFRs mention "notify of updates", "check for new version", "self-update" | Auto-update = yes |
|
|
373
|
+
| Application is distributed via npm or GitHub releases | Auto-update = yes (default) |
|
|
374
|
+
| Internal tool used only within a controlled environment | Auto-update = no |
|
|
375
|
+
|
|
376
|
+
### Binary Packaging Detection
|
|
377
|
+
|
|
378
|
+
| Content Pattern | Binary Packaging Selection |
|
|
379
|
+
|---|---|
|
|
380
|
+
| CLAUDE.md mentions "standalone binary", "no Node.js required", "self-contained" | Binary Packaging = yes |
|
|
381
|
+
| Target users are unlikely to have Node.js installed | Binary Packaging = yes |
|
|
382
|
+
| Distribution via GitHub releases, Homebrew, or Chocolatey is mentioned | Binary Packaging = yes |
|
|
383
|
+
| Published to npm for developer toolchain use | Binary Packaging = no (npm distribution only) |
|
|
384
|
+
|
|
385
|
+
### Async Pattern Detection
|
|
386
|
+
|
|
387
|
+
Three sub-types are detected independently. A single application may use more than one.
|
|
388
|
+
|
|
389
|
+
#### Polling Detection
|
|
390
|
+
|
|
391
|
+
| Content Pattern | Polling Selection |
|
|
392
|
+
|---|---|
|
|
393
|
+
| User stories describe `--watch`, `--follow`, `--wait`, `--poll` flags | Polling = yes |
|
|
394
|
+
| NFRs say "wait until complete", "follow progress", "tail status" | Polling = yes |
|
|
395
|
+
| Commands trigger async operations that have a terminal state (success/failed) | Polling = yes |
|
|
396
|
+
| All operations complete synchronously within the API call | Polling = no |
|
|
397
|
+
|
|
398
|
+
#### Inline Batch Detection
|
|
399
|
+
|
|
400
|
+
| Content Pattern | Inline Batch Selection |
|
|
401
|
+
|---|---|
|
|
402
|
+
| User stories describe processing "all records", "all items", "bulk import/export" | Inline Batch = yes |
|
|
403
|
+
| NFRs mention `--concurrency`, parallel processing, rate limiting | Inline Batch = yes |
|
|
404
|
+
| Commands iterate over a potentially large collection (files, API resources, DB rows) | Inline Batch = yes |
|
|
405
|
+
| NFRs mention "skip errors", "continue on failure", "bail on first error" | Inline Batch = yes |
|
|
406
|
+
| NFRs mention "resume", "checkpoint", "skip already processed" | Inline Batch = yes (+ Local Database) |
|
|
407
|
+
| Processing is always a single item | Inline Batch = no |
|
|
408
|
+
|
|
409
|
+
#### Background Daemon Detection
|
|
410
|
+
|
|
411
|
+
| Content Pattern | Background Daemon Selection |
|
|
412
|
+
|---|---|
|
|
413
|
+
| User stories describe `daemon start`, `daemon stop`, `daemon status` commands | Background Daemon = yes |
|
|
414
|
+
| NFRs mention "background process", "persistent watcher", "always-on agent" | Background Daemon = yes |
|
|
415
|
+
| User stories describe a `worker` or `watcher` sub-command group | Background Daemon = yes |
|
|
416
|
+
| NFRs mention "detach", "run in background", "PID file" | Background Daemon = yes |
|
|
417
|
+
| All operations complete within a single command invocation | Background Daemon = no |
|
|
418
|
+
|
|
419
|
+
> **Async pattern vs User Config:** Any application with a Background Daemon also
|
|
420
|
+
> requires User Config = yes (to store the PID). The skill must force this
|
|
421
|
+
> dependency automatically when Background Daemon is detected.
|
|
422
|
+
|
|
423
|
+
### Table Output Detection
|
|
424
|
+
|
|
425
|
+
| Content Pattern | Table Output Selection |
|
|
426
|
+
|---|---|
|
|
427
|
+
| Commands produce list output (resources, records, results) | Table Output = yes |
|
|
428
|
+
| NFRs mention "tabular", "list view", "columns" | Table Output = yes |
|
|
429
|
+
|
|
430
|
+
### Summary of Determination
|
|
431
|
+
|
|
432
|
+
After analyzing all inputs, produce a determination summary before generating the spec:
|
|
433
|
+
|
|
434
|
+
```
|
|
435
|
+
Optional Component Determination:
|
|
436
|
+
- Prompts: yes (from PRD.md → init command has interactive wizard)
|
|
437
|
+
- User Config: yes (from PRD.md → login command stores API token)
|
|
438
|
+
- Project Config: yes (from PRD.md → per-project .mytoolrc support)
|
|
439
|
+
- Local Database: yes (from PRD.md → history command lists past runs)
|
|
440
|
+
- Async - Polling: yes (from PRD.md → deploy --watch flag)
|
|
441
|
+
- Async - Inline Batch: yes (from PRD.md → sync --all processes 1000s of items)
|
|
442
|
+
- Async - Daemon: no
|
|
443
|
+
- Shell Execution: no
|
|
444
|
+
- HTTP Client: yes (from CLAUDE.md → depends on My API)
|
|
445
|
+
- Auto-update: yes (default for npm-distributed tool)
|
|
446
|
+
- Binary Packaging: no (npm distribution only)
|
|
447
|
+
- Table Output: yes (from PRD.md → list commands produce tabular output)
|
|
448
|
+
- Banner/Box UI: no
|
|
449
|
+
- File Operations: no
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
If the user disagrees with any determination, allow them to override before proceeding.
|
|
453
|
+
|
|
454
|
+
## Generating the Specification
|
|
455
|
+
|
|
456
|
+
Once inputs are gathered and optional components are determined, generate the specification
|
|
457
|
+
as a **multi-file output split by command**. Read the spec template at
|
|
458
|
+
`references/spec-template.md` for the exact structure and content of each section.
|
|
459
|
+
The template is the authoritative guide — follow it closely.
|
|
460
|
+
|
|
461
|
+
The specification is split into two categories:
|
|
462
|
+
|
|
463
|
+
1. **Root `SPECIFICATION.md`** — Shared infrastructure: `package.json`, TypeScript config,
|
|
464
|
+
build tooling, CLI entry point, shared services, UI utilities, config management,
|
|
465
|
+
error handling, testing strategy, and packaging.
|
|
466
|
+
2. **Per-command `<command-name>/SPEC.md`** — Each command gets its own folder with a
|
|
467
|
+
self-contained specification covering argument/option definitions, service methods,
|
|
468
|
+
prompt flows, and output formatting.
|
|
469
|
+
|
|
470
|
+
**Important:** The generated spec must use **real application data** from the context files:
|
|
471
|
+
|
|
472
|
+
- **Commands** must use the actual command names from PRD.md (e.g., `init`, `deploy`, `status`)
|
|
473
|
+
- **Arguments and options** must match the actual definitions in `model/<command>/model.md`
|
|
474
|
+
- **Service methods** must map to the actual user stories
|
|
475
|
+
- **Config keys** must match what the model defines
|
|
476
|
+
- **Version tags** on every user story ID, NFR ID, constraint ID
|
|
477
|
+
- **Removed / Replaced items** listed for deprecated items
|
|
478
|
+
|
|
479
|
+
### Output Structure
|
|
480
|
+
|
|
481
|
+
```
|
|
482
|
+
<app_folder>/context/specification/
|
|
483
|
+
├── SPECIFICATION.md ↠Shared infrastructure + TOC
|
|
484
|
+
├── init/
|
|
485
|
+
│ └── SPEC.md ↠Command blueprint for 'init'
|
|
486
|
+
├── deploy/
|
|
487
|
+
│ └── SPEC.md ↠Command blueprint for 'deploy'
|
|
488
|
+
├── config/
|
|
489
|
+
│ └── SPEC.md ↠Command blueprint for 'config'
|
|
490
|
+
└── ... ↠One folder per command from PRD.md
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
### What Goes in `SPECIFICATION.md` (Root)
|
|
494
|
+
|
|
495
|
+
#### 1. Project Overview
|
|
496
|
+
Application metadata, description, tech stack summary, binary name, target platforms,
|
|
497
|
+
the complete command list, and distribution strategy.
|
|
498
|
+
|
|
499
|
+
#### 2. package.json Configuration
|
|
500
|
+
Complete `package.json` with `"type": "module"`, `bin` entry, `files`, `engines`,
|
|
501
|
+
all runtime dependencies (core + selected conditional), all `devDependencies`, and `scripts`
|
|
502
|
+
(dev, build, typecheck, test, lint, plus platform-specific pkg scripts if Binary Packaging = yes).
|
|
503
|
+
|
|
504
|
+
#### 3. TypeScript & Build Configuration
|
|
505
|
+
Complete `tsconfig.json` targeting ESM. Complete `tsup.config.ts` with shebang injection,
|
|
506
|
+
ESM format, and conditional sourcemap/minify for production. ESLint configuration.
|
|
507
|
+
|
|
508
|
+
#### 3a. Application Version Configuration
|
|
509
|
+
The `package.json` `version` field MUST be set to the version value derived from the
|
|
510
|
+
version argument provided during skill invocation (e.g., `1.0.3`). If multiple versions
|
|
511
|
+
were provided, use the highest one.
|
|
512
|
+
|
|
513
|
+
Commander.js uses `package.json` version automatically for `--version` output. The CLI
|
|
514
|
+
entry point (`src/cli.ts`) must call `.version(packageJson.version)` on the Commander
|
|
515
|
+
program instance so that `<tool> --version` prints the correct version.
|
|
516
|
+
|
|
517
|
+
The version MUST also be included in JSON output when `--json` flag is used (e.g.,
|
|
518
|
+
`{"version": "1.0.3", "data": {...}}`).
|
|
519
|
+
|
|
520
|
+
#### 3b. `.env` File Generation from ENVIRONMENT.md
|
|
521
|
+
Generate a `.env` file at the project root by reading `ENVIRONMENT.md` from the project root.
|
|
522
|
+
The `.env` file maps ENVIRONMENT.md credential and platform values to the environment variable
|
|
523
|
+
names used by the CLI application. The spec must define the complete `.env` content with
|
|
524
|
+
actual values from ENVIRONMENT.md.
|
|
525
|
+
|
|
526
|
+
**Process:**
|
|
527
|
+
1. Read `ENVIRONMENT.md` from the project root
|
|
528
|
+
2. Extract credential values from `ENVIRONMENT.md` (`# Supporting 3rd Party Applications`
|
|
529
|
+
and `# External Services` for API hosts, ports, tokens); read any toolchain paths
|
|
530
|
+
(e.g., Node.js) from `DEVTOOL.md`
|
|
531
|
+
3. Map each value to the corresponding environment variable name used by the CLI
|
|
532
|
+
4. Generate the `.env` file with `KEY=value` pairs
|
|
533
|
+
|
|
534
|
+
**Example `.env` output (derived from ENVIRONMENT.md):**
|
|
535
|
+
```properties
|
|
536
|
+
# API
|
|
537
|
+
API_BASE_URL=http://localhost:8080/api/v1
|
|
538
|
+
API_KEY=
|
|
539
|
+
|
|
540
|
+
# Platform
|
|
541
|
+
NODE_HOME=C:\nvm4w\nodejs
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
**Rules:**
|
|
545
|
+
- Only include variables that are actually used by the application (via `process.env`)
|
|
546
|
+
- Use actual values from ENVIRONMENT.md — never use placeholders or `TODO`
|
|
547
|
+
- If ENVIRONMENT.md does not exist or a value is not found, use sensible defaults for local
|
|
548
|
+
development (e.g., `localhost`, default ports)
|
|
549
|
+
- The `.env` file must be loaded using `dotenv` (add as a dependency if not already present)
|
|
550
|
+
- The `.env` file is gitignored
|
|
551
|
+
|
|
552
|
+
#### 4. Application Entry Point
|
|
553
|
+
`src/cli.ts` — the Commander.js `Program` setup: name, description, version, global options
|
|
554
|
+
(`--verbose`, `--json`, `--no-color`), command registration imports, and `program.parse()`.
|
|
555
|
+
See `references/command-patterns.md` for the root program setup, global option propagation
|
|
556
|
+
pattern, and async error handling with `parseAsync`.
|
|
557
|
+
|
|
558
|
+
#### 5. Project Directory Structure
|
|
559
|
+
Full `src/` directory tree with all files, named after actual commands and services
|
|
560
|
+
from the context.
|
|
561
|
+
|
|
562
|
+
#### 6. Shared Types
|
|
563
|
+
`src/types/index.ts` — all shared TypeScript interfaces and type aliases used across
|
|
564
|
+
commands and services.
|
|
565
|
+
|
|
566
|
+
#### 7. Terminal UI Utilities
|
|
567
|
+
- `src/ui/logger.ts` — chalk-based logger with `info`, `success`, `warn`, `error`,
|
|
568
|
+
`debug` (gated on `--verbose`) methods
|
|
569
|
+
- `src/ui/spinner.ts` — ora wrapper with typed start/succeed/fail/stop helpers
|
|
570
|
+
- `src/ui/table.ts` — cli-table3 wrapper *(conditional on Table Output = yes)*
|
|
571
|
+
- `src/ui/output.ts` — Unified output handler respecting `--json` flag
|
|
572
|
+
|
|
573
|
+
#### 8. Error Handling
|
|
574
|
+
`src/errors.ts` — Base `CliError` class with exit code mapping. `handleError()` function
|
|
575
|
+
used in every command `action` handler to catch, format, and exit cleanly.
|
|
576
|
+
|
|
577
|
+
#### 9. User Configuration Management *(conditional — include only if User Config = yes)*
|
|
578
|
+
`src/config/user.config.ts` — `conf` setup with schema (Zod), typed accessors, and
|
|
579
|
+
migration strategy. Key names, default values, and OS storage paths.
|
|
580
|
+
See `references/config-patterns.md`.
|
|
581
|
+
|
|
582
|
+
#### 10. Project Configuration Management *(conditional — include only if Project Config = yes)*
|
|
583
|
+
`src/config/project.config.ts` — `cosmiconfig` loader with Zod validation. Config file
|
|
584
|
+
search path, supported formats, and merge strategy with defaults.
|
|
585
|
+
See `references/config-patterns.md`.
|
|
586
|
+
|
|
587
|
+
#### 11. HTTP Client Setup *(conditional — include only if HTTP Client = yes)*
|
|
588
|
+
`src/services/http.client.ts` — `got` instance with base URL, auth header injection,
|
|
589
|
+
retry configuration, and typed error handling.
|
|
590
|
+
|
|
591
|
+
#### 12. Shell Execution Utilities *(conditional — include only if Shell Execution = yes)*
|
|
592
|
+
`src/utils/shell.ts` — `execa` wrapper with logging, timeout, and error handling.
|
|
593
|
+
|
|
594
|
+
#### 13. Auto-Update Notifier *(conditional — include only if Auto-update = yes)*
|
|
595
|
+
`src/utils/updater.ts` — `update-notifier` integration called once at CLI startup with
|
|
596
|
+
non-blocking async check.
|
|
597
|
+
|
|
598
|
+
#### 14. Testing Strategy
|
|
599
|
+
Vitest configuration, command testing patterns with `process.argv` mocking, service unit
|
|
600
|
+
testing, config testing with temp directories.
|
|
601
|
+
See `references/testing-patterns.md`.
|
|
602
|
+
|
|
603
|
+
#### 15. Packaging & Distribution *(conditional — include only if Binary Packaging = yes)*
|
|
604
|
+
`tsup` build pipeline, `@yao-pkg/pkg` configuration, platform targets, npm scripts for
|
|
605
|
+
each platform binary, GitHub Actions release workflow stub.
|
|
606
|
+
See `references/packaging-patterns.md`.
|
|
607
|
+
|
|
608
|
+
**For npm-only distribution:** `package.json` `files`, `bin`, `engines`, `prepublishOnly`
|
|
609
|
+
script, `.npmignore`, semantic versioning guidance.
|
|
610
|
+
|
|
611
|
+
#### 16. Local Database *(conditional — include only if Local Database = yes)*
|
|
612
|
+
`src/db/schema.ts` — Drizzle table definitions (all entity tables derived from model files).
|
|
613
|
+
`src/db/client.ts` — `better-sqlite3` singleton with WAL mode, foreign keys, and
|
|
614
|
+
automatic migration runner on first open.
|
|
615
|
+
`src/db/path.ts` — `env-paths` based OS data directory resolution.
|
|
616
|
+
`src/db/repositories/` — One repository class per entity exposing typed CRUD and query
|
|
617
|
+
methods. `drizzle.config.ts`, `drizzle/` migration folder, and `db:generate` / `db:migrate`
|
|
618
|
+
/ `db:studio` npm scripts.
|
|
619
|
+
See `references/database-patterns.md`.
|
|
620
|
+
|
|
621
|
+
#### 17. Async Patterns *(conditional — include only if any async pattern is detected)*
|
|
622
|
+
|
|
623
|
+
Include only the sub-sections that apply. Multiple sub-sections may be included together.
|
|
624
|
+
|
|
625
|
+
**17a. Shared Signal Handling** *(include whenever any async pattern is yes)*
|
|
626
|
+
`src/utils/signal.ts` — `onSignal(cleanupFn)` utility that registers SIGINT and SIGTERM
|
|
627
|
+
handlers, runs the cleanup function, then exits with code 130 (Ctrl+C) or 0 (SIGTERM).
|
|
628
|
+
Used by polling loops, batch processors, and the daemon runner to ensure Ctrl+C always
|
|
629
|
+
produces a clean exit rather than a Node.js stack trace.
|
|
630
|
+
|
|
631
|
+
**17b. Polling** *(conditional — include only if Polling = yes)*
|
|
632
|
+
`src/utils/poll.ts` — `poll<T>(options)` function with configurable interval, timeout,
|
|
633
|
+
spinner integration, and `onTick` callback for dynamic status text. Command handlers
|
|
634
|
+
pass `--watch` / `--follow` / `--wait` flags down to the poll utility. Non-watch invocation
|
|
635
|
+
(fire-and-forget) must remain supported when the flag is absent.
|
|
636
|
+
See `references/async-patterns.md`.
|
|
637
|
+
|
|
638
|
+
**17c. Inline Batch Processing** *(conditional — include only if Inline Batch = yes)*
|
|
639
|
+
`src/utils/batch.ts` — `runBatch<TInput, TOutput>(options)` function with configurable
|
|
640
|
+
concurrency, bail-on-error mode, per-item error collection, and `onProgress` callback.
|
|
641
|
+
`src/ui/progress.ts` — `ProgressBar` wrapper over ora showing `[percent%] n/total — ETA Xs`.
|
|
642
|
+
When `Local Database = yes`, include the resume pattern: services filter out already-processed
|
|
643
|
+
IDs from the item list by querying the repository before the batch starts.
|
|
644
|
+
See `references/async-patterns.md`.
|
|
645
|
+
|
|
646
|
+
**17d. Background Daemon** *(conditional — include only if Background Daemon = yes)*
|
|
647
|
+
`src/daemon/runner.ts` — `runDaemon()` function implementing the daemon's event loop;
|
|
648
|
+
called when the process detects `MY_TOOL_DAEMON_MODE=1` in the environment before
|
|
649
|
+
Commander parses arguments.
|
|
650
|
+
`src/services/daemon.service.ts` — `DaemonManager` class with `start()` (spawn detached),
|
|
651
|
+
`stop()` (SIGTERM + timeout + SIGKILL), `isRunning()` (signal-0 check), `getStatus()`,
|
|
652
|
+
and `getRecentLogs()`. PID stored in `conf` (requires User Config = yes).
|
|
653
|
+
`src/commands/daemon/index.ts` — `start`, `stop`, `status`, `logs` sub-commands.
|
|
654
|
+
See `references/async-patterns.md`.
|
|
655
|
+
|
|
656
|
+
### What Goes in Each `<command-name>/SPEC.md` (Per-Command)
|
|
657
|
+
|
|
658
|
+
For EACH command from PRD.md, create a folder named after the command (kebab-case) and
|
|
659
|
+
generate a `SPEC.md` inside it. Each file is **self-contained** — a coding agent can
|
|
660
|
+
implement the command after the shared infrastructure is in place.
|
|
661
|
+
|
|
662
|
+
Each command SPEC.md must include:
|
|
663
|
+
|
|
664
|
+
- **Header** with command name and back-reference to root `SPECIFICATION.md`
|
|
665
|
+
- **Traceability**: user story IDs, NFR IDs, constraint IDs
|
|
666
|
+
- **Command definition**: full Commander.js `.command()` chain with all arguments,
|
|
667
|
+
options, and description strings
|
|
668
|
+
- **Argument & Option contracts**: Zod schema for validation, complete option flag table
|
|
669
|
+
- **Prompt flow** *(conditional)*: `@inquirer/prompts` sequence for interactive mode
|
|
670
|
+
- **Service interface**: methods this command calls with TypeScript signatures
|
|
671
|
+
- **Service implementation**: full business logic, no terminal I/O
|
|
672
|
+
- **Output contract**: exact structure for `--json` output and human-readable output,
|
|
673
|
+
including async output contracts if Polling or Inline Batch apply to this command
|
|
674
|
+
- **Error cases**: every error type, exit code, and user-facing message
|
|
675
|
+
- **Complete code samples** for every component
|
|
676
|
+
|
|
677
|
+
See `references/command-patterns.md` for the canonical command registration patterns
|
|
678
|
+
covering simple commands, sub-command groups, confirmation prompts, `--dry-run`,
|
|
679
|
+
tabular output, global option propagation, help text conventions, and exit code table.
|
|
680
|
+
|
|
681
|
+
## Changelog Append
|
|
682
|
+
|
|
683
|
+
After all specification files are successfully generated, append an entry to `CHANGELOG.md` in the application folder (`<app_folder>/CHANGELOG.md`):
|
|
684
|
+
|
|
685
|
+
1. Read `<app_folder>/CHANGELOG.md`. If it does not exist, create it with:
|
|
686
|
+
```markdown
|
|
687
|
+
# Changelog
|
|
688
|
+
|
|
689
|
+
- This file tracks all skill executions by version for this application.
|
|
690
|
+
- The highest version recorded here is the current application version.
|
|
691
|
+
- Skills MUST NOT execute for a version lower than the highest version in this file.
|
|
692
|
+
|
|
693
|
+
---
|
|
694
|
+
```
|
|
695
|
+
2. Search for a `## {version}` heading matching the current version.
|
|
696
|
+
3. If the section **exists**: append a new row to its table.
|
|
697
|
+
4. If the section **does not exist**: insert a new section after the `---` below the context header and before any existing `## vX.Y.Z` section (newest-first ordering), with a new table header and the first row.
|
|
698
|
+
5. Row format: `| {YYYY-MM-DD} | {application_name} | specgen-ts-cli | {module or "All"} | Generated TypeScript CLI technical specification |`
|
|
699
|
+
6. **Never modify or delete existing rows.**
|
|
700
|
+
|
|
701
|
+
## Output Format
|
|
702
|
+
|
|
703
|
+
```
|
|
704
|
+
<app_folder>/context/specification/
|
|
705
|
+
├── SPECIFICATION.md ↠Root: TOC + shared infrastructure
|
|
706
|
+
├── <command-1>/
|
|
707
|
+
│ └── SPEC.md ↠Self-contained command blueprint
|
|
708
|
+
├── <command-2>/
|
|
709
|
+
│ └── SPEC.md
|
|
710
|
+
└── <command-N>/
|
|
711
|
+
└── SPEC.md
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
**Sample code is mandatory.** Every component described in any spec file must include a
|
|
715
|
+
complete, self-explanatory code sample. The code must be continuous (no `// ...` gaps)
|
|
716
|
+
and usable as a direct reference by a coding agent.
|
|
717
|
+
|
|
718
|
+
## Constraints
|
|
719
|
+
|
|
720
|
+
These constraints are non-negotiable. Every code sample in the generated spec must follow
|
|
721
|
+
them.
|
|
722
|
+
|
|
723
|
+
### Universal Constraints
|
|
724
|
+
|
|
725
|
+
**Use ESM throughout.** The project sets `"type": "module"` in `package.json`. All
|
|
726
|
+
imports in TypeScript source use the `.js` extension (TypeScript resolves to `.ts`).
|
|
727
|
+
Never use `require()` or CommonJS `module.exports`.
|
|
728
|
+
|
|
729
|
+
**No `any` types.** Every function signature, variable, and generic must be explicitly
|
|
730
|
+
typed. Use `unknown` with runtime narrowing (Zod) instead of `any`.
|
|
731
|
+
|
|
732
|
+
**Constructor injection for services.** Services accept their dependencies (config, HTTP
|
|
733
|
+
client, logger) through the constructor. No global singletons imported directly in service
|
|
734
|
+
files. This enables clean unit testing with mocks.
|
|
735
|
+
|
|
736
|
+
**Commands must not contain business logic.** The command `action` handler is a thin
|
|
737
|
+
orchestrator: parse options → call service → format output → handle errors. All domain
|
|
738
|
+
logic lives in `src/services/`.
|
|
739
|
+
|
|
740
|
+
**Separate output from logic.** Service methods return typed data structures. The command
|
|
741
|
+
handler is responsible for formatting and printing. Services never call `console.log`
|
|
742
|
+
or manipulate terminal state.
|
|
743
|
+
|
|
744
|
+
**Always handle exit codes.** Every command `action` handler wraps its body in
|
|
745
|
+
`try/catch`. On error: print formatted message, call `process.exit(1)` (or the
|
|
746
|
+
appropriate code). On success: `process.exit(0)` is implicit.
|
|
747
|
+
|
|
748
|
+
**ESM import paths use `.js` extension.** In TypeScript source files:
|
|
749
|
+
```ts
|
|
750
|
+
import { UserConfig } from '../config/user.config.js' // ✓ correct
|
|
751
|
+
import { UserConfig } from '../config/user.config' // ✗ wrong
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
**All user-facing strings go through the logger or output module.** Never call
|
|
755
|
+
`console.log` directly in commands or services. Use `logger.info()`, `logger.error()`,
|
|
756
|
+
`output.print()`, etc.
|
|
757
|
+
|
|
758
|
+
**Zod for all external data.** Any data from config files, API responses, or CLI
|
|
759
|
+
arguments that crosses a system boundary must be parsed with a Zod schema before use.
|
|
760
|
+
|
|
761
|
+
**Use `@inquirer/prompts` not `inquirer`.** The modern scoped package is the officially
|
|
762
|
+
maintained version. Import individual prompt functions, not the legacy `inquirer` default.
|
|
763
|
+
|
|
764
|
+
### Conditional Constraints
|
|
765
|
+
|
|
766
|
+
**If Binary Packaging = yes:**
|
|
767
|
+
- Use dynamic `import()` for any modules not compatible with pkg's static analysis
|
|
768
|
+
- Avoid `__filename` / `__dirname` — use `import.meta.url` with `fileURLToPath`
|
|
769
|
+
- All asset files (templates, default configs) must be embedded via `pkg`'s `assets` config
|
|
770
|
+
|
|
771
|
+
**If User Config = yes:**
|
|
772
|
+
- Credentials and tokens must be stored using `conf` (uses OS keychain on macOS)
|
|
773
|
+
- Never write secrets to plain text files manually
|
|
774
|
+
- The `conf` schema must be defined with Zod and validated on read
|
|
775
|
+
|
|
776
|
+
**If Project Config = yes:**
|
|
777
|
+
- Config loading must be non-fatal if no config file is found (use defaults)
|
|
778
|
+
- Loaded config must be merged with defaults using a predictable precedence order:
|
|
779
|
+
CLI flags > environment variables > project config file > user config > hardcoded defaults
|
|
780
|
+
|
|
781
|
+
**If HTTP Client = yes:**
|
|
782
|
+
- All API calls must use the shared `got` instance (never raw `fetch` or `axios`)
|
|
783
|
+
- HTTP errors must be caught, parsed for `statusCode`, and rethrown as `CliError`
|
|
784
|
+
- Authentication tokens must come from the config system, never hardcoded
|
|
785
|
+
|
|
786
|
+
**If Local Database = yes:**
|
|
787
|
+
- All database access must go through repository classes — services never use `db` directly
|
|
788
|
+
- Repositories receive `DbClient` via constructor injection — no global `getDb()` calls
|
|
789
|
+
inside service files (only in the composition root `cli.ts` or service constructors)
|
|
790
|
+
- Every write statement (`insert`, `update`, `delete`) must call `.run()` to execute —
|
|
791
|
+
Drizzle returns a prepared statement object that is not automatically executed
|
|
792
|
+
- All multi-step writes that must succeed or fail together must use `db.transaction()`
|
|
793
|
+
- JSON columns must be serialised with `JSON.stringify` on insert and `JSON.parse` on
|
|
794
|
+
read — never store raw objects in `text` columns
|
|
795
|
+
- Migration files in `drizzle/` are committed to source control; never edit generated
|
|
796
|
+
SQL files after commit — always generate new ones via `drizzle-kit generate`
|
|
797
|
+
- The database file path must come from `getDatabasePath()` — never hardcode a path
|
|
798
|
+
|
|
799
|
+
**If any Async Pattern is yes (Polling, Inline Batch, or Background Daemon):**
|
|
800
|
+
- Every long-running loop MUST register an `onSignal` handler before entering the loop
|
|
801
|
+
and dispose it via the returned function when the loop exits normally
|
|
802
|
+
- Ctrl+C must NEVER produce a Node.js stack trace — the signal handler catches it,
|
|
803
|
+
runs cleanup, and calls `process.exit(130)`
|
|
804
|
+
- SIGTERM must exit cleanly with code `0` — it signals intentional shutdown
|
|
805
|
+
(e.g. `daemon stop`), not an error
|
|
806
|
+
|
|
807
|
+
**If Polling = yes:**
|
|
808
|
+
- Every command with a watch flag must also work without it (fire-and-forget behaviour
|
|
809
|
+
is always supported; `--watch` / `--follow` is additive)
|
|
810
|
+
- The polling timeout must be configurable via a `--timeout <seconds>` option; the
|
|
811
|
+
default (300s) is a maximum, not a guarantee
|
|
812
|
+
|
|
813
|
+
**If Inline Batch = yes:**
|
|
814
|
+
- Concurrency must be configurable via `--concurrency <n>` — never hardcode parallelism
|
|
815
|
+
- Both `--bail` (stop on first error) and the default (collect all errors, continue) must
|
|
816
|
+
be supported
|
|
817
|
+
- Exit code must be `1` when any items fail, even if the majority succeeded
|
|
818
|
+
- The `onProgress` callback updates the spinner — service code never touches ora directly
|
|
819
|
+
|
|
820
|
+
**If Background Daemon = yes:**
|
|
821
|
+
- The daemon process is the SAME binary launched with `MY_TOOL_DAEMON_MODE=1` in the
|
|
822
|
+
environment — never ship a separate daemon binary
|
|
823
|
+
- The daemon entry point check in `cli.ts` must appear BEFORE Commander parses `argv`,
|
|
824
|
+
so the daemon mode is invisible to all user-facing `--help` output
|
|
825
|
+
- PID storage requires User Config (`conf`) — Background Daemon detection automatically
|
|
826
|
+
forces User Config = yes in the determination summary
|
|
827
|
+
- `DaemonManager.isRunning()` must use signal-0 (`process.kill(pid, 0)`) to test
|
|
828
|
+
process liveness — never rely on PID alone (PIDs are reused by the OS)
|
|
829
|
+
|
|
830
|
+
## Principles Embedded in the Spec
|
|
831
|
+
|
|
832
|
+
### Always-Applicable Principles
|
|
833
|
+
- ESM-first TypeScript with strict mode (`"strict": true`)
|
|
834
|
+
- Thin command action handlers — orchestrate, don't implement
|
|
835
|
+
- Services are pure TypeScript — no CLI concerns, fully testable
|
|
836
|
+
- Single output module respects `--json` flag for machine-readable output
|
|
837
|
+
- Every command has `--help` text that matches the user stories
|
|
838
|
+
- Errors produce clean, human-friendly messages with non-zero exit codes
|
|
839
|
+
- Verbose mode (`--verbose`, `-v`) reveals internal steps via `logger.debug()`
|
|
840
|
+
- All file paths use `node:path` and `node:url` — no raw string concatenation
|
|
841
|
+
|
|
842
|
+
### Conditional Principles
|
|
843
|
+
- **If Prompts = yes:** Interactive and non-interactive modes are both supported. Every
|
|
844
|
+
prompt has a corresponding flag so the command can run non-interactively in CI.
|
|
845
|
+
- **If User Config = yes:** The `config` command exposes `get`, `set`, `list`, and
|
|
846
|
+
`reset` sub-commands for user-visible settings.
|
|
847
|
+
- **If Local Database = yes:** SQLite is the single source of truth for all structured
|
|
848
|
+
local data. `conf` remains for user preferences and tokens; SQLite is for anything
|
|
849
|
+
with multiple rows, history, or relational structure. The database opens and migrates
|
|
850
|
+
automatically on first command run — no manual `init-db` step required.
|
|
851
|
+
- **If Polling = yes:** Every watched command has a non-watch path that exits immediately.
|
|
852
|
+
The `poll()` utility owns all timing and spinner state; the command handler only
|
|
853
|
+
provides the `check` function and interprets the final result.
|
|
854
|
+
- **If Inline Batch = yes:** The `runBatch()` utility owns concurrency and error
|
|
855
|
+
collection; the service owns per-item logic; the command handler owns progress display
|
|
856
|
+
and final output. These three responsibilities must never be mixed.
|
|
857
|
+
- **If Background Daemon = yes:** The daemon runner (`runDaemon`) is a plain async
|
|
858
|
+
function — it has no Commander, no prompts, and no user interaction. Its only
|
|
859
|
+
interface is `MY_TOOL_DAEMON_MODE=1` (start) and SIGTERM (stop).
|
|
860
|
+
- **If Binary Packaging = yes:** The binary must work with zero Node.js dependency on the
|
|
861
|
+
target machine. Asset embedding and path resolution must be validated for each platform.
|