@jeger-ai/opengantry 3.0.1 → 3.1.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/LICENSE +10 -27
- package/README.md +64 -16
- package/dist/cli/commands/attest.d.ts +8 -0
- package/dist/cli/commands/attest.d.ts.map +1 -0
- package/dist/cli/commands/attest.js +19 -0
- package/dist/cli/commands/attest.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +4 -2
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +1 -1
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/lib/attest-mission.d.ts +13 -0
- package/dist/cli/lib/attest-mission.d.ts.map +1 -0
- package/dist/cli/lib/attest-mission.js +22 -0
- package/dist/cli/lib/attest-mission.js.map +1 -0
- package/dist/cli/lib/attestation-receipt.d.ts +40 -0
- package/dist/cli/lib/attestation-receipt.d.ts.map +1 -0
- package/dist/cli/lib/attestation-receipt.js +110 -0
- package/dist/cli/lib/attestation-receipt.js.map +1 -0
- package/dist/cli/lib/canonical-json.d.ts +3 -0
- package/dist/cli/lib/canonical-json.d.ts.map +1 -0
- package/dist/cli/lib/canonical-json.js +13 -0
- package/dist/cli/lib/canonical-json.js.map +1 -0
- package/dist/cli/lib/constants.d.ts +2 -0
- package/dist/cli/lib/constants.d.ts.map +1 -1
- package/dist/cli/lib/constants.js +2 -0
- package/dist/cli/lib/constants.js.map +1 -1
- package/dist/cli/lib/doctor-core.d.ts +1 -1
- package/dist/cli/lib/doctor-core.d.ts.map +1 -1
- package/dist/cli/lib/doctor-core.js +25 -3
- package/dist/cli/lib/doctor-core.js.map +1 -1
- package/dist/cli/lib/draft-token.d.ts +1 -2
- package/dist/cli/lib/draft-token.d.ts.map +1 -1
- package/dist/cli/lib/draft-token.js +2 -12
- package/dist/cli/lib/draft-token.js.map +1 -1
- package/dist/cli/lib/flight-telemetry-doctor.d.ts +3 -0
- package/dist/cli/lib/flight-telemetry-doctor.d.ts.map +1 -0
- package/dist/cli/lib/flight-telemetry-doctor.js +25 -0
- package/dist/cli/lib/flight-telemetry-doctor.js.map +1 -0
- package/dist/cli/lib/gxt-config.d.ts +11 -0
- package/dist/cli/lib/gxt-config.d.ts.map +1 -1
- package/dist/cli/lib/gxt-config.js +10 -0
- package/dist/cli/lib/gxt-config.js.map +1 -1
- package/dist/cli/lib/kpi-advisory-findings.d.ts +5 -0
- package/dist/cli/lib/kpi-advisory-findings.d.ts.map +1 -0
- package/dist/cli/lib/kpi-advisory-findings.js +16 -0
- package/dist/cli/lib/kpi-advisory-findings.js.map +1 -0
- package/dist/cli/lib/kpi-engine.d.ts +2 -1
- package/dist/cli/lib/kpi-engine.d.ts.map +1 -1
- package/dist/cli/lib/kpi-engine.js +36 -20
- package/dist/cli/lib/kpi-engine.js.map +1 -1
- package/dist/cli/lib/mcp-attest.d.ts +6 -0
- package/dist/cli/lib/mcp-attest.d.ts.map +1 -0
- package/dist/cli/lib/mcp-attest.js +15 -0
- package/dist/cli/lib/mcp-attest.js.map +1 -0
- package/dist/cli/lib/mcp-tools-register.d.ts.map +1 -1
- package/dist/cli/lib/mcp-tools-register.js +13 -0
- package/dist/cli/lib/mcp-tools-register.js.map +1 -1
- package/dist/cli/lib/policy-digest-doctor.d.ts +11 -0
- package/dist/cli/lib/policy-digest-doctor.d.ts.map +1 -0
- package/dist/cli/lib/policy-digest-doctor.js +37 -0
- package/dist/cli/lib/policy-digest-doctor.js.map +1 -0
- package/dist/cli/lib/receipt-signing.d.ts +12 -0
- package/dist/cli/lib/receipt-signing.d.ts.map +1 -0
- package/dist/cli/lib/receipt-signing.js +150 -0
- package/dist/cli/lib/receipt-signing.js.map +1 -0
- package/dist/cli/lib/runtime-exec.d.ts +1 -0
- package/dist/cli/lib/runtime-exec.d.ts.map +1 -1
- package/dist/cli/lib/runtime-exec.js +21 -17
- package/dist/cli/lib/runtime-exec.js.map +1 -1
- package/dist/cli/lib/types.d.ts +1 -0
- package/dist/cli/lib/types.d.ts.map +1 -1
- package/dist/cli/lib/verify-engine.d.ts +2 -1
- package/dist/cli/lib/verify-engine.d.ts.map +1 -1
- package/dist/cli/lib/verify-engine.js +13 -2
- package/dist/cli/lib/verify-engine.js.map +1 -1
- package/dist/cli/lib/verify-options.d.ts +4 -0
- package/dist/cli/lib/verify-options.d.ts.map +1 -1
- package/dist/cli/lib/verify-options.js.map +1 -1
- package/dist/cli/lib/verify-payload.d.ts +1 -0
- package/dist/cli/lib/verify-payload.d.ts.map +1 -1
- package/dist/cli/lib/verify-payload.js +4 -0
- package/dist/cli/lib/verify-payload.js.map +1 -1
- package/dist/cli/lib/verify-presenters.d.ts +10 -5
- package/dist/cli/lib/verify-presenters.d.ts.map +1 -1
- package/dist/cli/lib/verify-presenters.js +22 -26
- package/dist/cli/lib/verify-presenters.js.map +1 -1
- package/dist/cli/lib/verify-receipt.d.ts +11 -0
- package/dist/cli/lib/verify-receipt.d.ts.map +1 -0
- package/dist/cli/lib/verify-receipt.js +40 -0
- package/dist/cli/lib/verify-receipt.js.map +1 -0
- package/dist/cli/lib/verify-run.d.ts.map +1 -1
- package/dist/cli/lib/verify-run.js +44 -6
- package/dist/cli/lib/verify-run.js.map +1 -1
- package/dist/cli/lib/version.gen.d.ts +1 -1
- package/dist/cli/lib/version.gen.js +1 -1
- package/dist/cli/lib/working-digests.d.ts +8 -0
- package/dist/cli/lib/working-digests.d.ts.map +1 -0
- package/dist/cli/lib/working-digests.js +21 -0
- package/dist/cli/lib/working-digests.js.map +1 -0
- package/dist/cli/program-core.d.ts.map +1 -1
- package/dist/cli/program-core.js +8 -2
- package/dist/cli/program-core.js.map +1 -1
- package/dist/cli/program-workflow.d.ts.map +1 -1
- package/dist/cli/program-workflow.js +21 -0
- package/dist/cli/program-workflow.js.map +1 -1
- package/package.json +2 -2
- package/templates/.gitagent/config.json +3 -0
- package/templates/.gitagent/foreman/SUBSTRATE.version.json +1 -1
- package/templates/.gitagent/planner/KPI-REPORT.schema.yaml +4 -0
- package/templates/.gitagent/planner/PERFORMANCE.md +18 -0
- package/templates/.gitagent/planner/PERFORMANCE_RUBRIC.template.md +32 -0
- package/templates/.githooks/pre-push +5 -5
- package/templates/.github/workflows/gxt-validate.yml +7 -4
- package/templates/integrations/compatibility.json +1 -1
- package/templates/scripts/lib/trusted-automation.mjs +56 -9
- package/templates/scripts/verify-pr-missions.sh +3 -3
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# PERFORMANCE_RUBRIC (advisory LLM judge)
|
|
2
|
+
|
|
3
|
+
Use this rubric with a BYO `llm_verifiers` command in mission YAML. Verdicts are **ADVISORY_ONLY** — write `findings[]` to the KPI report; do **not** add blocking `kpi_gate` thresholds on judge metrics.
|
|
4
|
+
|
|
5
|
+
Judge **structural strategies only** (pooling, blocking I/O, memoization, streaming). Never guess runtime latency or throughput from source inspection.
|
|
6
|
+
|
|
7
|
+
Anchor each question to a rule `id` and cite `PERFORMANCE.md` via `doc_anchor` when emitting findings:
|
|
8
|
+
|
|
9
|
+
| Rule ID | Review question |
|
|
10
|
+
|---------|-----------------|
|
|
11
|
+
| `PERF-POOLING` | Did the diff introduce per-iteration client instantiation instead of pooling or injection? |
|
|
12
|
+
| `PERF-NONBLOCKING` | Did the diff add sync file/crypto/I/O inside an async handler critical path? |
|
|
13
|
+
| `PERF-MEMOIZATION` | Did the diff drop memoization or cache for an expensive repeated pure computation? |
|
|
14
|
+
|
|
15
|
+
Example verifier stdout fragment:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"metrics": { "perf_judge::reviewed": 1 },
|
|
20
|
+
"findings": [
|
|
21
|
+
{
|
|
22
|
+
"id": "PERF-POOLING",
|
|
23
|
+
"severity": "warn",
|
|
24
|
+
"path": "src/db.ts",
|
|
25
|
+
"line": 12,
|
|
26
|
+
"message": "new Pool() inside loop — see PERFORMANCE.md pooling policy",
|
|
27
|
+
"doc_anchor": "PERFORMANCE.md#connection-pooling"
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"exit_code": 0
|
|
31
|
+
}
|
|
32
|
+
```
|
|
@@ -5,9 +5,9 @@ set -euo pipefail
|
|
|
5
5
|
cd "$(git rev-parse --show-toplevel)"
|
|
6
6
|
|
|
7
7
|
if [[ -f dist/cli/index.js ]]; then
|
|
8
|
-
|
|
8
|
+
GANTRY=(node dist/cli/index.js)
|
|
9
9
|
elif command -v gantry >/dev/null 2>&1; then
|
|
10
|
-
|
|
10
|
+
GANTRY=(gantry)
|
|
11
11
|
else
|
|
12
12
|
echo "pre-push: gantry not found — run: npm run build" >&2
|
|
13
13
|
exit 1
|
|
@@ -35,17 +35,17 @@ for mission in "${missions[@]}"; do
|
|
|
35
35
|
[[ -n "$mission" ]] || continue
|
|
36
36
|
[[ -f "$mission" ]] || continue
|
|
37
37
|
echo "pre-push: gantry verify --mission ${mission} (--pre-push)" >&2
|
|
38
|
-
"${
|
|
38
|
+
"${GANTRY[@]}" verify --mission "$mission" --pre-push || exit 1
|
|
39
39
|
done
|
|
40
40
|
|
|
41
41
|
if git diff --name-only "${base}..HEAD" | grep -qE '^\.gitagent/foreman/MANIFEST\.json$|^\.gitagent/planner/RULES\.md$|\.gxt-skill\.yaml$'; then
|
|
42
42
|
echo "pre-push: gantry perimeter (advisory)" >&2
|
|
43
|
-
"${
|
|
43
|
+
"${GANTRY[@]}" perimeter --base-ref "$base" || true
|
|
44
44
|
fi
|
|
45
45
|
|
|
46
46
|
if git diff --name-only "${base}..HEAD" | grep -qE '^\.gitagent/foreman/MANIFEST\.json$|^skills/'; then
|
|
47
47
|
echo "pre-push: gantry check (manifest / skills changed)" >&2
|
|
48
|
-
"${
|
|
48
|
+
"${GANTRY[@]}" check || exit 1
|
|
49
49
|
fi
|
|
50
50
|
|
|
51
51
|
if git diff --name-only "${base}..HEAD" -- 'src/cli/**/*.ts' | grep -q .; then
|
|
@@ -41,7 +41,7 @@ jobs:
|
|
|
41
41
|
with:
|
|
42
42
|
fetch-depth: 0
|
|
43
43
|
|
|
44
|
-
- uses: actions/setup-node@
|
|
44
|
+
- uses: actions/setup-node@v7
|
|
45
45
|
with:
|
|
46
46
|
node-version: "24"
|
|
47
47
|
cache: "npm"
|
|
@@ -80,7 +80,7 @@ jobs:
|
|
|
80
80
|
fetch-depth: 0
|
|
81
81
|
ref: ${{ github.event.pull_request.head.sha }}
|
|
82
82
|
|
|
83
|
-
- uses: actions/setup-node@
|
|
83
|
+
- uses: actions/setup-node@v7
|
|
84
84
|
with:
|
|
85
85
|
node-version: "24"
|
|
86
86
|
cache: "npm"
|
|
@@ -102,7 +102,7 @@ jobs:
|
|
|
102
102
|
steps:
|
|
103
103
|
- uses: actions/checkout@v7
|
|
104
104
|
|
|
105
|
-
- uses: actions/setup-node@
|
|
105
|
+
- uses: actions/setup-node@v7
|
|
106
106
|
with:
|
|
107
107
|
node-version: "24"
|
|
108
108
|
cache: npm
|
|
@@ -142,7 +142,10 @@ jobs:
|
|
|
142
142
|
fetch-depth: 0
|
|
143
143
|
ref: ${{ github.event.pull_request.head.sha }}
|
|
144
144
|
|
|
145
|
-
-
|
|
145
|
+
- name: Install ripgrep
|
|
146
|
+
run: sudo apt-get update && sudo apt-get install -y ripgrep
|
|
147
|
+
|
|
148
|
+
- uses: actions/setup-node@v7
|
|
146
149
|
with:
|
|
147
150
|
node-version: "24"
|
|
148
151
|
cache: npm
|
|
@@ -3,11 +3,14 @@ import path from "node:path";
|
|
|
3
3
|
import { execFileSync } from "node:child_process";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
-
import { pathMatchesAllowed } from "./glob-match.mjs";
|
|
7
|
-
import { isMsnEnforcedPath, listMsnEnforcedPrefixes } from "./manifest-validate.mjs";
|
|
6
|
+
import { matchGlob, pathMatchesAllowed } from "./glob-match.mjs";
|
|
7
|
+
import { isMsnEnforcedPath, listMsnEnforcedPrefixes, readManifest } from "./manifest-validate.mjs";
|
|
8
8
|
|
|
9
|
-
const
|
|
10
|
-
|
|
9
|
+
const STRUCTURAL_KIND_HARD_MAX_NET_LOC = {
|
|
10
|
+
workflow_version_pin: 5,
|
|
11
|
+
bounded_content: 100,
|
|
12
|
+
};
|
|
13
|
+
const ALLOWED_STRUCTURAL_CHANGES = new Set(Object.keys(STRUCTURAL_KIND_HARD_MAX_NET_LOC));
|
|
11
14
|
const CONFIG_REL = ".gitagent/config.json";
|
|
12
15
|
|
|
13
16
|
function normalizePath(p) {
|
|
@@ -75,11 +78,18 @@ export function loadTrustedAutomationRules(repoRoot) {
|
|
|
75
78
|
throw new Error(`gxt-manifest-lib: rule ${rule.id} has unsupported structural change: ${change}`);
|
|
76
79
|
}
|
|
77
80
|
}
|
|
81
|
+
if (rule.allowed_structural_changes.length !== 1) {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`gxt-manifest-lib: rule ${rule.id} must declare exactly one allowed_structural_changes kind`,
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
const structuralKind = rule.allowed_structural_changes[0];
|
|
87
|
+
const hardCap = STRUCTURAL_KIND_HARD_MAX_NET_LOC[structuralKind];
|
|
78
88
|
if (typeof rule.max_net_loc !== "number" || !Number.isInteger(rule.max_net_loc) || rule.max_net_loc < 1) {
|
|
79
89
|
throw new Error(`gxt-manifest-lib: rule ${rule.id} max_net_loc must be a positive integer`);
|
|
80
90
|
}
|
|
81
|
-
if (rule.max_net_loc >
|
|
82
|
-
throw new Error(`gxt-manifest-lib: rule ${rule.id} max_net_loc exceeds hard cap ${
|
|
91
|
+
if (rule.max_net_loc > hardCap) {
|
|
92
|
+
throw new Error(`gxt-manifest-lib: rule ${rule.id} max_net_loc exceeds hard cap ${hardCap} for ${structuralKind}`);
|
|
83
93
|
}
|
|
84
94
|
rules.push({
|
|
85
95
|
id: rule.id,
|
|
@@ -213,10 +223,36 @@ function readBlobAt(repoRoot, commitSha, filePath) {
|
|
|
213
223
|
}
|
|
214
224
|
}
|
|
215
225
|
|
|
216
|
-
function
|
|
217
|
-
|
|
218
|
-
|
|
226
|
+
function listPerimeterProtectedGlobs(repoRoot) {
|
|
227
|
+
const manifest = readManifest(repoRoot);
|
|
228
|
+
if (!Array.isArray(manifest.perimeter_protected)) {
|
|
229
|
+
return [];
|
|
230
|
+
}
|
|
231
|
+
return manifest.perimeter_protected.map((g) => normalizePath(String(g)));
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function isSubstrateHardDeniedPath(filePath, perimeterGlobs) {
|
|
235
|
+
const p = normalizePath(filePath);
|
|
236
|
+
if (p === ".gitagent" || p.startsWith(".gitagent/")) {
|
|
237
|
+
return true;
|
|
219
238
|
}
|
|
239
|
+
return perimeterGlobs.some((g) => matchGlob(g, p));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function validateBoundedContentStructural(repoRoot, files, rule) {
|
|
243
|
+
const perimeterGlobs = listPerimeterProtectedGlobs(repoRoot);
|
|
244
|
+
for (const file of files) {
|
|
245
|
+
if (isSubstrateHardDeniedPath(file, perimeterGlobs)) {
|
|
246
|
+
return {
|
|
247
|
+
ok: false,
|
|
248
|
+
reason: `rule ${rule.id}: substrate hard-deny path not allowed (${file})`,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return { ok: true, reason: "" };
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function validateWorkflowVersionPinStructural(repoRoot, files, rule, baseSha, headSha, mode) {
|
|
220
256
|
const yaml = resolveYamlParser(repoRoot);
|
|
221
257
|
const workflowFiles = files.filter((f) => /\.ya?ml$/i.test(f));
|
|
222
258
|
for (const file of workflowFiles) {
|
|
@@ -241,6 +277,17 @@ function validateStructuralChanges(repoRoot, files, rule, baseSha, headSha, mode
|
|
|
241
277
|
return { ok: true, reason: "" };
|
|
242
278
|
}
|
|
243
279
|
|
|
280
|
+
function validateStructuralChanges(repoRoot, files, rule, baseSha, headSha, mode) {
|
|
281
|
+
const kind = [...rule.allowed_structural_changes][0];
|
|
282
|
+
if (kind === "bounded_content") {
|
|
283
|
+
return validateBoundedContentStructural(repoRoot, files, rule);
|
|
284
|
+
}
|
|
285
|
+
if (kind === "workflow_version_pin") {
|
|
286
|
+
return validateWorkflowVersionPinStructural(repoRoot, files, rule, baseSha, headSha, mode);
|
|
287
|
+
}
|
|
288
|
+
return { ok: false, reason: `rule ${rule.id}: no matching structural change policy` };
|
|
289
|
+
}
|
|
290
|
+
|
|
244
291
|
function findMatchingRule(rules, actorEmail) {
|
|
245
292
|
const actor = actorEmail.toLowerCase();
|
|
246
293
|
return rules.filter((rule) => rule.allowed_actors.includes(actor));
|
|
@@ -56,9 +56,9 @@ if [[ ${#UNIQUE_MSNS[@]} -gt 1 ]]; then
|
|
|
56
56
|
fi
|
|
57
57
|
|
|
58
58
|
if [[ -f dist/cli/index.js ]]; then
|
|
59
|
-
|
|
59
|
+
GANTRY=(node dist/cli/index.js)
|
|
60
60
|
elif command -v gantry >/dev/null 2>&1; then
|
|
61
|
-
|
|
61
|
+
GANTRY=(gantry)
|
|
62
62
|
else
|
|
63
63
|
echo "verify-pr-missions: build gantry first (npm run build)" >&2
|
|
64
64
|
exit 1
|
|
@@ -141,7 +141,7 @@ fi
|
|
|
141
141
|
|
|
142
142
|
for mission in "${CHANGED_MISSIONS[@]}"; do
|
|
143
143
|
echo "verify-pr-missions: gantry verify --mission ${mission}" >&2
|
|
144
|
-
"${
|
|
144
|
+
"${GANTRY[@]}" verify --mission "$mission" --audience verifier || exit 1
|
|
145
145
|
done
|
|
146
146
|
|
|
147
147
|
echo "verify-pr-missions OK (${#CHANGED_MISSIONS[@]} mission(s))"
|