@agentic-sdlc/dispatch 0.1.3 → 0.2.1

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/dispatch.ts CHANGED
@@ -126,13 +126,13 @@ async function main(): Promise<void> {
126
126
  console.log(`[dispatch] Issue #${args.issue} | repo: ${args.repo} | ${args.label ? `label: ${args.label}` : `comment mode`}`);
127
127
 
128
128
  const provider = createSandboxProvider({
129
- apiKey: config.daytonaApiKey ?? "",
130
- apiUrl: config.daytonaApiUrl ?? "",
131
- ghToken: config.ghToken,
132
- snapshotName: config.snapshotName,
133
- modelApiKey: config.modelApiKey,
134
- modelRegion: config.modelRegion,
135
- model: config.model,
129
+ DAYTONA_API_KEY: config.daytonaApiKey ?? "",
130
+ DAYTONA_API_URL: config.daytonaApiUrl ?? "",
131
+ GH_TOKEN: config.ghToken,
132
+ SNAPSHOT_NAME: config.snapshotName,
133
+ MODEL_API_KEY: config.modelApiKey,
134
+ MODEL_REGION: config.modelRegion,
135
+ MODEL: config.model,
136
136
  });
137
137
 
138
138
  const sandbox = await provider.create({
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env node
2
+ import { resolve } from "node:path";
3
+ import { existsSync } from "node:fs";
4
+ import { orchestrateStage } from "../src/orchestrator.js";
5
+ import { readWorkflow } from "../src/workflow-reader.js";
6
+ import { createSandboxProvider } from "../src/sandbox-provider.js";
7
+ function parseArgs(argv) {
8
+ const args = {};
9
+ for (let i = 0; i < argv.length; i++) {
10
+ const key = argv[i];
11
+ const value = argv[i + 1];
12
+ switch (key) {
13
+ case "--issue":
14
+ args.issue = Number(value);
15
+ i++;
16
+ break;
17
+ case "--repo":
18
+ args.repo = value;
19
+ i++;
20
+ break;
21
+ case "--label":
22
+ args.label = value;
23
+ i++;
24
+ break;
25
+ case "--comment":
26
+ args.comment = value;
27
+ i++;
28
+ break;
29
+ case "--help":
30
+ printUsage();
31
+ process.exit(0);
32
+ }
33
+ }
34
+ if (!args.issue)
35
+ args.issue = parseInt(process.env.ISSUE_NUMBER ?? "", 10);
36
+ if (!args.repo)
37
+ args.repo = process.env.REPO_NAME ?? process.env.GITHUB_REPOSITORY ?? "";
38
+ if (!args.label && !args.comment)
39
+ args.label = process.env.LABEL_NAME ?? "";
40
+ if (!args.issue || isNaN(args.issue)) {
41
+ console.error("[dispatch] Missing required: --issue <number> or ISSUE_NUMBER env");
42
+ process.exit(1);
43
+ }
44
+ if (!args.repo) {
45
+ console.error("[dispatch] Missing required: --repo <owner/repo> or REPO_NAME env");
46
+ process.exit(1);
47
+ }
48
+ if (!args.label && !args.comment) {
49
+ console.error("[dispatch] Missing required: --label or --comment (or LABEL_NAME env)");
50
+ process.exit(1);
51
+ }
52
+ return args;
53
+ }
54
+ function printUsage() {
55
+ console.log(`Usage: harness-dispatch [options]
56
+
57
+ Options:
58
+ --issue <number> Issue number (or ISSUE_NUMBER env)
59
+ --repo <owner/repo> Repository (or REPO_NAME / GITHUB_REPOSITORY env)
60
+ --label <name> Label that triggered the pipeline (or LABEL_NAME env)
61
+ --comment <text> Forward a comment to the agent
62
+ --help Show this help
63
+
64
+ Environment variables:
65
+ DAYTONA_API_KEY Sandbox provider auth
66
+ DAYTONA_API_URL Sandbox API endpoint (default: https://app.daytona.io/api)
67
+ GH_TOKEN GitHub token for API access
68
+ HARNESS_MODEL_API_KEY Model provider API key
69
+ MODEL Model identifier
70
+ AWS_REGION AWS region (default: us-east-1)
71
+ SNAPSHOT_NAME Daytona snapshot name (default: pi-agent-v1)
72
+ HARNESS_SANDBOX_PROVIDER Provider override: daytona | direct
73
+ `);
74
+ }
75
+ function loadConfig() {
76
+ const ghToken = process.env.GH_TOKEN ?? "";
77
+ if (!ghToken) {
78
+ console.error("[dispatch] Missing required: GH_TOKEN env");
79
+ process.exit(1);
80
+ }
81
+ return {
82
+ ghToken,
83
+ modelApiKey: process.env.HARNESS_MODEL_API_KEY ?? process.env.MODEL_API_KEY ?? "",
84
+ modelRegion: process.env.AWS_REGION ?? "us-east-1",
85
+ model: process.env.MODEL ?? "us.anthropic.claude-sonnet-4-20250514-v1:0",
86
+ snapshotName: process.env.SNAPSHOT_NAME ?? "pi-agent-v1",
87
+ daytonaApiKey: process.env.DAYTONA_API_KEY,
88
+ daytonaApiUrl: process.env.DAYTONA_API_URL,
89
+ };
90
+ }
91
+ async function main() {
92
+ const args = parseArgs(process.argv.slice(2));
93
+ const config = loadConfig();
94
+ const workflowPath = resolve("WORKFLOW.md");
95
+ if (!existsSync(workflowPath)) {
96
+ console.error("[dispatch] WORKFLOW.md not found in current directory");
97
+ process.exit(1);
98
+ }
99
+ const workflowConfig = readWorkflow(workflowPath);
100
+ console.log(`[dispatch] Issue #${args.issue} | repo: ${args.repo} | ${args.label ? `label: ${args.label}` : `comment mode`}`);
101
+ const provider = createSandboxProvider({
102
+ DAYTONA_API_KEY: config.daytonaApiKey ?? "",
103
+ DAYTONA_API_URL: config.daytonaApiUrl ?? "",
104
+ GH_TOKEN: config.ghToken,
105
+ SNAPSHOT_NAME: config.snapshotName,
106
+ MODEL_API_KEY: config.modelApiKey,
107
+ MODEL_REGION: config.modelRegion,
108
+ MODEL: config.model,
109
+ });
110
+ const sandbox = await provider.create({
111
+ issue: args.issue,
112
+ repo: args.repo,
113
+ profile: workflowConfig.sandbox.default_profile,
114
+ });
115
+ console.log(`[dispatch] Sandbox created: ${sandbox.id}`);
116
+ try {
117
+ await provider.rpc(sandbox.id, {
118
+ type: "prompt",
119
+ text: [
120
+ 'git config user.email "bot@harness.dev"',
121
+ 'git config user.name "Harness Bot"',
122
+ ].join(" && "),
123
+ issueNumber: args.issue,
124
+ });
125
+ if (args.label) {
126
+ await runLabelDispatch(args, config, provider, sandbox.id, workflowConfig);
127
+ }
128
+ else if (args.comment) {
129
+ await runCommentDispatch(args, config, provider, sandbox.id);
130
+ }
131
+ }
132
+ finally {
133
+ console.log(`[dispatch] Destroying sandbox ${sandbox.id}...`);
134
+ await provider.destroy(sandbox.id);
135
+ console.log("[dispatch] Done.");
136
+ }
137
+ }
138
+ async function runLabelDispatch(args, config, provider, sandboxId, workflowConfig) {
139
+ const piCommand = [
140
+ `ISSUE_NUMBER=${args.issue}`,
141
+ `AWS_BEARER_TOKEN_BEDROCK=$HARNESS_MODEL_API_KEY`,
142
+ `AWS_REGION=${config.modelRegion}`,
143
+ `GH_TOKEN=$GH_TOKEN`,
144
+ `pi -p "Process issue #${args.issue}. Current label: ${args.label}."`,
145
+ `-e node_modules/@agentic-sdlc/extension/src/index.ts`,
146
+ `--provider amazon-bedrock`,
147
+ `--model ${config.model}`,
148
+ ].join(" ");
149
+ console.log("[dispatch] Starting Pi agent...");
150
+ try {
151
+ const output = await provider.rpc(sandboxId, {
152
+ type: "prompt",
153
+ text: piCommand,
154
+ issueNumber: args.issue,
155
+ });
156
+ if (output)
157
+ console.log(`[dispatch] Pi output: ${output.slice(0, 500)}`);
158
+ }
159
+ catch (err) {
160
+ const message = err instanceof Error ? err.message : String(err);
161
+ console.log(`[dispatch] Pi exited: ${message.slice(0, 500)}`);
162
+ }
163
+ console.log("[dispatch] Running post-agent orchestration...");
164
+ const artifactsDir = resolve(`artifacts/issue-${args.issue}`);
165
+ const result = orchestrateStage({
166
+ issueNumber: args.issue,
167
+ repo: args.repo,
168
+ label: args.label,
169
+ workflowConfig,
170
+ artifactsDir,
171
+ });
172
+ console.log(`[dispatch] Orchestration: stage=${result.stage} action=${result.action} nextLabel=${result.nextLabel ?? "none"}`);
173
+ }
174
+ async function runCommentDispatch(args, config, provider, sandboxId) {
175
+ const escapedComment = (args.comment ?? "").replace(/'/g, "'\\''");
176
+ const piCommand = [
177
+ `ISSUE_NUMBER=${args.issue}`,
178
+ `AWS_BEARER_TOKEN_BEDROCK=$HARNESS_MODEL_API_KEY`,
179
+ `AWS_REGION=${config.modelRegion}`,
180
+ `GH_TOKEN=$GH_TOKEN`,
181
+ `pi -p 'Human commented on issue #${args.issue}: ${escapedComment}'`,
182
+ `-e node_modules/@agentic-sdlc/extension/src/index.ts`,
183
+ `--provider amazon-bedrock`,
184
+ `--model ${config.model}`,
185
+ ].join(" ");
186
+ console.log("[dispatch] Forwarding comment to Pi agent...");
187
+ try {
188
+ await provider.rpc(sandboxId, {
189
+ type: "follow_up",
190
+ text: piCommand,
191
+ issueNumber: args.issue,
192
+ });
193
+ }
194
+ catch (err) {
195
+ const message = err instanceof Error ? err.message : String(err);
196
+ console.log(`[dispatch] Pi exited: ${message.slice(0, 500)}`);
197
+ }
198
+ }
199
+ main().catch((err) => {
200
+ console.error(`[dispatch] Fatal: ${err instanceof Error ? err.message : String(err)}`);
201
+ process.exit(1);
202
+ });
203
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../bin/dispatch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export { orchestrateStage } from "./orchestrator.js";
2
+ export { readWorkflow } from "./workflow-reader.js";
3
+ export type { StageConfig, PipelineConfig, WorkflowConfig, OrchestrationContext, OrchestrationResult } from "./types.js";
4
+ export { createSandboxProvider } from "./sandbox-provider.js";
5
+ export type { SandboxProvider, SandboxProviderConfig, RpcCommand, SandboxStatus } from "./sandbox-provider.js";
6
+ export { DaytonaSandboxProvider } from "./providers/daytona.js";
7
+ export { DirectRunnerProvider } from "./providers/direct-runner.js";
@@ -0,0 +1,6 @@
1
+ export { orchestrateStage } from "./orchestrator.js";
2
+ export { readWorkflow } from "./workflow-reader.js";
3
+ export { createSandboxProvider } from "./sandbox-provider.js";
4
+ export { DaytonaSandboxProvider } from "./providers/daytona.js";
5
+ export { DirectRunnerProvider } from "./providers/direct-runner.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { OrchestrationContext, OrchestrationResult } from "./types.js";
2
+ export declare function orchestrateStage(ctx: OrchestrationContext): OrchestrationResult;
@@ -0,0 +1,226 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ export function orchestrateStage(ctx) {
5
+ const { issueNumber, repo, label, workflowConfig, artifactsDir } = ctx;
6
+ const { pipeline } = workflowConfig;
7
+ // 1. Find the stage from the label
8
+ const stageName = pipeline.labels[label];
9
+ if (!stageName) {
10
+ console.error(`[dispatch] No stage mapped for label "${label}"`);
11
+ return { stage: "unknown", action: "escalated", nextLabel: "escalated" };
12
+ }
13
+ const stageIndex = pipeline.stages.findIndex((s) => s.name === stageName);
14
+ if (stageIndex === -1) {
15
+ console.error(`[dispatch] Stage "${stageName}" not found in pipeline.stages`);
16
+ return { stage: stageName, action: "escalated", nextLabel: "escalated" };
17
+ }
18
+ const stage = pipeline.stages[stageIndex];
19
+ // 2. Check artifact exists (if stage produces one)
20
+ if (stage.produces) {
21
+ const artifactPath = join(artifactsDir, stage.produces);
22
+ if (!existsSync(artifactPath)) {
23
+ console.error(`[dispatch] Artifact not found: ${artifactPath}`);
24
+ applyLabel(repo, issueNumber, "escalated", label);
25
+ return { stage: stage.name, action: "no-artifact", nextLabel: "escalated" };
26
+ }
27
+ }
28
+ // 3. Handle by gate type
29
+ switch (stage.gate) {
30
+ case "none":
31
+ return handleGateNone(ctx, stage, stageIndex);
32
+ case "pr-review":
33
+ return handleGatePrReview(ctx, stage, stageIndex);
34
+ case "retry":
35
+ return handleGateRetry(ctx, stage, stageIndex);
36
+ default:
37
+ console.error(`[dispatch] Unknown gate type: ${stage.gate}`);
38
+ return { stage: stage.name, action: "escalated", nextLabel: "escalated" };
39
+ }
40
+ }
41
+ function handleGateNone(ctx, stage, stageIndex) {
42
+ const { issueNumber, repo, label, workflowConfig, artifactsDir } = ctx;
43
+ // Commit artifact to current branch and push
44
+ try {
45
+ execFileSync("git", ["add", artifactsDir]);
46
+ execFileSync("git", ["commit", "-m", `chore: add ${stage.produces} for issue #${issueNumber}`]);
47
+ execFileSync("git", ["push"]);
48
+ }
49
+ catch (err) {
50
+ console.error(`[dispatch] Git commit/push failed for gate=none:`, err);
51
+ }
52
+ // Advance to next stage label
53
+ const nextLabel = findNextStageLabel(workflowConfig.pipeline, stageIndex);
54
+ if (nextLabel) {
55
+ applyLabel(repo, issueNumber, nextLabel, label);
56
+ }
57
+ return { stage: stage.name, action: "advanced", nextLabel };
58
+ }
59
+ function handleGatePrReview(ctx, stage, stageIndex) {
60
+ const { issueNumber, repo, label, workflowConfig, artifactsDir } = ctx;
61
+ const branchName = renderTemplate(stage.branch_pattern ?? `${stage.name}/issue-{{ issue.number }}`, issueNumber);
62
+ // Create or checkout branch
63
+ try {
64
+ execFileSync("git", ["checkout", "-b", branchName]);
65
+ }
66
+ catch {
67
+ // Branch may already exist — try checking it out
68
+ try {
69
+ execFileSync("git", ["checkout", branchName]);
70
+ }
71
+ catch (err) {
72
+ console.error(`[dispatch] Failed to checkout branch ${branchName}:`, err);
73
+ }
74
+ }
75
+ // Commit artifacts
76
+ try {
77
+ execFileSync("git", ["add", artifactsDir]);
78
+ execFileSync("git", ["commit", "-m", `feat: add ${stage.produces} for issue #${issueNumber}`]);
79
+ }
80
+ catch (err) {
81
+ console.error(`[dispatch] Git commit failed for pr-review gate:`, err);
82
+ }
83
+ // Push branch
84
+ try {
85
+ execFileSync("git", ["push", "-u", "origin", branchName]);
86
+ }
87
+ catch (err) {
88
+ console.error(`[dispatch] Git push failed:`, err);
89
+ }
90
+ // Open PR if one does not already exist
91
+ let prCreated = false;
92
+ try {
93
+ const existing = execFileSync("gh", [
94
+ "pr", "list",
95
+ "--repo", repo,
96
+ "--head", branchName,
97
+ "--json", "number",
98
+ ]).toString().trim();
99
+ const prs = JSON.parse(existing || "[]");
100
+ if (prs.length === 0) {
101
+ execFileSync("gh", [
102
+ "pr", "create",
103
+ "--repo", repo,
104
+ "--head", branchName,
105
+ "--title", `[#${issueNumber}] ${stage.name}: ${stage.produces}`,
106
+ "--body", `Automated PR for issue #${issueNumber} — stage: ${stage.name}`,
107
+ ]);
108
+ prCreated = true;
109
+ }
110
+ }
111
+ catch (err) {
112
+ console.error(`[dispatch] PR creation failed:`, err);
113
+ }
114
+ // Find the "ready" label for this stage (convention: stage's own ready label)
115
+ const readyLabel = findReadyLabel(workflowConfig.pipeline, stage.name);
116
+ const nextLabel = readyLabel ?? findNextStageLabel(workflowConfig.pipeline, stageIndex);
117
+ if (nextLabel) {
118
+ applyLabel(repo, issueNumber, nextLabel, label);
119
+ }
120
+ return {
121
+ stage: stage.name,
122
+ action: prCreated ? "opened-pr" : "advanced",
123
+ nextLabel,
124
+ };
125
+ }
126
+ function handleGateRetry(ctx, stage, stageIndex) {
127
+ const { issueNumber, repo, label, workflowConfig, artifactsDir } = ctx;
128
+ // Read verdict from artifact frontmatter
129
+ const verdict = readVerdictFromArtifact(artifactsDir, stage.produces ?? "");
130
+ const maxRetries = stage.max_retries ?? 3;
131
+ if (verdict === "pass") {
132
+ // Advance to next stage
133
+ const nextLabel = findNextStageLabel(workflowConfig.pipeline, stageIndex);
134
+ if (nextLabel) {
135
+ applyLabel(repo, issueNumber, nextLabel, label);
136
+ }
137
+ return { stage: stage.name, action: "advanced", nextLabel };
138
+ }
139
+ // verdict is "fail" or unknown — check retry count
140
+ const attemptCount = getAttemptCount(artifactsDir, stage.name);
141
+ if (attemptCount >= maxRetries) {
142
+ applyLabel(repo, issueNumber, "escalated", label);
143
+ return { stage: stage.name, action: "escalated", nextLabel: "escalated" };
144
+ }
145
+ // Apply retry label (needs-fix)
146
+ const retryLabel = findRetryLabel(workflowConfig.pipeline, stage.name);
147
+ if (retryLabel) {
148
+ applyLabel(repo, issueNumber, retryLabel, label);
149
+ }
150
+ return { stage: stage.name, action: "retried", nextLabel: retryLabel };
151
+ }
152
+ // --- Helpers ---
153
+ function renderTemplate(pattern, issueNumber) {
154
+ return pattern.replace(/\{\{\s*issue\.number\s*\}\}/g, String(issueNumber));
155
+ }
156
+ function applyLabel(repo, issueNumber, addLabel, removeLabel) {
157
+ try {
158
+ execFileSync("gh", [
159
+ "issue", "edit", String(issueNumber),
160
+ "--repo", repo,
161
+ "--add-label", addLabel,
162
+ "--remove-label", removeLabel,
163
+ ]);
164
+ }
165
+ catch (err) {
166
+ console.error(`[dispatch] Label transition failed (add=${addLabel}, remove=${removeLabel}):`, err);
167
+ }
168
+ }
169
+ function findNextStageLabel(pipeline, currentStageIndex) {
170
+ const nextStage = pipeline.stages[currentStageIndex + 1];
171
+ if (!nextStage)
172
+ return undefined;
173
+ // Find the label that maps to the next stage's name
174
+ for (const [lbl, stageName] of Object.entries(pipeline.labels)) {
175
+ if (stageName === nextStage.name) {
176
+ return lbl;
177
+ }
178
+ }
179
+ return undefined;
180
+ }
181
+ function findReadyLabel(pipeline, stageName) {
182
+ // Convention: look for a label like "{stage}-ready" that maps to this stage
183
+ for (const [lbl, mapped] of Object.entries(pipeline.labels)) {
184
+ if (mapped === stageName && lbl.endsWith("-ready")) {
185
+ return lbl;
186
+ }
187
+ }
188
+ return undefined;
189
+ }
190
+ function findRetryLabel(pipeline, stageName) {
191
+ // Look for a label that triggers the preceding stage (for retry, we go back)
192
+ // Convention: "needs-fix" maps to the build stage for retries
193
+ for (const [lbl, mapped] of Object.entries(pipeline.labels)) {
194
+ if (lbl === "needs-fix" || lbl.includes("retry") || lbl.includes("fix")) {
195
+ return lbl;
196
+ }
197
+ }
198
+ return undefined;
199
+ }
200
+ function readVerdictFromArtifact(artifactsDir, artifactName) {
201
+ try {
202
+ const content = readFileSync(join(artifactsDir, artifactName), "utf-8");
203
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
204
+ if (!frontmatterMatch)
205
+ return "unknown";
206
+ const verdictMatch = frontmatterMatch[1].match(/^verdict:\s*(.+)$/m);
207
+ return verdictMatch ? verdictMatch[1].trim().toLowerCase() : "unknown";
208
+ }
209
+ catch {
210
+ return "unknown";
211
+ }
212
+ }
213
+ function getAttemptCount(artifactsDir, stageName) {
214
+ try {
215
+ const attemptFile = join(artifactsDir, `.${stageName}-attempts`);
216
+ if (existsSync(attemptFile)) {
217
+ const count = parseInt(readFileSync(attemptFile, "utf-8").trim(), 10);
218
+ return isNaN(count) ? 1 : count;
219
+ }
220
+ return 1;
221
+ }
222
+ catch {
223
+ return 1;
224
+ }
225
+ }
226
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { SandboxProvider, SandboxProviderConfig, RpcCommand, SandboxStatus } from "../sandbox-provider.js";
2
+ export declare function mapDaytonaState(daytonaState: string): SandboxStatus["state"];
3
+ export interface DaytonaSandboxProviderOptions {
4
+ apiKey: string;
5
+ apiUrl: string;
6
+ ghToken: string;
7
+ snapshotName?: string;
8
+ modelApiKey?: string;
9
+ modelRegion?: string;
10
+ model?: string;
11
+ }
12
+ export declare class DaytonaSandboxProvider implements SandboxProvider {
13
+ private daytona;
14
+ private ghToken;
15
+ private snapshotName;
16
+ private modelApiKey;
17
+ private modelRegion;
18
+ private model;
19
+ private sandboxCache;
20
+ constructor(options: DaytonaSandboxProviderOptions);
21
+ create(config: SandboxProviderConfig): Promise<{
22
+ id: string;
23
+ }>;
24
+ resume(id: string): Promise<void>;
25
+ pause(id: string): Promise<void>;
26
+ destroy(id: string): Promise<void>;
27
+ rpc(id: string, command: RpcCommand): Promise<string>;
28
+ status(id: string): Promise<SandboxStatus>;
29
+ private getSandbox;
30
+ }
@@ -0,0 +1,112 @@
1
+ import { Daytona } from "@daytona/sdk";
2
+ // ---------------------------------------------------------------------------
3
+ // Daytona state mapping
4
+ // ---------------------------------------------------------------------------
5
+ export function mapDaytonaState(daytonaState) {
6
+ switch (daytonaState) {
7
+ case "started":
8
+ return "running";
9
+ case "stopped":
10
+ case "archived":
11
+ return "paused";
12
+ default:
13
+ return "stopped";
14
+ }
15
+ }
16
+ export class DaytonaSandboxProvider {
17
+ daytona;
18
+ ghToken;
19
+ snapshotName;
20
+ modelApiKey;
21
+ modelRegion;
22
+ model;
23
+ sandboxCache = new Map();
24
+ constructor(options) {
25
+ if (!options.apiKey) {
26
+ throw new Error("DaytonaSandboxProvider: apiKey is required");
27
+ }
28
+ if (!options.apiUrl) {
29
+ options.apiUrl = "https://app.daytona.io/api";
30
+ }
31
+ if (!options.ghToken) {
32
+ throw new Error("DaytonaSandboxProvider: ghToken is required");
33
+ }
34
+ this.daytona = new Daytona({
35
+ apiKey: options.apiKey,
36
+ apiUrl: options.apiUrl,
37
+ });
38
+ this.ghToken = options.ghToken;
39
+ this.snapshotName = options.snapshotName;
40
+ this.modelApiKey = options.modelApiKey ?? "";
41
+ this.modelRegion = options.modelRegion ?? "us-east-1";
42
+ this.model = options.model ?? "bedrock:us.anthropic.claude-sonnet-4-20250514-v1:0";
43
+ }
44
+ async create(config) {
45
+ const createOptions = {
46
+ language: "typescript",
47
+ labels: {
48
+ "github-issue": String(config.issue),
49
+ "github-repo": config.repo,
50
+ profile: config.profile,
51
+ },
52
+ autoStopInterval: 30,
53
+ };
54
+ if (this.snapshotName) {
55
+ createOptions.snapshot = this.snapshotName;
56
+ }
57
+ const sandbox = await this.daytona.create(createOptions);
58
+ const id = sandbox.id;
59
+ this.sandboxCache.set(id, sandbox);
60
+ // Use token-authenticated URL for private repos
61
+ const repoUrl = `https://x-access-token:${this.ghToken}@github.com/${config.repo}.git`;
62
+ await sandbox.git.clone(repoUrl, "/home/daytona/project");
63
+ // Configure gh CLI auth and strip token from git remote
64
+ await sandbox.process.executeCommand("gh auth setup-git", "/home/daytona/project", { GH_TOKEN: this.ghToken });
65
+ await sandbox.process.executeCommand(`git remote set-url origin https://github.com/${config.repo}.git`, "/home/daytona/project");
66
+ return { id };
67
+ }
68
+ async resume(id) {
69
+ const sandbox = await this.getSandbox(id);
70
+ await sandbox.start();
71
+ }
72
+ async pause(id) {
73
+ const sandbox = await this.getSandbox(id);
74
+ await sandbox.stop();
75
+ }
76
+ async destroy(id) {
77
+ const sandbox = await this.getSandbox(id);
78
+ await sandbox.delete();
79
+ this.sandboxCache.delete(id);
80
+ }
81
+ async rpc(id, command) {
82
+ const sandbox = await this.getSandbox(id);
83
+ if (command.text) {
84
+ const result = await sandbox.process.executeCommand(command.text, "/home/daytona/project", {
85
+ GH_TOKEN: this.ghToken,
86
+ MODEL_API_KEY: this.modelApiKey,
87
+ AWS_REGION: this.modelRegion,
88
+ MODEL: this.model,
89
+ ISSUE_NUMBER: String(command.issueNumber ?? ""),
90
+ });
91
+ if (result.exitCode !== 0) {
92
+ throw new Error(`RPC command failed (exit ${result.exitCode}): ${result.result}`);
93
+ }
94
+ return result.result ?? "";
95
+ }
96
+ return "";
97
+ }
98
+ async status(id) {
99
+ const sandbox = await this.getSandbox(id);
100
+ const daytonaState = sandbox.state ?? "unknown";
101
+ return { state: mapDaytonaState(daytonaState) };
102
+ }
103
+ async getSandbox(id) {
104
+ const cached = this.sandboxCache.get(id);
105
+ if (cached)
106
+ return cached;
107
+ const sandbox = await this.daytona.get(id);
108
+ this.sandboxCache.set(id, sandbox);
109
+ return sandbox;
110
+ }
111
+ }
112
+ //# sourceMappingURL=daytona.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daytona.js","sourceRoot":"","sources":["../../../src/providers/daytona.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { SandboxProvider, SandboxProviderConfig, RpcCommand, SandboxStatus } from "../sandbox-provider.js";
2
+ export declare class DirectRunnerProvider implements SandboxProvider {
3
+ private sandboxes;
4
+ create(config: SandboxProviderConfig): Promise<{
5
+ id: string;
6
+ }>;
7
+ resume(_id: string): Promise<void>;
8
+ pause(_id: string): Promise<void>;
9
+ destroy(id: string): Promise<void>;
10
+ rpc(id: string, command: RpcCommand): Promise<string>;
11
+ status(_id: string): Promise<SandboxStatus>;
12
+ /** Visible for testing: get the working directory for a sandbox */
13
+ getWorkDir(id: string): string | undefined;
14
+ }
@@ -0,0 +1,78 @@
1
+ import { mkdtempSync, rmSync, existsSync } from "node:fs";
2
+ import { execFileSync } from "node:child_process";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { randomUUID } from "node:crypto";
6
+ // ---------------------------------------------------------------------------
7
+ // DirectRunnerProvider — lightweight local execution without remote sandboxes
8
+ // ---------------------------------------------------------------------------
9
+ export class DirectRunnerProvider {
10
+ sandboxes = new Map();
11
+ async create(config) {
12
+ const id = randomUUID();
13
+ const dir = mkdtempSync(join(tmpdir(), `harness-sandbox-${id.slice(0, 8)}-`));
14
+ // Clone the repo into the temp directory
15
+ const repoUrl = `https://github.com/${config.repo}.git`;
16
+ try {
17
+ execFileSync("git", ["clone", repoUrl, dir], {
18
+ stdio: "pipe",
19
+ env: { ...process.env },
20
+ });
21
+ }
22
+ catch (err) {
23
+ // Clean up on clone failure
24
+ rmSync(dir, { recursive: true, force: true });
25
+ const message = err instanceof Error ? err.message : String(err);
26
+ throw new Error(`DirectRunnerProvider: failed to clone ${config.repo}: ${message}`);
27
+ }
28
+ this.sandboxes.set(id, dir);
29
+ return { id };
30
+ }
31
+ async resume(_id) {
32
+ // no-op for local execution
33
+ }
34
+ async pause(_id) {
35
+ // no-op for local execution
36
+ }
37
+ async destroy(id) {
38
+ const dir = this.sandboxes.get(id);
39
+ if (dir && existsSync(dir)) {
40
+ rmSync(dir, { recursive: true, force: true });
41
+ }
42
+ this.sandboxes.delete(id);
43
+ }
44
+ async rpc(id, command) {
45
+ const dir = this.sandboxes.get(id);
46
+ if (!dir) {
47
+ throw new Error(`DirectRunnerProvider: sandbox ${id} not found`);
48
+ }
49
+ if (!command.text) {
50
+ return "";
51
+ }
52
+ try {
53
+ const result = execFileSync("bash", ["-c", command.text], {
54
+ cwd: dir,
55
+ stdio: "pipe",
56
+ env: {
57
+ ...process.env,
58
+ ISSUE_NUMBER: String(command.issueNumber ?? ""),
59
+ },
60
+ maxBuffer: 10 * 1024 * 1024, // 10MB
61
+ });
62
+ return result.toString();
63
+ }
64
+ catch (err) {
65
+ const exitCode = err.status ?? 1;
66
+ const stderr = err.stderr?.toString() ?? "";
67
+ throw new Error(`DirectRunnerProvider: command failed (exit ${exitCode}): ${stderr || (err instanceof Error ? err.message : String(err))}`);
68
+ }
69
+ }
70
+ async status(_id) {
71
+ return { state: "running" };
72
+ }
73
+ /** Visible for testing: get the working directory for a sandbox */
74
+ getWorkDir(id) {
75
+ return this.sandboxes.get(id);
76
+ }
77
+ }
78
+ //# sourceMappingURL=direct-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"direct-runner.js","sourceRoot":"","sources":["../../../src/providers/direct-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export interface SandboxProviderConfig {
2
+ issue: number;
3
+ repo: string;
4
+ profile: string;
5
+ }
6
+ export interface RpcCommand {
7
+ type: "prompt" | "follow_up" | "steer" | "abort" | "new_session";
8
+ text?: string;
9
+ issueNumber?: number;
10
+ }
11
+ export interface SandboxStatus {
12
+ state: "running" | "paused" | "stopped";
13
+ }
14
+ export interface SandboxProvider {
15
+ create(config: SandboxProviderConfig): Promise<{
16
+ id: string;
17
+ }>;
18
+ resume(id: string): Promise<void>;
19
+ pause(id: string): Promise<void>;
20
+ destroy(id: string): Promise<void>;
21
+ rpc(id: string, command: RpcCommand): Promise<string>;
22
+ status(id: string): Promise<SandboxStatus>;
23
+ }
24
+ export declare function createSandboxProvider(options?: Record<string, string>): SandboxProvider;
@@ -0,0 +1,32 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Sandbox provider interface and factory
3
+ // ---------------------------------------------------------------------------
4
+ // ---------------------------------------------------------------------------
5
+ // Factory: auto-detect which provider to use
6
+ // ---------------------------------------------------------------------------
7
+ import { DirectRunnerProvider } from "./providers/direct-runner.js";
8
+ import { DaytonaSandboxProvider } from "./providers/daytona.js";
9
+ export function createSandboxProvider(options = {}) {
10
+ const daytonaKey = options["DAYTONA_API_KEY"] ?? process.env["DAYTONA_API_KEY"];
11
+ const providerOverride = options["HARNESS_SANDBOX_PROVIDER"] ?? process.env["HARNESS_SANDBOX_PROVIDER"];
12
+ if (providerOverride === "direct") {
13
+ console.log("[dispatch] Provider: direct-runner (override)");
14
+ return new DirectRunnerProvider();
15
+ }
16
+ if (daytonaKey) {
17
+ console.log("[dispatch] Provider: daytona");
18
+ return new DaytonaSandboxProvider({
19
+ apiKey: daytonaKey,
20
+ apiUrl: options["DAYTONA_API_URL"] ?? process.env["DAYTONA_API_URL"] ?? "https://app.daytona.io/api",
21
+ ghToken: options["GH_TOKEN"] ?? process.env["GH_TOKEN"] ?? "",
22
+ snapshotName: options["SNAPSHOT_NAME"] ?? process.env["SNAPSHOT_NAME"],
23
+ modelApiKey: options["MODEL_API_KEY"] ?? process.env["MODEL_API_KEY"],
24
+ modelRegion: options["MODEL_REGION"] ?? process.env["AWS_REGION"],
25
+ model: options["MODEL"] ?? process.env["MODEL"],
26
+ });
27
+ }
28
+ // Default: fall back to DirectRunnerProvider
29
+ console.log("[dispatch] Provider: direct-runner (no DAYTONA_API_KEY found)");
30
+ return new DirectRunnerProvider();
31
+ }
32
+ //# sourceMappingURL=sandbox-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-provider.js","sourceRoot":"","sources":["../../src/sandbox-provider.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,yCAAyC;AACzC,8EAA8E;AA2B9E,8EAA8E;AAC9E,6CAA6C;AAC7C,8EAA8E;AAE9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,MAAM,UAAU,qBAAqB,CAAC,UAAkC,EAAE;IACxE,MAAM,UAAU,GAAG,OAAO,CAAC,iBAAiB,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAChF,MAAM,gBAAgB,GAAG,OAAO,CAAC,0BAA0B,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IAExG,IAAI,gBAAgB,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;QAC7D,OAAO,IAAI,oBAAoB,EAAE,CAAC;IACpC,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;QAC5C,OAAO,IAAI,sBAAsB,CAAC;YAChC,MAAM,EAAE,UAAU;YAClB,MAAM,EAAE,OAAO,CAAC,iBAAiB,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,4BAA4B;YACpG,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE;YAC7D,YAAY,EAAE,OAAO,CAAC,eAAe,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;YACtE,WAAW,EAAE,OAAO,CAAC,eAAe,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;YACrE,WAAW,EAAE,OAAO,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;YACjE,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;SAChD,CAAC,CAAC;IACL,CAAC;IAED,6CAA6C;IAC7C,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC;IAC7E,OAAO,IAAI,oBAAoB,EAAE,CAAC;AACpC,CAAC"}
@@ -0,0 +1,43 @@
1
+ export interface StageConfig {
2
+ name: string;
3
+ role: string;
4
+ skill: string;
5
+ tools: string[];
6
+ gate: "none" | "pr-review" | "retry";
7
+ produces?: string;
8
+ branch_pattern?: string;
9
+ hooks?: Record<string, string>;
10
+ reads_only?: string[];
11
+ max_retries?: number;
12
+ trigger?: string;
13
+ }
14
+ export interface PipelineConfig {
15
+ stages: StageConfig[];
16
+ labels: Record<string, string>;
17
+ }
18
+ export interface WorkflowConfig {
19
+ pipeline: PipelineConfig;
20
+ sandbox: {
21
+ default_profile: string;
22
+ profiles: Record<string, string[]>;
23
+ };
24
+ agent: {
25
+ max_concurrent_issues: number;
26
+ cost_ceiling: number;
27
+ stale_threshold_minutes: number;
28
+ };
29
+ validation: Record<string, string>;
30
+ prompts: Record<string, string>;
31
+ }
32
+ export interface OrchestrationContext {
33
+ issueNumber: number;
34
+ repo: string;
35
+ label: string;
36
+ workflowConfig: WorkflowConfig;
37
+ artifactsDir: string;
38
+ }
39
+ export interface OrchestrationResult {
40
+ stage: string;
41
+ action: "advanced" | "opened-pr" | "retried" | "escalated" | "no-artifact";
42
+ nextLabel?: string;
43
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import type { WorkflowConfig } from "./types.js";
2
+ export declare function readWorkflow(filePath: string): WorkflowConfig;
3
+ export declare function parseWorkflow(content: string): WorkflowConfig;
@@ -0,0 +1,77 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { parse } from "yaml";
3
+ export function readWorkflow(filePath) {
4
+ const content = readFileSync(filePath, "utf-8");
5
+ return parseWorkflow(content);
6
+ }
7
+ export function parseWorkflow(content) {
8
+ if (!content || content.trim().length === 0) {
9
+ throw new Error("WORKFLOW.md is empty. Expected YAML frontmatter between --- delimiters.");
10
+ }
11
+ const frontmatter = extractFrontmatter(content);
12
+ const body = extractBody(content);
13
+ const config = parseYaml(frontmatter);
14
+ const prompts = extractPrompts(body);
15
+ return {
16
+ pipeline: config.pipeline,
17
+ sandbox: config.sandbox,
18
+ agent: config.agent,
19
+ validation: (config.validation ?? {}),
20
+ prompts,
21
+ };
22
+ }
23
+ function extractFrontmatter(content) {
24
+ const trimmed = content.trimStart();
25
+ if (!trimmed.startsWith("---")) {
26
+ throw new Error("WORKFLOW.md missing frontmatter. Expected file to start with --- delimiters.");
27
+ }
28
+ const afterOpening = trimmed.slice(3);
29
+ const closingIndex = afterOpening.indexOf("\n---");
30
+ if (closingIndex === -1) {
31
+ throw new Error("WORKFLOW.md missing closing --- delimiter for frontmatter.");
32
+ }
33
+ return afterOpening.slice(0, closingIndex);
34
+ }
35
+ function extractBody(content) {
36
+ const trimmed = content.trimStart();
37
+ const afterOpening = trimmed.slice(3);
38
+ const closingIndex = afterOpening.indexOf("\n---");
39
+ if (closingIndex === -1) {
40
+ return "";
41
+ }
42
+ return afterOpening.slice(closingIndex + 4);
43
+ }
44
+ function parseYaml(frontmatter) {
45
+ try {
46
+ const parsed = parse(frontmatter);
47
+ if (!parsed || typeof parsed !== "object") {
48
+ throw new Error("WORKFLOW.md frontmatter is not a valid YAML object.");
49
+ }
50
+ return parsed;
51
+ }
52
+ catch (err) {
53
+ if (err instanceof Error && err.message.startsWith("WORKFLOW.md")) {
54
+ throw err;
55
+ }
56
+ const message = err instanceof Error ? err.message : String(err);
57
+ throw new Error(`WORKFLOW.md contains malformed YAML: ${message}`);
58
+ }
59
+ }
60
+ function extractPrompts(body) {
61
+ const prompts = {};
62
+ const sections = body.split(/^### /m);
63
+ for (const section of sections) {
64
+ if (!section.trim())
65
+ continue;
66
+ const newlineIndex = section.indexOf("\n");
67
+ if (newlineIndex === -1)
68
+ continue;
69
+ const name = section.slice(0, newlineIndex).trim();
70
+ const template = section.slice(newlineIndex + 1).trimEnd();
71
+ if (name && template.trim()) {
72
+ prompts[name] = template.trimStart();
73
+ }
74
+ }
75
+ return prompts;
76
+ }
77
+ //# sourceMappingURL=workflow-reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow-reader.js","sourceRoot":"","sources":["../../src/workflow-reader.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentic-sdlc/dispatch",
3
- "version": "0.1.3",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "description": "CI-side dispatch and orchestration for the agentic SDLC harness",
6
6
  "repository": {
@@ -10,12 +10,12 @@
10
10
  },
11
11
  "exports": {
12
12
  ".": {
13
- "import": "./src/index.ts",
14
- "types": "./src/index.ts"
13
+ "import": "./dist/src/index.js",
14
+ "types": "./dist/src/index.d.ts"
15
15
  }
16
16
  },
17
17
  "bin": {
18
- "harness-dispatch": "./bin/dispatch.ts"
18
+ "harness-dispatch": "./dist/bin/dispatch.js"
19
19
  },
20
20
  "files": ["src", "bin", "dist"],
21
21
  "dependencies": {
@@ -39,14 +39,17 @@ export function createSandboxProvider(options: Record<string, string> = {}): San
39
39
  const providerOverride = options["HARNESS_SANDBOX_PROVIDER"] ?? process.env["HARNESS_SANDBOX_PROVIDER"];
40
40
 
41
41
  if (providerOverride === "direct") {
42
+ console.log("[dispatch] Provider: direct-runner (override)");
42
43
  return new DirectRunnerProvider();
43
44
  }
44
45
 
45
46
  if (daytonaKey) {
47
+ console.log("[dispatch] Provider: daytona");
46
48
  return new DaytonaSandboxProvider({
47
49
  apiKey: daytonaKey,
48
50
  apiUrl: options["DAYTONA_API_URL"] ?? process.env["DAYTONA_API_URL"] ?? "https://app.daytona.io/api",
49
51
  ghToken: options["GH_TOKEN"] ?? process.env["GH_TOKEN"] ?? "",
52
+ snapshotName: options["SNAPSHOT_NAME"] ?? process.env["SNAPSHOT_NAME"],
50
53
  modelApiKey: options["MODEL_API_KEY"] ?? process.env["MODEL_API_KEY"],
51
54
  modelRegion: options["MODEL_REGION"] ?? process.env["AWS_REGION"],
52
55
  model: options["MODEL"] ?? process.env["MODEL"],
@@ -54,5 +57,6 @@ export function createSandboxProvider(options: Record<string, string> = {}): San
54
57
  }
55
58
 
56
59
  // Default: fall back to DirectRunnerProvider
60
+ console.log("[dispatch] Provider: direct-runner (no DAYTONA_API_KEY found)");
57
61
  return new DirectRunnerProvider();
58
62
  }