@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-exec-bits.ts
|
|
6
|
-
import { execFileSync as
|
|
7
|
-
import { readFileSync as
|
|
6
|
+
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
7
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
8
8
|
|
|
9
9
|
// src/checks/contract.ts
|
|
10
10
|
var CHECK_SCHEMA_VERSION = 1;
|
|
@@ -14,8 +14,8 @@ function emitCheckError(error) {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
// src/lib/diff-evidence.ts
|
|
17
|
-
import { execFileSync as
|
|
18
|
-
import { join as
|
|
17
|
+
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
18
|
+
import { join as join5, relative, resolve as resolve2 } from "node:path";
|
|
19
19
|
// ../../packages/aeg-core/src/gate-audience.ts
|
|
20
20
|
var GATE_AUDIENCE = {
|
|
21
21
|
"check-branch-topology": { shippedAs: "branch-topology", ring: 0 },
|
|
@@ -1656,6 +1656,52 @@ var systemEnv3 = {
|
|
|
1656
1656
|
...process.env,
|
|
1657
1657
|
PATH: [process.env.PATH, "/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin"].filter(Boolean).join(":")
|
|
1658
1658
|
};
|
|
1659
|
+
var defaultExec = () => execFileAsync3("git", ["remote", "get-url", "origin"], { env: systemEnv3, timeout: 5000 });
|
|
1660
|
+
var cached;
|
|
1661
|
+
var inflight;
|
|
1662
|
+
async function resolveRepo(exec = defaultExec) {
|
|
1663
|
+
if (cached !== undefined)
|
|
1664
|
+
return cached;
|
|
1665
|
+
const fromEnv = process.env.AEG_REPO;
|
|
1666
|
+
if (fromEnv) {
|
|
1667
|
+
const parsed = parseOwnerRepo(fromEnv);
|
|
1668
|
+
if (parsed) {
|
|
1669
|
+
cached = parsed;
|
|
1670
|
+
return cached;
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
if (inflight)
|
|
1674
|
+
return inflight;
|
|
1675
|
+
inflight = (async () => {
|
|
1676
|
+
try {
|
|
1677
|
+
const { stdout } = await exec();
|
|
1678
|
+
cached = parseGitRemoteUrl(stdout.trim());
|
|
1679
|
+
return cached;
|
|
1680
|
+
} catch (err) {
|
|
1681
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1682
|
+
console.warn(`[aeg-forge-state] resolveRepo: git remote lookup failed (will retry): ${message}`);
|
|
1683
|
+
return null;
|
|
1684
|
+
} finally {
|
|
1685
|
+
inflight = undefined;
|
|
1686
|
+
}
|
|
1687
|
+
})();
|
|
1688
|
+
return inflight;
|
|
1689
|
+
}
|
|
1690
|
+
function parseGitRemoteUrl(url) {
|
|
1691
|
+
const ssh = url.match(/^git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/);
|
|
1692
|
+
if (ssh?.[1] && ssh[2])
|
|
1693
|
+
return { owner: ssh[1], repo: ssh[2] };
|
|
1694
|
+
const https = url.match(/^https?:\/\/(?:[^@]+@)?github\.com\/([^/]+)\/(.+?)(?:\.git)?\/?$/);
|
|
1695
|
+
if (https?.[1] && https[2])
|
|
1696
|
+
return { owner: https[1], repo: https[2] };
|
|
1697
|
+
return null;
|
|
1698
|
+
}
|
|
1699
|
+
function parseOwnerRepo(value) {
|
|
1700
|
+
const match = value.match(/^([^/]+)\/(.+)$/);
|
|
1701
|
+
if (!match?.[1] || !match[2])
|
|
1702
|
+
return null;
|
|
1703
|
+
return { owner: match[1], repo: match[2] };
|
|
1704
|
+
}
|
|
1659
1705
|
// ../../packages/aeg-core/src/anchored-region.ts
|
|
1660
1706
|
function anchoredRegionBounds(body, field) {
|
|
1661
1707
|
const masked = maskCode(body);
|
|
@@ -1968,6 +2014,7 @@ var OBJECTIVES_VERSION_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Objectives version:\
|
|
|
1968
2014
|
var RULING_ORDINAL_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Ruling ordinal:\s*(\d+)(?!\d)/im;
|
|
1969
2015
|
var BRIEF_HASH_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Brief hash:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
|
|
1970
2016
|
var POLICY_DIGEST_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Policy digest:\s*([0-9a-f]{64})(?![A-Za-z0-9])/im;
|
|
2017
|
+
var BASE_SHA_PATTERN = /^[ \t]*(?:\*{1,3}|_{1,3})?Judged base:\s*([0-9a-f]{7,40})(?![A-Za-z0-9])/im;
|
|
1971
2018
|
function firstFiveLines(comment) {
|
|
1972
2019
|
return comment.split(`
|
|
1973
2020
|
`).slice(0, 5).join(`
|
|
@@ -2003,6 +2050,15 @@ function extractPolicyDigest(comment) {
|
|
|
2003
2050
|
const m = firstElevenLines(comment).match(POLICY_DIGEST_PATTERN);
|
|
2004
2051
|
return m ? m[1].toLowerCase() : null;
|
|
2005
2052
|
}
|
|
2053
|
+
function firstThirteenLines(comment) {
|
|
2054
|
+
return comment.split(`
|
|
2055
|
+
`).slice(0, 13).join(`
|
|
2056
|
+
`);
|
|
2057
|
+
}
|
|
2058
|
+
function extractBaseSha(comment) {
|
|
2059
|
+
const m = firstThirteenLines(comment).match(BASE_SHA_PATTERN);
|
|
2060
|
+
return m ? m[1].toLowerCase() : null;
|
|
2061
|
+
}
|
|
2006
2062
|
var FINDING_SEVERITY_LINE = /^\d+\.\s+\[([A-Z][A-Z]*)\]\s+(.+?)\s+—/gm;
|
|
2007
2063
|
function extractFindingSeverities(comment) {
|
|
2008
2064
|
return [...comment.matchAll(FINDING_SEVERITY_LINE)].map((m) => ({
|
|
@@ -2020,6 +2076,7 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
2020
2076
|
rulingOrdinal: null,
|
|
2021
2077
|
briefHash: null,
|
|
2022
2078
|
policyDigest: null,
|
|
2079
|
+
baseSha: null,
|
|
2023
2080
|
findingSeverities: [],
|
|
2024
2081
|
danglingNote: `no ${missingLabel} verdict comment found on this PR`
|
|
2025
2082
|
};
|
|
@@ -2034,6 +2091,7 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
2034
2091
|
rulingOrdinal: null,
|
|
2035
2092
|
briefHash: null,
|
|
2036
2093
|
policyDigest: null,
|
|
2094
|
+
baseSha: null,
|
|
2037
2095
|
findingSeverities: [],
|
|
2038
2096
|
danglingNote: `the most recent ${missingLabel} verdict comment carries a VERDICT-shaped line outside the first-five-line read window`
|
|
2039
2097
|
};
|
|
@@ -2045,6 +2103,7 @@ function extractVerdict(comments, valuePattern, missingLabel) {
|
|
|
2045
2103
|
rulingOrdinal: extractRulingOrdinal(latest),
|
|
2046
2104
|
briefHash: extractBriefHash(latest),
|
|
2047
2105
|
policyDigest: extractPolicyDigest(latest),
|
|
2106
|
+
baseSha: extractBaseSha(latest),
|
|
2048
2107
|
findingSeverities: extractFindingSeverities(latest),
|
|
2049
2108
|
danglingNote: null
|
|
2050
2109
|
};
|
|
@@ -3958,7 +4017,11 @@ function briefHash(brief) {
|
|
|
3958
4017
|
`).digest("hex");
|
|
3959
4018
|
}
|
|
3960
4019
|
function policyDigest(policy) {
|
|
3961
|
-
return createHash4("sha256").update(JSON.stringify({
|
|
4020
|
+
return createHash4("sha256").update(JSON.stringify({
|
|
4021
|
+
codeReviewThreshold: policy.codeReviewThreshold,
|
|
4022
|
+
securityThreshold: policy.securityThreshold,
|
|
4023
|
+
maxRounds: policy.maxRounds
|
|
4024
|
+
})).digest("hex");
|
|
3962
4025
|
}
|
|
3963
4026
|
function isBoundToHead(echoed, headSha) {
|
|
3964
4027
|
if (!echoed.headSha)
|
|
@@ -3974,8 +4037,12 @@ function isBoundByPatchIdentity(echoed, headSha, patchIdOf) {
|
|
|
3974
4037
|
return false;
|
|
3975
4038
|
return judged === current;
|
|
3976
4039
|
}
|
|
3977
|
-
function
|
|
3978
|
-
|
|
4040
|
+
function isBoundToBase(echoed, currentBase) {
|
|
4041
|
+
if (currentBase === null)
|
|
4042
|
+
return true;
|
|
4043
|
+
if (!echoed.baseSha)
|
|
4044
|
+
return false;
|
|
4045
|
+
return currentBase.toLowerCase().startsWith(echoed.baseSha.toLowerCase());
|
|
3979
4046
|
}
|
|
3980
4047
|
function isBoundToObjectives(echoed, currentVersion) {
|
|
3981
4048
|
if (currentVersion === null)
|
|
@@ -3996,14 +4063,18 @@ function isBoundToPolicy(echoed, currentDigest) {
|
|
|
3996
4063
|
return echoed.policyDigest === currentDigest;
|
|
3997
4064
|
}
|
|
3998
4065
|
function compareManifest(echoed, current, patchIdOf) {
|
|
3999
|
-
const
|
|
4066
|
+
const exactHead = isBoundToHead(echoed, current.headSha);
|
|
4067
|
+
const patchHead = exactHead ? false : isBoundByPatchIdentity(echoed, current.headSha, patchIdOf);
|
|
4068
|
+
const head = exactHead || patchHead;
|
|
4069
|
+
const base = patchHead ? true : isBoundToBase(echoed, current.baseSha);
|
|
4000
4070
|
const briefHashBound = isBoundToBriefHash(echoed, current.briefHash);
|
|
4001
4071
|
const objectivesVersion2 = isBoundToObjectives(echoed, current.objectivesVersion);
|
|
4002
4072
|
const rulingOrdinal = isBoundToRulings(echoed, current.rulingOrdinal);
|
|
4003
4073
|
const policyDigestBound = isBoundToPolicy(echoed, current.policyDigest);
|
|
4004
4074
|
return {
|
|
4005
|
-
bound: head && briefHashBound && objectivesVersion2 && rulingOrdinal && policyDigestBound,
|
|
4075
|
+
bound: head && base && briefHashBound && objectivesVersion2 && rulingOrdinal && policyDigestBound,
|
|
4006
4076
|
head,
|
|
4077
|
+
base,
|
|
4007
4078
|
briefHash: briefHashBound,
|
|
4008
4079
|
objectivesVersion: objectivesVersion2,
|
|
4009
4080
|
rulingOrdinal,
|
|
@@ -4055,6 +4126,7 @@ function checkReviewGate(input) {
|
|
|
4055
4126
|
const securityClean = securityTextClean && securityPolicyClean;
|
|
4056
4127
|
const currentManifest = {
|
|
4057
4128
|
headSha: input.headSha,
|
|
4129
|
+
baseSha: input.baseSha ?? null,
|
|
4058
4130
|
briefHash: input.briefHash ?? null,
|
|
4059
4131
|
objectivesVersion: input.objectivesVersion,
|
|
4060
4132
|
rulingOrdinal: input.rulingOrdinal,
|
|
@@ -4062,6 +4134,7 @@ function checkReviewGate(input) {
|
|
|
4062
4134
|
};
|
|
4063
4135
|
const codeReviewEchoed = {
|
|
4064
4136
|
headSha: codeReview.headSha,
|
|
4137
|
+
baseSha: codeReview.baseSha,
|
|
4065
4138
|
briefHash: codeReview.briefHash,
|
|
4066
4139
|
objectivesVersion: codeReview.objectivesVersion,
|
|
4067
4140
|
rulingOrdinal: codeReview.rulingOrdinal,
|
|
@@ -4069,6 +4142,7 @@ function checkReviewGate(input) {
|
|
|
4069
4142
|
};
|
|
4070
4143
|
const securityEchoed = {
|
|
4071
4144
|
headSha: security.headSha,
|
|
4145
|
+
baseSha: security.baseSha,
|
|
4072
4146
|
briefHash: security.briefHash,
|
|
4073
4147
|
objectivesVersion: security.objectivesVersion,
|
|
4074
4148
|
rulingOrdinal: security.rulingOrdinal,
|
|
@@ -4096,6 +4170,8 @@ function checkReviewGate(input) {
|
|
|
4096
4170
|
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`);
|
|
4097
4171
|
} else if (!codeReviewBound) {
|
|
4098
4172
|
problems.push(`the newest code-review verdict covers ${codeReview.headSha ?? "no recorded commit"}, head is ${input.headSha}`);
|
|
4173
|
+
} else if (!codeReviewBinding.base) {
|
|
4174
|
+
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)`);
|
|
4099
4175
|
} else if (!codeReviewObjectivesBound) {
|
|
4100
4176
|
problems.push(`the newest code-review verdict was cast against objectives version ${codeReview.objectivesVersion ?? "none"}, the Issue's list is now ${input.objectivesVersion}`);
|
|
4101
4177
|
} else if (!codeReviewRulingsBound) {
|
|
@@ -4111,6 +4187,8 @@ function checkReviewGate(input) {
|
|
|
4111
4187
|
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`);
|
|
4112
4188
|
} else if (!securityBound) {
|
|
4113
4189
|
problems.push(`the newest security-review verdict covers ${security.headSha ?? "no recorded commit"}, head is ${input.headSha}`);
|
|
4190
|
+
} else if (!securityBinding.base) {
|
|
4191
|
+
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)`);
|
|
4114
4192
|
} else if (!securityObjectivesBound) {
|
|
4115
4193
|
problems.push(`the newest security-review verdict was cast against objectives version ${security.objectivesVersion ?? "none"}, the Issue's list is now ${input.objectivesVersion}`);
|
|
4116
4194
|
} else if (!securityRulingsBound) {
|
|
@@ -4968,8 +5046,8 @@ var TaskToolErrorSchema = z.object({
|
|
|
4968
5046
|
detail: z.string().optional()
|
|
4969
5047
|
});
|
|
4970
5048
|
var TaskToolRefSchema = z.union([
|
|
4971
|
-
z.object({ tranche: z.string().min(1), id: z.string().min(1) }),
|
|
4972
|
-
z.object({ issue: z.number().int().positive() })
|
|
5049
|
+
z.object({ tranche: z.string().min(1), id: z.string().min(1) }).strict(),
|
|
5050
|
+
z.object({ issue: z.number().int().positive() }).strict()
|
|
4973
5051
|
]);
|
|
4974
5052
|
var MAX_PAGE_LIMIT = 100;
|
|
4975
5053
|
var PageRequestSchema = z.object({
|
|
@@ -4983,7 +5061,7 @@ var ObservedSchema = z.object({
|
|
|
4983
5061
|
});
|
|
4984
5062
|
var TaskStatusInputSchema = z.object({
|
|
4985
5063
|
task: TaskToolRefSchema.optional()
|
|
4986
|
-
}).merge(PageRequestSchema);
|
|
5064
|
+
}).merge(PageRequestSchema).strict();
|
|
4987
5065
|
var TaskStatusItemSchema = z.object({
|
|
4988
5066
|
task: TaskToolRefSchema,
|
|
4989
5067
|
issue: z.number().int().positive(),
|
|
@@ -5007,9 +5085,20 @@ var EscalationEvidenceSchema = z.object({
|
|
|
5007
5085
|
reviewer: z.string().nullable(),
|
|
5008
5086
|
security: z.string().nullable()
|
|
5009
5087
|
});
|
|
5088
|
+
var EscalationRunIdentitySchema = z.object({
|
|
5089
|
+
runId: z.string(),
|
|
5090
|
+
pid: z.number().int().positive(),
|
|
5091
|
+
host: z.string()
|
|
5092
|
+
});
|
|
5093
|
+
var EscalationInputVersionsSchema = z.object({
|
|
5094
|
+
briefHash: z.string().nullable(),
|
|
5095
|
+
objectivesVersion: z.string().nullable(),
|
|
5096
|
+
rulingOrdinal: z.number().int().nonnegative(),
|
|
5097
|
+
policyDigest: z.string()
|
|
5098
|
+
});
|
|
5010
5099
|
var TaskEscalationReadInputSchema = z.object({
|
|
5011
5100
|
task: TaskToolRefSchema
|
|
5012
|
-
}).merge(PageRequestSchema);
|
|
5101
|
+
}).merge(PageRequestSchema).strict();
|
|
5013
5102
|
var TaskEscalationPacketSchema = z.object({
|
|
5014
5103
|
reason: z.string(),
|
|
5015
5104
|
detail: z.string().nullable(),
|
|
@@ -5017,7 +5106,9 @@ var TaskEscalationPacketSchema = z.object({
|
|
|
5017
5106
|
evidence: EscalationEvidenceSchema.nullable(),
|
|
5018
5107
|
attemptedRecovery: z.string(),
|
|
5019
5108
|
requestedAuthority: RequestedAuthoritySchema,
|
|
5020
|
-
permittedNextActions: z.array(z.string())
|
|
5109
|
+
permittedNextActions: z.array(z.string()),
|
|
5110
|
+
runIdentity: EscalationRunIdentitySchema.nullable(),
|
|
5111
|
+
inputVersions: EscalationInputVersionsSchema.nullable()
|
|
5021
5112
|
}).merge(ObservedSchema);
|
|
5022
5113
|
var TaskEscalationReadResultSchema = z.object({
|
|
5023
5114
|
items: z.array(TaskEscalationPacketSchema),
|
|
@@ -5026,15 +5117,48 @@ var TaskEscalationReadResultSchema = z.object({
|
|
|
5026
5117
|
var TaskStartInputSchema = z.object({
|
|
5027
5118
|
tranche: z.string().min(1),
|
|
5028
5119
|
id: z.string().min(1)
|
|
5120
|
+
}).strict();
|
|
5121
|
+
var TaskStartResultSchema = z.object({
|
|
5122
|
+
requestId: z.string().min(1),
|
|
5123
|
+
run: z.object({ tranche: z.string().min(1), id: z.string().min(1) }),
|
|
5124
|
+
started: z.boolean(),
|
|
5125
|
+
startedAt: z.string(),
|
|
5126
|
+
mode: z.literal("attended")
|
|
5029
5127
|
});
|
|
5030
5128
|
var TaskResumeInputSchema = z.object({
|
|
5031
5129
|
task: TaskToolRefSchema
|
|
5032
|
-
});
|
|
5130
|
+
}).strict();
|
|
5033
5131
|
var TaskCancelInputSchema = z.object({
|
|
5034
5132
|
task: TaskToolRefSchema,
|
|
5035
5133
|
reason: z.string().min(1)
|
|
5134
|
+
}).strict();
|
|
5135
|
+
var TaskResumeResultSchema = z.object({
|
|
5136
|
+
task: z.number().int().positive(),
|
|
5137
|
+
pr: z.number().int().positive(),
|
|
5138
|
+
escalationId: z.string().min(1),
|
|
5139
|
+
outcome: z.enum(["started", "already_resumed"]),
|
|
5140
|
+
authenticatedBy: z.string().min(1),
|
|
5141
|
+
authenticatedFrom: z.string().min(1)
|
|
5142
|
+
});
|
|
5143
|
+
var TaskCancelOutcomeSchema = z.enum(["confirmed", "pending", "uncertain"]);
|
|
5144
|
+
var TaskCancelResultSchema = z.object({
|
|
5145
|
+
task: z.number().int().positive(),
|
|
5146
|
+
pr: z.number().int().positive(),
|
|
5147
|
+
escalationId: z.string().min(1),
|
|
5148
|
+
outcome: TaskCancelOutcomeSchema,
|
|
5149
|
+
authenticatedBy: z.string().min(1),
|
|
5150
|
+
authenticatedFrom: z.string().min(1),
|
|
5151
|
+
fencedEffectKeys: z.array(z.string())
|
|
5036
5152
|
});
|
|
5037
|
-
var
|
|
5153
|
+
var TASK_TOOL_NAMES = [
|
|
5154
|
+
"task_start",
|
|
5155
|
+
"task_status",
|
|
5156
|
+
"task_escalation_read",
|
|
5157
|
+
"task_resume",
|
|
5158
|
+
"task_cancel"
|
|
5159
|
+
];
|
|
5160
|
+
var OPERATOR_STATUS_FOLLOW = "task_status_follow";
|
|
5161
|
+
var OPERATOR_TOOL_GRANT = [...TASK_TOOL_NAMES, OPERATOR_STATUS_FOLLOW];
|
|
5038
5162
|
// ../../packages/aeg-core/src/first-push-dispatch-gate.ts
|
|
5039
5163
|
function parseTaskBranch(branch) {
|
|
5040
5164
|
const m = /^task\/([^/]+)\/([^/]+)$/.exec(branch);
|
|
@@ -5257,6 +5381,9 @@ function findWorkspaceEscapes(files, knownPaths, workspaceDirs = DEFAULT_WORKSPA
|
|
|
5257
5381
|
}
|
|
5258
5382
|
return findings;
|
|
5259
5383
|
}
|
|
5384
|
+
// ../../packages/aeg-core/src/log/envelope.ts
|
|
5385
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
5386
|
+
|
|
5260
5387
|
// ../../packages/aeg-core/src/log/schema.ts
|
|
5261
5388
|
import { z as z2 } from "zod";
|
|
5262
5389
|
var ROLE_VALUES = [
|
|
@@ -5358,7 +5485,8 @@ var DispatchOutcomeSchema = z2.discriminatedUnion("type", [
|
|
|
5358
5485
|
}).strict(),
|
|
5359
5486
|
z2.object({ type: z2.literal("brief"), comment_id: z2.number().int(), hash: z2.string() }).strict(),
|
|
5360
5487
|
z2.object({ type: z2.literal("plan"), issues: z2.array(z2.number().int()) }).strict(),
|
|
5361
|
-
z2.object({ type: z2.literal("archive"), provenance_comment_id: z2.number().int() }).strict()
|
|
5488
|
+
z2.object({ type: z2.literal("archive"), provenance_comment_id: z2.number().int() }).strict(),
|
|
5489
|
+
z2.object({ type: z2.literal("completed") }).strict()
|
|
5362
5490
|
]);
|
|
5363
5491
|
var dispatchShared = {
|
|
5364
5492
|
meta: HeaderMetaSchema,
|
|
@@ -5418,7 +5546,8 @@ var DevReviewLoopEventSchema = z2.discriminatedUnion("event", [
|
|
|
5418
5546
|
round: z2.number().int(),
|
|
5419
5547
|
head: z2.string(),
|
|
5420
5548
|
all_approve: z2.boolean(),
|
|
5421
|
-
blockers: z2.number().int().nonnegative()
|
|
5549
|
+
blockers: z2.number().int().nonnegative(),
|
|
5550
|
+
findings: z2.array(ReviewFindingSchema).optional()
|
|
5422
5551
|
}).strict(),
|
|
5423
5552
|
z2.object({
|
|
5424
5553
|
...loopShared,
|
|
@@ -5597,7 +5726,9 @@ var roleAttemptShared = {
|
|
|
5597
5726
|
kind: z2.literal("role_attempt"),
|
|
5598
5727
|
...envelopeTail,
|
|
5599
5728
|
actor: z2.string().nullable(),
|
|
5600
|
-
attempt: z2.number().int().nullable()
|
|
5729
|
+
attempt: z2.number().int().nullable(),
|
|
5730
|
+
effect_id: z2.string(),
|
|
5731
|
+
model: z2.string().nullable()
|
|
5601
5732
|
};
|
|
5602
5733
|
var RoleAttemptEventSchema = z2.discriminatedUnion("event", [
|
|
5603
5734
|
z2.object({
|
|
@@ -5656,6 +5787,144 @@ var LogEventSchema = z2.union([
|
|
|
5656
5787
|
HandoffEventSchema,
|
|
5657
5788
|
EffectEventSchema
|
|
5658
5789
|
]);
|
|
5790
|
+
|
|
5791
|
+
// ../../packages/aeg-core/src/log/envelope.ts
|
|
5792
|
+
function isRole(value) {
|
|
5793
|
+
return value !== undefined && ROLE_VALUES.includes(value);
|
|
5794
|
+
}
|
|
5795
|
+
function actorIdFromEnv(role) {
|
|
5796
|
+
return role === undefined || role === "" ? null : role;
|
|
5797
|
+
}
|
|
5798
|
+
function lineageFieldFromEnv(value) {
|
|
5799
|
+
return value === undefined || value === "" ? null : value;
|
|
5800
|
+
}
|
|
5801
|
+
function attemptFromEnv(value) {
|
|
5802
|
+
if (value === undefined || value === "")
|
|
5803
|
+
return null;
|
|
5804
|
+
const n = Number(value);
|
|
5805
|
+
return Number.isInteger(n) ? n : null;
|
|
5806
|
+
}
|
|
5807
|
+
function provenanceFor(input) {
|
|
5808
|
+
if (input.provenance)
|
|
5809
|
+
return input.provenance;
|
|
5810
|
+
if (input.env.role || input.env.task)
|
|
5811
|
+
return "env_correlated";
|
|
5812
|
+
return "unavailable";
|
|
5813
|
+
}
|
|
5814
|
+
function issueFromTask(task) {
|
|
5815
|
+
if (task === undefined || task === "")
|
|
5816
|
+
return null;
|
|
5817
|
+
const n = Number(task);
|
|
5818
|
+
return Number.isInteger(n) ? n : null;
|
|
5819
|
+
}
|
|
5820
|
+
function roundFromEnv(round) {
|
|
5821
|
+
if (round === undefined || round === "")
|
|
5822
|
+
return;
|
|
5823
|
+
const n = Number(round);
|
|
5824
|
+
return Number.isInteger(n) ? n : undefined;
|
|
5825
|
+
}
|
|
5826
|
+
function buildHeader(input) {
|
|
5827
|
+
const role = isRole(input.env.role) ? input.env.role : "unattributed";
|
|
5828
|
+
const round = roundFromEnv(input.env.round);
|
|
5829
|
+
const subject = {
|
|
5830
|
+
issue: issueFromTask(input.env.task),
|
|
5831
|
+
role,
|
|
5832
|
+
...round !== undefined ? { round } : {},
|
|
5833
|
+
...input.subject ?? {}
|
|
5834
|
+
};
|
|
5835
|
+
return {
|
|
5836
|
+
meta: {
|
|
5837
|
+
schema: 2,
|
|
5838
|
+
ts: input.now.toISOString(),
|
|
5839
|
+
run_id: input.runId,
|
|
5840
|
+
seq: input.seq,
|
|
5841
|
+
repo: input.repo,
|
|
5842
|
+
vinaya: input.vinaya,
|
|
5843
|
+
doctrine: input.doctrine,
|
|
5844
|
+
host: input.host,
|
|
5845
|
+
machine: createHash5("sha256").update(input.hostname).digest("hex"),
|
|
5846
|
+
event_id: input.eventId,
|
|
5847
|
+
process_id: input.processId,
|
|
5848
|
+
actor_id: actorIdFromEnv(input.env.role),
|
|
5849
|
+
lineage: {
|
|
5850
|
+
run: lineageFieldFromEnv(input.env.run),
|
|
5851
|
+
attempt: attemptFromEnv(input.env.attempt),
|
|
5852
|
+
parent: lineageFieldFromEnv(input.env.parent)
|
|
5853
|
+
},
|
|
5854
|
+
input_versions: {
|
|
5855
|
+
objectives_version: input.inputVersions?.objectivesVersion ?? null,
|
|
5856
|
+
brief_hash: input.inputVersions?.briefHash ?? null,
|
|
5857
|
+
ruling_ordinal: input.inputVersions?.rulingOrdinal ?? null,
|
|
5858
|
+
policy_digest: input.inputVersions?.policyDigest ?? null
|
|
5859
|
+
},
|
|
5860
|
+
provenance: provenanceFor(input)
|
|
5861
|
+
},
|
|
5862
|
+
subject
|
|
5863
|
+
};
|
|
5864
|
+
}
|
|
5865
|
+
// ../../packages/aeg-core/src/log/redact.ts
|
|
5866
|
+
var GITHUB_TOKEN_PATTERN = /\b(?:gho_|ghp_|ghs_|ghu_|ghr_|github_pat_)[A-Za-z0-9_]+\b/g;
|
|
5867
|
+
var CLASSIC_GITHUB_PAT_PATTERN = /\b((?:token|GITHUB_TOKEN|PAT|api[_-]?key|api[_-]?token)\s*[:=]\s*)[a-f0-9]{40}\b/gi;
|
|
5868
|
+
var BEARER_TOKEN_PATTERN = /\bBearer\s+\S+/g;
|
|
5869
|
+
var AWS_ACCESS_KEY_PATTERN = /\bAKIA[0-9A-Z]{16}\b/g;
|
|
5870
|
+
var SLACK_TOKEN_PATTERN = /\bxox[baprs]-[0-9A-Za-z-]+\b/g;
|
|
5871
|
+
var STRIPE_KEY_PATTERN = /\b(?:sk|pk|rk)_(?:live|test)_[0-9A-Za-z]{10,}\b/g;
|
|
5872
|
+
var ANTHROPIC_KEY_PATTERN = /\bsk-ant-[A-Za-z0-9_-]{20,}\b/g;
|
|
5873
|
+
var OPENAI_KEY_PATTERN = /\bsk-(?!ant-)[A-Za-z0-9]{20,}\b/g;
|
|
5874
|
+
var NPM_TOKEN_PATTERN = /\bnpm_[A-Za-z0-9]{36}\b/g;
|
|
5875
|
+
var JWT_PATTERN = /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g;
|
|
5876
|
+
var PEM_BLOCK_PATTERN = /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g;
|
|
5877
|
+
var BASIC_AUTH_URL_PATTERN = /(https?:\/\/)[^/\s:@]+:[^/\s@]+@/g;
|
|
5878
|
+
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;
|
|
5879
|
+
function redactString(value, home) {
|
|
5880
|
+
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>");
|
|
5881
|
+
if (home.length > 0 && out.startsWith(home)) {
|
|
5882
|
+
const rest = out.slice(home.length);
|
|
5883
|
+
if (rest === "" || rest.startsWith("/"))
|
|
5884
|
+
out = `~${rest}`;
|
|
5885
|
+
}
|
|
5886
|
+
return out;
|
|
5887
|
+
}
|
|
5888
|
+
function redact(value, home) {
|
|
5889
|
+
if (typeof value === "string")
|
|
5890
|
+
return redactString(value, home);
|
|
5891
|
+
if (Array.isArray(value))
|
|
5892
|
+
return value.map((v) => redact(v, home));
|
|
5893
|
+
if (value !== null && typeof value === "object") {
|
|
5894
|
+
const out = {};
|
|
5895
|
+
for (const [k, v] of Object.entries(value)) {
|
|
5896
|
+
out[k] = redact(v, home);
|
|
5897
|
+
}
|
|
5898
|
+
return out;
|
|
5899
|
+
}
|
|
5900
|
+
return value;
|
|
5901
|
+
}
|
|
5902
|
+
// ../../packages/aeg-core/src/log/store.ts
|
|
5903
|
+
function metaOf(obj) {
|
|
5904
|
+
if (obj === null || typeof obj !== "object")
|
|
5905
|
+
return null;
|
|
5906
|
+
const meta = obj.meta;
|
|
5907
|
+
if (meta === null || typeof meta !== "object")
|
|
5908
|
+
return null;
|
|
5909
|
+
return meta;
|
|
5910
|
+
}
|
|
5911
|
+
function recordIdentity(obj) {
|
|
5912
|
+
const meta = metaOf(obj);
|
|
5913
|
+
if (meta === null)
|
|
5914
|
+
return null;
|
|
5915
|
+
const eventId = meta.event_id;
|
|
5916
|
+
if (typeof eventId === "string" && eventId.length > 0)
|
|
5917
|
+
return eventId;
|
|
5918
|
+
const runId = meta.run_id;
|
|
5919
|
+
const seq = meta.seq;
|
|
5920
|
+
if (typeof runId === "string" && runId.length > 0 && typeof seq === "number" && Number.isInteger(seq)) {
|
|
5921
|
+
return `${runId}:${seq}`;
|
|
5922
|
+
}
|
|
5923
|
+
return null;
|
|
5924
|
+
}
|
|
5925
|
+
|
|
5926
|
+
// ../../packages/aeg-core/src/log/artifact.ts
|
|
5927
|
+
var TASK_LOG_ARTIFACT_MAX_BYTES = 8 * 1024 * 1024;
|
|
5659
5928
|
// ../../packages/aeg-core/src/dev-review-loop/journal-reconstruction.ts
|
|
5660
5929
|
var STOPPED_CONDITIONS = new Set(["confidence", "reappearance", "no_progress", "max_rounds"]);
|
|
5661
5930
|
// ../../packages/aeg-core/src/control-store/records.ts
|
|
@@ -5670,7 +5939,9 @@ var RunRecordSchema = z3.object({
|
|
|
5670
5939
|
runId: z3.string().min(1),
|
|
5671
5940
|
pid: z3.number().int().positive(),
|
|
5672
5941
|
host: z3.string().min(1),
|
|
5673
|
-
startedAt: isoTimestamp
|
|
5942
|
+
startedAt: isoTimestamp,
|
|
5943
|
+
childStartedAt: z3.string().min(1).nullable().optional(),
|
|
5944
|
+
childCommand: z3.string().min(1).nullable().optional()
|
|
5674
5945
|
}).strict();
|
|
5675
5946
|
var InputRecordSchema = z3.object({
|
|
5676
5947
|
version: z3.literal(1),
|
|
@@ -5703,6 +5974,88 @@ var TransitionRecordSchema = z3.object({
|
|
|
5703
5974
|
detail: z3.string().optional(),
|
|
5704
5975
|
at: isoTimestamp
|
|
5705
5976
|
}).strict();
|
|
5977
|
+
var ManifestRecordSchema = z3.object({
|
|
5978
|
+
version: z3.literal(1),
|
|
5979
|
+
kind: z3.literal("manifest"),
|
|
5980
|
+
task: taskId,
|
|
5981
|
+
round: epochNumber,
|
|
5982
|
+
repository: z3.string().min(1),
|
|
5983
|
+
pr: z3.number().int().positive(),
|
|
5984
|
+
branch: z3.string().min(1),
|
|
5985
|
+
baseSha: z3.string().min(1).nullable(),
|
|
5986
|
+
headSha: z3.string().min(1),
|
|
5987
|
+
briefHash: z3.string().min(1).nullable(),
|
|
5988
|
+
objectivesVersion: z3.string().min(1).nullable(),
|
|
5989
|
+
rulingOrdinal: epochNumber,
|
|
5990
|
+
policyDigest: z3.string().min(1),
|
|
5991
|
+
recordedAt: isoTimestamp
|
|
5992
|
+
}).strict();
|
|
5993
|
+
var roundHeadIdentity = z3.object({ round: z3.number().int().positive(), head: z3.string().min(1) }).strict();
|
|
5994
|
+
var LoopBudgetsSchema = z3.object({
|
|
5995
|
+
mechanicalRetries: z3.number().int().nonnegative(),
|
|
5996
|
+
reviewRounds: z3.number().int().nonnegative(),
|
|
5997
|
+
infrastructureRetries: z3.number().int().nonnegative()
|
|
5998
|
+
}).strict();
|
|
5999
|
+
var LoopStateRecordSchema = z3.object({
|
|
6000
|
+
version: z3.literal(1),
|
|
6001
|
+
kind: z3.literal("loop_state"),
|
|
6002
|
+
task: taskId,
|
|
6003
|
+
round: z3.number().int().positive(),
|
|
6004
|
+
phase: z3.string().min(1),
|
|
6005
|
+
pauseReason: z3.string().min(1).nullable(),
|
|
6006
|
+
budgets: LoopBudgetsSchema,
|
|
6007
|
+
heldResult: roundHeadIdentity.nullable(),
|
|
6008
|
+
deliveredFindings: roundHeadIdentity.nullable(),
|
|
6009
|
+
recordedAt: isoTimestamp
|
|
6010
|
+
}).strict();
|
|
6011
|
+
var EffectRecordSchema = z3.object({
|
|
6012
|
+
version: z3.literal(1),
|
|
6013
|
+
kind: z3.literal("effect"),
|
|
6014
|
+
task: taskId,
|
|
6015
|
+
key: z3.string().min(1),
|
|
6016
|
+
operation: z3.string().min(1),
|
|
6017
|
+
target: z3.string().min(1),
|
|
6018
|
+
inputVersion: z3.number().int().nonnegative(),
|
|
6019
|
+
payloadDigest: z3.string().min(1),
|
|
6020
|
+
status: z3.union([z3.literal("started"), z3.literal("verified"), z3.literal("uncertain")]),
|
|
6021
|
+
url: z3.string().optional(),
|
|
6022
|
+
recordedAt: isoTimestamp
|
|
6023
|
+
}).strict();
|
|
6024
|
+
var EscalationRecordSchema = z3.object({
|
|
6025
|
+
version: z3.literal(1),
|
|
6026
|
+
kind: z3.literal("escalation"),
|
|
6027
|
+
task: taskId,
|
|
6028
|
+
escalationId: z3.string().min(1),
|
|
6029
|
+
round: epochNumber,
|
|
6030
|
+
head: z3.string().min(1),
|
|
6031
|
+
branch: z3.string().min(1),
|
|
6032
|
+
pr: z3.number().int().positive().nullable(),
|
|
6033
|
+
runId: z3.string().min(1),
|
|
6034
|
+
pid: z3.number().int().positive(),
|
|
6035
|
+
host: z3.string().min(1),
|
|
6036
|
+
agent: z3.string().min(1).optional(),
|
|
6037
|
+
reason: z3.string().min(1),
|
|
6038
|
+
detail: z3.string().optional(),
|
|
6039
|
+
evidence: z3.string().optional(),
|
|
6040
|
+
attemptedRecovery: z3.string().min(1),
|
|
6041
|
+
requestedDecision: z3.string().min(1),
|
|
6042
|
+
recipient: z3.string().min(1),
|
|
6043
|
+
briefHash: z3.string().min(1).nullable(),
|
|
6044
|
+
objectivesVersion: z3.string().min(1).nullable(),
|
|
6045
|
+
rulingOrdinal: epochNumber,
|
|
6046
|
+
policyDigest: z3.string().min(1),
|
|
6047
|
+
recordedAt: isoTimestamp
|
|
6048
|
+
}).strict();
|
|
6049
|
+
var ResolutionRecordSchema = z3.object({
|
|
6050
|
+
version: z3.literal(1),
|
|
6051
|
+
kind: z3.literal("resolution"),
|
|
6052
|
+
task: taskId,
|
|
6053
|
+
escalationId: z3.string().min(1),
|
|
6054
|
+
decision: z3.union([z3.literal("resume"), z3.literal("cancel")]),
|
|
6055
|
+
authenticatedBy: z3.string().min(1),
|
|
6056
|
+
authenticatedFrom: z3.string().min(1),
|
|
6057
|
+
consumedAt: isoTimestamp
|
|
6058
|
+
}).strict();
|
|
5706
6059
|
// src/lib/config.ts
|
|
5707
6060
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
5708
6061
|
import { existsSync, mkdirSync, readFileSync as readFileSync2, realpathSync, writeFileSync } from "node:fs";
|
|
@@ -5883,6 +6236,13 @@ var VinayaConfigSchema = z4.object({
|
|
|
5883
6236
|
message: "must be at most 3600000 (1 hour)"
|
|
5884
6237
|
});
|
|
5885
6238
|
}
|
|
6239
|
+
}).optional(),
|
|
6240
|
+
logPublish: z4.object({
|
|
6241
|
+
issue: z4.number().int().positive().optional(),
|
|
6242
|
+
pr: z4.number().int().positive().optional(),
|
|
6243
|
+
maxChunksPerFlush: z4.number().int().positive().optional()
|
|
6244
|
+
}).refine((v) => !(v.issue !== undefined && v.pr !== undefined), {
|
|
6245
|
+
message: "logPublish: set at most one of issue/pr, not both"
|
|
5886
6246
|
}).optional()
|
|
5887
6247
|
});
|
|
5888
6248
|
var GLOBAL_VINAYA_HOME = join(homedir(), ".vinaya");
|
|
@@ -6230,6 +6590,16 @@ var COMMANDS = [
|
|
|
6230
6590
|
],
|
|
6231
6591
|
status: "shipped"
|
|
6232
6592
|
},
|
|
6593
|
+
{
|
|
6594
|
+
name: "task-tools serve",
|
|
6595
|
+
description: "Run the task-operator MCP tool server over stdio — the command both runtime adapters register",
|
|
6596
|
+
details: [
|
|
6597
|
+
"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.",
|
|
6598
|
+
"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.",
|
|
6599
|
+
"`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."
|
|
6600
|
+
],
|
|
6601
|
+
status: "shipped"
|
|
6602
|
+
},
|
|
6233
6603
|
{
|
|
6234
6604
|
name: "pr create",
|
|
6235
6605
|
description: "Open a pull request after full brief-schema validation",
|
|
@@ -6374,6 +6744,30 @@ var COMMANDS = [
|
|
|
6374
6744
|
],
|
|
6375
6745
|
status: "shipped"
|
|
6376
6746
|
},
|
|
6747
|
+
{
|
|
6748
|
+
name: "log export-artifact",
|
|
6749
|
+
description: "Copy this run's own local outbox into a file, for the generated task-path workflow's own upload step",
|
|
6750
|
+
flags: [],
|
|
6751
|
+
details: [
|
|
6752
|
+
"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.",
|
|
6753
|
+
"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."
|
|
6754
|
+
],
|
|
6755
|
+
status: "shipped"
|
|
6756
|
+
},
|
|
6757
|
+
{
|
|
6758
|
+
name: "log collect-artifact",
|
|
6759
|
+
description: "Validate a downloaded task-log artifact and publish the valid records through the existing flush path",
|
|
6760
|
+
flags: [
|
|
6761
|
+
{ flag: "--pr", description: "The pull request this artifact belongs to" },
|
|
6762
|
+
{ flag: "--repo", description: "Expected `owner/repo` — a provenance cross-check against each record" }
|
|
6763
|
+
],
|
|
6764
|
+
details: [
|
|
6765
|
+
"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.",
|
|
6766
|
+
"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.",
|
|
6767
|
+
"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."
|
|
6768
|
+
],
|
|
6769
|
+
status: "shipped"
|
|
6770
|
+
},
|
|
6377
6771
|
{
|
|
6378
6772
|
name: "milestone create",
|
|
6379
6773
|
description: "Create a GitHub Milestone from a validated body",
|
|
@@ -7436,8 +7830,254 @@ function coreCheckRegistry() {
|
|
|
7436
7830
|
}
|
|
7437
7831
|
var CORE_CHECK_RING = Object.fromEntries(REGISTRY.map(([spec, ring]) => [spec.name, ring]));
|
|
7438
7832
|
|
|
7833
|
+
// src/lib/log-sink.ts
|
|
7834
|
+
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
7835
|
+
import { randomUUID } from "node:crypto";
|
|
7836
|
+
import {
|
|
7837
|
+
closeSync as closeSync2,
|
|
7838
|
+
constants as fsConstants2,
|
|
7839
|
+
existsSync as existsSync4,
|
|
7840
|
+
fstatSync as fstatSync2,
|
|
7841
|
+
mkdirSync as mkdirSync2,
|
|
7842
|
+
openSync as openSync2,
|
|
7843
|
+
readFileSync as readFileSync3,
|
|
7844
|
+
renameSync,
|
|
7845
|
+
writeSync
|
|
7846
|
+
} from "node:fs";
|
|
7847
|
+
import { hostname as osHostname, homedir as homedir2 } from "node:os";
|
|
7848
|
+
import { dirname as dirname3, join as join4 } from "node:path";
|
|
7849
|
+
var OUTBOX_MAX_BYTES = 8 * 1024 * 1024;
|
|
7850
|
+
function isEnoent(err) {
|
|
7851
|
+
return typeof err === "object" && err !== null && err.code === "ENOENT";
|
|
7852
|
+
}
|
|
7853
|
+
function resolveDoctrine(cwd, vinayaVersion) {
|
|
7854
|
+
let toplevel;
|
|
7855
|
+
try {
|
|
7856
|
+
toplevel = execFileSync5("git", ["-C", cwd, "rev-parse", "--show-toplevel"], {
|
|
7857
|
+
encoding: "utf8",
|
|
7858
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
7859
|
+
}).trim();
|
|
7860
|
+
} catch (err) {
|
|
7861
|
+
return isEnoent(err) ? "unknown" : vinayaVersion;
|
|
7862
|
+
}
|
|
7863
|
+
if (!existsSync4(join4(toplevel, "aeg-root", "roles")))
|
|
7864
|
+
return vinayaVersion;
|
|
7865
|
+
try {
|
|
7866
|
+
const sha = execFileSync5("git", ["-C", toplevel, "rev-parse", "HEAD:aeg-root"], {
|
|
7867
|
+
encoding: "utf8",
|
|
7868
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
7869
|
+
}).trim();
|
|
7870
|
+
return `aeg-root@${sha}`;
|
|
7871
|
+
} catch {
|
|
7872
|
+
return vinayaVersion;
|
|
7873
|
+
}
|
|
7874
|
+
}
|
|
7875
|
+
function readVinayaVersion() {
|
|
7876
|
+
try {
|
|
7877
|
+
const pkg = JSON.parse(readFileSync3(join4(packageRoot(import.meta.url), "package.json"), "utf8"));
|
|
7878
|
+
return pkg.version ?? "unknown";
|
|
7879
|
+
} catch {
|
|
7880
|
+
return "unknown";
|
|
7881
|
+
}
|
|
7882
|
+
}
|
|
7883
|
+
var SAFE_PATH_SEGMENT = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/;
|
|
7884
|
+
function isSafeRepoSegment(segment) {
|
|
7885
|
+
return SAFE_PATH_SEGMENT.test(segment) && !segment.includes("..");
|
|
7886
|
+
}
|
|
7887
|
+
function outboxPathFor(deps, repo, issue) {
|
|
7888
|
+
const dirName = repo ? `${repo.owner}-${repo.repo}` : "unresolved";
|
|
7889
|
+
const fileName = `${issue ?? "none"}.ndjson`;
|
|
7890
|
+
return join4(deps.outboxRoot(), dirName, fileName);
|
|
7891
|
+
}
|
|
7892
|
+
function hostFromEnv(env) {
|
|
7893
|
+
if (env.GITHUB_ACTIONS)
|
|
7894
|
+
return "ci";
|
|
7895
|
+
if (env.VINAYA_HOST === "hook")
|
|
7896
|
+
return "hook";
|
|
7897
|
+
if (env.VINAYA_HOST === "loop")
|
|
7898
|
+
return "loop";
|
|
7899
|
+
return "cli";
|
|
7900
|
+
}
|
|
7901
|
+
function defaultDeps() {
|
|
7902
|
+
return {
|
|
7903
|
+
outboxRoot: () => join4(GLOBAL_VINAYA_HOME, "outbox"),
|
|
7904
|
+
home: () => homedir2(),
|
|
7905
|
+
hostname: () => osHostname(),
|
|
7906
|
+
cwd: () => process.cwd(),
|
|
7907
|
+
now: () => new Date,
|
|
7908
|
+
env: () => process.env,
|
|
7909
|
+
resolveRepo: () => resolveRepo(),
|
|
7910
|
+
vinayaVersion: () => readVinayaVersion(),
|
|
7911
|
+
stderr: (message) => {
|
|
7912
|
+
process.stderr.write(message);
|
|
7913
|
+
},
|
|
7914
|
+
inputVersions: () => {
|
|
7915
|
+
return;
|
|
7916
|
+
}
|
|
7917
|
+
};
|
|
7918
|
+
}
|
|
7919
|
+
var APPEND_OPEN_FLAGS = fsConstants2.O_WRONLY | fsConstants2.O_APPEND | fsConstants2.O_CREAT | fsConstants2.O_NOFOLLOW | fsConstants2.O_NONBLOCK;
|
|
7920
|
+
function guardedAppendOpen(path) {
|
|
7921
|
+
try {
|
|
7922
|
+
return openSync2(path, APPEND_OPEN_FLAGS, 384);
|
|
7923
|
+
} catch {
|
|
7924
|
+
return;
|
|
7925
|
+
}
|
|
7926
|
+
}
|
|
7927
|
+
function reportRotationOverflow(backupPath, warn) {
|
|
7928
|
+
let raw;
|
|
7929
|
+
try {
|
|
7930
|
+
raw = readFileSync3(backupPath, "utf8");
|
|
7931
|
+
} catch {
|
|
7932
|
+
return;
|
|
7933
|
+
}
|
|
7934
|
+
const lines = raw.split(`
|
|
7935
|
+
`).filter((l) => l.length > 0);
|
|
7936
|
+
if (lines.length === 0)
|
|
7937
|
+
return;
|
|
7938
|
+
const droppedIdentities = lines.map((line, i) => {
|
|
7939
|
+
try {
|
|
7940
|
+
return recordIdentity(JSON.parse(line)) ?? `unreadable:${i}`;
|
|
7941
|
+
} catch {
|
|
7942
|
+
return `unreadable:${i}`;
|
|
7943
|
+
}
|
|
7944
|
+
});
|
|
7945
|
+
const diagnostic = { reason: "capacity", dropped: droppedIdentities.length, droppedIdentities };
|
|
7946
|
+
const shown = diagnostic.droppedIdentities.slice(0, 20);
|
|
7947
|
+
const more = diagnostic.dropped > shown.length ? `, +${diagnostic.dropped - shown.length} more` : "";
|
|
7948
|
+
warn(`vinaya: log outbox rotation is overwriting ${backupPath} — ${diagnostic.dropped} record(s) permanently lost: ${shown.join(", ")}${more}
|
|
7949
|
+
`);
|
|
7950
|
+
}
|
|
7951
|
+
function appendLine(path, line, warn) {
|
|
7952
|
+
try {
|
|
7953
|
+
mkdirSync2(dirname3(path), { recursive: true, mode: 448 });
|
|
7954
|
+
let fd = guardedAppendOpen(path);
|
|
7955
|
+
if (fd === undefined) {
|
|
7956
|
+
warn(`vinaya: log outbox target could not be opened (symlink, FIFO, or unwritable) — refusing: ${path}
|
|
7957
|
+
`);
|
|
7958
|
+
return;
|
|
7959
|
+
}
|
|
7960
|
+
let closed = false;
|
|
7961
|
+
try {
|
|
7962
|
+
const stat = fstatSync2(fd);
|
|
7963
|
+
if (!stat.isFile()) {
|
|
7964
|
+
warn(`vinaya: log outbox target is not a regular file — refusing to write: ${path}
|
|
7965
|
+
`);
|
|
7966
|
+
return;
|
|
7967
|
+
}
|
|
7968
|
+
if (stat.size > OUTBOX_MAX_BYTES) {
|
|
7969
|
+
closeSync2(fd);
|
|
7970
|
+
closed = true;
|
|
7971
|
+
const backupPath = path.replace(/\.ndjson$/, ".1.ndjson");
|
|
7972
|
+
reportRotationOverflow(backupPath, warn);
|
|
7973
|
+
renameSync(path, backupPath);
|
|
7974
|
+
const rotated = guardedAppendOpen(path);
|
|
7975
|
+
if (rotated === undefined) {
|
|
7976
|
+
warn(`vinaya: log outbox target could not be reopened after rotation — refusing: ${path}
|
|
7977
|
+
`);
|
|
7978
|
+
return;
|
|
7979
|
+
}
|
|
7980
|
+
fd = rotated;
|
|
7981
|
+
closed = false;
|
|
7982
|
+
}
|
|
7983
|
+
writeSync(fd, line);
|
|
7984
|
+
} finally {
|
|
7985
|
+
if (!closed)
|
|
7986
|
+
closeSync2(fd);
|
|
7987
|
+
}
|
|
7988
|
+
} catch (err) {
|
|
7989
|
+
warn(`vinaya: log outbox write failed — ${err instanceof Error ? err.message : String(err)}
|
|
7990
|
+
`);
|
|
7991
|
+
}
|
|
7992
|
+
}
|
|
7993
|
+
function createLogSink(overrides = {}) {
|
|
7994
|
+
const deps = { ...defaultDeps(), ...overrides };
|
|
7995
|
+
const runId = deps.env().VINAYA_RUN_ID || randomUUID();
|
|
7996
|
+
const processId = randomUUID();
|
|
7997
|
+
let seq = 0;
|
|
7998
|
+
let warned = false;
|
|
7999
|
+
const warnOnce = (message) => {
|
|
8000
|
+
if (warned)
|
|
8001
|
+
return;
|
|
8002
|
+
warned = true;
|
|
8003
|
+
try {
|
|
8004
|
+
deps.stderr(message);
|
|
8005
|
+
} catch {}
|
|
8006
|
+
};
|
|
8007
|
+
let doctrineCache;
|
|
8008
|
+
const doctrine = () => {
|
|
8009
|
+
if (doctrineCache === undefined)
|
|
8010
|
+
doctrineCache = resolveDoctrine(deps.cwd(), deps.vinayaVersion());
|
|
8011
|
+
return doctrineCache;
|
|
8012
|
+
};
|
|
8013
|
+
let resolveRepoCache;
|
|
8014
|
+
const resolveRepoOnce = () => {
|
|
8015
|
+
if (resolveRepoCache === undefined)
|
|
8016
|
+
resolveRepoCache = deps.resolveRepo();
|
|
8017
|
+
return resolveRepoCache;
|
|
8018
|
+
};
|
|
8019
|
+
function log(e) {
|
|
8020
|
+
try {
|
|
8021
|
+
const env = deps.env();
|
|
8022
|
+
const host = hostFromEnv(env);
|
|
8023
|
+
const now = deps.now();
|
|
8024
|
+
const mySeq = seq++;
|
|
8025
|
+
resolveRepoOnce().then((resolved) => {
|
|
8026
|
+
const repo = resolved && isSafeRepoSegment(resolved.owner) && isSafeRepoSegment(resolved.repo) ? resolved : null;
|
|
8027
|
+
const header = buildHeader({
|
|
8028
|
+
now,
|
|
8029
|
+
runId,
|
|
8030
|
+
seq: mySeq,
|
|
8031
|
+
repo: repo ? `${repo.owner}/${repo.repo}` : null,
|
|
8032
|
+
vinaya: deps.vinayaVersion(),
|
|
8033
|
+
doctrine: doctrine(),
|
|
8034
|
+
host,
|
|
8035
|
+
hostname: deps.hostname(),
|
|
8036
|
+
env: {
|
|
8037
|
+
role: env.VINAYA_ROLE,
|
|
8038
|
+
task: env.VINAYA_TASK,
|
|
8039
|
+
round: env.VINAYA_ROUND,
|
|
8040
|
+
run: env.VINAYA_RUN,
|
|
8041
|
+
attempt: env.VINAYA_ATTEMPT,
|
|
8042
|
+
parent: env.VINAYA_PARENT_EVENT
|
|
8043
|
+
},
|
|
8044
|
+
eventId: randomUUID(),
|
|
8045
|
+
processId,
|
|
8046
|
+
inputVersions: deps.inputVersions()
|
|
8047
|
+
});
|
|
8048
|
+
const full = { ...e, ...header };
|
|
8049
|
+
const parsed = LogEventSchema.safeParse(full);
|
|
8050
|
+
if (!parsed.success) {
|
|
8051
|
+
warnOnce(`vinaya: log() refused an invalid payload — ${parsed.error.issues[0]?.message ?? "schema violation"}
|
|
8052
|
+
`);
|
|
8053
|
+
return;
|
|
8054
|
+
}
|
|
8055
|
+
const line = `${JSON.stringify(redact(parsed.data, deps.home()))}
|
|
8056
|
+
`;
|
|
8057
|
+
appendLine(outboxPathFor(deps, repo, header.subject.issue), line, warnOnce);
|
|
8058
|
+
}).catch((err) => {
|
|
8059
|
+
warnOnce(`vinaya: log() failed — ${err instanceof Error ? err.message : String(err)}
|
|
8060
|
+
`);
|
|
8061
|
+
});
|
|
8062
|
+
} catch (err) {
|
|
8063
|
+
warnOnce(`vinaya: log() failed — ${err instanceof Error ? err.message : String(err)}
|
|
8064
|
+
`);
|
|
8065
|
+
}
|
|
8066
|
+
}
|
|
8067
|
+
const warmup = () => {
|
|
8068
|
+
doctrine();
|
|
8069
|
+
const originalWarn = console.warn;
|
|
8070
|
+
console.warn = () => {};
|
|
8071
|
+
resolveRepoOnce().finally(() => {
|
|
8072
|
+
console.warn = originalWarn;
|
|
8073
|
+
});
|
|
8074
|
+
};
|
|
8075
|
+
return { log, runId, warmup };
|
|
8076
|
+
}
|
|
8077
|
+
var defaultSink = createLogSink();
|
|
8078
|
+
|
|
7439
8079
|
// src/checks/runner.ts
|
|
7440
|
-
var
|
|
8080
|
+
var activeChecks = new Map;
|
|
7441
8081
|
|
|
7442
8082
|
// src/lib/forge-write.ts
|
|
7443
8083
|
var INFORMATIONAL_DISPATCH_BLOCKER_CLASSES = new Set([
|
|
@@ -7476,7 +8116,7 @@ function parseChangedLineRanges(diffOutput) {
|
|
|
7476
8116
|
function fileDiffAgainst(ref, path) {
|
|
7477
8117
|
let out;
|
|
7478
8118
|
try {
|
|
7479
|
-
out =
|
|
8119
|
+
out = execFileSync6("git", ["diff", `${ref}...HEAD`, "--", path], {
|
|
7480
8120
|
encoding: "utf8",
|
|
7481
8121
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7482
8122
|
}).trim();
|
|
@@ -7487,7 +8127,7 @@ function fileDiffAgainst(ref, path) {
|
|
|
7487
8127
|
}
|
|
7488
8128
|
function revParse(ref) {
|
|
7489
8129
|
try {
|
|
7490
|
-
return
|
|
8130
|
+
return execFileSync6("git", ["rev-parse", "--verify", ref], {
|
|
7491
8131
|
encoding: "utf8",
|
|
7492
8132
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7493
8133
|
}).trim();
|
|
@@ -7497,7 +8137,7 @@ function revParse(ref) {
|
|
|
7497
8137
|
}
|
|
7498
8138
|
function repoRoot() {
|
|
7499
8139
|
try {
|
|
7500
|
-
return
|
|
8140
|
+
return execFileSync6("git", ["rev-parse", "--show-toplevel"], {
|
|
7501
8141
|
encoding: "utf8",
|
|
7502
8142
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7503
8143
|
}).trim();
|
|
@@ -7508,7 +8148,7 @@ function repoRoot() {
|
|
|
7508
8148
|
function changedFiles(base) {
|
|
7509
8149
|
let out;
|
|
7510
8150
|
try {
|
|
7511
|
-
out =
|
|
8151
|
+
out = execFileSync6("git", ["diff", "--name-only", `${base}...HEAD`], {
|
|
7512
8152
|
encoding: "utf8",
|
|
7513
8153
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7514
8154
|
}).trim();
|
|
@@ -7533,7 +8173,7 @@ function resolveDiff(base = process.env.BASE_SHA || "origin/main") {
|
|
|
7533
8173
|
const relPaths = changedFiles(ref);
|
|
7534
8174
|
if (relPaths === null)
|
|
7535
8175
|
continue;
|
|
7536
|
-
return { base: ref, root, files: relPaths.map((p) =>
|
|
8176
|
+
return { base: ref, root, files: relPaths.map((p) => join5(root, p)) };
|
|
7537
8177
|
}
|
|
7538
8178
|
return null;
|
|
7539
8179
|
}
|
|
@@ -7569,7 +8209,7 @@ var CHECK_NAME = "exec-bits";
|
|
|
7569
8209
|
var EXECUTABLE_MODE = "100755";
|
|
7570
8210
|
function git2(args) {
|
|
7571
8211
|
try {
|
|
7572
|
-
return
|
|
8212
|
+
return execFileSync7("git", args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
|
|
7573
8213
|
} catch {
|
|
7574
8214
|
return null;
|
|
7575
8215
|
}
|
|
@@ -7583,7 +8223,7 @@ function indexMode(path) {
|
|
|
7583
8223
|
}
|
|
7584
8224
|
function hasShebang(path) {
|
|
7585
8225
|
try {
|
|
7586
|
-
return
|
|
8226
|
+
return readFileSync4(path, "utf8").startsWith("#!");
|
|
7587
8227
|
} catch {
|
|
7588
8228
|
return false;
|
|
7589
8229
|
}
|