@captain_z/zsk 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +38 -3
  2. package/dist/bin.js +40 -1
  3. package/dist/bin.js.map +1 -1
  4. package/dist/commands/check.d.ts +4 -0
  5. package/dist/commands/check.js +157 -0
  6. package/dist/commands/check.js.map +1 -0
  7. package/dist/commands/config.d.ts +4 -0
  8. package/dist/commands/config.js +18 -0
  9. package/dist/commands/config.js.map +1 -0
  10. package/dist/commands/prep.d.ts +4 -0
  11. package/dist/commands/prep.js +27 -0
  12. package/dist/commands/prep.js.map +1 -0
  13. package/dist/commands/project-init.js +12 -11
  14. package/dist/commands/project-init.js.map +1 -1
  15. package/dist/core/config.d.ts +35 -0
  16. package/dist/core/config.js +191 -0
  17. package/dist/core/config.js.map +1 -0
  18. package/dist/core/raw-manifest.d.ts +21 -0
  19. package/dist/core/raw-manifest.js +53 -0
  20. package/dist/core/raw-manifest.js.map +1 -0
  21. package/package.json +3 -2
  22. package/templates/project-init/.issues/README.md +26 -0
  23. package/templates/project-init/.issues/_templates/issue.md +44 -0
  24. package/templates/project-init/.raws/README.md +15 -12
  25. package/templates/project-init/.raws/api-contracts/README.md +13 -0
  26. package/templates/project-init/.raws/design-assets/README.md +16 -0
  27. package/templates/project-init/.raws/manifest.json +4 -0
  28. package/templates/project-init/.raws/testing/README.md +10 -0
  29. package/templates/project-init/.zsk/schemas/module.schema.json +203 -0
  30. package/templates/project-init/.zsk/schemas/zsk-config.schema.json +246 -0
  31. package/templates/project-init/SYSTEM-SPEC.md +55 -0
  32. package/templates/project-init/docs/_module-index.md +7 -0
  33. package/templates/project-init/docs/_module-template/module.yaml +32 -0
  34. package/templates/project-init/docs/system/README.md +12 -0
  35. package/templates/project-init/zsk.config.yaml +50 -0
@@ -0,0 +1,191 @@
1
+ import { Ajv } from "ajv/dist/ajv.js";
2
+ import { readFile, readdir, access, stat } from "node:fs/promises";
3
+ import { isAbsolute, join, relative, resolve } from "node:path";
4
+ import YAML from "yaml";
5
+ import { resolveTemplatesRoot } from "./scaffolder.js";
6
+ const PROJECT_SCHEMA = "zsk-config.schema.json";
7
+ const MODULE_SCHEMA = "module.schema.json";
8
+ export async function checkProjectConfig(target) {
9
+ const root = resolve(target);
10
+ const issues = [];
11
+ const projectFile = join(root, "zsk.config.yaml");
12
+ const project = await readYaml(projectFile, issues);
13
+ const projectSchema = await readSchema(root, PROJECT_SCHEMA);
14
+ validateWithSchema(projectFile, project, projectSchema, issues);
15
+ const projectConfig = isObject(project) ? project : {};
16
+ const moduleFiles = await findModuleConfigFiles(root, projectConfig);
17
+ const moduleSchema = await readSchema(root, MODULE_SCHEMA);
18
+ for (const file of moduleFiles) {
19
+ const moduleConfig = await readYaml(file, issues);
20
+ validateWithSchema(file, moduleConfig, moduleSchema, issues);
21
+ validateModuleBoundaries(root, projectConfig, file, moduleConfig, issues);
22
+ }
23
+ validateProjectBoundaries(root, projectConfig, projectFile, issues);
24
+ return {
25
+ ok: issues.length === 0,
26
+ issues,
27
+ project,
28
+ moduleFiles,
29
+ };
30
+ }
31
+ export async function readProjectConfig(target) {
32
+ const file = join(resolve(target), "zsk.config.yaml");
33
+ const content = await readFile(file, "utf8");
34
+ const parsed = YAML.parse(content);
35
+ return isObject(parsed) ? parsed : {};
36
+ }
37
+ export async function findModuleConfigFiles(root, projectConfig) {
38
+ const docsRoot = resolvePath(root, projectConfig.modules?.root ?? "docs");
39
+ try {
40
+ const entries = await readdir(docsRoot, { withFileTypes: true });
41
+ const files = [];
42
+ for (const entry of entries) {
43
+ if (!entry.isDirectory())
44
+ continue;
45
+ if (entry.name.startsWith("_"))
46
+ continue;
47
+ if (entry.name === "system")
48
+ continue;
49
+ const file = join(docsRoot, entry.name, "module.yaml");
50
+ if (await exists(file))
51
+ files.push(file);
52
+ }
53
+ return files.sort();
54
+ }
55
+ catch {
56
+ return [];
57
+ }
58
+ }
59
+ export function formatConfigIssues(issues) {
60
+ return issues
61
+ .map((issue) => `${issue.file}${issue.path ? ` ${issue.path}` : ""}: ${issue.message}`)
62
+ .join("\n");
63
+ }
64
+ async function readYaml(file, issues) {
65
+ try {
66
+ const content = await readFile(file, "utf8");
67
+ return YAML.parse(content);
68
+ }
69
+ catch (error) {
70
+ issues.push({
71
+ file,
72
+ path: "",
73
+ message: error instanceof Error ? error.message : String(error),
74
+ });
75
+ return null;
76
+ }
77
+ }
78
+ async function readSchema(root, name) {
79
+ const local = join(root, ".zsk", "schemas", name);
80
+ if (await exists(local))
81
+ return JSON.parse(await readFile(local, "utf8"));
82
+ const templatesRoot = await resolveTemplatesRoot();
83
+ const bundled = join(templatesRoot, "project-init", ".zsk", "schemas", name);
84
+ return JSON.parse(await readFile(bundled, "utf8"));
85
+ }
86
+ function validateWithSchema(file, data, schema, issues) {
87
+ const ajv = new Ajv({ allErrors: true, strict: false });
88
+ const validate = ajv.compile(schema);
89
+ if (validate(data))
90
+ return;
91
+ for (const error of validate.errors ?? []) {
92
+ issues.push({
93
+ file,
94
+ path: formatSchemaPath(error),
95
+ message: error.message ?? "schema validation failed",
96
+ });
97
+ }
98
+ }
99
+ function validateProjectBoundaries(root, config, file, issues) {
100
+ const raws = config.paths?.raws ?? ".raws";
101
+ const docs = config.paths?.docs ?? "docs";
102
+ const issueRoot = config.paths?.issues ?? ".issues";
103
+ validateRelativeInside(root, raws, file, "/paths/raws", issues);
104
+ validateRelativeInside(root, docs, file, "/paths/docs", issues);
105
+ validateRelativeInside(root, issueRoot, file, "/paths/issues", issues);
106
+ const rawRoot = resolvePath(root, raws);
107
+ for (const [name, source] of Object.entries(config.sources ?? {})) {
108
+ if (!source)
109
+ continue;
110
+ if (source.kind === "local" && source.path) {
111
+ validateUnder(root, source.path, rawRoot, file, `/sources/${name}/path`, issues);
112
+ continue;
113
+ }
114
+ if ((source.kind === "script" || source.kind === "skill") && source.output) {
115
+ validateUnder(root, source.output, rawRoot, file, `/sources/${name}/output`, issues);
116
+ }
117
+ }
118
+ }
119
+ function validateModuleBoundaries(root, projectConfig, file, moduleData, issues) {
120
+ if (!isObject(moduleData))
121
+ return;
122
+ const moduleConfig = moduleData;
123
+ const docsRoot = resolvePath(root, projectConfig.paths?.docs ?? "docs");
124
+ const issueRoot = resolvePath(root, projectConfig.paths?.issues ?? ".issues");
125
+ if (moduleConfig.outputs?.docs) {
126
+ validateUnder(root, moduleConfig.outputs.docs, docsRoot, file, "/outputs/docs", issues);
127
+ }
128
+ if (moduleConfig.outputs?.issues) {
129
+ validateUnder(root, moduleConfig.outputs.issues, issueRoot, file, "/outputs/issues", issues);
130
+ }
131
+ }
132
+ function validateRelativeInside(root, value, file, path, issues) {
133
+ if (isAbsolute(value))
134
+ return;
135
+ const target = resolve(root, value);
136
+ if (isInside(root, target))
137
+ return;
138
+ issues.push({
139
+ file,
140
+ path,
141
+ message: "relative path must stay inside the project root",
142
+ });
143
+ }
144
+ function validateUnder(root, value, expectedRoot, file, path, issues) {
145
+ const target = resolvePath(root, value);
146
+ if (isInside(expectedRoot, target))
147
+ return;
148
+ issues.push({
149
+ file,
150
+ path,
151
+ message: `path must stay under ${expectedRoot}`,
152
+ });
153
+ }
154
+ function resolvePath(root, value) {
155
+ return isAbsolute(value) ? value : resolve(root, value);
156
+ }
157
+ function isInside(root, target) {
158
+ const rel = relative(root, target);
159
+ return rel === "" || (!rel.startsWith("..") && !isAbsolute(rel));
160
+ }
161
+ function formatSchemaPath(error) {
162
+ const path = error.instancePath || "/";
163
+ if (error.keyword === "required" && typeof error.params === "object") {
164
+ const missing = error.params.missingProperty;
165
+ if (missing)
166
+ return `${path === "/" ? "" : path}/${missing}`;
167
+ }
168
+ return path;
169
+ }
170
+ function isObject(value) {
171
+ return typeof value === "object" && value !== null && !Array.isArray(value);
172
+ }
173
+ async function exists(path) {
174
+ try {
175
+ await access(path);
176
+ return true;
177
+ }
178
+ catch {
179
+ return false;
180
+ }
181
+ }
182
+ export async function pathStat(path) {
183
+ try {
184
+ const info = await stat(path);
185
+ return { size: info.size };
186
+ }
187
+ catch {
188
+ return null;
189
+ }
190
+ }
191
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export type RawResourceRecord = {
2
+ provider: string;
3
+ kind: string;
4
+ path?: string;
5
+ output?: string;
6
+ exists: boolean;
7
+ size: number | null;
8
+ hash: string | null;
9
+ syncedAt: string;
10
+ method: "local" | "script" | "skill" | "manual";
11
+ };
12
+ export type RawManifest = {
13
+ version: number;
14
+ resources: RawResourceRecord[];
15
+ };
16
+ export declare function updateRawManifest(file: string, records: RawResourceRecord[]): Promise<void>;
17
+ export declare function describeResource(root: string, provider: string, source: {
18
+ kind?: string;
19
+ path?: string;
20
+ output?: string;
21
+ }): Promise<RawResourceRecord>;
@@ -0,0 +1,53 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFile, writeFile, mkdir, stat } from "node:fs/promises";
3
+ import { dirname, isAbsolute, resolve } from "node:path";
4
+ export async function updateRawManifest(file, records) {
5
+ await mkdir(dirname(file), { recursive: true });
6
+ const manifest = {
7
+ version: 1,
8
+ resources: records,
9
+ };
10
+ await writeFile(file, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
11
+ }
12
+ export async function describeResource(root, provider, source) {
13
+ const ref = source.path ?? source.output;
14
+ const fullPath = ref ? resolvePath(root, ref) : null;
15
+ const info = fullPath ? await safeStat(fullPath) : null;
16
+ return {
17
+ provider,
18
+ kind: source.kind ?? "local",
19
+ path: source.path,
20
+ output: source.output,
21
+ exists: Boolean(info),
22
+ size: info?.size ?? null,
23
+ hash: info && info.isFile ? await sha256(fullPath) : null,
24
+ syncedAt: new Date().toISOString(),
25
+ method: toMethod(source.kind),
26
+ };
27
+ }
28
+ function toMethod(kind) {
29
+ if (kind === "script")
30
+ return "script";
31
+ if (kind === "skill")
32
+ return "skill";
33
+ if (kind === "manual")
34
+ return "manual";
35
+ return "local";
36
+ }
37
+ async function safeStat(path) {
38
+ try {
39
+ const info = await stat(path);
40
+ return { size: info.size, isFile: info.isFile() };
41
+ }
42
+ catch {
43
+ return null;
44
+ }
45
+ }
46
+ async function sha256(path) {
47
+ const content = await readFile(path);
48
+ return createHash("sha256").update(content).digest("hex");
49
+ }
50
+ function resolvePath(root, value) {
51
+ return isAbsolute(value) ? value : resolve(root, value);
52
+ }
53
+ //# sourceMappingURL=raw-manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-manifest.js","sourceRoot":"","sources":["../../src/core/raw-manifest.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@captain_z/zsk",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "ZNorth Standard Kit — CLI installer for zsk skill bundles (npx @captain_z/zsk add)",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -15,10 +15,11 @@
15
15
  ],
16
16
  "dependencies": {
17
17
  "@clack/prompts": "^0.9.0",
18
+ "ajv": "^8.17.1",
18
19
  "commander": "^12.1.0",
19
20
  "picocolors": "^1.1.1",
20
21
  "yaml": "^2.7.0",
21
- "@captain_z/zsk-skills": "1.0.1"
22
+ "@captain_z/zsk-skills": "1.1.0"
22
23
  },
23
24
  "devDependencies": {
24
25
  "@types/node": "^22.10.0",
@@ -0,0 +1,26 @@
1
+ # Issues
2
+
3
+ `.issues/` stores local review findings, bug reports, screenshots, logs, reproduction evidence, and verification records created during project work.
4
+
5
+ ## Layout
6
+
7
+ ```text
8
+ .issues/
9
+ ├── README.md
10
+ ├── _templates/
11
+ │ └── issue.md
12
+ └── {module}/
13
+ └── BUG-0001-short-slug/
14
+ ├── issue.md
15
+ ├── assets/
16
+ └── debug-logs/
17
+ ```
18
+
19
+ ## Rules
20
+
21
+ - Keep one confirmed bug per `BUG-xxxx-short-slug/` directory.
22
+ - Group related bugs under the same module directory.
23
+ - Put bug-specific screenshots and runtime evidence under that bug's `assets/`.
24
+ - Put bug-specific console logs, test output, and investigation logs under that bug's `debug-logs/`.
25
+ - Do not place runtime screenshots, debug logs, or failed verification artifacts under `docs/`.
26
+ - Do not place local verification artifacts under `.raws/`.
@@ -0,0 +1,44 @@
1
+ # BUG-0000-short-description
2
+
3
+ ## Priority
4
+
5
+ P1
6
+
7
+ ## Module
8
+
9
+ `<module-id>`
10
+
11
+ ## Environment
12
+
13
+ - Date: YYYY-MM-DD
14
+ - Branch:
15
+ - URL:
16
+ - Command:
17
+ - Browser:
18
+ - Data source:
19
+
20
+ ## Reproduction Steps
21
+
22
+ 1.
23
+
24
+ ## Actual Result
25
+
26
+
27
+ ## Expected Result
28
+
29
+
30
+ ## Logs And Evidence
31
+
32
+ - `assets/<file>`:
33
+ - `debug-logs/<file>`:
34
+
35
+ ## Impact
36
+
37
+
38
+ ## Root Cause / Hypothesis
39
+
40
+
41
+ ## Status
42
+
43
+ - Status: Open
44
+ - Retest:
@@ -4,24 +4,26 @@
4
4
 
5
5
  ## 推荐内容
6
6
 
7
- | 文件 / 子目录 | 用途 | zsk skill 引用 |
7
+ | 文件 / 子目录 | 用途 | zsk 配置入口 |
8
8
  | --- | --- | --- |
9
- | `SRS.md` | 原始需求文档(Software Requirements Spec) | `{{config.paths.srs}}` |
10
- | `FIGMA-INDEX.md` | 模块 → Figma URL / node-id 索引 | `{{config.paths.figma_index}}` |
11
- | `api-contracts/` | 后端 API 契约(OpenAPI / GraphQL schema) | `{{config.paths.api_contracts}}` |
12
- | `design-assets/{module}/{snapshot}/` | Figma 快照(由 `zsk:ue-mcp` 产出) | `{{config.paths.design_assets}}` |
9
+ | `SRS.md` | 原始需求文档(Software Requirements Spec) | `zsk.config.yaml#sources.srs.path` |
10
+ | `FIGMA-INDEX.md` | 模块 → Figma URL / node-id 索引 | `zsk.config.yaml#sources.figma_index.path` |
11
+ | `api-contracts/` | 后端 API 契约(OpenAPI / GraphQL schema) | `zsk.config.yaml#sources.api_contracts.path` |
12
+ | `design-assets/{module}/{snapshot}/` | Figma 快照(由 `zsk:ue-mcp` 产出) | `zsk.config.yaml#sources.design_assets.path` |
13
+ | `testing/` | 原始测试用例、验收用例、提测测试包 | `docs/{module}/module.yaml` 的 `tests.raw_cases` |
14
+ | `manifest.json` | 资源同步清单,由 `zsk prep` / `zsk sync` 维护 | N/A |
13
15
 
14
16
  ## 消费路径
15
17
 
16
- skill 通过 `project-config.md` frontmatter `paths.*` 键找到本目录文件:
18
+ skill 通过 `zsk.config.yaml` `docs/{module}/module.yaml` 找到本目录文件:
17
19
 
18
20
  ```
19
- project-config.md:
20
- paths:
21
- srs: .raws/SRS.md
22
- figma_index: .raws/FIGMA-INDEX.md
23
- api_contracts: .raws/api-contracts
24
- design_assets: .raws/design-assets
21
+ zsk.config.yaml:
22
+ sources:
23
+ srs:
24
+ path: .raws/SRS.md
25
+ testing:
26
+ path: .raws/testing
25
27
  ```
26
28
 
27
29
  ## Git 状态建议
@@ -35,3 +37,4 @@ project-config.md:
35
37
  - **源文件不被 LLM 随意改写**:变更走人工/流程
36
38
  - **变更即新 snapshot**:Figma 更新→新 snapshot 目录,不覆盖历史
37
39
  - **编号锚稳定**:SRS 中的 `FR-001` / `US-001` / `AC-001` 一旦发布不改(仅废弃,合并/拆分留追踪)
40
+ - **测试用例是一等资产**:原始测试用例保存在 `.raws/testing/`,派生测试矩阵和自动化映射写入 `docs/{module}/`
@@ -0,0 +1,13 @@
1
+ # API Contracts
2
+
3
+ Store upstream API contracts here, grouped by service or provider.
4
+
5
+ Recommended layout:
6
+
7
+ ```text
8
+ .raws/api-contracts/
9
+ └── {service}/
10
+ └── contracts/
11
+ ```
12
+
13
+ Do not edit generated or upstream-owned contracts to match frontend assumptions. If a contract conflicts with SRS, test cases, or design assets, record an issue and resolve the decision in `docs/{module}/`.
@@ -0,0 +1,16 @@
1
+ # Design Assets
2
+
3
+ Store Figma, MCP, and design-source snapshots here.
4
+
5
+ Recommended layout:
6
+
7
+ ```text
8
+ .raws/design-assets/
9
+ └── {module}/
10
+ └── {snapshot}/
11
+ ├── description.md
12
+ ├── screenshot-*.png
13
+ └── raw/
14
+ ```
15
+
16
+ Treat each sync as a snapshot. Prefer adding a new snapshot over overwriting historical evidence.
@@ -0,0 +1,4 @@
1
+ {
2
+ "version": 1,
3
+ "resources": []
4
+ }
@@ -0,0 +1,10 @@
1
+ # Testing Sources
2
+
3
+ Store original test assets here:
4
+
5
+ - QA test cases
6
+ - acceptance spreadsheets or exports
7
+ - release test packs
8
+ - manually supplied validation scenarios
9
+
10
+ These are raw source facts. Derived scenario matrices and automated test mappings belong under `docs/{module}/`.