@captain_z/zsk 1.8.3 → 1.8.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/bin.js +13 -0
- package/dist/bin.js.map +1 -1
- 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/commands/check.js +14 -575
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/config.js +1 -1
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/demo.d.ts +5 -0
- package/dist/commands/demo.js +70 -297
- package/dist/commands/demo.js.map +1 -1
- package/dist/commands/doctor.js +9 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/gate.d.ts +1 -0
- package/dist/commands/gate.js +8 -2
- package/dist/commands/gate.js.map +1 -1
- package/dist/commands/prepare.js +7 -1
- package/dist/commands/prepare.js.map +1 -1
- package/dist/commands/project-init.js +30 -8
- package/dist/commands/project-init.js.map +1 -1
- package/dist/core/config.d.ts +68 -0
- package/dist/core/config.js +198 -15
- package/dist/core/config.js.map +1 -1
- package/dist/core/demo-auth.d.ts +30 -0
- package/dist/core/demo-auth.js +213 -0
- package/dist/core/demo-auth.js.map +1 -0
- package/dist/core/demo-scenarios.d.ts +62 -0
- package/dist/core/demo-scenarios.js +276 -0
- package/dist/core/demo-scenarios.js.map +1 -0
- package/dist/core/demo-sources.d.ts +37 -0
- package/dist/core/demo-sources.js +198 -0
- package/dist/core/demo-sources.js.map +1 -0
- package/dist/core/mcp-registry-discovery.d.ts +16 -0
- package/dist/core/mcp-registry-discovery.js +187 -0
- package/dist/core/mcp-registry-discovery.js.map +1 -0
- package/dist/core/origin-detection.js +1 -1
- package/dist/core/origin-detection.js.map +1 -1
- package/dist/core/prepare-artifacts.d.ts +16 -0
- package/dist/core/prepare-artifacts.js +25 -0
- package/dist/core/prepare-artifacts.js.map +1 -0
- package/dist/core/prepare-auth-helper.d.ts +8 -0
- package/dist/core/prepare-auth-helper.js +32 -0
- package/dist/core/prepare-auth-helper.js.map +1 -0
- package/dist/core/prepare-materialization.d.ts +8 -0
- package/dist/core/prepare-materialization.js +26 -0
- package/dist/core/prepare-materialization.js.map +1 -0
- package/dist/core/prepare-migration.d.ts +6 -0
- package/dist/core/prepare-migration.js +57 -0
- package/dist/core/prepare-migration.js.map +1 -0
- package/dist/core/prepare-reporting.d.ts +5 -0
- package/dist/core/prepare-reporting.js +106 -0
- package/dist/core/prepare-reporting.js.map +1 -0
- package/dist/core/prepare-routing.d.ts +12 -0
- package/dist/core/prepare-routing.js +182 -0
- package/dist/core/prepare-routing.js.map +1 -0
- package/dist/core/prepare-sync.d.ts +13 -53
- package/dist/core/prepare-sync.js +878 -359
- package/dist/core/prepare-sync.js.map +1 -1
- package/dist/core/prepare-utils.d.ts +6 -0
- package/dist/core/prepare-utils.js +35 -0
- package/dist/core/prepare-utils.js.map +1 -0
- 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/provider-policy.d.ts +26 -0
- package/dist/core/provider-policy.js +180 -0
- package/dist/core/provider-policy.js.map +1 -0
- package/dist/core/provider-readiness.d.ts +39 -0
- package/dist/core/provider-readiness.js +78 -0
- package/dist/core/provider-readiness.js.map +1 -0
- package/dist/core/source-adapter-normalization.d.ts +31 -0
- package/dist/core/source-adapter-normalization.js +235 -0
- package/dist/core/source-adapter-normalization.js.map +1 -0
- package/dist/core/source-snapshot-adapters.d.ts +59 -0
- package/dist/core/source-snapshot-adapters.js +60 -0
- package/dist/core/source-snapshot-adapters.js.map +1 -0
- package/dist/core/staffing-plan.d.ts +1 -0
- package/dist/core/staffing-plan.js +113 -21
- 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 +316 -0
- package/dist/core/stage-clarity-verification.js.map +1 -0
- package/dist/core/stage-output-quality.d.ts +3 -0
- package/dist/core/stage-output-quality.js +122 -0
- package/dist/core/stage-output-quality.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 +105 -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 +286 -0
- package/dist/core/stage-quality-criteria.js.map +1 -0
- package/dist/core/stage-quality-rendering.d.ts +15 -0
- package/dist/core/stage-quality-rendering.js +240 -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 +54 -795
- package/dist/core/stage-quality.js.map +1 -1
- package/dist/core/template-registry.js +12 -15
- package/dist/core/template-registry.js.map +1 -1
- package/dist/core/workspace-conformance.d.ts +39 -0
- package/dist/core/workspace-conformance.js +603 -0
- package/dist/core/workspace-conformance.js.map +1 -0
- package/package.json +2 -2
- package/schemas/providers.schema.json +74 -0
- package/schemas/zsk-config.schema.json +417 -1
- 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/README.md +48 -0
- package/templates/project-init/.zsk/config.yaml +37 -0
- package/templates/project-init/.zsk/docs/CONFIG-SCHEMA.md +127 -0
- package/templates/project-init/.zsk/docs/PROJECT-CONFIG.md +53 -5
- package/templates/project-init/.zsk/docs/README.md +10 -0
- package/templates/project-init/.zsk/docs/SECURITY.md +34 -0
- package/templates/project-init/.zsk/docs/SYSTEM-SPEC.md +39 -7
- package/templates/project-init/.zsk/evidence/README.md +15 -0
- package/templates/project-init/.zsk/issues/README.md +10 -0
- package/templates/project-init/.zsk/modules/README.md +19 -0
- package/templates/project-init/.zsk/modules/index.md +9 -5
- package/templates/project-init/.zsk/raws/README.md +34 -0
- package/templates/project-init/.zsk/roles.yaml +36 -105
- package/templates/project-init/.zsk/templates/config.examples.yaml +83 -0
- package/templates/project-init/.zsk/templates/issue-card.md +23 -0
- package/templates/project-init/.zsk/templates/module/README.md +13 -0
- package/templates/project-init/.zsk/templates/module/design.md +22 -0
- package/templates/project-init/.zsk/templates/module/module.yaml +15 -0
- package/templates/project-init/.zsk/templates/module/proposal.md +20 -0
- package/templates/project-init/.zsk/templates/module/spec.md +22 -0
- package/templates/project-init/.zsk/templates/module/tasks.md +16 -0
- package/templates/project-init/.zsk/raws/index.md +0 -18
- package/templates/project-init/.zsk/raws/manifest.json +0 -4
- package/templates/project-init/.zsk/raws/prepare/backend/index.md +0 -4
- package/templates/project-init/.zsk/raws/prepare/design/index.md +0 -3
- package/templates/project-init/.zsk/raws/prepare/index.md +0 -4
- package/templates/project-init/.zsk/raws/prepare/product/index.md +0 -4
- package/templates/project-init/.zsk/raws/prepare/qa/index.md +0 -4
- package/templates/project-init/.zsk/raws/prepare/ux/index.md +0 -3
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type ProjectConfig, type SourceConfig, type SourceEntry } from "./config.js";
|
|
2
|
+
import { type OriginInference } from "./origin-detection.js";
|
|
3
|
+
import { type SourceSnapshotAdapterId } from "./source-adapter-normalization.js";
|
|
4
|
+
export type PrepareSyncOptions = {
|
|
5
|
+
source?: string;
|
|
6
|
+
all?: boolean;
|
|
7
|
+
allowNetwork?: boolean;
|
|
8
|
+
authState?: string;
|
|
9
|
+
authProfile?: string;
|
|
10
|
+
browser?: boolean;
|
|
11
|
+
dryRun?: boolean;
|
|
12
|
+
runId?: string;
|
|
13
|
+
};
|
|
14
|
+
export type PrepareSyncStatus = "materialized" | "materialized-partial" | "metadata-only" | "blocked-auth" | "source-gap" | "skipped" | "failed";
|
|
15
|
+
export type PrepareSyncResult = {
|
|
16
|
+
envelopeVersion?: 1;
|
|
17
|
+
sourceKey: string;
|
|
18
|
+
sourcePath: string;
|
|
19
|
+
rawLane?: string;
|
|
20
|
+
provider?: string;
|
|
21
|
+
adapter?: string;
|
|
22
|
+
strategy: string;
|
|
23
|
+
status: PrepareSyncStatus;
|
|
24
|
+
origin?: string;
|
|
25
|
+
resolvedOrigin?: string;
|
|
26
|
+
contentType?: string;
|
|
27
|
+
snapshot?: string;
|
|
28
|
+
snapshotHash?: string;
|
|
29
|
+
previousSnapshotHash?: string;
|
|
30
|
+
metadata?: Record<string, unknown>;
|
|
31
|
+
changed: boolean;
|
|
32
|
+
reason: string;
|
|
33
|
+
validation: Record<string, "pass" | "fail" | "skipped">;
|
|
34
|
+
};
|
|
35
|
+
export type PrepareSyncBase = Omit<PrepareSyncResult, "strategy" | "status" | "changed" | "reason" | "validation">;
|
|
36
|
+
export type SourceSnapshotProviderAdapter = SourceSnapshotAdapterId;
|
|
37
|
+
export type SourceSnapshotContext = {
|
|
38
|
+
target: string;
|
|
39
|
+
config: ProjectConfig;
|
|
40
|
+
entry: SourceEntry;
|
|
41
|
+
source: SourceConfig;
|
|
42
|
+
origin: OriginInference;
|
|
43
|
+
opts: PrepareSyncOptions;
|
|
44
|
+
snapshot: string;
|
|
45
|
+
snapshotPath: string;
|
|
46
|
+
previousSnapshotHash?: string;
|
|
47
|
+
base: PrepareSyncBase;
|
|
48
|
+
};
|
|
49
|
+
export type SourceSnapshotAdapterHandlers = {
|
|
50
|
+
dryRun: (context: SourceSnapshotContext) => Promise<PrepareSyncResult> | PrepareSyncResult;
|
|
51
|
+
local: (context: SourceSnapshotContext) => Promise<PrepareSyncResult>;
|
|
52
|
+
provider: (context: SourceSnapshotContext, adapter: SourceSnapshotProviderAdapter) => Promise<PrepareSyncResult | null>;
|
|
53
|
+
repository: (context: SourceSnapshotContext) => Promise<PrepareSyncResult>;
|
|
54
|
+
url: (context: SourceSnapshotContext) => Promise<PrepareSyncResult>;
|
|
55
|
+
providerManaged: (context: SourceSnapshotContext) => Promise<PrepareSyncResult> | PrepareSyncResult;
|
|
56
|
+
};
|
|
57
|
+
export declare function createSourceSnapshotContext(target: string, config: ProjectConfig, entry: SourceEntry, opts: PrepareSyncOptions, previousSnapshotHashFor: (snapshotPath: string) => Promise<string | undefined>): Promise<SourceSnapshotContext>;
|
|
58
|
+
export declare function acquireSourceSnapshot(context: SourceSnapshotContext, handlers: SourceSnapshotAdapterHandlers): Promise<PrepareSyncResult>;
|
|
59
|
+
export declare function chooseSourceSnapshotStrategy(method: string): string;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { resolveSourceSnapshot, } from "./config.js";
|
|
3
|
+
import { inferSourceOrigin } from "./origin-detection.js";
|
|
4
|
+
import { selectSourceSnapshotAdapter, } from "./source-adapter-normalization.js";
|
|
5
|
+
export async function createSourceSnapshotContext(target, config, entry, opts, previousSnapshotHashFor) {
|
|
6
|
+
const source = entry.source;
|
|
7
|
+
const origin = inferSourceOrigin(source);
|
|
8
|
+
const snapshot = resolveSourceSnapshot(config, entry);
|
|
9
|
+
const snapshotPath = resolve(target, snapshot);
|
|
10
|
+
const previousSnapshotHash = await previousSnapshotHashFor(snapshotPath);
|
|
11
|
+
const base = {
|
|
12
|
+
envelopeVersion: 1,
|
|
13
|
+
sourceKey: entry.id,
|
|
14
|
+
sourcePath: entry.path,
|
|
15
|
+
rawLane: entry.rawLane,
|
|
16
|
+
provider: origin.provider,
|
|
17
|
+
origin: origin.ref,
|
|
18
|
+
snapshot,
|
|
19
|
+
previousSnapshotHash,
|
|
20
|
+
};
|
|
21
|
+
return {
|
|
22
|
+
target,
|
|
23
|
+
config,
|
|
24
|
+
entry,
|
|
25
|
+
source,
|
|
26
|
+
origin,
|
|
27
|
+
opts,
|
|
28
|
+
snapshot,
|
|
29
|
+
snapshotPath,
|
|
30
|
+
previousSnapshotHash,
|
|
31
|
+
base,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export async function acquireSourceSnapshot(context, handlers) {
|
|
35
|
+
if (context.opts.dryRun)
|
|
36
|
+
return handlers.dryRun(context);
|
|
37
|
+
if (context.origin.method === "local")
|
|
38
|
+
return handlers.local(context);
|
|
39
|
+
const providerAdapter = selectSourceSnapshotAdapter(context.source, context.origin);
|
|
40
|
+
if (providerAdapter) {
|
|
41
|
+
const result = await handlers.provider(context, providerAdapter);
|
|
42
|
+
if (result)
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
if (context.origin.method === "repository")
|
|
46
|
+
return handlers.repository(context);
|
|
47
|
+
if (context.origin.method === "url")
|
|
48
|
+
return handlers.url(context);
|
|
49
|
+
return handlers.providerManaged(context);
|
|
50
|
+
}
|
|
51
|
+
export function chooseSourceSnapshotStrategy(method) {
|
|
52
|
+
if (method === "local")
|
|
53
|
+
return "local-copy-structured-markdown";
|
|
54
|
+
if (method === "repository")
|
|
55
|
+
return "repository-metadata-only";
|
|
56
|
+
if (method === "url")
|
|
57
|
+
return "playwright-auth-or-direct-fetch";
|
|
58
|
+
return "confirm-acquisition-method";
|
|
59
|
+
}
|
|
60
|
+
//# 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":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,qBAAqB,GAItB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAwB,MAAM,uBAAuB,CAAC;AAChF,OAAO,EACL,2BAA2B,GAE5B,MAAM,mCAAmC,CAAC;AAwE3C,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,MAAc,EACd,MAAqB,EACrB,KAAkB,EAClB,IAAwB,EACxB,uBAA8E;IAE9E,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5B,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,qBAAqB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACtD,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC/C,MAAM,oBAAoB,GAAG,MAAM,uBAAuB,CAAC,YAAY,CAAC,CAAC;IACzE,MAAM,IAAI,GAAoB;QAC5B,eAAe,EAAE,CAAC;QAClB,SAAS,EAAE,KAAK,CAAC,EAAE;QACnB,UAAU,EAAE,KAAK,CAAC,IAAI;QACtB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,MAAM,EAAE,MAAM,CAAC,GAAG;QAClB,QAAQ;QACR,oBAAoB;KACrB,CAAC;IACF,OAAO;QACL,MAAM;QACN,MAAM;QACN,KAAK;QACL,MAAM;QACN,MAAM;QACN,IAAI;QACJ,QAAQ;QACR,YAAY;QACZ,oBAAoB;QACpB,IAAI;KACL,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAA8B,EAC9B,QAAuC;IAEvC,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACzD,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,OAAO;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAEtE,MAAM,eAAe,GAAG,2BAA2B,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACpF,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QACjE,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;IAC5B,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,YAAY;QAAE,OAAO,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAChF,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,KAAK;QAAE,OAAO,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAClE,OAAO,QAAQ,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,MAAc;IACzD,IAAI,MAAM,KAAK,OAAO;QAAE,OAAO,gCAAgC,CAAC;IAChE,IAAI,MAAM,KAAK,YAAY;QAAE,OAAO,0BAA0B,CAAC;IAC/D,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,iCAAiC,CAAC;IAC/D,OAAO,4BAA4B,CAAC;AACtC,CAAC"}
|
|
@@ -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"
|
|
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
|
},
|
|
@@ -378,7 +385,7 @@ async function readStaffingRolePool(target, config) {
|
|
|
378
385
|
if (config.staffing?.roles) {
|
|
379
386
|
pools.push(parseRolePool({ roles: config.staffing.roles }));
|
|
380
387
|
}
|
|
381
|
-
return mergeRolePools(...pools);
|
|
388
|
+
return resolveRoleInheritance(mergeRolePools(...pools));
|
|
382
389
|
}
|
|
383
390
|
function parseRolePool(value) {
|
|
384
391
|
const rolesValue = isRecord(value) ? value.roles : undefined;
|
|
@@ -389,16 +396,24 @@ function parseRolePool(value) {
|
|
|
389
396
|
if (!isRecord(config))
|
|
390
397
|
continue;
|
|
391
398
|
entries.push(rolePoolEntry(role, {
|
|
399
|
+
baseRole: stringValue(config.extends),
|
|
392
400
|
subagentType: stringValue(config.subagentType),
|
|
393
401
|
reason: stringValue(config.reason),
|
|
394
402
|
stages: stringList(config.stages),
|
|
395
403
|
skills: stringList(config.skills),
|
|
396
|
-
lanes:
|
|
404
|
+
lanes: unique([
|
|
405
|
+
...stringList(config.lanes),
|
|
406
|
+
...stringList(config.resources),
|
|
407
|
+
...stringList(config.artifacts),
|
|
408
|
+
]),
|
|
397
409
|
required: booleanValue(config.required),
|
|
398
410
|
remoteSources: booleanValue(config.remoteSources),
|
|
399
411
|
activation: stringValue(config.activation),
|
|
400
412
|
extraInputs: stringList(config.inputs),
|
|
401
|
-
writeScope:
|
|
413
|
+
writeScope: unique([
|
|
414
|
+
...stringList(config.writeScope),
|
|
415
|
+
...stringList(config.writeScopes),
|
|
416
|
+
]),
|
|
402
417
|
outputs: stringList(config.outputs),
|
|
403
418
|
evidenceRequired: stringList(config.evidenceRequired),
|
|
404
419
|
contract: {
|
|
@@ -424,6 +439,7 @@ function mergeRolePools(...pools) {
|
|
|
424
439
|
function mergeRolePoolRole(base, override) {
|
|
425
440
|
return {
|
|
426
441
|
role: base.role,
|
|
442
|
+
baseRole: override.baseRole ?? base.baseRole,
|
|
427
443
|
subagentType: override.subagentType ?? base.subagentType,
|
|
428
444
|
reason: override.reason ?? base.reason,
|
|
429
445
|
stages: unique([...base.stages, ...override.stages]),
|
|
@@ -442,6 +458,7 @@ function mergeRolePoolRole(base, override) {
|
|
|
442
458
|
function rolePoolEntry(role, config) {
|
|
443
459
|
return [role, {
|
|
444
460
|
role,
|
|
461
|
+
baseRole: config.baseRole,
|
|
445
462
|
subagentType: config.subagentType,
|
|
446
463
|
reason: config.reason,
|
|
447
464
|
stages: normalizeList(config.stages ?? []),
|
|
@@ -457,6 +474,54 @@ function rolePoolEntry(role, config) {
|
|
|
457
474
|
contract: config.contract,
|
|
458
475
|
}];
|
|
459
476
|
}
|
|
477
|
+
function resolveRoleInheritance(pool) {
|
|
478
|
+
const resolving = new Set();
|
|
479
|
+
const resolved = new Map();
|
|
480
|
+
const resolveRole = (name) => {
|
|
481
|
+
const cached = resolved.get(name);
|
|
482
|
+
if (cached)
|
|
483
|
+
return cached;
|
|
484
|
+
const role = pool.roles[name];
|
|
485
|
+
if (!role)
|
|
486
|
+
return undefined;
|
|
487
|
+
if (!role.baseRole) {
|
|
488
|
+
resolved.set(name, role);
|
|
489
|
+
return role;
|
|
490
|
+
}
|
|
491
|
+
if (resolving.has(name)) {
|
|
492
|
+
resolved.set(name, role);
|
|
493
|
+
return role;
|
|
494
|
+
}
|
|
495
|
+
resolving.add(name);
|
|
496
|
+
const base = resolveRole(role.baseRole);
|
|
497
|
+
resolving.delete(name);
|
|
498
|
+
const merged = base ? inheritRole(base, role) : role;
|
|
499
|
+
resolved.set(name, merged);
|
|
500
|
+
return merged;
|
|
501
|
+
};
|
|
502
|
+
for (const name of Object.keys(pool.roles))
|
|
503
|
+
resolveRole(name);
|
|
504
|
+
return { roles: Object.fromEntries(resolved) };
|
|
505
|
+
}
|
|
506
|
+
function inheritRole(base, role) {
|
|
507
|
+
return {
|
|
508
|
+
role: role.role,
|
|
509
|
+
baseRole: role.baseRole,
|
|
510
|
+
subagentType: role.subagentType ?? base.subagentType,
|
|
511
|
+
reason: role.reason ?? base.reason,
|
|
512
|
+
stages: unique([...base.stages, ...role.stages]),
|
|
513
|
+
skills: unique([...base.skills, ...role.skills]),
|
|
514
|
+
lanes: unique([...base.lanes, ...role.lanes]),
|
|
515
|
+
required: role.required,
|
|
516
|
+
remoteSources: base.remoteSources || role.remoteSources,
|
|
517
|
+
activation: role.activation ?? base.activation,
|
|
518
|
+
extraInputs: unique([...base.extraInputs, ...role.extraInputs]),
|
|
519
|
+
writeScope: unique([...base.writeScope, ...role.writeScope]),
|
|
520
|
+
outputs: unique([...base.outputs, ...role.outputs]),
|
|
521
|
+
evidenceRequired: unique([...base.evidenceRequired, ...role.evidenceRequired]),
|
|
522
|
+
contract: mergeContractOverrides(base.contract, role.contract),
|
|
523
|
+
};
|
|
524
|
+
}
|
|
460
525
|
function seedFromRolePool(role, entries, overrides = {}) {
|
|
461
526
|
return {
|
|
462
527
|
role: role.role,
|
|
@@ -464,7 +529,7 @@ function seedFromRolePool(role, entries, overrides = {}) {
|
|
|
464
529
|
reason: overrides.reason ?? role.reason ?? `configured ${role.role} role`,
|
|
465
530
|
entries,
|
|
466
531
|
activation: overrides.activation ?? role.activation,
|
|
467
|
-
extraInputs: role.extraInputs,
|
|
532
|
+
extraInputs: unique([...(role.extraInputs ?? []), ...(overrides.extraInputs ?? [])]),
|
|
468
533
|
writeScope: unique([...(role.writeScope ?? []), ...(overrides.writeScope ?? [])]),
|
|
469
534
|
outputs: unique([...(role.outputs ?? []), ...(overrides.outputs ?? [])]),
|
|
470
535
|
evidenceRequired: unique([...(role.evidenceRequired ?? []), ...(overrides.evidenceRequired ?? [])]),
|
|
@@ -559,7 +624,7 @@ export function buildStaffingPlan(target, config, opts = {}, rolePool = BUILTIN_
|
|
|
559
624
|
const reviewMode = reviewModeForReviewTarget(reviewTarget);
|
|
560
625
|
const timeoutPolicy = packetTimeoutPolicyFromConfig(config);
|
|
561
626
|
const entries = flattenProjectSources(config.sources);
|
|
562
|
-
const seeds = seedRoles(stage, skill, entries, rolePool, reviewMode);
|
|
627
|
+
const seeds = seedRoles(stage, skill, entries, rolePool, reviewMode, opts.module);
|
|
563
628
|
const orchestration = buildOrchestrationPlan(surface, stage, entries, seeds, config);
|
|
564
629
|
const roles = seeds.map((seed) => buildRole(seed, stage, skill, orchestration, config));
|
|
565
630
|
const dir = resolve(target, getWorkspacePath(config, "evidenceRoot"), "dispatch", runId);
|
|
@@ -660,7 +725,7 @@ function markPacketStale(packet, now) {
|
|
|
660
725
|
blocker: "No heartbeat was recorded before the packet deadline; route this lane through leader-sequential fallback or re-emit with a new packet.",
|
|
661
726
|
};
|
|
662
727
|
}
|
|
663
|
-
function seedRoles(stage, skill, entries, rolePool, reviewMode) {
|
|
728
|
+
function seedRoles(stage, skill, entries, rolePool, reviewMode, module) {
|
|
664
729
|
const seeds = new Map();
|
|
665
730
|
const poolRoles = Object.values(rolePool.roles);
|
|
666
731
|
for (const role of poolRoles) {
|
|
@@ -706,13 +771,26 @@ function seedRoles(stage, skill, entries, rolePool, reviewMode) {
|
|
|
706
771
|
}
|
|
707
772
|
}
|
|
708
773
|
if (stage === "preproposal" || skill === "preproposal") {
|
|
774
|
+
const topic = module ?? "{topic}";
|
|
775
|
+
const moduleInputs = module
|
|
776
|
+
? [
|
|
777
|
+
`.zsk/modules/${module}/module.yaml`,
|
|
778
|
+
`.zsk/modules/${module}/CONTEXT.md`,
|
|
779
|
+
`.zsk/modules/${module}/proposal.md when present`,
|
|
780
|
+
`.zsk/modules/${module}/spec.md when present`,
|
|
781
|
+
`.zsk/modules/${module}/design.md when present`,
|
|
782
|
+
`.zsk/modules/${module}/tasks.md when present`,
|
|
783
|
+
]
|
|
784
|
+
: [];
|
|
709
785
|
for (const roleName of PREPROPOSAL_ROLE_NAMES) {
|
|
710
786
|
const role = rolePool.roles[roleName];
|
|
711
787
|
if (!role)
|
|
712
788
|
continue;
|
|
713
789
|
addSeed(seeds, seedFromRolePool(role, [], {
|
|
714
790
|
activation: "required for preproposal product/roadmap/UX/readiness checkpoint coverage",
|
|
715
|
-
reason:
|
|
791
|
+
reason: module
|
|
792
|
+
? role.reason || `produce and review module-scoped preproposal raw resources for ${module} before formal proposal`
|
|
793
|
+
: role.reason || "produce and review preproposal raw resources before formal proposal",
|
|
716
794
|
writeScope: [
|
|
717
795
|
".zsk/raws/prepare/product/**",
|
|
718
796
|
".zsk/raws/prepare/ux/**",
|
|
@@ -723,23 +801,37 @@ function seedRoles(stage, skill, entries, rolePool, reviewMode) {
|
|
|
723
801
|
...role.writeScope,
|
|
724
802
|
],
|
|
725
803
|
outputs: [
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
804
|
+
`.zsk/raws/prepare/product/${topic}/intake-clarity.md`,
|
|
805
|
+
`.zsk/raws/prepare/product/${topic}/product-brief.md`,
|
|
806
|
+
`.zsk/raws/prepare/product/${topic}/roadmap.md`,
|
|
807
|
+
`.zsk/raws/prepare/ux/${topic}/ux-readiness.md`,
|
|
808
|
+
`.zsk/raws/prepare/ux/${topic}/interaction-handoff.md when UI/UX/design-source interaction is triggered`,
|
|
809
|
+
`.zsk/raws/prepare/design/${topic}/design-source-needs.md`,
|
|
810
|
+
`.zsk/raws/prepare/design/${topic}/design-source-map.md when provider-backed design sources are used`,
|
|
730
811
|
".zsk/evidence/preproposal/{run}/checkpoint-*.md",
|
|
731
812
|
".zsk/evidence/preproposal/{run}/readiness-review.md",
|
|
732
813
|
...role.outputs,
|
|
733
814
|
],
|
|
734
815
|
evidenceRequired: [
|
|
816
|
+
...(module ? [
|
|
817
|
+
`module target is fixed to ${module}; module docs and raw sources are challenged before widening scope`,
|
|
818
|
+
`interaction handoff and design-source map use ${module} as the default raw topic unless a narrower page/topic is justified`,
|
|
819
|
+
] : []),
|
|
820
|
+
"source-discoverable questions answered before user clarification",
|
|
821
|
+
"accepted clarifications, inferred assumptions, and one blocking question are separated",
|
|
735
822
|
"product checkpoint passes before roadmap/decomposition",
|
|
736
823
|
"roadmap/decomposition checkpoint passes before UX/design-readiness",
|
|
824
|
+
"AI brief drafts and candidate code component mapping exist for source-backed page/module interaction details before asking humans to fill gaps",
|
|
825
|
+
"interaction handoff separates sourced provider facts from accepted decisions, assumptions, and missing page/module interaction details when triggered",
|
|
737
826
|
"UX/design-readiness checkpoint passes before readiness handoff",
|
|
738
827
|
"final readiness review passes or blocks with owner, missing input, impact, and next action",
|
|
739
828
|
...role.evidenceRequired,
|
|
740
829
|
],
|
|
830
|
+
...(moduleInputs.length > 0 ? { extraInputs: moduleInputs } : {}),
|
|
741
831
|
contract: {
|
|
742
|
-
owns:
|
|
832
|
+
owns: module
|
|
833
|
+
? [`preproposal lane facts, source gaps, checkpoint evidence, and readiness handoff for module ${module}`]
|
|
834
|
+
: ["preproposal lane facts, source gaps, checkpoint evidence, and readiness handoff for this role"],
|
|
743
835
|
doesNotOwn: ["formal module proposal/spec/design/task artifacts", "formal test cases", "implementation edits"],
|
|
744
836
|
forbiddenDecisions: ["Do not skip checkpoint order.", "Do not treat scenario seeds as formal post-design test cases."],
|
|
745
837
|
stopCondition: "Preproposal lane output is reviewable, or blockers are recorded for the checkpoint owner.",
|