agent-gov-core 0.4.3 → 0.7.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/CHANGELOG.md +101 -0
- package/README.md +53 -5
- package/dist/action.d.ts +30 -0
- package/dist/action.js +98 -0
- package/dist/exceptions.d.ts +83 -0
- package/dist/exceptions.js +129 -0
- package/dist/finding.js +7 -4
- package/dist/index.d.ts +12 -2
- package/dist/index.js +7 -2
- package/dist/jsonc.js +2 -1
- package/dist/locators.d.ts +3 -1
- package/dist/locators.js +66 -34
- package/dist/mcp.js +61 -2
- package/dist/merge.d.ts +91 -0
- package/dist/merge.js +154 -0
- package/dist/parse-error.d.ts +54 -0
- package/dist/parse-error.js +85 -0
- package/dist/report.d.ts +85 -0
- package/dist/report.js +156 -0
- package/dist/secrets.d.ts +67 -0
- package/dist/secrets.js +81 -0
- package/dist/shell.d.ts +26 -0
- package/dist/shell.js +210 -1
- package/dist/toml.js +28 -7
- package/package.json +3 -2
- package/schemas/report.schema.json +55 -0
package/dist/toml.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { toConfigParseError } from './parse-error.js';
|
|
2
3
|
export function readTomlObject(path) {
|
|
3
4
|
const text = readFileSync(path, 'utf8');
|
|
4
5
|
try {
|
|
@@ -6,7 +7,7 @@ export function readTomlObject(path) {
|
|
|
6
7
|
return { value: parsed, toml: parsed, text };
|
|
7
8
|
}
|
|
8
9
|
catch (err) {
|
|
9
|
-
return { value: undefined, toml: undefined, text, parseError: err };
|
|
10
|
+
return { value: undefined, toml: undefined, text, parseError: toConfigParseError(text, err) };
|
|
10
11
|
}
|
|
11
12
|
}
|
|
12
13
|
/**
|
|
@@ -122,11 +123,11 @@ class TomlParser {
|
|
|
122
123
|
// TOML spec violation. Without this guard, `[foo]` silently descended
|
|
123
124
|
// into the last `[[foo]]` entry and let writes leak into it.
|
|
124
125
|
if (this.aotPaths.has(path)) {
|
|
125
|
-
throw new Error(`Cannot redefine array-of-tables [[${keys.join('.')}]] as a standard table [${keys.join('.')}]`);
|
|
126
|
+
throw new Error(`Cannot redefine array-of-tables [[${keys.join('.')}]] as a standard table [${keys.join('.')}] at offset ${this.pos}`);
|
|
126
127
|
}
|
|
127
128
|
const table = this.descendTablePath(keys, /*forHeader*/ true);
|
|
128
129
|
if (this.definedTables.has(path)) {
|
|
129
|
-
throw new Error(`Duplicate table definition: [${keys.join('.')}]`);
|
|
130
|
+
throw new Error(`Duplicate table definition: [${keys.join('.')}] at offset ${this.pos}`);
|
|
130
131
|
}
|
|
131
132
|
this.definedTables.add(path);
|
|
132
133
|
this.current = table;
|
|
@@ -153,6 +154,17 @@ class TomlParser {
|
|
|
153
154
|
else if (!Array.isArray(arr)) {
|
|
154
155
|
throw new Error(`Key ${keys.join('.')} is not an array-of-tables`);
|
|
155
156
|
}
|
|
157
|
+
// Each new array entry resets the "already defined" status of any subtables
|
|
158
|
+
// declared under this AOT path. TOML spec permits the same subtable header
|
|
159
|
+
// (`[fruits.physical]`) to reappear under each fresh `[[fruits]]` entry — it
|
|
160
|
+
// binds to the current array entry. Without this clearing, the v0.4.2
|
|
161
|
+
// definedTables guard rejected the second [fruits.physical] as a duplicate.
|
|
162
|
+
const aotPathPrefix = keys.join(this.PATH_KEY_SEPARATOR) + this.PATH_KEY_SEPARATOR;
|
|
163
|
+
for (const definedPath of this.definedTables) {
|
|
164
|
+
if (definedPath.startsWith(aotPathPrefix)) {
|
|
165
|
+
this.definedTables.delete(definedPath);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
156
168
|
const newTable = {};
|
|
157
169
|
arr.push(newTable);
|
|
158
170
|
this.current = newTable;
|
|
@@ -248,7 +260,7 @@ class TomlParser {
|
|
|
248
260
|
}
|
|
249
261
|
const lastKey = keys[keys.length - 1];
|
|
250
262
|
if (Object.prototype.hasOwnProperty.call(node, lastKey)) {
|
|
251
|
-
throw new Error(`Duplicate key: ${keys.join('.')}`);
|
|
263
|
+
throw new Error(`Duplicate key: ${keys.join('.')} at offset ${this.pos}`);
|
|
252
264
|
}
|
|
253
265
|
node[lastKey] = value;
|
|
254
266
|
this.expectLineEnd();
|
|
@@ -322,9 +334,18 @@ class TomlParser {
|
|
|
322
334
|
const c = this.src[this.pos];
|
|
323
335
|
if (c === '\\') {
|
|
324
336
|
this.pos++;
|
|
325
|
-
//
|
|
326
|
-
|
|
337
|
+
// Line-ending backslash: per TOML spec, a `\` followed by *any amount
|
|
338
|
+
// of inline whitespace* (spaces/tabs) and then a newline strips the
|
|
339
|
+
// newline and trims leading whitespace on the next line. Peek past
|
|
340
|
+
// trailing inline whitespace before deciding whether this is a
|
|
341
|
+
// line-ending backslash or a regular escape.
|
|
342
|
+
let peek = this.pos;
|
|
343
|
+
while (peek < this.len && (this.src[peek] === ' ' || this.src[peek] === '\t')) {
|
|
344
|
+
peek++;
|
|
345
|
+
}
|
|
346
|
+
const next = this.src[peek];
|
|
327
347
|
if (next === '\n' || next === '\r' || next === undefined) {
|
|
348
|
+
this.pos = peek;
|
|
328
349
|
while (this.pos < this.len &&
|
|
329
350
|
(this.src[this.pos] === ' ' ||
|
|
330
351
|
this.src[this.pos] === '\t' ||
|
|
@@ -480,7 +501,7 @@ class TomlParser {
|
|
|
480
501
|
// Without this guard, `{ host = "a", host = "b" }` silently parsed as
|
|
481
502
|
// `{ host: "b" }` instead of raising.
|
|
482
503
|
if (Object.prototype.hasOwnProperty.call(node, leaf)) {
|
|
483
|
-
throw new Error(`Duplicate key in inline table: ${keys.join('.')}`);
|
|
504
|
+
throw new Error(`Duplicate key in inline table: ${keys.join('.')} at offset ${this.pos}`);
|
|
484
505
|
}
|
|
485
506
|
node[leaf] = value;
|
|
486
507
|
this.skipInlineWhitespace();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-gov-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Shared primitives for the AI-agent governance suite: Finding schema, JSONC/TOML readers, line locators, MCP command normalization, shell tokenization, and GitHub Action helpers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"types": "./dist/test-utils.d.ts",
|
|
15
15
|
"import": "./dist/test-utils.js"
|
|
16
16
|
},
|
|
17
|
-
"./schemas/finding.schema.json": "./schemas/finding.schema.json"
|
|
17
|
+
"./schemas/finding.schema.json": "./schemas/finding.schema.json",
|
|
18
|
+
"./schemas/report.schema.json": "./schemas/report.schema.json"
|
|
18
19
|
},
|
|
19
20
|
"files": [
|
|
20
21
|
"dist/**/*.js",
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/Conalh/agent-gov-core/schemas/report.schema.json",
|
|
4
|
+
"title": "Report",
|
|
5
|
+
"description": "Canonical multi-tool report envelope emitted by tools in the AI-agent governance suite. Wraps a `Finding[]` with provenance, rating, and optional tool-specific extension data so a cross-tool meta-reviewer can ingest reports from N tools through one shape.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["schemaVersion", "tool", "rating", "findings"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"schemaVersion": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"const": "1.0",
|
|
13
|
+
"description": "Envelope schema version. Currently '1.0'. Future incompatible envelope changes require a major bump on this field; readers must reject unknown major versions."
|
|
14
|
+
},
|
|
15
|
+
"tool": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"enum": ["scope_trail", "policy_mesh", "capability_echo", "task_bound", "session_trail"],
|
|
18
|
+
"description": "Originating tool. Matches the `Finding.tool` enum."
|
|
19
|
+
},
|
|
20
|
+
"toolVersion": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Semver of the emitting tool (e.g. '0.1.18'). Optional; helps a meta-reviewer attribute findings to a specific release."
|
|
23
|
+
},
|
|
24
|
+
"runId": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"description": "Unique identifier for this run. Optional; useful when merging reports from concurrent runs or comparing runs over time."
|
|
27
|
+
},
|
|
28
|
+
"conversationId": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"description": "Identifier for the agent session, PR review, or thread this run belongs to. Distinct from runId (one conversation can produce many runs). Matches OpenTelemetry's gen_ai.conversation.id semantic convention — if a consumer also emits OTel traces about the same agent session, pass the same string here."
|
|
31
|
+
},
|
|
32
|
+
"baseRef": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"description": "Git base ref for diff-mode tools (ScopeTrail, CapabilityEcho, TaskBound). Omit for non-diff tools (PolicyMesh, SessionTrail)."
|
|
35
|
+
},
|
|
36
|
+
"headRef": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"description": "Git head ref for diff-mode tools. Omit for non-diff tools."
|
|
39
|
+
},
|
|
40
|
+
"rating": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"enum": ["none", "low", "medium", "high", "critical"],
|
|
43
|
+
"description": "Aggregate severity for this report. 'none' iff `findings` is empty or all findings fell below the tool's fail-on threshold."
|
|
44
|
+
},
|
|
45
|
+
"findings": {
|
|
46
|
+
"type": "array",
|
|
47
|
+
"items": { "$ref": "./finding.schema.json" },
|
|
48
|
+
"description": "Findings emitted by this tool run."
|
|
49
|
+
},
|
|
50
|
+
"data": {
|
|
51
|
+
"type": "object",
|
|
52
|
+
"description": "Tool-specific extension data (e.g. PolicyMesh's `effectiveUnion`, CapabilityEcho's `surfaceSummary`, ScopeTrail's `scopeMatchCount`). Opaque to a cross-tool meta-reviewer but preserved so each tool's UX can read its own extensions back from a merged report."
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|