@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,7 +3,7 @@ import { createRequire } from "node:module";
|
|
|
3
3
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
4
4
|
|
|
5
5
|
// src/checks/bin/check-evidence-fresh.ts
|
|
6
|
-
import { execFileSync as
|
|
6
|
+
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
7
7
|
// ../../packages/aeg-core/src/gate-audience.ts
|
|
8
8
|
var GATE_AUDIENCE = {
|
|
9
9
|
"check-branch-topology": { shippedAs: "branch-topology", ring: 0 },
|
|
@@ -1644,6 +1644,52 @@ var systemEnv3 = {
|
|
|
1644
1644
|
...process.env,
|
|
1645
1645
|
PATH: [process.env.PATH, "/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin"].filter(Boolean).join(":")
|
|
1646
1646
|
};
|
|
1647
|
+
var defaultExec = () => execFileAsync3("git", ["remote", "get-url", "origin"], { env: systemEnv3, timeout: 5000 });
|
|
1648
|
+
var cached;
|
|
1649
|
+
var inflight;
|
|
1650
|
+
async function resolveRepo(exec = defaultExec) {
|
|
1651
|
+
if (cached !== undefined)
|
|
1652
|
+
return cached;
|
|
1653
|
+
const fromEnv = process.env.AEG_REPO;
|
|
1654
|
+
if (fromEnv) {
|
|
1655
|
+
const parsed = parseOwnerRepo(fromEnv);
|
|
1656
|
+
if (parsed) {
|
|
1657
|
+
cached = parsed;
|
|
1658
|
+
return cached;
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
if (inflight)
|
|
1662
|
+
return inflight;
|
|
1663
|
+
inflight = (async () => {
|
|
1664
|
+
try {
|
|
1665
|
+
const { stdout } = await exec();
|
|
1666
|
+
cached = parseGitRemoteUrl(stdout.trim());
|
|
1667
|
+
return cached;
|
|
1668
|
+
} catch (err) {
|
|
1669
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1670
|
+
console.warn(`[aeg-forge-state] resolveRepo: git remote lookup failed (will retry): ${message}`);
|
|
1671
|
+
return null;
|
|
1672
|
+
} finally {
|
|
1673
|
+
inflight = undefined;
|
|
1674
|
+
}
|
|
1675
|
+
})();
|
|
1676
|
+
return inflight;
|
|
1677
|
+
}
|
|
1678
|
+
function parseGitRemoteUrl(url) {
|
|
1679
|
+
const ssh = url.match(/^git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/);
|
|
1680
|
+
if (ssh?.[1] && ssh[2])
|
|
1681
|
+
return { owner: ssh[1], repo: ssh[2] };
|
|
1682
|
+
const https = url.match(/^https?:\/\/(?:[^@]+@)?github\.com\/([^/]+)\/(.+?)(?:\.git)?\/?$/);
|
|
1683
|
+
if (https?.[1] && https[2])
|
|
1684
|
+
return { owner: https[1], repo: https[2] };
|
|
1685
|
+
return null;
|
|
1686
|
+
}
|
|
1687
|
+
function parseOwnerRepo(value) {
|
|
1688
|
+
const match = value.match(/^([^/]+)\/(.+)$/);
|
|
1689
|
+
if (!match?.[1] || !match[2])
|
|
1690
|
+
return null;
|
|
1691
|
+
return { owner: match[1], repo: match[2] };
|
|
1692
|
+
}
|
|
1647
1693
|
// ../../packages/aeg-core/src/anchored-region.ts
|
|
1648
1694
|
function anchoredRegionBounds(body, field) {
|
|
1649
1695
|
const masked = maskCode(body);
|
|
@@ -1956,6 +2002,7 @@ var OBJECTIVES_VERSION_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Objectives version:\
|
|
|
1956
2002
|
var RULING_ORDINAL_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Ruling ordinal:\s*(\d+)(?!\d)/im;
|
|
1957
2003
|
var BRIEF_HASH_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Brief hash:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
|
|
1958
2004
|
var POLICY_DIGEST_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Policy digest:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
|
|
2005
|
+
var BASE_SHA_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Judged base:\s*([0-9a-f]{7,40})(?![A-Za-z0-9])/im;
|
|
1959
2006
|
function firstFiveLines(comment) {
|
|
1960
2007
|
return comment.split(`
|
|
1961
2008
|
`).slice(0, 5).join(`
|
|
@@ -1991,6 +2038,15 @@ function extractPolicyDigest(comment) {
|
|
|
1991
2038
|
const m = firstElevenLines(comment).match(POLICY_DIGEST_PATTERN);
|
|
1992
2039
|
return m ? m[1].toLowerCase() : null;
|
|
1993
2040
|
}
|
|
2041
|
+
function firstThirteenLines(comment) {
|
|
2042
|
+
return comment.split(`
|
|
2043
|
+
`).slice(0, 13).join(`
|
|
2044
|
+
`);
|
|
2045
|
+
}
|
|
2046
|
+
function extractBaseSha(comment) {
|
|
2047
|
+
const m = firstThirteenLines(comment).match(BASE_SHA_PATTERN);
|
|
2048
|
+
return m ? m[1].toLowerCase() : null;
|
|
2049
|
+
}
|
|
1994
2050
|
var FINDING_SEVERITY_LINE = /^\d+\.\s+\[([A-Z][A-Z]*)\]\s+(.+?)\s+—/gm;
|
|
1995
2051
|
function extractFindingSeverities(comment) {
|
|
1996
2052
|
return [...comment.matchAll(FINDING_SEVERITY_LINE)].map((m) => ({
|
|
@@ -2008,6 +2064,7 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
2008
2064
|
rulingOrdinal: null,
|
|
2009
2065
|
briefHash: null,
|
|
2010
2066
|
policyDigest: null,
|
|
2067
|
+
baseSha: null,
|
|
2011
2068
|
findingSeverities: [],
|
|
2012
2069
|
danglingNote: `no ${missingLabel} verdict comment found on this PR`
|
|
2013
2070
|
};
|
|
@@ -2022,6 +2079,7 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
2022
2079
|
rulingOrdinal: null,
|
|
2023
2080
|
briefHash: null,
|
|
2024
2081
|
policyDigest: null,
|
|
2082
|
+
baseSha: null,
|
|
2025
2083
|
findingSeverities: [],
|
|
2026
2084
|
danglingNote: `the most recent ${missingLabel} verdict comment carries a VERDICT-shaped line outside the first-five-line read window`
|
|
2027
2085
|
};
|
|
@@ -2033,6 +2091,7 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
2033
2091
|
rulingOrdinal: extractRulingOrdinal(latest),
|
|
2034
2092
|
briefHash: extractBriefHash(latest),
|
|
2035
2093
|
policyDigest: extractPolicyDigest(latest),
|
|
2094
|
+
baseSha: extractBaseSha(latest),
|
|
2036
2095
|
findingSeverities: extractFindingSeverities(latest),
|
|
2037
2096
|
danglingNote: null
|
|
2038
2097
|
};
|
|
@@ -3946,7 +4005,11 @@ function briefHash(brief) {
|
|
|
3946
4005
|
`).digest("hex");
|
|
3947
4006
|
}
|
|
3948
4007
|
function policyDigest(policy) {
|
|
3949
|
-
return createHash4("sha256").update(JSON.stringify({
|
|
4008
|
+
return createHash4("sha256").update(JSON.stringify({
|
|
4009
|
+
codeReviewThreshold: policy.codeReviewThreshold,
|
|
4010
|
+
securityThreshold: policy.securityThreshold,
|
|
4011
|
+
maxRounds: policy.maxRounds
|
|
4012
|
+
})).digest("hex");
|
|
3950
4013
|
}
|
|
3951
4014
|
function isBoundToHead(echoed, headSha) {
|
|
3952
4015
|
if (!echoed.headSha)
|
|
@@ -3962,8 +4025,12 @@ function isBoundByPatchIdentity(echoed, headSha, patchIdOf) {
|
|
|
3962
4025
|
return false;
|
|
3963
4026
|
return judged === current;
|
|
3964
4027
|
}
|
|
3965
|
-
function
|
|
3966
|
-
|
|
4028
|
+
function isBoundToBase(echoed, currentBase) {
|
|
4029
|
+
if (currentBase === null)
|
|
4030
|
+
return true;
|
|
4031
|
+
if (!echoed.baseSha)
|
|
4032
|
+
return false;
|
|
4033
|
+
return currentBase.toLowerCase().startsWith(echoed.baseSha.toLowerCase());
|
|
3967
4034
|
}
|
|
3968
4035
|
function isBoundToObjectives(echoed, currentVersion) {
|
|
3969
4036
|
if (currentVersion === null)
|
|
@@ -3984,14 +4051,18 @@ function isBoundToPolicy(echoed, currentDigest) {
|
|
|
3984
4051
|
return echoed.policyDigest === currentDigest;
|
|
3985
4052
|
}
|
|
3986
4053
|
function compareManifest(echoed, current, patchIdOf) {
|
|
3987
|
-
const
|
|
4054
|
+
const exactHead = isBoundToHead(echoed, current.headSha);
|
|
4055
|
+
const patchHead = exactHead ? false : isBoundByPatchIdentity(echoed, current.headSha, patchIdOf);
|
|
4056
|
+
const head = exactHead || patchHead;
|
|
4057
|
+
const base = patchHead ? true : isBoundToBase(echoed, current.baseSha);
|
|
3988
4058
|
const briefHashBound = isBoundToBriefHash(echoed, current.briefHash);
|
|
3989
4059
|
const objectivesVersion2 = isBoundToObjectives(echoed, current.objectivesVersion);
|
|
3990
4060
|
const rulingOrdinal = isBoundToRulings(echoed, current.rulingOrdinal);
|
|
3991
4061
|
const policyDigestBound = isBoundToPolicy(echoed, current.policyDigest);
|
|
3992
4062
|
return {
|
|
3993
|
-
bound: head && briefHashBound && objectivesVersion2 && rulingOrdinal && policyDigestBound,
|
|
4063
|
+
bound: head && base && briefHashBound && objectivesVersion2 && rulingOrdinal && policyDigestBound,
|
|
3994
4064
|
head,
|
|
4065
|
+
base,
|
|
3995
4066
|
briefHash: briefHashBound,
|
|
3996
4067
|
objectivesVersion: objectivesVersion2,
|
|
3997
4068
|
rulingOrdinal,
|
|
@@ -4043,6 +4114,7 @@ function checkReviewGate(input) {
|
|
|
4043
4114
|
const securityClean = securityTextClean && securityPolicyClean;
|
|
4044
4115
|
const currentManifest = {
|
|
4045
4116
|
headSha: input.headSha,
|
|
4117
|
+
baseSha: input.baseSha ?? null,
|
|
4046
4118
|
briefHash: input.briefHash ?? null,
|
|
4047
4119
|
objectivesVersion: input.objectivesVersion,
|
|
4048
4120
|
rulingOrdinal: input.rulingOrdinal,
|
|
@@ -4050,6 +4122,7 @@ function checkReviewGate(input) {
|
|
|
4050
4122
|
};
|
|
4051
4123
|
const codeReviewEchoed = {
|
|
4052
4124
|
headSha: codeReview.headSha,
|
|
4125
|
+
baseSha: codeReview.baseSha,
|
|
4053
4126
|
briefHash: codeReview.briefHash,
|
|
4054
4127
|
objectivesVersion: codeReview.objectivesVersion,
|
|
4055
4128
|
rulingOrdinal: codeReview.rulingOrdinal,
|
|
@@ -4057,6 +4130,7 @@ function checkReviewGate(input) {
|
|
|
4057
4130
|
};
|
|
4058
4131
|
const securityEchoed = {
|
|
4059
4132
|
headSha: security.headSha,
|
|
4133
|
+
baseSha: security.baseSha,
|
|
4060
4134
|
briefHash: security.briefHash,
|
|
4061
4135
|
objectivesVersion: security.objectivesVersion,
|
|
4062
4136
|
rulingOrdinal: security.rulingOrdinal,
|
|
@@ -4084,6 +4158,8 @@ function checkReviewGate(input) {
|
|
|
4084
4158
|
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`);
|
|
4085
4159
|
} else if (!codeReviewBound) {
|
|
4086
4160
|
problems.push(`the newest code-review verdict covers ${codeReview.headSha ?? "no recorded commit"}, head is ${input.headSha}`);
|
|
4161
|
+
} else if (!codeReviewBinding.base) {
|
|
4162
|
+
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)`);
|
|
4087
4163
|
} else if (!codeReviewObjectivesBound) {
|
|
4088
4164
|
problems.push(`the newest code-review verdict was cast against objectives version ${codeReview.objectivesVersion ?? "none"}, the Issue's list is now ${input.objectivesVersion}`);
|
|
4089
4165
|
} else if (!codeReviewRulingsBound) {
|
|
@@ -4099,6 +4175,8 @@ function checkReviewGate(input) {
|
|
|
4099
4175
|
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`);
|
|
4100
4176
|
} else if (!securityBound) {
|
|
4101
4177
|
problems.push(`the newest security-review verdict covers ${security.headSha ?? "no recorded commit"}, head is ${input.headSha}`);
|
|
4178
|
+
} else if (!securityBinding.base) {
|
|
4179
|
+
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)`);
|
|
4102
4180
|
} else if (!securityObjectivesBound) {
|
|
4103
4181
|
problems.push(`the newest security-review verdict was cast against objectives version ${security.objectivesVersion ?? "none"}, the Issue's list is now ${input.objectivesVersion}`);
|
|
4104
4182
|
} else if (!securityRulingsBound) {
|
|
@@ -4956,8 +5034,8 @@ var TaskToolErrorSchema = z.object({
|
|
|
4956
5034
|
detail: z.string().optional()
|
|
4957
5035
|
});
|
|
4958
5036
|
var TaskToolRefSchema = z.union([
|
|
4959
|
-
z.object({ tranche: z.string().min(1), id: z.string().min(1) }),
|
|
4960
|
-
z.object({ issue: z.number().int().positive() })
|
|
5037
|
+
z.object({ tranche: z.string().min(1), id: z.string().min(1) }).strict(),
|
|
5038
|
+
z.object({ issue: z.number().int().positive() }).strict()
|
|
4961
5039
|
]);
|
|
4962
5040
|
var MAX_PAGE_LIMIT = 100;
|
|
4963
5041
|
var PageRequestSchema = z.object({
|
|
@@ -4971,7 +5049,7 @@ var ObservedSchema = z.object({
|
|
|
4971
5049
|
});
|
|
4972
5050
|
var TaskStatusInputSchema = z.object({
|
|
4973
5051
|
task: TaskToolRefSchema.optional()
|
|
4974
|
-
}).merge(PageRequestSchema);
|
|
5052
|
+
}).merge(PageRequestSchema).strict();
|
|
4975
5053
|
var TaskStatusItemSchema = z.object({
|
|
4976
5054
|
task: TaskToolRefSchema,
|
|
4977
5055
|
issue: z.number().int().positive(),
|
|
@@ -4995,9 +5073,20 @@ var EscalationEvidenceSchema = z.object({
|
|
|
4995
5073
|
reviewer: z.string().nullable(),
|
|
4996
5074
|
security: z.string().nullable()
|
|
4997
5075
|
});
|
|
5076
|
+
var EscalationRunIdentitySchema = z.object({
|
|
5077
|
+
runId: z.string(),
|
|
5078
|
+
pid: z.number().int().positive(),
|
|
5079
|
+
host: z.string()
|
|
5080
|
+
});
|
|
5081
|
+
var EscalationInputVersionsSchema = z.object({
|
|
5082
|
+
briefHash: z.string().nullable(),
|
|
5083
|
+
objectivesVersion: z.string().nullable(),
|
|
5084
|
+
rulingOrdinal: z.number().int().nonnegative(),
|
|
5085
|
+
policyDigest: z.string()
|
|
5086
|
+
});
|
|
4998
5087
|
var TaskEscalationReadInputSchema = z.object({
|
|
4999
5088
|
task: TaskToolRefSchema
|
|
5000
|
-
}).merge(PageRequestSchema);
|
|
5089
|
+
}).merge(PageRequestSchema).strict();
|
|
5001
5090
|
var TaskEscalationPacketSchema = z.object({
|
|
5002
5091
|
reason: z.string(),
|
|
5003
5092
|
detail: z.string().nullable(),
|
|
@@ -5005,7 +5094,9 @@ var TaskEscalationPacketSchema = z.object({
|
|
|
5005
5094
|
evidence: EscalationEvidenceSchema.nullable(),
|
|
5006
5095
|
attemptedRecovery: z.string(),
|
|
5007
5096
|
requestedAuthority: RequestedAuthoritySchema,
|
|
5008
|
-
permittedNextActions: z.array(z.string())
|
|
5097
|
+
permittedNextActions: z.array(z.string()),
|
|
5098
|
+
runIdentity: EscalationRunIdentitySchema.nullable(),
|
|
5099
|
+
inputVersions: EscalationInputVersionsSchema.nullable()
|
|
5009
5100
|
}).merge(ObservedSchema);
|
|
5010
5101
|
var TaskEscalationReadResultSchema = z.object({
|
|
5011
5102
|
items: z.array(TaskEscalationPacketSchema),
|
|
@@ -5014,15 +5105,48 @@ var TaskEscalationReadResultSchema = z.object({
|
|
|
5014
5105
|
var TaskStartInputSchema = z.object({
|
|
5015
5106
|
tranche: z.string().min(1),
|
|
5016
5107
|
id: z.string().min(1)
|
|
5108
|
+
}).strict();
|
|
5109
|
+
var TaskStartResultSchema = z.object({
|
|
5110
|
+
requestId: z.string().min(1),
|
|
5111
|
+
run: z.object({ tranche: z.string().min(1), id: z.string().min(1) }),
|
|
5112
|
+
started: z.boolean(),
|
|
5113
|
+
startedAt: z.string(),
|
|
5114
|
+
mode: z.literal("attended")
|
|
5017
5115
|
});
|
|
5018
5116
|
var TaskResumeInputSchema = z.object({
|
|
5019
5117
|
task: TaskToolRefSchema
|
|
5020
|
-
});
|
|
5118
|
+
}).strict();
|
|
5021
5119
|
var TaskCancelInputSchema = z.object({
|
|
5022
5120
|
task: TaskToolRefSchema,
|
|
5023
5121
|
reason: z.string().min(1)
|
|
5122
|
+
}).strict();
|
|
5123
|
+
var TaskResumeResultSchema = z.object({
|
|
5124
|
+
task: z.number().int().positive(),
|
|
5125
|
+
pr: z.number().int().positive(),
|
|
5126
|
+
escalationId: z.string().min(1),
|
|
5127
|
+
outcome: z.enum(["started", "already_resumed"]),
|
|
5128
|
+
authenticatedBy: z.string().min(1),
|
|
5129
|
+
authenticatedFrom: z.string().min(1)
|
|
5024
5130
|
});
|
|
5025
|
-
var
|
|
5131
|
+
var TaskCancelOutcomeSchema = z.enum(["confirmed", "pending", "uncertain"]);
|
|
5132
|
+
var TaskCancelResultSchema = z.object({
|
|
5133
|
+
task: z.number().int().positive(),
|
|
5134
|
+
pr: z.number().int().positive(),
|
|
5135
|
+
escalationId: z.string().min(1),
|
|
5136
|
+
outcome: TaskCancelOutcomeSchema,
|
|
5137
|
+
authenticatedBy: z.string().min(1),
|
|
5138
|
+
authenticatedFrom: z.string().min(1),
|
|
5139
|
+
fencedEffectKeys: z.array(z.string())
|
|
5140
|
+
});
|
|
5141
|
+
var TASK_TOOL_NAMES = [
|
|
5142
|
+
"task_start",
|
|
5143
|
+
"task_status",
|
|
5144
|
+
"task_escalation_read",
|
|
5145
|
+
"task_resume",
|
|
5146
|
+
"task_cancel"
|
|
5147
|
+
];
|
|
5148
|
+
var OPERATOR_STATUS_FOLLOW = "task_status_follow";
|
|
5149
|
+
var OPERATOR_TOOL_GRANT = [...TASK_TOOL_NAMES, OPERATOR_STATUS_FOLLOW];
|
|
5026
5150
|
// ../../packages/aeg-core/src/first-push-dispatch-gate.ts
|
|
5027
5151
|
function parseTaskBranch(branch) {
|
|
5028
5152
|
const m = /^task\/([^/]+)\/([^/]+)$/.exec(branch);
|
|
@@ -5245,6 +5369,9 @@ function findWorkspaceEscapes(files, knownPaths, workspaceDirs = DEFAULT_WORKSPA
|
|
|
5245
5369
|
}
|
|
5246
5370
|
return findings;
|
|
5247
5371
|
}
|
|
5372
|
+
// ../../packages/aeg-core/src/log/envelope.ts
|
|
5373
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
5374
|
+
|
|
5248
5375
|
// ../../packages/aeg-core/src/log/schema.ts
|
|
5249
5376
|
import { z as z2 } from "zod";
|
|
5250
5377
|
var ROLE_VALUES = [
|
|
@@ -5346,7 +5473,8 @@ var DispatchOutcomeSchema = z2.discriminatedUnion("type", [
|
|
|
5346
5473
|
}).strict(),
|
|
5347
5474
|
z2.object({ type: z2.literal("brief"), comment_id: z2.number().int(), hash: z2.string() }).strict(),
|
|
5348
5475
|
z2.object({ type: z2.literal("plan"), issues: z2.array(z2.number().int()) }).strict(),
|
|
5349
|
-
z2.object({ type: z2.literal("archive"), provenance_comment_id: z2.number().int() }).strict()
|
|
5476
|
+
z2.object({ type: z2.literal("archive"), provenance_comment_id: z2.number().int() }).strict(),
|
|
5477
|
+
z2.object({ type: z2.literal("completed") }).strict()
|
|
5350
5478
|
]);
|
|
5351
5479
|
var dispatchShared = {
|
|
5352
5480
|
meta: HeaderMetaSchema,
|
|
@@ -5406,7 +5534,8 @@ var DevReviewLoopEventSchema = z2.discriminatedUnion("event", [
|
|
|
5406
5534
|
round: z2.number().int(),
|
|
5407
5535
|
head: z2.string(),
|
|
5408
5536
|
all_approve: z2.boolean(),
|
|
5409
|
-
blockers: z2.number().int().nonnegative()
|
|
5537
|
+
blockers: z2.number().int().nonnegative(),
|
|
5538
|
+
findings: z2.array(ReviewFindingSchema).optional()
|
|
5410
5539
|
}).strict(),
|
|
5411
5540
|
z2.object({
|
|
5412
5541
|
...loopShared,
|
|
@@ -5585,7 +5714,9 @@ var roleAttemptShared = {
|
|
|
5585
5714
|
kind: z2.literal("role_attempt"),
|
|
5586
5715
|
...envelopeTail,
|
|
5587
5716
|
actor: z2.string().nullable(),
|
|
5588
|
-
attempt: z2.number().int().nullable()
|
|
5717
|
+
attempt: z2.number().int().nullable(),
|
|
5718
|
+
effect_id: z2.string(),
|
|
5719
|
+
model: z2.string().nullable()
|
|
5589
5720
|
};
|
|
5590
5721
|
var RoleAttemptEventSchema = z2.discriminatedUnion("event", [
|
|
5591
5722
|
z2.object({
|
|
@@ -5644,6 +5775,144 @@ var LogEventSchema = z2.union([
|
|
|
5644
5775
|
HandoffEventSchema,
|
|
5645
5776
|
EffectEventSchema
|
|
5646
5777
|
]);
|
|
5778
|
+
|
|
5779
|
+
// ../../packages/aeg-core/src/log/envelope.ts
|
|
5780
|
+
function isRole(value) {
|
|
5781
|
+
return value !== undefined && ROLE_VALUES.includes(value);
|
|
5782
|
+
}
|
|
5783
|
+
function actorIdFromEnv(role) {
|
|
5784
|
+
return role === undefined || role === "" ? null : role;
|
|
5785
|
+
}
|
|
5786
|
+
function lineageFieldFromEnv(value) {
|
|
5787
|
+
return value === undefined || value === "" ? null : value;
|
|
5788
|
+
}
|
|
5789
|
+
function attemptFromEnv(value) {
|
|
5790
|
+
if (value === undefined || value === "")
|
|
5791
|
+
return null;
|
|
5792
|
+
const n = Number(value);
|
|
5793
|
+
return Number.isInteger(n) ? n : null;
|
|
5794
|
+
}
|
|
5795
|
+
function provenanceFor(input) {
|
|
5796
|
+
if (input.provenance)
|
|
5797
|
+
return input.provenance;
|
|
5798
|
+
if (input.env.role || input.env.task)
|
|
5799
|
+
return "env_correlated";
|
|
5800
|
+
return "unavailable";
|
|
5801
|
+
}
|
|
5802
|
+
function issueFromTask(task) {
|
|
5803
|
+
if (task === undefined || task === "")
|
|
5804
|
+
return null;
|
|
5805
|
+
const n = Number(task);
|
|
5806
|
+
return Number.isInteger(n) ? n : null;
|
|
5807
|
+
}
|
|
5808
|
+
function roundFromEnv(round) {
|
|
5809
|
+
if (round === undefined || round === "")
|
|
5810
|
+
return;
|
|
5811
|
+
const n = Number(round);
|
|
5812
|
+
return Number.isInteger(n) ? n : undefined;
|
|
5813
|
+
}
|
|
5814
|
+
function buildHeader(input) {
|
|
5815
|
+
const role = isRole(input.env.role) ? input.env.role : "unattributed";
|
|
5816
|
+
const round = roundFromEnv(input.env.round);
|
|
5817
|
+
const subject = {
|
|
5818
|
+
issue: issueFromTask(input.env.task),
|
|
5819
|
+
role,
|
|
5820
|
+
...round !== undefined ? { round } : {},
|
|
5821
|
+
...input.subject ?? {}
|
|
5822
|
+
};
|
|
5823
|
+
return {
|
|
5824
|
+
meta: {
|
|
5825
|
+
schema: 2,
|
|
5826
|
+
ts: input.now.toISOString(),
|
|
5827
|
+
run_id: input.runId,
|
|
5828
|
+
seq: input.seq,
|
|
5829
|
+
repo: input.repo,
|
|
5830
|
+
vinaya: input.vinaya,
|
|
5831
|
+
doctrine: input.doctrine,
|
|
5832
|
+
host: input.host,
|
|
5833
|
+
machine: createHash5("sha256").update(input.hostname).digest("hex"),
|
|
5834
|
+
event_id: input.eventId,
|
|
5835
|
+
process_id: input.processId,
|
|
5836
|
+
actor_id: actorIdFromEnv(input.env.role),
|
|
5837
|
+
lineage: {
|
|
5838
|
+
run: lineageFieldFromEnv(input.env.run),
|
|
5839
|
+
attempt: attemptFromEnv(input.env.attempt),
|
|
5840
|
+
parent: lineageFieldFromEnv(input.env.parent)
|
|
5841
|
+
},
|
|
5842
|
+
input_versions: {
|
|
5843
|
+
objectives_version: input.inputVersions?.objectivesVersion ?? null,
|
|
5844
|
+
brief_hash: input.inputVersions?.briefHash ?? null,
|
|
5845
|
+
ruling_ordinal: input.inputVersions?.rulingOrdinal ?? null,
|
|
5846
|
+
policy_digest: input.inputVersions?.policyDigest ?? null
|
|
5847
|
+
},
|
|
5848
|
+
provenance: provenanceFor(input)
|
|
5849
|
+
},
|
|
5850
|
+
subject
|
|
5851
|
+
};
|
|
5852
|
+
}
|
|
5853
|
+
// ../../packages/aeg-core/src/log/redact.ts
|
|
5854
|
+
var GITHUB_TOKEN_PATTERN = /\b(?:gho_|ghp_|ghs_|ghu_|ghr_|github_pat_)[A-Za-z0-9_]+\b/g;
|
|
5855
|
+
var CLASSIC_GITHUB_PAT_PATTERN = /\b((?:token|GITHUB_TOKEN|PAT|api[_-]?key|api[_-]?token)\s*[:=]\s*)[a-f0-9]{40}\b/gi;
|
|
5856
|
+
var BEARER_TOKEN_PATTERN = /\bBearer\s+\S+/g;
|
|
5857
|
+
var AWS_ACCESS_KEY_PATTERN = /\bAKIA[0-9A-Z]{16}\b/g;
|
|
5858
|
+
var SLACK_TOKEN_PATTERN = /\bxox[baprs]-[0-9A-Za-z-]+\b/g;
|
|
5859
|
+
var STRIPE_KEY_PATTERN = /\b(?:sk|pk|rk)_(?:live|test)_[0-9A-Za-z]{10,}\b/g;
|
|
5860
|
+
var ANTHROPIC_KEY_PATTERN = /\bsk-ant-[A-Za-z0-9_-]{20,}\b/g;
|
|
5861
|
+
var OPENAI_KEY_PATTERN = /\bsk-(?!ant-)[A-Za-z0-9]{20,}\b/g;
|
|
5862
|
+
var NPM_TOKEN_PATTERN = /\bnpm_[A-Za-z0-9]{36}\b/g;
|
|
5863
|
+
var JWT_PATTERN = /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g;
|
|
5864
|
+
var PEM_BLOCK_PATTERN = /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g;
|
|
5865
|
+
var BASIC_AUTH_URL_PATTERN = /(https?:\/\/)[^/\s:@]+:[^/\s@]+@/g;
|
|
5866
|
+
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;
|
|
5867
|
+
function redactString(value, home) {
|
|
5868
|
+
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>");
|
|
5869
|
+
if (home.length > 0 && out.startsWith(home)) {
|
|
5870
|
+
const rest = out.slice(home.length);
|
|
5871
|
+
if (rest === "" || rest.startsWith("/"))
|
|
5872
|
+
out = `~${rest}`;
|
|
5873
|
+
}
|
|
5874
|
+
return out;
|
|
5875
|
+
}
|
|
5876
|
+
function redact(value, home) {
|
|
5877
|
+
if (typeof value === "string")
|
|
5878
|
+
return redactString(value, home);
|
|
5879
|
+
if (Array.isArray(value))
|
|
5880
|
+
return value.map((v) => redact(v, home));
|
|
5881
|
+
if (value !== null && typeof value === "object") {
|
|
5882
|
+
const out = {};
|
|
5883
|
+
for (const [k, v] of Object.entries(value)) {
|
|
5884
|
+
out[k] = redact(v, home);
|
|
5885
|
+
}
|
|
5886
|
+
return out;
|
|
5887
|
+
}
|
|
5888
|
+
return value;
|
|
5889
|
+
}
|
|
5890
|
+
// ../../packages/aeg-core/src/log/store.ts
|
|
5891
|
+
function metaOf(obj) {
|
|
5892
|
+
if (obj === null || typeof obj !== "object")
|
|
5893
|
+
return null;
|
|
5894
|
+
const meta = obj.meta;
|
|
5895
|
+
if (meta === null || typeof meta !== "object")
|
|
5896
|
+
return null;
|
|
5897
|
+
return meta;
|
|
5898
|
+
}
|
|
5899
|
+
function recordIdentity(obj) {
|
|
5900
|
+
const meta = metaOf(obj);
|
|
5901
|
+
if (meta === null)
|
|
5902
|
+
return null;
|
|
5903
|
+
const eventId = meta.event_id;
|
|
5904
|
+
if (typeof eventId === "string" && eventId.length > 0)
|
|
5905
|
+
return eventId;
|
|
5906
|
+
const runId = meta.run_id;
|
|
5907
|
+
const seq = meta.seq;
|
|
5908
|
+
if (typeof runId === "string" && runId.length > 0 && typeof seq === "number" && Number.isInteger(seq)) {
|
|
5909
|
+
return `${runId}:${seq}`;
|
|
5910
|
+
}
|
|
5911
|
+
return null;
|
|
5912
|
+
}
|
|
5913
|
+
|
|
5914
|
+
// ../../packages/aeg-core/src/log/artifact.ts
|
|
5915
|
+
var TASK_LOG_ARTIFACT_MAX_BYTES = 8 * 1024 * 1024;
|
|
5647
5916
|
// ../../packages/aeg-core/src/dev-review-loop/journal-reconstruction.ts
|
|
5648
5917
|
var STOPPED_CONDITIONS = new Set(["confidence", "reappearance", "no_progress", "max_rounds"]);
|
|
5649
5918
|
// ../../packages/aeg-core/src/control-store/records.ts
|
|
@@ -5658,7 +5927,9 @@ var RunRecordSchema = z3.object({
|
|
|
5658
5927
|
runId: z3.string().min(1),
|
|
5659
5928
|
pid: z3.number().int().positive(),
|
|
5660
5929
|
host: z3.string().min(1),
|
|
5661
|
-
startedAt: isoTimestamp
|
|
5930
|
+
startedAt: isoTimestamp,
|
|
5931
|
+
childStartedAt: z3.string().min(1).nullable().optional(),
|
|
5932
|
+
childCommand: z3.string().min(1).nullable().optional()
|
|
5662
5933
|
}).strict();
|
|
5663
5934
|
var InputRecordSchema = z3.object({
|
|
5664
5935
|
version: z3.literal(1),
|
|
@@ -5691,6 +5962,88 @@ var TransitionRecordSchema = z3.object({
|
|
|
5691
5962
|
detail: z3.string().optional(),
|
|
5692
5963
|
at: isoTimestamp
|
|
5693
5964
|
}).strict();
|
|
5965
|
+
var ManifestRecordSchema = z3.object({
|
|
5966
|
+
version: z3.literal(1),
|
|
5967
|
+
kind: z3.literal("manifest"),
|
|
5968
|
+
task: taskId,
|
|
5969
|
+
round: epochNumber,
|
|
5970
|
+
repository: z3.string().min(1),
|
|
5971
|
+
pr: z3.number().int().positive(),
|
|
5972
|
+
branch: z3.string().min(1),
|
|
5973
|
+
baseSha: z3.string().min(1).nullable(),
|
|
5974
|
+
headSha: z3.string().min(1),
|
|
5975
|
+
briefHash: z3.string().min(1).nullable(),
|
|
5976
|
+
objectivesVersion: z3.string().min(1).nullable(),
|
|
5977
|
+
rulingOrdinal: epochNumber,
|
|
5978
|
+
policyDigest: z3.string().min(1),
|
|
5979
|
+
recordedAt: isoTimestamp
|
|
5980
|
+
}).strict();
|
|
5981
|
+
var roundHeadIdentity = z3.object({ round: z3.number().int().positive(), head: z3.string().min(1) }).strict();
|
|
5982
|
+
var LoopBudgetsSchema = z3.object({
|
|
5983
|
+
mechanicalRetries: z3.number().int().nonnegative(),
|
|
5984
|
+
reviewRounds: z3.number().int().nonnegative(),
|
|
5985
|
+
infrastructureRetries: z3.number().int().nonnegative()
|
|
5986
|
+
}).strict();
|
|
5987
|
+
var LoopStateRecordSchema = z3.object({
|
|
5988
|
+
version: z3.literal(1),
|
|
5989
|
+
kind: z3.literal("loop_state"),
|
|
5990
|
+
task: taskId,
|
|
5991
|
+
round: z3.number().int().positive(),
|
|
5992
|
+
phase: z3.string().min(1),
|
|
5993
|
+
pauseReason: z3.string().min(1).nullable(),
|
|
5994
|
+
budgets: LoopBudgetsSchema,
|
|
5995
|
+
heldResult: roundHeadIdentity.nullable(),
|
|
5996
|
+
deliveredFindings: roundHeadIdentity.nullable(),
|
|
5997
|
+
recordedAt: isoTimestamp
|
|
5998
|
+
}).strict();
|
|
5999
|
+
var EffectRecordSchema = z3.object({
|
|
6000
|
+
version: z3.literal(1),
|
|
6001
|
+
kind: z3.literal("effect"),
|
|
6002
|
+
task: taskId,
|
|
6003
|
+
key: z3.string().min(1),
|
|
6004
|
+
operation: z3.string().min(1),
|
|
6005
|
+
target: z3.string().min(1),
|
|
6006
|
+
inputVersion: z3.number().int().nonnegative(),
|
|
6007
|
+
payloadDigest: z3.string().min(1),
|
|
6008
|
+
status: z3.union([z3.literal("started"), z3.literal("verified"), z3.literal("uncertain")]),
|
|
6009
|
+
url: z3.string().optional(),
|
|
6010
|
+
recordedAt: isoTimestamp
|
|
6011
|
+
}).strict();
|
|
6012
|
+
var EscalationRecordSchema = z3.object({
|
|
6013
|
+
version: z3.literal(1),
|
|
6014
|
+
kind: z3.literal("escalation"),
|
|
6015
|
+
task: taskId,
|
|
6016
|
+
escalationId: z3.string().min(1),
|
|
6017
|
+
round: epochNumber,
|
|
6018
|
+
head: z3.string().min(1),
|
|
6019
|
+
branch: z3.string().min(1),
|
|
6020
|
+
pr: z3.number().int().positive().nullable(),
|
|
6021
|
+
runId: z3.string().min(1),
|
|
6022
|
+
pid: z3.number().int().positive(),
|
|
6023
|
+
host: z3.string().min(1),
|
|
6024
|
+
agent: z3.string().min(1).optional(),
|
|
6025
|
+
reason: z3.string().min(1),
|
|
6026
|
+
detail: z3.string().optional(),
|
|
6027
|
+
evidence: z3.string().optional(),
|
|
6028
|
+
attemptedRecovery: z3.string().min(1),
|
|
6029
|
+
requestedDecision: z3.string().min(1),
|
|
6030
|
+
recipient: z3.string().min(1),
|
|
6031
|
+
briefHash: z3.string().min(1).nullable(),
|
|
6032
|
+
objectivesVersion: z3.string().min(1).nullable(),
|
|
6033
|
+
rulingOrdinal: epochNumber,
|
|
6034
|
+
policyDigest: z3.string().min(1),
|
|
6035
|
+
recordedAt: isoTimestamp
|
|
6036
|
+
}).strict();
|
|
6037
|
+
var ResolutionRecordSchema = z3.object({
|
|
6038
|
+
version: z3.literal(1),
|
|
6039
|
+
kind: z3.literal("resolution"),
|
|
6040
|
+
task: taskId,
|
|
6041
|
+
escalationId: z3.string().min(1),
|
|
6042
|
+
decision: z3.union([z3.literal("resume"), z3.literal("cancel")]),
|
|
6043
|
+
authenticatedBy: z3.string().min(1),
|
|
6044
|
+
authenticatedFrom: z3.string().min(1),
|
|
6045
|
+
consumedAt: isoTimestamp
|
|
6046
|
+
}).strict();
|
|
5694
6047
|
// src/checks/registry.ts
|
|
5695
6048
|
import { existsSync as existsSync2 } from "node:fs";
|
|
5696
6049
|
import { join as join2 } from "node:path";
|
|
@@ -6250,90 +6603,22 @@ function coreCheckRegistry() {
|
|
|
6250
6603
|
}
|
|
6251
6604
|
var CORE_CHECK_RING = Object.fromEntries(REGISTRY.map(([spec, ring]) => [spec.name, ring]));
|
|
6252
6605
|
|
|
6253
|
-
// src/
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
let binary = 0;
|
|
6270
|
-
for (const row of rows) {
|
|
6271
|
-
const [a, d] = row.split("\t");
|
|
6272
|
-
if (a === "-" || d === "-") {
|
|
6273
|
-
binary++;
|
|
6274
|
-
continue;
|
|
6275
|
-
}
|
|
6276
|
-
added += Number(a) || 0;
|
|
6277
|
-
deleted += Number(d) || 0;
|
|
6278
|
-
}
|
|
6279
|
-
const files = `${rows.length} file${rows.length === 1 ? "" : "s"} changed`;
|
|
6280
|
-
const bin2 = binary > 0 ? `, ${binary} binary` : "";
|
|
6281
|
-
return `${files}, ${added} insertion${added === 1 ? "" : "s"}(+), ${deleted} deletion${deleted === 1 ? "" : "s"}(-)${bin2}`;
|
|
6282
|
-
}
|
|
6283
|
-
var EVIDENCE_SUMMARY_PREFIX = "Summary: ";
|
|
6284
|
-
|
|
6285
|
-
// src/checks/scan-context.ts
|
|
6286
|
-
var ZERO_WIDTH = /[\u200B-\u200D\u2060\uFEFF]/g;
|
|
6287
|
-
var HTML_ENTITIES = {
|
|
6288
|
-
""": '"',
|
|
6289
|
-
"'": "'",
|
|
6290
|
-
"<": "<",
|
|
6291
|
-
">": ">",
|
|
6292
|
-
"&": "&"
|
|
6293
|
-
};
|
|
6294
|
-
function decodeNamedEntities(body) {
|
|
6295
|
-
return body.replace(/&(?:quot|apos|lt|gt|amp);/g, (m) => HTML_ENTITIES[m] ?? m);
|
|
6296
|
-
}
|
|
6297
|
-
function normalizeBody(rawBody) {
|
|
6298
|
-
return decodeNamedEntities(rawBody.replace(ZERO_WIDTH, ""));
|
|
6299
|
-
}
|
|
6300
|
-
function buildAnchorLookupMask(body) {
|
|
6301
|
-
return maskDetailsBlocks(maskCode(body));
|
|
6302
|
-
}
|
|
6303
|
-
|
|
6304
|
-
class ScanContext {
|
|
6305
|
-
raw;
|
|
6306
|
-
normalised;
|
|
6307
|
-
masked;
|
|
6308
|
-
constructor(raw, normalised, masked) {
|
|
6309
|
-
this.raw = raw;
|
|
6310
|
-
this.normalised = normalised;
|
|
6311
|
-
this.masked = masked;
|
|
6312
|
-
}
|
|
6313
|
-
static from(rawBody) {
|
|
6314
|
-
const normalised = normalizeBody(rawBody);
|
|
6315
|
-
return new ScanContext(rawBody, normalised, buildAnchorLookupMask(normalised));
|
|
6316
|
-
}
|
|
6317
|
-
rawResolutionAgrees(field) {
|
|
6318
|
-
const rawHasPair = anchoredRegionBounds(this.raw, field) !== null;
|
|
6319
|
-
return rawHasPair === (anchoredRegionBounds(this.masked, field) !== null);
|
|
6320
|
-
}
|
|
6321
|
-
}
|
|
6322
|
-
function resolveAnchoredRegion(ctx, field) {
|
|
6323
|
-
const bounds = anchoredRegionBounds(ctx.masked, field);
|
|
6324
|
-
if (bounds === null) {
|
|
6325
|
-
return anchoredRegionBounds(ctx.normalised, field) !== null ? "hidden" : null;
|
|
6326
|
-
}
|
|
6327
|
-
return {
|
|
6328
|
-
region: ctx.normalised.slice(bounds.innerStart, bounds.innerEnd),
|
|
6329
|
-
maskedRegion: ctx.masked.slice(bounds.innerStart, bounds.innerEnd)
|
|
6330
|
-
};
|
|
6331
|
-
}
|
|
6332
|
-
function summaryLineIndex(maskedRegion) {
|
|
6333
|
-
const index = maskedRegion.split(`
|
|
6334
|
-
`).findIndex((line) => line.startsWith(EVIDENCE_SUMMARY_PREFIX));
|
|
6335
|
-
return index === -1 ? null : index;
|
|
6336
|
-
}
|
|
6606
|
+
// src/lib/log-sink.ts
|
|
6607
|
+
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
6608
|
+
import { randomUUID } from "node:crypto";
|
|
6609
|
+
import {
|
|
6610
|
+
closeSync as closeSync2,
|
|
6611
|
+
constants as fsConstants2,
|
|
6612
|
+
existsSync as existsSync4,
|
|
6613
|
+
fstatSync as fstatSync2,
|
|
6614
|
+
mkdirSync as mkdirSync2,
|
|
6615
|
+
openSync as openSync2,
|
|
6616
|
+
readFileSync as readFileSync3,
|
|
6617
|
+
renameSync,
|
|
6618
|
+
writeSync
|
|
6619
|
+
} from "node:fs";
|
|
6620
|
+
import { hostname as osHostname, homedir as homedir2 } from "node:os";
|
|
6621
|
+
import { dirname as dirname3, join as join4 } from "node:path";
|
|
6337
6622
|
|
|
6338
6623
|
// src/lib/config.ts
|
|
6339
6624
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
@@ -6515,6 +6800,13 @@ var VinayaConfigSchema = z4.object({
|
|
|
6515
6800
|
message: "must be at most 3600000 (1 hour)"
|
|
6516
6801
|
});
|
|
6517
6802
|
}
|
|
6803
|
+
}).optional(),
|
|
6804
|
+
logPublish: z4.object({
|
|
6805
|
+
issue: z4.number().int().positive().optional(),
|
|
6806
|
+
pr: z4.number().int().positive().optional(),
|
|
6807
|
+
maxChunksPerFlush: z4.number().int().positive().optional()
|
|
6808
|
+
}).refine((v) => !(v.issue !== undefined && v.pr !== undefined), {
|
|
6809
|
+
message: "logPublish: set at most one of issue/pr, not both"
|
|
6518
6810
|
}).optional()
|
|
6519
6811
|
});
|
|
6520
6812
|
var GLOBAL_VINAYA_HOME = join3(homedir(), ".vinaya");
|
|
@@ -6690,8 +6982,331 @@ function loadConfig() {
|
|
|
6690
6982
|
}
|
|
6691
6983
|
var TOKENS_COLLECT_TRUST_PATH = join3(GLOBAL_VINAYA_HOME, "tokens-collect-trust.json");
|
|
6692
6984
|
|
|
6985
|
+
// src/lib/log-sink.ts
|
|
6986
|
+
var OUTBOX_MAX_BYTES = 8 * 1024 * 1024;
|
|
6987
|
+
function isEnoent(err) {
|
|
6988
|
+
return typeof err === "object" && err !== null && err.code === "ENOENT";
|
|
6989
|
+
}
|
|
6990
|
+
function resolveDoctrine(cwd, vinayaVersion) {
|
|
6991
|
+
let toplevel;
|
|
6992
|
+
try {
|
|
6993
|
+
toplevel = execFileSync3("git", ["-C", cwd, "rev-parse", "--show-toplevel"], {
|
|
6994
|
+
encoding: "utf8",
|
|
6995
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
6996
|
+
}).trim();
|
|
6997
|
+
} catch (err) {
|
|
6998
|
+
return isEnoent(err) ? "unknown" : vinayaVersion;
|
|
6999
|
+
}
|
|
7000
|
+
if (!existsSync4(join4(toplevel, "aeg-root", "roles")))
|
|
7001
|
+
return vinayaVersion;
|
|
7002
|
+
try {
|
|
7003
|
+
const sha = execFileSync3("git", ["-C", toplevel, "rev-parse", "HEAD:aeg-root"], {
|
|
7004
|
+
encoding: "utf8",
|
|
7005
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
7006
|
+
}).trim();
|
|
7007
|
+
return `aeg-root@${sha}`;
|
|
7008
|
+
} catch {
|
|
7009
|
+
return vinayaVersion;
|
|
7010
|
+
}
|
|
7011
|
+
}
|
|
7012
|
+
function readVinayaVersion() {
|
|
7013
|
+
try {
|
|
7014
|
+
const pkg = JSON.parse(readFileSync3(join4(packageRoot(import.meta.url), "package.json"), "utf8"));
|
|
7015
|
+
return pkg.version ?? "unknown";
|
|
7016
|
+
} catch {
|
|
7017
|
+
return "unknown";
|
|
7018
|
+
}
|
|
7019
|
+
}
|
|
7020
|
+
var SAFE_PATH_SEGMENT = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/;
|
|
7021
|
+
function isSafeRepoSegment(segment) {
|
|
7022
|
+
return SAFE_PATH_SEGMENT.test(segment) && !segment.includes("..");
|
|
7023
|
+
}
|
|
7024
|
+
function outboxPathFor(deps, repo, issue) {
|
|
7025
|
+
const dirName = repo ? `${repo.owner}-${repo.repo}` : "unresolved";
|
|
7026
|
+
const fileName = `${issue ?? "none"}.ndjson`;
|
|
7027
|
+
return join4(deps.outboxRoot(), dirName, fileName);
|
|
7028
|
+
}
|
|
7029
|
+
function hostFromEnv(env) {
|
|
7030
|
+
if (env.GITHUB_ACTIONS)
|
|
7031
|
+
return "ci";
|
|
7032
|
+
if (env.VINAYA_HOST === "hook")
|
|
7033
|
+
return "hook";
|
|
7034
|
+
if (env.VINAYA_HOST === "loop")
|
|
7035
|
+
return "loop";
|
|
7036
|
+
return "cli";
|
|
7037
|
+
}
|
|
7038
|
+
function defaultDeps() {
|
|
7039
|
+
return {
|
|
7040
|
+
outboxRoot: () => join4(GLOBAL_VINAYA_HOME, "outbox"),
|
|
7041
|
+
home: () => homedir2(),
|
|
7042
|
+
hostname: () => osHostname(),
|
|
7043
|
+
cwd: () => process.cwd(),
|
|
7044
|
+
now: () => new Date,
|
|
7045
|
+
env: () => process.env,
|
|
7046
|
+
resolveRepo: () => resolveRepo(),
|
|
7047
|
+
vinayaVersion: () => readVinayaVersion(),
|
|
7048
|
+
stderr: (message) => {
|
|
7049
|
+
process.stderr.write(message);
|
|
7050
|
+
},
|
|
7051
|
+
inputVersions: () => {
|
|
7052
|
+
return;
|
|
7053
|
+
}
|
|
7054
|
+
};
|
|
7055
|
+
}
|
|
7056
|
+
var APPEND_OPEN_FLAGS = fsConstants2.O_WRONLY | fsConstants2.O_APPEND | fsConstants2.O_CREAT | fsConstants2.O_NOFOLLOW | fsConstants2.O_NONBLOCK;
|
|
7057
|
+
function guardedAppendOpen(path) {
|
|
7058
|
+
try {
|
|
7059
|
+
return openSync2(path, APPEND_OPEN_FLAGS, 384);
|
|
7060
|
+
} catch {
|
|
7061
|
+
return;
|
|
7062
|
+
}
|
|
7063
|
+
}
|
|
7064
|
+
function reportRotationOverflow(backupPath, warn) {
|
|
7065
|
+
let raw;
|
|
7066
|
+
try {
|
|
7067
|
+
raw = readFileSync3(backupPath, "utf8");
|
|
7068
|
+
} catch {
|
|
7069
|
+
return;
|
|
7070
|
+
}
|
|
7071
|
+
const lines = raw.split(`
|
|
7072
|
+
`).filter((l) => l.length > 0);
|
|
7073
|
+
if (lines.length === 0)
|
|
7074
|
+
return;
|
|
7075
|
+
const droppedIdentities = lines.map((line, i) => {
|
|
7076
|
+
try {
|
|
7077
|
+
return recordIdentity(JSON.parse(line)) ?? `unreadable:${i}`;
|
|
7078
|
+
} catch {
|
|
7079
|
+
return `unreadable:${i}`;
|
|
7080
|
+
}
|
|
7081
|
+
});
|
|
7082
|
+
const diagnostic = { reason: "capacity", dropped: droppedIdentities.length, droppedIdentities };
|
|
7083
|
+
const shown = diagnostic.droppedIdentities.slice(0, 20);
|
|
7084
|
+
const more = diagnostic.dropped > shown.length ? `, +${diagnostic.dropped - shown.length} more` : "";
|
|
7085
|
+
warn(`vinaya: log outbox rotation is overwriting ${backupPath} — ${diagnostic.dropped} record(s) permanently lost: ${shown.join(", ")}${more}
|
|
7086
|
+
`);
|
|
7087
|
+
}
|
|
7088
|
+
function appendLine(path, line, warn) {
|
|
7089
|
+
try {
|
|
7090
|
+
mkdirSync2(dirname3(path), { recursive: true, mode: 448 });
|
|
7091
|
+
let fd = guardedAppendOpen(path);
|
|
7092
|
+
if (fd === undefined) {
|
|
7093
|
+
warn(`vinaya: log outbox target could not be opened (symlink, FIFO, or unwritable) — refusing: ${path}
|
|
7094
|
+
`);
|
|
7095
|
+
return;
|
|
7096
|
+
}
|
|
7097
|
+
let closed = false;
|
|
7098
|
+
try {
|
|
7099
|
+
const stat = fstatSync2(fd);
|
|
7100
|
+
if (!stat.isFile()) {
|
|
7101
|
+
warn(`vinaya: log outbox target is not a regular file — refusing to write: ${path}
|
|
7102
|
+
`);
|
|
7103
|
+
return;
|
|
7104
|
+
}
|
|
7105
|
+
if (stat.size > OUTBOX_MAX_BYTES) {
|
|
7106
|
+
closeSync2(fd);
|
|
7107
|
+
closed = true;
|
|
7108
|
+
const backupPath = path.replace(/\.ndjson$/, ".1.ndjson");
|
|
7109
|
+
reportRotationOverflow(backupPath, warn);
|
|
7110
|
+
renameSync(path, backupPath);
|
|
7111
|
+
const rotated = guardedAppendOpen(path);
|
|
7112
|
+
if (rotated === undefined) {
|
|
7113
|
+
warn(`vinaya: log outbox target could not be reopened after rotation — refusing: ${path}
|
|
7114
|
+
`);
|
|
7115
|
+
return;
|
|
7116
|
+
}
|
|
7117
|
+
fd = rotated;
|
|
7118
|
+
closed = false;
|
|
7119
|
+
}
|
|
7120
|
+
writeSync(fd, line);
|
|
7121
|
+
} finally {
|
|
7122
|
+
if (!closed)
|
|
7123
|
+
closeSync2(fd);
|
|
7124
|
+
}
|
|
7125
|
+
} catch (err) {
|
|
7126
|
+
warn(`vinaya: log outbox write failed — ${err instanceof Error ? err.message : String(err)}
|
|
7127
|
+
`);
|
|
7128
|
+
}
|
|
7129
|
+
}
|
|
7130
|
+
function createLogSink(overrides = {}) {
|
|
7131
|
+
const deps = { ...defaultDeps(), ...overrides };
|
|
7132
|
+
const runId = deps.env().VINAYA_RUN_ID || randomUUID();
|
|
7133
|
+
const processId = randomUUID();
|
|
7134
|
+
let seq = 0;
|
|
7135
|
+
let warned = false;
|
|
7136
|
+
const warnOnce = (message) => {
|
|
7137
|
+
if (warned)
|
|
7138
|
+
return;
|
|
7139
|
+
warned = true;
|
|
7140
|
+
try {
|
|
7141
|
+
deps.stderr(message);
|
|
7142
|
+
} catch {}
|
|
7143
|
+
};
|
|
7144
|
+
let doctrineCache;
|
|
7145
|
+
const doctrine = () => {
|
|
7146
|
+
if (doctrineCache === undefined)
|
|
7147
|
+
doctrineCache = resolveDoctrine(deps.cwd(), deps.vinayaVersion());
|
|
7148
|
+
return doctrineCache;
|
|
7149
|
+
};
|
|
7150
|
+
let resolveRepoCache;
|
|
7151
|
+
const resolveRepoOnce = () => {
|
|
7152
|
+
if (resolveRepoCache === undefined)
|
|
7153
|
+
resolveRepoCache = deps.resolveRepo();
|
|
7154
|
+
return resolveRepoCache;
|
|
7155
|
+
};
|
|
7156
|
+
function log(e) {
|
|
7157
|
+
try {
|
|
7158
|
+
const env = deps.env();
|
|
7159
|
+
const host = hostFromEnv(env);
|
|
7160
|
+
const now = deps.now();
|
|
7161
|
+
const mySeq = seq++;
|
|
7162
|
+
resolveRepoOnce().then((resolved) => {
|
|
7163
|
+
const repo = resolved && isSafeRepoSegment(resolved.owner) && isSafeRepoSegment(resolved.repo) ? resolved : null;
|
|
7164
|
+
const header = buildHeader({
|
|
7165
|
+
now,
|
|
7166
|
+
runId,
|
|
7167
|
+
seq: mySeq,
|
|
7168
|
+
repo: repo ? `${repo.owner}/${repo.repo}` : null,
|
|
7169
|
+
vinaya: deps.vinayaVersion(),
|
|
7170
|
+
doctrine: doctrine(),
|
|
7171
|
+
host,
|
|
7172
|
+
hostname: deps.hostname(),
|
|
7173
|
+
env: {
|
|
7174
|
+
role: env.VINAYA_ROLE,
|
|
7175
|
+
task: env.VINAYA_TASK,
|
|
7176
|
+
round: env.VINAYA_ROUND,
|
|
7177
|
+
run: env.VINAYA_RUN,
|
|
7178
|
+
attempt: env.VINAYA_ATTEMPT,
|
|
7179
|
+
parent: env.VINAYA_PARENT_EVENT
|
|
7180
|
+
},
|
|
7181
|
+
eventId: randomUUID(),
|
|
7182
|
+
processId,
|
|
7183
|
+
inputVersions: deps.inputVersions()
|
|
7184
|
+
});
|
|
7185
|
+
const full = { ...e, ...header };
|
|
7186
|
+
const parsed = LogEventSchema.safeParse(full);
|
|
7187
|
+
if (!parsed.success) {
|
|
7188
|
+
warnOnce(`vinaya: log() refused an invalid payload — ${parsed.error.issues[0]?.message ?? "schema violation"}
|
|
7189
|
+
`);
|
|
7190
|
+
return;
|
|
7191
|
+
}
|
|
7192
|
+
const line = `${JSON.stringify(redact(parsed.data, deps.home()))}
|
|
7193
|
+
`;
|
|
7194
|
+
appendLine(outboxPathFor(deps, repo, header.subject.issue), line, warnOnce);
|
|
7195
|
+
}).catch((err) => {
|
|
7196
|
+
warnOnce(`vinaya: log() failed — ${err instanceof Error ? err.message : String(err)}
|
|
7197
|
+
`);
|
|
7198
|
+
});
|
|
7199
|
+
} catch (err) {
|
|
7200
|
+
warnOnce(`vinaya: log() failed — ${err instanceof Error ? err.message : String(err)}
|
|
7201
|
+
`);
|
|
7202
|
+
}
|
|
7203
|
+
}
|
|
7204
|
+
const warmup = () => {
|
|
7205
|
+
doctrine();
|
|
7206
|
+
const originalWarn = console.warn;
|
|
7207
|
+
console.warn = () => {};
|
|
7208
|
+
resolveRepoOnce().finally(() => {
|
|
7209
|
+
console.warn = originalWarn;
|
|
7210
|
+
});
|
|
7211
|
+
};
|
|
7212
|
+
return { log, runId, warmup };
|
|
7213
|
+
}
|
|
7214
|
+
var defaultSink = createLogSink();
|
|
7215
|
+
|
|
7216
|
+
// src/checks/contract.ts
|
|
7217
|
+
var CHECK_SCHEMA_VERSION = 1;
|
|
7218
|
+
function emitCheckError(error) {
|
|
7219
|
+
process.stderr.write(`${JSON.stringify(error)}
|
|
7220
|
+
`);
|
|
7221
|
+
}
|
|
7222
|
+
|
|
7223
|
+
// src/checks/runner.ts
|
|
7224
|
+
var activeChecks = new Map;
|
|
7225
|
+
|
|
7226
|
+
// src/lib/numstat.ts
|
|
7227
|
+
function summariseNumstat(numstat) {
|
|
7228
|
+
const rows = numstat.split(`
|
|
7229
|
+
`).filter((l) => l.trim() !== "");
|
|
7230
|
+
let added = 0;
|
|
7231
|
+
let deleted = 0;
|
|
7232
|
+
let binary = 0;
|
|
7233
|
+
for (const row of rows) {
|
|
7234
|
+
const [a, d] = row.split("\t");
|
|
7235
|
+
if (a === "-" || d === "-") {
|
|
7236
|
+
binary++;
|
|
7237
|
+
continue;
|
|
7238
|
+
}
|
|
7239
|
+
added += Number(a) || 0;
|
|
7240
|
+
deleted += Number(d) || 0;
|
|
7241
|
+
}
|
|
7242
|
+
const files = `${rows.length} file${rows.length === 1 ? "" : "s"} changed`;
|
|
7243
|
+
const bin2 = binary > 0 ? `, ${binary} binary` : "";
|
|
7244
|
+
return `${files}, ${added} insertion${added === 1 ? "" : "s"}(+), ${deleted} deletion${deleted === 1 ? "" : "s"}(-)${bin2}`;
|
|
7245
|
+
}
|
|
7246
|
+
var EVIDENCE_SUMMARY_PREFIX = "Summary: ";
|
|
7247
|
+
|
|
7248
|
+
// src/checks/scan-context.ts
|
|
7249
|
+
var ZERO_WIDTH = /[\u200B-\u200D\u2060\uFEFF]/g;
|
|
7250
|
+
var HTML_ENTITIES = {
|
|
7251
|
+
""": '"',
|
|
7252
|
+
"'": "'",
|
|
7253
|
+
"<": "<",
|
|
7254
|
+
">": ">",
|
|
7255
|
+
"&": "&"
|
|
7256
|
+
};
|
|
7257
|
+
function decodeNamedEntities(body) {
|
|
7258
|
+
return body.replace(/&(?:quot|apos|lt|gt|amp);/g, (m) => HTML_ENTITIES[m] ?? m);
|
|
7259
|
+
}
|
|
7260
|
+
function normalizeBody(rawBody) {
|
|
7261
|
+
return decodeNamedEntities(rawBody.replace(ZERO_WIDTH, ""));
|
|
7262
|
+
}
|
|
7263
|
+
function buildAnchorLookupMask(body) {
|
|
7264
|
+
return maskDetailsBlocks(maskCode(body));
|
|
7265
|
+
}
|
|
7266
|
+
|
|
7267
|
+
class ScanContext {
|
|
7268
|
+
raw;
|
|
7269
|
+
normalised;
|
|
7270
|
+
masked;
|
|
7271
|
+
constructor(raw, normalised, masked) {
|
|
7272
|
+
this.raw = raw;
|
|
7273
|
+
this.normalised = normalised;
|
|
7274
|
+
this.masked = masked;
|
|
7275
|
+
}
|
|
7276
|
+
static from(rawBody) {
|
|
7277
|
+
const normalised = normalizeBody(rawBody);
|
|
7278
|
+
return new ScanContext(rawBody, normalised, buildAnchorLookupMask(normalised));
|
|
7279
|
+
}
|
|
7280
|
+
rawResolutionAgrees(field) {
|
|
7281
|
+
const rawHasPair = anchoredRegionBounds(this.raw, field) !== null;
|
|
7282
|
+
return rawHasPair === (anchoredRegionBounds(this.masked, field) !== null);
|
|
7283
|
+
}
|
|
7284
|
+
}
|
|
7285
|
+
function resolveAnchoredRegion(ctx, field) {
|
|
7286
|
+
const bounds = anchoredRegionBounds(ctx.masked, field);
|
|
7287
|
+
if (bounds === null) {
|
|
7288
|
+
return anchoredRegionBounds(ctx.normalised, field) !== null ? "hidden" : null;
|
|
7289
|
+
}
|
|
7290
|
+
return {
|
|
7291
|
+
region: ctx.normalised.slice(bounds.innerStart, bounds.innerEnd),
|
|
7292
|
+
maskedRegion: ctx.masked.slice(bounds.innerStart, bounds.innerEnd)
|
|
7293
|
+
};
|
|
7294
|
+
}
|
|
7295
|
+
function summaryLineIndex(maskedRegion) {
|
|
7296
|
+
const index = maskedRegion.split(`
|
|
7297
|
+
`).findIndex((line) => line.startsWith(EVIDENCE_SUMMARY_PREFIX));
|
|
7298
|
+
return index === -1 ? null : index;
|
|
7299
|
+
}
|
|
7300
|
+
|
|
7301
|
+
// src/lib/loop-log.ts
|
|
7302
|
+
var LOOP_LOG_MAX_BYTES = 8 * 1024 * 1024;
|
|
7303
|
+
|
|
7304
|
+
// src/lib/dispatch.ts
|
|
7305
|
+
var MAX_TEE_BYTES = 8 * 1024 * 1024;
|
|
7306
|
+
var CLAUDE_MODEL_ALIASES = new Set(["fable", "opus", "sonnet", "haiku"]);
|
|
7307
|
+
|
|
6693
7308
|
// src/lib/brief-assembly.ts
|
|
6694
|
-
import { execFileSync as
|
|
7309
|
+
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
6695
7310
|
|
|
6696
7311
|
// ../../packages/sources/src/commands.ts
|
|
6697
7312
|
var COMMANDS = [
|
|
@@ -6862,6 +7477,16 @@ var COMMANDS = [
|
|
|
6862
7477
|
],
|
|
6863
7478
|
status: "shipped"
|
|
6864
7479
|
},
|
|
7480
|
+
{
|
|
7481
|
+
name: "task-tools serve",
|
|
7482
|
+
description: "Run the task-operator MCP tool server over stdio — the command both runtime adapters register",
|
|
7483
|
+
details: [
|
|
7484
|
+
"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.",
|
|
7485
|
+
"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.",
|
|
7486
|
+
"`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."
|
|
7487
|
+
],
|
|
7488
|
+
status: "shipped"
|
|
7489
|
+
},
|
|
6865
7490
|
{
|
|
6866
7491
|
name: "pr create",
|
|
6867
7492
|
description: "Open a pull request after full brief-schema validation",
|
|
@@ -7006,6 +7631,30 @@ var COMMANDS = [
|
|
|
7006
7631
|
],
|
|
7007
7632
|
status: "shipped"
|
|
7008
7633
|
},
|
|
7634
|
+
{
|
|
7635
|
+
name: "log export-artifact",
|
|
7636
|
+
description: "Copy this run's own local outbox into a file, for the generated task-path workflow's own upload step",
|
|
7637
|
+
flags: [],
|
|
7638
|
+
details: [
|
|
7639
|
+
"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.",
|
|
7640
|
+
"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."
|
|
7641
|
+
],
|
|
7642
|
+
status: "shipped"
|
|
7643
|
+
},
|
|
7644
|
+
{
|
|
7645
|
+
name: "log collect-artifact",
|
|
7646
|
+
description: "Validate a downloaded task-log artifact and publish the valid records through the existing flush path",
|
|
7647
|
+
flags: [
|
|
7648
|
+
{ flag: "--pr", description: "The pull request this artifact belongs to" },
|
|
7649
|
+
{ flag: "--repo", description: "Expected `owner/repo` — a provenance cross-check against each record" }
|
|
7650
|
+
],
|
|
7651
|
+
details: [
|
|
7652
|
+
"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.",
|
|
7653
|
+
"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.",
|
|
7654
|
+
"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."
|
|
7655
|
+
],
|
|
7656
|
+
status: "shipped"
|
|
7657
|
+
},
|
|
7009
7658
|
{
|
|
7010
7659
|
name: "milestone create",
|
|
7011
7660
|
description: "Create a GitHub Milestone from a validated body",
|
|
@@ -7377,7 +8026,7 @@ var StateSourceConfigSchema = z5.discriminatedUnion("kind", [
|
|
|
7377
8026
|
z5.object({ kind: z5.literal("file"), root: z5.string().optional() })
|
|
7378
8027
|
]);
|
|
7379
8028
|
// src/checks/edge-resolve.ts
|
|
7380
|
-
import { execFileSync as
|
|
8029
|
+
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
7381
8030
|
var DIRECT_ISSUE_REF = /#(\d+)/;
|
|
7382
8031
|
var issueCache = new Map;
|
|
7383
8032
|
function fetchIssueState(num, repo) {
|
|
@@ -7386,7 +8035,7 @@ function fetchIssueState(num, repo) {
|
|
|
7386
8035
|
return issueCache.get(key) ?? null;
|
|
7387
8036
|
let out = null;
|
|
7388
8037
|
try {
|
|
7389
|
-
const raw =
|
|
8038
|
+
const raw = execFileSync4("gh", [
|
|
7390
8039
|
"issue",
|
|
7391
8040
|
"view",
|
|
7392
8041
|
String(num),
|
|
@@ -7497,7 +8146,7 @@ async function resolveEdge(id, taskById, factsByTaskId, repo, resolveSibling = d
|
|
|
7497
8146
|
// src/lib/brief-assembly.ts
|
|
7498
8147
|
function git(args) {
|
|
7499
8148
|
try {
|
|
7500
|
-
return
|
|
8149
|
+
return execFileSync5("git", args, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
7501
8150
|
} catch {
|
|
7502
8151
|
return "";
|
|
7503
8152
|
}
|
|
@@ -7577,20 +8226,20 @@ var TOKEN_ROW_REMEDY = [
|
|
|
7577
8226
|
var USAGE2 = "Usage: vinaya pr report [--write <body-file> | --push <pr> [--body-file <path>]] [--phase <phase>] " + "[--role <role>] [--model <id>] [--transcript <path>]";
|
|
7578
8227
|
|
|
7579
8228
|
// src/lib/patch-id.ts
|
|
7580
|
-
import { execFileSync as
|
|
8229
|
+
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
7581
8230
|
function patchIdAt(base, sha) {
|
|
7582
8231
|
try {
|
|
7583
|
-
|
|
8232
|
+
execFileSync6("git", ["fetch", "--quiet", "origin", sha], { stdio: ["ignore", "ignore", "ignore"] });
|
|
7584
8233
|
} catch {}
|
|
7585
8234
|
try {
|
|
7586
|
-
const diff =
|
|
8235
|
+
const diff = execFileSync6("git", ["diff", `origin/${base}...${sha}`], {
|
|
7587
8236
|
encoding: "utf8",
|
|
7588
8237
|
maxBuffer: 64 * 1024 * 1024,
|
|
7589
8238
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7590
8239
|
});
|
|
7591
8240
|
if (diff === "")
|
|
7592
8241
|
return null;
|
|
7593
|
-
const out =
|
|
8242
|
+
const out = execFileSync6("git", ["patch-id", "--stable"], {
|
|
7594
8243
|
input: diff,
|
|
7595
8244
|
encoding: "utf8",
|
|
7596
8245
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -7702,7 +8351,7 @@ function compareEvidenceBlock(resolved, resolvedHead, actualNumstat, expectedGro
|
|
|
7702
8351
|
var DEVELOPER_ROUND_MARKER = /<!--\s*aeg:developer:round-\d+\s*-->/i;
|
|
7703
8352
|
function fetchHasPriorDeveloperRound(prNumber) {
|
|
7704
8353
|
try {
|
|
7705
|
-
const out =
|
|
8354
|
+
const out = execFileSync7("gh", ["pr", "view", String(prNumber), "--json", "comments"], {
|
|
7706
8355
|
encoding: "utf8",
|
|
7707
8356
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7708
8357
|
});
|
|
@@ -7716,7 +8365,7 @@ function fetchHasPriorDeveloperRound(prNumber) {
|
|
|
7716
8365
|
var CHECK_NAME = "evidence-fresh";
|
|
7717
8366
|
function git2(args) {
|
|
7718
8367
|
try {
|
|
7719
|
-
return
|
|
8368
|
+
return execFileSync7("git", args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
|
|
7720
8369
|
} catch {
|
|
7721
8370
|
return "";
|
|
7722
8371
|
}
|
|
@@ -7735,7 +8384,7 @@ class GitCommandError2 extends Error {
|
|
|
7735
8384
|
}
|
|
7736
8385
|
function gitStrict(args) {
|
|
7737
8386
|
try {
|
|
7738
|
-
return
|
|
8387
|
+
return execFileSync7("git", args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
|
|
7739
8388
|
} catch (err) {
|
|
7740
8389
|
const stderr = err.stderr;
|
|
7741
8390
|
throw new GitCommandError2(args, String(stderr ?? err.message).trim() || "non-zero exit");
|
|
@@ -7753,7 +8402,7 @@ function resolveMergeBase(head) {
|
|
|
7753
8402
|
}
|
|
7754
8403
|
function fetchPrRefs(prNumber) {
|
|
7755
8404
|
try {
|
|
7756
|
-
const out =
|
|
8405
|
+
const out = execFileSync7("gh", ["pr", "view", String(prNumber), "--json", "headRefOid,baseRefName"], {
|
|
7757
8406
|
encoding: "utf8",
|
|
7758
8407
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7759
8408
|
});
|