pipeline-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +146 -0
  3. package/package.json +63 -0
  4. package/schemas/pipeline.schema.json +158 -0
  5. package/src/adapters/claude-code.ts +112 -0
  6. package/src/adapters/detector.ts +26 -0
  7. package/src/adapters/generic.ts +30 -0
  8. package/src/adapters/interface.ts +7 -0
  9. package/src/cli/advance.ts +27 -0
  10. package/src/cli/cleanup.ts +55 -0
  11. package/src/cli/helpers.ts +52 -0
  12. package/src/cli/index.ts +92 -0
  13. package/src/cli/init.ts +248 -0
  14. package/src/cli/resume.ts +45 -0
  15. package/src/cli/signal.ts +21 -0
  16. package/src/cli/start.ts +33 -0
  17. package/src/cli/status.ts +24 -0
  18. package/src/cli/template.ts +28 -0
  19. package/src/cli/validate.ts +21 -0
  20. package/src/cli/verify.ts +33 -0
  21. package/src/cli/visualize.ts +36 -0
  22. package/src/core/cleanup.ts +75 -0
  23. package/src/core/evidence.ts +144 -0
  24. package/src/core/gate-runner.ts +109 -0
  25. package/src/core/loader.ts +125 -0
  26. package/src/core/state-machine.ts +119 -0
  27. package/src/daemon/ipc.ts +56 -0
  28. package/src/daemon/server.ts +144 -0
  29. package/src/daemon/state-file.ts +65 -0
  30. package/src/gates/async.ts +60 -0
  31. package/src/gates/builtin.ts +40 -0
  32. package/src/gates/custom.ts +71 -0
  33. package/src/index.ts +20 -0
  34. package/src/mcp/prompts.ts +40 -0
  35. package/src/mcp/resources.ts +71 -0
  36. package/src/mcp/server.ts +211 -0
  37. package/src/mcp/tools.ts +52 -0
  38. package/src/templates/infra-gitops.yaml +37 -0
  39. package/src/templates/sdlc-full.yaml +69 -0
  40. package/src/templates/static-site.yaml +45 -0
  41. package/src/templates/zship.yaml +224 -0
  42. package/src/types.ts +210 -0
@@ -0,0 +1,211 @@
1
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import {
4
+ CallToolRequestSchema,
5
+ GetPromptRequestSchema,
6
+ ListPromptsRequestSchema,
7
+ ListResourcesRequestSchema,
8
+ ListToolsRequestSchema,
9
+ ReadResourceRequestSchema,
10
+ } from "@modelcontextprotocol/sdk/types.js";
11
+ import type { EvidenceStore } from "../core/evidence";
12
+ import type { StateMachine } from "../core/state-machine";
13
+ import type { PipelineDefinition } from "../types";
14
+ import { createStagePrompt } from "./prompts";
15
+ import { createPipelineResources } from "./resources";
16
+ import { createPipelineTools } from "./tools";
17
+
18
+ export function createMcpServer(
19
+ machine: StateMachine,
20
+ pipeline: PipelineDefinition,
21
+ _evidenceStore: EvidenceStore,
22
+ ) {
23
+ const server = new Server(
24
+ { name: "pipeline-sdk", version: "1.0.0" },
25
+ {
26
+ capabilities: {
27
+ tools: {},
28
+ resources: {},
29
+ prompts: {},
30
+ },
31
+ },
32
+ );
33
+
34
+ const tools = createPipelineTools(machine);
35
+ const resources = createPipelineResources(machine, pipeline);
36
+
37
+ // ─── Tools ────────────────────────────────────────────────
38
+
39
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
40
+ tools: [
41
+ {
42
+ name: "pipeline_check",
43
+ description: "Check whether a tool is allowed in the current pipeline stage.",
44
+ inputSchema: {
45
+ type: "object",
46
+ properties: {
47
+ tool: { type: "string", description: "Tool name to check" },
48
+ command: { type: "string", description: "Optional command string" },
49
+ },
50
+ required: ["tool"],
51
+ },
52
+ },
53
+ {
54
+ name: "pipeline_advance",
55
+ description: "Advance the pipeline by firing a transition event.",
56
+ inputSchema: {
57
+ type: "object",
58
+ properties: {
59
+ event: { type: "string", description: "Transition event name, e.g. STAGE_COMPLETE" },
60
+ },
61
+ required: ["event"],
62
+ },
63
+ },
64
+ {
65
+ name: "pipeline_signal",
66
+ description: "Deliver a signal to clear a named gate.",
67
+ inputSchema: {
68
+ type: "object",
69
+ properties: {
70
+ signal: { type: "string", description: "Signal name" },
71
+ gate_id: { type: "string", description: "Gate ID to clear" },
72
+ source: { type: "string", description: "Optional signal source" },
73
+ },
74
+ required: ["signal", "gate_id"],
75
+ },
76
+ },
77
+ {
78
+ name: "pipeline_status",
79
+ description: "Return the current pipeline stage and gate status.",
80
+ inputSchema: {
81
+ type: "object",
82
+ properties: {},
83
+ },
84
+ },
85
+ ],
86
+ }));
87
+
88
+ server.setRequestHandler(CallToolRequestSchema, async (req) => {
89
+ const { name, arguments: args } = req.params;
90
+ const input = (args ?? {}) as Record<string, string>;
91
+
92
+ let result: unknown;
93
+
94
+ switch (name) {
95
+ case "pipeline_check":
96
+ result = tools.check({ tool: input.tool, command: input.command });
97
+ break;
98
+ case "pipeline_advance":
99
+ result = tools.advance({ event: input.event });
100
+ break;
101
+ case "pipeline_signal":
102
+ result = tools.signal({
103
+ signal: input.signal,
104
+ gate_id: input.gate_id,
105
+ source: input.source,
106
+ });
107
+ break;
108
+ case "pipeline_status":
109
+ result = tools.status();
110
+ break;
111
+ default:
112
+ return {
113
+ content: [{ type: "text" as const, text: `Unknown tool: ${name}` }],
114
+ isError: true,
115
+ };
116
+ }
117
+
118
+ return {
119
+ content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
120
+ };
121
+ });
122
+
123
+ // ─── Resources ────────────────────────────────────────────
124
+
125
+ server.setRequestHandler(ListResourcesRequestSchema, async () => ({
126
+ resources: [
127
+ {
128
+ uri: "pipeline://state/current",
129
+ name: "Current Pipeline State",
130
+ mimeType: "application/json",
131
+ },
132
+ {
133
+ uri: "pipeline://instructions/current",
134
+ name: "Current Stage Instructions",
135
+ mimeType: "application/json",
136
+ },
137
+ {
138
+ uri: "pipeline://gates/available",
139
+ name: "Available Gates",
140
+ mimeType: "application/json",
141
+ },
142
+ ],
143
+ }));
144
+
145
+ server.setRequestHandler(ReadResourceRequestSchema, async (req) => {
146
+ const { uri } = req.params;
147
+ const handler = resources[uri as keyof typeof resources];
148
+
149
+ if (!handler) {
150
+ throw new Error(`Unknown resource: ${uri}`);
151
+ }
152
+
153
+ const content = handler();
154
+ return {
155
+ contents: [
156
+ {
157
+ uri: content.uri,
158
+ mimeType: content.mimeType,
159
+ text: content.text,
160
+ },
161
+ ],
162
+ };
163
+ });
164
+
165
+ // ─── Prompts ──────────────────────────────────────────────
166
+
167
+ server.setRequestHandler(ListPromptsRequestSchema, async () => ({
168
+ prompts: [
169
+ {
170
+ name: "pipeline_stage_prompt",
171
+ description: "System prompt for the current pipeline stage.",
172
+ arguments: [
173
+ {
174
+ name: "stage",
175
+ description: "Stage name (defaults to current stage)",
176
+ required: false,
177
+ },
178
+ ],
179
+ },
180
+ ],
181
+ }));
182
+
183
+ server.setRequestHandler(GetPromptRequestSchema, async (req) => {
184
+ const { name, arguments: args } = req.params;
185
+
186
+ if (name !== "pipeline_stage_prompt") {
187
+ throw new Error(`Unknown prompt: ${name}`);
188
+ }
189
+
190
+ const stageName = (args as Record<string, string> | undefined)?.stage ?? machine.currentStage;
191
+ const text = createStagePrompt(pipeline, stageName);
192
+
193
+ return {
194
+ description: `Stage prompt for "${stageName}"`,
195
+ messages: [
196
+ {
197
+ role: "user" as const,
198
+ content: { type: "text" as const, text },
199
+ },
200
+ ],
201
+ };
202
+ });
203
+
204
+ return {
205
+ server,
206
+ async startStdio(): Promise<void> {
207
+ const transport = new StdioServerTransport();
208
+ await server.connect(transport);
209
+ },
210
+ };
211
+ }
@@ -0,0 +1,52 @@
1
+ import type { StateMachine } from "../core/state-machine";
2
+ import type { IpcResponse } from "../types";
3
+
4
+ export function createPipelineTools(machine: StateMachine) {
5
+ return {
6
+ check(input: { tool: string; command?: string }): IpcResponse {
7
+ const allowedTools = machine.allowedTools;
8
+ if (allowedTools.length === 0) {
9
+ return {
10
+ allowed: true,
11
+ current_stage: machine.currentStage,
12
+ allowed_tools: [],
13
+ };
14
+ }
15
+ const allowed = allowedTools.includes(input.tool);
16
+ return {
17
+ allowed,
18
+ current_stage: machine.currentStage,
19
+ allowed_tools: allowedTools,
20
+ reason: allowed
21
+ ? undefined
22
+ : `Tool "${input.tool}" not allowed in stage "${machine.currentStage}"`,
23
+ };
24
+ },
25
+
26
+ status(): IpcResponse {
27
+ const stage = machine.currentStageDefinition;
28
+ const state = machine.exportState();
29
+ return {
30
+ stage: machine.currentStage,
31
+ gates_remaining: stage?.gates?.exit ?? [],
32
+ elapsed: `${Math.round((Date.now() - new Date(state.started_at).getTime()) / 1000)}s`,
33
+ };
34
+ },
35
+
36
+ advance(input: { event: string }): IpcResponse {
37
+ const result = machine.transition(input.event);
38
+ return {
39
+ transitioned: result.success,
40
+ new_stage: result.newStage,
41
+ error: result.error,
42
+ };
43
+ },
44
+
45
+ signal(input: { signal: string; gate_id: string; source?: string }): IpcResponse {
46
+ return {
47
+ received: true,
48
+ gate_cleared: input.gate_id,
49
+ };
50
+ },
51
+ };
52
+ }
@@ -0,0 +1,37 @@
1
+ pipeline:
2
+ id: infra-gitops
3
+ version: 1
4
+ description: "Infrastructure changes with mandatory approval"
5
+ initial: validate
6
+ stages:
7
+ validate:
8
+ description: "Validate manifests and configs"
9
+ on:
10
+ STAGE_COMPLETE: { target: preview }
11
+ preview:
12
+ description: "Deploy to staging environment"
13
+ on:
14
+ STAGE_COMPLETE: { target: approve }
15
+ HEALTH_FAIL: { target: validate }
16
+ approve:
17
+ description: "Human approval required"
18
+ gates:
19
+ entry: [human-approval]
20
+ on:
21
+ APPROVED: { target: production }
22
+ REJECTED: { target: validate }
23
+ production:
24
+ description: "Deploy to production"
25
+ on:
26
+ STAGE_COMPLETE: { target: complete }
27
+ HEALTH_FAIL: { target: rollback }
28
+ rollback:
29
+ on:
30
+ ROLLBACK_COMPLETE: { target: complete }
31
+ complete:
32
+ type: terminal
33
+
34
+ gates:
35
+ human-approval:
36
+ type: async
37
+ signal: approval
@@ -0,0 +1,69 @@
1
+ pipeline:
2
+ id: sdlc-full
3
+ version: 1
4
+ description: "Full SDLC enforcement for production monorepos"
5
+ initial: planning
6
+ stages:
7
+ planning:
8
+ description: "Analyze requirements and create implementation plan"
9
+ agent:
10
+ instructions: "Create a detailed implementation plan with TDD"
11
+ tools: [Read, Grep, Glob, Write, WebSearch]
12
+ gates:
13
+ exit: [plan-document-exists]
14
+ on:
15
+ STAGE_COMPLETE: { target: implement }
16
+ implement:
17
+ description: "Write code following TDD red-green-refactor"
18
+ agent:
19
+ instructions: "Implement using TDD. Write failing test first."
20
+ tools: [Read, Write, Edit, Bash, Grep, Glob]
21
+ gates:
22
+ exit: [lint-pass, typecheck-pass, tests-pass]
23
+ on:
24
+ STAGE_COMPLETE: { target: review }
25
+ TESTS_FAIL: { target: fix }
26
+ fix:
27
+ description: "Fix failing tests or lint issues"
28
+ max_retries: 3
29
+ agent:
30
+ instructions: "Fix the failures. Do not change test expectations."
31
+ tools: [Read, Edit, Bash, Grep]
32
+ on:
33
+ FIX_COMPLETE: { target: implement }
34
+ MAX_RETRIES: { target: escalate }
35
+ review:
36
+ description: "Code review gate"
37
+ on:
38
+ APPROVED: { target: deploy }
39
+ CHANGES_REQUESTED: { target: implement }
40
+ deploy:
41
+ description: "Deploy to production"
42
+ gates:
43
+ exit: [build-succeeds]
44
+ on:
45
+ STAGE_COMPLETE: { target: complete }
46
+ escalate:
47
+ type: terminal
48
+ description: "Human intervention required"
49
+ complete:
50
+ type: terminal
51
+ description: "Pipeline succeeded"
52
+
53
+ gates:
54
+ plan-document-exists:
55
+ type: custom
56
+ script: "test -f docs/plan.md"
57
+ expect: { status: pass }
58
+ lint-pass:
59
+ type: builtin
60
+ command: "bun run lint"
61
+ typecheck-pass:
62
+ type: builtin
63
+ command: "bun run typecheck"
64
+ tests-pass:
65
+ type: builtin
66
+ command: "bun test"
67
+ build-succeeds:
68
+ type: builtin
69
+ command: "bun run build"
@@ -0,0 +1,45 @@
1
+ pipeline:
2
+ id: static-site
3
+ version: 1
4
+ description: "Pipeline for static sites and portfolios"
5
+ initial: quality
6
+ stages:
7
+ quality:
8
+ gates:
9
+ exit: [lint-pass, typecheck-pass, build-succeeds]
10
+ on:
11
+ STAGE_COMPLETE: { target: visual }
12
+ visual:
13
+ description: "Visual and accessibility checks"
14
+ on:
15
+ STAGE_COMPLETE: { target: deploy }
16
+ ANY_FAILED: { target: fix }
17
+ fix:
18
+ max_retries: 2
19
+ on:
20
+ FIX_COMPLETE: { target: quality }
21
+ deploy:
22
+ type: terminal
23
+
24
+ gates:
25
+ lint-pass:
26
+ type: builtin
27
+ command: "bun run lint"
28
+ typecheck-pass:
29
+ type: builtin
30
+ command: "bun run typecheck"
31
+ build-succeeds:
32
+ type: builtin
33
+ command: "bun run build"
34
+ a11y-audit:
35
+ type: custom
36
+ script: "bun run a11y"
37
+ expect: { status: pass }
38
+ lighthouse-pass:
39
+ type: custom
40
+ script: "bun run lighthouse"
41
+ expect: { status: pass }
42
+ responsive-check:
43
+ type: custom
44
+ script: "bun run responsive"
45
+ expect: { status: pass }
@@ -0,0 +1,224 @@
1
+ # zship.yaml — Dual-Model Development Pipeline
2
+ # 6-stage pipeline with dual-phase gates (Claude + Codex)
3
+ # Converts the zship process into Pipeline SDK format
4
+
5
+ pipeline:
6
+ id: zship
7
+ version: 1
8
+ description: "Dual-model autonomous development pipeline (BRAINSTORM → PLAN → IMPLEMENT → TEST → REVIEW → SHIP)"
9
+ initial: brainstorm
10
+
11
+ stages:
12
+ brainstorm:
13
+ description: "Interrogate requirements via grill-me interrogation"
14
+ agent:
15
+ instructions: "Interrogate requirements relentlessly. Produce approved spec at docs/zship/spec.md."
16
+ tools: [Read, Grep, Glob, Write, WebSearch]
17
+ on:
18
+ SPEC_APPROVED: { target: plan }
19
+ ABORT: { target: aborted }
20
+
21
+ plan:
22
+ description: "Create TDD implementation plan with task breakdown"
23
+ agent:
24
+ instructions: "Produce TDD plan from spec. Each task: RED test → GREEN implement → REFACTOR."
25
+ tools: [Read, Grep, Glob, Write]
26
+ gates:
27
+ exit: [plan-document-exists]
28
+ on:
29
+ STAGE_COMPLETE: { target: implement }
30
+ SPEC_CHANGES: { target: brainstorm }
31
+
32
+ implement:
33
+ description: "Ralph Loop: TDD cycles per task with Gate 1 (test quality) and Gate 2 (impl review)"
34
+ agent:
35
+ instructions: "Execute TDD plan. RED → GREEN → Gate 1 review → REFACTOR. After all tasks: Gate 2 full review."
36
+ tools: [Read, Write, Edit, Bash, Grep, Glob]
37
+ gates:
38
+ exit: [lint-pass, typecheck-pass, tests-pass, tdd-quality-review, impl-review]
39
+ max_retries: 6
40
+ on:
41
+ STAGE_COMPLETE: { target: test }
42
+ TESTS_FAIL: { target: fix-implement }
43
+ GATE_FAIL: { target: fix-implement }
44
+
45
+ fix-implement:
46
+ description: "Fix test quality or implementation issues from Gates 1-2"
47
+ max_retries: 3
48
+ agent:
49
+ instructions: "Fix gate findings. Do not change test expectations unless finding specifically requires it."
50
+ tools: [Read, Edit, Bash, Grep]
51
+ on:
52
+ FIX_COMPLETE: { target: implement }
53
+ MAX_RETRIES: { target: escalate-implement }
54
+
55
+ test:
56
+ description: "E2E testing + smoke testing with Gate 3 (coverage) and Gate 4 (smoke gaps)"
57
+ agent:
58
+ instructions: "Create E2E tests covering spec requirements. Run smoke tests. Gates review coverage and gaps."
59
+ tools: [Read, Write, Edit, Bash, Grep, Glob]
60
+ gates:
61
+ exit: [e2e-tests-pass, coverage-review, smoke-gap-review]
62
+ max_retries: 6
63
+ on:
64
+ STAGE_COMPLETE: { target: review }
65
+ GATE_FAIL: { target: fix-test }
66
+ IMPLEMENT_CHANGES: { target: implement }
67
+
68
+ fix-test:
69
+ description: "Fix test coverage gaps or smoke testing issues from Gates 3-4"
70
+ max_retries: 3
71
+ agent:
72
+ instructions: "Fix coverage gaps and smoke test findings."
73
+ tools: [Read, Edit, Bash, Grep]
74
+ on:
75
+ FIX_COMPLETE: { target: test }
76
+ MAX_RETRIES: { target: escalate-test }
77
+
78
+ review:
79
+ description: "Gate 5: Adversarial code review (dual-phase Claude + Codex)"
80
+ agent:
81
+ instructions: "Process adversarial findings. Fix security, concurrency, performance issues."
82
+ tools: [Read, Edit, Bash, Grep]
83
+ gates:
84
+ exit: [adversarial-review]
85
+ max_retries: 6
86
+ on:
87
+ STAGE_COMPLETE: { target: ship }
88
+ GATE_FAIL: { target: fix-review }
89
+ TEST_CHANGES: { target: test }
90
+
91
+ fix-review:
92
+ description: "Fix adversarial review findings from Gate 5"
93
+ max_retries: 3
94
+ agent:
95
+ instructions: "Fix adversarial findings. Verify fixes via tests. Do not introduce regressions."
96
+ tools: [Read, Edit, Bash, Grep]
97
+ on:
98
+ FIX_COMPLETE: { target: review }
99
+ MAX_RETRIES: { target: escalate-review }
100
+
101
+ ship:
102
+ description: "Gate 6: Final quality gate then PR creation"
103
+ agent:
104
+ instructions: "Final quality check. If passes, create PR with full context and evidence links."
105
+ tools: [Read, Edit, Bash, Grep]
106
+ gates:
107
+ exit: [final-quality-gate]
108
+ on:
109
+ STAGE_COMPLETE: { target: complete }
110
+ GATE_FAIL: { target: fix-ship }
111
+ REVIEW_CHANGES: { target: review }
112
+
113
+ fix-ship:
114
+ description: "Fix regressions or unresolved issues from Gate 6"
115
+ max_retries: 3
116
+ agent:
117
+ instructions: "Fix final gate findings. This is the last chance before shipping."
118
+ tools: [Read, Edit, Bash, Grep]
119
+ on:
120
+ FIX_COMPLETE: { target: ship }
121
+ MAX_RETRIES: { target: escalate-ship }
122
+
123
+ complete:
124
+ type: terminal
125
+ description: "Pipeline succeeded — PR created and ready for human merge"
126
+
127
+ aborted:
128
+ type: terminal
129
+ description: "Pipeline aborted by user"
130
+
131
+ escalate-implement:
132
+ type: terminal
133
+ description: "Implementation gates failed after max retries"
134
+ on_enter:
135
+ - script: "./tools/pipeline/notify-escalation.sh"
136
+ - script: "./tools/pipeline/create-escalation-issue.sh"
137
+
138
+ escalate-test:
139
+ type: terminal
140
+ description: "Testing gates failed after max retries"
141
+ on_enter:
142
+ - script: "./tools/pipeline/notify-escalation.sh"
143
+ - script: "./tools/pipeline/create-escalation-issue.sh"
144
+
145
+ escalate-review:
146
+ type: terminal
147
+ description: "Review gate failed after max retries"
148
+ on_enter:
149
+ - script: "./tools/pipeline/notify-escalation.sh"
150
+ - script: "./tools/pipeline/create-escalation-issue.sh"
151
+
152
+ escalate-ship:
153
+ type: terminal
154
+ description: "Final gate failed after max retries"
155
+ on_enter:
156
+ - script: "./tools/pipeline/notify-escalation.sh"
157
+ - script: "./tools/pipeline/create-escalation-issue.sh"
158
+
159
+ gates:
160
+ plan-document-exists:
161
+ type: custom
162
+ script: "test -f docs/zship/spec.md"
163
+ expect: { status: pass }
164
+ lint-pass:
165
+ type: builtin
166
+ command: "bun run lint"
167
+ typecheck-pass:
168
+ type: builtin
169
+ command: "bun run typecheck"
170
+ tests-pass:
171
+ type: builtin
172
+ command: "bun test"
173
+ e2e-tests-pass:
174
+ type: builtin
175
+ command: "bun run test:e2e"
176
+
177
+ tdd-quality-review:
178
+ type: custom
179
+ script: "./tools/gates/tdd-quality-review.sh"
180
+ protocol: json-stdout
181
+ inputs:
182
+ mode: dual-phase
183
+ phase_a: claude
184
+ phase_b: codex
185
+
186
+ impl-review:
187
+ type: custom
188
+ script: "./tools/gates/impl-review.sh"
189
+ protocol: json-stdout
190
+ inputs:
191
+ mode: dual-phase
192
+ focus: architecture
193
+
194
+ coverage-review:
195
+ type: custom
196
+ script: "./tools/gates/coverage-review.sh"
197
+ protocol: json-stdout
198
+ inputs:
199
+ mode: dual-phase
200
+ focus: test_coverage
201
+
202
+ smoke-gap-review:
203
+ type: custom
204
+ script: "./tools/gates/smoke-gap-review.sh"
205
+ protocol: json-stdout
206
+ inputs:
207
+ mode: dual-phase
208
+ focus: smoke_analysis
209
+
210
+ adversarial-review:
211
+ type: custom
212
+ script: "./tools/gates/adversarial-review.sh"
213
+ protocol: json-stdout
214
+ inputs:
215
+ mode: dual-phase
216
+ focus: adversarial
217
+
218
+ final-quality-gate:
219
+ type: custom
220
+ script: "./tools/gates/final-quality-gate.sh"
221
+ protocol: json-stdout
222
+ inputs:
223
+ mode: dual-phase
224
+ focus: final_quality