@inteeka/task-cli 0.2.28 → 0.2.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +81 -15
- package/dist/cli.js.map +1 -1
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -949,7 +949,7 @@ function registerLink(program2) {
|
|
|
949
949
|
project_slug: chosen.slug,
|
|
950
950
|
project_name: chosen.name,
|
|
951
951
|
cli_protected_paths: chosen.cli_protected_paths,
|
|
952
|
-
cli_base_branch: chosen.cli_base_branch
|
|
952
|
+
...chosen.cli_base_branch ? { cli_base_branch: chosen.cli_base_branch } : {},
|
|
953
953
|
cli_test_command: chosen.cli_test_command ?? null
|
|
954
954
|
},
|
|
955
955
|
repoRoot
|
|
@@ -1099,10 +1099,14 @@ function currentBranch(cwd) {
|
|
|
1099
1099
|
}
|
|
1100
1100
|
|
|
1101
1101
|
// src/git/branch.ts
|
|
1102
|
-
var
|
|
1102
|
+
var BRANCH_NAME_REGEX = /^[A-Za-z0-9._/-]{1,200}$/;
|
|
1103
|
+
var VALID_BRANCH = BRANCH_NAME_REGEX;
|
|
1103
1104
|
var TICKET_BRANCH = /^task\/[a-z0-9-]{1,80}$/;
|
|
1105
|
+
function isValidBranchName(branch) {
|
|
1106
|
+
return BRANCH_NAME_REGEX.test(branch) && !branch.includes("..") && !branch.startsWith("/") && !branch.endsWith("/");
|
|
1107
|
+
}
|
|
1104
1108
|
function assertValidBranchName(branch) {
|
|
1105
|
-
if (!
|
|
1109
|
+
if (!isValidBranchName(branch)) {
|
|
1106
1110
|
throw new CliError(
|
|
1107
1111
|
CLI_EXIT_CODES.MISCONFIGURATION,
|
|
1108
1112
|
`Invalid branch name: ${branch}`,
|
|
@@ -1264,6 +1268,32 @@ function remoteBranchExists(cwd, branchName, opts = {}) {
|
|
|
1264
1268
|
}
|
|
1265
1269
|
return stdout.trim().length > 0;
|
|
1266
1270
|
}
|
|
1271
|
+
function detectDefaultBranch(cwd) {
|
|
1272
|
+
try {
|
|
1273
|
+
const ref = execFileSync2("git", ["symbolic-ref", "refs/remotes/origin/HEAD"], {
|
|
1274
|
+
cwd,
|
|
1275
|
+
encoding: "utf8",
|
|
1276
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
1277
|
+
}).trim();
|
|
1278
|
+
const prefix = "refs/remotes/origin/";
|
|
1279
|
+
if (ref.startsWith(prefix)) {
|
|
1280
|
+
const name = ref.slice(prefix.length);
|
|
1281
|
+
if (isValidBranchName(name)) return name;
|
|
1282
|
+
}
|
|
1283
|
+
} catch {
|
|
1284
|
+
}
|
|
1285
|
+
for (const candidate of ["main", "development", "master"]) {
|
|
1286
|
+
try {
|
|
1287
|
+
execFileSync2("git", ["rev-parse", "--verify", `origin/${candidate}`], {
|
|
1288
|
+
cwd,
|
|
1289
|
+
stdio: ["ignore", "ignore", "ignore"]
|
|
1290
|
+
});
|
|
1291
|
+
return candidate;
|
|
1292
|
+
} catch {
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
return null;
|
|
1296
|
+
}
|
|
1267
1297
|
function listLocalTicketBranches(cwd) {
|
|
1268
1298
|
let stdout;
|
|
1269
1299
|
try {
|
|
@@ -2292,11 +2322,20 @@ async function buildWorkContext(opts) {
|
|
|
2292
2322
|
);
|
|
2293
2323
|
}
|
|
2294
2324
|
const localCfg = await readLocalConfig();
|
|
2325
|
+
const cwd = findRepoRoot();
|
|
2326
|
+
if (opts.baseBranch !== void 0 && !isValidBranchName(opts.baseBranch)) {
|
|
2327
|
+
throw new CliError(
|
|
2328
|
+
CLI_EXIT_CODES.MISCONFIGURATION,
|
|
2329
|
+
`Invalid --base-branch value: ${opts.baseBranch}`,
|
|
2330
|
+
'Branch names must contain only [A-Za-z0-9._/-], no "..", and no leading/trailing slash.'
|
|
2331
|
+
);
|
|
2332
|
+
}
|
|
2333
|
+
const baseBranch = opts.baseBranch ?? project.cli_base_branch ?? detectDefaultBranch(cwd) ?? "main";
|
|
2295
2334
|
return {
|
|
2296
2335
|
project,
|
|
2297
2336
|
localCfg,
|
|
2298
|
-
cwd
|
|
2299
|
-
baseBranch
|
|
2337
|
+
cwd,
|
|
2338
|
+
baseBranch,
|
|
2300
2339
|
silent: !!opts.silent || localCfg.silent
|
|
2301
2340
|
};
|
|
2302
2341
|
}
|
|
@@ -2310,6 +2349,9 @@ function registerWork(program2) {
|
|
|
2310
2349
|
).option(
|
|
2311
2350
|
"--no-auto-review",
|
|
2312
2351
|
"Skip the post-PR /qa + /security auto-review. The PR is left open for a human to review and merge."
|
|
2352
|
+
).option(
|
|
2353
|
+
"--base-branch <name>",
|
|
2354
|
+
"Override the base branch for this run. Wins over the project's configured cli_base_branch and the git auto-detect fallback. Typically supplied by the dashboard listener on each spawn."
|
|
2313
2355
|
).option("--schedule-id <id>", "Internal: schedule id when invoked from a scheduled task").action(async (ticketId, opts) => {
|
|
2314
2356
|
await runWork(ticketId, opts);
|
|
2315
2357
|
});
|
|
@@ -3159,12 +3201,19 @@ function registerMultiWork(program2) {
|
|
|
3159
3201
|
).option(
|
|
3160
3202
|
"--reset",
|
|
3161
3203
|
"DESTRUCTIVE: discard local working-tree changes before the first ticket. Requires --confirm in non-TTY contexts."
|
|
3162
|
-
).option("--confirm", "Confirm --reset in non-TTY (silent / scheduled-task) contexts.").option(
|
|
3204
|
+
).option("--confirm", "Confirm --reset in non-TTY (silent / scheduled-task) contexts.").option(
|
|
3205
|
+
"--base-branch <name>",
|
|
3206
|
+
"Override the base branch for the whole batch. Wins over the project's configured cli_base_branch and the git auto-detect fallback."
|
|
3207
|
+
).option("--schedule-id <id>", "Internal: schedule id when invoked from a scheduled task").action(async (opts) => {
|
|
3163
3208
|
await runMultiWork(opts);
|
|
3164
3209
|
});
|
|
3165
3210
|
}
|
|
3166
3211
|
async function runMultiWork(opts) {
|
|
3167
|
-
const ctx = await buildWorkContext({
|
|
3212
|
+
const ctx = await buildWorkContext({
|
|
3213
|
+
max: opts.max,
|
|
3214
|
+
silent: opts.silent,
|
|
3215
|
+
...opts.baseBranch ? { baseBranch: opts.baseBranch } : {}
|
|
3216
|
+
});
|
|
3168
3217
|
const max = Math.max(1, parseInt(opts.max, 10) || 10);
|
|
3169
3218
|
let firstIteration = true;
|
|
3170
3219
|
const innerOpts = {
|
|
@@ -3175,7 +3224,8 @@ async function runMultiWork(opts) {
|
|
|
3175
3224
|
silent: opts.silent,
|
|
3176
3225
|
scheduleId: opts.scheduleId,
|
|
3177
3226
|
reset: opts.reset,
|
|
3178
|
-
confirm: opts.confirm
|
|
3227
|
+
confirm: opts.confirm,
|
|
3228
|
+
...opts.baseBranch ? { baseBranch: opts.baseBranch } : {}
|
|
3179
3229
|
};
|
|
3180
3230
|
const results = [];
|
|
3181
3231
|
let processed = 0;
|
|
@@ -3314,7 +3364,7 @@ async function runResume(ticketRef, opts) {
|
|
|
3314
3364
|
"Run 'task link' first."
|
|
3315
3365
|
);
|
|
3316
3366
|
}
|
|
3317
|
-
const baseBranch = project.cli_base_branch ?? "
|
|
3367
|
+
const baseBranch = project.cli_base_branch ?? detectDefaultBranch(cwd) ?? "main";
|
|
3318
3368
|
const silent = !!opts.silent;
|
|
3319
3369
|
assertBaseBranch(cwd, baseBranch);
|
|
3320
3370
|
const access2 = await apiCallOrThrow("GET", "/api/v1/cli/access");
|
|
@@ -4676,6 +4726,9 @@ function registerFastTrack(program2) {
|
|
|
4676
4726
|
).option("--confirm", "Confirm --reset in non-TTY (silent / scheduled-task) contexts").option(
|
|
4677
4727
|
"--no-auto-review",
|
|
4678
4728
|
"Skip the post-PR /qa + /security auto-review. Each PR is left open for a human to review and merge."
|
|
4729
|
+
).option(
|
|
4730
|
+
"--base-branch <name>",
|
|
4731
|
+
"Override the base branch for this run. Wins over the project's configured cli_base_branch and the git auto-detect fallback."
|
|
4679
4732
|
).option("--schedule-id <id>", "Internal: schedule id when invoked from a scheduled task").action(async (opts) => {
|
|
4680
4733
|
await runFastTrack(opts);
|
|
4681
4734
|
});
|
|
@@ -4702,7 +4755,11 @@ async function runFastTrack(opts) {
|
|
|
4702
4755
|
const apiUrl = (opts.apiUrl ?? process.env["TASK_API_URL"] ?? creds.api_url ?? localCfg.api_url ?? linkedProject.api_url ?? "http://localhost:3400").replace(/\/$/, "");
|
|
4703
4756
|
const max = Math.max(1, parseInt(opts.max, 10) || 1);
|
|
4704
4757
|
const silent = !!opts.silent || localCfg.silent;
|
|
4705
|
-
const ctx = await buildWorkContext({
|
|
4758
|
+
const ctx = await buildWorkContext({
|
|
4759
|
+
max: "1",
|
|
4760
|
+
silent: opts.silent,
|
|
4761
|
+
...opts.baseBranch ? { baseBranch: opts.baseBranch } : {}
|
|
4762
|
+
});
|
|
4706
4763
|
const api = new AutopilotApi({ apiUrl, creds });
|
|
4707
4764
|
const claudePath = localCfg.claude_path ?? void 0;
|
|
4708
4765
|
let firstIteration = true;
|
|
@@ -4721,7 +4778,8 @@ async function runFastTrack(opts) {
|
|
|
4721
4778
|
// Commander sets opts.autoReview to `false` only when --no-auto-review
|
|
4722
4779
|
// is passed; otherwise it's `undefined` and processOneTicketImpl
|
|
4723
4780
|
// treats `undefined` as "auto-review enabled" (opts.autoReview !== false).
|
|
4724
|
-
...opts.autoReview === false ? { autoReview: false } : {}
|
|
4781
|
+
...opts.autoReview === false ? { autoReview: false } : {},
|
|
4782
|
+
...opts.baseBranch ? { baseBranch: opts.baseBranch } : {}
|
|
4725
4783
|
};
|
|
4726
4784
|
const outcome = await fastTrackOneTicket({
|
|
4727
4785
|
api,
|
|
@@ -4939,7 +4997,7 @@ async function runPrTest(opts) {
|
|
|
4939
4997
|
"Run 'task link' first."
|
|
4940
4998
|
);
|
|
4941
4999
|
}
|
|
4942
|
-
const baseBranch = project.cli_base_branch ?? "
|
|
5000
|
+
const baseBranch = project.cli_base_branch ?? detectDefaultBranch(cwd) ?? "main";
|
|
4943
5001
|
const silent = !!opts.silent;
|
|
4944
5002
|
if (!silent) process.stdout.write(`${c.dim(`Step 1/6: assertBaseBranch (${baseBranch})\u2026`)}
|
|
4945
5003
|
`);
|
|
@@ -6101,7 +6159,15 @@ function registerDoctor(program2) {
|
|
|
6101
6159
|
});
|
|
6102
6160
|
}
|
|
6103
6161
|
if (project) {
|
|
6104
|
-
const
|
|
6162
|
+
const explicitlyConfigured = typeof project.cli_base_branch === "string";
|
|
6163
|
+
checks.push({
|
|
6164
|
+
group: "setup",
|
|
6165
|
+
name: "cli base branch configured",
|
|
6166
|
+
ok: explicitlyConfigured,
|
|
6167
|
+
detail: explicitlyConfigured ? `set to "${project.cli_base_branch}"` : "no value set on the project \u2014 using auto-detect fallback",
|
|
6168
|
+
remediation: explicitlyConfigured ? void 0 : `Open the dashboard \u2192 Project settings \u2192 Agentic CLI and set the base branch (typically "main" or "development"), then re-run \`task link\`.`
|
|
6169
|
+
});
|
|
6170
|
+
const baseBranch = project.cli_base_branch ?? detectDefaultBranch(root) ?? "main";
|
|
6105
6171
|
try {
|
|
6106
6172
|
const exists = remoteBranchExists(root, baseBranch);
|
|
6107
6173
|
checks.push({
|
|
@@ -6109,7 +6175,7 @@ function registerDoctor(program2) {
|
|
|
6109
6175
|
name: "base branch on origin",
|
|
6110
6176
|
ok: exists,
|
|
6111
6177
|
detail: exists ? `origin/${baseBranch} reachable` : `origin has no branch "${baseBranch}"`,
|
|
6112
|
-
remediation: exists ? void 0 : `push it (\`git push origin ${baseBranch}\`) or
|
|
6178
|
+
remediation: exists ? void 0 : `push it (\`git push origin ${baseBranch}\`) or set the project's base branch in the dashboard (Project settings \u2192 Agentic CLI), or pass --base-branch <name> on the next \`task work\``
|
|
6113
6179
|
});
|
|
6114
6180
|
} catch (err) {
|
|
6115
6181
|
checks.push({
|
|
@@ -6337,7 +6403,7 @@ function checkBinary(name, command) {
|
|
|
6337
6403
|
}
|
|
6338
6404
|
|
|
6339
6405
|
// src/commands/version.ts
|
|
6340
|
-
var CLI_VERSION = true ? "0.2.
|
|
6406
|
+
var CLI_VERSION = true ? "0.2.30" : "0.0.0-dev";
|
|
6341
6407
|
function registerVersion(program2) {
|
|
6342
6408
|
program2.command("version").description("Print the CLI version").action(() => {
|
|
6343
6409
|
process.stdout.write(CLI_VERSION + "\n");
|