@dadado/agent-kit-cli 5.0.0 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dashboard/dashboard.html +35 -1
- package/dashboard/lib/guards.mjs +56 -2
- package/dashboard/start-broadcast.mjs +2 -1
- package/dashboard/start.mjs +2 -1
- package/dist/index.js +518 -129
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -72,8 +72,11 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
|
|
|
72
72
|
"004d98f557942677264d053dcd8335f2bbcf19c5591123ec16a7a2697cb88932",
|
|
73
73
|
"05ee6ecde4215e33ace0ee152ffbf2cd885d2bd4b032900f0f0bb001d350ef0f",
|
|
74
74
|
"082bdbc584be3f3d8aa6e9d7b9f4e076450f3ff48f9147a1deb557e31475036b",
|
|
75
|
+
"09850afc201eccb3e700cb934400d49c9cbe7510d4a546ee84ee519771a8200e",
|
|
75
76
|
"0b5fe4729c3c68654434837630d775b847c082418f25b0b2c581700fe84b797a",
|
|
76
77
|
"1106b279558b6a20f87951102f172a680976f3e6530855d5dad083e1f89b9ba3",
|
|
78
|
+
"12bed56b332406477cf546d9e8360d3cab129bd82a638bea356726d00a6847a3",
|
|
79
|
+
"13f6a0711a2fcadcc7f1b751772448517ce4871cdef6a0269fc26dad51ebe26d",
|
|
77
80
|
"15566765ec95dad3bc3160f20ac910e01a13471df536e6d990f4b263700784a9",
|
|
78
81
|
"1681e6cf7b80a67cd999b94b8b6e16eb8caed0e11b32905848ba733da956e902",
|
|
79
82
|
"17818e47e06349ee35c1d8e1cc16e8bcbbbcc89c664014e9096e1f08c8567807",
|
|
@@ -83,6 +86,7 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
|
|
|
83
86
|
"1c5c1af87951367ad04bb6fa5b1d6ebaaefbc0ee95989b624cabf406a1869907",
|
|
84
87
|
"1ded5c7b7eefc355fc1d17feb65ec472e35ed96076e47ce95f7bff5c1b84746c",
|
|
85
88
|
"1e58e0d4f2e8459b95a40d1b1e72c5c85a87230cbde945840a84073fe3a20422",
|
|
89
|
+
"2280e3ca96129ab2de8a85a301df7c2b15ffaa6204b734ed3b1f303e0055c41d",
|
|
86
90
|
"285668d08f1b15d96286d27e29cc4a67e126e097fb8a940bdde33ccf25bd2bcd",
|
|
87
91
|
"2acdb148b07f3a4872b896da419af796fd3fefaace7ac79cdee0aab447004a83",
|
|
88
92
|
"2cd7fc018a384b0188737259ecf593ce25b4b75cc38b3e410063ac91745894b9",
|
|
@@ -95,6 +99,7 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
|
|
|
95
99
|
"46a1dd4a07a2190ab9fb09abc05a3962277209f8e0c28033bb41450301474c86",
|
|
96
100
|
"48a0d55e21132a305946b195db7f6b75da78d44a1d32166fb0c69bef4a5ffbe2",
|
|
97
101
|
"4b62a46c74e5fa6a80283f21e8e6711958fbcd577051dc73ff4050643a031475",
|
|
102
|
+
"4ba6e319ac79455a7d2713674f64fabbc9cd401b5d26b1c0edbd19c27a52297e",
|
|
98
103
|
"4bf23acbc9bd4e0f8468e61f4970e182600b72d9025d29e81ddbd83cb7b1710a",
|
|
99
104
|
"4c5167d0ebde685f266dce32c516a7c43876e0520647b93f07f2e2147e6a7b2f",
|
|
100
105
|
"4dc4efcd1b43c643d3889fb349df8d4964d0867c3a67eb67e2ec168fbb70fc75",
|
|
@@ -113,11 +118,16 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
|
|
|
113
118
|
"6994595e3a62edb6c518006a6bece6848c7077977c041439cf7c822b89304a14",
|
|
114
119
|
"6a42e76fc038ca69ddad18541b8df161770c58980fefaf9e5e80d87407074bec",
|
|
115
120
|
"6a9af9e8a95dbb279347166c43dcee245ca673f9687841086b49911c54944c26",
|
|
121
|
+
"99fdd85310e658a1c1b0e8f92257493409c28c3d693f24deeaa665861788e1e4",
|
|
122
|
+
// public registry SoT n8n-workflows/SKILL.md (em dash description)
|
|
116
123
|
"6b66ed7747ea2d19cb457f5af656e3c07f9f563f7f32b3951fa4ae5f27f0ac46",
|
|
117
124
|
"6dede0588274f5b44d833bcc696ec4776eb978ed24a20efdcc9c38caf3df1576",
|
|
118
125
|
"71991a10972b8b956cae93c88517e31741c95e351814082df65e44f813590210",
|
|
126
|
+
"75ae3018a70ed838428c0e63e8b6901ac05bf1f1cf1845faa6f73c3940d22e4a",
|
|
119
127
|
"75e591bfde61ca1ca3ca1303cc9bc487197af2f713c68f346a46e94ca9432fd5",
|
|
120
128
|
"76ae85bbc336c6f435d9653e8f254ae49774b4ebaecf7335697115933eb8797c",
|
|
129
|
+
"76c4361e70a73276771e841e2c939253b4124d690a0fd25aff2a3ac636d8f4b0",
|
|
130
|
+
// mission-kit-comms/SKILL.md
|
|
121
131
|
"79878f0f6f59d1a0b65d94011c0cafe7b6f8e03e89f568aa638b8ba7a2c34076",
|
|
122
132
|
"8108b202c829627c3c2df33575016ebe942df42acf4f1cc393900be3b82b402c",
|
|
123
133
|
"819b7bd3ba9e8bf12dcd4f81a76c98e48261b34c397f339b36d36eb364d9c3f4",
|
|
@@ -126,6 +136,7 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
|
|
|
126
136
|
"8a11c80b0fbf6c4aabf60eec05b8cca7dccf5bca472787a8afa3028fd8fbedfa",
|
|
127
137
|
"8b25659727063013e8bf6d7925f815b2630c2919b21e6fdac354362bf122bfab",
|
|
128
138
|
"8c7edbacc74b1431fbecb04c9857c0e7a9cb1578fc6ca6367be888dbcec3c98f",
|
|
139
|
+
"8d8d60e929ebf717eed3c1a29ee0de7c71ae917d125eb1b220a77220597281ed",
|
|
129
140
|
"8ffc181bb152c68a3353309bfdc87c42bdb925b98675cdba959c0cdb90b2adea",
|
|
130
141
|
"91ce0c933e3c8ee81927b8224f944ec5ce5445098a2ad154773092e3541dbf69",
|
|
131
142
|
"9309af07a0a99a56143386b3ddd2a35fae29378fba3f6b4c9297a5d1c02a9724",
|
|
@@ -137,6 +148,7 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
|
|
|
137
148
|
"9ccf52fe53c6fa4d731650ab4928ce50e201fa34f3e174fee70e3d29867fef2a",
|
|
138
149
|
"9d905aca0123f3018c81c579217104f1749d8da802f3837b2407fbad8f2d803f",
|
|
139
150
|
"9e324c52c1a9d1ceee738bccf47da92910aca9f7a5a21cc41738d9573c414830",
|
|
151
|
+
"9eb457654167df562481637b25ecd91f0ff3c9282ba79409089d644d3b09b926",
|
|
140
152
|
"a013a6a476160183d6457ff6c1c51ec228bdca359b11eb15cd9b7fc177a705db",
|
|
141
153
|
"a08d04f8efa121ad498f96873778c22630c9172c07c216839e348cd0bb7c2292",
|
|
142
154
|
"a7cd7058bcb6fbd962c37317fa16893bc86a270d0164af5a0e6f3f026aa408ad",
|
|
@@ -145,6 +157,8 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
|
|
|
145
157
|
"b5c7a10df90d209be07159b7ff9bfa24e869538a0b6026bb5ce79e1cdd5b2528",
|
|
146
158
|
"bd9fd1efacbd132c5dafc12cd0cf2b651a2b1fab7b2d7a9ba4a3e44128097f48",
|
|
147
159
|
"be964ff33a40280e13ce6071fb3e30ce87c374527efbb74c25c9d4534084a634",
|
|
160
|
+
"c245035b539e41e822fab8c74fcde3b18c45f4b9f26f1c8583fc9e7254249698",
|
|
161
|
+
"c794accc6668d74a739c982c1b63985a8be4be08afe3766214ab1e08d25ea95c",
|
|
148
162
|
"c96d522be440fbb638dbe953cebf1bb31185c431ac2e14446369cfb7d155a951",
|
|
149
163
|
"cf2bd11891b934484171fa705f470de284e3874402e1e487750735dbc7692857",
|
|
150
164
|
"d0e3bf82efbe32c09761689802ffea7838046dbdd4803b88ead5ec3dfc7efb7e",
|
|
@@ -174,11 +188,13 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
|
|
|
174
188
|
"f061432a2606049717c0cbf098ef07b1da4df2b136c4cb9cdaa7ea44c876bcd6",
|
|
175
189
|
"f061d36a1180293519fbb560bbf659c621bd90885e995fca6eaf2eda9e418a50",
|
|
176
190
|
"f28731a82f4b394a5765fdefe2d1b667810831f6dcea400ca62bc66e1d65371c",
|
|
191
|
+
"f43a5484e39aca4e6af86e7f8d2941773cdc1c960838ad88ae3540c49a1097df",
|
|
177
192
|
"f46c108457e4fe12953dca75b409e06fca9cb264baffabe0c0d04c89af471e56",
|
|
178
193
|
"f6bc17efa746680a44bbc49be67ac3f924d9c306c6d937f9959c57a1d3c5b9af",
|
|
179
194
|
"f981764422d468567b5aff31148dc659aeee22cb13dc0ecd873d737deaf07372",
|
|
180
195
|
"fa306a0cdb0f40c817e32164cd03b946564a02b4b7f7c3f4f0b9513096584d28",
|
|
181
|
-
"fa5cf460eb314437081f7cea30dc8041c0bd6fc3f560a74bc2d7be1bf07384b0"
|
|
196
|
+
"fa5cf460eb314437081f7cea30dc8041c0bd6fc3f560a74bc2d7be1bf07384b0",
|
|
197
|
+
"fc39ec6d8a22498697f968ffc0fe5f717bed97afd68f922c76a80ed1f10d6579"
|
|
182
198
|
]);
|
|
183
199
|
|
|
184
200
|
// src/lifecycle/paths.ts
|
|
@@ -2270,7 +2286,7 @@ var KIT_ROOT_ENV_KEYS = Object.freeze(["MISSION_CONTROL_KIT_ROOT", "AGENT_KIT_HO
|
|
|
2270
2286
|
var CONTEXT_CONFIG_REL = ".cursor/context/config.json";
|
|
2271
2287
|
var CONFIG_PERSONA_IDS = Object.freeze(["autopilot", "night-shift", "ghost-runner"]);
|
|
2272
2288
|
var CONFIG_PERSONA_MODES = Object.freeze(["continue-plan", "run-plan", "cli-run-plan"]);
|
|
2273
|
-
var CONFIG_REVIEW_BACKENDS = Object.freeze(["claude"]);
|
|
2289
|
+
var CONFIG_REVIEW_BACKENDS = Object.freeze(["auto", "claude", "cursor"]);
|
|
2274
2290
|
var CONFIG_REVIEW_MODES = Object.freeze(["paste", "autonomous"]);
|
|
2275
2291
|
var CONFIG_REVIEW_PREFLIGHT = Object.freeze(["off", "warn", "block"]);
|
|
2276
2292
|
function resolveContextConfigPath(repoRoot, fsHooks = {}) {
|
|
@@ -2367,6 +2383,14 @@ function applyDashboardOpenEnv(env, opts) {
|
|
|
2367
2383
|
}
|
|
2368
2384
|
return next;
|
|
2369
2385
|
}
|
|
2386
|
+
function dashboardSpawnEnv(env, snapshotRoot, opts) {
|
|
2387
|
+
const root = path11.resolve(snapshotRoot);
|
|
2388
|
+
return applyDashboardOpenEnv({ ...env, MISSION_CONTROL_REPO_ROOT: root }, { ...opts, cwd: root });
|
|
2389
|
+
}
|
|
2390
|
+
function dashboardProcessTitle(snapshotRoot) {
|
|
2391
|
+
const base = path11.basename(path11.resolve(snapshotRoot)) || "workspace";
|
|
2392
|
+
return `Mission Control \xB7 ${base}`;
|
|
2393
|
+
}
|
|
2370
2394
|
function bundledDashboardCandidates(filename, moduleUrl = import.meta.url) {
|
|
2371
2395
|
const here = path11.dirname(fileURLToPath(moduleUrl));
|
|
2372
2396
|
return [
|
|
@@ -2501,10 +2525,11 @@ var dashboardCommand = defineCommand4({
|
|
|
2501
2525
|
process.exitCode = 1;
|
|
2502
2526
|
return;
|
|
2503
2527
|
}
|
|
2504
|
-
const env =
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
);
|
|
2528
|
+
const env = dashboardSpawnEnv({ ...process.env }, snapshotRoot, {
|
|
2529
|
+
noOpen: Boolean(args["no-open"]),
|
|
2530
|
+
browser: args.browser
|
|
2531
|
+
});
|
|
2532
|
+
process.title = dashboardProcessTitle(snapshotRoot);
|
|
2508
2533
|
const code = await runStartScript(startPath, env);
|
|
2509
2534
|
if (code !== 0) process.exitCode = code;
|
|
2510
2535
|
}
|
|
@@ -2601,10 +2626,11 @@ var dashboardBroadcastCommand = defineCommand5({
|
|
|
2601
2626
|
return;
|
|
2602
2627
|
}
|
|
2603
2628
|
const snapshotRoot = resolveDashboardSnapshotRoot(args.cwd);
|
|
2604
|
-
const env =
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
);
|
|
2629
|
+
const env = dashboardSpawnEnv({ ...process.env }, snapshotRoot, {
|
|
2630
|
+
noOpen: Boolean(args["no-open"]),
|
|
2631
|
+
browser: args.browser
|
|
2632
|
+
});
|
|
2633
|
+
process.title = dashboardProcessTitle(snapshotRoot);
|
|
2608
2634
|
const code = await runStartScript2(startPath, env);
|
|
2609
2635
|
if (code !== 0) process.exitCode = code;
|
|
2610
2636
|
}
|
|
@@ -4115,6 +4141,169 @@ async function writeReadinessSnapshot(rootDir, report) {
|
|
|
4115
4141
|
return snapshotPath;
|
|
4116
4142
|
}
|
|
4117
4143
|
|
|
4144
|
+
// src/welcome/visual-kit.ts
|
|
4145
|
+
import { cyan as cyan2, gray, options as koloristOptions } from "kolorist";
|
|
4146
|
+
var HELMET_OUTLINE = "#e2e8f0";
|
|
4147
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
4148
|
+
var SPACE_MARKS = {
|
|
4149
|
+
star: "\u2726",
|
|
4150
|
+
tick: "\xB7",
|
|
4151
|
+
diamond: "\u2727",
|
|
4152
|
+
visor: "( )"
|
|
4153
|
+
};
|
|
4154
|
+
var KIT_TIPS = [
|
|
4155
|
+
"Try agent-kit doctor for repository readiness.",
|
|
4156
|
+
"HITL gates stay in Cursor slash commands.",
|
|
4157
|
+
"/run-plan never promotes to production.",
|
|
4158
|
+
"Mission Control is the dashboard, not the CLI name.",
|
|
4159
|
+
"NO_COLOR and CI keep this output static.",
|
|
4160
|
+
"agent-kit --help groups SETUP, MISSION, DASHBOARD, INTEGRITY."
|
|
4161
|
+
];
|
|
4162
|
+
function shouldUseWelcomeColor(opts = {}) {
|
|
4163
|
+
if (opts.color === false) return false;
|
|
4164
|
+
if (process.env.NO_COLOR) return false;
|
|
4165
|
+
if (process.env.NODE_DISABLE_COLORS) return false;
|
|
4166
|
+
if (process.env.FORCE_COLOR === "0") return false;
|
|
4167
|
+
if (process.env.CI != null && process.env.CI !== "") return false;
|
|
4168
|
+
if (opts.color === true) return true;
|
|
4169
|
+
const tty = opts.stdoutIsTTY ?? Boolean(process.stdout.isTTY);
|
|
4170
|
+
return tty;
|
|
4171
|
+
}
|
|
4172
|
+
function shouldUseVisualMotion(opts = {}) {
|
|
4173
|
+
if (process.env.AGENT_KIT_REDUCED_MOTION === "1") return false;
|
|
4174
|
+
return shouldUseWelcomeColor(opts);
|
|
4175
|
+
}
|
|
4176
|
+
function spinnerFrame(index) {
|
|
4177
|
+
const n = SPINNER_FRAMES.length;
|
|
4178
|
+
return SPINNER_FRAMES[(index % n + n) % n] ?? SPINNER_FRAMES[0];
|
|
4179
|
+
}
|
|
4180
|
+
function tipAt(index) {
|
|
4181
|
+
const n = KIT_TIPS.length;
|
|
4182
|
+
return KIT_TIPS[(index % n + n) % n] ?? KIT_TIPS[0];
|
|
4183
|
+
}
|
|
4184
|
+
function wrapNarrow(text, columns) {
|
|
4185
|
+
const width = Math.max(8, Number.isFinite(columns) ? Math.floor(columns) : 80);
|
|
4186
|
+
const words = text.trim().split(/\s+/).filter(Boolean);
|
|
4187
|
+
if (words.length === 0) return "";
|
|
4188
|
+
const lines = [];
|
|
4189
|
+
let current = "";
|
|
4190
|
+
for (const word of words) {
|
|
4191
|
+
if (word.length > width) {
|
|
4192
|
+
if (current) {
|
|
4193
|
+
lines.push(current);
|
|
4194
|
+
current = "";
|
|
4195
|
+
}
|
|
4196
|
+
for (let i = 0; i < word.length; i += width) {
|
|
4197
|
+
const chunk = word.slice(i, i + width);
|
|
4198
|
+
if (i + width >= word.length) current = chunk;
|
|
4199
|
+
else lines.push(chunk);
|
|
4200
|
+
}
|
|
4201
|
+
continue;
|
|
4202
|
+
}
|
|
4203
|
+
const next = current ? `${current} ${word}` : word;
|
|
4204
|
+
if (next.length > width) {
|
|
4205
|
+
lines.push(current);
|
|
4206
|
+
current = word;
|
|
4207
|
+
} else {
|
|
4208
|
+
current = next;
|
|
4209
|
+
}
|
|
4210
|
+
}
|
|
4211
|
+
if (current) lines.push(current);
|
|
4212
|
+
return lines.join("\n");
|
|
4213
|
+
}
|
|
4214
|
+
function renderProgressLine(opts) {
|
|
4215
|
+
const motion = opts.motion ?? shouldUseVisualMotion();
|
|
4216
|
+
const color = opts.color ?? shouldUseWelcomeColor();
|
|
4217
|
+
const mark = motion ? spinnerFrame(opts.frameIndex) : SPACE_MARKS.tick;
|
|
4218
|
+
const tip = tipAt(opts.tipIndex);
|
|
4219
|
+
const label = opts.label?.trim() ?? "";
|
|
4220
|
+
const raw = label ? `${mark} ${label} ${SPACE_MARKS.star} ${tip}` : `${mark} ${tip}`;
|
|
4221
|
+
const cols = opts.columns ?? process.stdout.columns ?? 80;
|
|
4222
|
+
const wrapped = wrapNarrow(raw, cols);
|
|
4223
|
+
if (!color) return wrapped;
|
|
4224
|
+
const prevEnabled = koloristOptions.enabled;
|
|
4225
|
+
koloristOptions.enabled = true;
|
|
4226
|
+
try {
|
|
4227
|
+
return wrapped.split("\n").map((line, i) => i === 0 ? cyan2(line) : gray(line)).join("\n");
|
|
4228
|
+
} finally {
|
|
4229
|
+
koloristOptions.enabled = prevEnabled;
|
|
4230
|
+
}
|
|
4231
|
+
}
|
|
4232
|
+
var TtySpinner = class {
|
|
4233
|
+
timer = null;
|
|
4234
|
+
frame = 0;
|
|
4235
|
+
startedAt = 0;
|
|
4236
|
+
label = "";
|
|
4237
|
+
write;
|
|
4238
|
+
columns;
|
|
4239
|
+
motion;
|
|
4240
|
+
color;
|
|
4241
|
+
intervalMs;
|
|
4242
|
+
now;
|
|
4243
|
+
constructor(opts = {}) {
|
|
4244
|
+
this.write = opts.write ?? ((chunk) => process.stdout.write(chunk));
|
|
4245
|
+
this.columns = opts.columns ?? (() => process.stdout.columns ?? 80);
|
|
4246
|
+
this.motion = opts.motion ?? shouldUseVisualMotion();
|
|
4247
|
+
this.color = opts.color ?? shouldUseWelcomeColor();
|
|
4248
|
+
this.intervalMs = opts.intervalMs ?? 80;
|
|
4249
|
+
this.now = opts.now ?? (() => Date.now());
|
|
4250
|
+
}
|
|
4251
|
+
start(label = "") {
|
|
4252
|
+
this.stop();
|
|
4253
|
+
this.label = label;
|
|
4254
|
+
this.frame = 0;
|
|
4255
|
+
this.startedAt = this.now();
|
|
4256
|
+
this.paint(false);
|
|
4257
|
+
if (!this.motion) return;
|
|
4258
|
+
this.timer = setInterval(() => {
|
|
4259
|
+
this.frame += 1;
|
|
4260
|
+
this.paint(true);
|
|
4261
|
+
}, this.intervalMs);
|
|
4262
|
+
this.timer.unref?.();
|
|
4263
|
+
}
|
|
4264
|
+
stop(finalLine) {
|
|
4265
|
+
if (this.timer) {
|
|
4266
|
+
clearInterval(this.timer);
|
|
4267
|
+
this.timer = null;
|
|
4268
|
+
}
|
|
4269
|
+
if (this.motion) this.write("\r\x1B[K");
|
|
4270
|
+
if (finalLine) this.write(`${finalLine}
|
|
4271
|
+
`);
|
|
4272
|
+
}
|
|
4273
|
+
paint(overwrite) {
|
|
4274
|
+
const elapsed = this.now() - this.startedAt;
|
|
4275
|
+
const tipIndex = Math.floor(elapsed / 4e3);
|
|
4276
|
+
const line = renderProgressLine({
|
|
4277
|
+
frameIndex: this.frame,
|
|
4278
|
+
tipIndex,
|
|
4279
|
+
columns: this.columns(),
|
|
4280
|
+
label: this.label,
|
|
4281
|
+
motion: this.motion,
|
|
4282
|
+
color: this.color
|
|
4283
|
+
}).split("\n")[0] ?? "";
|
|
4284
|
+
if (overwrite && this.motion) this.write(`\r\x1B[K${line}`);
|
|
4285
|
+
else if (this.motion) this.write(line);
|
|
4286
|
+
else this.write(`${line}
|
|
4287
|
+
`);
|
|
4288
|
+
}
|
|
4289
|
+
};
|
|
4290
|
+
async function withCliProgress(label, fn, opts) {
|
|
4291
|
+
const motion = opts?.motion ?? shouldUseVisualMotion();
|
|
4292
|
+
if (!motion) {
|
|
4293
|
+
return fn();
|
|
4294
|
+
}
|
|
4295
|
+
const spinner = new TtySpinner({ ...opts, motion: true });
|
|
4296
|
+
spinner.start(label);
|
|
4297
|
+
try {
|
|
4298
|
+
const result = await fn();
|
|
4299
|
+
spinner.stop();
|
|
4300
|
+
return result;
|
|
4301
|
+
} catch (err) {
|
|
4302
|
+
spinner.stop();
|
|
4303
|
+
throw err;
|
|
4304
|
+
}
|
|
4305
|
+
}
|
|
4306
|
+
|
|
4118
4307
|
// src/commands/doctor.ts
|
|
4119
4308
|
async function runDoctor(cwd, options = {}) {
|
|
4120
4309
|
const rootDir = path24.resolve(cwd);
|
|
@@ -4188,7 +4377,8 @@ var doctorCommand = defineCommand7({
|
|
|
4188
4377
|
}
|
|
4189
4378
|
},
|
|
4190
4379
|
async run({ args }) {
|
|
4191
|
-
const
|
|
4380
|
+
const run = () => runDoctor(args.cwd, { fixSafe: args["fix-safe"] });
|
|
4381
|
+
const result = args.json ? await run() : await withCliProgress("doctor", run);
|
|
4192
4382
|
if (args.json) {
|
|
4193
4383
|
console.log(JSON.stringify(result, null, 2));
|
|
4194
4384
|
return;
|
|
@@ -5340,16 +5530,83 @@ function classifyInstallError(err) {
|
|
|
5340
5530
|
}
|
|
5341
5531
|
|
|
5342
5532
|
// src/commands/install.ts
|
|
5343
|
-
import
|
|
5533
|
+
import path33 from "path";
|
|
5344
5534
|
import { defineCommand as defineCommand11 } from "citty";
|
|
5345
5535
|
|
|
5346
5536
|
// src/generator/personalization.ts
|
|
5347
|
-
import { readFile as readFile15, writeFile as
|
|
5348
|
-
import
|
|
5537
|
+
import { readFile as readFile15, writeFile as writeFile9 } from "fs/promises";
|
|
5538
|
+
import path31 from "path";
|
|
5349
5539
|
|
|
5350
|
-
// src/generator/
|
|
5540
|
+
// src/generator/claude-kit-load.ts
|
|
5351
5541
|
import { writeFile as writeFile7 } from "fs/promises";
|
|
5352
5542
|
import path29 from "path";
|
|
5543
|
+
var CLAUDE_MD_REL = "CLAUDE.md";
|
|
5544
|
+
var AGENT_KIT_COMMAND_REL = ".claude/commands/agent-kit.md";
|
|
5545
|
+
function renderClaudeMd() {
|
|
5546
|
+
return `# Agent Kit (Claude Code)
|
|
5547
|
+
|
|
5548
|
+
This repository uses Agent Kit / Mission Control. Before rediscovering the tree, read the shared sources of truth (paths below are pointers; do not treat this file as a second rulebook).
|
|
5549
|
+
|
|
5550
|
+
## Read first
|
|
5551
|
+
|
|
5552
|
+
1. \`AGENTS.md\` - cross-IDE contract
|
|
5553
|
+
2. \`.cursor/project-context.md\` - verified repository facts (derived; prefer code, tests, SHAs when docs conflict)
|
|
5554
|
+
3. \`.cursor/HANDOFF.md\` - if present: active plan, next to-do, queue fields
|
|
5555
|
+
4. \`.cursor/commands/\` - slash catalog (Cursor). Follow the same HITL contracts here.
|
|
5556
|
+
|
|
5557
|
+
Mid-session refresh: \`/agent-kit\`.
|
|
5558
|
+
|
|
5559
|
+
## HITL
|
|
5560
|
+
|
|
5561
|
+
Cursor Ask questions is not available in this CLI. When a command requires a choice, list the same labels as a numbered list and wait. Skip or cancel means stop. Never \`/git-prod\` without an explicit operator yes.
|
|
5562
|
+
|
|
5563
|
+
## Non-goals
|
|
5564
|
+
|
|
5565
|
+
- Not Action A7 (Windsurf / VS Code generator parity)
|
|
5566
|
+
- Not Claude external plan-review audits (\`/plan-external-review\`)
|
|
5567
|
+
- Not \`--backend claude\` plan-loop ticks
|
|
5568
|
+
- Not a copy of Cursor \`sessionStart\` / other IDE hooks
|
|
5569
|
+
`;
|
|
5570
|
+
}
|
|
5571
|
+
function renderAgentKitCommand() {
|
|
5572
|
+
return `---
|
|
5573
|
+
description: Load Agent Kit session context (HANDOFF, project-context, commands). Manual refresh only.
|
|
5574
|
+
disable-model-invocation: true
|
|
5575
|
+
---
|
|
5576
|
+
|
|
5577
|
+
Read these files if they exist, then summarize the active plan, next to-do, and any Gaps. Do not scan the whole repository first.
|
|
5578
|
+
|
|
5579
|
+
1. \`AGENTS.md\`
|
|
5580
|
+
2. \`.cursor/project-context.md\`
|
|
5581
|
+
3. \`.cursor/HANDOFF.md\`
|
|
5582
|
+
4. The plan file named in HANDOFF \`- **Plan:**\` under \`.cursor/plans/\`
|
|
5583
|
+
|
|
5584
|
+
If HANDOFF is missing, say so and point at \`/agent-kit-onboard\` or \`/start-project\` rather than inventing a plan.
|
|
5585
|
+
|
|
5586
|
+
HITL: numbered-list fallback for Ask questions labels. Never \`/git-prod\` from this skill.
|
|
5587
|
+
|
|
5588
|
+
Non-goals: not audits / \`/plan-external-review\`, not \`--backend claude\` ticks, not A7, not Cursor hook clones.
|
|
5589
|
+
`;
|
|
5590
|
+
}
|
|
5591
|
+
async function writeUnlessExists(rootDir, relativePath, content) {
|
|
5592
|
+
const target = path29.join(rootDir, relativePath);
|
|
5593
|
+
if (await fileExists(target)) {
|
|
5594
|
+
return { relativePath, status: "skipped-customized" };
|
|
5595
|
+
}
|
|
5596
|
+
await ensureDir(path29.dirname(target));
|
|
5597
|
+
await writeFile7(target, content, "utf8");
|
|
5598
|
+
return { relativePath, status: "applied" };
|
|
5599
|
+
}
|
|
5600
|
+
async function generateClaudeKitLoadArtifacts(rootDir) {
|
|
5601
|
+
return Promise.all([
|
|
5602
|
+
writeUnlessExists(rootDir, CLAUDE_MD_REL, renderClaudeMd()),
|
|
5603
|
+
writeUnlessExists(rootDir, AGENT_KIT_COMMAND_REL, renderAgentKitCommand())
|
|
5604
|
+
]);
|
|
5605
|
+
}
|
|
5606
|
+
|
|
5607
|
+
// src/generator/vscode.ts
|
|
5608
|
+
import { writeFile as writeFile8 } from "fs/promises";
|
|
5609
|
+
import path30 from "path";
|
|
5353
5610
|
|
|
5354
5611
|
// src/generator/platform.ts
|
|
5355
5612
|
function gitProviderLabel(profile) {
|
|
@@ -5373,14 +5630,14 @@ function prTerminology(profile) {
|
|
|
5373
5630
|
// src/generator/vscode.ts
|
|
5374
5631
|
async function generateVSCodeArtifacts(profile) {
|
|
5375
5632
|
const results = [];
|
|
5376
|
-
const vscodeDir =
|
|
5377
|
-
const githubDir =
|
|
5633
|
+
const vscodeDir = path30.join(profile.rootDir, ".vscode");
|
|
5634
|
+
const githubDir = path30.join(profile.rootDir, ".github");
|
|
5378
5635
|
await Promise.all([ensureDir(vscodeDir), ensureDir(githubDir)]);
|
|
5379
|
-
const settingsPath =
|
|
5636
|
+
const settingsPath = path30.join(vscodeDir, "settings.json");
|
|
5380
5637
|
if (await fileExists(settingsPath)) {
|
|
5381
5638
|
results.push({ relativePath: ".vscode/settings.json", status: "skipped-customized" });
|
|
5382
5639
|
} else {
|
|
5383
|
-
await
|
|
5640
|
+
await writeFile8(
|
|
5384
5641
|
settingsPath,
|
|
5385
5642
|
`${JSON.stringify(
|
|
5386
5643
|
{
|
|
@@ -5400,11 +5657,11 @@ async function generateVSCodeArtifacts(profile) {
|
|
|
5400
5657
|
}
|
|
5401
5658
|
const provider = gitProviderLabel(profile);
|
|
5402
5659
|
const prTerm = prTerminology(profile);
|
|
5403
|
-
const copilotPath =
|
|
5660
|
+
const copilotPath = path30.join(githubDir, "copilot-instructions.md");
|
|
5404
5661
|
if (await fileExists(copilotPath)) {
|
|
5405
5662
|
results.push({ relativePath: ".github/copilot-instructions.md", status: "skipped-customized" });
|
|
5406
5663
|
} else {
|
|
5407
|
-
await
|
|
5664
|
+
await writeFile8(
|
|
5408
5665
|
copilotPath,
|
|
5409
5666
|
`# Copilot Instructions
|
|
5410
5667
|
|
|
@@ -5418,14 +5675,14 @@ async function generateVSCodeArtifacts(profile) {
|
|
|
5418
5675
|
results.push({ relativePath: ".github/copilot-instructions.md", status: "applied" });
|
|
5419
5676
|
}
|
|
5420
5677
|
if (profile.ide.plan === "vscode-pro") {
|
|
5421
|
-
const securityPath =
|
|
5678
|
+
const securityPath = path30.join(vscodeDir, "security-review.agent.md");
|
|
5422
5679
|
if (await fileExists(securityPath)) {
|
|
5423
5680
|
results.push({
|
|
5424
5681
|
relativePath: ".vscode/security-review.agent.md",
|
|
5425
5682
|
status: "skipped-customized"
|
|
5426
5683
|
});
|
|
5427
5684
|
} else {
|
|
5428
|
-
await
|
|
5685
|
+
await writeFile8(
|
|
5429
5686
|
securityPath,
|
|
5430
5687
|
"# Security Review Agent\n\nSpecialized mode for security review.\n",
|
|
5431
5688
|
"utf8"
|
|
@@ -5597,7 +5854,7 @@ function renderProjectContext(profile) {
|
|
|
5597
5854
|
`;
|
|
5598
5855
|
}
|
|
5599
5856
|
async function createOwnedFile(rootDir, relativePath, content, evidence) {
|
|
5600
|
-
const target =
|
|
5857
|
+
const target = path31.join(rootDir, relativePath);
|
|
5601
5858
|
if (await fileExists(target)) {
|
|
5602
5859
|
return {
|
|
5603
5860
|
kind: "file",
|
|
@@ -5607,8 +5864,8 @@ async function createOwnedFile(rootDir, relativePath, content, evidence) {
|
|
|
5607
5864
|
evidence
|
|
5608
5865
|
};
|
|
5609
5866
|
}
|
|
5610
|
-
await ensureDir(
|
|
5611
|
-
await
|
|
5867
|
+
await ensureDir(path31.dirname(target));
|
|
5868
|
+
await writeFile9(target, content, "utf8");
|
|
5612
5869
|
return {
|
|
5613
5870
|
kind: "file",
|
|
5614
5871
|
id: relativePath,
|
|
@@ -5624,7 +5881,7 @@ async function packTargets(registryRoot, packId) {
|
|
|
5624
5881
|
async function existingTargets(projectRoot, targets) {
|
|
5625
5882
|
const checks = await Promise.all(
|
|
5626
5883
|
targets.map(
|
|
5627
|
-
async (target) => await fileExists(
|
|
5884
|
+
async (target) => await fileExists(path31.join(projectRoot, target)) ? target : null
|
|
5628
5885
|
)
|
|
5629
5886
|
);
|
|
5630
5887
|
return checks.filter((target) => target !== null);
|
|
@@ -5646,14 +5903,14 @@ async function applyPersonalization(input) {
|
|
|
5646
5903
|
componentResults.push({ ...item, status: "unavailable" });
|
|
5647
5904
|
continue;
|
|
5648
5905
|
}
|
|
5649
|
-
const target =
|
|
5906
|
+
const target = path31.posix.join(
|
|
5650
5907
|
".cursor",
|
|
5651
5908
|
"skills",
|
|
5652
5909
|
skill.path.includes("/core/") ? "core" : "community",
|
|
5653
5910
|
skill.id,
|
|
5654
5911
|
"SKILL.md"
|
|
5655
5912
|
);
|
|
5656
|
-
if (await fileExists(
|
|
5913
|
+
if (await fileExists(path31.join(input.rootDir, target))) {
|
|
5657
5914
|
componentResults.push({ ...item, status: "skipped-customized", path: target });
|
|
5658
5915
|
protectedPaths.add(target);
|
|
5659
5916
|
continue;
|
|
@@ -5701,6 +5958,17 @@ async function applyPersonalization(input) {
|
|
|
5701
5958
|
]);
|
|
5702
5959
|
protectedPaths.add(CONTEXT_PATH);
|
|
5703
5960
|
protectedPaths.add(AGENTS_PATH);
|
|
5961
|
+
const claudeResults = await generateClaudeKitLoadArtifacts(input.rootDir);
|
|
5962
|
+
const claudeItems = claudeResults.map((artifact) => {
|
|
5963
|
+
protectedPaths.add(artifact.relativePath);
|
|
5964
|
+
return {
|
|
5965
|
+
kind: "file",
|
|
5966
|
+
id: artifact.relativePath,
|
|
5967
|
+
path: artifact.relativePath,
|
|
5968
|
+
status: artifact.status,
|
|
5969
|
+
evidence: profileEvidence
|
|
5970
|
+
};
|
|
5971
|
+
});
|
|
5704
5972
|
const ideDetection = await detectIde(input.rootDir);
|
|
5705
5973
|
if (ideDetection.ide === "vscode" || ideDetection.ide === "other") {
|
|
5706
5974
|
const git = {
|
|
@@ -5748,10 +6016,10 @@ async function applyPersonalization(input) {
|
|
|
5748
6016
|
contractVersion: PERSONALIZATION_CONTRACT_VERSION,
|
|
5749
6017
|
generatorVersion: input.generatorVersion,
|
|
5750
6018
|
repositoryFingerprint: input.report.repositoryFingerprint,
|
|
5751
|
-
items: [...fileResults, ...componentResults],
|
|
6019
|
+
items: [...fileResults, ...claudeItems, ...componentResults],
|
|
5752
6020
|
protectedPaths: [...protectedPaths].sort()
|
|
5753
6021
|
};
|
|
5754
|
-
await writeJson(
|
|
6022
|
+
await writeJson(path31.join(input.rootDir, RESULT_PATH), result);
|
|
5755
6023
|
return {
|
|
5756
6024
|
result,
|
|
5757
6025
|
manifest: {
|
|
@@ -5769,7 +6037,7 @@ async function applyPersonalization(input) {
|
|
|
5769
6037
|
};
|
|
5770
6038
|
}
|
|
5771
6039
|
async function readRepositoryProfile(rootDir) {
|
|
5772
|
-
const target =
|
|
6040
|
+
const target = path31.join(rootDir, ".cursor/agent-kit.config.json");
|
|
5773
6041
|
if (!await fileExists(target)) return null;
|
|
5774
6042
|
return JSON.parse(await readFile15(target, "utf8"));
|
|
5775
6043
|
}
|
|
@@ -5777,16 +6045,16 @@ async function readRepositoryProfile(rootDir) {
|
|
|
5777
6045
|
// src/lifecycle/onboard-migration.ts
|
|
5778
6046
|
import { createHash as createHash4 } from "crypto";
|
|
5779
6047
|
import { readFile as readFile16, unlink } from "fs/promises";
|
|
5780
|
-
import
|
|
6048
|
+
import path32 from "path";
|
|
5781
6049
|
var LEGACY_ONBOARD_PATH = ".cursor/commands/onboard.md";
|
|
5782
6050
|
var NAMESPACED_ONBOARD_PATH = ".cursor/commands/agent-kit-onboard.md";
|
|
5783
6051
|
var MANAGED_LEGACY_HASHES = /* @__PURE__ */ new Set([
|
|
5784
6052
|
"b274a68941813f19b185893cb7c5561dff027f53270890029992f208e24992fe"
|
|
5785
6053
|
]);
|
|
5786
6054
|
async function migrateLegacyOnboardCommand(projectRoot, managedHashes = MANAGED_LEGACY_HASHES) {
|
|
5787
|
-
const legacyPath =
|
|
6055
|
+
const legacyPath = path32.join(projectRoot, LEGACY_ONBOARD_PATH);
|
|
5788
6056
|
if (!await fileExists(legacyPath)) return "absent";
|
|
5789
|
-
const namespacedPath =
|
|
6057
|
+
const namespacedPath = path32.join(projectRoot, NAMESPACED_ONBOARD_PATH);
|
|
5790
6058
|
if (!await fileExists(namespacedPath)) return "preserved-customized";
|
|
5791
6059
|
const content = await readFile16(legacyPath);
|
|
5792
6060
|
const hash = createHash4("sha256").update(content).digest("hex");
|
|
@@ -5861,7 +6129,7 @@ function printReadinessNarrative(result) {
|
|
|
5861
6129
|
);
|
|
5862
6130
|
}
|
|
5863
6131
|
async function performInstall(options) {
|
|
5864
|
-
const projectRoot =
|
|
6132
|
+
const projectRoot = path33.resolve(options.cwd);
|
|
5865
6133
|
const packs = parsePackList(options.pack);
|
|
5866
6134
|
const existing = await loadAgentKitManifest(projectRoot);
|
|
5867
6135
|
const registry = await resolveRegistryFromCli({
|
|
@@ -5979,15 +6247,18 @@ var installCommand = defineCommand11({
|
|
|
5979
6247
|
}
|
|
5980
6248
|
}
|
|
5981
6249
|
try {
|
|
5982
|
-
const result = await
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
6250
|
+
const result = await withCliProgress(
|
|
6251
|
+
"install",
|
|
6252
|
+
() => performInstall({
|
|
6253
|
+
cwd: projectRoot,
|
|
6254
|
+
profile: args.profile,
|
|
6255
|
+
pack: args.pack,
|
|
6256
|
+
registry: args.registry,
|
|
6257
|
+
url: args.url,
|
|
6258
|
+
ref: args.ref,
|
|
6259
|
+
refresh: args.refresh
|
|
6260
|
+
})
|
|
6261
|
+
);
|
|
5991
6262
|
logApplyStats(result.stats);
|
|
5992
6263
|
logger.success(`Manifest written: ${result.manifestPath}`);
|
|
5993
6264
|
logger.success("Readiness snapshot written: .cursor/context/readiness.json");
|
|
@@ -6028,7 +6299,7 @@ var initCommand = defineCommand12({
|
|
|
6028
6299
|
}
|
|
6029
6300
|
logger.info("init now uses the canonical install and readiness workflow.");
|
|
6030
6301
|
try {
|
|
6031
|
-
const result = await runInitCompatibility(args.cwd);
|
|
6302
|
+
const result = await withCliProgress("init", () => runInitCompatibility(args.cwd));
|
|
6032
6303
|
const pending = result.readiness.pendingActions.length;
|
|
6033
6304
|
logger.success(`L0 and readiness prepared in ${result.projectRoot}`);
|
|
6034
6305
|
const nextStep = pending > 0 ? "Next: run /agent-kit-onboard in Cursor to resolve the first pending action." : "Next: run /start-project in Cursor when you have a deliverable.";
|
|
@@ -6049,13 +6320,13 @@ ${hint.recovery}
|
|
|
6049
6320
|
});
|
|
6050
6321
|
|
|
6051
6322
|
// src/commands/monitors.ts
|
|
6052
|
-
import
|
|
6323
|
+
import path35 from "path";
|
|
6053
6324
|
import { defineCommand as defineCommand13 } from "citty";
|
|
6054
6325
|
|
|
6055
6326
|
// src/invariants/monitors-untriaged.ts
|
|
6056
6327
|
import { execFile as execFile5 } from "child_process";
|
|
6057
6328
|
import { readFile as readFile17, readdir as readdir5, stat as stat3 } from "fs/promises";
|
|
6058
|
-
import
|
|
6329
|
+
import path34 from "path";
|
|
6059
6330
|
import { promisify as promisify5 } from "util";
|
|
6060
6331
|
|
|
6061
6332
|
// src/invariants/triage-heading.ts
|
|
@@ -6096,7 +6367,7 @@ async function gitFreshMonitorNames(rootDir) {
|
|
|
6096
6367
|
for (const line of stdout.split("\n")) {
|
|
6097
6368
|
if (!line.trim()) continue;
|
|
6098
6369
|
const file = line.slice(3).trim().replace(/^.* -> /, "");
|
|
6099
|
-
const base =
|
|
6370
|
+
const base = path34.basename(file);
|
|
6100
6371
|
if (base.startsWith("plan-monitor-") && base.endsWith(".md")) {
|
|
6101
6372
|
names.add(base);
|
|
6102
6373
|
}
|
|
@@ -6119,13 +6390,13 @@ function monitorSlugFromName(fileName) {
|
|
|
6119
6390
|
return fileName.replace(/^plan-monitor-/, "").replace(/\.md$/, "").toLowerCase();
|
|
6120
6391
|
}
|
|
6121
6392
|
async function selectUntriagedMonitors(rootDir) {
|
|
6122
|
-
const root =
|
|
6123
|
-
const memoryDir =
|
|
6393
|
+
const root = path34.resolve(rootDir);
|
|
6394
|
+
const memoryDir = path34.join(root, ".cursor", "memory");
|
|
6124
6395
|
const allNames = await listMonitorFiles(memoryDir);
|
|
6125
6396
|
const selectionOrder = ["git-fresh", "handoff-aligned", "untriaged-scan"];
|
|
6126
6397
|
const byName = /* @__PURE__ */ new Map();
|
|
6127
6398
|
for (const name of allNames) {
|
|
6128
|
-
const abs =
|
|
6399
|
+
const abs = path34.join(memoryDir, name);
|
|
6129
6400
|
try {
|
|
6130
6401
|
const [content, st] = await Promise.all([readFile17(abs, "utf8"), stat3(abs)]);
|
|
6131
6402
|
byName.set(name, { content, mtimeMs: st.mtimeMs });
|
|
@@ -6140,7 +6411,7 @@ async function selectUntriagedMonitors(rootDir) {
|
|
|
6140
6411
|
const gitFreshSet = [...gitFresh].filter(untriaged).sort();
|
|
6141
6412
|
let handoff = "";
|
|
6142
6413
|
try {
|
|
6143
|
-
handoff = await readFile17(
|
|
6414
|
+
handoff = await readFile17(path34.join(root, ".cursor", "HANDOFF.md"), "utf8");
|
|
6144
6415
|
} catch {
|
|
6145
6416
|
handoff = "";
|
|
6146
6417
|
}
|
|
@@ -6160,8 +6431,8 @@ async function selectUntriagedMonitors(rootDir) {
|
|
|
6160
6431
|
const row = byName.get(name);
|
|
6161
6432
|
if (!row) continue;
|
|
6162
6433
|
entries.push({
|
|
6163
|
-
path:
|
|
6164
|
-
relativePath:
|
|
6434
|
+
path: path34.join(memoryDir, name),
|
|
6435
|
+
relativePath: path34.relative(root, path34.join(memoryDir, name)).split(path34.sep).join("/"),
|
|
6165
6436
|
mtimeMs: row.mtimeMs,
|
|
6166
6437
|
hasTriageHeading: false,
|
|
6167
6438
|
hasOpenGaps: hasOpenGaps(row.content),
|
|
@@ -6207,7 +6478,7 @@ var monitorsCommand = defineCommand13({
|
|
|
6207
6478
|
process.exitCode = 2;
|
|
6208
6479
|
return;
|
|
6209
6480
|
}
|
|
6210
|
-
const result = await selectUntriagedMonitors(
|
|
6481
|
+
const result = await selectUntriagedMonitors(path35.resolve(args.cwd));
|
|
6211
6482
|
if (args.json) {
|
|
6212
6483
|
console.log(JSON.stringify(result, null, 2));
|
|
6213
6484
|
return;
|
|
@@ -6223,7 +6494,7 @@ var monitorsCommand = defineCommand13({
|
|
|
6223
6494
|
});
|
|
6224
6495
|
|
|
6225
6496
|
// src/commands/run-plan.ts
|
|
6226
|
-
import
|
|
6497
|
+
import path40 from "path";
|
|
6227
6498
|
import { defineCommand as defineCommand14 } from "citty";
|
|
6228
6499
|
|
|
6229
6500
|
// src/plan-loop/backends.ts
|
|
@@ -6309,13 +6580,13 @@ function listBackendIds() {
|
|
|
6309
6580
|
|
|
6310
6581
|
// src/plan-loop/run-loop.ts
|
|
6311
6582
|
import { mkdir as mkdir6, readFile as readFile20, rm as rm2, unlink as unlink2 } from "fs/promises";
|
|
6312
|
-
import
|
|
6583
|
+
import path39 from "path";
|
|
6313
6584
|
|
|
6314
6585
|
// src/plan-loop/external-review.ts
|
|
6315
6586
|
import { spawn as spawn7 } from "child_process";
|
|
6316
|
-
import
|
|
6317
|
-
var CANONICAL_REL =
|
|
6318
|
-
var FALLBACK_REL =
|
|
6587
|
+
import path36 from "path";
|
|
6588
|
+
var CANONICAL_REL = path36.join(".cursor", "scripts", "plan-external-review.sh");
|
|
6589
|
+
var FALLBACK_REL = path36.join("scripts", "plan-external-review.sh");
|
|
6319
6590
|
function isPlanExhaustedReason(reason) {
|
|
6320
6591
|
const r = reason.trim().toLowerCase();
|
|
6321
6592
|
if (!r) return false;
|
|
@@ -6337,8 +6608,8 @@ async function armExternalPlanReview(root, options = {}) {
|
|
|
6337
6608
|
const existsFn = options.existsFn ?? fileExists;
|
|
6338
6609
|
const log = options.log ?? ((line) => console.log(line));
|
|
6339
6610
|
const force = options.force === true;
|
|
6340
|
-
const canonicalPath =
|
|
6341
|
-
const fallbackPath =
|
|
6611
|
+
const canonicalPath = path36.join(root, CANONICAL_REL);
|
|
6612
|
+
const fallbackPath = path36.join(root, FALLBACK_REL);
|
|
6342
6613
|
let scriptPath = null;
|
|
6343
6614
|
let scriptRel = CANONICAL_REL;
|
|
6344
6615
|
if (await existsFn(canonicalPath)) {
|
|
@@ -6391,11 +6662,11 @@ async function armExternalPlanReview(root, options = {}) {
|
|
|
6391
6662
|
}
|
|
6392
6663
|
|
|
6393
6664
|
// src/plan-loop/persona-banners.ts
|
|
6394
|
-
import
|
|
6665
|
+
import path37 from "path";
|
|
6395
6666
|
import {
|
|
6396
6667
|
blue,
|
|
6397
|
-
cyan as
|
|
6398
|
-
gray,
|
|
6668
|
+
cyan as cyan3,
|
|
6669
|
+
gray as gray2,
|
|
6399
6670
|
green as green2,
|
|
6400
6671
|
lightGray,
|
|
6401
6672
|
lightGreen,
|
|
@@ -6408,9 +6679,9 @@ var CLI_RUN_PLAN_MODE = "cli-run-plan";
|
|
|
6408
6679
|
var DEFAULT_CLI_PERSONA_ID = "ghost-runner";
|
|
6409
6680
|
var COLORS = {
|
|
6410
6681
|
white,
|
|
6411
|
-
gray,
|
|
6682
|
+
gray: gray2,
|
|
6412
6683
|
green: green2,
|
|
6413
|
-
cyan:
|
|
6684
|
+
cyan: cyan3,
|
|
6414
6685
|
magenta,
|
|
6415
6686
|
yellow: yellow2,
|
|
6416
6687
|
red: red2,
|
|
@@ -6427,7 +6698,7 @@ function resolveColor(name, fallback) {
|
|
|
6427
6698
|
async function resolveCliPersonaId(root) {
|
|
6428
6699
|
try {
|
|
6429
6700
|
const cfg = await readJson(
|
|
6430
|
-
|
|
6701
|
+
path37.join(root, ".cursor", "context", "config.json")
|
|
6431
6702
|
);
|
|
6432
6703
|
const modes = cfg?.agentPersona?.modes ?? cfg?.workspaceSkin?.modes;
|
|
6433
6704
|
const id = modes?.[CLI_RUN_PLAN_MODE];
|
|
@@ -6438,7 +6709,7 @@ async function resolveCliPersonaId(root) {
|
|
|
6438
6709
|
}
|
|
6439
6710
|
async function loadPersonaPack(root, personaId) {
|
|
6440
6711
|
try {
|
|
6441
|
-
const personaPath =
|
|
6712
|
+
const personaPath = path37.join(root, "registry", "personas", "core", personaId, "persona.json");
|
|
6442
6713
|
const pack = await readJson(personaPath);
|
|
6443
6714
|
if (!pack || typeof pack.id !== "string") return null;
|
|
6444
6715
|
return pack;
|
|
@@ -6455,7 +6726,7 @@ function createPersonaBannerPrinter(persona) {
|
|
|
6455
6726
|
const banners = persona.cliBanners;
|
|
6456
6727
|
if (!banners.tickStart && !banners.tickEnd && !banners.phaseComplete) return null;
|
|
6457
6728
|
const primary = resolveColor(persona.ansiPalette?.primary, white);
|
|
6458
|
-
const secondary = resolveColor(persona.ansiPalette?.secondary,
|
|
6729
|
+
const secondary = resolveColor(persona.ansiPalette?.secondary, gray2);
|
|
6459
6730
|
const accent = resolveColor(persona.ansiPalette?.accent, green2);
|
|
6460
6731
|
return {
|
|
6461
6732
|
tickStart(detail) {
|
|
@@ -6488,7 +6759,7 @@ function createPersonaBannerPrinter(persona) {
|
|
|
6488
6759
|
|
|
6489
6760
|
// src/plan-loop/plan-state.ts
|
|
6490
6761
|
import { readFile as readFile18, readdir as readdir6 } from "fs/promises";
|
|
6491
|
-
import
|
|
6762
|
+
import path38 from "path";
|
|
6492
6763
|
function countPendingTodos(raw) {
|
|
6493
6764
|
const lines = raw.split(/\r?\n/);
|
|
6494
6765
|
let inFront = 0;
|
|
@@ -6516,7 +6787,7 @@ function countPendingTodos(raw) {
|
|
|
6516
6787
|
async function findActivePlanFile(plansDir) {
|
|
6517
6788
|
if (!await fileExists(plansDir)) return null;
|
|
6518
6789
|
const files = (await readdir6(plansDir)).filter((f) => f.endsWith(".plan.md")).sort();
|
|
6519
|
-
return files[0] ?
|
|
6790
|
+
return files[0] ? path38.join(plansDir, files[0]) : null;
|
|
6520
6791
|
}
|
|
6521
6792
|
async function readPlan(planPath) {
|
|
6522
6793
|
return readFile18(planPath, "utf8");
|
|
@@ -6593,9 +6864,9 @@ function sleep(ms) {
|
|
|
6593
6864
|
return new Promise((r) => setTimeout(r, ms));
|
|
6594
6865
|
}
|
|
6595
6866
|
async function runPlanLoop(opts) {
|
|
6596
|
-
const plansDir =
|
|
6597
|
-
const stopFile =
|
|
6598
|
-
const logDir =
|
|
6867
|
+
const plansDir = path39.join(opts.root, ".cursor", "plans");
|
|
6868
|
+
const stopFile = path39.join(opts.root, ".cursor", "loop.stop");
|
|
6869
|
+
const logDir = path39.join(opts.root, ".cursor", "loop-logs");
|
|
6599
6870
|
const planPath = await findActivePlanFile(plansDir);
|
|
6600
6871
|
if (!planPath) {
|
|
6601
6872
|
logger.error("No active plan in .cursor/plans/");
|
|
@@ -6616,7 +6887,7 @@ async function runPlanLoop(opts) {
|
|
|
6616
6887
|
try {
|
|
6617
6888
|
const persona = await loadCliRunPlanPersona(opts.root);
|
|
6618
6889
|
const banners = createPersonaBannerPrinter(persona);
|
|
6619
|
-
console.log(`Active plan: ${
|
|
6890
|
+
console.log(`Active plan: ${path39.basename(planPath)}`);
|
|
6620
6891
|
console.log(`Pending to-dos: ${await pending()} | max ticks: ${opts.maxTicks}`);
|
|
6621
6892
|
console.log(`Backend: ${opts.backend.id}`);
|
|
6622
6893
|
if (persona) {
|
|
@@ -6659,20 +6930,23 @@ async function runPlanLoop(opts) {
|
|
|
6659
6930
|
planExhausted = true;
|
|
6660
6931
|
break;
|
|
6661
6932
|
}
|
|
6662
|
-
const logPath =
|
|
6663
|
-
const relLog =
|
|
6933
|
+
const logPath = path39.join(logDir, `tick-${stamp()}.log`);
|
|
6934
|
+
const relLog = path39.relative(opts.root, logPath);
|
|
6664
6935
|
console.log("");
|
|
6665
6936
|
const tickLine = `=== tick ${tick}/${opts.maxTicks} - pending: ${before} - log: ${relLog} ===`;
|
|
6666
6937
|
if (banners) banners.tickStart(tickLine);
|
|
6667
6938
|
else console.log(tickLine);
|
|
6668
6939
|
let agentExit = 0;
|
|
6669
6940
|
try {
|
|
6670
|
-
const result = await
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6941
|
+
const result = await withCliProgress(
|
|
6942
|
+
`tick ${tick}`,
|
|
6943
|
+
() => opts.backend.run({
|
|
6944
|
+
workspace: opts.root,
|
|
6945
|
+
prompt: TICK_PROMPT,
|
|
6946
|
+
model: opts.model,
|
|
6947
|
+
logPath
|
|
6948
|
+
})
|
|
6949
|
+
);
|
|
6676
6950
|
agentExit = result.exitCode;
|
|
6677
6951
|
} catch (err) {
|
|
6678
6952
|
logger.error(String(err));
|
|
@@ -6728,7 +7002,7 @@ async function runPlanLoop(opts) {
|
|
|
6728
7002
|
}
|
|
6729
7003
|
if (opts.sleepSeconds > 0) {
|
|
6730
7004
|
if (banners) banners.sleep(opts.sleepSeconds);
|
|
6731
|
-
await sleep(opts.sleepSeconds * 1e3);
|
|
7005
|
+
await withCliProgress(`sleep ${opts.sleepSeconds}s`, () => sleep(opts.sleepSeconds * 1e3));
|
|
6732
7006
|
}
|
|
6733
7007
|
}
|
|
6734
7008
|
const pendingNow = await pending();
|
|
@@ -6736,7 +7010,7 @@ async function runPlanLoop(opts) {
|
|
|
6736
7010
|
const finishDetail = `after ${tick} tick(s); pending: ${pendingNow}`;
|
|
6737
7011
|
if (banners) banners.phaseComplete(finishDetail);
|
|
6738
7012
|
console.log(
|
|
6739
|
-
`Loop finished after ${tick} tick(s). Pending now: ${pendingNow}. Logs in ${
|
|
7013
|
+
`Loop finished after ${tick} tick(s). Pending now: ${pendingNow}. Logs in ${path39.relative(opts.root, logDir)}/`
|
|
6740
7014
|
);
|
|
6741
7015
|
if (planExhausted || shouldArmExternalPlanReview({ pending: pendingNow, stopReason })) {
|
|
6742
7016
|
await armExternalPlanReview(opts.root);
|
|
@@ -6807,7 +7081,7 @@ var runPlanCommand = defineCommand14({
|
|
|
6807
7081
|
return;
|
|
6808
7082
|
}
|
|
6809
7083
|
const code = await runPlanLoop({
|
|
6810
|
-
root:
|
|
7084
|
+
root: path40.resolve(args.cwd),
|
|
6811
7085
|
maxTicks,
|
|
6812
7086
|
sleepSeconds,
|
|
6813
7087
|
model: args.model ? String(args.model) : void 0,
|
|
@@ -6841,7 +7115,7 @@ var scanCommand = defineCommand15({
|
|
|
6841
7115
|
});
|
|
6842
7116
|
|
|
6843
7117
|
// src/commands/status.ts
|
|
6844
|
-
import
|
|
7118
|
+
import path41 from "path";
|
|
6845
7119
|
import { defineCommand as defineCommand16 } from "citty";
|
|
6846
7120
|
function profileStatus(profile) {
|
|
6847
7121
|
if (!profile) return { origin: "none", evidence: [], profile: null };
|
|
@@ -6872,11 +7146,11 @@ var statusCommand = defineCommand16({
|
|
|
6872
7146
|
}
|
|
6873
7147
|
},
|
|
6874
7148
|
async run({ args }) {
|
|
6875
|
-
const rootDir =
|
|
7149
|
+
const rootDir = path41.resolve(args.cwd);
|
|
6876
7150
|
const [manifest, rawProfile, scan] = await Promise.all([
|
|
6877
7151
|
loadAgentKitManifest(rootDir),
|
|
6878
7152
|
readJson(
|
|
6879
|
-
|
|
7153
|
+
path41.join(rootDir, ".cursor", "agent-kit.config.json")
|
|
6880
7154
|
),
|
|
6881
7155
|
runScanner(rootDir)
|
|
6882
7156
|
]);
|
|
@@ -6935,7 +7209,7 @@ import { defineCommand as defineCommand17 } from "citty";
|
|
|
6935
7209
|
|
|
6936
7210
|
// src/lifecycle/check-updates.ts
|
|
6937
7211
|
import { execFile as execFile6 } from "child_process";
|
|
6938
|
-
import
|
|
7212
|
+
import path42 from "path";
|
|
6939
7213
|
import { promisify as promisify6 } from "util";
|
|
6940
7214
|
var execFileAsync5 = promisify6(execFile6);
|
|
6941
7215
|
var SEMVER_CORE = /^v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/i;
|
|
@@ -7026,11 +7300,11 @@ function intervalElapsed2(lastCheckedAt, intervalDays) {
|
|
|
7026
7300
|
return Date.now() - last >= ms;
|
|
7027
7301
|
}
|
|
7028
7302
|
async function loadContextConfig2(cwd) {
|
|
7029
|
-
const configPath =
|
|
7303
|
+
const configPath = path42.join(cwd, ".cursor", "context", "config.json");
|
|
7030
7304
|
return readJson(configPath);
|
|
7031
7305
|
}
|
|
7032
7306
|
async function stampLastCheckedAt(cwd) {
|
|
7033
|
-
const configPath =
|
|
7307
|
+
const configPath = path42.join(cwd, ".cursor", "context", "config.json");
|
|
7034
7308
|
const existing = await loadContextConfig2(cwd) ?? {};
|
|
7035
7309
|
const prev = existing.updateCheck && typeof existing.updateCheck === "object" ? { ...existing.updateCheck } : {};
|
|
7036
7310
|
existing.updateCheck = {
|
|
@@ -7040,6 +7314,117 @@ async function stampLastCheckedAt(cwd) {
|
|
|
7040
7314
|
};
|
|
7041
7315
|
await writeJson(configPath, existing);
|
|
7042
7316
|
}
|
|
7317
|
+
async function readLocalKitVersion(registryRoot) {
|
|
7318
|
+
for (const rel of ["packages/cli/package.json", "package.json"]) {
|
|
7319
|
+
const data = await readJson(path42.join(registryRoot, rel));
|
|
7320
|
+
if (data && typeof data.version === "string" && data.version.length > 0) {
|
|
7321
|
+
return data.version;
|
|
7322
|
+
}
|
|
7323
|
+
}
|
|
7324
|
+
return null;
|
|
7325
|
+
}
|
|
7326
|
+
async function checkAgainstLocalRegistry(cwd, manifest, options) {
|
|
7327
|
+
const registryPath = options.registryPath;
|
|
7328
|
+
if (!registryPath) {
|
|
7329
|
+
throw new Error("checkAgainstLocalRegistry requires registryPath");
|
|
7330
|
+
}
|
|
7331
|
+
let resolved;
|
|
7332
|
+
try {
|
|
7333
|
+
resolved = await resolveRegistryRoot({ cwd, registryPath });
|
|
7334
|
+
} catch (err) {
|
|
7335
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
7336
|
+
return {
|
|
7337
|
+
status: "error",
|
|
7338
|
+
installedVersion: manifest.version,
|
|
7339
|
+
latestVersion: null,
|
|
7340
|
+
registryUrl: path42.resolve(registryPath),
|
|
7341
|
+
registryRef: "local",
|
|
7342
|
+
applyRecommended: false,
|
|
7343
|
+
message: `Failed to resolve --registry: ${msg}`
|
|
7344
|
+
};
|
|
7345
|
+
}
|
|
7346
|
+
const registryUrl = resolved.root;
|
|
7347
|
+
const registryRef = "local";
|
|
7348
|
+
try {
|
|
7349
|
+
let latest;
|
|
7350
|
+
if (options.latestVersion !== void 0) {
|
|
7351
|
+
latest = options.latestVersion;
|
|
7352
|
+
} else {
|
|
7353
|
+
const raw = await readLocalKitVersion(resolved.root);
|
|
7354
|
+
latest = raw ? normalizeSemver(raw) : null;
|
|
7355
|
+
}
|
|
7356
|
+
const summary = summarizeDiff(await diffAgainstRegistry(resolved.root, cwd, manifest));
|
|
7357
|
+
const hasFileDrift = summary.drift > 0 || summary["missing-local"] > 0;
|
|
7358
|
+
const installed = normalizeSemver(manifest.version);
|
|
7359
|
+
if (!installed) {
|
|
7360
|
+
return {
|
|
7361
|
+
status: "error",
|
|
7362
|
+
installedVersion: manifest.version,
|
|
7363
|
+
latestVersion: latest,
|
|
7364
|
+
registryUrl,
|
|
7365
|
+
registryRef,
|
|
7366
|
+
applyRecommended: false,
|
|
7367
|
+
message: `Installed version "${manifest.version}" is not valid semver.`
|
|
7368
|
+
};
|
|
7369
|
+
}
|
|
7370
|
+
if (!latest) {
|
|
7371
|
+
return {
|
|
7372
|
+
status: "error",
|
|
7373
|
+
installedVersion: installed,
|
|
7374
|
+
latestVersion: null,
|
|
7375
|
+
registryUrl,
|
|
7376
|
+
registryRef,
|
|
7377
|
+
applyRecommended: false,
|
|
7378
|
+
message: "No semver found in the local --registry checkout (packages/cli/package.json or package.json)."
|
|
7379
|
+
};
|
|
7380
|
+
}
|
|
7381
|
+
const cmp = compareSemver(installed, latest);
|
|
7382
|
+
if (hasFileDrift) {
|
|
7383
|
+
return {
|
|
7384
|
+
status: "update-available",
|
|
7385
|
+
installedVersion: installed,
|
|
7386
|
+
latestVersion: latest,
|
|
7387
|
+
registryUrl,
|
|
7388
|
+
registryRef,
|
|
7389
|
+
applyRecommended: false,
|
|
7390
|
+
message: `Local registry has drift vs this install (drift=${summary.drift}, missing-local=${summary["missing-local"]}; source v${latest}). Run /update --registry <path> (Ask confirm) to apply; never silent.`
|
|
7391
|
+
};
|
|
7392
|
+
}
|
|
7393
|
+
if (cmp === 0) {
|
|
7394
|
+
return {
|
|
7395
|
+
status: "up-to-date",
|
|
7396
|
+
installedVersion: installed,
|
|
7397
|
+
latestVersion: latest,
|
|
7398
|
+
registryUrl,
|
|
7399
|
+
registryRef,
|
|
7400
|
+
applyRecommended: false,
|
|
7401
|
+
message: `Installed v${installed} matches local registry v${latest}.`
|
|
7402
|
+
};
|
|
7403
|
+
}
|
|
7404
|
+
if (cmp < 0) {
|
|
7405
|
+
return {
|
|
7406
|
+
status: "update-available",
|
|
7407
|
+
installedVersion: installed,
|
|
7408
|
+
latestVersion: latest,
|
|
7409
|
+
registryUrl,
|
|
7410
|
+
registryRef,
|
|
7411
|
+
applyRecommended: false,
|
|
7412
|
+
message: `Update available from local registry: v${installed} \u2192 v${latest}. Run /update --registry <path> (Ask confirm) to apply; never silent.`
|
|
7413
|
+
};
|
|
7414
|
+
}
|
|
7415
|
+
return {
|
|
7416
|
+
status: "ahead-of-public",
|
|
7417
|
+
installedVersion: installed,
|
|
7418
|
+
latestVersion: latest,
|
|
7419
|
+
registryUrl,
|
|
7420
|
+
registryRef,
|
|
7421
|
+
applyRecommended: false,
|
|
7422
|
+
message: `Installed v${installed} is ahead of local registry v${latest}.`
|
|
7423
|
+
};
|
|
7424
|
+
} finally {
|
|
7425
|
+
await resolved.unlock?.();
|
|
7426
|
+
}
|
|
7427
|
+
}
|
|
7043
7428
|
async function checkForUpdates(cwd, options = {}) {
|
|
7044
7429
|
const manifest = await loadAgentKitManifest(cwd);
|
|
7045
7430
|
if (!manifest) {
|
|
@@ -7053,7 +7438,10 @@ async function checkForUpdates(cwd, options = {}) {
|
|
|
7053
7438
|
message: "No .cursor/agent-kit.json \u2014 run agent-kit install first."
|
|
7054
7439
|
};
|
|
7055
7440
|
}
|
|
7056
|
-
|
|
7441
|
+
if (options.registryPath) {
|
|
7442
|
+
return checkAgainstLocalRegistry(cwd, manifest, options);
|
|
7443
|
+
}
|
|
7444
|
+
const registryUrl = options.publicRegistryUrl ?? manifest.registry?.url ?? null;
|
|
7057
7445
|
const registryRef = manifest.registry?.ref ?? null;
|
|
7058
7446
|
if (isFactoryOrDevRegistry(registryUrl, registryRef)) {
|
|
7059
7447
|
return {
|
|
@@ -7183,7 +7571,7 @@ var updateCommand = defineCommand17({
|
|
|
7183
7571
|
},
|
|
7184
7572
|
check: {
|
|
7185
7573
|
type: "boolean",
|
|
7186
|
-
description: "Check-only: compare installed version to
|
|
7574
|
+
description: "Check-only: compare installed version to the resolved registry (public tags, or --registry local checkout); never apply L0 writes",
|
|
7187
7575
|
default: false
|
|
7188
7576
|
},
|
|
7189
7577
|
json: {
|
|
@@ -7224,7 +7612,8 @@ var updateCommand = defineCommand17({
|
|
|
7224
7612
|
const result = await checkForUpdates(args.cwd, {
|
|
7225
7613
|
respectPrefs: Boolean(args["respect-prefs"]),
|
|
7226
7614
|
stamp: Boolean(args.stamp),
|
|
7227
|
-
publicRegistryUrl: typeof args.url === "string" && args.url ? args.url : void 0
|
|
7615
|
+
publicRegistryUrl: typeof args.url === "string" && args.url ? args.url : void 0,
|
|
7616
|
+
registryPath: typeof args.registry === "string" && args.registry ? args.registry : void 0
|
|
7228
7617
|
});
|
|
7229
7618
|
if (args.json) {
|
|
7230
7619
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -7287,7 +7676,10 @@ var updateCommand = defineCommand17({
|
|
|
7287
7676
|
await seedManagedHashLedger(projectRoot);
|
|
7288
7677
|
logger.info("Seeded managed-hash ledger from current local overlay files.");
|
|
7289
7678
|
}
|
|
7290
|
-
const stats = await
|
|
7679
|
+
const stats = await withCliProgress(
|
|
7680
|
+
"update",
|
|
7681
|
+
() => syncFromManifest(registry.root, projectRoot, next)
|
|
7682
|
+
);
|
|
7291
7683
|
await saveManifest(projectRoot, next);
|
|
7292
7684
|
logApplyStats(stats);
|
|
7293
7685
|
logger.success("Update complete (L3 protected paths left untouched).");
|
|
@@ -7299,7 +7691,7 @@ var updateCommand = defineCommand17({
|
|
|
7299
7691
|
|
|
7300
7692
|
// src/commands/validate.ts
|
|
7301
7693
|
import { readFile as readFile21 } from "fs/promises";
|
|
7302
|
-
import
|
|
7694
|
+
import path43 from "path";
|
|
7303
7695
|
import { defineCommand as defineCommand18 } from "citty";
|
|
7304
7696
|
|
|
7305
7697
|
// src/invariants/plan-schema.ts
|
|
@@ -7346,7 +7738,7 @@ function validatePlanFrontmatterText(text) {
|
|
|
7346
7738
|
// src/commands/validate.ts
|
|
7347
7739
|
async function resolveEditedPath(cwd, explicit) {
|
|
7348
7740
|
if (explicit) {
|
|
7349
|
-
const filePath2 =
|
|
7741
|
+
const filePath2 = path43.resolve(cwd, explicit);
|
|
7350
7742
|
try {
|
|
7351
7743
|
return { filePath: filePath2, content: await readFile21(filePath2, "utf8") };
|
|
7352
7744
|
} catch {
|
|
@@ -7356,7 +7748,7 @@ async function resolveEditedPath(cwd, explicit) {
|
|
|
7356
7748
|
const payload = await readStdinJson();
|
|
7357
7749
|
const rel = typeof payload.file_path === "string" && payload.file_path || typeof payload.path === "string" && payload.path || typeof payload.file === "string" && payload.file || "";
|
|
7358
7750
|
if (!rel) return null;
|
|
7359
|
-
const filePath =
|
|
7751
|
+
const filePath = path43.isAbsolute(rel) ? rel : path43.resolve(cwd, rel);
|
|
7360
7752
|
try {
|
|
7361
7753
|
return { filePath, content: await readFile21(filePath, "utf8") };
|
|
7362
7754
|
} catch {
|
|
@@ -7386,7 +7778,7 @@ var validateCommand = defineCommand18({
|
|
|
7386
7778
|
async run({ args }) {
|
|
7387
7779
|
const cwd = typeof args.cwd === "string" ? args.cwd : process.cwd();
|
|
7388
7780
|
const fileArg = typeof args.file === "string" ? args.file : void 0;
|
|
7389
|
-
const filePath = fileArg ?
|
|
7781
|
+
const filePath = fileArg ? path43.resolve(cwd, fileArg) : path43.join(path43.resolve(cwd), ".cursor", "HANDOFF.md");
|
|
7390
7782
|
let content = "";
|
|
7391
7783
|
try {
|
|
7392
7784
|
content = await readFile21(filePath, "utf8");
|
|
@@ -7413,7 +7805,7 @@ var validateCommand = defineCommand18({
|
|
|
7413
7805
|
process.exitCode = 2;
|
|
7414
7806
|
return;
|
|
7415
7807
|
}
|
|
7416
|
-
const filePath =
|
|
7808
|
+
const filePath = path43.resolve(cwd, fileArg);
|
|
7417
7809
|
let content = "";
|
|
7418
7810
|
try {
|
|
7419
7811
|
content = await readFile21(filePath, "utf8");
|
|
@@ -7435,7 +7827,7 @@ var validateCommand = defineCommand18({
|
|
|
7435
7827
|
},
|
|
7436
7828
|
async run({ args }) {
|
|
7437
7829
|
const cwd = typeof args.cwd === "string" ? args.cwd : process.cwd();
|
|
7438
|
-
const resolved = await resolveEditedPath(
|
|
7830
|
+
const resolved = await resolveEditedPath(path43.resolve(cwd));
|
|
7439
7831
|
if (!resolved) {
|
|
7440
7832
|
console.log(JSON.stringify({}));
|
|
7441
7833
|
return;
|
|
@@ -7478,19 +7870,18 @@ var validateCommand = defineCommand18({
|
|
|
7478
7870
|
});
|
|
7479
7871
|
|
|
7480
7872
|
// src/welcome/help-groups.ts
|
|
7481
|
-
import { bold, gray as
|
|
7873
|
+
import { bold, gray as gray4, underline } from "kolorist";
|
|
7482
7874
|
|
|
7483
7875
|
// src/welcome/screen.ts
|
|
7484
7876
|
import {
|
|
7485
7877
|
blue as blue2,
|
|
7486
|
-
cyan as
|
|
7487
|
-
gray as
|
|
7488
|
-
options as
|
|
7878
|
+
cyan as cyan4,
|
|
7879
|
+
gray as gray3,
|
|
7880
|
+
options as koloristOptions2,
|
|
7489
7881
|
lightCyan,
|
|
7490
7882
|
trueColor,
|
|
7491
7883
|
white as white2
|
|
7492
7884
|
} from "kolorist";
|
|
7493
|
-
var HELMET_OUTLINE = "#e2e8f0";
|
|
7494
7885
|
var KOLORIST_TRUECOLOR = 3;
|
|
7495
7886
|
var HELMET_ASCII = [
|
|
7496
7887
|
" ____",
|
|
@@ -7515,30 +7906,20 @@ function outlineAnsi(line) {
|
|
|
7515
7906
|
return trueColor(r, g, b)(line);
|
|
7516
7907
|
}
|
|
7517
7908
|
function withKoloristColor(fn) {
|
|
7518
|
-
const prevEnabled =
|
|
7519
|
-
const prevLevel =
|
|
7520
|
-
|
|
7521
|
-
|
|
7909
|
+
const prevEnabled = koloristOptions2.enabled;
|
|
7910
|
+
const prevLevel = koloristOptions2.supportLevel;
|
|
7911
|
+
koloristOptions2.enabled = true;
|
|
7912
|
+
koloristOptions2.supportLevel = KOLORIST_TRUECOLOR;
|
|
7522
7913
|
try {
|
|
7523
7914
|
return fn();
|
|
7524
7915
|
} finally {
|
|
7525
|
-
|
|
7526
|
-
|
|
7916
|
+
koloristOptions2.enabled = prevEnabled;
|
|
7917
|
+
koloristOptions2.supportLevel = prevLevel;
|
|
7527
7918
|
}
|
|
7528
7919
|
}
|
|
7529
7920
|
function hasCliSubcommand(rawArgs) {
|
|
7530
7921
|
return Boolean(rawArgs?.some((arg) => !arg.startsWith("-")));
|
|
7531
7922
|
}
|
|
7532
|
-
function shouldUseWelcomeColor(opts = {}) {
|
|
7533
|
-
if (opts.color === false) return false;
|
|
7534
|
-
if (process.env.NO_COLOR) return false;
|
|
7535
|
-
if (process.env.NODE_DISABLE_COLORS) return false;
|
|
7536
|
-
if (process.env.FORCE_COLOR === "0") return false;
|
|
7537
|
-
if (process.env.CI != null && process.env.CI !== "") return false;
|
|
7538
|
-
if (opts.color === true) return true;
|
|
7539
|
-
const tty = opts.stdoutIsTTY ?? Boolean(process.stdout.isTTY);
|
|
7540
|
-
return tty;
|
|
7541
|
-
}
|
|
7542
7923
|
function renderHelmetAscii(color) {
|
|
7543
7924
|
if (!color) return HELMET_ASCII.join("\n");
|
|
7544
7925
|
return withKoloristColor(
|
|
@@ -7560,8 +7941,8 @@ function renderWelcomeScreen(opts = {}) {
|
|
|
7560
7941
|
const version = opts.version ?? KIT_VERSION;
|
|
7561
7942
|
const color = shouldUseWelcomeColor(opts);
|
|
7562
7943
|
const title = color ? white2("Mission Kit") : "Mission Kit";
|
|
7563
|
-
const product = color ?
|
|
7564
|
-
const muted = (s) => color ?
|
|
7944
|
+
const product = color ? cyan4("agent-kit") : "agent-kit";
|
|
7945
|
+
const muted = (s) => color ? gray3(s) : s;
|
|
7565
7946
|
const lines = [
|
|
7566
7947
|
renderHelmetAscii(color),
|
|
7567
7948
|
"",
|
|
@@ -7573,13 +7954,18 @@ function renderWelcomeScreen(opts = {}) {
|
|
|
7573
7954
|
const width = Math.max(...WELCOME_UTILITY_HINTS.map(({ cmd }) => cmd.length));
|
|
7574
7955
|
return WELCOME_UTILITY_HINTS.map(({ cmd, hint }) => {
|
|
7575
7956
|
const pad = " ".repeat(width - cmd.length + 2);
|
|
7576
|
-
const left = color ?
|
|
7957
|
+
const left = color ? cyan4(` ${cmd}`) : ` ${cmd}`;
|
|
7577
7958
|
return `${left}${pad}${muted(hint)}`;
|
|
7578
7959
|
});
|
|
7579
7960
|
})(),
|
|
7580
7961
|
"",
|
|
7581
7962
|
muted(
|
|
7582
7963
|
"Chat HITL (start-project, git-staging/prod, run-plan-all) stays in Cursor slash commands."
|
|
7964
|
+
),
|
|
7965
|
+
muted(
|
|
7966
|
+
`${shouldUseVisualMotion(opts) ? SPACE_MARKS.star : SPACE_MARKS.tick} ${tipAt(
|
|
7967
|
+
[...version].reduce((n, c) => n + c.charCodeAt(0), 0)
|
|
7968
|
+
)}`
|
|
7583
7969
|
)
|
|
7584
7970
|
];
|
|
7585
7971
|
return `${lines.join("\n")}
|
|
@@ -7630,7 +8016,7 @@ async function resolveSubMeta(subCommands) {
|
|
|
7630
8016
|
async function renderGroupedRootHelp(cmd) {
|
|
7631
8017
|
const color = shouldUseWelcomeColor();
|
|
7632
8018
|
const u = (s) => color ? underline(bold(s)) : s;
|
|
7633
|
-
const g = (s) => color ?
|
|
8019
|
+
const g = (s) => color ? gray4(s) : s;
|
|
7634
8020
|
const meta = await resolveCommandMeta(cmd.meta);
|
|
7635
8021
|
const name = meta?.name ?? "agent-kit";
|
|
7636
8022
|
const version = meta?.version ?? KIT_VERSION;
|
|
@@ -7660,11 +8046,14 @@ async function renderGroupedRootHelp(cmd) {
|
|
|
7660
8046
|
}
|
|
7661
8047
|
lines.push("");
|
|
7662
8048
|
}
|
|
8049
|
+
const tipMark = shouldUseVisualMotion() ? SPACE_MARKS.star : SPACE_MARKS.tick;
|
|
8050
|
+
const tip = tipAt([...version].reduce((n, c) => n + c.charCodeAt(0), 0));
|
|
7663
8051
|
lines.push(
|
|
7664
8052
|
g(`Use \`${name} <command> --help\` for more information about a command.`),
|
|
7665
8053
|
g(
|
|
7666
8054
|
"Chat-only HITL (start-project, backlog, git-staging/prod, run-plan-all) is not a CLI surface."
|
|
7667
8055
|
),
|
|
8056
|
+
g(`${tipMark} ${tip}`),
|
|
7668
8057
|
""
|
|
7669
8058
|
);
|
|
7670
8059
|
return lines.join("\n");
|