@attalabs/vinaya 0.28.0 → 0.29.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 +1 -1
- package/aeg-root/contracts/planner-developer.md +4 -1
- package/aeg-root/contracts/planner-operator.md +86 -0
- package/aeg-root/contracts/principal-operator.md +88 -0
- package/aeg-root/roles/developer.md +2 -1
- package/aeg-root/roles/operator.md +133 -0
- package/aeg-root/roles/planner.md +4 -0
- package/aeg-root/skills/aeg-context-packets/SKILL.md +123 -0
- package/aeg-root/skills/aeg-context-packets/examples/operator-start.md +30 -0
- package/aeg-root/templates/brief-template.md +6 -2
- package/dist/checks/bin/check-body-bare-digits.js +376 -16
- package/dist/checks/bin/check-branch-topology.js +403 -16
- package/dist/checks/bin/check-brief-shape.js +380 -19
- package/dist/checks/bin/check-changeset-coverage.js +673 -33
- package/dist/checks/bin/check-closes-n.js +403 -16
- package/dist/checks/bin/check-coherence.js +410 -16
- package/dist/checks/bin/check-dead-branch-push.js +369 -16
- package/dist/checks/bin/check-dispatch-readiness.js +410 -16
- package/dist/checks/bin/check-doc-coverage-push.js +670 -30
- package/dist/checks/bin/check-doc-coverage.js +672 -32
- package/dist/checks/bin/check-doctrine-no-procedures.js +376 -16
- package/dist/checks/bin/check-doctrine-portability.js +670 -30
- package/dist/checks/bin/check-evidence-fresh.js +762 -113
- package/dist/checks/bin/check-exec-bits.js +668 -28
- package/dist/checks/bin/check-first-push-dispatch.js +410 -16
- package/dist/checks/bin/check-issue-assignment.js +403 -16
- package/dist/checks/bin/check-issue-milestone-attach.js +369 -16
- package/dist/checks/bin/check-issue-objectives-numbering.js +369 -16
- package/dist/checks/bin/check-issue-parts-coverage.js +369 -16
- package/dist/checks/bin/check-issue-surface-globs.js +410 -16
- package/dist/checks/bin/check-issue-title-grammar.js +369 -16
- package/dist/checks/bin/check-issue-tranche-label.js +369 -16
- package/dist/checks/bin/check-main-branch-refusal.js +369 -16
- package/dist/checks/bin/check-no-disk-state.js +369 -16
- package/dist/checks/bin/check-pr-premise-reassert.js +376 -16
- package/dist/checks/bin/check-pr-report-density.js +369 -16
- package/dist/checks/bin/check-quoted-command.js +671 -31
- package/dist/checks/bin/check-reader-resolvable-prose.js +674 -34
- package/dist/checks/bin/check-registry-gates.js +369 -16
- package/dist/checks/bin/check-retired-vocabulary.js +669 -29
- package/dist/checks/bin/check-review-gate.js +391 -16
- package/dist/checks/bin/check-single-plan-pr.js +369 -16
- package/dist/checks/bin/check-surface-scope.js +403 -16
- package/dist/checks/bin/check-test-plan.js +369 -16
- package/dist/checks/bin/check-token-collection-wired.js +369 -16
- package/dist/checks/bin/check-token-report.js +382 -19
- package/dist/checks/bin/check-workspace-escape.js +668 -28
- package/dist/index.js +15307 -10932
- package/dist/lib/pre-push-select-tests.js +154 -11
- 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/page.js +2 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error/page.js.nft.json +1 -1
- 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/_head.segment.rsc +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_index.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 +8 -7
- 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/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page.js +8 -7
- 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 +9 -8
- 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 +9 -8
- 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 +8 -7
- 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 +16 -4
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page.js +10 -8
- 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 +8 -7
- 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 +8 -7
- 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 +9 -8
- 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/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]__08f5pba._.js +3 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__1o_0tjy._.js → [root-of-the-server]__0h9yhwx._.js} +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0053k9k._.js → [root-of-the-server]__0ls23oh._.js} +3 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0puovz5._.js → [root-of-the-server]__0nye8tb._.js} +3 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__18kqy4q._.js → [root-of-the-server]__0tfykr-._.js} +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0o771t1._.js → [root-of-the-server]__0th3gyp._.js} +3 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1-zcufa._.js +51 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0p8q38b._.js → [root-of-the-server]__11svemm._.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__02c71kv._.js → [root-of-the-server]__140m1i_._.js} +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1bh2awk._.js +3 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0112h-k._.js → [root-of-the-server]__1gjqmhq._.js} +3 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1qmxez3._.js +4 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1r47dr7._.js +28 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1wc4-ip._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_01fv4fj._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_0gvm3og._.js → _096f46i._.js} +3 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_0lwxg63._.js → _0af2one._.js} +3 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_1n0cnq-._.js → _0zf4d27._.js} +45 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_03x_w6q._.js → _1-wo68i._.js} +3 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/apps_vinaya-studio_web_src_app_studio_projects_[name]_tranches_[slug]_05ufo8i._.js +1 -12
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/node_modules_1wdusod._.js +3 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{node_modules_1vo08dj._.js → node_modules_@clerk_nextjs_dist_esm_app-router_server-actions_1x7vfhn.js} +3 -4
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/node_modules_next_1khj-jh._.js +3 -0
- 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 +17 -5
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{3_9xytdmiv1xi.js → 25f3-jtiv8p5n.js} +4 -4
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{0bn8c8v5q429o.js → 27-6ym7lp2v8o.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{3-6a3tinbdb-7.js → 3daxns3o--9me.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/tsconfig.json +12 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0z6dav-._.js +0 -51
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__13rrmhr._.js +0 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__17h4sy8._.js +0 -45
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1hs0dcu._.js +0 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/node_modules_next_17sz44y._.js +0 -3
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{DMofV2-9FrHE7100GfrpI → -UC6GS6zDHeiawEYgYbTN}/_buildManifest.js +0 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{DMofV2-9FrHE7100GfrpI → -UC6GS6zDHeiawEYgYbTN}/_clientMiddlewareManifest.js +0 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{DMofV2-9FrHE7100GfrpI → -UC6GS6zDHeiawEYgYbTN}/_ssgManifest.js +0 -0
|
@@ -3,8 +3,8 @@ import { createRequire } from "node:module";
|
|
|
3
3
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
4
4
|
|
|
5
5
|
// src/checks/bin/check-quoted-command.ts
|
|
6
|
-
import { existsSync as
|
|
7
|
-
import { join as
|
|
6
|
+
import { existsSync as existsSync6, readdirSync as readdirSync2, readFileSync as readFileSync5, statSync } from "node:fs";
|
|
7
|
+
import { join as join7, relative as relative2, resolve as resolve3 } from "node:path";
|
|
8
8
|
// ../../packages/aeg-core/src/gate-audience.ts
|
|
9
9
|
var GATE_AUDIENCE = {
|
|
10
10
|
"check-branch-topology": { shippedAs: "branch-topology", ring: 0 },
|
|
@@ -1645,6 +1645,52 @@ var systemEnv3 = {
|
|
|
1645
1645
|
...process.env,
|
|
1646
1646
|
PATH: [process.env.PATH, "/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin"].filter(Boolean).join(":")
|
|
1647
1647
|
};
|
|
1648
|
+
var defaultExec = () => execFileAsync3("git", ["remote", "get-url", "origin"], { env: systemEnv3, timeout: 5000 });
|
|
1649
|
+
var cached;
|
|
1650
|
+
var inflight;
|
|
1651
|
+
async function resolveRepo(exec = defaultExec) {
|
|
1652
|
+
if (cached !== undefined)
|
|
1653
|
+
return cached;
|
|
1654
|
+
const fromEnv = process.env.AEG_REPO;
|
|
1655
|
+
if (fromEnv) {
|
|
1656
|
+
const parsed = parseOwnerRepo(fromEnv);
|
|
1657
|
+
if (parsed) {
|
|
1658
|
+
cached = parsed;
|
|
1659
|
+
return cached;
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
if (inflight)
|
|
1663
|
+
return inflight;
|
|
1664
|
+
inflight = (async () => {
|
|
1665
|
+
try {
|
|
1666
|
+
const { stdout } = await exec();
|
|
1667
|
+
cached = parseGitRemoteUrl(stdout.trim());
|
|
1668
|
+
return cached;
|
|
1669
|
+
} catch (err) {
|
|
1670
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1671
|
+
console.warn(`[aeg-forge-state] resolveRepo: git remote lookup failed (will retry): ${message}`);
|
|
1672
|
+
return null;
|
|
1673
|
+
} finally {
|
|
1674
|
+
inflight = undefined;
|
|
1675
|
+
}
|
|
1676
|
+
})();
|
|
1677
|
+
return inflight;
|
|
1678
|
+
}
|
|
1679
|
+
function parseGitRemoteUrl(url) {
|
|
1680
|
+
const ssh = url.match(/^git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/);
|
|
1681
|
+
if (ssh?.[1] && ssh[2])
|
|
1682
|
+
return { owner: ssh[1], repo: ssh[2] };
|
|
1683
|
+
const https = url.match(/^https?:\/\/(?:[^@]+@)?github\.com\/([^/]+)\/(.+?)(?:\.git)?\/?$/);
|
|
1684
|
+
if (https?.[1] && https[2])
|
|
1685
|
+
return { owner: https[1], repo: https[2] };
|
|
1686
|
+
return null;
|
|
1687
|
+
}
|
|
1688
|
+
function parseOwnerRepo(value) {
|
|
1689
|
+
const match = value.match(/^([^/]+)\/(.+)$/);
|
|
1690
|
+
if (!match?.[1] || !match[2])
|
|
1691
|
+
return null;
|
|
1692
|
+
return { owner: match[1], repo: match[2] };
|
|
1693
|
+
}
|
|
1648
1694
|
// ../../packages/aeg-core/src/anchored-region.ts
|
|
1649
1695
|
function anchoredRegionBounds(body, field) {
|
|
1650
1696
|
const masked = maskCode(body);
|
|
@@ -1957,6 +2003,7 @@ var OBJECTIVES_VERSION_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Objectives version:\
|
|
|
1957
2003
|
var RULING_ORDINAL_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Ruling ordinal:\s*(\d+)(?!\d)/im;
|
|
1958
2004
|
var BRIEF_HASH_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Brief hash:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
|
|
1959
2005
|
var POLICY_DIGEST_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Policy digest:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
|
|
2006
|
+
var BASE_SHA_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Judged base:\s*([0-9a-f]{7,40})(?![A-Za-z0-9])/im;
|
|
1960
2007
|
function firstFiveLines(comment) {
|
|
1961
2008
|
return comment.split(`
|
|
1962
2009
|
`).slice(0, 5).join(`
|
|
@@ -1992,6 +2039,15 @@ function extractPolicyDigest(comment) {
|
|
|
1992
2039
|
const m = firstElevenLines(comment).match(POLICY_DIGEST_PATTERN);
|
|
1993
2040
|
return m ? m[1].toLowerCase() : null;
|
|
1994
2041
|
}
|
|
2042
|
+
function firstThirteenLines(comment) {
|
|
2043
|
+
return comment.split(`
|
|
2044
|
+
`).slice(0, 13).join(`
|
|
2045
|
+
`);
|
|
2046
|
+
}
|
|
2047
|
+
function extractBaseSha(comment) {
|
|
2048
|
+
const m = firstThirteenLines(comment).match(BASE_SHA_PATTERN);
|
|
2049
|
+
return m ? m[1].toLowerCase() : null;
|
|
2050
|
+
}
|
|
1995
2051
|
var FINDING_SEVERITY_LINE = /^\d+\.\s+\[([A-Z][A-Z]*)\]\s+(.+?)\s+—/gm;
|
|
1996
2052
|
function extractFindingSeverities(comment) {
|
|
1997
2053
|
return [...comment.matchAll(FINDING_SEVERITY_LINE)].map((m) => ({
|
|
@@ -2009,6 +2065,7 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
2009
2065
|
rulingOrdinal: null,
|
|
2010
2066
|
briefHash: null,
|
|
2011
2067
|
policyDigest: null,
|
|
2068
|
+
baseSha: null,
|
|
2012
2069
|
findingSeverities: [],
|
|
2013
2070
|
danglingNote: `no ${missingLabel} verdict comment found on this PR`
|
|
2014
2071
|
};
|
|
@@ -2023,6 +2080,7 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
2023
2080
|
rulingOrdinal: null,
|
|
2024
2081
|
briefHash: null,
|
|
2025
2082
|
policyDigest: null,
|
|
2083
|
+
baseSha: null,
|
|
2026
2084
|
findingSeverities: [],
|
|
2027
2085
|
danglingNote: `the most recent ${missingLabel} verdict comment carries a VERDICT-shaped line outside the first-five-line read window`
|
|
2028
2086
|
};
|
|
@@ -2034,6 +2092,7 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
2034
2092
|
rulingOrdinal: extractRulingOrdinal(latest),
|
|
2035
2093
|
briefHash: extractBriefHash(latest),
|
|
2036
2094
|
policyDigest: extractPolicyDigest(latest),
|
|
2095
|
+
baseSha: extractBaseSha(latest),
|
|
2037
2096
|
findingSeverities: extractFindingSeverities(latest),
|
|
2038
2097
|
danglingNote: null
|
|
2039
2098
|
};
|
|
@@ -3947,7 +4006,11 @@ function briefHash(brief) {
|
|
|
3947
4006
|
`).digest("hex");
|
|
3948
4007
|
}
|
|
3949
4008
|
function policyDigest(policy) {
|
|
3950
|
-
return createHash4("sha256").update(JSON.stringify({
|
|
4009
|
+
return createHash4("sha256").update(JSON.stringify({
|
|
4010
|
+
codeReviewThreshold: policy.codeReviewThreshold,
|
|
4011
|
+
securityThreshold: policy.securityThreshold,
|
|
4012
|
+
maxRounds: policy.maxRounds
|
|
4013
|
+
})).digest("hex");
|
|
3951
4014
|
}
|
|
3952
4015
|
function isBoundToHead(echoed, headSha) {
|
|
3953
4016
|
if (!echoed.headSha)
|
|
@@ -3963,8 +4026,12 @@ function isBoundByPatchIdentity(echoed, headSha, patchIdOf) {
|
|
|
3963
4026
|
return false;
|
|
3964
4027
|
return judged === current;
|
|
3965
4028
|
}
|
|
3966
|
-
function
|
|
3967
|
-
|
|
4029
|
+
function isBoundToBase(echoed, currentBase) {
|
|
4030
|
+
if (currentBase === null)
|
|
4031
|
+
return true;
|
|
4032
|
+
if (!echoed.baseSha)
|
|
4033
|
+
return false;
|
|
4034
|
+
return currentBase.toLowerCase().startsWith(echoed.baseSha.toLowerCase());
|
|
3968
4035
|
}
|
|
3969
4036
|
function isBoundToObjectives(echoed, currentVersion) {
|
|
3970
4037
|
if (currentVersion === null)
|
|
@@ -3985,14 +4052,18 @@ function isBoundToPolicy(echoed, currentDigest) {
|
|
|
3985
4052
|
return echoed.policyDigest === currentDigest;
|
|
3986
4053
|
}
|
|
3987
4054
|
function compareManifest(echoed, current, patchIdOf) {
|
|
3988
|
-
const
|
|
4055
|
+
const exactHead = isBoundToHead(echoed, current.headSha);
|
|
4056
|
+
const patchHead = exactHead ? false : isBoundByPatchIdentity(echoed, current.headSha, patchIdOf);
|
|
4057
|
+
const head = exactHead || patchHead;
|
|
4058
|
+
const base = patchHead ? true : isBoundToBase(echoed, current.baseSha);
|
|
3989
4059
|
const briefHashBound = isBoundToBriefHash(echoed, current.briefHash);
|
|
3990
4060
|
const objectivesVersion2 = isBoundToObjectives(echoed, current.objectivesVersion);
|
|
3991
4061
|
const rulingOrdinal = isBoundToRulings(echoed, current.rulingOrdinal);
|
|
3992
4062
|
const policyDigestBound = isBoundToPolicy(echoed, current.policyDigest);
|
|
3993
4063
|
return {
|
|
3994
|
-
bound: head && briefHashBound && objectivesVersion2 && rulingOrdinal && policyDigestBound,
|
|
4064
|
+
bound: head && base && briefHashBound && objectivesVersion2 && rulingOrdinal && policyDigestBound,
|
|
3995
4065
|
head,
|
|
4066
|
+
base,
|
|
3996
4067
|
briefHash: briefHashBound,
|
|
3997
4068
|
objectivesVersion: objectivesVersion2,
|
|
3998
4069
|
rulingOrdinal,
|
|
@@ -4044,6 +4115,7 @@ function checkReviewGate(input) {
|
|
|
4044
4115
|
const securityClean = securityTextClean && securityPolicyClean;
|
|
4045
4116
|
const currentManifest = {
|
|
4046
4117
|
headSha: input.headSha,
|
|
4118
|
+
baseSha: input.baseSha ?? null,
|
|
4047
4119
|
briefHash: input.briefHash ?? null,
|
|
4048
4120
|
objectivesVersion: input.objectivesVersion,
|
|
4049
4121
|
rulingOrdinal: input.rulingOrdinal,
|
|
@@ -4051,6 +4123,7 @@ function checkReviewGate(input) {
|
|
|
4051
4123
|
};
|
|
4052
4124
|
const codeReviewEchoed = {
|
|
4053
4125
|
headSha: codeReview.headSha,
|
|
4126
|
+
baseSha: codeReview.baseSha,
|
|
4054
4127
|
briefHash: codeReview.briefHash,
|
|
4055
4128
|
objectivesVersion: codeReview.objectivesVersion,
|
|
4056
4129
|
rulingOrdinal: codeReview.rulingOrdinal,
|
|
@@ -4058,6 +4131,7 @@ function checkReviewGate(input) {
|
|
|
4058
4131
|
};
|
|
4059
4132
|
const securityEchoed = {
|
|
4060
4133
|
headSha: security.headSha,
|
|
4134
|
+
baseSha: security.baseSha,
|
|
4061
4135
|
briefHash: security.briefHash,
|
|
4062
4136
|
objectivesVersion: security.objectivesVersion,
|
|
4063
4137
|
rulingOrdinal: security.rulingOrdinal,
|
|
@@ -4085,6 +4159,8 @@ function checkReviewGate(input) {
|
|
|
4085
4159
|
problems.push(`code-reviewer verdict says APPROVE but carries a finding (${codeReviewPolicyEvaluation.blockingFindings.map((f) => f.severity).join(", ")}) at or above this repository's code-review policy threshold (${policy.codeReviewThreshold}) — a reviewer's own APPROVE never overrides policy`);
|
|
4086
4160
|
} else if (!codeReviewBound) {
|
|
4087
4161
|
problems.push(`the newest code-review verdict covers ${codeReview.headSha ?? "no recorded commit"}, head is ${input.headSha}`);
|
|
4162
|
+
} else if (!codeReviewBinding.base) {
|
|
4163
|
+
problems.push(`the newest code-review verdict was cast against base ${codeReview.baseSha ?? "no recorded base"}, the PR's base is now ${currentManifest.baseSha ?? "unresolved"} (a base-only change under an unchanged candidate — same patch text on a new base is not automatically equivalent)`);
|
|
4088
4164
|
} else if (!codeReviewObjectivesBound) {
|
|
4089
4165
|
problems.push(`the newest code-review verdict was cast against objectives version ${codeReview.objectivesVersion ?? "none"}, the Issue's list is now ${input.objectivesVersion}`);
|
|
4090
4166
|
} else if (!codeReviewRulingsBound) {
|
|
@@ -4100,6 +4176,8 @@ function checkReviewGate(input) {
|
|
|
4100
4176
|
problems.push(`security-review verdict says PASS but carries a finding (${securityPolicyEvaluation.blockingFindings.map((f) => f.severity).join(", ")}) at or above this repository's security policy threshold (${policy.securityThreshold}) — a reviewer's own PASS never overrides policy`);
|
|
4101
4177
|
} else if (!securityBound) {
|
|
4102
4178
|
problems.push(`the newest security-review verdict covers ${security.headSha ?? "no recorded commit"}, head is ${input.headSha}`);
|
|
4179
|
+
} else if (!securityBinding.base) {
|
|
4180
|
+
problems.push(`the newest security-review verdict was cast against base ${security.baseSha ?? "no recorded base"}, the PR's base is now ${currentManifest.baseSha ?? "unresolved"} (a base-only change under an unchanged candidate — same patch text on a new base is not automatically equivalent)`);
|
|
4103
4181
|
} else if (!securityObjectivesBound) {
|
|
4104
4182
|
problems.push(`the newest security-review verdict was cast against objectives version ${security.objectivesVersion ?? "none"}, the Issue's list is now ${input.objectivesVersion}`);
|
|
4105
4183
|
} else if (!securityRulingsBound) {
|
|
@@ -4957,8 +5035,8 @@ var TaskToolErrorSchema = z.object({
|
|
|
4957
5035
|
detail: z.string().optional()
|
|
4958
5036
|
});
|
|
4959
5037
|
var TaskToolRefSchema = z.union([
|
|
4960
|
-
z.object({ tranche: z.string().min(1), id: z.string().min(1) }),
|
|
4961
|
-
z.object({ issue: z.number().int().positive() })
|
|
5038
|
+
z.object({ tranche: z.string().min(1), id: z.string().min(1) }).strict(),
|
|
5039
|
+
z.object({ issue: z.number().int().positive() }).strict()
|
|
4962
5040
|
]);
|
|
4963
5041
|
var MAX_PAGE_LIMIT = 100;
|
|
4964
5042
|
var PageRequestSchema = z.object({
|
|
@@ -4972,7 +5050,7 @@ var ObservedSchema = z.object({
|
|
|
4972
5050
|
});
|
|
4973
5051
|
var TaskStatusInputSchema = z.object({
|
|
4974
5052
|
task: TaskToolRefSchema.optional()
|
|
4975
|
-
}).merge(PageRequestSchema);
|
|
5053
|
+
}).merge(PageRequestSchema).strict();
|
|
4976
5054
|
var TaskStatusItemSchema = z.object({
|
|
4977
5055
|
task: TaskToolRefSchema,
|
|
4978
5056
|
issue: z.number().int().positive(),
|
|
@@ -4996,9 +5074,20 @@ var EscalationEvidenceSchema = z.object({
|
|
|
4996
5074
|
reviewer: z.string().nullable(),
|
|
4997
5075
|
security: z.string().nullable()
|
|
4998
5076
|
});
|
|
5077
|
+
var EscalationRunIdentitySchema = z.object({
|
|
5078
|
+
runId: z.string(),
|
|
5079
|
+
pid: z.number().int().positive(),
|
|
5080
|
+
host: z.string()
|
|
5081
|
+
});
|
|
5082
|
+
var EscalationInputVersionsSchema = z.object({
|
|
5083
|
+
briefHash: z.string().nullable(),
|
|
5084
|
+
objectivesVersion: z.string().nullable(),
|
|
5085
|
+
rulingOrdinal: z.number().int().nonnegative(),
|
|
5086
|
+
policyDigest: z.string()
|
|
5087
|
+
});
|
|
4999
5088
|
var TaskEscalationReadInputSchema = z.object({
|
|
5000
5089
|
task: TaskToolRefSchema
|
|
5001
|
-
}).merge(PageRequestSchema);
|
|
5090
|
+
}).merge(PageRequestSchema).strict();
|
|
5002
5091
|
var TaskEscalationPacketSchema = z.object({
|
|
5003
5092
|
reason: z.string(),
|
|
5004
5093
|
detail: z.string().nullable(),
|
|
@@ -5006,7 +5095,9 @@ var TaskEscalationPacketSchema = z.object({
|
|
|
5006
5095
|
evidence: EscalationEvidenceSchema.nullable(),
|
|
5007
5096
|
attemptedRecovery: z.string(),
|
|
5008
5097
|
requestedAuthority: RequestedAuthoritySchema,
|
|
5009
|
-
permittedNextActions: z.array(z.string())
|
|
5098
|
+
permittedNextActions: z.array(z.string()),
|
|
5099
|
+
runIdentity: EscalationRunIdentitySchema.nullable(),
|
|
5100
|
+
inputVersions: EscalationInputVersionsSchema.nullable()
|
|
5010
5101
|
}).merge(ObservedSchema);
|
|
5011
5102
|
var TaskEscalationReadResultSchema = z.object({
|
|
5012
5103
|
items: z.array(TaskEscalationPacketSchema),
|
|
@@ -5015,15 +5106,48 @@ var TaskEscalationReadResultSchema = z.object({
|
|
|
5015
5106
|
var TaskStartInputSchema = z.object({
|
|
5016
5107
|
tranche: z.string().min(1),
|
|
5017
5108
|
id: z.string().min(1)
|
|
5109
|
+
}).strict();
|
|
5110
|
+
var TaskStartResultSchema = z.object({
|
|
5111
|
+
requestId: z.string().min(1),
|
|
5112
|
+
run: z.object({ tranche: z.string().min(1), id: z.string().min(1) }),
|
|
5113
|
+
started: z.boolean(),
|
|
5114
|
+
startedAt: z.string(),
|
|
5115
|
+
mode: z.literal("attended")
|
|
5018
5116
|
});
|
|
5019
5117
|
var TaskResumeInputSchema = z.object({
|
|
5020
5118
|
task: TaskToolRefSchema
|
|
5021
|
-
});
|
|
5119
|
+
}).strict();
|
|
5022
5120
|
var TaskCancelInputSchema = z.object({
|
|
5023
5121
|
task: TaskToolRefSchema,
|
|
5024
5122
|
reason: z.string().min(1)
|
|
5123
|
+
}).strict();
|
|
5124
|
+
var TaskResumeResultSchema = z.object({
|
|
5125
|
+
task: z.number().int().positive(),
|
|
5126
|
+
pr: z.number().int().positive(),
|
|
5127
|
+
escalationId: z.string().min(1),
|
|
5128
|
+
outcome: z.enum(["started", "already_resumed"]),
|
|
5129
|
+
authenticatedBy: z.string().min(1),
|
|
5130
|
+
authenticatedFrom: z.string().min(1)
|
|
5131
|
+
});
|
|
5132
|
+
var TaskCancelOutcomeSchema = z.enum(["confirmed", "pending", "uncertain"]);
|
|
5133
|
+
var TaskCancelResultSchema = z.object({
|
|
5134
|
+
task: z.number().int().positive(),
|
|
5135
|
+
pr: z.number().int().positive(),
|
|
5136
|
+
escalationId: z.string().min(1),
|
|
5137
|
+
outcome: TaskCancelOutcomeSchema,
|
|
5138
|
+
authenticatedBy: z.string().min(1),
|
|
5139
|
+
authenticatedFrom: z.string().min(1),
|
|
5140
|
+
fencedEffectKeys: z.array(z.string())
|
|
5025
5141
|
});
|
|
5026
|
-
var
|
|
5142
|
+
var TASK_TOOL_NAMES = [
|
|
5143
|
+
"task_start",
|
|
5144
|
+
"task_status",
|
|
5145
|
+
"task_escalation_read",
|
|
5146
|
+
"task_resume",
|
|
5147
|
+
"task_cancel"
|
|
5148
|
+
];
|
|
5149
|
+
var OPERATOR_STATUS_FOLLOW = "task_status_follow";
|
|
5150
|
+
var OPERATOR_TOOL_GRANT = [...TASK_TOOL_NAMES, OPERATOR_STATUS_FOLLOW];
|
|
5027
5151
|
// ../../packages/aeg-core/src/first-push-dispatch-gate.ts
|
|
5028
5152
|
function parseTaskBranch(branch) {
|
|
5029
5153
|
const m = /^task\/([^/]+)\/([^/]+)$/.exec(branch);
|
|
@@ -5246,6 +5370,9 @@ function findWorkspaceEscapes(files, knownPaths, workspaceDirs = DEFAULT_WORKSPA
|
|
|
5246
5370
|
}
|
|
5247
5371
|
return findings;
|
|
5248
5372
|
}
|
|
5373
|
+
// ../../packages/aeg-core/src/log/envelope.ts
|
|
5374
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
5375
|
+
|
|
5249
5376
|
// ../../packages/aeg-core/src/log/schema.ts
|
|
5250
5377
|
import { z as z2 } from "zod";
|
|
5251
5378
|
var ROLE_VALUES = [
|
|
@@ -5347,7 +5474,8 @@ var DispatchOutcomeSchema = z2.discriminatedUnion("type", [
|
|
|
5347
5474
|
}).strict(),
|
|
5348
5475
|
z2.object({ type: z2.literal("brief"), comment_id: z2.number().int(), hash: z2.string() }).strict(),
|
|
5349
5476
|
z2.object({ type: z2.literal("plan"), issues: z2.array(z2.number().int()) }).strict(),
|
|
5350
|
-
z2.object({ type: z2.literal("archive"), provenance_comment_id: z2.number().int() }).strict()
|
|
5477
|
+
z2.object({ type: z2.literal("archive"), provenance_comment_id: z2.number().int() }).strict(),
|
|
5478
|
+
z2.object({ type: z2.literal("completed") }).strict()
|
|
5351
5479
|
]);
|
|
5352
5480
|
var dispatchShared = {
|
|
5353
5481
|
meta: HeaderMetaSchema,
|
|
@@ -5407,7 +5535,8 @@ var DevReviewLoopEventSchema = z2.discriminatedUnion("event", [
|
|
|
5407
5535
|
round: z2.number().int(),
|
|
5408
5536
|
head: z2.string(),
|
|
5409
5537
|
all_approve: z2.boolean(),
|
|
5410
|
-
blockers: z2.number().int().nonnegative()
|
|
5538
|
+
blockers: z2.number().int().nonnegative(),
|
|
5539
|
+
findings: z2.array(ReviewFindingSchema).optional()
|
|
5411
5540
|
}).strict(),
|
|
5412
5541
|
z2.object({
|
|
5413
5542
|
...loopShared,
|
|
@@ -5586,7 +5715,9 @@ var roleAttemptShared = {
|
|
|
5586
5715
|
kind: z2.literal("role_attempt"),
|
|
5587
5716
|
...envelopeTail,
|
|
5588
5717
|
actor: z2.string().nullable(),
|
|
5589
|
-
attempt: z2.number().int().nullable()
|
|
5718
|
+
attempt: z2.number().int().nullable(),
|
|
5719
|
+
effect_id: z2.string(),
|
|
5720
|
+
model: z2.string().nullable()
|
|
5590
5721
|
};
|
|
5591
5722
|
var RoleAttemptEventSchema = z2.discriminatedUnion("event", [
|
|
5592
5723
|
z2.object({
|
|
@@ -5645,6 +5776,144 @@ var LogEventSchema = z2.union([
|
|
|
5645
5776
|
HandoffEventSchema,
|
|
5646
5777
|
EffectEventSchema
|
|
5647
5778
|
]);
|
|
5779
|
+
|
|
5780
|
+
// ../../packages/aeg-core/src/log/envelope.ts
|
|
5781
|
+
function isRole(value) {
|
|
5782
|
+
return value !== undefined && ROLE_VALUES.includes(value);
|
|
5783
|
+
}
|
|
5784
|
+
function actorIdFromEnv(role) {
|
|
5785
|
+
return role === undefined || role === "" ? null : role;
|
|
5786
|
+
}
|
|
5787
|
+
function lineageFieldFromEnv(value) {
|
|
5788
|
+
return value === undefined || value === "" ? null : value;
|
|
5789
|
+
}
|
|
5790
|
+
function attemptFromEnv(value) {
|
|
5791
|
+
if (value === undefined || value === "")
|
|
5792
|
+
return null;
|
|
5793
|
+
const n = Number(value);
|
|
5794
|
+
return Number.isInteger(n) ? n : null;
|
|
5795
|
+
}
|
|
5796
|
+
function provenanceFor(input) {
|
|
5797
|
+
if (input.provenance)
|
|
5798
|
+
return input.provenance;
|
|
5799
|
+
if (input.env.role || input.env.task)
|
|
5800
|
+
return "env_correlated";
|
|
5801
|
+
return "unavailable";
|
|
5802
|
+
}
|
|
5803
|
+
function issueFromTask(task) {
|
|
5804
|
+
if (task === undefined || task === "")
|
|
5805
|
+
return null;
|
|
5806
|
+
const n = Number(task);
|
|
5807
|
+
return Number.isInteger(n) ? n : null;
|
|
5808
|
+
}
|
|
5809
|
+
function roundFromEnv(round) {
|
|
5810
|
+
if (round === undefined || round === "")
|
|
5811
|
+
return;
|
|
5812
|
+
const n = Number(round);
|
|
5813
|
+
return Number.isInteger(n) ? n : undefined;
|
|
5814
|
+
}
|
|
5815
|
+
function buildHeader(input) {
|
|
5816
|
+
const role = isRole(input.env.role) ? input.env.role : "unattributed";
|
|
5817
|
+
const round = roundFromEnv(input.env.round);
|
|
5818
|
+
const subject = {
|
|
5819
|
+
issue: issueFromTask(input.env.task),
|
|
5820
|
+
role,
|
|
5821
|
+
...round !== undefined ? { round } : {},
|
|
5822
|
+
...input.subject ?? {}
|
|
5823
|
+
};
|
|
5824
|
+
return {
|
|
5825
|
+
meta: {
|
|
5826
|
+
schema: 2,
|
|
5827
|
+
ts: input.now.toISOString(),
|
|
5828
|
+
run_id: input.runId,
|
|
5829
|
+
seq: input.seq,
|
|
5830
|
+
repo: input.repo,
|
|
5831
|
+
vinaya: input.vinaya,
|
|
5832
|
+
doctrine: input.doctrine,
|
|
5833
|
+
host: input.host,
|
|
5834
|
+
machine: createHash5("sha256").update(input.hostname).digest("hex"),
|
|
5835
|
+
event_id: input.eventId,
|
|
5836
|
+
process_id: input.processId,
|
|
5837
|
+
actor_id: actorIdFromEnv(input.env.role),
|
|
5838
|
+
lineage: {
|
|
5839
|
+
run: lineageFieldFromEnv(input.env.run),
|
|
5840
|
+
attempt: attemptFromEnv(input.env.attempt),
|
|
5841
|
+
parent: lineageFieldFromEnv(input.env.parent)
|
|
5842
|
+
},
|
|
5843
|
+
input_versions: {
|
|
5844
|
+
objectives_version: input.inputVersions?.objectivesVersion ?? null,
|
|
5845
|
+
brief_hash: input.inputVersions?.briefHash ?? null,
|
|
5846
|
+
ruling_ordinal: input.inputVersions?.rulingOrdinal ?? null,
|
|
5847
|
+
policy_digest: input.inputVersions?.policyDigest ?? null
|
|
5848
|
+
},
|
|
5849
|
+
provenance: provenanceFor(input)
|
|
5850
|
+
},
|
|
5851
|
+
subject
|
|
5852
|
+
};
|
|
5853
|
+
}
|
|
5854
|
+
// ../../packages/aeg-core/src/log/redact.ts
|
|
5855
|
+
var GITHUB_TOKEN_PATTERN = /\b(?:gho_|ghp_|ghs_|ghu_|ghr_|github_pat_)[A-Za-z0-9_]+\b/g;
|
|
5856
|
+
var CLASSIC_GITHUB_PAT_PATTERN = /\b((?:token|GITHUB_TOKEN|PAT|api[_-]?key|api[_-]?token)\s*[:=]\s*)[a-f0-9]{40}\b/gi;
|
|
5857
|
+
var BEARER_TOKEN_PATTERN = /\bBearer\s+\S+/g;
|
|
5858
|
+
var AWS_ACCESS_KEY_PATTERN = /\bAKIA[0-9A-Z]{16}\b/g;
|
|
5859
|
+
var SLACK_TOKEN_PATTERN = /\bxox[baprs]-[0-9A-Za-z-]+\b/g;
|
|
5860
|
+
var STRIPE_KEY_PATTERN = /\b(?:sk|pk|rk)_(?:live|test)_[0-9A-Za-z]{10,}\b/g;
|
|
5861
|
+
var ANTHROPIC_KEY_PATTERN = /\bsk-ant-[A-Za-z0-9_-]{20,}\b/g;
|
|
5862
|
+
var OPENAI_KEY_PATTERN = /\bsk-(?!ant-)[A-Za-z0-9]{20,}\b/g;
|
|
5863
|
+
var NPM_TOKEN_PATTERN = /\bnpm_[A-Za-z0-9]{36}\b/g;
|
|
5864
|
+
var JWT_PATTERN = /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g;
|
|
5865
|
+
var PEM_BLOCK_PATTERN = /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g;
|
|
5866
|
+
var BASIC_AUTH_URL_PATTERN = /(https?:\/\/)[^/\s:@]+:[^/\s@]+@/g;
|
|
5867
|
+
var GENERIC_SECRET_ASSIGNMENT_PATTERN = /\b((?:secret|password|passwd|api[_-]?key|access[_-]?key|client[_-]?secret|private[_-]?key)\s*[:=]\s*)[A-Za-z0-9+/_=-]{16,}\b/gi;
|
|
5868
|
+
function redactString(value, home) {
|
|
5869
|
+
let out = value.replace(GITHUB_TOKEN_PATTERN, "<redacted>").replace(CLASSIC_GITHUB_PAT_PATTERN, "$1<redacted>").replace(BEARER_TOKEN_PATTERN, "<redacted>").replace(AWS_ACCESS_KEY_PATTERN, "<redacted>").replace(SLACK_TOKEN_PATTERN, "<redacted>").replace(STRIPE_KEY_PATTERN, "<redacted>").replace(ANTHROPIC_KEY_PATTERN, "<redacted>").replace(OPENAI_KEY_PATTERN, "<redacted>").replace(NPM_TOKEN_PATTERN, "<redacted>").replace(JWT_PATTERN, "<redacted>").replace(PEM_BLOCK_PATTERN, "<redacted>").replace(BASIC_AUTH_URL_PATTERN, "$1<redacted>@").replace(GENERIC_SECRET_ASSIGNMENT_PATTERN, "$1<redacted>");
|
|
5870
|
+
if (home.length > 0 && out.startsWith(home)) {
|
|
5871
|
+
const rest = out.slice(home.length);
|
|
5872
|
+
if (rest === "" || rest.startsWith("/"))
|
|
5873
|
+
out = `~${rest}`;
|
|
5874
|
+
}
|
|
5875
|
+
return out;
|
|
5876
|
+
}
|
|
5877
|
+
function redact(value, home) {
|
|
5878
|
+
if (typeof value === "string")
|
|
5879
|
+
return redactString(value, home);
|
|
5880
|
+
if (Array.isArray(value))
|
|
5881
|
+
return value.map((v) => redact(v, home));
|
|
5882
|
+
if (value !== null && typeof value === "object") {
|
|
5883
|
+
const out = {};
|
|
5884
|
+
for (const [k, v] of Object.entries(value)) {
|
|
5885
|
+
out[k] = redact(v, home);
|
|
5886
|
+
}
|
|
5887
|
+
return out;
|
|
5888
|
+
}
|
|
5889
|
+
return value;
|
|
5890
|
+
}
|
|
5891
|
+
// ../../packages/aeg-core/src/log/store.ts
|
|
5892
|
+
function metaOf(obj) {
|
|
5893
|
+
if (obj === null || typeof obj !== "object")
|
|
5894
|
+
return null;
|
|
5895
|
+
const meta = obj.meta;
|
|
5896
|
+
if (meta === null || typeof meta !== "object")
|
|
5897
|
+
return null;
|
|
5898
|
+
return meta;
|
|
5899
|
+
}
|
|
5900
|
+
function recordIdentity(obj) {
|
|
5901
|
+
const meta = metaOf(obj);
|
|
5902
|
+
if (meta === null)
|
|
5903
|
+
return null;
|
|
5904
|
+
const eventId = meta.event_id;
|
|
5905
|
+
if (typeof eventId === "string" && eventId.length > 0)
|
|
5906
|
+
return eventId;
|
|
5907
|
+
const runId = meta.run_id;
|
|
5908
|
+
const seq = meta.seq;
|
|
5909
|
+
if (typeof runId === "string" && runId.length > 0 && typeof seq === "number" && Number.isInteger(seq)) {
|
|
5910
|
+
return `${runId}:${seq}`;
|
|
5911
|
+
}
|
|
5912
|
+
return null;
|
|
5913
|
+
}
|
|
5914
|
+
|
|
5915
|
+
// ../../packages/aeg-core/src/log/artifact.ts
|
|
5916
|
+
var TASK_LOG_ARTIFACT_MAX_BYTES = 8 * 1024 * 1024;
|
|
5648
5917
|
// ../../packages/aeg-core/src/dev-review-loop/journal-reconstruction.ts
|
|
5649
5918
|
var STOPPED_CONDITIONS = new Set(["confidence", "reappearance", "no_progress", "max_rounds"]);
|
|
5650
5919
|
// ../../packages/aeg-core/src/control-store/records.ts
|
|
@@ -5659,7 +5928,9 @@ var RunRecordSchema = z3.object({
|
|
|
5659
5928
|
runId: z3.string().min(1),
|
|
5660
5929
|
pid: z3.number().int().positive(),
|
|
5661
5930
|
host: z3.string().min(1),
|
|
5662
|
-
startedAt: isoTimestamp
|
|
5931
|
+
startedAt: isoTimestamp,
|
|
5932
|
+
childStartedAt: z3.string().min(1).nullable().optional(),
|
|
5933
|
+
childCommand: z3.string().min(1).nullable().optional()
|
|
5663
5934
|
}).strict();
|
|
5664
5935
|
var InputRecordSchema = z3.object({
|
|
5665
5936
|
version: z3.literal(1),
|
|
@@ -5692,6 +5963,88 @@ var TransitionRecordSchema = z3.object({
|
|
|
5692
5963
|
detail: z3.string().optional(),
|
|
5693
5964
|
at: isoTimestamp
|
|
5694
5965
|
}).strict();
|
|
5966
|
+
var ManifestRecordSchema = z3.object({
|
|
5967
|
+
version: z3.literal(1),
|
|
5968
|
+
kind: z3.literal("manifest"),
|
|
5969
|
+
task: taskId,
|
|
5970
|
+
round: epochNumber,
|
|
5971
|
+
repository: z3.string().min(1),
|
|
5972
|
+
pr: z3.number().int().positive(),
|
|
5973
|
+
branch: z3.string().min(1),
|
|
5974
|
+
baseSha: z3.string().min(1).nullable(),
|
|
5975
|
+
headSha: z3.string().min(1),
|
|
5976
|
+
briefHash: z3.string().min(1).nullable(),
|
|
5977
|
+
objectivesVersion: z3.string().min(1).nullable(),
|
|
5978
|
+
rulingOrdinal: epochNumber,
|
|
5979
|
+
policyDigest: z3.string().min(1),
|
|
5980
|
+
recordedAt: isoTimestamp
|
|
5981
|
+
}).strict();
|
|
5982
|
+
var roundHeadIdentity = z3.object({ round: z3.number().int().positive(), head: z3.string().min(1) }).strict();
|
|
5983
|
+
var LoopBudgetsSchema = z3.object({
|
|
5984
|
+
mechanicalRetries: z3.number().int().nonnegative(),
|
|
5985
|
+
reviewRounds: z3.number().int().nonnegative(),
|
|
5986
|
+
infrastructureRetries: z3.number().int().nonnegative()
|
|
5987
|
+
}).strict();
|
|
5988
|
+
var LoopStateRecordSchema = z3.object({
|
|
5989
|
+
version: z3.literal(1),
|
|
5990
|
+
kind: z3.literal("loop_state"),
|
|
5991
|
+
task: taskId,
|
|
5992
|
+
round: z3.number().int().positive(),
|
|
5993
|
+
phase: z3.string().min(1),
|
|
5994
|
+
pauseReason: z3.string().min(1).nullable(),
|
|
5995
|
+
budgets: LoopBudgetsSchema,
|
|
5996
|
+
heldResult: roundHeadIdentity.nullable(),
|
|
5997
|
+
deliveredFindings: roundHeadIdentity.nullable(),
|
|
5998
|
+
recordedAt: isoTimestamp
|
|
5999
|
+
}).strict();
|
|
6000
|
+
var EffectRecordSchema = z3.object({
|
|
6001
|
+
version: z3.literal(1),
|
|
6002
|
+
kind: z3.literal("effect"),
|
|
6003
|
+
task: taskId,
|
|
6004
|
+
key: z3.string().min(1),
|
|
6005
|
+
operation: z3.string().min(1),
|
|
6006
|
+
target: z3.string().min(1),
|
|
6007
|
+
inputVersion: z3.number().int().nonnegative(),
|
|
6008
|
+
payloadDigest: z3.string().min(1),
|
|
6009
|
+
status: z3.union([z3.literal("started"), z3.literal("verified"), z3.literal("uncertain")]),
|
|
6010
|
+
url: z3.string().optional(),
|
|
6011
|
+
recordedAt: isoTimestamp
|
|
6012
|
+
}).strict();
|
|
6013
|
+
var EscalationRecordSchema = z3.object({
|
|
6014
|
+
version: z3.literal(1),
|
|
6015
|
+
kind: z3.literal("escalation"),
|
|
6016
|
+
task: taskId,
|
|
6017
|
+
escalationId: z3.string().min(1),
|
|
6018
|
+
round: epochNumber,
|
|
6019
|
+
head: z3.string().min(1),
|
|
6020
|
+
branch: z3.string().min(1),
|
|
6021
|
+
pr: z3.number().int().positive().nullable(),
|
|
6022
|
+
runId: z3.string().min(1),
|
|
6023
|
+
pid: z3.number().int().positive(),
|
|
6024
|
+
host: z3.string().min(1),
|
|
6025
|
+
agent: z3.string().min(1).optional(),
|
|
6026
|
+
reason: z3.string().min(1),
|
|
6027
|
+
detail: z3.string().optional(),
|
|
6028
|
+
evidence: z3.string().optional(),
|
|
6029
|
+
attemptedRecovery: z3.string().min(1),
|
|
6030
|
+
requestedDecision: z3.string().min(1),
|
|
6031
|
+
recipient: z3.string().min(1),
|
|
6032
|
+
briefHash: z3.string().min(1).nullable(),
|
|
6033
|
+
objectivesVersion: z3.string().min(1).nullable(),
|
|
6034
|
+
rulingOrdinal: epochNumber,
|
|
6035
|
+
policyDigest: z3.string().min(1),
|
|
6036
|
+
recordedAt: isoTimestamp
|
|
6037
|
+
}).strict();
|
|
6038
|
+
var ResolutionRecordSchema = z3.object({
|
|
6039
|
+
version: z3.literal(1),
|
|
6040
|
+
kind: z3.literal("resolution"),
|
|
6041
|
+
task: taskId,
|
|
6042
|
+
escalationId: z3.string().min(1),
|
|
6043
|
+
decision: z3.union([z3.literal("resume"), z3.literal("cancel")]),
|
|
6044
|
+
authenticatedBy: z3.string().min(1),
|
|
6045
|
+
authenticatedFrom: z3.string().min(1),
|
|
6046
|
+
consumedAt: isoTimestamp
|
|
6047
|
+
}).strict();
|
|
5695
6048
|
// src/commands/doctrine.ts
|
|
5696
6049
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
5697
6050
|
import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync2 } from "node:fs";
|
|
@@ -5925,6 +6278,13 @@ var VinayaConfigSchema = z4.object({
|
|
|
5925
6278
|
message: "must be at most 3600000 (1 hour)"
|
|
5926
6279
|
});
|
|
5927
6280
|
}
|
|
6281
|
+
}).optional(),
|
|
6282
|
+
logPublish: z4.object({
|
|
6283
|
+
issue: z4.number().int().positive().optional(),
|
|
6284
|
+
pr: z4.number().int().positive().optional(),
|
|
6285
|
+
maxChunksPerFlush: z4.number().int().positive().optional()
|
|
6286
|
+
}).refine((v) => !(v.issue !== undefined && v.pr !== undefined), {
|
|
6287
|
+
message: "logPublish: set at most one of issue/pr, not both"
|
|
5928
6288
|
}).optional()
|
|
5929
6289
|
});
|
|
5930
6290
|
var GLOBAL_VINAYA_HOME = join3(homedir(), ".vinaya");
|
|
@@ -6108,8 +6468,8 @@ function emitCheckError(error) {
|
|
|
6108
6468
|
}
|
|
6109
6469
|
|
|
6110
6470
|
// src/lib/diff-evidence.ts
|
|
6111
|
-
import { execFileSync as
|
|
6112
|
-
import { join as
|
|
6471
|
+
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
6472
|
+
import { join as join6, relative, resolve as resolve2 } from "node:path";
|
|
6113
6473
|
|
|
6114
6474
|
// src/lib/brief-assembly.ts
|
|
6115
6475
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
@@ -6283,6 +6643,16 @@ var COMMANDS = [
|
|
|
6283
6643
|
],
|
|
6284
6644
|
status: "shipped"
|
|
6285
6645
|
},
|
|
6646
|
+
{
|
|
6647
|
+
name: "task-tools serve",
|
|
6648
|
+
description: "Run the task-operator MCP tool server over stdio — the command both runtime adapters register",
|
|
6649
|
+
details: [
|
|
6650
|
+
"Exposes the task-operator tool catalog (`packages/aeg-core/src/task-tools.ts`) to an agent runtime as one MCP server speaking newline-delimited JSON-RPC 2.0 (`initialize`/`tools/list`/`tools/call`). Claude registers it through the generated `.mcp.json`; Codex through its documented `~/.codex/config.toml` `[mcp_servers]` table — both point at this same command.",
|
|
6651
|
+
"stdout carries JSON-RPC and nothing else: any stray write from the CLI (a forge-read warning) is redirected to stderr, so the protocol stream is never corrupted.",
|
|
6652
|
+
"`task_status`/`task_escalation_read` read; `task_start` starts a run in attended mode only, requiring an authenticated caller from the invocation context (`VINAYA_MCP_CALLER`) and refusing without one — MCP is a transport, not authorization. `task_resume`/`task_cancel` require the same authenticated caller, plus a current Principal ruling read fresh from the run's own PR — never a caller-supplied approval; `task_resume` triggers the existing `dev-review-loop --resume` continuation exactly once per escalation, and `task_cancel` reports a truthful `confirmed`/`pending`/`uncertain` outcome, idempotently, across repeated calls. No unattended start until the worker-isolation boundary and a capability flag land."
|
|
6653
|
+
],
|
|
6654
|
+
status: "shipped"
|
|
6655
|
+
},
|
|
6286
6656
|
{
|
|
6287
6657
|
name: "pr create",
|
|
6288
6658
|
description: "Open a pull request after full brief-schema validation",
|
|
@@ -6427,6 +6797,30 @@ var COMMANDS = [
|
|
|
6427
6797
|
],
|
|
6428
6798
|
status: "shipped"
|
|
6429
6799
|
},
|
|
6800
|
+
{
|
|
6801
|
+
name: "log export-artifact",
|
|
6802
|
+
description: "Copy this run's own local outbox into a file, for the generated task-path workflow's own upload step",
|
|
6803
|
+
flags: [],
|
|
6804
|
+
details: [
|
|
6805
|
+
"Concatenates every `*.ndjson` file under `~/.vinaya/outbox/` into `<dest>`, verbatim — no filtering, no second redaction pass (lines are already redacted at `log()`'s own write boundary). Writes nothing when the outbox is empty, and exits 0 either way: no gate events this run is a legitimate outcome, never a failure.",
|
|
6806
|
+
"Runs inside the generated `vinaya-checks.yml` job, which holds no forge-write credential — this command never calls the forge. Both this step and the `actions/upload-artifact` step after it run `if: always()`, so a cancelled or failed job still exports whatever partial outbox it has."
|
|
6807
|
+
],
|
|
6808
|
+
status: "shipped"
|
|
6809
|
+
},
|
|
6810
|
+
{
|
|
6811
|
+
name: "log collect-artifact",
|
|
6812
|
+
description: "Validate a downloaded task-log artifact and publish the valid records through the existing flush path",
|
|
6813
|
+
flags: [
|
|
6814
|
+
{ flag: "--pr", description: "The pull request this artifact belongs to" },
|
|
6815
|
+
{ flag: "--repo", description: "Expected `owner/repo` — a provenance cross-check against each record" }
|
|
6816
|
+
],
|
|
6817
|
+
details: [
|
|
6818
|
+
"Runs inside the generated `vinaya-task-log-collector.yml` workflow — a `workflow_run`-triggered job on the default branch, holding the write credential the task-path job that produced the artifact never gets. `<path>` is already downloaded by that workflow, scoped to a specific, API-verified run id — a provenance guarantee this command never re-derives from the artifact bytes.",
|
|
6819
|
+
"Never executes, imports, or evaluates the artifact's content: every line is read as text and validated (schema, an 8 MiB whole-artifact size cap, redaction, and a repo cross-check) before anything is trusted. A rejected line becomes a named gap — printed, never a silent drop — and the artifact is never partially trusted past that check into executing anything.",
|
|
6820
|
+
"The valid, re-redacted survivors are appended into the same local outbox `vinaya log flush` would read for that PR's Issue, then published through the existing `flushOutbox` unmodified — reusing its chunking, its `<!-- aeg:log:… -->` marker, and its idempotent-retry read, rather than a second publisher. A retried collector run (a fresh runner, the same forge state) therefore dedupes for free: the marker already on the forge is acknowledged, never re-posted."
|
|
6821
|
+
],
|
|
6822
|
+
status: "shipped"
|
|
6823
|
+
},
|
|
6430
6824
|
{
|
|
6431
6825
|
name: "milestone create",
|
|
6432
6826
|
description: "Create a GitHub Milestone from a validated body",
|
|
@@ -7470,8 +7864,254 @@ function coreCheckRegistry() {
|
|
|
7470
7864
|
}
|
|
7471
7865
|
var CORE_CHECK_RING = Object.fromEntries(REGISTRY.map(([spec, ring]) => [spec.name, ring]));
|
|
7472
7866
|
|
|
7867
|
+
// src/lib/log-sink.ts
|
|
7868
|
+
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
7869
|
+
import { randomUUID } from "node:crypto";
|
|
7870
|
+
import {
|
|
7871
|
+
closeSync as closeSync2,
|
|
7872
|
+
constants as fsConstants2,
|
|
7873
|
+
existsSync as existsSync5,
|
|
7874
|
+
fstatSync as fstatSync2,
|
|
7875
|
+
mkdirSync as mkdirSync2,
|
|
7876
|
+
openSync as openSync2,
|
|
7877
|
+
readFileSync as readFileSync4,
|
|
7878
|
+
renameSync,
|
|
7879
|
+
writeSync
|
|
7880
|
+
} from "node:fs";
|
|
7881
|
+
import { hostname as osHostname, homedir as homedir2 } from "node:os";
|
|
7882
|
+
import { dirname as dirname4, join as join5 } from "node:path";
|
|
7883
|
+
var OUTBOX_MAX_BYTES = 8 * 1024 * 1024;
|
|
7884
|
+
function isEnoent(err) {
|
|
7885
|
+
return typeof err === "object" && err !== null && err.code === "ENOENT";
|
|
7886
|
+
}
|
|
7887
|
+
function resolveDoctrine(cwd, vinayaVersion) {
|
|
7888
|
+
let toplevel;
|
|
7889
|
+
try {
|
|
7890
|
+
toplevel = execFileSync6("git", ["-C", cwd, "rev-parse", "--show-toplevel"], {
|
|
7891
|
+
encoding: "utf8",
|
|
7892
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
7893
|
+
}).trim();
|
|
7894
|
+
} catch (err) {
|
|
7895
|
+
return isEnoent(err) ? "unknown" : vinayaVersion;
|
|
7896
|
+
}
|
|
7897
|
+
if (!existsSync5(join5(toplevel, "aeg-root", "roles")))
|
|
7898
|
+
return vinayaVersion;
|
|
7899
|
+
try {
|
|
7900
|
+
const sha = execFileSync6("git", ["-C", toplevel, "rev-parse", "HEAD:aeg-root"], {
|
|
7901
|
+
encoding: "utf8",
|
|
7902
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
7903
|
+
}).trim();
|
|
7904
|
+
return `aeg-root@${sha}`;
|
|
7905
|
+
} catch {
|
|
7906
|
+
return vinayaVersion;
|
|
7907
|
+
}
|
|
7908
|
+
}
|
|
7909
|
+
function readVinayaVersion() {
|
|
7910
|
+
try {
|
|
7911
|
+
const pkg = JSON.parse(readFileSync4(join5(packageRoot(import.meta.url), "package.json"), "utf8"));
|
|
7912
|
+
return pkg.version ?? "unknown";
|
|
7913
|
+
} catch {
|
|
7914
|
+
return "unknown";
|
|
7915
|
+
}
|
|
7916
|
+
}
|
|
7917
|
+
var SAFE_PATH_SEGMENT = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/;
|
|
7918
|
+
function isSafeRepoSegment(segment) {
|
|
7919
|
+
return SAFE_PATH_SEGMENT.test(segment) && !segment.includes("..");
|
|
7920
|
+
}
|
|
7921
|
+
function outboxPathFor(deps, repo, issue) {
|
|
7922
|
+
const dirName = repo ? `${repo.owner}-${repo.repo}` : "unresolved";
|
|
7923
|
+
const fileName = `${issue ?? "none"}.ndjson`;
|
|
7924
|
+
return join5(deps.outboxRoot(), dirName, fileName);
|
|
7925
|
+
}
|
|
7926
|
+
function hostFromEnv(env) {
|
|
7927
|
+
if (env.GITHUB_ACTIONS)
|
|
7928
|
+
return "ci";
|
|
7929
|
+
if (env.VINAYA_HOST === "hook")
|
|
7930
|
+
return "hook";
|
|
7931
|
+
if (env.VINAYA_HOST === "loop")
|
|
7932
|
+
return "loop";
|
|
7933
|
+
return "cli";
|
|
7934
|
+
}
|
|
7935
|
+
function defaultDeps() {
|
|
7936
|
+
return {
|
|
7937
|
+
outboxRoot: () => join5(GLOBAL_VINAYA_HOME, "outbox"),
|
|
7938
|
+
home: () => homedir2(),
|
|
7939
|
+
hostname: () => osHostname(),
|
|
7940
|
+
cwd: () => process.cwd(),
|
|
7941
|
+
now: () => new Date,
|
|
7942
|
+
env: () => process.env,
|
|
7943
|
+
resolveRepo: () => resolveRepo(),
|
|
7944
|
+
vinayaVersion: () => readVinayaVersion(),
|
|
7945
|
+
stderr: (message) => {
|
|
7946
|
+
process.stderr.write(message);
|
|
7947
|
+
},
|
|
7948
|
+
inputVersions: () => {
|
|
7949
|
+
return;
|
|
7950
|
+
}
|
|
7951
|
+
};
|
|
7952
|
+
}
|
|
7953
|
+
var APPEND_OPEN_FLAGS = fsConstants2.O_WRONLY | fsConstants2.O_APPEND | fsConstants2.O_CREAT | fsConstants2.O_NOFOLLOW | fsConstants2.O_NONBLOCK;
|
|
7954
|
+
function guardedAppendOpen(path) {
|
|
7955
|
+
try {
|
|
7956
|
+
return openSync2(path, APPEND_OPEN_FLAGS, 384);
|
|
7957
|
+
} catch {
|
|
7958
|
+
return;
|
|
7959
|
+
}
|
|
7960
|
+
}
|
|
7961
|
+
function reportRotationOverflow(backupPath, warn) {
|
|
7962
|
+
let raw;
|
|
7963
|
+
try {
|
|
7964
|
+
raw = readFileSync4(backupPath, "utf8");
|
|
7965
|
+
} catch {
|
|
7966
|
+
return;
|
|
7967
|
+
}
|
|
7968
|
+
const lines = raw.split(`
|
|
7969
|
+
`).filter((l) => l.length > 0);
|
|
7970
|
+
if (lines.length === 0)
|
|
7971
|
+
return;
|
|
7972
|
+
const droppedIdentities = lines.map((line, i) => {
|
|
7973
|
+
try {
|
|
7974
|
+
return recordIdentity(JSON.parse(line)) ?? `unreadable:${i}`;
|
|
7975
|
+
} catch {
|
|
7976
|
+
return `unreadable:${i}`;
|
|
7977
|
+
}
|
|
7978
|
+
});
|
|
7979
|
+
const diagnostic = { reason: "capacity", dropped: droppedIdentities.length, droppedIdentities };
|
|
7980
|
+
const shown = diagnostic.droppedIdentities.slice(0, 20);
|
|
7981
|
+
const more = diagnostic.dropped > shown.length ? `, +${diagnostic.dropped - shown.length} more` : "";
|
|
7982
|
+
warn(`vinaya: log outbox rotation is overwriting ${backupPath} — ${diagnostic.dropped} record(s) permanently lost: ${shown.join(", ")}${more}
|
|
7983
|
+
`);
|
|
7984
|
+
}
|
|
7985
|
+
function appendLine(path, line, warn) {
|
|
7986
|
+
try {
|
|
7987
|
+
mkdirSync2(dirname4(path), { recursive: true, mode: 448 });
|
|
7988
|
+
let fd = guardedAppendOpen(path);
|
|
7989
|
+
if (fd === undefined) {
|
|
7990
|
+
warn(`vinaya: log outbox target could not be opened (symlink, FIFO, or unwritable) — refusing: ${path}
|
|
7991
|
+
`);
|
|
7992
|
+
return;
|
|
7993
|
+
}
|
|
7994
|
+
let closed = false;
|
|
7995
|
+
try {
|
|
7996
|
+
const stat = fstatSync2(fd);
|
|
7997
|
+
if (!stat.isFile()) {
|
|
7998
|
+
warn(`vinaya: log outbox target is not a regular file — refusing to write: ${path}
|
|
7999
|
+
`);
|
|
8000
|
+
return;
|
|
8001
|
+
}
|
|
8002
|
+
if (stat.size > OUTBOX_MAX_BYTES) {
|
|
8003
|
+
closeSync2(fd);
|
|
8004
|
+
closed = true;
|
|
8005
|
+
const backupPath = path.replace(/\.ndjson$/, ".1.ndjson");
|
|
8006
|
+
reportRotationOverflow(backupPath, warn);
|
|
8007
|
+
renameSync(path, backupPath);
|
|
8008
|
+
const rotated = guardedAppendOpen(path);
|
|
8009
|
+
if (rotated === undefined) {
|
|
8010
|
+
warn(`vinaya: log outbox target could not be reopened after rotation — refusing: ${path}
|
|
8011
|
+
`);
|
|
8012
|
+
return;
|
|
8013
|
+
}
|
|
8014
|
+
fd = rotated;
|
|
8015
|
+
closed = false;
|
|
8016
|
+
}
|
|
8017
|
+
writeSync(fd, line);
|
|
8018
|
+
} finally {
|
|
8019
|
+
if (!closed)
|
|
8020
|
+
closeSync2(fd);
|
|
8021
|
+
}
|
|
8022
|
+
} catch (err) {
|
|
8023
|
+
warn(`vinaya: log outbox write failed — ${err instanceof Error ? err.message : String(err)}
|
|
8024
|
+
`);
|
|
8025
|
+
}
|
|
8026
|
+
}
|
|
8027
|
+
function createLogSink(overrides = {}) {
|
|
8028
|
+
const deps = { ...defaultDeps(), ...overrides };
|
|
8029
|
+
const runId = deps.env().VINAYA_RUN_ID || randomUUID();
|
|
8030
|
+
const processId = randomUUID();
|
|
8031
|
+
let seq = 0;
|
|
8032
|
+
let warned = false;
|
|
8033
|
+
const warnOnce = (message) => {
|
|
8034
|
+
if (warned)
|
|
8035
|
+
return;
|
|
8036
|
+
warned = true;
|
|
8037
|
+
try {
|
|
8038
|
+
deps.stderr(message);
|
|
8039
|
+
} catch {}
|
|
8040
|
+
};
|
|
8041
|
+
let doctrineCache;
|
|
8042
|
+
const doctrine = () => {
|
|
8043
|
+
if (doctrineCache === undefined)
|
|
8044
|
+
doctrineCache = resolveDoctrine(deps.cwd(), deps.vinayaVersion());
|
|
8045
|
+
return doctrineCache;
|
|
8046
|
+
};
|
|
8047
|
+
let resolveRepoCache;
|
|
8048
|
+
const resolveRepoOnce = () => {
|
|
8049
|
+
if (resolveRepoCache === undefined)
|
|
8050
|
+
resolveRepoCache = deps.resolveRepo();
|
|
8051
|
+
return resolveRepoCache;
|
|
8052
|
+
};
|
|
8053
|
+
function log(e) {
|
|
8054
|
+
try {
|
|
8055
|
+
const env = deps.env();
|
|
8056
|
+
const host = hostFromEnv(env);
|
|
8057
|
+
const now = deps.now();
|
|
8058
|
+
const mySeq = seq++;
|
|
8059
|
+
resolveRepoOnce().then((resolved) => {
|
|
8060
|
+
const repo = resolved && isSafeRepoSegment(resolved.owner) && isSafeRepoSegment(resolved.repo) ? resolved : null;
|
|
8061
|
+
const header = buildHeader({
|
|
8062
|
+
now,
|
|
8063
|
+
runId,
|
|
8064
|
+
seq: mySeq,
|
|
8065
|
+
repo: repo ? `${repo.owner}/${repo.repo}` : null,
|
|
8066
|
+
vinaya: deps.vinayaVersion(),
|
|
8067
|
+
doctrine: doctrine(),
|
|
8068
|
+
host,
|
|
8069
|
+
hostname: deps.hostname(),
|
|
8070
|
+
env: {
|
|
8071
|
+
role: env.VINAYA_ROLE,
|
|
8072
|
+
task: env.VINAYA_TASK,
|
|
8073
|
+
round: env.VINAYA_ROUND,
|
|
8074
|
+
run: env.VINAYA_RUN,
|
|
8075
|
+
attempt: env.VINAYA_ATTEMPT,
|
|
8076
|
+
parent: env.VINAYA_PARENT_EVENT
|
|
8077
|
+
},
|
|
8078
|
+
eventId: randomUUID(),
|
|
8079
|
+
processId,
|
|
8080
|
+
inputVersions: deps.inputVersions()
|
|
8081
|
+
});
|
|
8082
|
+
const full = { ...e, ...header };
|
|
8083
|
+
const parsed = LogEventSchema.safeParse(full);
|
|
8084
|
+
if (!parsed.success) {
|
|
8085
|
+
warnOnce(`vinaya: log() refused an invalid payload — ${parsed.error.issues[0]?.message ?? "schema violation"}
|
|
8086
|
+
`);
|
|
8087
|
+
return;
|
|
8088
|
+
}
|
|
8089
|
+
const line = `${JSON.stringify(redact(parsed.data, deps.home()))}
|
|
8090
|
+
`;
|
|
8091
|
+
appendLine(outboxPathFor(deps, repo, header.subject.issue), line, warnOnce);
|
|
8092
|
+
}).catch((err) => {
|
|
8093
|
+
warnOnce(`vinaya: log() failed — ${err instanceof Error ? err.message : String(err)}
|
|
8094
|
+
`);
|
|
8095
|
+
});
|
|
8096
|
+
} catch (err) {
|
|
8097
|
+
warnOnce(`vinaya: log() failed — ${err instanceof Error ? err.message : String(err)}
|
|
8098
|
+
`);
|
|
8099
|
+
}
|
|
8100
|
+
}
|
|
8101
|
+
const warmup = () => {
|
|
8102
|
+
doctrine();
|
|
8103
|
+
const originalWarn = console.warn;
|
|
8104
|
+
console.warn = () => {};
|
|
8105
|
+
resolveRepoOnce().finally(() => {
|
|
8106
|
+
console.warn = originalWarn;
|
|
8107
|
+
});
|
|
8108
|
+
};
|
|
8109
|
+
return { log, runId, warmup };
|
|
8110
|
+
}
|
|
8111
|
+
var defaultSink = createLogSink();
|
|
8112
|
+
|
|
7473
8113
|
// src/checks/runner.ts
|
|
7474
|
-
var
|
|
8114
|
+
var activeChecks = new Map;
|
|
7475
8115
|
|
|
7476
8116
|
// src/lib/forge-write.ts
|
|
7477
8117
|
var INFORMATIONAL_DISPATCH_BLOCKER_CLASSES = new Set([
|
|
@@ -7510,7 +8150,7 @@ function parseChangedLineRanges(diffOutput) {
|
|
|
7510
8150
|
function fileDiffAgainst(ref, path) {
|
|
7511
8151
|
let out;
|
|
7512
8152
|
try {
|
|
7513
|
-
out =
|
|
8153
|
+
out = execFileSync7("git", ["diff", `${ref}...HEAD`, "--", path], {
|
|
7514
8154
|
encoding: "utf8",
|
|
7515
8155
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7516
8156
|
}).trim();
|
|
@@ -7521,7 +8161,7 @@ function fileDiffAgainst(ref, path) {
|
|
|
7521
8161
|
}
|
|
7522
8162
|
function revParse(ref) {
|
|
7523
8163
|
try {
|
|
7524
|
-
return
|
|
8164
|
+
return execFileSync7("git", ["rev-parse", "--verify", ref], {
|
|
7525
8165
|
encoding: "utf8",
|
|
7526
8166
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7527
8167
|
}).trim();
|
|
@@ -7531,7 +8171,7 @@ function revParse(ref) {
|
|
|
7531
8171
|
}
|
|
7532
8172
|
function repoRoot() {
|
|
7533
8173
|
try {
|
|
7534
|
-
return
|
|
8174
|
+
return execFileSync7("git", ["rev-parse", "--show-toplevel"], {
|
|
7535
8175
|
encoding: "utf8",
|
|
7536
8176
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7537
8177
|
}).trim();
|
|
@@ -7542,7 +8182,7 @@ function repoRoot() {
|
|
|
7542
8182
|
function changedFiles(base) {
|
|
7543
8183
|
let out;
|
|
7544
8184
|
try {
|
|
7545
|
-
out =
|
|
8185
|
+
out = execFileSync7("git", ["diff", "--name-only", `${base}...HEAD`], {
|
|
7546
8186
|
encoding: "utf8",
|
|
7547
8187
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7548
8188
|
}).trim();
|
|
@@ -7567,7 +8207,7 @@ function resolveDiff(base = process.env.BASE_SHA || "origin/main") {
|
|
|
7567
8207
|
const relPaths = changedFiles(ref);
|
|
7568
8208
|
if (relPaths === null)
|
|
7569
8209
|
continue;
|
|
7570
|
-
return { base: ref, root, files: relPaths.map((p) =>
|
|
8210
|
+
return { base: ref, root, files: relPaths.map((p) => join6(root, p)) };
|
|
7571
8211
|
}
|
|
7572
8212
|
return null;
|
|
7573
8213
|
}
|
|
@@ -7613,7 +8253,7 @@ function collect(dir, out = []) {
|
|
|
7613
8253
|
return out;
|
|
7614
8254
|
}
|
|
7615
8255
|
for (const name of entries) {
|
|
7616
|
-
const full =
|
|
8256
|
+
const full = join7(dir, name);
|
|
7617
8257
|
let isDir;
|
|
7618
8258
|
try {
|
|
7619
8259
|
isDir = statSync(full).isDirectory();
|
|
@@ -7631,7 +8271,7 @@ function collect(dir, out = []) {
|
|
|
7631
8271
|
return out;
|
|
7632
8272
|
}
|
|
7633
8273
|
function readAll(paths) {
|
|
7634
|
-
return paths.map((p) => ({ path: p, content:
|
|
8274
|
+
return paths.map((p) => ({ path: p, content: readFileSync5(p, "utf8") }));
|
|
7635
8275
|
}
|
|
7636
8276
|
function toPosix(p) {
|
|
7637
8277
|
return p.split("\\").join("/");
|
|
@@ -7656,9 +8296,9 @@ function main() {
|
|
|
7656
8296
|
continue;
|
|
7657
8297
|
if (!isValidCitedFilePath(quote.citedFile))
|
|
7658
8298
|
continue;
|
|
7659
|
-
const abs =
|
|
7660
|
-
if (
|
|
7661
|
-
citedFileContents.set(quote.citedFile,
|
|
8299
|
+
const abs = join7(root, quote.citedFile);
|
|
8300
|
+
if (existsSync6(abs) && statSync(abs).isFile()) {
|
|
8301
|
+
citedFileContents.set(quote.citedFile, readFileSync5(abs, "utf8"));
|
|
7662
8302
|
}
|
|
7663
8303
|
}
|
|
7664
8304
|
const findings = evaluateCitedQuotes(citedQuotes, citedFileContents);
|