@specship/specship-win32-arm64 0.25.0 → 0.29.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.
- package/bin/specship.cmd +31 -1
- package/lib/dist/activation/cheatsheet.d.ts +17 -1
- package/lib/dist/activation/cheatsheet.d.ts.map +1 -1
- package/lib/dist/activation/cheatsheet.js +47 -3
- package/lib/dist/activation/cheatsheet.js.map +1 -1
- package/lib/dist/activation/hook-output.d.ts +80 -0
- package/lib/dist/activation/hook-output.d.ts.map +1 -0
- package/lib/dist/activation/hook-output.js +103 -0
- package/lib/dist/activation/hook-output.js.map +1 -0
- package/lib/dist/activation/search-intercept.d.ts +60 -29
- package/lib/dist/activation/search-intercept.d.ts.map +1 -1
- package/lib/dist/activation/search-intercept.js +159 -55
- package/lib/dist/activation/search-intercept.js.map +1 -1
- package/lib/dist/activation/steering.d.ts +8 -10
- package/lib/dist/activation/steering.d.ts.map +1 -1
- package/lib/dist/activation/steering.js +21 -6
- package/lib/dist/activation/steering.js.map +1 -1
- package/lib/dist/behaviour/behaviour-surface.d.ts +47 -0
- package/lib/dist/behaviour/behaviour-surface.d.ts.map +1 -1
- package/lib/dist/behaviour/behaviour-surface.js +108 -2
- package/lib/dist/behaviour/behaviour-surface.js.map +1 -1
- package/lib/dist/bin/node-version-check.d.ts +22 -7
- package/lib/dist/bin/node-version-check.d.ts.map +1 -1
- package/lib/dist/bin/node-version-check.js +39 -9
- package/lib/dist/bin/node-version-check.js.map +1 -1
- package/lib/dist/bin/specship.js +799 -81
- package/lib/dist/bin/specship.js.map +1 -1
- package/lib/dist/commands/specship/learn.md +22 -0
- package/lib/dist/commands/specship/spec.md +19 -1
- package/lib/dist/db/sqlite-adapter.d.ts +7 -5
- package/lib/dist/db/sqlite-adapter.d.ts.map +1 -1
- package/lib/dist/db/sqlite-adapter.js +11 -9
- package/lib/dist/db/sqlite-adapter.js.map +1 -1
- package/lib/dist/design-md/check.d.ts +51 -0
- package/lib/dist/design-md/check.d.ts.map +1 -0
- package/lib/dist/design-md/check.js +335 -0
- package/lib/dist/design-md/check.js.map +1 -0
- package/lib/dist/design-md/css.d.ts +40 -0
- package/lib/dist/design-md/css.d.ts.map +1 -0
- package/lib/dist/design-md/css.js +224 -0
- package/lib/dist/design-md/css.js.map +1 -0
- package/lib/dist/design-md/extract.d.ts +84 -0
- package/lib/dist/design-md/extract.d.ts.map +1 -0
- package/lib/dist/design-md/extract.js +595 -0
- package/lib/dist/design-md/extract.js.map +1 -0
- package/lib/dist/design-md/maintain.d.ts +45 -0
- package/lib/dist/design-md/maintain.d.ts.map +1 -0
- package/lib/dist/design-md/maintain.js +127 -0
- package/lib/dist/design-md/maintain.js.map +1 -0
- package/lib/dist/design-md/render.d.ts +28 -0
- package/lib/dist/design-md/render.d.ts.map +1 -0
- package/lib/dist/design-md/render.js +178 -0
- package/lib/dist/design-md/render.js.map +1 -0
- package/lib/dist/design-md/upkeep.d.ts +48 -0
- package/lib/dist/design-md/upkeep.d.ts.map +1 -0
- package/lib/dist/design-md/upkeep.js +169 -0
- package/lib/dist/design-md/upkeep.js.map +1 -0
- package/lib/dist/design-md/verify.d.ts +65 -0
- package/lib/dist/design-md/verify.d.ts.map +1 -0
- package/lib/dist/design-md/verify.js +311 -0
- package/lib/dist/design-md/verify.js.map +1 -0
- package/lib/dist/enforce/changed-files.d.ts +11 -0
- package/lib/dist/enforce/changed-files.d.ts.map +1 -1
- package/lib/dist/enforce/changed-files.js +42 -0
- package/lib/dist/enforce/changed-files.js.map +1 -1
- package/lib/dist/enforce/enforce.d.ts +25 -1
- package/lib/dist/enforce/enforce.d.ts.map +1 -1
- package/lib/dist/enforce/enforce.js +58 -3
- package/lib/dist/enforce/enforce.js.map +1 -1
- package/lib/dist/enforce/mutation.d.ts +46 -0
- package/lib/dist/enforce/mutation.d.ts.map +1 -0
- package/lib/dist/enforce/mutation.js +104 -0
- package/lib/dist/enforce/mutation.js.map +1 -0
- package/lib/dist/enforce/suppressions.d.ts +33 -0
- package/lib/dist/enforce/suppressions.d.ts.map +1 -0
- package/lib/dist/enforce/suppressions.js +159 -0
- package/lib/dist/enforce/suppressions.js.map +1 -0
- package/lib/dist/extraction/specs/markdown-spec-extractor.d.ts.map +1 -1
- package/lib/dist/extraction/specs/markdown-spec-extractor.js +16 -2
- package/lib/dist/extraction/specs/markdown-spec-extractor.js.map +1 -1
- package/lib/dist/graph/spec-coverage.d.ts +57 -1
- package/lib/dist/graph/spec-coverage.d.ts.map +1 -1
- package/lib/dist/graph/spec-coverage.js +129 -5
- package/lib/dist/graph/spec-coverage.js.map +1 -1
- package/lib/dist/health/smoke-check.js +2 -2
- package/lib/dist/health/smoke-check.js.map +1 -1
- package/lib/dist/index.d.ts +8 -3
- package/lib/dist/index.d.ts.map +1 -1
- package/lib/dist/index.js +65 -9
- package/lib/dist/index.js.map +1 -1
- package/lib/dist/installer/gemini-commands.d.ts +107 -0
- package/lib/dist/installer/gemini-commands.d.ts.map +1 -0
- package/lib/dist/installer/gemini-commands.js +271 -0
- package/lib/dist/installer/gemini-commands.js.map +1 -0
- package/lib/dist/installer/index.d.ts +23 -1
- package/lib/dist/installer/index.d.ts.map +1 -1
- package/lib/dist/installer/index.js +22 -3
- package/lib/dist/installer/index.js.map +1 -1
- package/lib/dist/installer/install-defaults.d.ts +19 -0
- package/lib/dist/installer/install-defaults.d.ts.map +1 -1
- package/lib/dist/installer/install-defaults.js +28 -0
- package/lib/dist/installer/install-defaults.js.map +1 -1
- package/lib/dist/installer/instructions-template.d.ts +22 -0
- package/lib/dist/installer/instructions-template.d.ts.map +1 -1
- package/lib/dist/installer/instructions-template.js +37 -1
- package/lib/dist/installer/instructions-template.js.map +1 -1
- package/lib/dist/installer/targets/claude.d.ts +5 -1
- package/lib/dist/installer/targets/claude.d.ts.map +1 -1
- package/lib/dist/installer/targets/claude.js +15 -27
- package/lib/dist/installer/targets/claude.js.map +1 -1
- package/lib/dist/installer/targets/gemini.d.ts +85 -12
- package/lib/dist/installer/targets/gemini.d.ts.map +1 -1
- package/lib/dist/installer/targets/gemini.js +527 -30
- package/lib/dist/installer/targets/gemini.js.map +1 -1
- package/lib/dist/installer/targets/shared.d.ts +13 -0
- package/lib/dist/installer/targets/shared.d.ts.map +1 -1
- package/lib/dist/installer/targets/shared.js +18 -0
- package/lib/dist/installer/targets/shared.js.map +1 -1
- package/lib/dist/installer/targets/types.d.ts +12 -0
- package/lib/dist/installer/targets/types.d.ts.map +1 -1
- package/lib/dist/jira/auto-publish.d.ts +71 -4
- package/lib/dist/jira/auto-publish.d.ts.map +1 -1
- package/lib/dist/jira/auto-publish.js +186 -17
- package/lib/dist/jira/auto-publish.js.map +1 -1
- package/lib/dist/jira/reconcile.d.ts +24 -1
- package/lib/dist/jira/reconcile.d.ts.map +1 -1
- package/lib/dist/jira/reconcile.js +46 -2
- package/lib/dist/jira/reconcile.js.map +1 -1
- package/lib/dist/jira/repo-config.d.ts +9 -0
- package/lib/dist/jira/repo-config.d.ts.map +1 -1
- package/lib/dist/jira/repo-config.js +11 -0
- package/lib/dist/jira/repo-config.js.map +1 -1
- package/lib/dist/jira/types.d.ts +7 -0
- package/lib/dist/jira/types.d.ts.map +1 -1
- package/lib/dist/jira/types.js.map +1 -1
- package/lib/dist/knowledge/enforce.d.ts +75 -0
- package/lib/dist/knowledge/enforce.d.ts.map +1 -0
- package/lib/dist/knowledge/enforce.js +250 -0
- package/lib/dist/knowledge/enforce.js.map +1 -0
- package/lib/dist/knowledge/facts.d.ts +33 -0
- package/lib/dist/knowledge/facts.d.ts.map +1 -0
- package/lib/dist/knowledge/facts.js +117 -0
- package/lib/dist/knowledge/facts.js.map +1 -0
- package/lib/dist/knowledge/proposals.d.ts +88 -0
- package/lib/dist/knowledge/proposals.d.ts.map +1 -0
- package/lib/dist/knowledge/proposals.js +360 -0
- package/lib/dist/knowledge/proposals.js.map +1 -0
- package/lib/dist/knowledge/stale.d.ts +64 -0
- package/lib/dist/knowledge/stale.d.ts.map +1 -0
- package/lib/dist/knowledge/stale.js +174 -0
- package/lib/dist/knowledge/stale.js.map +1 -0
- package/lib/dist/mcp/gemini-session.d.ts +50 -0
- package/lib/dist/mcp/gemini-session.d.ts.map +1 -0
- package/lib/dist/mcp/gemini-session.js +159 -0
- package/lib/dist/mcp/gemini-session.js.map +1 -0
- package/lib/dist/mcp/jira-tools.d.ts.map +1 -1
- package/lib/dist/mcp/jira-tools.js +25 -0
- package/lib/dist/mcp/jira-tools.js.map +1 -1
- package/lib/dist/mcp/model-context.d.ts +22 -9
- package/lib/dist/mcp/model-context.d.ts.map +1 -1
- package/lib/dist/mcp/model-context.js +35 -13
- package/lib/dist/mcp/model-context.js.map +1 -1
- package/lib/dist/mcp/proxy.js +1 -1
- package/lib/dist/mcp/proxy.js.map +1 -1
- package/lib/dist/mcp/server-instructions.d.ts +16 -15
- package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
- package/lib/dist/mcp/server-instructions.js +67 -1
- package/lib/dist/mcp/server-instructions.js.map +1 -1
- package/lib/dist/mcp/session.js +1 -1
- package/lib/dist/mcp/session.js.map +1 -1
- package/lib/dist/mcp/spec-tools.d.ts +9 -1
- package/lib/dist/mcp/spec-tools.d.ts.map +1 -1
- package/lib/dist/mcp/spec-tools.js +69 -21
- package/lib/dist/mcp/spec-tools.js.map +1 -1
- package/lib/dist/mcp/tools.d.ts +37 -1
- package/lib/dist/mcp/tools.d.ts.map +1 -1
- package/lib/dist/mcp/tools.js +120 -9
- package/lib/dist/mcp/tools.js.map +1 -1
- package/lib/dist/pulse/pulse.d.ts +93 -0
- package/lib/dist/pulse/pulse.d.ts.map +1 -0
- package/lib/dist/pulse/pulse.js +401 -0
- package/lib/dist/pulse/pulse.js.map +1 -0
- package/lib/dist/reflect/apply.d.ts.map +1 -1
- package/lib/dist/reflect/apply.js +38 -3
- package/lib/dist/reflect/apply.js.map +1 -1
- package/lib/dist/reflect/auto-sweep.d.ts +26 -0
- package/lib/dist/reflect/auto-sweep.d.ts.map +1 -0
- package/lib/dist/reflect/auto-sweep.js +90 -0
- package/lib/dist/reflect/auto-sweep.js.map +1 -0
- package/lib/dist/reflect/cli.d.ts +62 -0
- package/lib/dist/reflect/cli.d.ts.map +1 -0
- package/lib/dist/reflect/cli.js +163 -0
- package/lib/dist/reflect/cli.js.map +1 -0
- package/lib/dist/reflect/miner.d.ts.map +1 -1
- package/lib/dist/reflect/miner.js +119 -0
- package/lib/dist/reflect/miner.js.map +1 -1
- package/lib/dist/reflect/sweep.d.ts +1 -0
- package/lib/dist/reflect/sweep.d.ts.map +1 -1
- package/lib/dist/reflect/sweep.js +62 -13
- package/lib/dist/reflect/sweep.js.map +1 -1
- package/lib/dist/reflect/targets.d.ts +2 -0
- package/lib/dist/reflect/targets.d.ts.map +1 -1
- package/lib/dist/reflect/targets.js +33 -0
- package/lib/dist/reflect/targets.js.map +1 -1
- package/lib/dist/reflect/types.d.ts +19 -2
- package/lib/dist/reflect/types.d.ts.map +1 -1
- package/lib/dist/resolution/test-title-links.d.ts.map +1 -1
- package/lib/dist/resolution/test-title-links.js +3 -14
- package/lib/dist/resolution/test-title-links.js.map +1 -1
- package/lib/dist/server/routes/claude.js +15 -7
- package/lib/dist/server/routes/knowledge.js +118 -0
- package/lib/dist/server/server.js +2 -0
- package/lib/dist/skills/design-md/SKILL.md +172 -0
- package/lib/dist/skills/design-md/references/authored-sections.md +90 -0
- package/lib/dist/skills/design-md/references/sources.md +71 -0
- package/lib/dist/spec-lint/lint.d.ts +1 -1
- package/lib/dist/spec-lint/lint.d.ts.map +1 -1
- package/lib/dist/spec-lint/lint.js +63 -2
- package/lib/dist/spec-lint/lint.js.map +1 -1
- package/lib/dist/spec-quality/criterion-ids.d.ts +13 -0
- package/lib/dist/spec-quality/criterion-ids.d.ts.map +1 -0
- package/lib/dist/spec-quality/criterion-ids.js +38 -0
- package/lib/dist/spec-quality/criterion-ids.js.map +1 -0
- package/lib/dist/spec-quality/evidence-kind.d.ts +54 -0
- package/lib/dist/spec-quality/evidence-kind.d.ts.map +1 -0
- package/lib/dist/spec-quality/evidence-kind.js +183 -0
- package/lib/dist/spec-quality/evidence-kind.js.map +1 -0
- package/lib/dist/spec-quality/link-persist.d.ts +65 -0
- package/lib/dist/spec-quality/link-persist.d.ts.map +1 -0
- package/lib/dist/spec-quality/link-persist.js +249 -0
- package/lib/dist/spec-quality/link-persist.js.map +1 -0
- package/lib/dist/spec-quality/plan-scope.d.ts +38 -0
- package/lib/dist/spec-quality/plan-scope.d.ts.map +1 -0
- package/lib/dist/spec-quality/plan-scope.js +129 -0
- package/lib/dist/spec-quality/plan-scope.js.map +1 -0
- package/lib/dist/spec-quality/postcheck.d.ts +91 -0
- package/lib/dist/spec-quality/postcheck.d.ts.map +1 -0
- package/lib/dist/spec-quality/postcheck.js +421 -0
- package/lib/dist/spec-quality/postcheck.js.map +1 -0
- package/lib/dist/spec-quality/readiness.d.ts +72 -0
- package/lib/dist/spec-quality/readiness.d.ts.map +1 -0
- package/lib/dist/spec-quality/readiness.js +226 -0
- package/lib/dist/spec-quality/readiness.js.map +1 -0
- package/lib/dist/workflows/agents/claude.d.ts +16 -0
- package/lib/dist/workflows/agents/claude.d.ts.map +1 -0
- package/lib/dist/workflows/agents/claude.js +82 -0
- package/lib/dist/workflows/agents/claude.js.map +1 -0
- package/lib/dist/workflows/agents/gemini.d.ts +21 -0
- package/lib/dist/workflows/agents/gemini.d.ts.map +1 -0
- package/lib/dist/workflows/agents/gemini.js +124 -0
- package/lib/dist/workflows/agents/gemini.js.map +1 -0
- package/lib/dist/workflows/agents/index.d.ts +28 -0
- package/lib/dist/workflows/agents/index.d.ts.map +1 -0
- package/lib/dist/workflows/agents/index.js +104 -0
- package/lib/dist/workflows/agents/index.js.map +1 -0
- package/lib/dist/workflows/agents/types.d.ts +55 -0
- package/lib/dist/workflows/agents/types.d.ts.map +1 -0
- package/lib/dist/workflows/agents/types.js +46 -0
- package/lib/dist/workflows/agents/types.js.map +1 -0
- package/lib/dist/workflows/batch.d.ts +63 -0
- package/lib/dist/workflows/batch.d.ts.map +1 -0
- package/lib/dist/workflows/batch.js +151 -0
- package/lib/dist/workflows/batch.js.map +1 -0
- package/lib/dist/workflows/defaults/claude-design-implement.yaml +37 -9
- package/lib/dist/workflows/defaults/spec-author.yaml +11 -9
- package/lib/dist/workflows/defaults/spec-implement-mixed.yaml +21 -436
- package/lib/dist/workflows/defaults/spec-implement.yaml +481 -46
- package/lib/dist/workflows/discovery.d.ts +13 -0
- package/lib/dist/workflows/discovery.d.ts.map +1 -1
- package/lib/dist/workflows/discovery.js +79 -17
- package/lib/dist/workflows/discovery.js.map +1 -1
- package/lib/dist/workflows/executor.d.ts +18 -0
- package/lib/dist/workflows/executor.d.ts.map +1 -1
- package/lib/dist/workflows/executor.js +130 -33
- package/lib/dist/workflows/executor.js.map +1 -1
- package/lib/dist/workflows/gc.d.ts +50 -0
- package/lib/dist/workflows/gc.d.ts.map +1 -0
- package/lib/dist/workflows/gc.js +120 -0
- package/lib/dist/workflows/gc.js.map +1 -0
- package/lib/dist/workflows/merge-queue.d.ts +64 -0
- package/lib/dist/workflows/merge-queue.d.ts.map +1 -0
- package/lib/dist/workflows/merge-queue.js +162 -0
- package/lib/dist/workflows/merge-queue.js.map +1 -0
- package/lib/dist/workflows/runners/approval.d.ts +1 -1
- package/lib/dist/workflows/runners/approval.d.ts.map +1 -1
- package/lib/dist/workflows/runners/approval.js +11 -2
- package/lib/dist/workflows/runners/approval.js.map +1 -1
- package/lib/dist/workflows/runners/bash.d.ts +15 -0
- package/lib/dist/workflows/runners/bash.d.ts.map +1 -1
- package/lib/dist/workflows/runners/bash.js +50 -1
- package/lib/dist/workflows/runners/bash.js.map +1 -1
- package/lib/dist/workflows/runners/prompt.d.ts +16 -41
- package/lib/dist/workflows/runners/prompt.d.ts.map +1 -1
- package/lib/dist/workflows/runners/prompt.js +55 -120
- package/lib/dist/workflows/runners/prompt.js.map +1 -1
- package/lib/dist/workflows/runners/types.d.ts +12 -0
- package/lib/dist/workflows/runners/types.d.ts.map +1 -1
- package/lib/dist/workflows/schemas/workflow.d.ts +17 -0
- package/lib/dist/workflows/schemas/workflow.d.ts.map +1 -1
- package/lib/dist/workflows/schemas/workflow.js +27 -0
- package/lib/dist/workflows/schemas/workflow.js.map +1 -1
- package/lib/node_modules/.package-lock.json +1 -1
- package/lib/package.json +2 -2
- package/package.json +5 -3
- package/node.exe +0 -4
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Headless-agent registry and selection (REQ-AGENTADAPT-005/006).
|
|
3
|
+
*
|
|
4
|
+
* The agent is resolved once at run start — `--agent`, then
|
|
5
|
+
* `SPECSHIP_WORKFLOW_AGENT`, then `workflow.agent` in specship.config.json,
|
|
6
|
+
* then the coding agent that launched the command, then Claude Code — and is
|
|
7
|
+
* stored on the run so approve / revise / resume use the same one.
|
|
8
|
+
*/
|
|
9
|
+
import type { HeadlessAgent, HeadlessAgentConfig } from './types';
|
|
10
|
+
export type { HeadlessAgent, HeadlessAgentConfig, HeadlessInvocation, StreamParseState } from './types';
|
|
11
|
+
export declare const DEFAULT_WORKFLOW_AGENT: string;
|
|
12
|
+
/** Run-metadata key the chosen agent is stored under. */
|
|
13
|
+
export declare const RUN_AGENT_KEY = "agent";
|
|
14
|
+
export declare function knownWorkflowAgents(): string[];
|
|
15
|
+
export declare function getHeadlessAgent(id: string): HeadlessAgent | undefined;
|
|
16
|
+
export declare class UnknownWorkflowAgentError extends Error {
|
|
17
|
+
constructor(name: string, source: string);
|
|
18
|
+
}
|
|
19
|
+
export interface ResolveAgentOptions {
|
|
20
|
+
flag?: string;
|
|
21
|
+
env?: NodeJS.ProcessEnv;
|
|
22
|
+
projectRoot: string;
|
|
23
|
+
}
|
|
24
|
+
/** The agent id for a new run, or throws UnknownWorkflowAgentError (REQ-AGENTADAPT-006.A4). */
|
|
25
|
+
export declare function resolveWorkflowAgent(opts: ResolveAgentOptions): string;
|
|
26
|
+
/** `workflow.agents.<id>` settings (model tier mapping), {} when unset. */
|
|
27
|
+
export declare function workflowAgentConfig(projectRoot: string, id: string): HeadlessAgentConfig;
|
|
28
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/workflows/agents/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAElE,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAGxG,eAAO,MAAM,sBAAsB,QAAyB,CAAC;AAC7D,yDAAyD;AACzD,eAAO,MAAM,aAAa,UAAU,CAAC;AAErC,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAE9C;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAEtE;AAED,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAIzC;AAgBD,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,+FAA+F;AAC/F,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAgBtE;AAED,2EAA2E;AAC3E,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,mBAAmB,CAGxF"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Headless-agent registry and selection (REQ-AGENTADAPT-005/006).
|
|
4
|
+
*
|
|
5
|
+
* The agent is resolved once at run start — `--agent`, then
|
|
6
|
+
* `SPECSHIP_WORKFLOW_AGENT`, then `workflow.agent` in specship.config.json,
|
|
7
|
+
* then the coding agent that launched the command, then Claude Code — and is
|
|
8
|
+
* stored on the run so approve / revise / resume use the same one.
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.UnknownWorkflowAgentError = exports.RUN_AGENT_KEY = exports.DEFAULT_WORKFLOW_AGENT = void 0;
|
|
45
|
+
exports.knownWorkflowAgents = knownWorkflowAgents;
|
|
46
|
+
exports.getHeadlessAgent = getHeadlessAgent;
|
|
47
|
+
exports.resolveWorkflowAgent = resolveWorkflowAgent;
|
|
48
|
+
exports.workflowAgentConfig = workflowAgentConfig;
|
|
49
|
+
const fs = __importStar(require("fs"));
|
|
50
|
+
const path = __importStar(require("path"));
|
|
51
|
+
const claude_1 = require("./claude");
|
|
52
|
+
const gemini_1 = require("./gemini");
|
|
53
|
+
const AGENTS = [claude_1.claudeHeadlessAgent, gemini_1.geminiHeadlessAgent];
|
|
54
|
+
exports.DEFAULT_WORKFLOW_AGENT = claude_1.claudeHeadlessAgent.id;
|
|
55
|
+
/** Run-metadata key the chosen agent is stored under. */
|
|
56
|
+
exports.RUN_AGENT_KEY = 'agent';
|
|
57
|
+
function knownWorkflowAgents() {
|
|
58
|
+
return AGENTS.map((a) => a.id);
|
|
59
|
+
}
|
|
60
|
+
function getHeadlessAgent(id) {
|
|
61
|
+
return AGENTS.find((a) => a.id === id);
|
|
62
|
+
}
|
|
63
|
+
class UnknownWorkflowAgentError extends Error {
|
|
64
|
+
constructor(name, source) {
|
|
65
|
+
super(`Unknown workflow agent "${name}" (from ${source}). Known agents: ${knownWorkflowAgents().join(', ')}`);
|
|
66
|
+
this.name = 'UnknownWorkflowAgentError';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.UnknownWorkflowAgentError = UnknownWorkflowAgentError;
|
|
70
|
+
function readWorkflowConfig(projectRoot) {
|
|
71
|
+
try {
|
|
72
|
+
const cfg = JSON.parse(fs.readFileSync(path.join(projectRoot, 'specship.config.json'), 'utf8'));
|
|
73
|
+
return (cfg && typeof cfg.workflow === 'object' && cfg.workflow) || {};
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return {};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** The agent id for a new run, or throws UnknownWorkflowAgentError (REQ-AGENTADAPT-006.A4). */
|
|
80
|
+
function resolveWorkflowAgent(opts) {
|
|
81
|
+
const env = opts.env ?? process.env;
|
|
82
|
+
const cfg = readWorkflowConfig(opts.projectRoot);
|
|
83
|
+
const explicit = [
|
|
84
|
+
[opts.flag, '--agent'],
|
|
85
|
+
[env.SPECSHIP_WORKFLOW_AGENT, 'SPECSHIP_WORKFLOW_AGENT'],
|
|
86
|
+
[cfg.agent, 'workflow.agent in specship.config.json'],
|
|
87
|
+
];
|
|
88
|
+
for (const [value, source] of explicit) {
|
|
89
|
+
if (typeof value !== 'string' || !value.trim())
|
|
90
|
+
continue;
|
|
91
|
+
const id = value.trim().toLowerCase();
|
|
92
|
+
if (!getHeadlessAgent(id))
|
|
93
|
+
throw new UnknownWorkflowAgentError(value, source);
|
|
94
|
+
return id;
|
|
95
|
+
}
|
|
96
|
+
const launcher = AGENTS.find((a) => a.id !== exports.DEFAULT_WORKFLOW_AGENT && a.launchedFrom(env));
|
|
97
|
+
return launcher?.id ?? exports.DEFAULT_WORKFLOW_AGENT;
|
|
98
|
+
}
|
|
99
|
+
/** `workflow.agents.<id>` settings (model tier mapping), {} when unset. */
|
|
100
|
+
function workflowAgentConfig(projectRoot, id) {
|
|
101
|
+
const entry = readWorkflowConfig(projectRoot).agents?.[id];
|
|
102
|
+
return entry && typeof entry === 'object' ? entry : {};
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/workflows/agents/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Headless-agent adapters for workflow prompt steps (AGENTADAPT-DOC,
|
|
3
|
+
* REQ-AGENTADAPT-005). One adapter per coding agent owns that host's binary,
|
|
4
|
+
* argument translation and output parsing; the prompt runner stays
|
|
5
|
+
* host-neutral and gets the same step result whichever host ran it.
|
|
6
|
+
*/
|
|
7
|
+
import type { PromptNode } from '../schemas/workflow';
|
|
8
|
+
import type { WorkflowEventType } from '../../types';
|
|
9
|
+
/** Accumulated state while parsing an agent's streamed output. */
|
|
10
|
+
export interface StreamParseState {
|
|
11
|
+
/** True once at least one line parsed as a known stream event. */
|
|
12
|
+
sawStream: boolean;
|
|
13
|
+
/** Final result text from a terminal result event, if the host sends one. */
|
|
14
|
+
resultText: string | null;
|
|
15
|
+
/** Concatenated assistant text (the result when there's no result text). */
|
|
16
|
+
assistantText: string;
|
|
17
|
+
costUsd?: number;
|
|
18
|
+
durationMs?: number;
|
|
19
|
+
model?: string;
|
|
20
|
+
/** Set when the host's own terminal event reports failure. */
|
|
21
|
+
failure?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function newStreamState(): StreamParseState;
|
|
24
|
+
export type EmitFn = (type: WorkflowEventType, data?: Record<string, unknown>) => void;
|
|
25
|
+
/** What to spawn for one step. */
|
|
26
|
+
export interface HeadlessInvocation {
|
|
27
|
+
bin: string;
|
|
28
|
+
args: string[];
|
|
29
|
+
/** Written to the child's stdin, then closed. */
|
|
30
|
+
stdin: string;
|
|
31
|
+
}
|
|
32
|
+
/** Per-agent settings from `workflow.agents.<id>` in specship.config.json. */
|
|
33
|
+
export interface HeadlessAgentConfig {
|
|
34
|
+
/** Model tier alias (`haiku`, `sonnet`, `opus`) → this host's model id. */
|
|
35
|
+
models?: Record<string, string>;
|
|
36
|
+
}
|
|
37
|
+
export interface HeadlessAgent {
|
|
38
|
+
/** The name `--agent` / `SPECSHIP_WORKFLOW_AGENT` / `workflow.agent` use. */
|
|
39
|
+
readonly id: string;
|
|
40
|
+
/** True when `env` shows the command was launched from inside this host. */
|
|
41
|
+
launchedFrom(env: NodeJS.ProcessEnv): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Translate a step. Returns `{ error }` — never a partial invocation — when
|
|
44
|
+
* the step uses something this host cannot honour (REQ-AGENTADAPT-007.A4).
|
|
45
|
+
*/
|
|
46
|
+
build(node: PromptNode, config: HeadlessAgentConfig, env: NodeJS.ProcessEnv): HeadlessInvocation | {
|
|
47
|
+
error: string;
|
|
48
|
+
};
|
|
49
|
+
/** Parse one output line, emitting live events and folding into `state`. */
|
|
50
|
+
handleLine(line: string, emit: EmitFn, state: StreamParseState): void;
|
|
51
|
+
}
|
|
52
|
+
/** A short, single-line summary of a tool's input for the `tool_called` event. */
|
|
53
|
+
export declare function summarizeToolInput(input: unknown): string;
|
|
54
|
+
export declare function parseJsonLine(line: string): Record<string, unknown> | null;
|
|
55
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/workflows/agents/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,kEAAkE;AAClE,MAAM,WAAW,gBAAgB;IAC/B,kEAAkE;IAClE,SAAS,EAAE,OAAO,CAAC;IACnB,6EAA6E;IAC7E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,4EAA4E;IAC5E,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,cAAc,IAAI,gBAAgB,CAEjD;AAED,MAAM,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,iBAAiB,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;AAEvF,kCAAkC;AAClC,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,8EAA8E;AAC9E,MAAM,WAAW,mBAAmB;IAClC,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC;IAC9C;;;OAGG;IACH,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,mBAAmB,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,kBAAkB,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACrH,4EAA4E;IAC5E,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAC;CACvE;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAezD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAS1E"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Headless-agent adapters for workflow prompt steps (AGENTADAPT-DOC,
|
|
4
|
+
* REQ-AGENTADAPT-005). One adapter per coding agent owns that host's binary,
|
|
5
|
+
* argument translation and output parsing; the prompt runner stays
|
|
6
|
+
* host-neutral and gets the same step result whichever host ran it.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.newStreamState = newStreamState;
|
|
10
|
+
exports.summarizeToolInput = summarizeToolInput;
|
|
11
|
+
exports.parseJsonLine = parseJsonLine;
|
|
12
|
+
function newStreamState() {
|
|
13
|
+
return { sawStream: false, resultText: null, assistantText: '' };
|
|
14
|
+
}
|
|
15
|
+
/** A short, single-line summary of a tool's input for the `tool_called` event. */
|
|
16
|
+
function summarizeToolInput(input) {
|
|
17
|
+
if (input == null)
|
|
18
|
+
return '';
|
|
19
|
+
let s;
|
|
20
|
+
if (typeof input === 'string') {
|
|
21
|
+
s = input;
|
|
22
|
+
}
|
|
23
|
+
else if (typeof input === 'object') {
|
|
24
|
+
const o = input;
|
|
25
|
+
const pick = o.file_path ?? o.path ?? o.command ?? o.pattern ?? o.query ?? o.url ?? o.prompt;
|
|
26
|
+
s = typeof pick === 'string' ? pick : JSON.stringify(o);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
s = String(input);
|
|
30
|
+
}
|
|
31
|
+
s = s.replace(/\s+/g, ' ').trim();
|
|
32
|
+
return s.length > 140 ? `${s.slice(0, 140)}…` : s;
|
|
33
|
+
}
|
|
34
|
+
function parseJsonLine(line) {
|
|
35
|
+
const trimmed = line.trim();
|
|
36
|
+
if (!trimmed)
|
|
37
|
+
return null;
|
|
38
|
+
try {
|
|
39
|
+
const ev = JSON.parse(trimmed);
|
|
40
|
+
return ev && typeof ev === 'object' && !Array.isArray(ev) ? ev : null;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return null; // not JSON — ignore (hosts may print plain diagnostics)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/workflows/agents/types.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAoBH,wCAEC;AAiCD,gDAeC;AAED,sCASC;AA7DD,SAAgB,cAAc;IAC5B,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC;AACnE,CAAC;AAgCD,kFAAkF;AAClF,SAAgB,kBAAkB,CAAC,KAAc;IAC/C,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC7B,IAAI,CAAS,CAAC;IACd,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,CAAC,GAAG,KAAK,CAAC;IACZ,CAAC;SAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,KAAgC,CAAC;QAC3C,MAAM,IAAI,GACR,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC;QAClF,CAAC,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1D,CAAC;SAAM,CAAC;QACN,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IACD,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAClC,OAAO,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,SAAgB,aAAa,CAAC,IAAY;IACxC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC/B,OAAO,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,EAA8B,CAAC,CAAC,CAAC,IAAI,CAAC;IACrG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,wDAAwD;IACvE,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* REQ-THRU-001 — parallel batch runs.
|
|
3
|
+
*
|
|
4
|
+
* `specship workflow run-batch <workflow> --specs <ID,…>` starts one run per
|
|
5
|
+
* requirement, each in its own worktree. Requirements whose `implementations:`
|
|
6
|
+
* files overlap never run concurrently: the later one is placed in a later
|
|
7
|
+
* wave and waits for the earlier wave to finish. No wave holds more runs than
|
|
8
|
+
* the concurrency limit.
|
|
9
|
+
*/
|
|
10
|
+
export declare const DEFAULT_BATCH_CONCURRENCY = 3;
|
|
11
|
+
export interface BatchSpec {
|
|
12
|
+
id: string;
|
|
13
|
+
implementationFiles: string[];
|
|
14
|
+
}
|
|
15
|
+
/** Statuses after which a run is finished (no longer holding its files). */
|
|
16
|
+
export declare const TERMINAL_RUN_STATUSES: Set<string>;
|
|
17
|
+
/**
|
|
18
|
+
* Plan the waves. Specs are visited in input order; each goes into the
|
|
19
|
+
* earliest wave that (a) comes after every wave holding a spec it shares an
|
|
20
|
+
* implementation file with, and (b) still has room under `concurrency`.
|
|
21
|
+
*/
|
|
22
|
+
export declare function planBatch(specs: BatchSpec[], concurrency: number): string[][];
|
|
23
|
+
/**
|
|
24
|
+
* Implementation files of a requirement, read from its spec file's
|
|
25
|
+
* `implementations:` block (`path:Symbol` bullets → `path`). Null when the
|
|
26
|
+
* requirement is not found under specs/.
|
|
27
|
+
*/
|
|
28
|
+
export declare function implementationFilesFor(projectRoot: string, requirementId: string): string[] | null;
|
|
29
|
+
export interface BatchRunResult {
|
|
30
|
+
specId: string;
|
|
31
|
+
runId: string;
|
|
32
|
+
status: string;
|
|
33
|
+
wave: number;
|
|
34
|
+
}
|
|
35
|
+
export interface RunBatchOptions {
|
|
36
|
+
projectRoot: string;
|
|
37
|
+
specIds: string[];
|
|
38
|
+
concurrency?: number;
|
|
39
|
+
/** Start one run for a requirement; resolves once the run is started/settled. */
|
|
40
|
+
startRun: (specId: string) => Promise<{
|
|
41
|
+
runId: string;
|
|
42
|
+
status: string;
|
|
43
|
+
}>;
|
|
44
|
+
/**
|
|
45
|
+
* Wait until a started run is finished. Default: the run is finished when
|
|
46
|
+
* `startRun` resolves. The CLI waits for a terminal status so a run paused
|
|
47
|
+
* at an approval still holds its files.
|
|
48
|
+
*/
|
|
49
|
+
waitForRun?: (runId: string, status: string) => Promise<string>;
|
|
50
|
+
/** Resolve a requirement's implementation files (default: its spec file). */
|
|
51
|
+
resolveFiles?: (specId: string) => string[] | null;
|
|
52
|
+
/** Called with the full plan before any run starts. */
|
|
53
|
+
onPlan?: (waves: string[][]) => void;
|
|
54
|
+
/** Called as each run is started. */
|
|
55
|
+
onRunStarted?: (run: BatchRunResult) => void;
|
|
56
|
+
}
|
|
57
|
+
export interface RunBatchResult {
|
|
58
|
+
waves: string[][];
|
|
59
|
+
runs: BatchRunResult[];
|
|
60
|
+
}
|
|
61
|
+
/** Start the runs wave by wave; a wave finishes before the next one starts. */
|
|
62
|
+
export declare function runBatch(opts: RunBatchOptions): Promise<RunBatchResult>;
|
|
63
|
+
//# sourceMappingURL=batch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../../src/workflows/batch.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,4EAA4E;AAC5E,eAAO,MAAM,qBAAqB,aAA4D,CAAC;AAE/F;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CA+B7E;AAMD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAalG;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzE;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAChE,6EAA6E;IAC7E,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,EAAE,GAAG,IAAI,CAAC;IACnD,uDAAuD;IACvD,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,IAAI,CAAC;IACrC,qCAAqC;IACrC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;CAC9C;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;IAClB,IAAI,EAAE,cAAc,EAAE,CAAC;CACxB;AAED,+EAA+E;AAC/E,wBAAsB,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CA8B7E"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* REQ-THRU-001 — parallel batch runs.
|
|
4
|
+
*
|
|
5
|
+
* `specship workflow run-batch <workflow> --specs <ID,…>` starts one run per
|
|
6
|
+
* requirement, each in its own worktree. Requirements whose `implementations:`
|
|
7
|
+
* files overlap never run concurrently: the later one is placed in a later
|
|
8
|
+
* wave and waits for the earlier wave to finish. No wave holds more runs than
|
|
9
|
+
* the concurrency limit.
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.TERMINAL_RUN_STATUSES = exports.DEFAULT_BATCH_CONCURRENCY = void 0;
|
|
46
|
+
exports.planBatch = planBatch;
|
|
47
|
+
exports.implementationFilesFor = implementationFilesFor;
|
|
48
|
+
exports.runBatch = runBatch;
|
|
49
|
+
const fs = __importStar(require("fs"));
|
|
50
|
+
const postcheck_1 = require("../spec-quality/postcheck");
|
|
51
|
+
exports.DEFAULT_BATCH_CONCURRENCY = 3;
|
|
52
|
+
/** Statuses after which a run is finished (no longer holding its files). */
|
|
53
|
+
exports.TERMINAL_RUN_STATUSES = new Set(['completed', 'failed', 'cancelled', 'rejected']);
|
|
54
|
+
/**
|
|
55
|
+
* Plan the waves. Specs are visited in input order; each goes into the
|
|
56
|
+
* earliest wave that (a) comes after every wave holding a spec it shares an
|
|
57
|
+
* implementation file with, and (b) still has room under `concurrency`.
|
|
58
|
+
*/
|
|
59
|
+
function planBatch(specs, concurrency) {
|
|
60
|
+
const limit = Math.max(1, Math.floor(concurrency) || 1);
|
|
61
|
+
const waves = [];
|
|
62
|
+
const waveOf = new Map();
|
|
63
|
+
const filesOf = new Map();
|
|
64
|
+
for (let i = 0; i < specs.length; i++) {
|
|
65
|
+
const spec = specs[i];
|
|
66
|
+
if (waveOf.has(spec.id))
|
|
67
|
+
continue; // duplicate id — schedule once
|
|
68
|
+
const files = new Set(spec.implementationFiles.map(normalizeFile));
|
|
69
|
+
let minWave = 0;
|
|
70
|
+
for (let j = 0; j < i; j++) {
|
|
71
|
+
const earlier = specs[j];
|
|
72
|
+
const w = waveOf.get(earlier.id);
|
|
73
|
+
if (w === undefined)
|
|
74
|
+
continue;
|
|
75
|
+
const ef = filesOf.get(earlier.id);
|
|
76
|
+
for (const f of files) {
|
|
77
|
+
if (ef.has(f)) {
|
|
78
|
+
minWave = Math.max(minWave, w + 1);
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
let wave = minWave;
|
|
84
|
+
while (waves[wave] && waves[wave].length >= limit)
|
|
85
|
+
wave++;
|
|
86
|
+
while (waves.length <= wave)
|
|
87
|
+
waves.push([]);
|
|
88
|
+
waves[wave].push(spec.id);
|
|
89
|
+
waveOf.set(spec.id, wave);
|
|
90
|
+
filesOf.set(spec.id, files);
|
|
91
|
+
}
|
|
92
|
+
return waves.filter((w) => w.length > 0);
|
|
93
|
+
}
|
|
94
|
+
function normalizeFile(f) {
|
|
95
|
+
return f.trim().replace(/\\/g, '/').replace(/^\.\//, '');
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Implementation files of a requirement, read from its spec file's
|
|
99
|
+
* `implementations:` block (`path:Symbol` bullets → `path`). Null when the
|
|
100
|
+
* requirement is not found under specs/.
|
|
101
|
+
*/
|
|
102
|
+
function implementationFilesFor(projectRoot, requirementId) {
|
|
103
|
+
const specFile = (0, postcheck_1.findSpecFile)(projectRoot, requirementId);
|
|
104
|
+
if (!specFile)
|
|
105
|
+
return null;
|
|
106
|
+
const block = (0, postcheck_1.requirementBlock)(fs.readFileSync(specFile, 'utf8'), requirementId);
|
|
107
|
+
if (block === null)
|
|
108
|
+
return null;
|
|
109
|
+
const files = new Set();
|
|
110
|
+
for (const bullet of (0, postcheck_1.linkBullets)(block, 'implementations')) {
|
|
111
|
+
const target = bullet.replace(/^`|`$/g, '').trim();
|
|
112
|
+
const colon = target.indexOf(':');
|
|
113
|
+
const file = normalizeFile(colon > 0 ? target.slice(0, colon) : target);
|
|
114
|
+
if (file)
|
|
115
|
+
files.add(file);
|
|
116
|
+
}
|
|
117
|
+
return [...files];
|
|
118
|
+
}
|
|
119
|
+
/** Start the runs wave by wave; a wave finishes before the next one starts. */
|
|
120
|
+
async function runBatch(opts) {
|
|
121
|
+
const resolve = opts.resolveFiles ?? ((id) => implementationFilesFor(opts.projectRoot, id));
|
|
122
|
+
const specs = [];
|
|
123
|
+
const missing = [];
|
|
124
|
+
for (const id of opts.specIds) {
|
|
125
|
+
const files = resolve(id);
|
|
126
|
+
if (files === null)
|
|
127
|
+
missing.push(id);
|
|
128
|
+
else
|
|
129
|
+
specs.push({ id, implementationFiles: files });
|
|
130
|
+
}
|
|
131
|
+
if (missing.length > 0) {
|
|
132
|
+
throw new Error(`Requirement(s) not found under specs/: ${missing.join(', ')}`);
|
|
133
|
+
}
|
|
134
|
+
const waves = planBatch(specs, opts.concurrency ?? exports.DEFAULT_BATCH_CONCURRENCY);
|
|
135
|
+
opts.onPlan?.(waves);
|
|
136
|
+
const runs = [];
|
|
137
|
+
for (let w = 0; w < waves.length; w++) {
|
|
138
|
+
const wave = waves[w];
|
|
139
|
+
const settled = await Promise.all(wave.map(async (specId) => {
|
|
140
|
+
const started = await opts.startRun(specId);
|
|
141
|
+
const run = { specId, runId: started.runId, status: started.status, wave: w };
|
|
142
|
+
opts.onRunStarted?.(run);
|
|
143
|
+
if (opts.waitForRun)
|
|
144
|
+
run.status = await opts.waitForRun(started.runId, started.status);
|
|
145
|
+
return run;
|
|
146
|
+
}));
|
|
147
|
+
runs.push(...settled);
|
|
148
|
+
}
|
|
149
|
+
return { waves, runs };
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=batch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch.js","sourceRoot":"","sources":["../../src/workflows/batch.ts"],"names":[],"mappings":"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"}
|
|
@@ -53,7 +53,9 @@ systemPromptAppend: |
|
|
|
53
53
|
|
|
54
54
|
The fidelity principle: never paraphrase or summarise design content
|
|
55
55
|
when capturing it. The snapshot HTML and tokens.css are the
|
|
56
|
-
zero-loss reference layer
|
|
56
|
+
zero-loss reference layer, and design.md states every value from them
|
|
57
|
+
verbatim in a fixed layout (written by `specship design extract`, never
|
|
58
|
+
transcribed by hand); the spec captures contract only (behaviour,
|
|
57
59
|
accessibility, responsive, interaction states, data shape).
|
|
58
60
|
|
|
59
61
|
There are two import shapes — exactly one source input is non-empty:
|
|
@@ -73,6 +75,7 @@ nodes:
|
|
|
73
75
|
allowed_tools:
|
|
74
76
|
- Read
|
|
75
77
|
- Write
|
|
78
|
+
- Edit
|
|
76
79
|
- Bash
|
|
77
80
|
- mcp__specship__specship_explore
|
|
78
81
|
- mcp__specship__specship_search
|
|
@@ -160,7 +163,29 @@ nodes:
|
|
|
160
163
|
|
|
161
164
|
── BOTH BRANCHES ──
|
|
162
165
|
|
|
163
|
-
4.
|
|
166
|
+
4. Write the pixel-exact design reference (DESIGNMD-DOC). The values
|
|
167
|
+
come from the extractor, never from you:
|
|
168
|
+
|
|
169
|
+
specship design extract specs/$INPUT.SLUG/snapshot.html \
|
|
170
|
+
--out specs/$INPUT.SLUG/design.md --title "$INPUT.FILE_LABEL"
|
|
171
|
+
|
|
172
|
+
(If design.md already exists from an earlier import, use
|
|
173
|
+
`--update specs/$INPUT.SLUG/design.md` instead of `--out`.)
|
|
174
|
+
If the generated block reports a "Missing linked stylesheet",
|
|
175
|
+
copy that file next to the snapshot and re-run with `--update`.
|
|
176
|
+
Then fill design.md's authored sections — Screens & layout,
|
|
177
|
+
Components & states, Interactions & motion, Responsive behaviour,
|
|
178
|
+
Assets — following the design-md skill
|
|
179
|
+
(~/.claude/skills/design-md/SKILL.md and its
|
|
180
|
+
references/authored-sections.md): every value copied verbatim
|
|
181
|
+
from the generated block with its selector, every styled state
|
|
182
|
+
listed, no approximate wording. Run
|
|
183
|
+
|
|
184
|
+
specship design check specs/$INPUT.SLUG/design.md
|
|
185
|
+
|
|
186
|
+
and fix findings until it passes.
|
|
187
|
+
|
|
188
|
+
5. Extract CSS custom properties + literal token-like values
|
|
164
189
|
(colors, spacing, font sizes, radii, transitions) from the
|
|
165
190
|
snapshot to `specs/$INPUT.SLUG/tokens.css`. Use
|
|
166
191
|
`specship_explore` first to find the project's existing token
|
|
@@ -175,6 +200,7 @@ nodes:
|
|
|
175
200
|
- Any visible interaction or state cues in the CSS (`:hover`,
|
|
176
201
|
`:focus`, `:disabled`, `[aria-*]` selectors) the spec
|
|
177
202
|
author should be aware of.
|
|
203
|
+
- Whether `specship design check` passes on design.md.
|
|
178
204
|
- For Branch A: note that source.md carries the verbatim decision
|
|
179
205
|
record — the draft step should mine it for stated behaviour.
|
|
180
206
|
|
|
@@ -196,6 +222,7 @@ nodes:
|
|
|
196
222
|
- specs/$INPUT.SLUG/snapshot.html (visual + structural source)
|
|
197
223
|
- specs/$INPUT.SLUG/tokens.css (design tokens)
|
|
198
224
|
- specs/$INPUT.SLUG/source.md (audit record)
|
|
225
|
+
- specs/$INPUT.SLUG/design.md (pixel-exact design reference)
|
|
199
226
|
|
|
200
227
|
Spec scope: $INPUT.FILE_LABEL component(s).
|
|
201
228
|
Optional inputs: owner=$INPUT.OWNER priority=$INPUT.PRIORITY
|
|
@@ -236,6 +263,7 @@ nodes:
|
|
|
236
263
|
source: specs/<SLUG>/source.md
|
|
237
264
|
snapshot: specs/<SLUG>/snapshot.html
|
|
238
265
|
tokens: specs/<SLUG>/tokens.css
|
|
266
|
+
design: specs/<SLUG>/design.md
|
|
239
267
|
---
|
|
240
268
|
```
|
|
241
269
|
|
|
@@ -257,18 +285,17 @@ nodes:
|
|
|
257
285
|
$draft_spec.output
|
|
258
286
|
capture_response: true
|
|
259
287
|
on_reject:
|
|
288
|
+
# The reviewer's rejection reason is appended automatically.
|
|
260
289
|
prompt: |
|
|
261
|
-
The draft was rejected
|
|
290
|
+
The draft was rejected (feedback follows). Revise the spec
|
|
262
291
|
per the feedback; keep ALL existing REQ IDs stable so any
|
|
263
292
|
downstream tracking survives the rewrite.
|
|
264
293
|
|
|
265
|
-
Feedback:
|
|
266
|
-
$gap_review.output
|
|
267
|
-
|
|
268
294
|
Current draft:
|
|
269
295
|
$draft_spec.output
|
|
270
296
|
|
|
271
297
|
Output the revised draft.
|
|
298
|
+
revises: draft_spec
|
|
272
299
|
max_attempts: 3
|
|
273
300
|
|
|
274
301
|
- id: write_spec
|
|
@@ -323,14 +350,15 @@ nodes:
|
|
|
323
350
|
1. The path of the spec file: `specs/$INPUT.SLUG.md`.
|
|
324
351
|
2. The full list of REQ IDs the spec defines, one per line.
|
|
325
352
|
3. The reference files the implementation phase should read:
|
|
353
|
+
- specs/$INPUT.SLUG/design.md (read first: every value verbatim)
|
|
326
354
|
- specs/$INPUT.SLUG/snapshot.html
|
|
327
355
|
- specs/$INPUT.SLUG/tokens.css
|
|
328
356
|
- specs/$INPUT.SLUG/source.md
|
|
329
357
|
4. The exact next command:
|
|
330
358
|
/specship:spec implement <first REQ ID>
|
|
331
|
-
5. A one-line reminder that the implementation step
|
|
332
|
-
|
|
333
|
-
|
|
359
|
+
5. A one-line reminder that the implementation step builds the UI
|
|
360
|
+
from design.md (values verbatim) — the spec covers contract
|
|
361
|
+
only.
|
|
334
362
|
|
|
335
363
|
Keep the message ≤200 words. The user is about to switch from
|
|
336
364
|
this workflow to the implement workflow; this is the bridge.
|
|
@@ -111,13 +111,15 @@ nodes:
|
|
|
111
111
|
[the agent fills these in based on the draft above]
|
|
112
112
|
capture_response: true
|
|
113
113
|
on_reject:
|
|
114
|
+
# The reviewer's rejection reason is appended automatically.
|
|
114
115
|
prompt: |
|
|
115
|
-
The draft was rejected
|
|
116
|
+
The draft was rejected (feedback follows). Revise the draft to
|
|
116
117
|
address it. Keep all existing IDs stable so any pre-existing links
|
|
117
|
-
survive.
|
|
118
|
+
survive. Output the full revised draft.
|
|
118
119
|
|
|
119
|
-
|
|
120
|
-
$
|
|
120
|
+
Current draft:
|
|
121
|
+
$draft.output
|
|
122
|
+
revises: draft
|
|
121
123
|
max_attempts: 3
|
|
122
124
|
|
|
123
125
|
- id: incorporate
|
|
@@ -177,15 +179,15 @@ nodes:
|
|
|
177
179
|
$incorporate.output
|
|
178
180
|
capture_response: true
|
|
179
181
|
on_reject:
|
|
182
|
+
# The reviewer's rejection reason is appended automatically.
|
|
180
183
|
prompt: |
|
|
181
|
-
Final approval was rejected. Revise the draft
|
|
182
|
-
re-run the quality review pass, and
|
|
183
|
-
|
|
184
|
-
Feedback:
|
|
185
|
-
$finalize.output
|
|
184
|
+
Final approval was rejected (feedback follows). Revise the draft
|
|
185
|
+
per the feedback, re-run the quality review pass, and output the
|
|
186
|
+
full revised draft.
|
|
186
187
|
|
|
187
188
|
Current draft:
|
|
188
189
|
$incorporate.output
|
|
190
|
+
revises: incorporate
|
|
189
191
|
max_attempts: 2
|
|
190
192
|
|
|
191
193
|
- id: write_file
|