@snappedly-tools/shipyard 0.11.0 → 0.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-IVE7QDGC.js → chunk-7ZMVEAAZ.js} +4 -4
- package/dist/{chunk-IVE7QDGC.js.map → chunk-7ZMVEAAZ.js.map} +1 -1
- package/dist/{chunk-BAP7BWQ2.js → chunk-KRFKZDNV.js} +14 -6
- package/dist/chunk-KRFKZDNV.js.map +1 -0
- package/dist/{chunk-KSTSHZNH.js → chunk-ZISP3EB4.js} +3 -3
- package/dist/{chunk-KSTSHZNH.js.map → chunk-ZISP3EB4.js.map} +1 -1
- package/dist/index.js +10 -8
- package/dist/index.js.map +1 -1
- package/dist/main.js +5 -5
- package/dist/main.js.map +1 -1
- package/dist/sandboxes/docker.js +2 -2
- package/dist/templates/parallel-planner/main.mts +38 -8
- package/dist/templates/parallel-planner-with-review/main.mts +38 -8
- package/dist/templates/sequential-reviewer/implement-prompt.md +4 -4
- package/dist/templates/sequential-reviewer/main.mts +31 -5
- package/dist/templates/simple-loop/main.mts +31 -5
- package/package.json +1 -1
- package/dist/chunk-BAP7BWQ2.js.map +0 -1
package/dist/sandboxes/docker.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { defaultImageName, docker } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
1
|
+
export { defaultImageName, docker } from '../chunk-ZISP3EB4.js';
|
|
2
|
+
import '../chunk-KRFKZDNV.js';
|
|
3
3
|
//# sourceMappingURL=docker.js.map
|
|
4
4
|
//# sourceMappingURL=docker.js.map
|
|
@@ -96,7 +96,7 @@ const closeClean = async (sandbox: {
|
|
|
96
96
|
if (preservedWorktreePath)
|
|
97
97
|
throw new Error(`Sandbox has uncommitted work at ${preservedWorktreePath}`);
|
|
98
98
|
};
|
|
99
|
-
const verifyTriage = (ticketId: string) => {
|
|
99
|
+
const verifyTriage = (ticketId: string, triageOutput?: string) => {
|
|
100
100
|
try {
|
|
101
101
|
execFileSync("bash", [".shipyard/verify-triage.sh", ticketId, repository], {
|
|
102
102
|
encoding: "utf8",
|
|
@@ -105,9 +105,31 @@ const verifyTriage = (ticketId: string) => {
|
|
|
105
105
|
const detail = (error as { stderr?: string | Buffer }).stderr
|
|
106
106
|
?.toString()
|
|
107
107
|
.trim();
|
|
108
|
-
|
|
108
|
+
const reason = detail || `Could not verify triage for #${ticketId}`;
|
|
109
|
+
const output = triageOutput?.trim();
|
|
110
|
+
throw new Error(
|
|
111
|
+
output ? `${reason}; triage output: ${output.slice(-1200)}` : reason,
|
|
112
|
+
);
|
|
109
113
|
}
|
|
110
114
|
};
|
|
115
|
+
const verifyTriageAccess = async (
|
|
116
|
+
sandbox: {
|
|
117
|
+
exec: (
|
|
118
|
+
command: string,
|
|
119
|
+
) => Promise<{ exitCode: number; stdout: string; stderr: string }>;
|
|
120
|
+
},
|
|
121
|
+
ticketId: string,
|
|
122
|
+
) => {
|
|
123
|
+
if (!/^\d+$/.test(ticketId))
|
|
124
|
+
throw new Error(`Invalid issue number: ${ticketId}`);
|
|
125
|
+
const result = await sandbox.exec(
|
|
126
|
+
`gh issue view ${ticketId} --repo ${repository} --json number --jq .number`,
|
|
127
|
+
);
|
|
128
|
+
if (result.exitCode !== 0)
|
|
129
|
+
throw new Error(
|
|
130
|
+
`Cannot triage issue #${ticketId}: GitHub access failed in the sandbox: ${result.stderr.trim() || result.stdout.trim() || `exit ${result.exitCode}`}`,
|
|
131
|
+
);
|
|
132
|
+
};
|
|
111
133
|
const planSchema = z.object({ issues: z.array(z.object({ id: z.string() })) });
|
|
112
134
|
type Ticket = {
|
|
113
135
|
id: string;
|
|
@@ -174,15 +196,19 @@ const runWorker = async (scope: Scope, ticket: Ticket) => {
|
|
|
174
196
|
copyToWorktree: [".shipyard/setup.sh"],
|
|
175
197
|
});
|
|
176
198
|
try {
|
|
177
|
-
|
|
178
|
-
|
|
199
|
+
let triageOutput: string | undefined;
|
|
200
|
+
if (!ticket.triageReady) {
|
|
201
|
+
await verifyTriageAccess(sandbox, ticket.id);
|
|
202
|
+
const triage = await sandbox.run({
|
|
179
203
|
name: `triage #${ticket.id}`,
|
|
180
204
|
maxIterations: 1,
|
|
181
205
|
agent: roleAgent("routine", shipyard.CODEX_MODELS.routine),
|
|
182
206
|
promptFile: "./.shipyard/triage-prompt.md",
|
|
183
207
|
promptArgs: { TASK_ID: ticket.id, BASE_BRANCH: targetBranch },
|
|
184
208
|
});
|
|
185
|
-
|
|
209
|
+
triageOutput = triage.stdout;
|
|
210
|
+
}
|
|
211
|
+
verifyTriage(ticket.id, triageOutput);
|
|
186
212
|
const implementation = await sandbox.run({
|
|
187
213
|
name: "implementer",
|
|
188
214
|
maxIterations: 100,
|
|
@@ -447,15 +473,19 @@ for (let iteration = 0; iteration < 10; iteration++) {
|
|
|
447
473
|
let handoffEvidence: string;
|
|
448
474
|
try {
|
|
449
475
|
if (scope.kind === "standalone") {
|
|
450
|
-
|
|
451
|
-
|
|
476
|
+
let triageOutput: string | undefined;
|
|
477
|
+
if (!scope.triageReady) {
|
|
478
|
+
await verifyTriageAccess(integration, id);
|
|
479
|
+
const triage = await integration.run({
|
|
452
480
|
name: `triage #${id}`,
|
|
453
481
|
maxIterations: 1,
|
|
454
482
|
agent: roleAgent("routine", shipyard.CODEX_MODELS.routine),
|
|
455
483
|
promptFile: "./.shipyard/triage-prompt.md",
|
|
456
484
|
promptArgs: { TASK_ID: id, BASE_BRANCH: targetBranch },
|
|
457
485
|
});
|
|
458
|
-
|
|
486
|
+
triageOutput = triage.stdout;
|
|
487
|
+
}
|
|
488
|
+
verifyTriage(id, triageOutput);
|
|
459
489
|
const standalone = await integration.run({
|
|
460
490
|
name: "implementer",
|
|
461
491
|
maxIterations: 100,
|
|
@@ -96,7 +96,7 @@ const closeClean = async (sandbox: {
|
|
|
96
96
|
if (preservedWorktreePath)
|
|
97
97
|
throw new Error(`Sandbox has uncommitted work at ${preservedWorktreePath}`);
|
|
98
98
|
};
|
|
99
|
-
const verifyTriage = (ticketId: string) => {
|
|
99
|
+
const verifyTriage = (ticketId: string, triageOutput?: string) => {
|
|
100
100
|
try {
|
|
101
101
|
execFileSync("bash", [".shipyard/verify-triage.sh", ticketId, repository], {
|
|
102
102
|
encoding: "utf8",
|
|
@@ -105,9 +105,31 @@ const verifyTriage = (ticketId: string) => {
|
|
|
105
105
|
const detail = (error as { stderr?: string | Buffer }).stderr
|
|
106
106
|
?.toString()
|
|
107
107
|
.trim();
|
|
108
|
-
|
|
108
|
+
const reason = detail || `Could not verify triage for #${ticketId}`;
|
|
109
|
+
const output = triageOutput?.trim();
|
|
110
|
+
throw new Error(
|
|
111
|
+
output ? `${reason}; triage output: ${output.slice(-1200)}` : reason,
|
|
112
|
+
);
|
|
109
113
|
}
|
|
110
114
|
};
|
|
115
|
+
const verifyTriageAccess = async (
|
|
116
|
+
sandbox: {
|
|
117
|
+
exec: (
|
|
118
|
+
command: string,
|
|
119
|
+
) => Promise<{ exitCode: number; stdout: string; stderr: string }>;
|
|
120
|
+
},
|
|
121
|
+
ticketId: string,
|
|
122
|
+
) => {
|
|
123
|
+
if (!/^\d+$/.test(ticketId))
|
|
124
|
+
throw new Error(`Invalid issue number: ${ticketId}`);
|
|
125
|
+
const result = await sandbox.exec(
|
|
126
|
+
`gh issue view ${ticketId} --repo ${repository} --json number --jq .number`,
|
|
127
|
+
);
|
|
128
|
+
if (result.exitCode !== 0)
|
|
129
|
+
throw new Error(
|
|
130
|
+
`Cannot triage issue #${ticketId}: GitHub access failed in the sandbox: ${result.stderr.trim() || result.stdout.trim() || `exit ${result.exitCode}`}`,
|
|
131
|
+
);
|
|
132
|
+
};
|
|
111
133
|
const planSchema = z.object({ issues: z.array(z.object({ id: z.string() })) });
|
|
112
134
|
type Ticket = {
|
|
113
135
|
id: string;
|
|
@@ -184,15 +206,19 @@ const runWorker = async (scope: Scope, ticket: Ticket) => {
|
|
|
184
206
|
copyToWorktree: [".shipyard/setup.sh"],
|
|
185
207
|
});
|
|
186
208
|
try {
|
|
187
|
-
|
|
188
|
-
|
|
209
|
+
let triageOutput: string | undefined;
|
|
210
|
+
if (!ticket.triageReady) {
|
|
211
|
+
await verifyTriageAccess(sandbox, ticket.id);
|
|
212
|
+
const triage = await sandbox.run({
|
|
189
213
|
name: `triage #${ticket.id}`,
|
|
190
214
|
maxIterations: 1,
|
|
191
215
|
agent: roleAgent("routine", shipyard.CODEX_MODELS.routine),
|
|
192
216
|
promptFile: "./.shipyard/triage-prompt.md",
|
|
193
217
|
promptArgs: { TASK_ID: ticket.id, BASE_BRANCH: targetBranch },
|
|
194
218
|
});
|
|
195
|
-
|
|
219
|
+
triageOutput = triage.stdout;
|
|
220
|
+
}
|
|
221
|
+
verifyTriage(ticket.id, triageOutput);
|
|
196
222
|
const implementation = await sandbox.run({
|
|
197
223
|
name: "implementer",
|
|
198
224
|
maxIterations: 100,
|
|
@@ -470,15 +496,19 @@ for (let iteration = 0; iteration < 10; iteration++) {
|
|
|
470
496
|
let handoffEvidence: string;
|
|
471
497
|
try {
|
|
472
498
|
if (scope.kind === "standalone") {
|
|
473
|
-
|
|
474
|
-
|
|
499
|
+
let triageOutput: string | undefined;
|
|
500
|
+
if (!scope.triageReady) {
|
|
501
|
+
await verifyTriageAccess(integration, id);
|
|
502
|
+
const triage = await integration.run({
|
|
475
503
|
name: `triage #${id}`,
|
|
476
504
|
maxIterations: 1,
|
|
477
505
|
agent: roleAgent("routine", shipyard.CODEX_MODELS.routine),
|
|
478
506
|
promptFile: "./.shipyard/triage-prompt.md",
|
|
479
507
|
promptArgs: { TASK_ID: id, BASE_BRANCH: targetBranch },
|
|
480
508
|
});
|
|
481
|
-
|
|
509
|
+
triageOutput = triage.stdout;
|
|
510
|
+
}
|
|
511
|
+
verifyTriage(id, triageOutput);
|
|
482
512
|
const standalone = await integration.run({
|
|
483
513
|
name: "implementer",
|
|
484
514
|
maxIterations: 100,
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# Assigned issue scope
|
|
2
2
|
|
|
3
3
|
Implement scope #{{TASK_ID}} ({{ISSUE_TITLE}}) on branch `{{BRANCH}}`.
|
|
4
|
-
Read it with `gh issue view {{TASK_ID}} --comments
|
|
4
|
+
Read it with `gh issue view {{TASK_ID}} --comments` and follow `AGENTS.md`. Use the resolved scope below for relationships. Read linked guidance, `CONTEXT.md`, and ADRs when relevant to the change; inspect affected files and nearby tests.
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Use {{SKILL}} if it appears in the provided skill catalog; otherwise follow this prompt and repository policy. For a planning spec, deliver only tickets in `SCOPE.tickets` in dependency order and integrate them on this one branch. Read parent or sibling details only when a selected ticket needs them. Other linked tickets are context; do not implement them. Do not create separate child PRs.
|
|
7
|
+
|
|
8
|
+
Use `/tdd` for changed logic and local `/code-cleanup`. For presentation-only changes, inspect the affected UI at representative viewports with an available preview. Install browser or system dependencies only when required by acceptance criteria or repository policy. Run the repository's required checks plus focused checks for changed behavior; stop when those checks pass. Reinstall candidate dependencies with `bash .shipyard/setup.sh` after manifest changes. Commit and self-check the implementation. The next stage owns independent `/code-review`; do not start another reviewer, orchestration chain, PR, merge, or issue closure.
|
|
7
9
|
|
|
8
10
|
If incomplete, report the blocker without a completion marker. After a verified commit, report scope, `Checks: <commands and results>`, and limitations:
|
|
9
11
|
|
|
@@ -15,5 +17,3 @@ If incomplete, report the blocker without a completion marker. After a verified
|
|
|
15
17
|
```json
|
|
16
18
|
{{SCOPE}}
|
|
17
19
|
```
|
|
18
|
-
|
|
19
|
-
Read the complete parent and child issue bodies and comments with `gh issue view`, including repository guidance and dependency links.
|
|
@@ -93,7 +93,7 @@ const closeClean = async (sandbox: {
|
|
|
93
93
|
if (preservedWorktreePath)
|
|
94
94
|
throw new Error(`Sandbox has uncommitted work at ${preservedWorktreePath}`);
|
|
95
95
|
};
|
|
96
|
-
const verifyTriage = (ticketId: string) => {
|
|
96
|
+
const verifyTriage = (ticketId: string, triageOutput?: string) => {
|
|
97
97
|
try {
|
|
98
98
|
execFileSync("bash", [".shipyard/verify-triage.sh", ticketId, repository], {
|
|
99
99
|
encoding: "utf8",
|
|
@@ -102,9 +102,31 @@ const verifyTriage = (ticketId: string) => {
|
|
|
102
102
|
const detail = (error as { stderr?: string | Buffer }).stderr
|
|
103
103
|
?.toString()
|
|
104
104
|
.trim();
|
|
105
|
-
|
|
105
|
+
const reason = detail || `Could not verify triage for #${ticketId}`;
|
|
106
|
+
const output = triageOutput?.trim();
|
|
107
|
+
throw new Error(
|
|
108
|
+
output ? `${reason}; triage output: ${output.slice(-1200)}` : reason,
|
|
109
|
+
);
|
|
106
110
|
}
|
|
107
111
|
};
|
|
112
|
+
const verifyTriageAccess = async (
|
|
113
|
+
sandbox: {
|
|
114
|
+
exec: (
|
|
115
|
+
command: string,
|
|
116
|
+
) => Promise<{ exitCode: number; stdout: string; stderr: string }>;
|
|
117
|
+
},
|
|
118
|
+
ticketId: string,
|
|
119
|
+
) => {
|
|
120
|
+
if (!/^\d+$/.test(ticketId))
|
|
121
|
+
throw new Error(`Invalid issue number: ${ticketId}`);
|
|
122
|
+
const result = await sandbox.exec(
|
|
123
|
+
`gh issue view ${ticketId} --repo ${repository} --json number --jq .number`,
|
|
124
|
+
);
|
|
125
|
+
if (result.exitCode !== 0)
|
|
126
|
+
throw new Error(
|
|
127
|
+
`Cannot triage issue #${ticketId}: GitHub access failed in the sandbox: ${result.stderr.trim() || result.stdout.trim() || `exit ${result.exitCode}`}`,
|
|
128
|
+
);
|
|
129
|
+
};
|
|
108
130
|
|
|
109
131
|
const handoffEvidence = (stdout: string): string | undefined =>
|
|
110
132
|
[...stdout.matchAll(/<handoff>([\s\S]*?)<\/handoff>/g)].at(-1)?.[1]?.trim();
|
|
@@ -200,15 +222,19 @@ for (let iteration = 0; iteration < MAX_ITERATIONS; iteration++) {
|
|
|
200
222
|
? issue.tickets?.find((ticket) => ticket.id === ticketId)
|
|
201
223
|
?.triageReady
|
|
202
224
|
: issue.triageReady;
|
|
203
|
-
|
|
204
|
-
|
|
225
|
+
let triageOutput: string | undefined;
|
|
226
|
+
if (!ready) {
|
|
227
|
+
await verifyTriageAccess(sandbox, ticketId);
|
|
228
|
+
const triage = await sandbox.run({
|
|
205
229
|
name: `triage #${ticketId}`,
|
|
206
230
|
agent: roleAgent("routine", shipyard.CODEX_MODELS.routine),
|
|
207
231
|
maxIterations: 1,
|
|
208
232
|
promptFile: "./.shipyard/triage-prompt.md",
|
|
209
233
|
promptArgs: { TASK_ID: ticketId, BASE_BRANCH: targetBranch },
|
|
210
234
|
});
|
|
211
|
-
|
|
235
|
+
triageOutput = triage.stdout;
|
|
236
|
+
}
|
|
237
|
+
verifyTriage(ticketId, triageOutput);
|
|
212
238
|
}
|
|
213
239
|
const implement = await sandbox.run({
|
|
214
240
|
name: "implementer",
|
|
@@ -92,7 +92,7 @@ const closeClean = async (sandbox: {
|
|
|
92
92
|
if (preservedWorktreePath)
|
|
93
93
|
throw new Error(`Sandbox has uncommitted work at ${preservedWorktreePath}`);
|
|
94
94
|
};
|
|
95
|
-
const verifyTriage = (ticketId: string) => {
|
|
95
|
+
const verifyTriage = (ticketId: string, triageOutput?: string) => {
|
|
96
96
|
try {
|
|
97
97
|
execFileSync("bash", [".shipyard/verify-triage.sh", ticketId, repository], {
|
|
98
98
|
encoding: "utf8",
|
|
@@ -101,9 +101,31 @@ const verifyTriage = (ticketId: string) => {
|
|
|
101
101
|
const detail = (error as { stderr?: string | Buffer }).stderr
|
|
102
102
|
?.toString()
|
|
103
103
|
.trim();
|
|
104
|
-
|
|
104
|
+
const reason = detail || `Could not verify triage for #${ticketId}`;
|
|
105
|
+
const output = triageOutput?.trim();
|
|
106
|
+
throw new Error(
|
|
107
|
+
output ? `${reason}; triage output: ${output.slice(-1200)}` : reason,
|
|
108
|
+
);
|
|
105
109
|
}
|
|
106
110
|
};
|
|
111
|
+
const verifyTriageAccess = async (
|
|
112
|
+
sandbox: {
|
|
113
|
+
exec: (
|
|
114
|
+
command: string,
|
|
115
|
+
) => Promise<{ exitCode: number; stdout: string; stderr: string }>;
|
|
116
|
+
},
|
|
117
|
+
ticketId: string,
|
|
118
|
+
) => {
|
|
119
|
+
if (!/^\d+$/.test(ticketId))
|
|
120
|
+
throw new Error(`Invalid issue number: ${ticketId}`);
|
|
121
|
+
const result = await sandbox.exec(
|
|
122
|
+
`gh issue view ${ticketId} --repo ${repository} --json number --jq .number`,
|
|
123
|
+
);
|
|
124
|
+
if (result.exitCode !== 0)
|
|
125
|
+
throw new Error(
|
|
126
|
+
`Cannot triage issue #${ticketId}: GitHub access failed in the sandbox: ${result.stderr.trim() || result.stdout.trim() || `exit ${result.exitCode}`}`,
|
|
127
|
+
);
|
|
128
|
+
};
|
|
107
129
|
|
|
108
130
|
const blockScope = (
|
|
109
131
|
scope: { id: string; branch: string; tickets?: Array<{ id: string }> },
|
|
@@ -197,15 +219,19 @@ for (let iteration = 0; iteration < 3; iteration++) {
|
|
|
197
219
|
? issue.tickets?.find((ticket) => ticket.id === ticketId)
|
|
198
220
|
?.triageReady
|
|
199
221
|
: issue.triageReady;
|
|
200
|
-
|
|
201
|
-
|
|
222
|
+
let triageOutput: string | undefined;
|
|
223
|
+
if (!ready) {
|
|
224
|
+
await verifyTriageAccess(sandbox, ticketId);
|
|
225
|
+
const triage = await sandbox.run({
|
|
202
226
|
name: `triage #${ticketId}`,
|
|
203
227
|
agent: roleAgent("routine", shipyard.CODEX_MODELS.routine),
|
|
204
228
|
maxIterations: 1,
|
|
205
229
|
promptFile: "./.shipyard/triage-prompt.md",
|
|
206
230
|
promptArgs: { TASK_ID: ticketId, BASE_BRANCH: targetBranch },
|
|
207
231
|
});
|
|
208
|
-
|
|
232
|
+
triageOutput = triage.stdout;
|
|
233
|
+
}
|
|
234
|
+
verifyTriage(ticketId, triageOutput);
|
|
209
235
|
}
|
|
210
236
|
const result = await sandbox.run({
|
|
211
237
|
name: "implementer",
|