@inteeka/task-cli 0.1.5 → 0.1.7

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 CHANGED
@@ -1876,8 +1876,9 @@ async function generateFixPromptJson(args) {
1876
1876
  );
1877
1877
  return;
1878
1878
  }
1879
+ const structuredFromEnvelope = extractStructuredOutput(stdoutBuf);
1879
1880
  const innerText = extractEnvelopeText(stdoutBuf);
1880
- const parsed = parseStructuredJson(innerText);
1881
+ const parsed = structuredFromEnvelope ?? parseStructuredJson(innerText);
1881
1882
  if (!parsed) {
1882
1883
  const dump = await maybeDumpDebug(args.ticketId, stdoutBuf, stderrBuf);
1883
1884
  reject(
@@ -1914,6 +1915,17 @@ function detectAuthFailure(raw) {
1914
1915
  }
1915
1916
  return false;
1916
1917
  }
1918
+ function extractStructuredOutput(raw) {
1919
+ const trimmed = raw.trim();
1920
+ if (!trimmed) return null;
1921
+ try {
1922
+ const env = JSON.parse(trimmed);
1923
+ const so = env.structured_output;
1924
+ if (so && typeof so === "object") return so;
1925
+ } catch {
1926
+ }
1927
+ return null;
1928
+ }
1917
1929
  function extractEnvelopeText(raw) {
1918
1930
  const trimmed = raw.trim();
1919
1931
  if (!trimmed) return raw;
@@ -2012,7 +2024,13 @@ function parseStructuredJson(raw) {
2012
2024
  function registerScan(program2) {
2013
2025
  program2.command("scan").description(
2014
2026
  "Drive the AI fix-prompt autopilot loop locally \u2014 same flow as the /task-autopilot skill, run by the CLI binary"
2015
- ).option("--project <slugOrId>", "Restrict to one project (default: every visible project)").option("--max <n>", "Max submissions per project token", "50").option("--batch <n>", "Tickets per /prepare batch (1-10)", "5").option("--api-url <url>", "Override TASK_API_URL").option("--silent", "Suppress per-ticket progress chrome").action(async (opts) => {
2027
+ ).option(
2028
+ "--project <slugOrId>",
2029
+ "Restrict to one project (default: the linked project from .task/config.json, falling back to every visible project if the repo is not linked)"
2030
+ ).option(
2031
+ "--all-projects",
2032
+ "Override the linked-project default and scan every CLI-eligible project the admin token can see"
2033
+ ).option("--max <n>", "Max submissions per project token", "50").option("--batch <n>", "Tickets per /prepare batch (1-10)", "5").option("--api-url <url>", "Override TASK_API_URL").option("--silent", "Suppress per-ticket progress chrome").action(async (opts) => {
2016
2034
  await runScan(opts);
2017
2035
  });
2018
2036
  }
@@ -2034,10 +2052,26 @@ async function runScan(opts) {
2034
2052
  );
2035
2053
  }
2036
2054
  const localCfg = await readLocalConfig();
2037
- const apiUrl = (opts.apiUrl ?? process.env["TASK_API_URL"] ?? localCfg.api_url ?? "http://localhost:3400").replace(/\/$/, "");
2055
+ const linkedProject = await readProjectConfig(findRepoRoot());
2056
+ const apiUrl = (opts.apiUrl ?? process.env["TASK_API_URL"] ?? localCfg.api_url ?? linkedProject?.api_url ?? "http://localhost:3400").replace(/\/$/, "");
2038
2057
  const max = clampInt(opts.max, 1, 500, 50);
2039
2058
  const batchSize = clampInt(opts.batch, 1, 10, 5);
2040
2059
  const silent = !!opts.silent || localCfg.silent;
2060
+ if (opts.project && opts.allProjects) {
2061
+ throw new CliError(
2062
+ CLI_EXIT_CODES.MISCONFIGURATION,
2063
+ "--project and --all-projects are mutually exclusive"
2064
+ );
2065
+ }
2066
+ let projectFilter = null;
2067
+ let filterSource = null;
2068
+ if (opts.project) {
2069
+ projectFilter = opts.project;
2070
+ filterSource = "flag";
2071
+ } else if (linkedProject && !opts.allProjects) {
2072
+ projectFilter = linkedProject.project_id;
2073
+ filterSource = "link";
2074
+ }
2041
2075
  const api = new AutopilotApi({ apiUrl, apiKey, actorEmail });
2042
2076
  if (!silent) process.stdout.write(`${c.dim("Discovering eligible projects\u2026")}
2043
2077
  `);
@@ -2046,15 +2080,33 @@ async function runScan(opts) {
2046
2080
  process.stdout.write(c.dim("No CLI-eligible tickets across any visible project.\n"));
2047
2081
  return;
2048
2082
  }
2049
- const projects = opts.project ? all.filter(
2050
- (p) => p.project_id === opts.project || p.project_slug === opts.project || `${p.organisation_slug}/${p.project_slug}` === opts.project
2083
+ const projects = projectFilter ? all.filter(
2084
+ (p) => p.project_id === projectFilter || p.project_slug === projectFilter || `${p.organisation_slug}/${p.project_slug}` === projectFilter
2051
2085
  ) : all;
2052
2086
  if (projects.length === 0) {
2087
+ if (filterSource === "link" && linkedProject) {
2088
+ throw new CliError(
2089
+ CLI_EXIT_CODES.GENERIC_ERROR,
2090
+ `Linked project ${linkedProject.organisation_slug}/${linkedProject.project_slug} has no CLI-eligible tickets right now`,
2091
+ "Mark a ticket as CLI-eligible from the dashboard, or pass --all-projects to scan everything the admin token can see."
2092
+ );
2093
+ }
2053
2094
  throw new CliError(
2054
2095
  CLI_EXIT_CODES.GENERIC_ERROR,
2055
2096
  `Project "${opts.project}" not found among eligible projects`
2056
2097
  );
2057
2098
  }
2099
+ if (!silent && filterSource === "link" && linkedProject) {
2100
+ process.stdout.write(
2101
+ `${c.dim("Scanning linked project")} ${c.bold(`${linkedProject.organisation_slug}/${linkedProject.project_slug}`)}${c.dim(" \u2014 pass --all-projects to scan every visible project.")}
2102
+ `
2103
+ );
2104
+ } else if (!silent && filterSource === null && !linkedProject) {
2105
+ process.stdout.write(
2106
+ `${c.dim("Repo is not linked. Scanning every visible project \u2014 run")} ${c.cyan("task link")} ${c.dim("to scope future runs to one project.")}
2107
+ `
2108
+ );
2109
+ }
2058
2110
  const aggregates = [];
2059
2111
  const claudePath = localCfg.claude_path ?? void 0;
2060
2112
  let interrupted = false;
@@ -3293,7 +3345,7 @@ function checkBinary(name, command) {
3293
3345
  }
3294
3346
 
3295
3347
  // src/commands/version.ts
3296
- var CLI_VERSION = true ? "0.1.5" : "0.0.0-dev";
3348
+ var CLI_VERSION = true ? "0.1.7" : "0.0.0-dev";
3297
3349
  function registerVersion(program2) {
3298
3350
  program2.command("version").description("Print the CLI version").action(() => {
3299
3351
  process.stdout.write(CLI_VERSION + "\n");