@buoy-design/cli 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +37 -21
- package/dist/bin.js +0 -0
- package/dist/cloud/config.d.ts +5 -0
- package/dist/cloud/config.d.ts.map +1 -1
- package/dist/cloud/config.js.map +1 -1
- package/dist/commands/ignore.d.ts +7 -3
- package/dist/commands/ignore.d.ts.map +1 -1
- package/dist/commands/ignore.js +81 -78
- package/dist/commands/ignore.js.map +1 -1
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +1 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +108 -33
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/rescue.d.ts +3 -0
- package/dist/commands/rescue.d.ts.map +1 -0
- package/dist/commands/rescue.js +147 -0
- package/dist/commands/rescue.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/rescue/report.d.ts +9 -0
- package/dist/rescue/report.d.ts.map +1 -0
- package/dist/rescue/report.js +107 -0
- package/dist/rescue/report.js.map +1 -0
- package/dist/rescue/store.d.ts +9 -0
- package/dist/rescue/store.d.ts.map +1 -0
- package/dist/rescue/store.js +50 -0
- package/dist/rescue/store.js.map +1 -0
- package/dist/rescue/types.d.ts +76 -0
- package/dist/rescue/types.d.ts.map +1 -0
- package/dist/rescue/types.js +2 -0
- package/dist/rescue/types.js.map +1 -0
- package/dist/rescue/workflow.d.ts +37 -0
- package/dist/rescue/workflow.d.ts.map +1 -0
- package/dist/rescue/workflow.js +355 -0
- package/dist/rescue/workflow.js.map +1 -0
- package/dist/services/drift-analysis.d.ts +3 -1
- package/dist/services/drift-analysis.d.ts.map +1 -1
- package/dist/services/drift-analysis.js +179 -98
- package/dist/services/drift-analysis.js.map +1 -1
- package/dist/utils/upgrade-hints.d.ts +13 -2
- package/dist/utils/upgrade-hints.d.ts.map +1 -1
- package/dist/utils/upgrade-hints.js +43 -5
- package/dist/utils/upgrade-hints.js.map +1 -1
- package/package.json +14 -14
package/dist/commands/login.js
CHANGED
|
@@ -7,6 +7,8 @@ import { Command } from 'commander';
|
|
|
7
7
|
import { createInterface } from 'readline';
|
|
8
8
|
import { exec } from 'child_process';
|
|
9
9
|
import { promisify } from 'util';
|
|
10
|
+
import { createServer } from 'http';
|
|
11
|
+
import { hostname } from 'os';
|
|
10
12
|
import { updateCloudConfig, isLoggedIn, getApiEndpoint, readCloudConfig, } from '../cloud/config.js';
|
|
11
13
|
import { getMe } from '../cloud/client.js';
|
|
12
14
|
import { spinner, error, info, warning, keyValue, newline } from '../output/reporters.js';
|
|
@@ -29,21 +31,6 @@ async function openBrowser(url) {
|
|
|
29
31
|
}
|
|
30
32
|
await execAsync(command);
|
|
31
33
|
}
|
|
32
|
-
/**
|
|
33
|
-
* Prompt for input
|
|
34
|
-
*/
|
|
35
|
-
function prompt(question) {
|
|
36
|
-
const rl = createInterface({
|
|
37
|
-
input: process.stdin,
|
|
38
|
-
output: process.stdout,
|
|
39
|
-
});
|
|
40
|
-
return new Promise((resolve) => {
|
|
41
|
-
rl.question(question, (answer) => {
|
|
42
|
-
rl.close();
|
|
43
|
-
resolve(answer.trim());
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
34
|
/**
|
|
48
35
|
* Validate API token by fetching user info
|
|
49
36
|
*/
|
|
@@ -63,6 +50,86 @@ async function validateToken(token) {
|
|
|
63
50
|
account: result.data.account,
|
|
64
51
|
};
|
|
65
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Listen on a random loopback port for the dashboard to POST the token.
|
|
55
|
+
* Resolves with the token, or null if the server could not start.
|
|
56
|
+
*/
|
|
57
|
+
function waitForTokenOnLoopback() {
|
|
58
|
+
let resolveToken = () => { };
|
|
59
|
+
const token = new Promise((resolve) => { resolveToken = resolve; });
|
|
60
|
+
const server = createServer((req, res) => {
|
|
61
|
+
// Only the dashboard origin should be talking to us; answer preflight so
|
|
62
|
+
// the browser allows the cross-origin POST from app.buoy.design.
|
|
63
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
64
|
+
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
|
|
65
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
66
|
+
if (req.method === 'OPTIONS') {
|
|
67
|
+
res.writeHead(204);
|
|
68
|
+
res.end();
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (req.method !== 'POST' || req.url !== '/token') {
|
|
72
|
+
res.writeHead(404);
|
|
73
|
+
res.end();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
let body = '';
|
|
77
|
+
req.on('data', (chunk) => { body += chunk; if (body.length > 4096)
|
|
78
|
+
req.destroy(); });
|
|
79
|
+
req.on('end', () => {
|
|
80
|
+
try {
|
|
81
|
+
const parsed = JSON.parse(body);
|
|
82
|
+
if (parsed.token && parsed.token.startsWith('buoy_')) {
|
|
83
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
84
|
+
res.end('{"ok":true}');
|
|
85
|
+
resolveToken(parsed.token);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch { /* fall through */ }
|
|
90
|
+
res.writeHead(400);
|
|
91
|
+
res.end();
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
let url = null;
|
|
95
|
+
try {
|
|
96
|
+
server.listen(0, '127.0.0.1');
|
|
97
|
+
const addr = server.address();
|
|
98
|
+
if (addr && typeof addr === 'object')
|
|
99
|
+
url = `http://127.0.0.1:${addr.port}/token`;
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
url = null;
|
|
103
|
+
}
|
|
104
|
+
return { url, token, close: () => { try {
|
|
105
|
+
server.close();
|
|
106
|
+
}
|
|
107
|
+
catch { /* ignore */ } } };
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Race a terminal prompt against the loopback listener. Whichever supplies a
|
|
111
|
+
* token first wins; the readline prompt is closed either way.
|
|
112
|
+
*/
|
|
113
|
+
function promptOrLoopback(question, loopbackToken) {
|
|
114
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
115
|
+
return new Promise((resolve) => {
|
|
116
|
+
let done = false;
|
|
117
|
+
const finish = (value) => {
|
|
118
|
+
if (done)
|
|
119
|
+
return;
|
|
120
|
+
done = true;
|
|
121
|
+
rl.close();
|
|
122
|
+
resolve(value.trim());
|
|
123
|
+
};
|
|
124
|
+
rl.question(question, finish);
|
|
125
|
+
loopbackToken.then((t) => {
|
|
126
|
+
if (!done) {
|
|
127
|
+
process.stdout.write('\n');
|
|
128
|
+
finish(t);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
}
|
|
66
133
|
export function createLoginCommand() {
|
|
67
134
|
const cmd = new Command('login');
|
|
68
135
|
cmd
|
|
@@ -87,34 +154,42 @@ export function createLoginCommand() {
|
|
|
87
154
|
token = options.token;
|
|
88
155
|
}
|
|
89
156
|
else {
|
|
90
|
-
// Interactive login/signup flow
|
|
157
|
+
// Interactive login/signup flow. The dashboard's /cli-auth page mints
|
|
158
|
+
// an API key and POSTs it back to a loopback listener, so pasting is
|
|
159
|
+
// only the fallback.
|
|
91
160
|
const endpoint = getApiEndpoint();
|
|
92
|
-
const
|
|
93
|
-
const
|
|
94
|
-
const
|
|
161
|
+
const appOrigin = endpoint.replace('api.', 'app.');
|
|
162
|
+
const listener = waitForTokenOnLoopback();
|
|
163
|
+
const params = new URLSearchParams({ host: hostname() });
|
|
164
|
+
if (listener.url)
|
|
165
|
+
params.set('callback', listener.url);
|
|
166
|
+
const cliAuthPath = `/cli-auth?${params.toString()}`;
|
|
167
|
+
const authUrl = options.signup
|
|
168
|
+
? `${appOrigin}/sign-up?redirect_url=${encodeURIComponent(cliAuthPath)}`
|
|
169
|
+
: `${appOrigin}${cliAuthPath}`;
|
|
95
170
|
newline();
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
info('Opening browser to authenticate with Buoy Cloud...');
|
|
102
|
-
}
|
|
171
|
+
info(options.signup
|
|
172
|
+
? 'Opening browser to create your Buoy account...'
|
|
173
|
+
: 'Opening browser to connect the CLI to Buoy Cloud...');
|
|
103
174
|
newline();
|
|
104
175
|
if (options.browser !== false) {
|
|
105
176
|
try {
|
|
106
177
|
await openBrowser(authUrl);
|
|
107
|
-
info('Browser opened.
|
|
178
|
+
info('Browser opened. Approve the key there and this terminal will continue.');
|
|
108
179
|
}
|
|
109
180
|
catch {
|
|
110
181
|
warning('Could not open browser automatically.');
|
|
111
182
|
}
|
|
112
183
|
}
|
|
113
184
|
newline();
|
|
114
|
-
info(`If browser didn't open, visit: ${authUrl}`);
|
|
185
|
+
info(`If the browser didn't open, visit: ${authUrl}`);
|
|
115
186
|
newline();
|
|
116
|
-
|
|
117
|
-
|
|
187
|
+
try {
|
|
188
|
+
token = await promptOrLoopback('Waiting for the browser (or paste the key here): ', listener.token);
|
|
189
|
+
}
|
|
190
|
+
finally {
|
|
191
|
+
listener.close();
|
|
192
|
+
}
|
|
118
193
|
if (!token) {
|
|
119
194
|
error('No token provided. Login cancelled.');
|
|
120
195
|
process.exit(1);
|
|
@@ -143,9 +218,9 @@ export function createLoginCommand() {
|
|
|
143
218
|
keyValue('Plan', validation.account?.plan || 'free');
|
|
144
219
|
newline();
|
|
145
220
|
info('You can now use:');
|
|
146
|
-
info(' buoy
|
|
147
|
-
info(' buoy
|
|
148
|
-
info(' buoy logout
|
|
221
|
+
info(' buoy ahoy github - Set up the GitHub PR bot');
|
|
222
|
+
info(' buoy ahoy status - Show current account');
|
|
223
|
+
info(' buoy ahoy logout - Sign out');
|
|
149
224
|
});
|
|
150
225
|
return cmd;
|
|
151
226
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAE1F,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAElC;;GAEG;AACH,KAAK,UAAU,WAAW,CAAC,GAAW;IACpC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,IAAI,OAAe,CAAC;IAEpB,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,OAAO,GAAG,SAAS,GAAG,GAAG,CAAC;YAC1B,MAAM;QACR,KAAK,OAAO;YACV,OAAO,GAAG,aAAa,GAAG,GAAG,CAAC;YAC9B,MAAM;QACR;YACE,OAAO,GAAG,aAAa,GAAG,GAAG,CAAC;IAClC,CAAC;IAED,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rescue.d.ts","sourceRoot":"","sources":["../../src/commands/rescue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2BpC,wBAAgB,mBAAmB,IAAI,OAAO,CA8L7C"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { error, header, info, keyValue, newline, setJsonMode, spinner, success, warning, } from "../output/reporters.js";
|
|
3
|
+
import { applyRescuePlan, createRescuePlan, guardRescueRun, reportRescueRun, rollbackRescueRun, verifyRescueRun, } from "../rescue/workflow.js";
|
|
4
|
+
import { rescueRunDir } from "../rescue/store.js";
|
|
5
|
+
function failure(cause) {
|
|
6
|
+
error(cause instanceof Error ? cause.message : String(cause));
|
|
7
|
+
process.exitCode = 1;
|
|
8
|
+
}
|
|
9
|
+
export function createRescueCommand() {
|
|
10
|
+
const command = new Command("rescue").description("Measure, repair, guard, and prove design-system health");
|
|
11
|
+
command
|
|
12
|
+
.command("plan", { isDefault: true })
|
|
13
|
+
.description("Create a read-only Rescue baseline and repair plan")
|
|
14
|
+
.option("--json", "Output the plan as JSON")
|
|
15
|
+
.action(async (options) => {
|
|
16
|
+
if (options.json)
|
|
17
|
+
setJsonMode(true);
|
|
18
|
+
const spin = spinner("Building Rescue plan...");
|
|
19
|
+
try {
|
|
20
|
+
const manifest = await createRescuePlan(process.cwd(), (message) => {
|
|
21
|
+
spin.text = message;
|
|
22
|
+
});
|
|
23
|
+
spin.stop();
|
|
24
|
+
if (options.json) {
|
|
25
|
+
console.log(JSON.stringify(manifest, null, 2));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
header("Buoy Rescue plan");
|
|
29
|
+
newline();
|
|
30
|
+
keyValue("Run", manifest.id);
|
|
31
|
+
keyValue("Findings", String(manifest.before.summary.total));
|
|
32
|
+
keyValue("High-confidence fixes", String(manifest.safeFixes.length));
|
|
33
|
+
keyValue("Review required", String(manifest.findings.filter((item) => item.classification === "review-required").length));
|
|
34
|
+
keyValue("Artifacts", rescueRunDir(manifest.projectRoot, manifest.id));
|
|
35
|
+
newline();
|
|
36
|
+
info(`Review report.html, then run \`buoy rescue apply --run ${manifest.id} --approve\`.`);
|
|
37
|
+
}
|
|
38
|
+
catch (cause) {
|
|
39
|
+
spin.stop();
|
|
40
|
+
failure(cause);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
command
|
|
44
|
+
.command("apply")
|
|
45
|
+
.description("Apply approved high-confidence fixes on a new branch")
|
|
46
|
+
.option("--run <id>", "Rescue run ID (defaults to latest)")
|
|
47
|
+
.requiredOption("--approve", "Confirm that the generated plan has been reviewed")
|
|
48
|
+
.option("--limit <count>", "Maximum fixes to apply", (value) => Number.parseInt(value, 10))
|
|
49
|
+
.action(async (options) => {
|
|
50
|
+
const spin = spinner("Applying approved Rescue fixes...");
|
|
51
|
+
try {
|
|
52
|
+
const manifest = await applyRescuePlan(process.cwd(), options.run, { limit: options.limit }, (message) => {
|
|
53
|
+
spin.text = message;
|
|
54
|
+
});
|
|
55
|
+
spin.stop();
|
|
56
|
+
success(`${manifest.appliedFixIds.length} high-confidence fix(es) applied on ${manifest.rescueBranch}.`);
|
|
57
|
+
if (manifest.verification?.skipped) {
|
|
58
|
+
warning("No test or typecheck scripts were detected. Manual verification is still required.");
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
success("Project verification passed.");
|
|
62
|
+
}
|
|
63
|
+
info(`Review ${rescueRunDir(manifest.projectRoot, manifest.id)}/report.html before committing.`);
|
|
64
|
+
}
|
|
65
|
+
catch (cause) {
|
|
66
|
+
spin.stop();
|
|
67
|
+
failure(cause);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
command
|
|
71
|
+
.command("verify")
|
|
72
|
+
.description("Run project checks and refresh the before/after report")
|
|
73
|
+
.option("--run <id>", "Rescue run ID (defaults to latest)")
|
|
74
|
+
.action(async (options) => {
|
|
75
|
+
const spin = spinner("Verifying Rescue changes...");
|
|
76
|
+
try {
|
|
77
|
+
const manifest = await verifyRescueRun(process.cwd(), options.run, (message) => {
|
|
78
|
+
spin.text = message;
|
|
79
|
+
});
|
|
80
|
+
spin.stop();
|
|
81
|
+
if (manifest.verification?.passed)
|
|
82
|
+
success("Rescue verification passed.");
|
|
83
|
+
else if (manifest.verification?.skipped)
|
|
84
|
+
warning("No automated project checks were detected.");
|
|
85
|
+
else
|
|
86
|
+
failure("Rescue verification failed. Review the report before proceeding.");
|
|
87
|
+
}
|
|
88
|
+
catch (cause) {
|
|
89
|
+
spin.stop();
|
|
90
|
+
failure(cause);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
command
|
|
94
|
+
.command("guard")
|
|
95
|
+
.description("Record reviewed legacy drift so checks focus on new violations")
|
|
96
|
+
.option("--run <id>", "Rescue run ID (defaults to latest)")
|
|
97
|
+
.requiredOption("--reason <reason>", "Why the remaining legacy drift is accepted")
|
|
98
|
+
.option("--actor <name>", "Person or team approving the baseline")
|
|
99
|
+
.action(async (options) => {
|
|
100
|
+
const spin = spinner("Recording reviewed legacy drift...");
|
|
101
|
+
try {
|
|
102
|
+
const manifest = await guardRescueRun(process.cwd(), options.run, options.reason, options.actor, (message) => {
|
|
103
|
+
spin.text = message;
|
|
104
|
+
});
|
|
105
|
+
spin.stop();
|
|
106
|
+
success(`${manifest.baseline?.count || 0} legacy finding(s) recorded with stable fingerprints.`);
|
|
107
|
+
info("Future drift checks focus on newly introduced violations.");
|
|
108
|
+
}
|
|
109
|
+
catch (cause) {
|
|
110
|
+
spin.stop();
|
|
111
|
+
failure(cause);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
command
|
|
115
|
+
.command("report")
|
|
116
|
+
.description("Regenerate JSON, Markdown, and HTML Rescue reports")
|
|
117
|
+
.option("--run <id>", "Rescue run ID (defaults to latest)")
|
|
118
|
+
.action(async (options) => {
|
|
119
|
+
try {
|
|
120
|
+
const { paths } = await reportRescueRun(process.cwd(), options.run);
|
|
121
|
+
success("Rescue reports generated.");
|
|
122
|
+
keyValue("HTML", paths.html);
|
|
123
|
+
keyValue("Markdown", paths.markdown);
|
|
124
|
+
keyValue("JSON", paths.json);
|
|
125
|
+
}
|
|
126
|
+
catch (cause) {
|
|
127
|
+
failure(cause);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
command
|
|
131
|
+
.command("rollback")
|
|
132
|
+
.description("Restore files saved before Rescue apply")
|
|
133
|
+
.option("--run <id>", "Rescue run ID (defaults to latest)")
|
|
134
|
+
.option("--force", "Overwrite files changed after Rescue apply")
|
|
135
|
+
.action(async (options) => {
|
|
136
|
+
try {
|
|
137
|
+
const manifest = await rollbackRescueRun(process.cwd(), options.run, options.force);
|
|
138
|
+
success(`Restored ${manifest.backups.length} file(s) from local Rescue backups.`);
|
|
139
|
+
info("The Rescue branch was retained for inspection and can be deleted manually.");
|
|
140
|
+
}
|
|
141
|
+
catch (cause) {
|
|
142
|
+
failure(cause);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
return command;
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=rescue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rescue.js","sourceRoot":"","sources":["../../src/commands/rescue.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,wBAAgB,SAAS,IAAI,OAAO,CAkDnC;AAGD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import pkg from "../package.json" with { type: "json" };
|
|
3
|
-
import { createShowCommand, createDriftCommand, createDockCommand, createAhoyCommand, createDesignMdCommand, createSystemCommand, } from "./commands/index.js";
|
|
3
|
+
import { createShowCommand, createDriftCommand, createDockCommand, createAhoyCommand, createDesignMdCommand, createSystemCommand, createRescueCommand, } from "./commands/index.js";
|
|
4
4
|
export function createCli() {
|
|
5
5
|
const program = new Command();
|
|
6
6
|
program
|
|
@@ -14,6 +14,7 @@ export function createCli() {
|
|
|
14
14
|
.addHelpText("after", `
|
|
15
15
|
Command Groups:
|
|
16
16
|
View show (components, tokens, drift, health, history, config, skills, agents, context, hooks, commands, graph, plugins, all), system
|
|
17
|
+
Product Journey rescue (plan, apply, verify, guard, report, rollback)
|
|
17
18
|
Drift Actions drift (scan, check, fix, ignore)
|
|
18
19
|
Setup dock (config, skills, agents, context, hooks, commands, plugins, tokens, graph)
|
|
19
20
|
Cloud ahoy (login, logout, status, github, gitlab, billing, plans)
|
|
@@ -22,11 +23,14 @@ Command Groups:
|
|
|
22
23
|
Quick Start:
|
|
23
24
|
$ buoy show all # everything an AI agent needs
|
|
24
25
|
$ buoy show drift # design system violations
|
|
26
|
+
$ buoy rescue plan # baseline and safe repair plan
|
|
25
27
|
$ buoy dock # set up config, skills, agents, hooks
|
|
26
28
|
`);
|
|
27
29
|
// === View (read-only) ===
|
|
28
30
|
program.addCommand(createShowCommand());
|
|
29
31
|
program.addCommand(createSystemCommand());
|
|
32
|
+
// === Complete product journey ===
|
|
33
|
+
program.addCommand(createRescueCommand());
|
|
30
34
|
// === Drift Actions ===
|
|
31
35
|
program.addCommand(createDriftCommand());
|
|
32
36
|
// === Setup ===
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACxD,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,UAAU,SAAS;IACvB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,MAAM,CAAC;SACZ,WAAW,CAAC,kDAAkD,CAAC;SAC/D,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;SACpB,aAAa,CAAC;QACb,eAAe,EAAE,KAAK;QACtB,cAAc,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE;KACpC,CAAC;SACD,WAAW,CACV,OAAO,EACP
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACxD,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,UAAU,SAAS;IACvB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,MAAM,CAAC;SACZ,WAAW,CAAC,kDAAkD,CAAC;SAC/D,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;SACpB,aAAa,CAAC;QACb,eAAe,EAAE,KAAK;QACtB,cAAc,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE;KACpC,CAAC;SACD,WAAW,CACV,OAAO,EACP;;;;;;;;;;;;;;CAcL,CACI,CAAC;IAEJ,2BAA2B;IAC3B,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACxC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAE1C,mCAAmC;IACnC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAE1C,wBAAwB;IACxB,OAAO,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAEzC,gBAAgB;IAChB,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAExC,gBAAgB;IAChB,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAExC,iBAAiB;IACjB,OAAO,CAAC,UAAU,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAE5C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,mDAAmD;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RescueManifest } from "./types.js";
|
|
2
|
+
export declare function renderRescueMarkdown(manifest: RescueManifest): string;
|
|
3
|
+
export declare function renderRescueHtml(manifest: RescueManifest): string;
|
|
4
|
+
export declare function writeRescueReports(manifest: RescueManifest): Promise<{
|
|
5
|
+
json: string;
|
|
6
|
+
markdown: string;
|
|
7
|
+
html: string;
|
|
8
|
+
}>;
|
|
9
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/rescue/report.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,YAAY,CAAC;AAoBhE,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAsDrE;AAWD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAsBjE;AAED,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAaD"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { rescueRunDir } from "./store.js";
|
|
4
|
+
function summaryTable(before, after) {
|
|
5
|
+
const rows = [
|
|
6
|
+
["Total", before.total, after?.total],
|
|
7
|
+
["Critical", before.critical, after?.critical],
|
|
8
|
+
["Warning", before.warning, after?.warning],
|
|
9
|
+
["Info", before.info, after?.info],
|
|
10
|
+
];
|
|
11
|
+
return [
|
|
12
|
+
"| Finding | Before | After | Change |",
|
|
13
|
+
"| --- | ---: | ---: | ---: |",
|
|
14
|
+
...rows.map(([label, start, end]) => {
|
|
15
|
+
const afterValue = typeof end === "number" ? end : "—";
|
|
16
|
+
const delta = typeof end === "number" ? end - Number(start) : "—";
|
|
17
|
+
return `| ${label} | ${start} | ${afterValue} | ${typeof delta === "number" && delta > 0 ? "+" : ""}${delta} |`;
|
|
18
|
+
}),
|
|
19
|
+
].join("\n");
|
|
20
|
+
}
|
|
21
|
+
export function renderRescueMarkdown(manifest) {
|
|
22
|
+
const reviewRequired = manifest.findings.filter((finding) => finding.classification === "review-required").length;
|
|
23
|
+
const acceptedLegacy = manifest.findings.filter((finding) => finding.classification === "accepted-legacy").length;
|
|
24
|
+
const verification = manifest.verification;
|
|
25
|
+
const checks = verification?.commands.length
|
|
26
|
+
? verification.commands
|
|
27
|
+
.map((command) => `- ${command.passed ? "Passed" : "Failed"}: \`${command.command} ${command.args.join(" ")}\``)
|
|
28
|
+
.join("\n")
|
|
29
|
+
: "- No project test or typecheck scripts were detected; manual verification is required.";
|
|
30
|
+
return `# Buoy Rescue report
|
|
31
|
+
|
|
32
|
+
Run: \`${manifest.id}\`
|
|
33
|
+
Status: **${manifest.status}**
|
|
34
|
+
Generated: ${manifest.updatedAt}
|
|
35
|
+
|
|
36
|
+
## Outcome
|
|
37
|
+
|
|
38
|
+
${summaryTable(manifest.before.summary, manifest.after?.summary)}
|
|
39
|
+
|
|
40
|
+
- High-confidence fixes proposed: ${manifest.safeFixes.length}
|
|
41
|
+
- Fixes applied: ${manifest.appliedFixIds.length}
|
|
42
|
+
- Findings requiring review: ${reviewRequired}
|
|
43
|
+
- Findings already accepted as legacy: ${acceptedLegacy}
|
|
44
|
+
|
|
45
|
+
## Verification
|
|
46
|
+
|
|
47
|
+
${checks}
|
|
48
|
+
|
|
49
|
+
${manifest.status === "verification_failed"
|
|
50
|
+
? "Rescue restored every edited source file after the failed check. The branch and evidence remain for inspection."
|
|
51
|
+
: ""}
|
|
52
|
+
|
|
53
|
+
## Guardrail
|
|
54
|
+
|
|
55
|
+
${manifest.baseline
|
|
56
|
+
? `Remaining legacy drift was recorded at \`${manifest.baseline.path}\` with reason: ${manifest.baseline.reason}`
|
|
57
|
+
: 'No legacy baseline was created by this run. Use `buoy rescue guard --reason "…"` after reviewing the remaining findings.'}
|
|
58
|
+
|
|
59
|
+
## Safety and privacy
|
|
60
|
+
|
|
61
|
+
Buoy Rescue runs against local files. This run did not commit, push, merge, or upload source code. Ambiguous findings remain review-required, and backups are retained locally for rollback.
|
|
62
|
+
`;
|
|
63
|
+
}
|
|
64
|
+
function escapeHtml(value) {
|
|
65
|
+
return value
|
|
66
|
+
.replaceAll("&", "&")
|
|
67
|
+
.replaceAll("<", "<")
|
|
68
|
+
.replaceAll(">", ">")
|
|
69
|
+
.replaceAll('"', """)
|
|
70
|
+
.replaceAll("'", "'");
|
|
71
|
+
}
|
|
72
|
+
export function renderRescueHtml(manifest) {
|
|
73
|
+
const markdown = renderRescueMarkdown(manifest);
|
|
74
|
+
const before = manifest.before.summary;
|
|
75
|
+
const after = manifest.after?.summary;
|
|
76
|
+
const cards = [
|
|
77
|
+
["Before", before.total],
|
|
78
|
+
["After", after?.total ?? "—"],
|
|
79
|
+
["Applied", manifest.appliedFixIds.length],
|
|
80
|
+
[
|
|
81
|
+
"Needs review",
|
|
82
|
+
manifest.findings.filter((item) => item.classification === "review-required").length,
|
|
83
|
+
],
|
|
84
|
+
];
|
|
85
|
+
return `<!doctype html>
|
|
86
|
+
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
87
|
+
<title>Buoy Rescue · ${escapeHtml(manifest.id)}</title>
|
|
88
|
+
<style>body{margin:0;background:#071827;color:#eaf6f8;font:16px/1.55 ui-sans-serif,system-ui,sans-serif}main{max-width:960px;margin:auto;padding:64px 24px}.eyebrow{color:#53d6df;font-weight:700}.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:16px;margin:32px 0}.card,pre{background:#0c2335;border:1px solid #244052;border-radius:14px;padding:20px}.value{font-size:32px;font-weight:800}pre{white-space:pre-wrap;color:#bfd0d8;overflow:auto}a{color:#53d6df}</style></head>
|
|
89
|
+
<body><main><p class="eyebrow">BUOY RESCUE</p><h1>Before-and-after implementation report</h1><p>Run ${escapeHtml(manifest.id)} · ${escapeHtml(manifest.status)}</p>
|
|
90
|
+
<section class="cards">${cards.map(([label, value]) => `<div class="card"><div>${escapeHtml(String(label))}</div><div class="value">${escapeHtml(String(value))}</div></div>`).join("")}</section>
|
|
91
|
+
<pre>${escapeHtml(markdown)}</pre></main></body></html>`;
|
|
92
|
+
}
|
|
93
|
+
export async function writeRescueReports(manifest) {
|
|
94
|
+
const dir = rescueRunDir(manifest.projectRoot, manifest.id);
|
|
95
|
+
const paths = {
|
|
96
|
+
json: join(dir, "report.json"),
|
|
97
|
+
markdown: join(dir, "report.md"),
|
|
98
|
+
html: join(dir, "report.html"),
|
|
99
|
+
};
|
|
100
|
+
await Promise.all([
|
|
101
|
+
writeFile(paths.json, JSON.stringify(manifest, null, 2), "utf8"),
|
|
102
|
+
writeFile(paths.markdown, renderRescueMarkdown(manifest), "utf8"),
|
|
103
|
+
writeFile(paths.html, renderRescueHtml(manifest), "utf8"),
|
|
104
|
+
]);
|
|
105
|
+
return paths;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/rescue/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RescueManifest } from "./types.js";
|
|
2
|
+
export declare function rescueRoot(projectRoot: string): string;
|
|
3
|
+
export declare function rescueRunDir(projectRoot: string, runId: string): string;
|
|
4
|
+
export declare function rescueManifestPath(projectRoot: string, runId: string): string;
|
|
5
|
+
export declare function saveRescueManifest(manifest: RescueManifest): Promise<void>;
|
|
6
|
+
export declare function resolveRunId(projectRoot: string, requested?: string): Promise<string>;
|
|
7
|
+
export declare function loadRescueManifest(projectRoot: string, requested?: string): Promise<RescueManifest>;
|
|
8
|
+
export declare function createRunId(now?: Date): string;
|
|
9
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/rescue/store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7E;AAMD,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC,CAef;AAED,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAUjB;AAED,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,cAAc,CAAC,CAKzB;AAED,wBAAgB,WAAW,CAAC,GAAG,OAAa,GAAG,MAAM,CAMpD"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
export function rescueRoot(projectRoot) {
|
|
5
|
+
return join(projectRoot, ".buoy", "rescue");
|
|
6
|
+
}
|
|
7
|
+
export function rescueRunDir(projectRoot, runId) {
|
|
8
|
+
return join(rescueRoot(projectRoot), "runs", runId);
|
|
9
|
+
}
|
|
10
|
+
export function rescueManifestPath(projectRoot, runId) {
|
|
11
|
+
return join(rescueRunDir(projectRoot, runId), "manifest.json");
|
|
12
|
+
}
|
|
13
|
+
function latestPath(projectRoot) {
|
|
14
|
+
return join(rescueRoot(projectRoot), "latest.json");
|
|
15
|
+
}
|
|
16
|
+
export async function saveRescueManifest(manifest) {
|
|
17
|
+
const runDir = rescueRunDir(manifest.projectRoot, manifest.id);
|
|
18
|
+
await mkdir(runDir, { recursive: true });
|
|
19
|
+
manifest.updatedAt = new Date().toISOString();
|
|
20
|
+
await writeFile(rescueManifestPath(manifest.projectRoot, manifest.id), JSON.stringify(manifest, null, 2), "utf8");
|
|
21
|
+
await mkdir(rescueRoot(manifest.projectRoot), { recursive: true });
|
|
22
|
+
await writeFile(latestPath(manifest.projectRoot), JSON.stringify({ runId: manifest.id }, null, 2), "utf8");
|
|
23
|
+
}
|
|
24
|
+
export async function resolveRunId(projectRoot, requested) {
|
|
25
|
+
if (requested)
|
|
26
|
+
return requested;
|
|
27
|
+
const path = latestPath(projectRoot);
|
|
28
|
+
if (!existsSync(path)) {
|
|
29
|
+
throw new Error("No Rescue run found. Start with `buoy rescue plan`.");
|
|
30
|
+
}
|
|
31
|
+
const latest = JSON.parse(await readFile(path, "utf8"));
|
|
32
|
+
if (!latest.runId)
|
|
33
|
+
throw new Error("The latest Rescue run pointer is invalid.");
|
|
34
|
+
return latest.runId;
|
|
35
|
+
}
|
|
36
|
+
export async function loadRescueManifest(projectRoot, requested) {
|
|
37
|
+
const runId = await resolveRunId(projectRoot, requested);
|
|
38
|
+
const path = rescueManifestPath(projectRoot, runId);
|
|
39
|
+
if (!existsSync(path))
|
|
40
|
+
throw new Error(`Rescue run not found: ${runId}`);
|
|
41
|
+
return JSON.parse(await readFile(path, "utf8"));
|
|
42
|
+
}
|
|
43
|
+
export function createRunId(now = new Date()) {
|
|
44
|
+
const stamp = now
|
|
45
|
+
.toISOString()
|
|
46
|
+
.replace(/[-:]/g, "")
|
|
47
|
+
.replace(/\.\d{3}Z$/, "Z");
|
|
48
|
+
return `rescue-${stamp}`;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/rescue/store.ts"],"names":[],"mappings":"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"}
|