@captain_z/zsk 1.8.3 → 1.8.4
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/commands/add-flow.d.ts +3 -7
- package/dist/commands/add-flow.js +7 -59
- package/dist/commands/add-flow.js.map +1 -1
- package/dist/commands/add.js +25 -104
- package/dist/commands/add.js.map +1 -1
- package/dist/core/prepare-sync.d.ts +2 -31
- package/dist/core/prepare-sync.js +96 -128
- package/dist/core/prepare-sync.js.map +1 -1
- package/dist/core/profile-bundle-installation.d.ts +55 -0
- package/dist/core/profile-bundle-installation.js +170 -0
- package/dist/core/profile-bundle-installation.js.map +1 -0
- package/dist/core/source-snapshot-adapters.d.ts +59 -0
- package/dist/core/source-snapshot-adapters.js +82 -0
- package/dist/core/source-snapshot-adapters.js.map +1 -0
- package/dist/core/staffing-plan.js +52 -18
- package/dist/core/staffing-plan.js.map +1 -1
- package/dist/core/stage-clarity-verification.d.ts +31 -0
- package/dist/core/stage-clarity-verification.js +313 -0
- package/dist/core/stage-clarity-verification.js.map +1 -0
- package/dist/core/stage-quality-artifacts.d.ts +15 -0
- package/dist/core/stage-quality-artifacts.js +421 -0
- package/dist/core/stage-quality-artifacts.js.map +1 -0
- package/dist/core/stage-quality-contracts.d.ts +86 -0
- package/dist/core/stage-quality-contracts.js +2 -0
- package/dist/core/stage-quality-contracts.js.map +1 -0
- package/dist/core/stage-quality-criteria.d.ts +9 -0
- package/dist/core/stage-quality-criteria.js +323 -0
- package/dist/core/stage-quality-criteria.js.map +1 -0
- package/dist/core/stage-quality-rendering.d.ts +13 -0
- package/dist/core/stage-quality-rendering.js +122 -0
- package/dist/core/stage-quality-rendering.js.map +1 -0
- package/dist/core/stage-quality.d.ts +4 -59
- package/dist/core/stage-quality.js +39 -791
- package/dist/core/stage-quality.js.map +1 -1
- package/package.json +2 -2
- package/templates/module/frontend-module/design.md +10 -0
- package/templates/module/frontend-module/proposal.md +8 -0
- package/templates/module/frontend-module/spec.md +7 -0
- package/templates/project-init/.zsk/config.yaml +33 -0
- package/templates/project-init/.zsk/docs/PROJECT-CONFIG.md +43 -0
- package/templates/project-init/.zsk/docs/SYSTEM-SPEC.md +22 -2
- package/templates/project-init/.zsk/raws/index.md +16 -0
- package/templates/project-init/.zsk/raws/prepare/design/index.md +18 -0
- package/templates/project-init/.zsk/raws/prepare/index.md +33 -0
- package/templates/project-init/.zsk/raws/prepare/ux/index.md +19 -0
- package/templates/project-init/.zsk/roles.yaml +3 -3
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readFile, readdir, stat } from "node:fs/promises";
|
|
3
|
+
import { basename, dirname, extname, join, relative, resolve } from "node:path";
|
|
4
|
+
import { getWorkspacePath } from "./workspace-layout.js";
|
|
5
|
+
const MODULE_STAGES = new Set(["proposal", "spec", "design", "task", "coding", "fix", "smoke", "review", "ready", "verify", "acceptance", "archive"]);
|
|
6
|
+
const SPLITTABLE_MODULE_STAGES = new Set(["proposal", "spec", "design", "tasks"]);
|
|
7
|
+
const SKIPPED_REVIEW_TARGET_DIRS = new Set([
|
|
8
|
+
".auth",
|
|
9
|
+
".cache",
|
|
10
|
+
".git",
|
|
11
|
+
".next",
|
|
12
|
+
".turbo",
|
|
13
|
+
"coverage",
|
|
14
|
+
"dist",
|
|
15
|
+
"node_modules",
|
|
16
|
+
]);
|
|
17
|
+
const STAGE_INPUTS = {
|
|
18
|
+
prepare: [
|
|
19
|
+
{ key: "project-config", path: (config) => getWorkspacePath(config, "projectConfig") },
|
|
20
|
+
{ key: "system-spec", path: (config) => getWorkspacePath(config, "systemSpec") },
|
|
21
|
+
],
|
|
22
|
+
preproposal: [],
|
|
23
|
+
proposal: [
|
|
24
|
+
{ key: "project-config", path: (config) => getWorkspacePath(config, "projectConfig") },
|
|
25
|
+
{ key: "system-spec", path: (config) => getWorkspacePath(config, "systemSpec") },
|
|
26
|
+
{ key: "raw-manifest", path: (config) => getWorkspacePath(config, "rawsManifest") },
|
|
27
|
+
],
|
|
28
|
+
spec: [
|
|
29
|
+
{ key: "project-config", path: (config) => getWorkspacePath(config, "projectConfig") },
|
|
30
|
+
{ key: "system-spec", path: (config) => getWorkspacePath(config, "systemSpec") },
|
|
31
|
+
{ key: "proposal", moduleStage: "proposal" },
|
|
32
|
+
],
|
|
33
|
+
design: [
|
|
34
|
+
{ key: "project-config", path: (config) => getWorkspacePath(config, "projectConfig") },
|
|
35
|
+
{ key: "system-spec", path: (config) => getWorkspacePath(config, "systemSpec") },
|
|
36
|
+
{ key: "spec", moduleStage: "spec" },
|
|
37
|
+
],
|
|
38
|
+
task: [
|
|
39
|
+
{ key: "project-config", path: (config) => getWorkspacePath(config, "projectConfig") },
|
|
40
|
+
{ key: "system-spec", path: (config) => getWorkspacePath(config, "systemSpec") },
|
|
41
|
+
{ key: "proposal", moduleStage: "proposal" },
|
|
42
|
+
{ key: "spec", moduleStage: "spec" },
|
|
43
|
+
{ key: "design", moduleStage: "design" },
|
|
44
|
+
],
|
|
45
|
+
coding: [
|
|
46
|
+
{ key: "tasks", moduleStage: "tasks" },
|
|
47
|
+
],
|
|
48
|
+
fix: [],
|
|
49
|
+
smoke: [
|
|
50
|
+
{ key: "tasks", moduleStage: "tasks" },
|
|
51
|
+
],
|
|
52
|
+
review: [
|
|
53
|
+
{ key: "spec", moduleStage: "spec" },
|
|
54
|
+
{ key: "design", moduleStage: "design" },
|
|
55
|
+
{ key: "tasks", moduleStage: "tasks" },
|
|
56
|
+
{ key: "smoke", moduleStage: "smoke" },
|
|
57
|
+
],
|
|
58
|
+
ready: [
|
|
59
|
+
{ key: "review", moduleStage: "review" },
|
|
60
|
+
],
|
|
61
|
+
verify: [
|
|
62
|
+
{ key: "ready", moduleStage: "ready" },
|
|
63
|
+
],
|
|
64
|
+
acceptance: [
|
|
65
|
+
{ key: "verify", moduleStage: "verify" },
|
|
66
|
+
],
|
|
67
|
+
archive: [
|
|
68
|
+
{ key: "acceptance", moduleStage: "acceptance" },
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
const CURRENT_STAGE_ARTIFACTS = {
|
|
72
|
+
proposal: "proposal",
|
|
73
|
+
spec: "spec",
|
|
74
|
+
design: "design",
|
|
75
|
+
task: "tasks",
|
|
76
|
+
};
|
|
77
|
+
export function listStageQualityInputStages() {
|
|
78
|
+
return Object.keys(STAGE_INPUTS);
|
|
79
|
+
}
|
|
80
|
+
export async function resolveStageQualityModuleId(target, config, stage, requested) {
|
|
81
|
+
if (!MODULE_STAGES.has(stage))
|
|
82
|
+
return undefined;
|
|
83
|
+
if (requested)
|
|
84
|
+
return requested;
|
|
85
|
+
const modulesRoot = resolve(target, getWorkspacePath(config, "modulesRoot"));
|
|
86
|
+
try {
|
|
87
|
+
const entries = (await readdir(modulesRoot, { withFileTypes: true }))
|
|
88
|
+
.filter((entry) => entry.isDirectory() && !entry.name.startsWith("_"))
|
|
89
|
+
.map((entry) => entry.name);
|
|
90
|
+
if (entries.length === 1)
|
|
91
|
+
return entries[0];
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Missing modules root is handled as missing artifacts by the assessment.
|
|
95
|
+
}
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
export async function readStageQualityArtifacts(request) {
|
|
99
|
+
const { target, config, stage, moduleId, issue, reviewTarget } = request;
|
|
100
|
+
if (stage === "fix")
|
|
101
|
+
return readFixGateArtifacts(target, config, moduleId, issue);
|
|
102
|
+
if (stage === "review" && reviewTarget)
|
|
103
|
+
return [await readPathArtifact(target, "review-target", reviewTarget)];
|
|
104
|
+
const specs = STAGE_INPUTS[stage] ?? [];
|
|
105
|
+
const artifacts = [];
|
|
106
|
+
for (const spec of specs) {
|
|
107
|
+
if (spec.moduleStage) {
|
|
108
|
+
artifacts.push(await readModuleStageArtifact(target, config, spec.key, spec.moduleStage, moduleId));
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const path = spec.path?.(config, moduleId);
|
|
112
|
+
if (!path) {
|
|
113
|
+
artifacts.push({ key: spec.key, path: "<module-required>", exists: false, bytes: 0 });
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const abs = resolve(target, path);
|
|
117
|
+
const exists = existsSync(abs);
|
|
118
|
+
artifacts.push({
|
|
119
|
+
key: spec.key,
|
|
120
|
+
path,
|
|
121
|
+
exists,
|
|
122
|
+
bytes: exists ? Buffer.byteLength(await readFile(abs, "utf8")) : 0,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
const currentStage = CURRENT_STAGE_ARTIFACTS[stage];
|
|
126
|
+
if (currentStage) {
|
|
127
|
+
const currentArtifact = await readModuleStageArtifact(target, config, `current-${stage}`, currentStage, moduleId);
|
|
128
|
+
if (currentArtifact.exists)
|
|
129
|
+
artifacts.push(currentArtifact);
|
|
130
|
+
}
|
|
131
|
+
return artifacts;
|
|
132
|
+
}
|
|
133
|
+
export async function readStageQualityArtifactContents(target, artifacts) {
|
|
134
|
+
const contentByKey = new Map();
|
|
135
|
+
for (const artifact of artifacts) {
|
|
136
|
+
if (!artifact.exists)
|
|
137
|
+
continue;
|
|
138
|
+
contentByKey.set(artifact.key, await readGateArtifactContent(target, artifact));
|
|
139
|
+
}
|
|
140
|
+
return contentByKey;
|
|
141
|
+
}
|
|
142
|
+
async function readPathArtifact(target, key, path) {
|
|
143
|
+
const boundary = resolve(target);
|
|
144
|
+
const abs = resolve(boundary, path);
|
|
145
|
+
if (!isInsidePath(boundary, abs))
|
|
146
|
+
throw new Error(`review target must stay under project root: ${path}`);
|
|
147
|
+
try {
|
|
148
|
+
const info = await stat(abs);
|
|
149
|
+
if (info.isFile()) {
|
|
150
|
+
return { key, path, exists: true, bytes: Buffer.byteLength(await readFile(abs, "utf8")) };
|
|
151
|
+
}
|
|
152
|
+
if (info.isDirectory()) {
|
|
153
|
+
const directoryContent = await readReviewTargetDirectoryContent(target, abs);
|
|
154
|
+
return {
|
|
155
|
+
key,
|
|
156
|
+
path,
|
|
157
|
+
exists: true,
|
|
158
|
+
bytes: Buffer.byteLength(directoryContent.content),
|
|
159
|
+
children: directoryContent.children,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
// Missing paths are reported as missing artifacts by the assessment.
|
|
165
|
+
}
|
|
166
|
+
return { key, path, exists: false, bytes: 0 };
|
|
167
|
+
}
|
|
168
|
+
async function readModuleStageArtifact(target, config, key, stage, moduleId) {
|
|
169
|
+
const path = moduleStagePath(config, stage, moduleId);
|
|
170
|
+
if (!path)
|
|
171
|
+
return { key, path: "<module-required>", exists: false, bytes: 0 };
|
|
172
|
+
const abs = resolve(target, path);
|
|
173
|
+
try {
|
|
174
|
+
const info = await stat(abs);
|
|
175
|
+
if (info.isFile()) {
|
|
176
|
+
return { key, path, exists: true, bytes: Buffer.byteLength(await readFile(abs, "utf8")) };
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
// Fall through to stage-directory lookup for splittable artifacts.
|
|
181
|
+
}
|
|
182
|
+
if (!SPLITTABLE_MODULE_STAGES.has(stage)) {
|
|
183
|
+
return { key, path, exists: false, bytes: 0 };
|
|
184
|
+
}
|
|
185
|
+
const indexPath = moduleStageIndexPath(config, stage, moduleId);
|
|
186
|
+
if (!indexPath)
|
|
187
|
+
return { key, path, exists: false, bytes: 0 };
|
|
188
|
+
const indexAbs = resolve(target, indexPath);
|
|
189
|
+
try {
|
|
190
|
+
const info = await stat(indexAbs);
|
|
191
|
+
if (!info.isFile())
|
|
192
|
+
return { key, path: indexPath, exists: false, bytes: 0 };
|
|
193
|
+
const content = await readStageDirectoryContent(indexAbs);
|
|
194
|
+
return { key, path: indexPath, exists: true, bytes: Buffer.byteLength(content) };
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
return { key, path, exists: false, bytes: 0 };
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
async function readFixGateArtifacts(target, config, moduleId, issue) {
|
|
201
|
+
const path = await resolveIssueArtifactPath(target, config, moduleId, issue);
|
|
202
|
+
if (!path)
|
|
203
|
+
return [{ key: "issue-record", path: "<issue-required>", exists: false, bytes: 0 }];
|
|
204
|
+
const abs = resolve(target, path);
|
|
205
|
+
const exists = existsSync(abs);
|
|
206
|
+
return [{
|
|
207
|
+
key: "issue-record",
|
|
208
|
+
path,
|
|
209
|
+
exists,
|
|
210
|
+
bytes: exists ? Buffer.byteLength(await readFile(abs, "utf8")) : 0,
|
|
211
|
+
}];
|
|
212
|
+
}
|
|
213
|
+
async function resolveIssueArtifactPath(target, config, moduleId, issue) {
|
|
214
|
+
const value = issue?.trim();
|
|
215
|
+
if (!value)
|
|
216
|
+
return undefined;
|
|
217
|
+
if (looksLikeIssuePath(value))
|
|
218
|
+
return normalizeIssuePath(target, value);
|
|
219
|
+
const candidates = await collectIssueRecordCandidates(target, config, moduleId);
|
|
220
|
+
return candidates.find((candidate) => issueKey(candidate) === value) ??
|
|
221
|
+
candidates.find((candidate) => issueKey(candidate).startsWith(`${value}-`));
|
|
222
|
+
}
|
|
223
|
+
async function normalizeIssuePath(target, value) {
|
|
224
|
+
const abs = resolve(target, value);
|
|
225
|
+
try {
|
|
226
|
+
const info = await stat(abs);
|
|
227
|
+
if (info.isDirectory())
|
|
228
|
+
return toProjectPath(target, join(abs, "issue.md"));
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
// Missing issue paths are returned as-is so the gate can report the missing artifact.
|
|
232
|
+
}
|
|
233
|
+
if (!extname(value))
|
|
234
|
+
return toProjectPath(target, join(abs, "issue.md"));
|
|
235
|
+
return toProjectPath(target, abs);
|
|
236
|
+
}
|
|
237
|
+
async function collectIssueRecordCandidates(target, config, moduleId) {
|
|
238
|
+
const roots = [
|
|
239
|
+
...(moduleId ? [resolve(target, getWorkspacePath(config, "moduleIssues", { module: moduleId }))] : []),
|
|
240
|
+
resolve(target, getWorkspacePath(config, "issuesRoot")),
|
|
241
|
+
resolve(target, getWorkspacePath(config, "issuesRoot"), "global"),
|
|
242
|
+
resolve(target, getWorkspacePath(config, "issuesRoot"), "shared"),
|
|
243
|
+
resolve(target, getWorkspacePath(config, "issuesRoot"), "public"),
|
|
244
|
+
];
|
|
245
|
+
const files = [];
|
|
246
|
+
for (const root of roots)
|
|
247
|
+
files.push(...(await collectIssueFiles(root)));
|
|
248
|
+
return [...new Set(files.map((file) => toProjectPath(target, file)))].sort();
|
|
249
|
+
}
|
|
250
|
+
async function collectIssueFiles(root) {
|
|
251
|
+
try {
|
|
252
|
+
const entries = await readdir(root, { withFileTypes: true });
|
|
253
|
+
const files = [];
|
|
254
|
+
for (const entry of entries) {
|
|
255
|
+
const path = join(root, entry.name);
|
|
256
|
+
if (entry.isDirectory())
|
|
257
|
+
files.push(...(await collectIssueFiles(path)));
|
|
258
|
+
if (entry.isFile() && entry.name !== "index.md" && entry.name.endsWith(".md"))
|
|
259
|
+
files.push(path);
|
|
260
|
+
}
|
|
261
|
+
return files;
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
return [];
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
function looksLikeIssuePath(value) {
|
|
268
|
+
return value.includes("/") || value.endsWith(".md") || value.startsWith(".");
|
|
269
|
+
}
|
|
270
|
+
function issueKey(path) {
|
|
271
|
+
const name = basename(path);
|
|
272
|
+
return name === "issue.md" ? basename(dirname(path)) : name.replace(/\.md$/i, "");
|
|
273
|
+
}
|
|
274
|
+
function toProjectPath(target, path) {
|
|
275
|
+
return relative(target, path).split("\\").join("/");
|
|
276
|
+
}
|
|
277
|
+
function moduleStagePath(config, stage, moduleId) {
|
|
278
|
+
if (!moduleId)
|
|
279
|
+
return undefined;
|
|
280
|
+
return join(getWorkspacePath(config, "modulesRoot"), moduleId, `${stage}.md`);
|
|
281
|
+
}
|
|
282
|
+
function moduleStageIndexPath(config, stage, moduleId) {
|
|
283
|
+
if (!moduleId)
|
|
284
|
+
return undefined;
|
|
285
|
+
return join(getWorkspacePath(config, "modulesRoot"), moduleId, stage, "index.md");
|
|
286
|
+
}
|
|
287
|
+
async function readGateArtifactContent(target, artifact) {
|
|
288
|
+
const boundary = resolve(target);
|
|
289
|
+
const abs = resolve(boundary, artifact.path);
|
|
290
|
+
if (!isInsidePath(boundary, abs))
|
|
291
|
+
throw new Error(`gate artifact must stay under project root: ${artifact.path}`);
|
|
292
|
+
if (basename(abs) === "index.md" && SPLITTABLE_MODULE_STAGES.has(basename(dirname(abs)))) {
|
|
293
|
+
return readStageDirectoryContent(abs);
|
|
294
|
+
}
|
|
295
|
+
try {
|
|
296
|
+
const info = await stat(abs);
|
|
297
|
+
if (info.isDirectory())
|
|
298
|
+
return (await readReviewTargetDirectoryContent(target, abs)).content;
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
// The caller only asks for content after the artifact exists; fall through
|
|
302
|
+
// to the file read so the original error remains visible if the path races.
|
|
303
|
+
}
|
|
304
|
+
return readFile(abs, "utf8");
|
|
305
|
+
}
|
|
306
|
+
async function readReviewTargetDirectoryContent(target, dir) {
|
|
307
|
+
const files = await collectReviewableFiles(dir, dir);
|
|
308
|
+
const contents = [];
|
|
309
|
+
const children = [];
|
|
310
|
+
for (const file of files) {
|
|
311
|
+
const path = toProjectPath(target, file);
|
|
312
|
+
try {
|
|
313
|
+
const content = await readFile(file, "utf8");
|
|
314
|
+
children.push({ path, status: "included", bytes: Buffer.byteLength(content) });
|
|
315
|
+
contents.push(`<!-- review-target-file: ${path} -->\n${content}`);
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
children.push({ path, status: "unreadable", bytes: 0 });
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return { content: contents.join("\n\n"), children };
|
|
322
|
+
}
|
|
323
|
+
async function collectReviewableFiles(root, boundary) {
|
|
324
|
+
try {
|
|
325
|
+
const entries = await readdir(root, { withFileTypes: true });
|
|
326
|
+
const files = [];
|
|
327
|
+
for (const entry of entries) {
|
|
328
|
+
if (shouldSkipReviewTargetEntry(entry.name))
|
|
329
|
+
continue;
|
|
330
|
+
const path = join(root, entry.name);
|
|
331
|
+
if (!isInsidePath(boundary, path))
|
|
332
|
+
continue;
|
|
333
|
+
if (entry.isDirectory()) {
|
|
334
|
+
files.push(...(await collectReviewableFiles(path, boundary)));
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
if (entry.isFile() && /\.(md|mdx|ya?ml|json|txt)$/i.test(entry.name))
|
|
338
|
+
files.push(path);
|
|
339
|
+
}
|
|
340
|
+
return files.sort();
|
|
341
|
+
}
|
|
342
|
+
catch {
|
|
343
|
+
return [];
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
export function normalizeReviewTargetPath(target, value) {
|
|
347
|
+
const trimmed = value?.trim();
|
|
348
|
+
if (!trimmed)
|
|
349
|
+
return undefined;
|
|
350
|
+
const boundary = resolve(target);
|
|
351
|
+
const abs = resolve(boundary, trimmed);
|
|
352
|
+
if (isInsidePath(boundary, abs))
|
|
353
|
+
return toProjectPath(boundary, abs) || ".";
|
|
354
|
+
throw new Error(`review target must stay under project root: ${trimmed}`);
|
|
355
|
+
}
|
|
356
|
+
export function reviewModeForReviewTarget(reviewTarget) {
|
|
357
|
+
if (!reviewTarget)
|
|
358
|
+
return undefined;
|
|
359
|
+
const path = reviewTarget.replace(/\\/g, "/");
|
|
360
|
+
if (path === ".zsk" || path.startsWith(".zsk/")) {
|
|
361
|
+
if (path.startsWith(".zsk/raws/prepare/product") ||
|
|
362
|
+
path.startsWith(".zsk/raws/prepare/roadmap") ||
|
|
363
|
+
path.startsWith(".zsk/raws/prepare/ux") ||
|
|
364
|
+
path.startsWith(".zsk/raws/prepare/design") ||
|
|
365
|
+
path.startsWith(".zsk/evidence/preproposal"))
|
|
366
|
+
return "preproposal";
|
|
367
|
+
if (path.startsWith(".zsk/raws/design/") || path.startsWith(".zsk/raws/visual/") || path.includes("/design-source"))
|
|
368
|
+
return "design-source";
|
|
369
|
+
if (path.startsWith(".zsk/raws/"))
|
|
370
|
+
return "raw-source";
|
|
371
|
+
if (/^\.zsk\/modules\/[^/]+\/(?:proposal|spec|design|tasks?)(?:\.md|\/|$)/.test(path))
|
|
372
|
+
return "stage-doc";
|
|
373
|
+
return "zsk-workspace";
|
|
374
|
+
}
|
|
375
|
+
if (/\.(?:cjs|cts|js|jsx|mjs|mts|ts|tsx|vue|svelte|css|scss|go|rs|java|kt|swift|py|rb|php|cs|cpp|c|h|hpp)$/i.test(path))
|
|
376
|
+
return "code-target";
|
|
377
|
+
if (/(?:design|figma|prototype|wireframe|mockup|screen|asset)/i.test(path))
|
|
378
|
+
return "design-source";
|
|
379
|
+
return "target-path";
|
|
380
|
+
}
|
|
381
|
+
function shouldSkipReviewTargetEntry(name) {
|
|
382
|
+
if (SKIPPED_REVIEW_TARGET_DIRS.has(name))
|
|
383
|
+
return true;
|
|
384
|
+
return /(?:storage-state|storagestate|cookies?|tokens?|secrets?|credentials?)\.(?:json|ya?ml|txt)$/i.test(name);
|
|
385
|
+
}
|
|
386
|
+
async function readStageDirectoryContent(indexPath) {
|
|
387
|
+
const indexContent = await readFile(indexPath, "utf8");
|
|
388
|
+
const dir = dirname(indexPath);
|
|
389
|
+
const linkedChildren = linkedMarkdownChildren(indexContent, dir);
|
|
390
|
+
const childContents = [];
|
|
391
|
+
for (const child of linkedChildren) {
|
|
392
|
+
try {
|
|
393
|
+
const info = await stat(child);
|
|
394
|
+
if (info.isFile())
|
|
395
|
+
childContents.push(await readFile(child, "utf8"));
|
|
396
|
+
}
|
|
397
|
+
catch {
|
|
398
|
+
// Missing linked children are handled by zsk check; gate content still
|
|
399
|
+
// relies on the index so the artifact cannot pass from hidden files.
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return [indexContent, ...childContents].join("\n\n");
|
|
403
|
+
}
|
|
404
|
+
function linkedMarkdownChildren(content, dir) {
|
|
405
|
+
const files = new Set();
|
|
406
|
+
for (const match of content.matchAll(/\[[^\]]+\]\(([^)]+?\.md)(?:#[^)]+)?\)/gi)) {
|
|
407
|
+
const raw = match[1]?.trim();
|
|
408
|
+
if (!raw || /^[a-z][a-z0-9+.-]*:/i.test(raw) || raw.startsWith("/"))
|
|
409
|
+
continue;
|
|
410
|
+
const resolved = resolve(dir, raw);
|
|
411
|
+
if (!isInsidePath(dir, resolved) || resolved === resolve(dir, "index.md"))
|
|
412
|
+
continue;
|
|
413
|
+
files.add(resolved);
|
|
414
|
+
}
|
|
415
|
+
return [...files].sort();
|
|
416
|
+
}
|
|
417
|
+
function isInsidePath(parent, child) {
|
|
418
|
+
const rel = relative(parent, child);
|
|
419
|
+
return rel === "" || (!rel.startsWith("..") && !rel.startsWith("/") && !rel.includes("..\\"));
|
|
420
|
+
}
|
|
421
|
+
//# sourceMappingURL=stage-quality-artifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stage-quality-artifacts.js","sourceRoot":"","sources":["../../src/core/stage-quality-artifacts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export type GateAssessmentOptions = {
|
|
2
|
+
stage: string;
|
|
3
|
+
module?: string;
|
|
4
|
+
issue?: string;
|
|
5
|
+
reviewTarget?: string;
|
|
6
|
+
threshold?: number;
|
|
7
|
+
acceptRisk?: string;
|
|
8
|
+
};
|
|
9
|
+
export type GateStatus = "READY" | "NEEDS_CONFIRMATION" | "BLOCKED" | "WAIVED";
|
|
10
|
+
export type GateCriterion = {
|
|
11
|
+
id: string;
|
|
12
|
+
label: string;
|
|
13
|
+
weight: number;
|
|
14
|
+
passed: boolean;
|
|
15
|
+
required: boolean;
|
|
16
|
+
evidence: string[];
|
|
17
|
+
gap?: string;
|
|
18
|
+
};
|
|
19
|
+
export type GateArtifact = {
|
|
20
|
+
key: string;
|
|
21
|
+
path: string;
|
|
22
|
+
exists: boolean;
|
|
23
|
+
bytes: number;
|
|
24
|
+
children?: GateArtifactChild[];
|
|
25
|
+
};
|
|
26
|
+
export type GateArtifactChild = {
|
|
27
|
+
path: string;
|
|
28
|
+
status: "included" | "unreadable";
|
|
29
|
+
bytes: number;
|
|
30
|
+
};
|
|
31
|
+
export type GateAssessment = {
|
|
32
|
+
version: 1;
|
|
33
|
+
runId: string;
|
|
34
|
+
stage: string;
|
|
35
|
+
module?: string;
|
|
36
|
+
reviewTarget?: string;
|
|
37
|
+
reviewMode?: ReviewGateMode;
|
|
38
|
+
threshold: number;
|
|
39
|
+
score: number;
|
|
40
|
+
status: GateStatus;
|
|
41
|
+
decision: "proceed" | "human-confirmation-required" | "blocked";
|
|
42
|
+
artifacts: GateArtifact[];
|
|
43
|
+
criteria: GateCriterion[];
|
|
44
|
+
blockers: string[];
|
|
45
|
+
gaps: string[];
|
|
46
|
+
waiver?: {
|
|
47
|
+
reason: string;
|
|
48
|
+
appliedAt: string;
|
|
49
|
+
};
|
|
50
|
+
nextAction: string;
|
|
51
|
+
};
|
|
52
|
+
export type GateAssessmentBundle = {
|
|
53
|
+
assessment: GateAssessment;
|
|
54
|
+
artifacts: {
|
|
55
|
+
dir: string;
|
|
56
|
+
jsonPath: string;
|
|
57
|
+
markdownPath: string;
|
|
58
|
+
waiverPath?: string;
|
|
59
|
+
};
|
|
60
|
+
markdown: string;
|
|
61
|
+
waiverMarkdown?: string;
|
|
62
|
+
};
|
|
63
|
+
export type StageQualityArtifactSpec = {
|
|
64
|
+
key: string;
|
|
65
|
+
moduleStage?: string;
|
|
66
|
+
path?: (config: import("./config.js").ProjectConfig, moduleId?: string) => string;
|
|
67
|
+
};
|
|
68
|
+
export type StageQualityCriterionSpec = {
|
|
69
|
+
id: string;
|
|
70
|
+
label: string;
|
|
71
|
+
weight: number;
|
|
72
|
+
required?: boolean;
|
|
73
|
+
artifactKeys?: string[];
|
|
74
|
+
test: (ctx: StageQualityCriterionContext) => boolean;
|
|
75
|
+
evidence: (ctx: StageQualityCriterionContext) => string[];
|
|
76
|
+
gap: string;
|
|
77
|
+
};
|
|
78
|
+
export type StageQualityCriterionContext = {
|
|
79
|
+
stage: string;
|
|
80
|
+
reviewTarget?: string;
|
|
81
|
+
reviewMode?: ReviewGateMode;
|
|
82
|
+
artifacts: GateArtifact[];
|
|
83
|
+
contentByKey: Map<string, string>;
|
|
84
|
+
};
|
|
85
|
+
export type ReviewGateMode = "implementation" | "preproposal" | "raw-source" | "zsk-workspace" | "stage-doc" | "design-source" | "code-target" | "target-path";
|
|
86
|
+
export declare const DEFAULT_STAGE_QUALITY_THRESHOLD = 9;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stage-quality-contracts.js","sourceRoot":"","sources":["../../src/core/stage-quality-contracts.ts"],"names":[],"mappings":"AAgGA,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { GateArtifact, GateCriterion, StageQualityCriterionContext } from "./stage-quality-contracts.js";
|
|
2
|
+
export declare function evaluateStageQualityCriteria(input: {
|
|
3
|
+
stage: string;
|
|
4
|
+
reviewTarget: string | undefined;
|
|
5
|
+
reviewMode: StageQualityCriterionContext["reviewMode"];
|
|
6
|
+
artifacts: GateArtifact[];
|
|
7
|
+
contentByKey: Map<string, string>;
|
|
8
|
+
knownStages: string[];
|
|
9
|
+
}): GateCriterion[];
|