@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.
Files changed (46) hide show
  1. package/dist/commands/add-flow.d.ts +3 -7
  2. package/dist/commands/add-flow.js +7 -59
  3. package/dist/commands/add-flow.js.map +1 -1
  4. package/dist/commands/add.js +25 -104
  5. package/dist/commands/add.js.map +1 -1
  6. package/dist/core/prepare-sync.d.ts +2 -31
  7. package/dist/core/prepare-sync.js +96 -128
  8. package/dist/core/prepare-sync.js.map +1 -1
  9. package/dist/core/profile-bundle-installation.d.ts +55 -0
  10. package/dist/core/profile-bundle-installation.js +170 -0
  11. package/dist/core/profile-bundle-installation.js.map +1 -0
  12. package/dist/core/source-snapshot-adapters.d.ts +59 -0
  13. package/dist/core/source-snapshot-adapters.js +82 -0
  14. package/dist/core/source-snapshot-adapters.js.map +1 -0
  15. package/dist/core/staffing-plan.js +52 -18
  16. package/dist/core/staffing-plan.js.map +1 -1
  17. package/dist/core/stage-clarity-verification.d.ts +31 -0
  18. package/dist/core/stage-clarity-verification.js +313 -0
  19. package/dist/core/stage-clarity-verification.js.map +1 -0
  20. package/dist/core/stage-quality-artifacts.d.ts +15 -0
  21. package/dist/core/stage-quality-artifacts.js +421 -0
  22. package/dist/core/stage-quality-artifacts.js.map +1 -0
  23. package/dist/core/stage-quality-contracts.d.ts +86 -0
  24. package/dist/core/stage-quality-contracts.js +2 -0
  25. package/dist/core/stage-quality-contracts.js.map +1 -0
  26. package/dist/core/stage-quality-criteria.d.ts +9 -0
  27. package/dist/core/stage-quality-criteria.js +323 -0
  28. package/dist/core/stage-quality-criteria.js.map +1 -0
  29. package/dist/core/stage-quality-rendering.d.ts +13 -0
  30. package/dist/core/stage-quality-rendering.js +122 -0
  31. package/dist/core/stage-quality-rendering.js.map +1 -0
  32. package/dist/core/stage-quality.d.ts +4 -59
  33. package/dist/core/stage-quality.js +39 -791
  34. package/dist/core/stage-quality.js.map +1 -1
  35. package/package.json +2 -2
  36. package/templates/module/frontend-module/design.md +10 -0
  37. package/templates/module/frontend-module/proposal.md +8 -0
  38. package/templates/module/frontend-module/spec.md +7 -0
  39. package/templates/project-init/.zsk/config.yaml +33 -0
  40. package/templates/project-init/.zsk/docs/PROJECT-CONFIG.md +43 -0
  41. package/templates/project-init/.zsk/docs/SYSTEM-SPEC.md +22 -2
  42. package/templates/project-init/.zsk/raws/index.md +16 -0
  43. package/templates/project-init/.zsk/raws/prepare/design/index.md +18 -0
  44. package/templates/project-init/.zsk/raws/prepare/index.md +33 -0
  45. package/templates/project-init/.zsk/raws/prepare/ux/index.md +19 -0
  46. package/templates/project-init/.zsk/roles.yaml +3 -3
@@ -0,0 +1,170 @@
1
+ import { readFile, readdir } from "node:fs/promises";
2
+ import { basename, dirname, join, relative } from "node:path";
3
+ import { expandCapabilityFilters, hasCapabilityFilter, } from "./capabilities.js";
4
+ import { install, skillRelPath } from "./installer.js";
5
+ import { buildManifest, sha256File, } from "./manifest.js";
6
+ import { loadSkill } from "./skills.js";
7
+ export const DEFAULT_PROFILE_BUNDLE = "zsk-sdlc";
8
+ export async function installProfileBundle(plan) {
9
+ return install(plan);
10
+ }
11
+ export function isProfileBundleMaintenanceRun(args) {
12
+ return args.targetProvided && args.hasManifest && !args.hasExplicitPicks;
13
+ }
14
+ export function resolveProfileInstallMode(args) {
15
+ if (!args.hasManifest)
16
+ return "new";
17
+ if (args.hasExplicitPicks)
18
+ return "append";
19
+ return args.requestedAction ?? "exit";
20
+ }
21
+ export function buildProfileBundleOptions(bundles) {
22
+ return profileBundleEntries(bundles)
23
+ .map(([name, bundle]) => ({
24
+ value: name,
25
+ label: bundle.label || name,
26
+ hint: buildProfileBundleSummary(bundle.skills),
27
+ }));
28
+ }
29
+ export function resolveProfileBundleChoices(selectedBundleNames, bundles, availableSkills) {
30
+ const skills = uniqueStrings(selectedBundleNames.flatMap((name) => {
31
+ const bundle = bundles[name];
32
+ return bundle ? profileBundleToAvailableSkills(bundle, availableSkills) : [];
33
+ }));
34
+ return {
35
+ skills,
36
+ bundle: selectedBundleNames.length === 1
37
+ ? inferProfileBundleName(selectedBundleNames[0] ?? null, skills, bundles, availableSkills)
38
+ : null,
39
+ };
40
+ }
41
+ export function resolveCapabilityProfileSelection(filters, availableSkills) {
42
+ const matched = expandCapabilityFilters(filters.skill ?? [], availableSkills);
43
+ if (!hasCapabilityFilter(filters))
44
+ return null;
45
+ return { skills: matched, bundle: null };
46
+ }
47
+ export function resolveProfileBundlePatternSelection(args) {
48
+ const { bundles, availableSkills, bundlePatterns, skillPatterns } = args;
49
+ const matched = expandCapabilityFilters(skillPatterns, availableSkills);
50
+ const selected = uniqueStrings([
51
+ ...bundlePatterns.flatMap((name) => {
52
+ const bundle = bundles[name];
53
+ return bundle ? profileBundleToAvailableSkills(bundle, availableSkills) : [];
54
+ }),
55
+ ...matched,
56
+ ]);
57
+ return {
58
+ skills: selected,
59
+ bundle: bundlePatterns.length === 1
60
+ ? inferProfileBundleName(bundlePatterns[0] ?? null, selected, bundles, availableSkills)
61
+ : null,
62
+ };
63
+ }
64
+ export function inferProfileBundleName(selectedBundleName, selectedSkills, bundles, availableSkills) {
65
+ if (!selectedBundleName)
66
+ return null;
67
+ const bundle = bundles[selectedBundleName];
68
+ if (!bundle)
69
+ return null;
70
+ const expected = profileBundleToAvailableSkills(bundle, availableSkills);
71
+ return sameMembers(selectedSkills, expected) ? selectedBundleName : null;
72
+ }
73
+ export function profileBundleToAvailableSkills(bundle, availableSkills) {
74
+ const set = new Set(availableSkills);
75
+ return bundle.skills.filter((skill) => set.has(skill));
76
+ }
77
+ export function inferProfileBundleInstallLayout(targetPath, format) {
78
+ if (format === "claude-plugin")
79
+ return "claude-plugin";
80
+ if (format === "flat")
81
+ return "flat";
82
+ const base = basename(targetPath);
83
+ return base === ".claude-plugin" || base === "claude-plugin"
84
+ ? "claude-plugin"
85
+ : "flat";
86
+ }
87
+ export async function buildProfileBundleManifestRecords(skillNames, targetPath, layout, zskVersion) {
88
+ const out = [];
89
+ for (const name of skillNames) {
90
+ try {
91
+ const skill = await loadSkill(name);
92
+ const relPath = skillRelPath(skill, layout);
93
+ const buf = await readFile(join(targetPath, relPath));
94
+ const skillRoot = dirname(relPath);
95
+ out.push({
96
+ name,
97
+ version: zskVersion,
98
+ sha256: sha256File(buf),
99
+ relPath,
100
+ files: await buildOwnedFileRecords(targetPath, skillRoot),
101
+ });
102
+ }
103
+ catch {
104
+ // The skill may have been skipped by conflict policy; omit it from the manifest.
105
+ }
106
+ }
107
+ return out;
108
+ }
109
+ export function buildProfileBundleManifest(params) {
110
+ return buildManifest(params);
111
+ }
112
+ export function mergeProfileBundleManifestSkills(existing, fresh, currentInstallableNames) {
113
+ const map = new Map();
114
+ for (const entry of existing) {
115
+ if (currentInstallableNames.has(entry.name))
116
+ map.set(entry.name, entry);
117
+ }
118
+ for (const entry of fresh)
119
+ map.set(entry.name, entry);
120
+ return [...map.values()].sort((left, right) => left.name.localeCompare(right.name));
121
+ }
122
+ function profileBundleEntries(bundles) {
123
+ return Object.entries(bundles)
124
+ .filter(([, bundle]) => bundle.skills.length > 0)
125
+ .sort(([leftName], [rightName]) => {
126
+ if (leftName === DEFAULT_PROFILE_BUNDLE)
127
+ return -1;
128
+ if (rightName === DEFAULT_PROFILE_BUNDLE)
129
+ return 1;
130
+ return leftName.localeCompare(rightName);
131
+ });
132
+ }
133
+ function buildProfileBundleSummary(skills) {
134
+ const preview = skills.slice(0, 3).join(", ");
135
+ const suffix = skills.length > 3 ? ", ..." : "";
136
+ return `${skills.length} 个 · ${preview}${suffix}`;
137
+ }
138
+ async function buildOwnedFileRecords(targetPath, skillRoot) {
139
+ const absRoot = join(targetPath, skillRoot);
140
+ const files = await walkFiles(absRoot);
141
+ const records = await Promise.all(files.map(async (absPath) => ({
142
+ relPath: relative(targetPath, absPath),
143
+ sha256: sha256File(await readFile(absPath)),
144
+ })));
145
+ return records.sort((left, right) => left.relPath.localeCompare(right.relPath));
146
+ }
147
+ async function walkFiles(dir) {
148
+ const out = [];
149
+ const entries = await readdir(dir, { withFileTypes: true });
150
+ for (const entry of entries) {
151
+ const path = join(dir, entry.name);
152
+ if (entry.isDirectory()) {
153
+ out.push(...(await walkFiles(path)));
154
+ }
155
+ else if (entry.isFile()) {
156
+ out.push(path);
157
+ }
158
+ }
159
+ return out;
160
+ }
161
+ function sameMembers(left, right) {
162
+ if (left.length !== right.length)
163
+ return false;
164
+ const rightSet = new Set(right);
165
+ return left.every((value) => rightSet.has(value));
166
+ }
167
+ function uniqueStrings(values) {
168
+ return [...new Set(values)].sort((left, right) => left.localeCompare(right));
169
+ }
170
+ //# sourceMappingURL=profile-bundle-installation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-bundle-installation.js","sourceRoot":"","sources":["../../src/core/profile-bundle-installation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import { type ProjectConfig, type SourceConfig, type SourceEntry } from "./config.js";
2
+ import { type OriginInference } from "./origin-detection.js";
3
+ export type PrepareSyncOptions = {
4
+ source?: string;
5
+ all?: boolean;
6
+ allowNetwork?: boolean;
7
+ authState?: string;
8
+ authProfile?: string;
9
+ browser?: boolean;
10
+ dryRun?: boolean;
11
+ runId?: string;
12
+ };
13
+ export type PrepareSyncStatus = "materialized" | "metadata-only" | "blocked-auth" | "source-gap" | "skipped" | "failed";
14
+ export type PrepareSyncResult = {
15
+ envelopeVersion?: 1;
16
+ sourceKey: string;
17
+ sourcePath: string;
18
+ rawLane?: string;
19
+ provider?: string;
20
+ adapter?: string;
21
+ strategy: string;
22
+ status: PrepareSyncStatus;
23
+ origin?: string;
24
+ resolvedOrigin?: string;
25
+ contentType?: string;
26
+ snapshot?: string;
27
+ snapshotHash?: string;
28
+ previousSnapshotHash?: string;
29
+ metadata?: Record<string, unknown>;
30
+ changed: boolean;
31
+ reason: string;
32
+ validation: Record<string, "pass" | "fail" | "skipped">;
33
+ };
34
+ export type PrepareSyncBase = Omit<PrepareSyncResult, "strategy" | "status" | "changed" | "reason" | "validation">;
35
+ export type SourceSnapshotProviderAdapter = "confluence" | "jira" | "gitlab" | "design-source";
36
+ export type SourceSnapshotContext = {
37
+ target: string;
38
+ config: ProjectConfig;
39
+ entry: SourceEntry;
40
+ source: SourceConfig;
41
+ origin: OriginInference;
42
+ opts: PrepareSyncOptions;
43
+ snapshot: string;
44
+ snapshotPath: string;
45
+ previousSnapshotHash?: string;
46
+ base: PrepareSyncBase;
47
+ };
48
+ export type SourceSnapshotAdapterHandlers = {
49
+ dryRun: (context: SourceSnapshotContext) => Promise<PrepareSyncResult> | PrepareSyncResult;
50
+ local: (context: SourceSnapshotContext) => Promise<PrepareSyncResult>;
51
+ provider: (context: SourceSnapshotContext, adapter: SourceSnapshotProviderAdapter) => Promise<PrepareSyncResult | null>;
52
+ repository: (context: SourceSnapshotContext) => Promise<PrepareSyncResult>;
53
+ url: (context: SourceSnapshotContext) => Promise<PrepareSyncResult>;
54
+ providerManaged: (context: SourceSnapshotContext) => Promise<PrepareSyncResult> | PrepareSyncResult;
55
+ };
56
+ export declare function createSourceSnapshotContext(target: string, config: ProjectConfig, entry: SourceEntry, opts: PrepareSyncOptions, previousSnapshotHashFor: (snapshotPath: string) => Promise<string | undefined>): Promise<SourceSnapshotContext>;
57
+ export declare function acquireSourceSnapshot(context: SourceSnapshotContext, handlers: SourceSnapshotAdapterHandlers): Promise<PrepareSyncResult>;
58
+ export declare function selectSourceSnapshotProviderAdapter(source: SourceConfig, origin: OriginInference): SourceSnapshotProviderAdapter | undefined;
59
+ export declare function chooseSourceSnapshotStrategy(method: string): string;
@@ -0,0 +1,82 @@
1
+ import { resolve } from "node:path";
2
+ import { resolveSourceSnapshot, } from "./config.js";
3
+ import { inferSourceOrigin } from "./origin-detection.js";
4
+ export async function createSourceSnapshotContext(target, config, entry, opts, previousSnapshotHashFor) {
5
+ const source = entry.source;
6
+ const origin = inferSourceOrigin(source);
7
+ const snapshot = resolveSourceSnapshot(config, entry);
8
+ const snapshotPath = resolve(target, snapshot);
9
+ const previousSnapshotHash = await previousSnapshotHashFor(snapshotPath);
10
+ const base = {
11
+ envelopeVersion: 1,
12
+ sourceKey: entry.id,
13
+ sourcePath: entry.path,
14
+ rawLane: entry.rawLane,
15
+ provider: origin.provider,
16
+ origin: origin.ref,
17
+ snapshot,
18
+ previousSnapshotHash,
19
+ };
20
+ return {
21
+ target,
22
+ config,
23
+ entry,
24
+ source,
25
+ origin,
26
+ opts,
27
+ snapshot,
28
+ snapshotPath,
29
+ previousSnapshotHash,
30
+ base,
31
+ };
32
+ }
33
+ export async function acquireSourceSnapshot(context, handlers) {
34
+ if (context.opts.dryRun)
35
+ return handlers.dryRun(context);
36
+ if (context.origin.method === "local")
37
+ return handlers.local(context);
38
+ const providerAdapter = selectSourceSnapshotProviderAdapter(context.source, context.origin);
39
+ if (providerAdapter) {
40
+ const result = await handlers.provider(context, providerAdapter);
41
+ if (result)
42
+ return result;
43
+ }
44
+ if (context.origin.method === "repository")
45
+ return handlers.repository(context);
46
+ if (context.origin.method === "url")
47
+ return handlers.url(context);
48
+ return handlers.providerManaged(context);
49
+ }
50
+ export function selectSourceSnapshotProviderAdapter(source, origin) {
51
+ const keys = [
52
+ origin.provider,
53
+ origin.kind,
54
+ source.origin?.provider,
55
+ source.origin?.kind,
56
+ source.kind,
57
+ source.type,
58
+ ].map((value) => normalizeAdapterKey(typeof value === "string" ? value : undefined));
59
+ if (keys.some((value) => value.includes("confluence")))
60
+ return "confluence";
61
+ if (keys.some((value) => value.includes("jira")))
62
+ return "jira";
63
+ if (keys.some((value) => value.includes("gitlab")))
64
+ return "gitlab";
65
+ if (keys.some((value) => ["figma", "modao", "mastergo", "design", "design-asset", "design-source"].includes(value))) {
66
+ return "design-source";
67
+ }
68
+ return undefined;
69
+ }
70
+ export function chooseSourceSnapshotStrategy(method) {
71
+ if (method === "local")
72
+ return "local-copy-structured-markdown";
73
+ if (method === "repository")
74
+ return "repository-metadata-only";
75
+ if (method === "url")
76
+ return "playwright-auth-or-direct-fetch";
77
+ return "confirm-acquisition-method";
78
+ }
79
+ function normalizeAdapterKey(value) {
80
+ return value?.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") ?? "";
81
+ }
82
+ //# sourceMappingURL=source-snapshot-adapters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-snapshot-adapters.js","sourceRoot":"","sources":["../../src/core/source-snapshot-adapters.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,7 @@ const PREPROPOSAL_ROLE_NAMES = [
17
17
  "planner",
18
18
  "ux-specialist",
19
19
  "design-specialist",
20
+ "frontend-engineer",
20
21
  "architect",
21
22
  "qa-engineer",
22
23
  "researcher",
@@ -69,14 +70,14 @@ const BUILTIN_ROLE_POOL = {
69
70
  }),
70
71
  rolePoolEntry("frontend-engineer", {
71
72
  subagentType: "executor",
72
- stages: ["design"],
73
+ stages: ["preproposal", "design"],
73
74
  lanes: ["frontend", "web", "client", "mobile"],
74
75
  activation: "when frontend implementation, routing, state, or UI integration is in scope",
75
76
  reason: "map UI implementation, routing, state, and component integration risk",
76
77
  }),
77
78
  rolePoolEntry("design-specialist", {
78
79
  subagentType: "designer",
79
- stages: ["prepare", "preproposal", "design"],
80
+ stages: ["prepare", "preproposal"],
80
81
  lanes: ["design", "ui", "visual"],
81
82
  activation: "when design, UI, visual, prototype, or asset sources are configured",
82
83
  reason: "inspect design assets, screens, visual states, and design-source gaps",
@@ -173,10 +174,12 @@ const ROLE_CONTRACTS = {
173
174
  ".zsk/evidence/{scope}/{run}/integration-summary.md",
174
175
  ".zsk/raws/manifest.json when prepare snapshots change",
175
176
  ".zsk/raws/manifest.json and .zsk/raws/index.md when preproposal raw resources change",
177
+ ".zsk/raws/prepare/product/{topic}/intake-clarity.md when running preproposal",
176
178
  ".zsk/evidence/preproposal/{run}/readiness-review.md when running preproposal",
177
179
  ],
178
180
  evidenceRequired: [
179
181
  "integrated lane status with pass/blocker/waived reason for each role",
182
+ "source-discoverable questions answered before user clarification when running preproposal",
180
183
  "confirmation that shared/global artifacts were updated only after lane validation",
181
184
  ],
182
185
  forbiddenDecisions: [
@@ -190,10 +193,11 @@ const ROLE_CONTRACTS = {
190
193
  doesNotOwn: ["backend implementation details", "technical feasibility signoff without architect/engineer evidence"],
191
194
  outputs: [
192
195
  ".zsk/evidence/{scope}/{run}/product-source-report.md",
196
+ ".zsk/raws/prepare/product/{topic}/intake-clarity.md when running preproposal",
193
197
  ".zsk/raws/prepare/product/{topic}/product-brief.md when running preproposal",
194
198
  ".zsk/evidence/preproposal/{run}/checkpoint-product-review.md when running preproposal",
195
199
  ],
196
- evidenceRequired: ["requirement/source IDs or paths behind each product claim", "open requirement gaps and acceptance risks", "product checkpoint verdict before roadmap/decomposition when running preproposal"],
200
+ evidenceRequired: ["requirement/source IDs or paths behind each product claim", "accepted clarifications, inferred assumptions, and one blocking question when running preproposal", "open requirement gaps and acceptance risks", "product checkpoint verdict before roadmap/decomposition when running preproposal"],
197
201
  forbiddenDecisions: ["Do not rewrite technical design or implementation ownership.", "Do not turn weak/inferred evidence into accepted requirements."],
198
202
  stopCondition: "Product facts, gaps, and acceptance risks are explicit and handed to lead-integrator.",
199
203
  },
@@ -229,33 +233,36 @@ const ROLE_CONTRACTS = {
229
233
  stopCondition: "Backend facts and gaps are reported with source references and no shared artifact edits pending.",
230
234
  },
231
235
  "frontend-engineer": {
232
- owns: ["UI implementation, routing, state, component integration, and frontend framework constraints"],
236
+ owns: ["UI implementation, routing, state, page/module-to-code component mapping, component integration, and frontend framework constraints"],
233
237
  doesNotOwn: ["source-of-truth product decisions", "backend/API correctness signoff"],
234
238
  outputs: [".zsk/evidence/{scope}/{run}/frontend-impact-report.md"],
235
- evidenceRequired: ["component/route/state file references", "UI implementation risks and validation hooks"],
239
+ evidenceRequired: ["component/route/state file references", "page/module-to-code mapping coverage", "UI implementation risks and validation hooks"],
236
240
  forbiddenDecisions: ["Do not reinterpret acceptance criteria without product-owner handoff.", "Do not approve API behavior without backend evidence."],
237
241
  stopCondition: "Frontend impact and validation needs are clear for lead-integrator.",
238
242
  },
239
243
  "design-specialist": {
240
- owns: ["design assets, visual constraints, screen/state inventory, and design snapshot validation"],
244
+ owns: ["design assets, visual constraints, screen/state inventory, provider source maps, and design snapshot validation"],
241
245
  doesNotOwn: ["backend/API correctness", "final product scope acceptance"],
242
246
  outputs: [
243
247
  ".zsk/evidence/{scope}/{run}/design-asset-report.md",
244
248
  ".zsk/raws/prepare/design/{topic}/design-source-needs.md when running preproposal",
249
+ ".zsk/raws/prepare/design/{topic}/design-source-map.md when provider-backed design sources are used",
245
250
  ],
246
- evidenceRequired: ["design/prototype source references", "screen/state map and missing asset list"],
251
+ evidenceRequired: ["design/prototype source references", "screen/state map, provider source coverage, and missing asset list"],
247
252
  forbiddenDecisions: ["Do not infer implementation truth from design assets.", "Do not store auth state or exported private assets outside declared scope."],
248
253
  stopCondition: "Design assets are mapped or blocked with provider/auth evidence.",
249
254
  },
250
255
  "ux-specialist": {
251
- owns: ["user flows, interaction constraints, usability risks, and UX source validation"],
256
+ owns: ["user flows, interaction handoff, interaction constraints, usability risks, and UX source validation"],
252
257
  doesNotOwn: ["backend/API correctness", "business priority decisions"],
253
258
  outputs: [
254
259
  ".zsk/evidence/{scope}/{run}/ux-source-report.md",
255
260
  ".zsk/raws/prepare/ux/{topic}/ux-readiness.md when running preproposal",
261
+ ".zsk/raws/prepare/ux/{topic}/interaction-handoff.md when UI, UX, or design-source interaction is triggered",
256
262
  ".zsk/evidence/preproposal/{run}/checkpoint-ux-review.md when running preproposal",
263
+ ".zsk/evidence/preproposal/{run}/checkpoint-interaction-review.md when interaction handoff is triggered",
257
264
  ],
258
- evidenceRequired: ["flow/source references", "usability risks and unresolved interaction questions"],
265
+ evidenceRequired: ["flow/source references", "AI brief draft status", "page/module interaction detail coverage", "interaction/state/a11y coverage", "usability risks and unresolved interaction questions"],
259
266
  forbiddenDecisions: ["Do not approve product scope or technical design alone.", "Do not resolve UX/product conflicts silently."],
260
267
  stopCondition: "UX facts, questions, and risks are ready for lead integration.",
261
268
  },
@@ -464,7 +471,7 @@ function seedFromRolePool(role, entries, overrides = {}) {
464
471
  reason: overrides.reason ?? role.reason ?? `configured ${role.role} role`,
465
472
  entries,
466
473
  activation: overrides.activation ?? role.activation,
467
- extraInputs: role.extraInputs,
474
+ extraInputs: unique([...(role.extraInputs ?? []), ...(overrides.extraInputs ?? [])]),
468
475
  writeScope: unique([...(role.writeScope ?? []), ...(overrides.writeScope ?? [])]),
469
476
  outputs: unique([...(role.outputs ?? []), ...(overrides.outputs ?? [])]),
470
477
  evidenceRequired: unique([...(role.evidenceRequired ?? []), ...(overrides.evidenceRequired ?? [])]),
@@ -559,7 +566,7 @@ export function buildStaffingPlan(target, config, opts = {}, rolePool = BUILTIN_
559
566
  const reviewMode = reviewModeForReviewTarget(reviewTarget);
560
567
  const timeoutPolicy = packetTimeoutPolicyFromConfig(config);
561
568
  const entries = flattenProjectSources(config.sources);
562
- const seeds = seedRoles(stage, skill, entries, rolePool, reviewMode);
569
+ const seeds = seedRoles(stage, skill, entries, rolePool, reviewMode, opts.module);
563
570
  const orchestration = buildOrchestrationPlan(surface, stage, entries, seeds, config);
564
571
  const roles = seeds.map((seed) => buildRole(seed, stage, skill, orchestration, config));
565
572
  const dir = resolve(target, getWorkspacePath(config, "evidenceRoot"), "dispatch", runId);
@@ -660,7 +667,7 @@ function markPacketStale(packet, now) {
660
667
  blocker: "No heartbeat was recorded before the packet deadline; route this lane through leader-sequential fallback or re-emit with a new packet.",
661
668
  };
662
669
  }
663
- function seedRoles(stage, skill, entries, rolePool, reviewMode) {
670
+ function seedRoles(stage, skill, entries, rolePool, reviewMode, module) {
664
671
  const seeds = new Map();
665
672
  const poolRoles = Object.values(rolePool.roles);
666
673
  for (const role of poolRoles) {
@@ -706,13 +713,26 @@ function seedRoles(stage, skill, entries, rolePool, reviewMode) {
706
713
  }
707
714
  }
708
715
  if (stage === "preproposal" || skill === "preproposal") {
716
+ const topic = module ?? "{topic}";
717
+ const moduleInputs = module
718
+ ? [
719
+ `.zsk/modules/${module}/module.yaml`,
720
+ `.zsk/modules/${module}/CONTEXT.md`,
721
+ `.zsk/modules/${module}/proposal.md when present`,
722
+ `.zsk/modules/${module}/spec.md when present`,
723
+ `.zsk/modules/${module}/design.md when present`,
724
+ `.zsk/modules/${module}/tasks.md when present`,
725
+ ]
726
+ : [];
709
727
  for (const roleName of PREPROPOSAL_ROLE_NAMES) {
710
728
  const role = rolePool.roles[roleName];
711
729
  if (!role)
712
730
  continue;
713
731
  addSeed(seeds, seedFromRolePool(role, [], {
714
732
  activation: "required for preproposal product/roadmap/UX/readiness checkpoint coverage",
715
- reason: role.reason || "produce and review preproposal raw resources before formal proposal",
733
+ reason: module
734
+ ? role.reason || `produce and review module-scoped preproposal raw resources for ${module} before formal proposal`
735
+ : role.reason || "produce and review preproposal raw resources before formal proposal",
716
736
  writeScope: [
717
737
  ".zsk/raws/prepare/product/**",
718
738
  ".zsk/raws/prepare/ux/**",
@@ -723,23 +743,37 @@ function seedRoles(stage, skill, entries, rolePool, reviewMode) {
723
743
  ...role.writeScope,
724
744
  ],
725
745
  outputs: [
726
- ".zsk/raws/prepare/product/{topic}/product-brief.md",
727
- ".zsk/raws/prepare/product/{topic}/roadmap.md",
728
- ".zsk/raws/prepare/ux/{topic}/ux-readiness.md",
729
- ".zsk/raws/prepare/design/{topic}/design-source-needs.md",
746
+ `.zsk/raws/prepare/product/${topic}/intake-clarity.md`,
747
+ `.zsk/raws/prepare/product/${topic}/product-brief.md`,
748
+ `.zsk/raws/prepare/product/${topic}/roadmap.md`,
749
+ `.zsk/raws/prepare/ux/${topic}/ux-readiness.md`,
750
+ `.zsk/raws/prepare/ux/${topic}/interaction-handoff.md when UI/UX/design-source interaction is triggered`,
751
+ `.zsk/raws/prepare/design/${topic}/design-source-needs.md`,
752
+ `.zsk/raws/prepare/design/${topic}/design-source-map.md when provider-backed design sources are used`,
730
753
  ".zsk/evidence/preproposal/{run}/checkpoint-*.md",
731
754
  ".zsk/evidence/preproposal/{run}/readiness-review.md",
732
755
  ...role.outputs,
733
756
  ],
734
757
  evidenceRequired: [
758
+ ...(module ? [
759
+ `module target is fixed to ${module}; module docs and raw sources are challenged before widening scope`,
760
+ `interaction handoff and design-source map use ${module} as the default raw topic unless a narrower page/topic is justified`,
761
+ ] : []),
762
+ "source-discoverable questions answered before user clarification",
763
+ "accepted clarifications, inferred assumptions, and one blocking question are separated",
735
764
  "product checkpoint passes before roadmap/decomposition",
736
765
  "roadmap/decomposition checkpoint passes before UX/design-readiness",
766
+ "AI brief drafts and candidate code component mapping exist for source-backed page/module interaction details before asking humans to fill gaps",
767
+ "interaction handoff separates sourced provider facts from accepted decisions, assumptions, and missing page/module interaction details when triggered",
737
768
  "UX/design-readiness checkpoint passes before readiness handoff",
738
769
  "final readiness review passes or blocks with owner, missing input, impact, and next action",
739
770
  ...role.evidenceRequired,
740
771
  ],
772
+ ...(moduleInputs.length > 0 ? { extraInputs: moduleInputs } : {}),
741
773
  contract: {
742
- owns: ["preproposal lane facts, source gaps, checkpoint evidence, and readiness handoff for this role"],
774
+ owns: module
775
+ ? [`preproposal lane facts, source gaps, checkpoint evidence, and readiness handoff for module ${module}`]
776
+ : ["preproposal lane facts, source gaps, checkpoint evidence, and readiness handoff for this role"],
743
777
  doesNotOwn: ["formal module proposal/spec/design/task artifacts", "formal test cases", "implementation edits"],
744
778
  forbiddenDecisions: ["Do not skip checkpoint order.", "Do not treat scenario seeds as formal post-design test cases."],
745
779
  stopCondition: "Preproposal lane output is reviewable, or blockers are recorded for the checkpoint owner.",