@launch11/srgical 0.0.1 → 0.0.3
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/README.md +23 -11
- package/dist/core/agent.js +20 -1
- package/dist/core/augment.js +267 -0
- package/dist/ui/studio.js +14 -1
- package/docs/distribution.md +22 -20
- package/docs/product-foundation.md +2 -2
- package/docs/testing-strategy.md +3 -2
- package/package.json +4 -12
package/README.md
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
3. repeatedly execute the next eligible step,
|
|
8
8
|
4. force validation and handoff updates every time.
|
|
9
9
|
|
|
10
|
-
The current launch slice supports
|
|
11
|
-
workflow. `srgical` detects which supported tools are actually installed, keeps the planning pack
|
|
12
|
-
lets you choose the active agent for the current workspace session.
|
|
10
|
+
The current launch slice supports local `codex`, local `claude`, and local `auggie` installs through the same
|
|
11
|
+
`.srgical/` workflow. `srgical` detects which supported tools are actually installed, keeps the planning pack
|
|
12
|
+
agent-neutral, and lets you choose the active agent for the current workspace session.
|
|
13
13
|
|
|
14
14
|
## Why This Exists
|
|
15
15
|
|
|
@@ -46,8 +46,11 @@ This repo currently ships the foundation for:
|
|
|
46
46
|
- `claude`
|
|
47
47
|
Supported through the same adapter seam for planning, pack writing, and execution when the local Claude Code CLI is
|
|
48
48
|
installed and available on `PATH`.
|
|
49
|
+
- `augment`
|
|
50
|
+
Supported through the same adapter seam by targeting the local `auggie` binary for planning, pack writing, and
|
|
51
|
+
execution when Augment CLI automation is available on the current machine.
|
|
49
52
|
|
|
50
|
-
If only one supported agent is installed, `srgical` can auto-select it for the workspace session. If
|
|
53
|
+
If only one supported agent is installed, `srgical` can auto-select it for the workspace session. If more than one is
|
|
51
54
|
installed, you can keep the stored choice in the studio and still override a single execution with
|
|
52
55
|
`srgical run-next --agent <id>`.
|
|
53
56
|
|
|
@@ -79,16 +82,14 @@ npm run release:pack
|
|
|
79
82
|
The release bundle lands under `.artifacts/release/`. The broader distribution path, including standalone binaries and
|
|
80
83
|
wrapper package-manager installs, is documented in `docs/distribution.md`.
|
|
81
84
|
|
|
82
|
-
For release work, add a changeset in your feature branch:
|
|
83
|
-
|
|
84
|
-
```bash
|
|
85
|
-
npm run changeset
|
|
86
|
-
```
|
|
87
|
-
|
|
88
85
|
When that branch reaches `main`, the release workflow versions the package, publishes `@launcheleven/srgical` to
|
|
89
86
|
GitHub Packages, publishes `@launch11/srgical` to npm, and opens a matching GitHub Release entry with the packaged
|
|
90
87
|
artifacts.
|
|
91
88
|
|
|
89
|
+
The repo keeps a base version line in `package.json` and CI computes the next patch version from matching git tags. For
|
|
90
|
+
example, a base version of `0.0.0` means releases flow as `0.0.1`, `0.0.2`, and so on. To move to a new minor line,
|
|
91
|
+
change the base version to something like `0.1.0`.
|
|
92
|
+
|
|
92
93
|
## Install Prerequisites
|
|
93
94
|
|
|
94
95
|
Install `srgical`, then install at least one supported local agent CLI separately.
|
|
@@ -147,6 +148,7 @@ To override the active workspace agent for one execution only:
|
|
|
147
148
|
```bash
|
|
148
149
|
node dist/index.js run-next --agent codex
|
|
149
150
|
node dist/index.js run-next --agent claude
|
|
151
|
+
node dist/index.js run-next --agent augment
|
|
150
152
|
```
|
|
151
153
|
|
|
152
154
|
## Current Claude Caveat
|
|
@@ -157,8 +159,18 @@ uses `plan` mode for planner replies and `acceptEdits` with allowlisted local to
|
|
|
157
159
|
If the Claude CLI is not installed locally, `doctor`, the studio, and `run-next --agent claude` all report that
|
|
158
160
|
honestly instead of falling back to a fake Claude path.
|
|
159
161
|
|
|
162
|
+
## Current Augment Caveat
|
|
163
|
+
|
|
164
|
+
Augment support is wired to the documented `auggie` automation flags: `--print`, `--quiet`, `--instruction-file`,
|
|
165
|
+
`--workspace-root`, `--allow-indexing`, `--wait-for-indexing`, `--dont-save-session`, `--max-turns`, and `--ask` for
|
|
166
|
+
planner-only runs.
|
|
167
|
+
|
|
168
|
+
That means successful Augment execution still depends on a real Augment CLI install, an authenticated session such as
|
|
169
|
+
`auggie login` or `AUGMENT_SESSION_AUTH`, and whatever automation entitlements or local permission policies your
|
|
170
|
+
account requires.
|
|
171
|
+
|
|
160
172
|
## Planned Next Steps
|
|
161
173
|
|
|
162
174
|
- deepen the studio experience without weakening the terminal-first workflow
|
|
163
|
-
- keep
|
|
175
|
+
- keep multi-agent docs and validation honest as Claude and Augment runtime behavior get more live coverage
|
|
164
176
|
- expand release outputs from npm tarballs into standalone binaries and wrapper package-manager installers
|
package/dist/core/agent.js
CHANGED
|
@@ -12,6 +12,7 @@ exports.runNextPrompt = runNextPrompt;
|
|
|
12
12
|
exports.selectPrimaryAgent = selectPrimaryAgent;
|
|
13
13
|
exports.resetAgentAdaptersForTesting = resetAgentAdaptersForTesting;
|
|
14
14
|
exports.setAgentAdaptersForTesting = setAgentAdaptersForTesting;
|
|
15
|
+
const augment_1 = require("./augment");
|
|
15
16
|
const claude_1 = require("./claude");
|
|
16
17
|
const codex_1 = require("./codex");
|
|
17
18
|
const studio_session_1 = require("./studio-session");
|
|
@@ -51,7 +52,25 @@ const claudeAdapter = {
|
|
|
51
52
|
writePlanningPack: claude_1.writePlanningPack,
|
|
52
53
|
runNextPrompt: claude_1.runNextPrompt
|
|
53
54
|
};
|
|
54
|
-
const
|
|
55
|
+
const augmentAdapter = {
|
|
56
|
+
id: "augment",
|
|
57
|
+
label: "Augment CLI",
|
|
58
|
+
async detectStatus() {
|
|
59
|
+
const status = await (0, augment_1.detectAugment)();
|
|
60
|
+
return {
|
|
61
|
+
id: "augment",
|
|
62
|
+
label: "Augment CLI",
|
|
63
|
+
available: status.available,
|
|
64
|
+
command: status.command,
|
|
65
|
+
version: status.version,
|
|
66
|
+
error: status.error
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
requestPlannerReply: augment_1.requestPlannerReply,
|
|
70
|
+
writePlanningPack: augment_1.writePlanningPack,
|
|
71
|
+
runNextPrompt: augment_1.runNextPrompt
|
|
72
|
+
};
|
|
73
|
+
const defaultAgentAdapters = [codexAdapter, claudeAdapter, augmentAdapter];
|
|
55
74
|
let registeredAgentAdapters = [...defaultAgentAdapters];
|
|
56
75
|
let primaryAgentId = registeredAgentAdapters[0].id;
|
|
57
76
|
function getSupportedAgentAdapters() {
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.detectAugment = detectAugment;
|
|
7
|
+
exports.requestPlannerReply = requestPlannerReply;
|
|
8
|
+
exports.writePlanningPack = writePlanningPack;
|
|
9
|
+
exports.runNextPrompt = runNextPrompt;
|
|
10
|
+
exports.setAugmentRuntimeForTesting = setAugmentRuntimeForTesting;
|
|
11
|
+
exports.resetAugmentRuntimeForTesting = resetAugmentRuntimeForTesting;
|
|
12
|
+
const node_child_process_1 = require("node:child_process");
|
|
13
|
+
const promises_1 = require("node:fs/promises");
|
|
14
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
15
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
16
|
+
const local_pack_1 = require("./local-pack");
|
|
17
|
+
const planning_epochs_1 = require("./planning-epochs");
|
|
18
|
+
const prompts_1 = require("./prompts");
|
|
19
|
+
const AUGMENT_INSTALL_HINT = "install Augment CLI to enable";
|
|
20
|
+
let augmentCommandPromise;
|
|
21
|
+
let forcedAugmentCommand = null;
|
|
22
|
+
let spawnAndCaptureImpl = spawnAndCaptureBase;
|
|
23
|
+
async function detectAugment() {
|
|
24
|
+
try {
|
|
25
|
+
const command = await resolveAugmentCommand();
|
|
26
|
+
const version = await spawnAndCaptureImpl(command, ["--version"], process.cwd());
|
|
27
|
+
return {
|
|
28
|
+
available: true,
|
|
29
|
+
command,
|
|
30
|
+
version: version.stdout.trim()
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
return {
|
|
35
|
+
available: false,
|
|
36
|
+
command: process.platform === "win32" ? "auggie.exe" : "auggie",
|
|
37
|
+
error: normalizeAugmentDetectionError(error)
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function requestPlannerReply(workspaceRoot, messages) {
|
|
42
|
+
const result = await runAugmentExec({
|
|
43
|
+
cwd: workspaceRoot,
|
|
44
|
+
prompt: (0, prompts_1.buildPlannerPrompt)(messages, workspaceRoot),
|
|
45
|
+
askMode: true,
|
|
46
|
+
maxTurns: 4
|
|
47
|
+
});
|
|
48
|
+
return result.lastMessage.trim();
|
|
49
|
+
}
|
|
50
|
+
async function writePlanningPack(workspaceRoot, messages) {
|
|
51
|
+
const planningEpoch = await (0, planning_epochs_1.preparePlanningPackForWrite)(workspaceRoot);
|
|
52
|
+
const augmentStatus = await detectAugment();
|
|
53
|
+
if (!augmentStatus.available) {
|
|
54
|
+
return appendPlanningEpochSummary(planningEpoch, await (0, local_pack_1.writePlanningPackFallback)(workspaceRoot, messages, augmentStatus.error ?? "Augment CLI is unavailable", "Augment CLI"));
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const result = await runAugmentExec({
|
|
58
|
+
cwd: workspaceRoot,
|
|
59
|
+
prompt: await (0, prompts_1.buildPackWriterPrompt)(messages, workspaceRoot),
|
|
60
|
+
maxTurns: 24
|
|
61
|
+
});
|
|
62
|
+
return appendPlanningEpochSummary(planningEpoch, result.lastMessage.trim());
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (isAugmentUnavailableError(error)) {
|
|
66
|
+
const message = error instanceof Error ? error.message : "Augment CLI is unavailable";
|
|
67
|
+
return appendPlanningEpochSummary(planningEpoch, await (0, local_pack_1.writePlanningPackFallback)(workspaceRoot, messages, message, "Augment CLI"));
|
|
68
|
+
}
|
|
69
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
70
|
+
const epochSummary = (0, planning_epochs_1.formatPlanningEpochSummary)(planningEpoch);
|
|
71
|
+
if (epochSummary) {
|
|
72
|
+
throw new Error(`${epochSummary}\n${message}`);
|
|
73
|
+
}
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function runNextPrompt(workspaceRoot, prompt) {
|
|
78
|
+
const result = await runAugmentExec({
|
|
79
|
+
cwd: workspaceRoot,
|
|
80
|
+
prompt,
|
|
81
|
+
maxTurns: 24
|
|
82
|
+
});
|
|
83
|
+
return result.lastMessage.trim();
|
|
84
|
+
}
|
|
85
|
+
function setAugmentRuntimeForTesting(options) {
|
|
86
|
+
if (Object.prototype.hasOwnProperty.call(options, "command")) {
|
|
87
|
+
forcedAugmentCommand = options.command ?? null;
|
|
88
|
+
augmentCommandPromise = undefined;
|
|
89
|
+
}
|
|
90
|
+
if (options.spawnAndCapture) {
|
|
91
|
+
spawnAndCaptureImpl = options.spawnAndCapture;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function resetAugmentRuntimeForTesting() {
|
|
95
|
+
forcedAugmentCommand = null;
|
|
96
|
+
augmentCommandPromise = undefined;
|
|
97
|
+
spawnAndCaptureImpl = spawnAndCaptureBase;
|
|
98
|
+
}
|
|
99
|
+
async function runAugmentExec(options) {
|
|
100
|
+
const tempDir = await (0, promises_1.mkdtemp)(node_path_1.default.join(node_os_1.default.tmpdir(), "srgical-augment-"));
|
|
101
|
+
const promptFile = node_path_1.default.join(tempDir, "prompt.txt");
|
|
102
|
+
const command = await resolveAugmentCommand();
|
|
103
|
+
const args = [
|
|
104
|
+
"--print",
|
|
105
|
+
"--quiet",
|
|
106
|
+
"--workspace-root",
|
|
107
|
+
options.cwd,
|
|
108
|
+
"--instruction-file",
|
|
109
|
+
promptFile,
|
|
110
|
+
"--allow-indexing",
|
|
111
|
+
"--wait-for-indexing",
|
|
112
|
+
"--dont-save-session"
|
|
113
|
+
];
|
|
114
|
+
if (options.askMode) {
|
|
115
|
+
args.push("--ask");
|
|
116
|
+
}
|
|
117
|
+
if (options.maxTurns) {
|
|
118
|
+
args.push("--max-turns", String(options.maxTurns));
|
|
119
|
+
}
|
|
120
|
+
await (0, promises_1.writeFile)(promptFile, options.prompt, "utf8");
|
|
121
|
+
try {
|
|
122
|
+
const result = await spawnAndCaptureImpl(command, args, options.cwd);
|
|
123
|
+
return {
|
|
124
|
+
stdout: result.stdout,
|
|
125
|
+
stderr: result.stderr,
|
|
126
|
+
lastMessage: result.stdout.trim()
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
await (0, promises_1.rm)(tempDir, { recursive: true, force: true });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async function resolveAugmentCommand() {
|
|
134
|
+
if (forcedAugmentCommand) {
|
|
135
|
+
return forcedAugmentCommand;
|
|
136
|
+
}
|
|
137
|
+
if (!augmentCommandPromise) {
|
|
138
|
+
augmentCommandPromise = loadAugmentCommand();
|
|
139
|
+
}
|
|
140
|
+
return augmentCommandPromise;
|
|
141
|
+
}
|
|
142
|
+
async function loadAugmentCommand() {
|
|
143
|
+
if (process.platform !== "win32") {
|
|
144
|
+
return "auggie";
|
|
145
|
+
}
|
|
146
|
+
const result = await spawnAndCaptureImpl("where.exe", ["auggie"], process.cwd());
|
|
147
|
+
const matches = result.stdout
|
|
148
|
+
.split(/\r?\n/)
|
|
149
|
+
.map((line) => line.trim())
|
|
150
|
+
.filter(Boolean);
|
|
151
|
+
const shim = matches.find((line) => {
|
|
152
|
+
const lower = line.toLowerCase();
|
|
153
|
+
return lower.endsWith(".cmd") || lower.endsWith(".bat");
|
|
154
|
+
});
|
|
155
|
+
if (shim) {
|
|
156
|
+
return shim;
|
|
157
|
+
}
|
|
158
|
+
const executable = matches.find((line) => line.toLowerCase().endsWith(".exe"));
|
|
159
|
+
if (executable) {
|
|
160
|
+
return executable;
|
|
161
|
+
}
|
|
162
|
+
for (const candidate of matches) {
|
|
163
|
+
const siblingShim = await resolveSiblingShim(candidate);
|
|
164
|
+
if (siblingShim) {
|
|
165
|
+
return siblingShim;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (matches.length > 0) {
|
|
169
|
+
return matches[0];
|
|
170
|
+
}
|
|
171
|
+
throw new Error("Unable to resolve an Augment executable path.");
|
|
172
|
+
}
|
|
173
|
+
function spawnAndCaptureBase(command, args, cwd, stdinText) {
|
|
174
|
+
return new Promise((resolve, reject) => {
|
|
175
|
+
const spec = buildSpawnSpec(command, args, cwd);
|
|
176
|
+
const child = (0, node_child_process_1.spawn)(spec.command, spec.args, spec.options);
|
|
177
|
+
let stdout = "";
|
|
178
|
+
let stderr = "";
|
|
179
|
+
child.stdout.on("data", (chunk) => {
|
|
180
|
+
stdout += chunk.toString();
|
|
181
|
+
});
|
|
182
|
+
child.stderr.on("data", (chunk) => {
|
|
183
|
+
stderr += chunk.toString();
|
|
184
|
+
});
|
|
185
|
+
child.on("error", reject);
|
|
186
|
+
child.on("close", (code) => {
|
|
187
|
+
if (code === 0) {
|
|
188
|
+
resolve({ stdout, stderr });
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
reject(new Error(stderr.trim() || stdout.trim() || `${command} exited with code ${code}`));
|
|
192
|
+
});
|
|
193
|
+
if (stdinText) {
|
|
194
|
+
child.stdin.write(stdinText);
|
|
195
|
+
}
|
|
196
|
+
child.stdin.end();
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
function buildSpawnSpec(command, args, cwd) {
|
|
200
|
+
const lower = command.toLowerCase();
|
|
201
|
+
if (lower.endsWith(".cmd") || lower.endsWith(".bat")) {
|
|
202
|
+
const commandLine = [quoteForShell(command), ...args.map(quoteForShell)].join(" ");
|
|
203
|
+
return {
|
|
204
|
+
command: commandLine,
|
|
205
|
+
args: [],
|
|
206
|
+
options: {
|
|
207
|
+
cwd,
|
|
208
|
+
env: process.env,
|
|
209
|
+
shell: true
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
command,
|
|
215
|
+
args,
|
|
216
|
+
options: {
|
|
217
|
+
cwd,
|
|
218
|
+
env: process.env
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
async function resolveSiblingShim(candidate) {
|
|
223
|
+
const extension = node_path_1.default.extname(candidate);
|
|
224
|
+
if (extension) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
for (const suffix of [".cmd", ".bat", ".exe"]) {
|
|
228
|
+
const sibling = `${candidate}${suffix}`;
|
|
229
|
+
try {
|
|
230
|
+
await (0, promises_1.access)(sibling);
|
|
231
|
+
return sibling;
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
function quoteForShell(value) {
|
|
240
|
+
if (/^[A-Za-z0-9_:\\/.=-]+$/.test(value)) {
|
|
241
|
+
return value;
|
|
242
|
+
}
|
|
243
|
+
const escaped = value.replace(/"/g, '""');
|
|
244
|
+
return `"${escaped}"`;
|
|
245
|
+
}
|
|
246
|
+
function normalizeAugmentDetectionError(error) {
|
|
247
|
+
const message = error instanceof Error ? error.message : "Failed to run auggie";
|
|
248
|
+
const normalized = message.toLowerCase();
|
|
249
|
+
if (normalized.includes("could not find files for the given pattern") ||
|
|
250
|
+
normalized.includes("unable to resolve an augment executable path") ||
|
|
251
|
+
normalized.includes("'auggie' is not recognized") ||
|
|
252
|
+
normalized.includes("enoent")) {
|
|
253
|
+
return AUGMENT_INSTALL_HINT;
|
|
254
|
+
}
|
|
255
|
+
return message;
|
|
256
|
+
}
|
|
257
|
+
function isAugmentUnavailableError(error) {
|
|
258
|
+
const message = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
|
|
259
|
+
return (message.includes("unable to resolve an augment executable path") ||
|
|
260
|
+
message.includes("'auggie' is not recognized") ||
|
|
261
|
+
message.includes("enoent") ||
|
|
262
|
+
message.includes("failed to run auggie"));
|
|
263
|
+
}
|
|
264
|
+
function appendPlanningEpochSummary(preparation, summary) {
|
|
265
|
+
const epochSummary = (0, planning_epochs_1.formatPlanningEpochSummary)(preparation);
|
|
266
|
+
return [epochSummary, summary].filter(Boolean).join("\n");
|
|
267
|
+
}
|
package/dist/ui/studio.js
CHANGED
|
@@ -335,7 +335,7 @@ async function launchStudio(options = {}) {
|
|
|
335
335
|
await appendMessage({
|
|
336
336
|
role: "system",
|
|
337
337
|
content: [
|
|
338
|
-
|
|
338
|
+
buildAgentUsageMessage(),
|
|
339
339
|
"",
|
|
340
340
|
renderAgentSelectionMessage(agentState.status, agentState.statuses)
|
|
341
341
|
].join("\n")
|
|
@@ -650,6 +650,19 @@ function renderAgentSelectionMessage(activeAgent, statuses) {
|
|
|
650
650
|
...statuses.map((status) => formatAgentStatusLine(status, status.id === activeAgent.id))
|
|
651
651
|
].join("\n");
|
|
652
652
|
}
|
|
653
|
+
function buildAgentUsageMessage() {
|
|
654
|
+
const usages = (0, agent_1.getSupportedAgentAdapters)().map((adapter) => `\`/agent ${adapter.id}\``);
|
|
655
|
+
if (usages.length === 0) {
|
|
656
|
+
return "Usage: `/agent <id>`";
|
|
657
|
+
}
|
|
658
|
+
if (usages.length === 1) {
|
|
659
|
+
return `Usage: ${usages[0]}`;
|
|
660
|
+
}
|
|
661
|
+
if (usages.length === 2) {
|
|
662
|
+
return `Usage: ${usages[0]} or ${usages[1]}`;
|
|
663
|
+
}
|
|
664
|
+
return `Usage: ${usages.slice(0, -1).join(", ")}, or ${usages[usages.length - 1]}`;
|
|
665
|
+
}
|
|
653
666
|
function formatAgentStatusLine(status, selected) {
|
|
654
667
|
const prefix = selected ? "*" : "-";
|
|
655
668
|
const detail = status.available ? `ready (${status.version ?? "version unknown"})` : formatUnavailableAgentDetail(status);
|
package/docs/distribution.md
CHANGED
|
@@ -3,26 +3,27 @@
|
|
|
3
3
|
## Current Production Channel
|
|
4
4
|
|
|
5
5
|
The current production release channels are GitHub Packages for npm, the public npm registry, and GitHub Releases.
|
|
6
|
-
Versioning is
|
|
7
|
-
|
|
6
|
+
Versioning is tag-driven from git history, which means the repo carries a base major/minor line and CI computes the
|
|
7
|
+
next patch version during release instead of committing a version bump back to `main`.
|
|
8
8
|
|
|
9
|
-
The npm package does not bundle `codex` or `
|
|
10
|
-
separately and available on `PATH`, and `srgical doctor` remains the truthful way to confirm which agents are
|
|
11
|
-
the current machine.
|
|
9
|
+
The npm package does not bundle `codex`, `claude`, or `auggie`. Users still need at least one supported local agent CLI
|
|
10
|
+
installed separately and available on `PATH`, and `srgical doctor` remains the truthful way to confirm which agents are
|
|
11
|
+
usable on the current machine.
|
|
12
12
|
|
|
13
13
|
## Release Flow
|
|
14
14
|
|
|
15
|
-
1.
|
|
16
|
-
2. When
|
|
17
|
-
3.
|
|
18
|
-
|
|
19
|
-
4. The
|
|
20
|
-
5. The workflow
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
1. `package.json` stores the release line, such as `0.0.0` or `0.1.0`.
|
|
16
|
+
2. When a commit lands on `main`, the release workflow runs `npm ci` and `npm test`.
|
|
17
|
+
3. CI reads the base version, looks for existing `v<major>.<minor>.*` tags, and computes the next patch version for
|
|
18
|
+
the current untagged commit.
|
|
19
|
+
4. The workflow stages that computed version into temporary package copies without mutating the committed repo files.
|
|
20
|
+
5. The same workflow publishes `@launcheleven/srgical` to GitHub Packages and `@launch11/srgical` to the public npm
|
|
21
|
+
registry.
|
|
22
|
+
6. After both publishes succeed, the workflow creates a `v<version>` tag and a GitHub Release with the packaged
|
|
23
|
+
artifacts attached.
|
|
23
24
|
|
|
24
|
-
This keeps the published semver repeatable
|
|
25
|
-
|
|
25
|
+
This keeps the published semver repeatable for a given commit, avoids commit-noise from release-only version bumps, and
|
|
26
|
+
still gives each published package a unique version that both registries can accept.
|
|
26
27
|
|
|
27
28
|
## Local Release Check
|
|
28
29
|
|
|
@@ -36,8 +37,9 @@ That command:
|
|
|
36
37
|
|
|
37
38
|
- builds the TypeScript CLI,
|
|
38
39
|
- runs `node dist/index.js doctor`,
|
|
39
|
-
-
|
|
40
|
-
-
|
|
40
|
+
- computes the next release version from git tags,
|
|
41
|
+
- creates GitHub Packages and npm tarballs under `.artifacts/release/`,
|
|
42
|
+
- writes `release-manifest.json` and `release-manifest.md` with the artifact paths and SHA256 hashes.
|
|
41
43
|
|
|
42
44
|
## Registry Configuration
|
|
43
45
|
|
|
@@ -74,8 +76,8 @@ After installing the package, run:
|
|
|
74
76
|
srgical doctor
|
|
75
77
|
```
|
|
76
78
|
|
|
77
|
-
That verifies the workspace state, shows the active agent, and reports whether `codex` and `
|
|
78
|
-
available or missing.
|
|
79
|
+
That verifies the workspace state, shows the active agent, and reports whether `codex`, `claude`, and `auggie` are
|
|
80
|
+
locally available or missing.
|
|
79
81
|
|
|
80
82
|
## Artifact Strategy
|
|
81
83
|
|
|
@@ -94,7 +96,7 @@ npm install -g @launch11/srgical
|
|
|
94
96
|
|
|
95
97
|
- Required local prerequisites after install:
|
|
96
98
|
- authenticated access to GitHub Packages
|
|
97
|
-
- `codex` and/or `
|
|
99
|
+
- `codex`, `claude`, and/or `auggie` installed separately
|
|
98
100
|
- available on `PATH` for the current shell session
|
|
99
101
|
|
|
100
102
|
- Local install smoke test from a generated tarball:
|
|
@@ -27,7 +27,7 @@ time.
|
|
|
27
27
|
|
|
28
28
|
## V1 Scope
|
|
29
29
|
|
|
30
|
-
-
|
|
30
|
+
- Three launch-scope agent adapters: `codex`, `claude`, and `augment`
|
|
31
31
|
- One planning-pack format under `.srgical/`
|
|
32
32
|
- One full-screen TUI for planning conversation
|
|
33
33
|
- One execution command that runs the current next-step prompt through the active workspace agent
|
|
@@ -45,6 +45,6 @@ time.
|
|
|
45
45
|
## Distribution Strategy
|
|
46
46
|
|
|
47
47
|
- Native packages: GitHub Packages as `@launcheleven/srgical` and npm public as `@launch11/srgical`
|
|
48
|
-
- Versioning model: semver via
|
|
48
|
+
- Versioning model: semver via git tags on GitHub Actions, with `package.json` carrying the base major/minor line
|
|
49
49
|
- Release artifacts: standalone binaries for Windows, macOS, and Linux
|
|
50
50
|
- Package-manager wrappers: `brew`, `choco`, and other ecosystems can install those release artifacts
|
package/docs/testing-strategy.md
CHANGED
|
@@ -24,8 +24,9 @@ real bugs.
|
|
|
24
24
|
|
|
25
25
|
### Tier 3: Adapter and Agent behavior
|
|
26
26
|
|
|
27
|
-
- primary-agent status detection must degrade cleanly when
|
|
28
|
-
- planner, pack-writing, and execution adapters must preserve today's
|
|
27
|
+
- primary-agent status detection must degrade cleanly when any supported adapter is unavailable.
|
|
28
|
+
- planner, pack-writing, and execution adapters must preserve today's multi-agent behavior across Codex, Claude Code,
|
|
29
|
+
and Augment CLI.
|
|
29
30
|
- Windows command resolution and shell-shim launching must stay covered because that path has already broken once.
|
|
30
31
|
|
|
31
32
|
### Tier 4: Release confidence
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@launch11/srgical",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "A polished local-first CLI for planning and executing long AI-driven delivery sequences.",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -13,18 +13,11 @@
|
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
15
|
"build": "tsc -p tsconfig.json",
|
|
16
|
-
"changeset": "changeset",
|
|
17
16
|
"dev": "tsx src/index.ts",
|
|
18
|
-
"release": "npm run release:pack && npm run publish:github && npm run publish:npm",
|
|
19
17
|
"start": "node dist/index.js",
|
|
20
18
|
"doctor": "tsx src/index.ts doctor",
|
|
21
19
|
"test": "tsx --test test/**/*.test.ts",
|
|
22
|
-
"test:coverage": "tsx --test --experimental-test-coverage test/**/*.test.ts"
|
|
23
|
-
"version-packages": "changeset version",
|
|
24
|
-
"release:pack": "node scripts/release-pack.mjs",
|
|
25
|
-
"publish:github": "changeset publish",
|
|
26
|
-
"publish:npm": "node scripts/publish-npm.mjs",
|
|
27
|
-
"release:version": "node scripts/read-package-version.mjs"
|
|
20
|
+
"test:coverage": "tsx --test --experimental-test-coverage test/**/*.test.ts"
|
|
28
21
|
},
|
|
29
22
|
"engines": {
|
|
30
23
|
"node": ">=20"
|
|
@@ -38,8 +31,8 @@
|
|
|
38
31
|
"url": "https://github.com/LaunchEleven/Srgical/issues"
|
|
39
32
|
},
|
|
40
33
|
"publishConfig": {
|
|
41
|
-
"
|
|
42
|
-
"
|
|
34
|
+
"registry": "https://registry.npmjs.org/",
|
|
35
|
+
"access": "public"
|
|
43
36
|
},
|
|
44
37
|
"keywords": [
|
|
45
38
|
"ai",
|
|
@@ -55,7 +48,6 @@
|
|
|
55
48
|
"commander": "^14.0.3"
|
|
56
49
|
},
|
|
57
50
|
"devDependencies": {
|
|
58
|
-
"@changesets/cli": "^2.30.0",
|
|
59
51
|
"@types/blessed": "^0.1.27",
|
|
60
52
|
"@types/node": "^25.5.0",
|
|
61
53
|
"tsx": "^4.21.0",
|