@primitivehub/mcp-server 0.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.
@@ -0,0 +1,64 @@
1
+ /**
2
+ * MCP tool: `audit_workspace`
3
+ *
4
+ * Active-surface audit: discovers + classifies + scans every agent-
5
+ * context artifact under a root path. Pure transport over
6
+ * `@primitivehub/phub`'s `runAudit` (ADR-0025).
7
+ *
8
+ * The agent uses this to ask "what context primitives are loadable in
9
+ * my workspace, and which trip Context CI v0.1?" — the answer it can
10
+ * never get from a file-at-a-time scan because the threat model is
11
+ * the file the agent didn't know about.
12
+ */
13
+ export declare const AUDIT_WORKSPACE_TOOL: {
14
+ readonly name: "audit_workspace";
15
+ readonly description: "Recursively discover, classify, and scan every agent-context artifact (AGENTS.md, CLAUDE.md, .cursorrules, .claude/skills/**, mcp.json, …) under a root path. Reuses the same T1/T2/T5 detector roster as scan_text. Returns inventory + per-artifact verdicts + project-level summary. Use this as the active default — file-at-a-time scanning can't defend against files the agent didn't know about.";
16
+ readonly inputSchema: {
17
+ readonly type: "object";
18
+ readonly additionalProperties: false;
19
+ readonly properties: {
20
+ readonly root: {
21
+ readonly type: "string";
22
+ readonly description: "Directory to audit. Defaults to the server's cwd.";
23
+ };
24
+ readonly max_files: {
25
+ readonly type: "number";
26
+ readonly description: "Hard cap on artifacts traversed. Default 10000.";
27
+ };
28
+ readonly max_depth: {
29
+ readonly type: "number";
30
+ readonly description: "Maximum directory depth from root. Default 16.";
31
+ };
32
+ readonly strict: {
33
+ readonly type: "boolean";
34
+ readonly description: "Treat WARN verdicts as FAIL.";
35
+ };
36
+ readonly detectors: {
37
+ readonly type: "array";
38
+ readonly items: {
39
+ readonly type: "string";
40
+ };
41
+ readonly description: "Restrict to specific detectors. Accepts names / CCI IDs / threat categories.";
42
+ };
43
+ readonly policy_path: {
44
+ readonly type: "string";
45
+ readonly description: "Path to a .primitivehub/policy.yaml. Without this: auto-discover from cwd → git root.";
46
+ };
47
+ readonly allow_fail: {
48
+ readonly type: "array";
49
+ readonly items: {
50
+ readonly type: "string";
51
+ };
52
+ };
53
+ };
54
+ };
55
+ };
56
+ export interface AuditWorkspaceResultText {
57
+ type: "text";
58
+ text: string;
59
+ }
60
+ export declare function callAuditWorkspace(rawArgs: unknown): {
61
+ content: AuditWorkspaceResultText[];
62
+ isError: boolean;
63
+ };
64
+ //# sourceMappingURL=audit-workspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-workspace.d.ts","sourceRoot":"","sources":["../../src/tools/audit-workspace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AASH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCvB,CAAA;AAYV,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAoCD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,GACf;IAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CA6B3D"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * MCP tool: `audit_workspace`
3
+ *
4
+ * Active-surface audit: discovers + classifies + scans every agent-
5
+ * context artifact under a root path. Pure transport over
6
+ * `@primitivehub/phub`'s `runAudit` (ADR-0025).
7
+ *
8
+ * The agent uses this to ask "what context primitives are loadable in
9
+ * my workspace, and which trip Context CI v0.1?" — the answer it can
10
+ * never get from a file-at-a-time scan because the threat model is
11
+ * the file the agent didn't know about.
12
+ */
13
+ import { runAudit, } from "@primitivehub/phub";
14
+ export const AUDIT_WORKSPACE_TOOL = {
15
+ name: "audit_workspace",
16
+ description: "Recursively discover, classify, and scan every agent-context artifact (AGENTS.md, CLAUDE.md, .cursorrules, .claude/skills/**, mcp.json, …) under a root path. Reuses the same T1/T2/T5 detector roster as scan_text. Returns inventory + per-artifact verdicts + project-level summary. Use this as the active default — file-at-a-time scanning can't defend against files the agent didn't know about.",
17
+ inputSchema: {
18
+ type: "object",
19
+ additionalProperties: false,
20
+ properties: {
21
+ root: {
22
+ type: "string",
23
+ description: "Directory to audit. Defaults to the server's cwd.",
24
+ },
25
+ max_files: {
26
+ type: "number",
27
+ description: "Hard cap on artifacts traversed. Default 10000.",
28
+ },
29
+ max_depth: {
30
+ type: "number",
31
+ description: "Maximum directory depth from root. Default 16.",
32
+ },
33
+ strict: { type: "boolean", description: "Treat WARN verdicts as FAIL." },
34
+ detectors: {
35
+ type: "array",
36
+ items: { type: "string" },
37
+ description: "Restrict to specific detectors. Accepts names / CCI IDs / threat categories.",
38
+ },
39
+ policy_path: {
40
+ type: "string",
41
+ description: "Path to a .primitivehub/policy.yaml. Without this: auto-discover from cwd → git root.",
42
+ },
43
+ allow_fail: {
44
+ type: "array",
45
+ items: { type: "string" },
46
+ },
47
+ },
48
+ },
49
+ };
50
+ function summarize(result) {
51
+ return {
52
+ root: result.root,
53
+ policySource: result.policySource,
54
+ truncated: result.truncated,
55
+ scanClean: result.scanClean,
56
+ exitCode: result.exitCode,
57
+ summary: result.summary,
58
+ artifacts: result.artifacts.map((a) => ({
59
+ path: a.path,
60
+ classification: a.classification,
61
+ digest: a.digest,
62
+ scanned: a.scanned,
63
+ flagged: a.flagged,
64
+ // Surface the post-policy verdicts only — these are what an
65
+ // agent acts on. Raw pre-policy verdicts are available via
66
+ // scan_text against the artifact path if needed.
67
+ verdicts: a.adjustedVerdicts.map((adj) => ({
68
+ cciId: adj.verdict.cciId,
69
+ severity: adj.verdict.severity,
70
+ passed: adj.verdict.passed,
71
+ summary: adj.verdict.summary,
72
+ diffHints: adj.verdict.diffHints,
73
+ allowedHints: adj.allowedHints.map((ah) => ({
74
+ line: ah.hint.line,
75
+ snippet: ah.hint.snippet,
76
+ detailTag: ah.hint.detailTag,
77
+ reason: ah.allowEntry.reason,
78
+ })),
79
+ })),
80
+ })),
81
+ };
82
+ }
83
+ export function callAuditWorkspace(rawArgs) {
84
+ const args = (rawArgs ?? {});
85
+ const auditOpts = {
86
+ json: true,
87
+ sarif: false,
88
+ strict: args.strict ?? false,
89
+ detectors: args.detectors ?? [],
90
+ maxFiles: args.max_files ?? 10000,
91
+ maxDepth: args.max_depth ?? 16,
92
+ };
93
+ if (args.policy_path !== undefined)
94
+ auditOpts.policyPath = args.policy_path;
95
+ if (args.allow_fail !== undefined)
96
+ auditOpts.allowFailFor = args.allow_fail;
97
+ let result;
98
+ try {
99
+ result = runAudit(args.root ?? process.cwd(), auditOpts);
100
+ }
101
+ catch (err) {
102
+ const msg = err instanceof Error ? err.message : String(err);
103
+ return {
104
+ content: [{ type: "text", text: JSON.stringify({ error: msg }, null, 2) }],
105
+ isError: true,
106
+ };
107
+ }
108
+ return {
109
+ content: [{ type: "text", text: JSON.stringify(summarize(result), null, 2) }],
110
+ isError: result.exitCode !== 0,
111
+ };
112
+ }
113
+ //# sourceMappingURL=audit-workspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-workspace.js","sourceRoot":"","sources":["../../src/tools/audit-workspace.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * MCP tool: `check_lock`
3
+ *
4
+ * Compares the working tree against `.primitivehub/phub.lock`
5
+ * (ADR-0026) and reports drift. Pure transport over phub's audit
6
+ * surface with lockMode = "check".
7
+ *
8
+ * Foreshadows ADR-0029 (MCP runtime gate `verify_before_load`):
9
+ * the runtime gate is "check_lock + refuse-to-load on drift" applied
10
+ * at the agent's read time. This tool gives the agent the data;
11
+ * the gate is built when ADR-0029 lands.
12
+ */
13
+ export declare const CHECK_LOCK_TOOL: {
14
+ readonly name: "check_lock";
15
+ readonly description: "Compare the workspace against .primitivehub/phub.lock and report drift (added / modified / removed / reclassified artifacts). Use this BEFORE consuming any agent-context primitive — drift means an artifact changed since the operator last sealed it. Returns drift summary; the agent decides whether to proceed.";
16
+ readonly inputSchema: {
17
+ readonly type: "object";
18
+ readonly additionalProperties: false;
19
+ readonly properties: {
20
+ readonly root: {
21
+ readonly type: "string";
22
+ readonly description: "Workspace root to check. Defaults to server cwd.";
23
+ };
24
+ readonly lock_path: {
25
+ readonly type: "string";
26
+ readonly description: "Override the auto-discovered lock path. Without this: ./.primitivehub/phub.lock.";
27
+ };
28
+ readonly policy_path: {
29
+ readonly type: "string";
30
+ readonly description: "Policy file path (same semantics as scan_text/audit_workspace).";
31
+ };
32
+ readonly max_files: {
33
+ readonly type: "number";
34
+ readonly description: "Hard cap on artifacts walked. Default 10000.";
35
+ };
36
+ readonly max_depth: {
37
+ readonly type: "number";
38
+ readonly description: "Max directory depth. Default 16.";
39
+ };
40
+ };
41
+ };
42
+ };
43
+ export interface CheckLockResultText {
44
+ type: "text";
45
+ text: string;
46
+ }
47
+ export declare function callCheckLock(rawArgs: unknown): {
48
+ content: CheckLockResultText[];
49
+ isError: boolean;
50
+ };
51
+ //# sourceMappingURL=check-lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-lock.d.ts","sourceRoot":"","sources":["../../src/tools/check-lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyBlB,CAAA;AAUV,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,OAAO,GACf;IAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CA4CtD"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * MCP tool: `check_lock`
3
+ *
4
+ * Compares the working tree against `.primitivehub/phub.lock`
5
+ * (ADR-0026) and reports drift. Pure transport over phub's audit
6
+ * surface with lockMode = "check".
7
+ *
8
+ * Foreshadows ADR-0029 (MCP runtime gate `verify_before_load`):
9
+ * the runtime gate is "check_lock + refuse-to-load on drift" applied
10
+ * at the agent's read time. This tool gives the agent the data;
11
+ * the gate is built when ADR-0029 lands.
12
+ */
13
+ import { runAudit, } from "@primitivehub/phub";
14
+ export const CHECK_LOCK_TOOL = {
15
+ name: "check_lock",
16
+ description: "Compare the workspace against .primitivehub/phub.lock and report drift (added / modified / removed / reclassified artifacts). Use this BEFORE consuming any agent-context primitive — drift means an artifact changed since the operator last sealed it. Returns drift summary; the agent decides whether to proceed.",
17
+ inputSchema: {
18
+ type: "object",
19
+ additionalProperties: false,
20
+ properties: {
21
+ root: {
22
+ type: "string",
23
+ description: "Workspace root to check. Defaults to server cwd.",
24
+ },
25
+ lock_path: {
26
+ type: "string",
27
+ description: "Override the auto-discovered lock path. Without this: ./.primitivehub/phub.lock.",
28
+ },
29
+ policy_path: {
30
+ type: "string",
31
+ description: "Policy file path (same semantics as scan_text/audit_workspace).",
32
+ },
33
+ max_files: { type: "number", description: "Hard cap on artifacts walked. Default 10000." },
34
+ max_depth: { type: "number", description: "Max directory depth. Default 16." },
35
+ },
36
+ },
37
+ };
38
+ export function callCheckLock(rawArgs) {
39
+ const args = (rawArgs ?? {});
40
+ const auditOpts = {
41
+ json: true,
42
+ sarif: false,
43
+ strict: false,
44
+ detectors: [],
45
+ maxFiles: args.max_files ?? 10000,
46
+ maxDepth: args.max_depth ?? 16,
47
+ lockMode: "check",
48
+ };
49
+ if (args.lock_path !== undefined)
50
+ auditOpts.lockPath = args.lock_path;
51
+ if (args.policy_path !== undefined)
52
+ auditOpts.policyPath = args.policy_path;
53
+ let result;
54
+ try {
55
+ result = runAudit(args.root ?? process.cwd(), auditOpts);
56
+ }
57
+ catch (err) {
58
+ const msg = err instanceof Error ? err.message : String(err);
59
+ return {
60
+ content: [{ type: "text", text: JSON.stringify({ error: msg }, null, 2) }],
61
+ isError: true,
62
+ };
63
+ }
64
+ const lockState = result.lockState;
65
+ const payload = {
66
+ root: result.root,
67
+ lockMode: lockState?.mode ?? "off",
68
+ lockPath: lockState?.lockPath ?? null,
69
+ missing: lockState?.missing ?? false,
70
+ specVersionMismatch: lockState?.specVersionMismatch ?? false,
71
+ hasDrift: lockState?.hasDrift ?? false,
72
+ drift: lockState?.drift ?? null,
73
+ artifactCount: result.artifacts.length,
74
+ scanClean: result.scanClean,
75
+ exitCode: result.exitCode,
76
+ };
77
+ return {
78
+ content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
79
+ isError: result.exitCode !== 0,
80
+ };
81
+ }
82
+ //# sourceMappingURL=check-lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-lock.js","sourceRoot":"","sources":["../../src/tools/check-lock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * MCP tool: `scan_text`
3
+ *
4
+ * Runs the Context CI Top 10 v0.1 detector roster (T1/T2/T5) against
5
+ * arbitrary text. Pure transport over `@primitivehub/phub`'s `runScan`.
6
+ *
7
+ * The agent passes the text it's about to consume (e.g. a freshly
8
+ * downloaded AGENTS.md, an MCP server's response, a copied skill);
9
+ * the tool returns the post-policy verdicts. The agent decides what
10
+ * to do with the result.
11
+ */
12
+ export declare const SCAN_TEXT_TOOL: {
13
+ readonly name: "scan_text";
14
+ readonly description: "Run the PrimitiveHub Context CI Top 10 v0.1 detectors (T1 prompt-injection, T2 Unicode-steganography, T5 unsafe-shell-install) against a string. Pure-local scan; no network. Returns per-detector verdicts, post-policy. Use this BEFORE loading any agent-context content from an untrusted source.";
15
+ readonly inputSchema: {
16
+ readonly type: "object";
17
+ readonly additionalProperties: false;
18
+ readonly required: readonly ["content"];
19
+ readonly properties: {
20
+ readonly content: {
21
+ readonly type: "string";
22
+ readonly description: "The text to scan (typically markdown — AGENTS.md, CLAUDE.md, .cursorrules, a skill body, etc.).";
23
+ };
24
+ readonly filename: {
25
+ readonly type: "string";
26
+ readonly description: "Optional filename for the content (used for policy matching against per-file allow rules). Defaults to '<inline>'.";
27
+ };
28
+ readonly detectors: {
29
+ readonly type: "array";
30
+ readonly items: {
31
+ readonly type: "string";
32
+ };
33
+ readonly description: "Restrict to specific detectors. Accepts detector names (t1.prompt_injection), CCI IDs (CCI-001), or threat categories (T1). Empty/omitted = all.";
34
+ };
35
+ readonly strict: {
36
+ readonly type: "boolean";
37
+ readonly description: "Treat WARN verdicts as FAIL for the policy exit code.";
38
+ };
39
+ readonly policy_path: {
40
+ readonly type: "string";
41
+ readonly description: "Path to a .primitivehub/policy.yaml file (ADR-0018). Without this: auto-discover from cwd → git root, fall back to implicit default.";
42
+ };
43
+ readonly allow_fail: {
44
+ readonly type: "array";
45
+ readonly items: {
46
+ readonly type: "string";
47
+ };
48
+ readonly description: "Detector/CCI/threat IDs permitted to FAIL without rejecting the scan. Appended to policy.allow as synthetic entries.";
49
+ };
50
+ };
51
+ };
52
+ };
53
+ export interface ScanTextResultText {
54
+ type: "text";
55
+ text: string;
56
+ }
57
+ export declare function callScanText(rawArgs: unknown): {
58
+ content: ScanTextResultText[];
59
+ isError: boolean;
60
+ };
61
+ //# sourceMappingURL=scan-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-text.d.ts","sourceRoot":"","sources":["../../src/tools/scan-text.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyCjB,CAAA;AAWV,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,OAAO,GACf;IAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CA6CrD"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * MCP tool: `scan_text`
3
+ *
4
+ * Runs the Context CI Top 10 v0.1 detector roster (T1/T2/T5) against
5
+ * arbitrary text. Pure transport over `@primitivehub/phub`'s `runScan`.
6
+ *
7
+ * The agent passes the text it's about to consume (e.g. a freshly
8
+ * downloaded AGENTS.md, an MCP server's response, a copied skill);
9
+ * the tool returns the post-policy verdicts. The agent decides what
10
+ * to do with the result.
11
+ */
12
+ import { runScan } from "@primitivehub/phub";
13
+ export const SCAN_TEXT_TOOL = {
14
+ name: "scan_text",
15
+ description: "Run the PrimitiveHub Context CI Top 10 v0.1 detectors (T1 prompt-injection, T2 Unicode-steganography, T5 unsafe-shell-install) against a string. Pure-local scan; no network. Returns per-detector verdicts, post-policy. Use this BEFORE loading any agent-context content from an untrusted source.",
16
+ inputSchema: {
17
+ type: "object",
18
+ additionalProperties: false,
19
+ required: ["content"],
20
+ properties: {
21
+ content: {
22
+ type: "string",
23
+ description: "The text to scan (typically markdown — AGENTS.md, CLAUDE.md, .cursorrules, a skill body, etc.).",
24
+ },
25
+ filename: {
26
+ type: "string",
27
+ description: "Optional filename for the content (used for policy matching against per-file allow rules). Defaults to '<inline>'.",
28
+ },
29
+ detectors: {
30
+ type: "array",
31
+ items: { type: "string" },
32
+ description: "Restrict to specific detectors. Accepts detector names (t1.prompt_injection), CCI IDs (CCI-001), or threat categories (T1). Empty/omitted = all.",
33
+ },
34
+ strict: {
35
+ type: "boolean",
36
+ description: "Treat WARN verdicts as FAIL for the policy exit code.",
37
+ },
38
+ policy_path: {
39
+ type: "string",
40
+ description: "Path to a .primitivehub/policy.yaml file (ADR-0018). Without this: auto-discover from cwd → git root, fall back to implicit default.",
41
+ },
42
+ allow_fail: {
43
+ type: "array",
44
+ items: { type: "string" },
45
+ description: "Detector/CCI/threat IDs permitted to FAIL without rejecting the scan. Appended to policy.allow as synthetic entries.",
46
+ },
47
+ },
48
+ },
49
+ };
50
+ export function callScanText(rawArgs) {
51
+ const args = (rawArgs ?? {});
52
+ if (typeof args.content !== "string") {
53
+ return errorResponse("content argument is required (string)");
54
+ }
55
+ const filename = args.filename ?? "<inline>";
56
+ const scanOpts = {
57
+ json: true,
58
+ sarif: false,
59
+ strict: args.strict ?? false,
60
+ detectors: args.detectors ?? [],
61
+ allowFail: args.allow_fail ?? [],
62
+ };
63
+ if (args.policy_path !== undefined) {
64
+ scanOpts.policyPath = args.policy_path;
65
+ }
66
+ const result = runScan(filename, args.content, scanOpts);
67
+ const summary = result.evaluation.summary;
68
+ const allowed = result.evaluation.adjusted.flatMap((a) => a.allowedHints.map((ah) => ({
69
+ cciId: a.verdict.cciId,
70
+ line: ah.hint.line,
71
+ snippet: ah.hint.snippet,
72
+ detailTag: ah.hint.detailTag,
73
+ reason: ah.allowEntry.reason,
74
+ })));
75
+ const payload = {
76
+ filename: result.filename,
77
+ policySource: result.policySource,
78
+ verdicts: result.verdicts,
79
+ policyAllowed: allowed,
80
+ summary,
81
+ exitCode: result.exitCode,
82
+ };
83
+ return {
84
+ content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
85
+ isError: result.exitCode !== 0,
86
+ };
87
+ }
88
+ function errorResponse(message) {
89
+ return {
90
+ content: [{ type: "text", text: JSON.stringify({ error: message }, null, 2) }],
91
+ isError: true,
92
+ };
93
+ }
94
+ //# sourceMappingURL=scan-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-text.js","sourceRoot":"","sources":["../../src/tools/scan-text.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * MCP tool: `verify_before_load`
3
+ *
4
+ * The composite runtime gate. Per ADR-0029, every agent runtime that
5
+ * loads agent-context primitives MUST consult this tool before reading
6
+ * the content. Refuses-by-default for:
7
+ * - missing lock (operator hasn't sealed anything)
8
+ * - lock spec-version mismatch (Top 10 ratcheted; re-seal required)
9
+ * - drift (working tree differs from lock)
10
+ * - unattested artifacts (with requireAttestation set)
11
+ * - scanner findings (T1/T2/T5 at v0.1)
12
+ * - invalid Trust Bundle (when one is provided)
13
+ *
14
+ * Pure transport per ADR-0031 § 2 rule #1. Combines two existing
15
+ * primitives:
16
+ * - `verifyBeforeLoad` from @primitivehub/phub (workspace + lock + scan)
17
+ * - `verifyBundle` from @primitivehub/verify (cryptographic bundle)
18
+ *
19
+ * If a future ADR changes any check semantics, it changes in phub /
20
+ * verify; this file inherits the new behavior with zero edits.
21
+ */
22
+ export declare const VERIFY_BEFORE_LOAD_TOOL: {
23
+ readonly name: "verify_before_load";
24
+ readonly description: "Composite runtime gate. Call this BEFORE loading any agent-context primitive — refuses-by-default for drift, unattested artifacts, scanner findings, or invalid Trust Bundles. Returns {safe, reasons[], checks}. The composite of check_lock + scan_text + (optional) verify_bundle.";
25
+ readonly inputSchema: {
26
+ readonly type: "object";
27
+ readonly additionalProperties: false;
28
+ readonly required: readonly ["path"];
29
+ readonly properties: {
30
+ readonly path: {
31
+ readonly type: "string";
32
+ readonly description: "The artifact path to gate (relative to workspace_root, or absolute). The agent's 'I'm about to read this file' anchor.";
33
+ };
34
+ readonly workspace_root: {
35
+ readonly type: "string";
36
+ readonly description: "Workspace root. Defaults to the server's cwd.";
37
+ };
38
+ readonly policy_path: {
39
+ readonly type: "string";
40
+ readonly description: "Path to .primitivehub/policy.yaml. Auto-discover if absent.";
41
+ };
42
+ readonly lock_path: {
43
+ readonly type: "string";
44
+ readonly description: "Explicit lock path. Auto-discover if absent.";
45
+ };
46
+ readonly require_attestation: {
47
+ readonly type: "boolean";
48
+ readonly description: "If true, an 'unattested' lock entry counts as unsafe. Use when consuming registry primitives that should carry rekor:* or registry:* attestations. Default false (matches v0.1 lock semantics).";
49
+ };
50
+ readonly bundle: {
51
+ readonly description: "Optional Trust Bundle (JSON string OR parsed object). When provided, verify_bundle runs at the requested level and contributes its failures to the unsafe reasons.";
52
+ readonly oneOf: readonly [{
53
+ readonly type: "string";
54
+ }, {
55
+ readonly type: "object";
56
+ }];
57
+ };
58
+ readonly level: {
59
+ readonly type: "string";
60
+ readonly enum: readonly ["structural", "policy", "full"];
61
+ readonly description: "Bundle verification depth. Only meaningful when 'bundle' is provided. Default 'policy'.";
62
+ };
63
+ };
64
+ };
65
+ };
66
+ export interface VerifyBeforeLoadResultText {
67
+ type: "text";
68
+ text: string;
69
+ }
70
+ export declare function callVerifyBeforeLoad(rawArgs: unknown): Promise<{
71
+ content: VerifyBeforeLoadResultText[];
72
+ isError: boolean;
73
+ }>;
74
+ //# sourceMappingURL=verify-before-load.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-before-load.d.ts","sourceRoot":"","sources":["../../src/tools/verify-before-load.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAKH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4C1B,CAAA;AAYV,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,OAAO,GACf,OAAO,CAAC;IAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CA0FtE"}