squad-kit 0.6.1 → 0.7.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/CHANGELOG.md +14 -0
- package/dist/cli.js +244 -10
- package/dist/cli.js.map +1 -1
- package/dist/console-ui/assets/{index-Lxr-TdWe.js → index-gaFPpGMN.js} +129 -129
- package/dist/console-ui/index.html +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.7.0] — 2026-04-28
|
|
11
|
+
|
|
12
|
+
### What's new
|
|
13
|
+
|
|
14
|
+
- GitHub Issues works as the issue tracker: set owner/repo in config, PAT (or
|
|
15
|
+
`GITHUB_TOKEN` / `GITHUB_HOST`) in secrets, search and import like Jira or
|
|
16
|
+
Azure. Console Secrets page has GitHub host and token fields plus a
|
|
17
|
+
connectivity test; `squad doctor` probes the GitHub REST API.
|
|
18
|
+
|
|
19
|
+
### Breaking changes
|
|
20
|
+
|
|
21
|
+
- Linear is no longer a tracker type. Use GitHub Issues, Jira, or Azure, or
|
|
22
|
+
set tracker to `none`. Update `.squad/config.yaml` if you had `linear`.
|
|
23
|
+
|
|
10
24
|
## [0.6.1] — 2026-04-26
|
|
11
25
|
|
|
12
26
|
### Bug fixes
|
package/dist/cli.js
CHANGED
|
@@ -495,6 +495,10 @@ function mergeSecrets(base, patch) {
|
|
|
495
495
|
azure: {
|
|
496
496
|
...base.tracker?.azure ?? {},
|
|
497
497
|
...filterEmpty(patch.tracker?.azure ?? {})
|
|
498
|
+
},
|
|
499
|
+
github: {
|
|
500
|
+
...base.tracker?.github ?? {},
|
|
501
|
+
...filterEmpty(patch.tracker?.github ?? {})
|
|
498
502
|
}
|
|
499
503
|
}
|
|
500
504
|
};
|
|
@@ -768,6 +772,8 @@ function overlayTrackerEnv(base) {
|
|
|
768
772
|
const azOrg = process.env.AZURE_DEVOPS_ORG;
|
|
769
773
|
const azProj = process.env.AZURE_DEVOPS_PROJECT;
|
|
770
774
|
const azPat = process.env.AZURE_DEVOPS_PAT ?? process.env.SQUAD_TRACKER_API_KEY;
|
|
775
|
+
const ghHost = process.env.GITHUB_HOST;
|
|
776
|
+
const ghPat = process.env.GITHUB_TOKEN ?? process.env.SQUAD_TRACKER_API_KEY;
|
|
771
777
|
return {
|
|
772
778
|
...base,
|
|
773
779
|
tracker: {
|
|
@@ -780,6 +786,10 @@ function overlayTrackerEnv(base) {
|
|
|
780
786
|
organization: azOrg ?? base.tracker?.azure?.organization,
|
|
781
787
|
project: azProj ?? base.tracker?.azure?.project,
|
|
782
788
|
pat: azPat ?? base.tracker?.azure?.pat
|
|
789
|
+
},
|
|
790
|
+
github: {
|
|
791
|
+
host: ghHost ?? base.tracker?.github?.host,
|
|
792
|
+
pat: ghPat ?? base.tracker?.github?.pat
|
|
783
793
|
}
|
|
784
794
|
}
|
|
785
795
|
};
|
|
@@ -858,6 +868,27 @@ async function probeAzureConnectivity(secrets, config2) {
|
|
|
858
868
|
return { ok: false, detail: err.message };
|
|
859
869
|
}
|
|
860
870
|
}
|
|
871
|
+
async function probeGitHubConnectivity(secrets, _config) {
|
|
872
|
+
const gh = overlayTrackerEnv(secrets).tracker?.github ?? {};
|
|
873
|
+
const pat = gh.pat ?? "";
|
|
874
|
+
const rawHost = (gh.host ?? "api.github.com").replace(/^https?:\/\//i, "").replace(/\/+$/, "");
|
|
875
|
+
const apiPath = rawHost === "api.github.com" ? "" : "/api/v3";
|
|
876
|
+
const url = `https://${rawHost}${apiPath}/user`;
|
|
877
|
+
try {
|
|
878
|
+
const res = await fetch(url, {
|
|
879
|
+
headers: {
|
|
880
|
+
Authorization: `Bearer ${pat}`,
|
|
881
|
+
Accept: "application/vnd.github+json",
|
|
882
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
883
|
+
"User-Agent": "squad-kit"
|
|
884
|
+
}
|
|
885
|
+
});
|
|
886
|
+
if (res.ok) return { ok: true };
|
|
887
|
+
return { ok: false, status: res.status, detail: (await res.text()).slice(0, 200) };
|
|
888
|
+
} catch (err) {
|
|
889
|
+
return { ok: false, detail: err.message };
|
|
890
|
+
}
|
|
891
|
+
}
|
|
861
892
|
|
|
862
893
|
// src/commands/config/shared.ts
|
|
863
894
|
import { input, password } from "@inquirer/prompts";
|
|
@@ -1379,6 +1410,166 @@ function stripHtml(html) {
|
|
|
1379
1410
|
return out.trim();
|
|
1380
1411
|
}
|
|
1381
1412
|
|
|
1413
|
+
// src/tracker/github.ts
|
|
1414
|
+
var PUBLIC_HOST = "api.github.com";
|
|
1415
|
+
var ID_PREFIX_RE = /^[\w.-]+\/[\w.-]+#/;
|
|
1416
|
+
var GitHubClient = class {
|
|
1417
|
+
constructor(cfg) {
|
|
1418
|
+
this.cfg = cfg;
|
|
1419
|
+
if (!cfg.owner) throw new Error('GitHubClient: missing "owner".');
|
|
1420
|
+
if (!cfg.repo) throw new Error('GitHubClient: missing "repo".');
|
|
1421
|
+
if (!cfg.pat) throw new Error('GitHubClient: missing "pat".');
|
|
1422
|
+
const host = (cfg.host ?? PUBLIC_HOST).replace(/^https?:\/\//i, "").replace(/\/+$/, "");
|
|
1423
|
+
const apiPath = host === PUBLIC_HOST ? "" : "/api/v3";
|
|
1424
|
+
this.baseUrl = `https://${host}${apiPath}`;
|
|
1425
|
+
this.webBase = host === PUBLIC_HOST ? "https://github.com" : `https://${host}`;
|
|
1426
|
+
this.authHeader = `Bearer ${cfg.pat}`;
|
|
1427
|
+
}
|
|
1428
|
+
cfg;
|
|
1429
|
+
name = "github";
|
|
1430
|
+
authHeader;
|
|
1431
|
+
baseUrl;
|
|
1432
|
+
webBase;
|
|
1433
|
+
async fetchIssue(id) {
|
|
1434
|
+
const number = stripIdPrefix(id);
|
|
1435
|
+
const url = `${this.baseUrl}/repos/${encodeURIComponent(this.cfg.owner)}/${encodeURIComponent(
|
|
1436
|
+
this.cfg.repo
|
|
1437
|
+
)}/issues/${encodeURIComponent(number)}`;
|
|
1438
|
+
let res;
|
|
1439
|
+
try {
|
|
1440
|
+
res = await fetch(url, { headers: this.headers() });
|
|
1441
|
+
} catch (err) {
|
|
1442
|
+
throw new TrackerError(`GitHub fetch failed: ${err.message}`, "network");
|
|
1443
|
+
}
|
|
1444
|
+
if (!res.ok) throw this.mapHttpError(res, number);
|
|
1445
|
+
const body = await res.json();
|
|
1446
|
+
return this.toFetchResult(body);
|
|
1447
|
+
}
|
|
1448
|
+
async searchIssues(query, opts) {
|
|
1449
|
+
const limit = Math.min(50, Math.max(1, opts?.limit ?? 25));
|
|
1450
|
+
const q = query.trim();
|
|
1451
|
+
const repoPath = `${encodeURIComponent(this.cfg.owner)}/${encodeURIComponent(this.cfg.repo)}`;
|
|
1452
|
+
if (q.length === 0) {
|
|
1453
|
+
const url2 = `${this.baseUrl}/repos/${repoPath}/issues?state=all&sort=updated&direction=desc&per_page=${limit}`;
|
|
1454
|
+
let res2;
|
|
1455
|
+
try {
|
|
1456
|
+
res2 = await fetch(url2, { headers: this.headers() });
|
|
1457
|
+
} catch (err) {
|
|
1458
|
+
throw new TrackerError(`GitHub search failed: ${err.message}`, "network");
|
|
1459
|
+
}
|
|
1460
|
+
if (!res2.ok) throw this.mapHttpError(res2, "search");
|
|
1461
|
+
const body2 = await res2.json();
|
|
1462
|
+
return (body2 ?? []).map((it) => this.toSearchRow(it));
|
|
1463
|
+
}
|
|
1464
|
+
if (/^\d+$/.test(q) || ID_PREFIX_RE.test(q)) {
|
|
1465
|
+
try {
|
|
1466
|
+
const issue = await this.fetchIssue(q);
|
|
1467
|
+
return [
|
|
1468
|
+
{
|
|
1469
|
+
id: issue.id,
|
|
1470
|
+
title: issue.title,
|
|
1471
|
+
type: issue.type,
|
|
1472
|
+
status: issue.status,
|
|
1473
|
+
url: issue.url
|
|
1474
|
+
}
|
|
1475
|
+
];
|
|
1476
|
+
} catch (err) {
|
|
1477
|
+
if (err instanceof TrackerError && err.kind === "not-found") return [];
|
|
1478
|
+
throw err;
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
const searchQuery = `${q} repo:${this.cfg.owner}/${this.cfg.repo}`;
|
|
1482
|
+
const url = `${this.baseUrl}/search/issues?q=${encodeURIComponent(searchQuery)}&sort=updated&order=desc&per_page=${limit}`;
|
|
1483
|
+
let res;
|
|
1484
|
+
try {
|
|
1485
|
+
res = await fetch(url, { headers: this.headers() });
|
|
1486
|
+
} catch (err) {
|
|
1487
|
+
throw new TrackerError(`GitHub search failed: ${err.message}`, "network");
|
|
1488
|
+
}
|
|
1489
|
+
if (!res.ok) throw this.mapHttpError(res, "search");
|
|
1490
|
+
const body = await res.json();
|
|
1491
|
+
return (body.items ?? []).map((it) => this.toSearchRow(it));
|
|
1492
|
+
}
|
|
1493
|
+
async downloadAttachments(refs, targetDir, opts) {
|
|
1494
|
+
if (refs.length === 0) return [];
|
|
1495
|
+
return downloadAttachmentsWith(refs, targetDir, this.headers(), opts);
|
|
1496
|
+
}
|
|
1497
|
+
toFetchResult(body) {
|
|
1498
|
+
return {
|
|
1499
|
+
id: String(body.number ?? ""),
|
|
1500
|
+
title: body.title ?? "(no title)",
|
|
1501
|
+
description: body.body ?? "",
|
|
1502
|
+
acceptanceCriteria: "",
|
|
1503
|
+
url: body.html_url ?? `${this.webBase}/${this.cfg.owner}/${this.cfg.repo}/issues/${body.number ?? ""}`,
|
|
1504
|
+
labels: Array.isArray(body.labels) ? body.labels.map((l) => typeof l === "string" ? l : l.name ?? "").filter(Boolean) : [],
|
|
1505
|
+
type: body.pull_request ? "Pull Request" : "Issue",
|
|
1506
|
+
assignee: body.assignee?.login,
|
|
1507
|
+
status: body.state,
|
|
1508
|
+
attachments: [],
|
|
1509
|
+
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1510
|
+
};
|
|
1511
|
+
}
|
|
1512
|
+
toSearchRow(body) {
|
|
1513
|
+
return {
|
|
1514
|
+
id: String(body.number ?? ""),
|
|
1515
|
+
title: body.title ?? "(no title)",
|
|
1516
|
+
type: body.pull_request ? "Pull Request" : "Issue",
|
|
1517
|
+
status: body.state,
|
|
1518
|
+
url: body.html_url ?? `${this.webBase}/${this.cfg.owner}/${this.cfg.repo}/issues/${body.number ?? ""}`
|
|
1519
|
+
};
|
|
1520
|
+
}
|
|
1521
|
+
headers() {
|
|
1522
|
+
return {
|
|
1523
|
+
authorization: this.authHeader,
|
|
1524
|
+
accept: "application/vnd.github+json",
|
|
1525
|
+
"x-github-api-version": "2022-11-28",
|
|
1526
|
+
"user-agent": "squad-kit"
|
|
1527
|
+
};
|
|
1528
|
+
}
|
|
1529
|
+
mapHttpError(res, id) {
|
|
1530
|
+
const status = res.status;
|
|
1531
|
+
if (status === 401 || status === 403) {
|
|
1532
|
+
if (res.headers.get("x-ratelimit-remaining") === "0") {
|
|
1533
|
+
return new TrackerError(
|
|
1534
|
+
`GitHub rate limit hit (HTTP ${status}). Wait until the limit resets and retry.`,
|
|
1535
|
+
"rate-limited",
|
|
1536
|
+
status
|
|
1537
|
+
);
|
|
1538
|
+
}
|
|
1539
|
+
return new TrackerError(
|
|
1540
|
+
`GitHub authentication failed (HTTP ${status}). Check your PAT in .squad/secrets.yaml; it needs "repo" scope (or "Issues: read" for fine-grained tokens).`,
|
|
1541
|
+
"auth",
|
|
1542
|
+
status
|
|
1543
|
+
);
|
|
1544
|
+
}
|
|
1545
|
+
if (status === 404) {
|
|
1546
|
+
return new TrackerError(
|
|
1547
|
+
id === "search" ? `GitHub search failed (HTTP 404) for ${this.cfg.owner}/${this.cfg.repo}.` : `GitHub issue "${id}" not found in ${this.cfg.owner}/${this.cfg.repo} (HTTP 404). Check the id and tracker.workspace / tracker.project in .squad/config.yaml.`,
|
|
1548
|
+
"not-found",
|
|
1549
|
+
status
|
|
1550
|
+
);
|
|
1551
|
+
}
|
|
1552
|
+
if (status === 422) {
|
|
1553
|
+
return new TrackerError(
|
|
1554
|
+
`GitHub rejected the search query (HTTP 422). Try a simpler query or a bare issue number.`,
|
|
1555
|
+
"other",
|
|
1556
|
+
status
|
|
1557
|
+
);
|
|
1558
|
+
}
|
|
1559
|
+
if (status === 429) {
|
|
1560
|
+
return new TrackerError(`GitHub rate limit hit (HTTP 429). Wait a minute and retry.`, "rate-limited", status);
|
|
1561
|
+
}
|
|
1562
|
+
return new TrackerError(
|
|
1563
|
+
id === "search" ? `GitHub search failed (HTTP ${status}).` : `GitHub request failed (HTTP ${status}).`,
|
|
1564
|
+
"other",
|
|
1565
|
+
status
|
|
1566
|
+
);
|
|
1567
|
+
}
|
|
1568
|
+
};
|
|
1569
|
+
function stripIdPrefix(id) {
|
|
1570
|
+
return id.replace(ID_PREFIX_RE, "");
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1382
1573
|
// src/tracker/adf.ts
|
|
1383
1574
|
var BLOCK_TYPES = /* @__PURE__ */ new Set([
|
|
1384
1575
|
"paragraph",
|
|
@@ -1565,29 +1756,44 @@ function clientFor(config2, secrets) {
|
|
|
1565
1756
|
}
|
|
1566
1757
|
return { client: new AzureDevOpsClient({ organization, project, pat: az.pat }) };
|
|
1567
1758
|
}
|
|
1759
|
+
case "github": {
|
|
1760
|
+
const gh = secrets.tracker?.github ?? {};
|
|
1761
|
+
const owner = config2.tracker.workspace;
|
|
1762
|
+
const repo = config2.tracker.project;
|
|
1763
|
+
if (!owner || !repo || !gh.pat) {
|
|
1764
|
+
return {
|
|
1765
|
+
error: {
|
|
1766
|
+
kind: "missing-credentials",
|
|
1767
|
+
message: "GitHub credentials are incomplete.",
|
|
1768
|
+
detail: "Set tracker.workspace (owner) and tracker.project (repo) in .squad/config.yaml, then run `squad config set tracker` to enter the PAT, or set GITHUB_TOKEN (and optionally GITHUB_HOST for GHES). Run `squad doctor` to verify the connection."
|
|
1769
|
+
}
|
|
1770
|
+
};
|
|
1771
|
+
}
|
|
1772
|
+
return { client: new GitHubClient({ owner, repo, pat: gh.pat, host: gh.host }) };
|
|
1773
|
+
}
|
|
1568
1774
|
case "none":
|
|
1569
1775
|
default:
|
|
1570
1776
|
return {
|
|
1571
1777
|
error: {
|
|
1572
1778
|
kind: "unsupported-tracker",
|
|
1573
1779
|
message: `Tracker type "${config2.tracker.type}" does not support auto-fetch in 0.2.0.`,
|
|
1574
|
-
detail: "Run `squad config set tracker` to use jira or
|
|
1780
|
+
detail: "Run `squad config set tracker` to use jira, azure, or github for fetch, or pass `--no-fetch` on new-story. Run `squad doctor` to review tracker setup."
|
|
1575
1781
|
}
|
|
1576
1782
|
};
|
|
1577
1783
|
}
|
|
1578
1784
|
}
|
|
1579
1785
|
|
|
1580
1786
|
// src/commands/config/set-tracker.ts
|
|
1581
|
-
var TYPES = ["none", "github", "
|
|
1787
|
+
var TYPES = ["none", "github", "jira", "azure"];
|
|
1582
1788
|
function parseType(t) {
|
|
1583
1789
|
if (!t) {
|
|
1584
1790
|
throw new Error(
|
|
1585
|
-
"Pass --type (none|jira|azure|github
|
|
1791
|
+
"Pass --type (none|jira|azure|github) with --yes, or run `squad config set tracker` without --yes in a TTY to pick a type."
|
|
1586
1792
|
);
|
|
1587
1793
|
}
|
|
1588
1794
|
if (!TYPES.includes(t)) {
|
|
1589
1795
|
throw new Error(
|
|
1590
|
-
`Invalid --type "${t}". Use none | jira | azure | github
|
|
1796
|
+
`Invalid --type "${t}". Use none | jira | azure | github, or run \`squad config set tracker\` interactively.`
|
|
1591
1797
|
);
|
|
1592
1798
|
}
|
|
1593
1799
|
return t;
|
|
@@ -1620,7 +1826,6 @@ async function runConfigSetTracker(opts = {}) {
|
|
|
1620
1826
|
choices: [
|
|
1621
1827
|
{ name: "None", value: "none" },
|
|
1622
1828
|
{ name: "GitHub Issues", value: "github" },
|
|
1623
|
-
{ name: "Linear", value: "linear" },
|
|
1624
1829
|
{ name: "Jira", value: "jira" },
|
|
1625
1830
|
{ name: "Azure DevOps", value: "azure" }
|
|
1626
1831
|
],
|
|
@@ -1630,7 +1835,7 @@ async function runConfigSetTracker(opts = {}) {
|
|
|
1630
1835
|
let nextTracker;
|
|
1631
1836
|
if (type === "none") {
|
|
1632
1837
|
nextTracker = { type: "none" };
|
|
1633
|
-
} else if (type === "github"
|
|
1838
|
+
} else if (type === "github") {
|
|
1634
1839
|
nextTracker = { ...config2.tracker, type };
|
|
1635
1840
|
} else if (type === "jira") {
|
|
1636
1841
|
if (interactive) {
|
|
@@ -1864,7 +2069,6 @@ async function runInit(opts) {
|
|
|
1864
2069
|
choices: [
|
|
1865
2070
|
{ name: "None", value: "none" },
|
|
1866
2071
|
{ name: "GitHub Issues", value: "github" },
|
|
1867
|
-
{ name: "Linear", value: "linear" },
|
|
1868
2072
|
{ name: "Jira", value: "jira" },
|
|
1869
2073
|
{ name: "Azure DevOps", value: "azure" }
|
|
1870
2074
|
],
|
|
@@ -2210,7 +2414,6 @@ function readPlanMetadata(planFileAbsPath) {
|
|
|
2210
2414
|
// src/core/tracker.ts
|
|
2211
2415
|
var VALIDATORS = {
|
|
2212
2416
|
github: /^(?:[\w.-]+\/[\w.-]+#)?\d+$/,
|
|
2213
|
-
linear: /^[A-Z][A-Z0-9]+-\d+$/i,
|
|
2214
2417
|
jira: /^[A-Z][A-Z0-9]+-\d+$/,
|
|
2215
2418
|
azure: /^\d+$/
|
|
2216
2419
|
};
|
|
@@ -5403,6 +5606,14 @@ async function checkTrackerConfig(_paths, ctx) {
|
|
|
5403
5606
|
detail: "Azure DevOps requires tracker.workspace (organization) and tracker.project"
|
|
5404
5607
|
};
|
|
5405
5608
|
}
|
|
5609
|
+
if (t.type === "github" && (!t.workspace?.trim() || !t.project?.trim())) {
|
|
5610
|
+
return {
|
|
5611
|
+
id: "tracker-config",
|
|
5612
|
+
name: "tracker configuration",
|
|
5613
|
+
status: "fail",
|
|
5614
|
+
detail: "GitHub requires tracker.workspace (owner) and tracker.project (repo)"
|
|
5615
|
+
};
|
|
5616
|
+
}
|
|
5406
5617
|
return { id: "tracker-config", name: "tracker configuration", status: "ok" };
|
|
5407
5618
|
}
|
|
5408
5619
|
function formatClientError(err) {
|
|
@@ -5466,6 +5677,16 @@ async function checkTrackerConnectivity(paths, ctx) {
|
|
|
5466
5677
|
detail: r.status !== void 0 ? `HTTP ${r.status}` : r.detail ?? "request failed"
|
|
5467
5678
|
};
|
|
5468
5679
|
}
|
|
5680
|
+
if (client.name === "github") {
|
|
5681
|
+
const r = await probeGitHubConnectivity(secrets, ctx.config);
|
|
5682
|
+
if (r.ok) return { id: "tracker-live", name: "tracker connectivity", status: "ok", detail: "GitHub REST" };
|
|
5683
|
+
return {
|
|
5684
|
+
id: "tracker-live",
|
|
5685
|
+
name: "tracker connectivity",
|
|
5686
|
+
status: "fail",
|
|
5687
|
+
detail: r.status !== void 0 ? `HTTP ${r.status}` : r.detail ?? "request failed"
|
|
5688
|
+
};
|
|
5689
|
+
}
|
|
5469
5690
|
return {
|
|
5470
5691
|
id: "tracker-live",
|
|
5471
5692
|
name: "tracker connectivity",
|
|
@@ -6440,6 +6661,10 @@ function mountSecretsApi(app, opts) {
|
|
|
6440
6661
|
organization: s.tracker?.azure?.organization ?? null,
|
|
6441
6662
|
project: s.tracker?.azure?.project ?? null,
|
|
6442
6663
|
pat: maskToken(s.tracker?.azure?.pat)
|
|
6664
|
+
},
|
|
6665
|
+
github: {
|
|
6666
|
+
host: s.tracker?.github?.host ?? null,
|
|
6667
|
+
pat: maskToken(s.tracker?.github?.pat)
|
|
6443
6668
|
}
|
|
6444
6669
|
}
|
|
6445
6670
|
});
|
|
@@ -6460,6 +6685,10 @@ function mountSecretsApi(app, opts) {
|
|
|
6460
6685
|
organization: z5.string().optional(),
|
|
6461
6686
|
project: z5.string().optional(),
|
|
6462
6687
|
pat: z5.string().optional()
|
|
6688
|
+
}).optional(),
|
|
6689
|
+
github: z5.object({
|
|
6690
|
+
host: z5.string().optional(),
|
|
6691
|
+
pat: z5.string().optional()
|
|
6463
6692
|
}).optional()
|
|
6464
6693
|
}).optional()
|
|
6465
6694
|
});
|
|
@@ -6491,6 +6720,11 @@ function mountSecretsApi(app, opts) {
|
|
|
6491
6720
|
const s = loadSecrets(opts.paths.secretsFile);
|
|
6492
6721
|
return c.json(await probeAzureConnectivity(s, cfg));
|
|
6493
6722
|
});
|
|
6723
|
+
app.post("/api/secrets/test/github", async (c) => {
|
|
6724
|
+
const cfg = loadConfig(opts.paths.configFile);
|
|
6725
|
+
const s = loadSecrets(opts.paths.secretsFile);
|
|
6726
|
+
return c.json(await probeGitHubConnectivity(s, cfg));
|
|
6727
|
+
});
|
|
6494
6728
|
}
|
|
6495
6729
|
|
|
6496
6730
|
// src/console/api/tracker.ts
|
|
@@ -7225,7 +7459,7 @@ async function runRmPlan(planPathOrSequence, opts = {}) {
|
|
|
7225
7459
|
// src/cli.ts
|
|
7226
7460
|
var program = new Command();
|
|
7227
7461
|
program.name("squad").description("Plan once, execute cheap. A 3-step SDD workflow CLI.").version("0.6.0");
|
|
7228
|
-
program.command("init").description("Bootstrap .squad/ in the current directory").option("--agents <list>", "Comma-separated agent list: claude-code,cursor,copilot,gemini").option("--tracker <type>", "Tracker type: none|github|
|
|
7462
|
+
program.command("init").description("Bootstrap .squad/ in the current directory").option("--agents <list>", "Comma-separated agent list: claude-code,cursor,copilot,gemini").option("--tracker <type>", "Tracker type: none|github|jira|azure").option(
|
|
7229
7463
|
"--tracker-workspace <hostOrOrg>",
|
|
7230
7464
|
"Jira host or Azure org (non-interactive default; also written to config for jira/azure)"
|
|
7231
7465
|
).option("--tracker-project <name>", "Azure project name (non-interactive; written to config when set)").option("--name <name>", "Project name").option("--language <lang>", "Primary language").option("--force", "Overwrite existing files", false).option("-y, --yes", "Accept defaults (non-interactive)", false).option(
|
|
@@ -7273,7 +7507,7 @@ var config = program.command("config").description("Inspect and change .squad/ s
|
|
|
7273
7507
|
config.command("show").description("Show the current .squad/config.yaml and .squad/secrets.yaml state (secrets masked)").option("--json", "Emit as JSON to stdout (secrets still masked)", false).action(wrap(runConfigShow));
|
|
7274
7508
|
var set = config.command("set").description("Interactively change a section");
|
|
7275
7509
|
set.command("planner").description("Set or change the planner provider, model override, and credentials").option("--provider <name>", "Skip the provider prompt (anthropic|openai|google)").option("-y, --yes", "Fail fast instead of prompting for missing values", false).action(wrap(runConfigSetPlanner));
|
|
7276
|
-
set.command("tracker").description("Set or change the tracker type, workspace, and credentials").option("--type <name>", "Skip the tracker-type prompt (none|jira|azure|github
|
|
7510
|
+
set.command("tracker").description("Set or change the tracker type, workspace, and credentials").option("--type <name>", "Skip the tracker-type prompt (none|jira|azure|github)").option("-y, --yes", "Fail fast instead of prompting for missing values", false).action(wrap(runConfigSetTracker));
|
|
7277
7511
|
var unset = config.command("unset").description("Disable or clear a section");
|
|
7278
7512
|
unset.command("planner").description("Disable the direct planner (keeps provider credentials unless --remove-credentials)").option("--remove-credentials", "Also delete planner keys from .squad/secrets.yaml", false).option("-y, --yes", "Skip the confirmation prompt", false).action(wrap(runConfigUnsetPlanner));
|
|
7279
7513
|
unset.command("tracker").description('Set tracker.type back to "none" (keeps credentials unless --remove-credentials)').option("--remove-credentials", "Also delete tracker credentials from .squad/secrets.yaml", false).option("-y, --yes", "Skip the confirmation prompt", false).action(wrap(runConfigUnsetTracker));
|