@attalabs/vinaya 0.18.0 → 0.19.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/aeg-root/contracts/architect-planner.md +72 -0
- package/aeg-root/roles/architect.md +91 -0
- package/aeg-root/roles/planner.md +14 -15
- package/aeg-root/tranche-model.md +9 -1
- package/dist/checks/bin/check-body-bare-digits.js +60 -13
- package/dist/checks/bin/check-branch-topology.js +57 -12
- package/dist/checks/bin/check-brief-shape.js +57 -12
- package/dist/checks/bin/check-closes-n.js +57 -12
- package/dist/checks/bin/check-coherence.js +60 -13
- package/dist/checks/bin/check-dead-branch-push.js +57 -12
- package/dist/checks/bin/check-dispatch-readiness.js +127 -40
- package/dist/checks/bin/check-doc-coverage-push.js +60 -13
- package/dist/checks/bin/check-doc-coverage.js +60 -13
- package/dist/checks/bin/check-evidence-fresh.js +57 -12
- package/dist/checks/bin/check-first-push-dispatch.js +128 -41
- package/dist/checks/bin/check-issue-assignment.js +57 -12
- package/dist/checks/bin/check-no-disk-state.js +57 -12
- package/dist/checks/bin/check-reader-resolvable-prose.js +57 -12
- package/dist/checks/bin/check-registry-gates.js +57 -12
- package/dist/checks/bin/check-review-gate.js +60 -13
- package/dist/checks/bin/check-single-plan-pr.js +57 -12
- package/dist/checks/bin/check-test-plan.js +57 -12
- package/dist/index.js +663 -37
- package/package.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/BUILD_ID +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/build-manifest.json +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/prerender-manifest.json +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.html +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.rsc +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/api/coherence/route.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/[root-of-the-server]__0e95dv5._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/1q96_modules_@clerk_nextjs_dist_esm_app-router_client_keyless-creator-reader_0lom2js.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__029-1ch._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0q56ohl._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0z47hfl._.js → [root-of-the-server]__0ulzsom._.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1_ojzp1._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1d_8nm4._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1zkwtx8._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__210ehg9._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_00yjcv1._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0rix02i._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_18-d2be._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_1fqw88f._.js +5 -5
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_1gw6vc9._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/node_modules_1vo08dj._.js +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/middleware-build-manifest.js +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/server/pages/500.html +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.json +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{2myi4phnshkfw.js → 2r36w820aqwb9.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{415k4k1rf3swg.js → 2xoclb4g7d9n7.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{3z3a3gb6he23i.js → 3ocvtlhgckh81.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/package.json +2 -2
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{8tXGbArNoU7_MriIVYvN0 → RISz5nirLr1mUfMqzSaFS}/_buildManifest.js +0 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{8tXGbArNoU7_MriIVYvN0 → RISz5nirLr1mUfMqzSaFS}/_clientMiddlewareManifest.js +0 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{8tXGbArNoU7_MriIVYvN0 → RISz5nirLr1mUfMqzSaFS}/_ssgManifest.js +0 -0
|
@@ -275,6 +275,9 @@ function issueListByLabelArgs(owner, repo, label) {
|
|
|
275
275
|
"200"
|
|
276
276
|
];
|
|
277
277
|
}
|
|
278
|
+
function ghIssueListByLabel(owner, repo, label) {
|
|
279
|
+
return JSON.parse(run(issueListByLabelArgs(owner, repo, label)));
|
|
280
|
+
}
|
|
278
281
|
async function ghIssueListByLabelAsync(owner, repo, label) {
|
|
279
282
|
return JSON.parse(await runAsync(issueListByLabelArgs(owner, repo, label)));
|
|
280
283
|
}
|
|
@@ -290,18 +293,6 @@ async function ghIssueListByAnyLabelAsync(owner, repo, labels) {
|
|
|
290
293
|
return dedupeByNumber(perLabel.flat());
|
|
291
294
|
}
|
|
292
295
|
|
|
293
|
-
// ../../packages/aeg-forge-state/src/fetch-milestone.ts
|
|
294
|
-
function findMilestoneForSlug(owner, repo, slug) {
|
|
295
|
-
const milestones = ghApiGet(`repos/${owner}/${repo}/milestones?state=all&per_page=100`);
|
|
296
|
-
const match = milestones.find((m) => m.title === slug);
|
|
297
|
-
if (!match)
|
|
298
|
-
return null;
|
|
299
|
-
return {
|
|
300
|
-
goal: match.description ?? "",
|
|
301
|
-
lifecycle: match.state === "closed" ? "complete" : "active"
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
|
|
305
296
|
// ../../packages/aeg-forge-state/src/labels.ts
|
|
306
297
|
var LABELS = [
|
|
307
298
|
{
|
|
@@ -544,6 +535,60 @@ function resolveTaskIssueRef(title, labels) {
|
|
|
544
535
|
return { trancheSlug, taskId };
|
|
545
536
|
}
|
|
546
537
|
|
|
538
|
+
// ../../packages/aeg-forge-state/src/fetch-milestone.ts
|
|
539
|
+
var INTENTS_HEADING = /^#{1,6}\s*Tranche intents\s*$/im;
|
|
540
|
+
var NEXT_HEADING = /^#{1,6}\s+\S/m;
|
|
541
|
+
var INTENT_BULLET = /^-\s+([a-z0-9][a-z0-9-]*)\s*:\s*(.+)$/i;
|
|
542
|
+
function intentGoalForSlug(description, slug) {
|
|
543
|
+
const text = stripCode(description, { inlineSpans: "keep" });
|
|
544
|
+
const start = text.match(INTENTS_HEADING);
|
|
545
|
+
if (!start || start.index === undefined)
|
|
546
|
+
return "";
|
|
547
|
+
const rest = text.slice(start.index + start[0].length);
|
|
548
|
+
const next = rest.match(NEXT_HEADING);
|
|
549
|
+
const section = rest.slice(0, next && next.index !== undefined ? next.index : rest.length);
|
|
550
|
+
for (const line of section.split(`
|
|
551
|
+
`)) {
|
|
552
|
+
const trimmed = line.trim();
|
|
553
|
+
if (trimmed.length === 0)
|
|
554
|
+
continue;
|
|
555
|
+
const m = trimmed.match(INTENT_BULLET);
|
|
556
|
+
if (m && (m[1] ?? "").toLowerCase() === slug.toLowerCase())
|
|
557
|
+
return (m[2] ?? "").trim();
|
|
558
|
+
}
|
|
559
|
+
return "";
|
|
560
|
+
}
|
|
561
|
+
function matchesLegacyMilestone(milestones, slug) {
|
|
562
|
+
return milestones.find((m) => m.title === slug) ?? null;
|
|
563
|
+
}
|
|
564
|
+
function factsFromLegacyMilestone(milestone) {
|
|
565
|
+
return {
|
|
566
|
+
goal: milestone.description ?? "",
|
|
567
|
+
lifecycle: milestone.state === "closed" ? "complete" : "active"
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
function lifecycleFromIssues(issues) {
|
|
571
|
+
if (issues.length === 0)
|
|
572
|
+
return "planned";
|
|
573
|
+
return issues.some((i) => i.state === "OPEN") ? "active" : "complete";
|
|
574
|
+
}
|
|
575
|
+
function goalFromMilestones(milestones, slug) {
|
|
576
|
+
for (const m of milestones) {
|
|
577
|
+
const goal = intentGoalForSlug(m.description ?? "", slug);
|
|
578
|
+
if (goal)
|
|
579
|
+
return goal;
|
|
580
|
+
}
|
|
581
|
+
return "";
|
|
582
|
+
}
|
|
583
|
+
function findMilestoneForSlug(owner, repo, slug) {
|
|
584
|
+
const milestones = ghApiGet(`repos/${owner}/${repo}/milestones?state=all&per_page=100`);
|
|
585
|
+
const legacy = matchesLegacyMilestone(milestones, slug);
|
|
586
|
+
if (legacy)
|
|
587
|
+
return factsFromLegacyMilestone(legacy);
|
|
588
|
+
const issues = ghIssueListByLabel(owner, repo, trancheLabel(slug));
|
|
589
|
+
return { goal: goalFromMilestones(milestones, slug), lifecycle: lifecycleFromIssues(issues) };
|
|
590
|
+
}
|
|
591
|
+
|
|
547
592
|
// ../../packages/aeg-forge-state/src/derive-from-forge.ts
|
|
548
593
|
function trancheFromIssues(slug, issues, known) {
|
|
549
594
|
return {
|
|
@@ -275,6 +275,9 @@ function issueListByLabelArgs(owner, repo, label) {
|
|
|
275
275
|
"200"
|
|
276
276
|
];
|
|
277
277
|
}
|
|
278
|
+
function ghIssueListByLabel(owner, repo, label) {
|
|
279
|
+
return JSON.parse(run(issueListByLabelArgs(owner, repo, label)));
|
|
280
|
+
}
|
|
278
281
|
async function ghIssueListByLabelAsync(owner, repo, label) {
|
|
279
282
|
return JSON.parse(await runAsync(issueListByLabelArgs(owner, repo, label)));
|
|
280
283
|
}
|
|
@@ -290,18 +293,6 @@ async function ghIssueListByAnyLabelAsync(owner, repo, labels) {
|
|
|
290
293
|
return dedupeByNumber(perLabel.flat());
|
|
291
294
|
}
|
|
292
295
|
|
|
293
|
-
// ../../packages/aeg-forge-state/src/fetch-milestone.ts
|
|
294
|
-
function findMilestoneForSlug(owner, repo, slug) {
|
|
295
|
-
const milestones = ghApiGet(`repos/${owner}/${repo}/milestones?state=all&per_page=100`);
|
|
296
|
-
const match = milestones.find((m) => m.title === slug);
|
|
297
|
-
if (!match)
|
|
298
|
-
return null;
|
|
299
|
-
return {
|
|
300
|
-
goal: match.description ?? "",
|
|
301
|
-
lifecycle: match.state === "closed" ? "complete" : "active"
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
|
|
305
296
|
// ../../packages/aeg-forge-state/src/labels.ts
|
|
306
297
|
var LABELS = [
|
|
307
298
|
{
|
|
@@ -544,6 +535,60 @@ function resolveTaskIssueRef(title, labels) {
|
|
|
544
535
|
return { trancheSlug, taskId };
|
|
545
536
|
}
|
|
546
537
|
|
|
538
|
+
// ../../packages/aeg-forge-state/src/fetch-milestone.ts
|
|
539
|
+
var INTENTS_HEADING = /^#{1,6}\s*Tranche intents\s*$/im;
|
|
540
|
+
var NEXT_HEADING = /^#{1,6}\s+\S/m;
|
|
541
|
+
var INTENT_BULLET = /^-\s+([a-z0-9][a-z0-9-]*)\s*:\s*(.+)$/i;
|
|
542
|
+
function intentGoalForSlug(description, slug) {
|
|
543
|
+
const text = stripCode(description, { inlineSpans: "keep" });
|
|
544
|
+
const start = text.match(INTENTS_HEADING);
|
|
545
|
+
if (!start || start.index === undefined)
|
|
546
|
+
return "";
|
|
547
|
+
const rest = text.slice(start.index + start[0].length);
|
|
548
|
+
const next = rest.match(NEXT_HEADING);
|
|
549
|
+
const section = rest.slice(0, next && next.index !== undefined ? next.index : rest.length);
|
|
550
|
+
for (const line of section.split(`
|
|
551
|
+
`)) {
|
|
552
|
+
const trimmed = line.trim();
|
|
553
|
+
if (trimmed.length === 0)
|
|
554
|
+
continue;
|
|
555
|
+
const m = trimmed.match(INTENT_BULLET);
|
|
556
|
+
if (m && (m[1] ?? "").toLowerCase() === slug.toLowerCase())
|
|
557
|
+
return (m[2] ?? "").trim();
|
|
558
|
+
}
|
|
559
|
+
return "";
|
|
560
|
+
}
|
|
561
|
+
function matchesLegacyMilestone(milestones, slug) {
|
|
562
|
+
return milestones.find((m) => m.title === slug) ?? null;
|
|
563
|
+
}
|
|
564
|
+
function factsFromLegacyMilestone(milestone) {
|
|
565
|
+
return {
|
|
566
|
+
goal: milestone.description ?? "",
|
|
567
|
+
lifecycle: milestone.state === "closed" ? "complete" : "active"
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
function lifecycleFromIssues(issues) {
|
|
571
|
+
if (issues.length === 0)
|
|
572
|
+
return "planned";
|
|
573
|
+
return issues.some((i) => i.state === "OPEN") ? "active" : "complete";
|
|
574
|
+
}
|
|
575
|
+
function goalFromMilestones(milestones, slug) {
|
|
576
|
+
for (const m of milestones) {
|
|
577
|
+
const goal = intentGoalForSlug(m.description ?? "", slug);
|
|
578
|
+
if (goal)
|
|
579
|
+
return goal;
|
|
580
|
+
}
|
|
581
|
+
return "";
|
|
582
|
+
}
|
|
583
|
+
function findMilestoneForSlug(owner, repo, slug) {
|
|
584
|
+
const milestones = ghApiGet(`repos/${owner}/${repo}/milestones?state=all&per_page=100`);
|
|
585
|
+
const legacy = matchesLegacyMilestone(milestones, slug);
|
|
586
|
+
if (legacy)
|
|
587
|
+
return factsFromLegacyMilestone(legacy);
|
|
588
|
+
const issues = ghIssueListByLabel(owner, repo, trancheLabel(slug));
|
|
589
|
+
return { goal: goalFromMilestones(milestones, slug), lifecycle: lifecycleFromIssues(issues) };
|
|
590
|
+
}
|
|
591
|
+
|
|
547
592
|
// ../../packages/aeg-forge-state/src/derive-from-forge.ts
|
|
548
593
|
function trancheFromIssues(slug, issues, known) {
|
|
549
594
|
return {
|
|
@@ -273,6 +273,9 @@ function issueListByLabelArgs(owner, repo, label) {
|
|
|
273
273
|
"200"
|
|
274
274
|
];
|
|
275
275
|
}
|
|
276
|
+
function ghIssueListByLabel(owner, repo, label) {
|
|
277
|
+
return JSON.parse(run(issueListByLabelArgs(owner, repo, label)));
|
|
278
|
+
}
|
|
276
279
|
async function ghIssueListByLabelAsync(owner, repo, label) {
|
|
277
280
|
return JSON.parse(await runAsync(issueListByLabelArgs(owner, repo, label)));
|
|
278
281
|
}
|
|
@@ -288,18 +291,6 @@ async function ghIssueListByAnyLabelAsync(owner, repo, labels) {
|
|
|
288
291
|
return dedupeByNumber(perLabel.flat());
|
|
289
292
|
}
|
|
290
293
|
|
|
291
|
-
// ../../packages/aeg-forge-state/src/fetch-milestone.ts
|
|
292
|
-
function findMilestoneForSlug(owner, repo, slug) {
|
|
293
|
-
const milestones = ghApiGet(`repos/${owner}/${repo}/milestones?state=all&per_page=100`);
|
|
294
|
-
const match = milestones.find((m) => m.title === slug);
|
|
295
|
-
if (!match)
|
|
296
|
-
return null;
|
|
297
|
-
return {
|
|
298
|
-
goal: match.description ?? "",
|
|
299
|
-
lifecycle: match.state === "closed" ? "complete" : "active"
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
|
|
303
294
|
// ../../packages/aeg-forge-state/src/labels.ts
|
|
304
295
|
var LABELS = [
|
|
305
296
|
{
|
|
@@ -542,6 +533,60 @@ function resolveTaskIssueRef(title, labels) {
|
|
|
542
533
|
return { trancheSlug, taskId };
|
|
543
534
|
}
|
|
544
535
|
|
|
536
|
+
// ../../packages/aeg-forge-state/src/fetch-milestone.ts
|
|
537
|
+
var INTENTS_HEADING = /^#{1,6}\s*Tranche intents\s*$/im;
|
|
538
|
+
var NEXT_HEADING = /^#{1,6}\s+\S/m;
|
|
539
|
+
var INTENT_BULLET = /^-\s+([a-z0-9][a-z0-9-]*)\s*:\s*(.+)$/i;
|
|
540
|
+
function intentGoalForSlug(description, slug) {
|
|
541
|
+
const text = stripCode(description, { inlineSpans: "keep" });
|
|
542
|
+
const start = text.match(INTENTS_HEADING);
|
|
543
|
+
if (!start || start.index === undefined)
|
|
544
|
+
return "";
|
|
545
|
+
const rest = text.slice(start.index + start[0].length);
|
|
546
|
+
const next = rest.match(NEXT_HEADING);
|
|
547
|
+
const section = rest.slice(0, next && next.index !== undefined ? next.index : rest.length);
|
|
548
|
+
for (const line of section.split(`
|
|
549
|
+
`)) {
|
|
550
|
+
const trimmed = line.trim();
|
|
551
|
+
if (trimmed.length === 0)
|
|
552
|
+
continue;
|
|
553
|
+
const m = trimmed.match(INTENT_BULLET);
|
|
554
|
+
if (m && (m[1] ?? "").toLowerCase() === slug.toLowerCase())
|
|
555
|
+
return (m[2] ?? "").trim();
|
|
556
|
+
}
|
|
557
|
+
return "";
|
|
558
|
+
}
|
|
559
|
+
function matchesLegacyMilestone(milestones, slug) {
|
|
560
|
+
return milestones.find((m) => m.title === slug) ?? null;
|
|
561
|
+
}
|
|
562
|
+
function factsFromLegacyMilestone(milestone) {
|
|
563
|
+
return {
|
|
564
|
+
goal: milestone.description ?? "",
|
|
565
|
+
lifecycle: milestone.state === "closed" ? "complete" : "active"
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
function lifecycleFromIssues(issues) {
|
|
569
|
+
if (issues.length === 0)
|
|
570
|
+
return "planned";
|
|
571
|
+
return issues.some((i) => i.state === "OPEN") ? "active" : "complete";
|
|
572
|
+
}
|
|
573
|
+
function goalFromMilestones(milestones, slug) {
|
|
574
|
+
for (const m of milestones) {
|
|
575
|
+
const goal = intentGoalForSlug(m.description ?? "", slug);
|
|
576
|
+
if (goal)
|
|
577
|
+
return goal;
|
|
578
|
+
}
|
|
579
|
+
return "";
|
|
580
|
+
}
|
|
581
|
+
function findMilestoneForSlug(owner, repo, slug) {
|
|
582
|
+
const milestones = ghApiGet(`repos/${owner}/${repo}/milestones?state=all&per_page=100`);
|
|
583
|
+
const legacy = matchesLegacyMilestone(milestones, slug);
|
|
584
|
+
if (legacy)
|
|
585
|
+
return factsFromLegacyMilestone(legacy);
|
|
586
|
+
const issues = ghIssueListByLabel(owner, repo, trancheLabel(slug));
|
|
587
|
+
return { goal: goalFromMilestones(milestones, slug), lifecycle: lifecycleFromIssues(issues) };
|
|
588
|
+
}
|
|
589
|
+
|
|
545
590
|
// ../../packages/aeg-forge-state/src/derive-from-forge.ts
|
|
546
591
|
function trancheFromIssues(slug, issues, known) {
|
|
547
592
|
return {
|
|
@@ -3180,7 +3225,8 @@ var BRIEF_BUILTINS = [
|
|
|
3180
3225
|
"for",
|
|
3181
3226
|
"closesN",
|
|
3182
3227
|
"premiseCoverage",
|
|
3183
|
-
"issueRationale"
|
|
3228
|
+
"issueRationale",
|
|
3229
|
+
"milestoneShape"
|
|
3184
3230
|
];
|
|
3185
3231
|
var BriefSectionSchema = z.union([
|
|
3186
3232
|
z.object({ builtin: z.enum(BRIEF_BUILTINS) }),
|
|
@@ -3191,6 +3237,7 @@ var BriefSectionSchema = z.union([
|
|
|
3191
3237
|
var BriefSchemaSchema = z.object({
|
|
3192
3238
|
pr: z.object({ sections: z.array(BriefSectionSchema) }).optional(),
|
|
3193
3239
|
issue: z.object({ sections: z.array(BriefSectionSchema) }).optional(),
|
|
3240
|
+
milestone: z.object({ sections: z.array(BriefSectionSchema) }).optional(),
|
|
3194
3241
|
ack: z.array(z.enum(BRIEF_BUILTINS)).optional()
|
|
3195
3242
|
});
|
|
3196
3243
|
function isSafeRepoRelPath(p) {
|
|
@@ -273,6 +273,9 @@ function issueListByLabelArgs(owner, repo, label) {
|
|
|
273
273
|
"200"
|
|
274
274
|
];
|
|
275
275
|
}
|
|
276
|
+
function ghIssueListByLabel(owner, repo, label) {
|
|
277
|
+
return JSON.parse(run(issueListByLabelArgs(owner, repo, label)));
|
|
278
|
+
}
|
|
276
279
|
async function ghIssueListByLabelAsync(owner, repo, label) {
|
|
277
280
|
return JSON.parse(await runAsync(issueListByLabelArgs(owner, repo, label)));
|
|
278
281
|
}
|
|
@@ -288,18 +291,6 @@ async function ghIssueListByAnyLabelAsync(owner, repo, labels) {
|
|
|
288
291
|
return dedupeByNumber(perLabel.flat());
|
|
289
292
|
}
|
|
290
293
|
|
|
291
|
-
// ../../packages/aeg-forge-state/src/fetch-milestone.ts
|
|
292
|
-
function findMilestoneForSlug(owner, repo, slug) {
|
|
293
|
-
const milestones = ghApiGet(`repos/${owner}/${repo}/milestones?state=all&per_page=100`);
|
|
294
|
-
const match = milestones.find((m) => m.title === slug);
|
|
295
|
-
if (!match)
|
|
296
|
-
return null;
|
|
297
|
-
return {
|
|
298
|
-
goal: match.description ?? "",
|
|
299
|
-
lifecycle: match.state === "closed" ? "complete" : "active"
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
|
|
303
294
|
// ../../packages/aeg-forge-state/src/labels.ts
|
|
304
295
|
var LABELS = [
|
|
305
296
|
{
|
|
@@ -542,6 +533,60 @@ function resolveTaskIssueRef(title, labels) {
|
|
|
542
533
|
return { trancheSlug, taskId };
|
|
543
534
|
}
|
|
544
535
|
|
|
536
|
+
// ../../packages/aeg-forge-state/src/fetch-milestone.ts
|
|
537
|
+
var INTENTS_HEADING = /^#{1,6}\s*Tranche intents\s*$/im;
|
|
538
|
+
var NEXT_HEADING = /^#{1,6}\s+\S/m;
|
|
539
|
+
var INTENT_BULLET = /^-\s+([a-z0-9][a-z0-9-]*)\s*:\s*(.+)$/i;
|
|
540
|
+
function intentGoalForSlug(description, slug) {
|
|
541
|
+
const text = stripCode(description, { inlineSpans: "keep" });
|
|
542
|
+
const start = text.match(INTENTS_HEADING);
|
|
543
|
+
if (!start || start.index === undefined)
|
|
544
|
+
return "";
|
|
545
|
+
const rest = text.slice(start.index + start[0].length);
|
|
546
|
+
const next = rest.match(NEXT_HEADING);
|
|
547
|
+
const section = rest.slice(0, next && next.index !== undefined ? next.index : rest.length);
|
|
548
|
+
for (const line of section.split(`
|
|
549
|
+
`)) {
|
|
550
|
+
const trimmed = line.trim();
|
|
551
|
+
if (trimmed.length === 0)
|
|
552
|
+
continue;
|
|
553
|
+
const m = trimmed.match(INTENT_BULLET);
|
|
554
|
+
if (m && (m[1] ?? "").toLowerCase() === slug.toLowerCase())
|
|
555
|
+
return (m[2] ?? "").trim();
|
|
556
|
+
}
|
|
557
|
+
return "";
|
|
558
|
+
}
|
|
559
|
+
function matchesLegacyMilestone(milestones, slug) {
|
|
560
|
+
return milestones.find((m) => m.title === slug) ?? null;
|
|
561
|
+
}
|
|
562
|
+
function factsFromLegacyMilestone(milestone) {
|
|
563
|
+
return {
|
|
564
|
+
goal: milestone.description ?? "",
|
|
565
|
+
lifecycle: milestone.state === "closed" ? "complete" : "active"
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
function lifecycleFromIssues(issues) {
|
|
569
|
+
if (issues.length === 0)
|
|
570
|
+
return "planned";
|
|
571
|
+
return issues.some((i) => i.state === "OPEN") ? "active" : "complete";
|
|
572
|
+
}
|
|
573
|
+
function goalFromMilestones(milestones, slug) {
|
|
574
|
+
for (const m of milestones) {
|
|
575
|
+
const goal = intentGoalForSlug(m.description ?? "", slug);
|
|
576
|
+
if (goal)
|
|
577
|
+
return goal;
|
|
578
|
+
}
|
|
579
|
+
return "";
|
|
580
|
+
}
|
|
581
|
+
function findMilestoneForSlug(owner, repo, slug) {
|
|
582
|
+
const milestones = ghApiGet(`repos/${owner}/${repo}/milestones?state=all&per_page=100`);
|
|
583
|
+
const legacy = matchesLegacyMilestone(milestones, slug);
|
|
584
|
+
if (legacy)
|
|
585
|
+
return factsFromLegacyMilestone(legacy);
|
|
586
|
+
const issues = ghIssueListByLabel(owner, repo, trancheLabel(slug));
|
|
587
|
+
return { goal: goalFromMilestones(milestones, slug), lifecycle: lifecycleFromIssues(issues) };
|
|
588
|
+
}
|
|
589
|
+
|
|
545
590
|
// ../../packages/aeg-forge-state/src/derive-from-forge.ts
|
|
546
591
|
function trancheFromIssues(slug, issues, known) {
|
|
547
592
|
return {
|
|
@@ -270,6 +270,9 @@ function issueListByLabelArgs(owner, repo, label) {
|
|
|
270
270
|
"200"
|
|
271
271
|
];
|
|
272
272
|
}
|
|
273
|
+
function ghIssueListByLabel(owner, repo, label) {
|
|
274
|
+
return JSON.parse(run(issueListByLabelArgs(owner, repo, label)));
|
|
275
|
+
}
|
|
273
276
|
async function ghIssueListByLabelAsync(owner, repo, label) {
|
|
274
277
|
return JSON.parse(await runAsync(issueListByLabelArgs(owner, repo, label)));
|
|
275
278
|
}
|
|
@@ -285,18 +288,6 @@ async function ghIssueListByAnyLabelAsync(owner, repo, labels) {
|
|
|
285
288
|
return dedupeByNumber(perLabel.flat());
|
|
286
289
|
}
|
|
287
290
|
|
|
288
|
-
// ../../packages/aeg-forge-state/src/fetch-milestone.ts
|
|
289
|
-
function findMilestoneForSlug(owner, repo, slug) {
|
|
290
|
-
const milestones = ghApiGet(`repos/${owner}/${repo}/milestones?state=all&per_page=100`);
|
|
291
|
-
const match = milestones.find((m) => m.title === slug);
|
|
292
|
-
if (!match)
|
|
293
|
-
return null;
|
|
294
|
-
return {
|
|
295
|
-
goal: match.description ?? "",
|
|
296
|
-
lifecycle: match.state === "closed" ? "complete" : "active"
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
|
|
300
291
|
// ../../packages/aeg-forge-state/src/labels.ts
|
|
301
292
|
var LABELS = [
|
|
302
293
|
{
|
|
@@ -539,6 +530,60 @@ function resolveTaskIssueRef(title, labels) {
|
|
|
539
530
|
return { trancheSlug, taskId };
|
|
540
531
|
}
|
|
541
532
|
|
|
533
|
+
// ../../packages/aeg-forge-state/src/fetch-milestone.ts
|
|
534
|
+
var INTENTS_HEADING = /^#{1,6}\s*Tranche intents\s*$/im;
|
|
535
|
+
var NEXT_HEADING = /^#{1,6}\s+\S/m;
|
|
536
|
+
var INTENT_BULLET = /^-\s+([a-z0-9][a-z0-9-]*)\s*:\s*(.+)$/i;
|
|
537
|
+
function intentGoalForSlug(description, slug) {
|
|
538
|
+
const text = stripCode(description, { inlineSpans: "keep" });
|
|
539
|
+
const start = text.match(INTENTS_HEADING);
|
|
540
|
+
if (!start || start.index === undefined)
|
|
541
|
+
return "";
|
|
542
|
+
const rest = text.slice(start.index + start[0].length);
|
|
543
|
+
const next = rest.match(NEXT_HEADING);
|
|
544
|
+
const section = rest.slice(0, next && next.index !== undefined ? next.index : rest.length);
|
|
545
|
+
for (const line of section.split(`
|
|
546
|
+
`)) {
|
|
547
|
+
const trimmed = line.trim();
|
|
548
|
+
if (trimmed.length === 0)
|
|
549
|
+
continue;
|
|
550
|
+
const m = trimmed.match(INTENT_BULLET);
|
|
551
|
+
if (m && (m[1] ?? "").toLowerCase() === slug.toLowerCase())
|
|
552
|
+
return (m[2] ?? "").trim();
|
|
553
|
+
}
|
|
554
|
+
return "";
|
|
555
|
+
}
|
|
556
|
+
function matchesLegacyMilestone(milestones, slug) {
|
|
557
|
+
return milestones.find((m) => m.title === slug) ?? null;
|
|
558
|
+
}
|
|
559
|
+
function factsFromLegacyMilestone(milestone) {
|
|
560
|
+
return {
|
|
561
|
+
goal: milestone.description ?? "",
|
|
562
|
+
lifecycle: milestone.state === "closed" ? "complete" : "active"
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
function lifecycleFromIssues(issues) {
|
|
566
|
+
if (issues.length === 0)
|
|
567
|
+
return "planned";
|
|
568
|
+
return issues.some((i) => i.state === "OPEN") ? "active" : "complete";
|
|
569
|
+
}
|
|
570
|
+
function goalFromMilestones(milestones, slug) {
|
|
571
|
+
for (const m of milestones) {
|
|
572
|
+
const goal = intentGoalForSlug(m.description ?? "", slug);
|
|
573
|
+
if (goal)
|
|
574
|
+
return goal;
|
|
575
|
+
}
|
|
576
|
+
return "";
|
|
577
|
+
}
|
|
578
|
+
function findMilestoneForSlug(owner, repo, slug) {
|
|
579
|
+
const milestones = ghApiGet(`repos/${owner}/${repo}/milestones?state=all&per_page=100`);
|
|
580
|
+
const legacy = matchesLegacyMilestone(milestones, slug);
|
|
581
|
+
if (legacy)
|
|
582
|
+
return factsFromLegacyMilestone(legacy);
|
|
583
|
+
const issues = ghIssueListByLabel(owner, repo, trancheLabel(slug));
|
|
584
|
+
return { goal: goalFromMilestones(milestones, slug), lifecycle: lifecycleFromIssues(issues) };
|
|
585
|
+
}
|
|
586
|
+
|
|
542
587
|
// ../../packages/aeg-forge-state/src/derive-from-forge.ts
|
|
543
588
|
function trancheFromIssues(slug, issues, known) {
|
|
544
589
|
return {
|