@zivis/mcp 0.1.0-alpha.21 → 0.1.0-alpha.23

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.
Files changed (223) hide show
  1. package/dist/matcher/ast-eval.d.ts +27 -0
  2. package/dist/matcher/ast-eval.js +132 -0
  3. package/dist/matcher/ast-eval.js.map +1 -0
  4. package/dist/matcher/finding.d.ts +76 -0
  5. package/dist/matcher/finding.js +14 -0
  6. package/dist/matcher/finding.js.map +1 -0
  7. package/dist/matcher/index.d.ts +30 -0
  8. package/dist/matcher/index.js +255 -0
  9. package/dist/matcher/index.js.map +1 -0
  10. package/dist/matcher/inference-candidates.d.ts +54 -0
  11. package/dist/matcher/inference-candidates.js +106 -0
  12. package/dist/matcher/inference-candidates.js.map +1 -0
  13. package/dist/matcher/walker.d.ts +14 -0
  14. package/dist/matcher/walker.js +79 -0
  15. package/dist/matcher/walker.js.map +1 -0
  16. package/dist/pattern-pack/index.d.ts +154 -0
  17. package/dist/pattern-pack/index.js +224 -0
  18. package/dist/pattern-pack/index.js.map +1 -0
  19. package/dist/pattern-packs/zivis-public-0.1.0/capsules/agents/privilege-separation.yaml +224 -0
  20. package/dist/pattern-packs/zivis-public-0.1.0/capsules/prompting/self-consistency-no-isolation.yaml +237 -0
  21. package/dist/pattern-packs/zivis-public-0.1.0/capsules/security/late-org-filter.yaml +266 -0
  22. package/dist/pattern-packs/zivis-public-0.1.0/controls/external_validator_on_facts.yaml +37 -0
  23. package/dist/pattern-packs/zivis-public-0.1.0/controls/human_approval_gate.yaml +44 -0
  24. package/dist/pattern-packs/zivis-public-0.1.0/controls/langgraph_state_machine_with_per_node_tools.yaml +35 -0
  25. package/dist/pattern-packs/zivis-public-0.1.0/controls/per_sample_retrieval_diversification.yaml +38 -0
  26. package/dist/pattern-packs/zivis-public-0.1.0/controls/prisma_extension_or_middleware_attaching_org_filter.yaml +31 -0
  27. package/dist/pattern-packs/zivis-public-0.1.0/controls/row_level_security_policy.yaml +37 -0
  28. package/dist/pattern-packs/zivis-public-0.1.0/manifest.json +129 -0
  29. package/dist/pattern-packs/zivis-public-0.1.0/prompts/agents/privilege-separation/identify.md +54 -0
  30. package/dist/pattern-packs/zivis-public-0.1.0/prompts/prompting/self-consistency-no-isolation/identify.md +60 -0
  31. package/dist/pattern-packs/zivis-public-0.1.0/prompts/security/late-org-filter/identify.md +78 -0
  32. package/dist/prompts/index.d.ts +1 -1
  33. package/dist/prompts/index.js +1 -7
  34. package/dist/prompts/index.js.map +1 -1
  35. package/dist/server.js +36 -166
  36. package/dist/server.js.map +1 -1
  37. package/dist/tools/enterprise/get-threat-model-artifact.d.ts +30 -0
  38. package/dist/tools/enterprise/get-threat-model-artifact.js +80 -0
  39. package/dist/tools/enterprise/get-threat-model-artifact.js.map +1 -0
  40. package/dist/tools/enterprise/get-threat-model.d.ts +1 -1
  41. package/dist/tools/enterprise/get-threat-model.js +59 -11
  42. package/dist/tools/enterprise/get-threat-model.js.map +1 -1
  43. package/dist/tools/enterprise/list-threat-model-artifacts.d.ts +67 -0
  44. package/dist/tools/enterprise/list-threat-model-artifacts.js +121 -0
  45. package/dist/tools/enterprise/list-threat-model-artifacts.js.map +1 -0
  46. package/dist/tools/enterprise/manage-actor.d.ts +1 -1
  47. package/dist/tools/enterprise/manage-actor.js +14 -1
  48. package/dist/tools/enterprise/manage-actor.js.map +1 -1
  49. package/dist/tools/enterprise/manage-attack-scenario.d.ts +1 -1
  50. package/dist/tools/enterprise/manage-attack-scenario.js +13 -1
  51. package/dist/tools/enterprise/manage-attack-scenario.js.map +1 -1
  52. package/dist/tools/enterprise/manage-component.d.ts +1 -1
  53. package/dist/tools/enterprise/manage-component.js +20 -1
  54. package/dist/tools/enterprise/manage-component.js.map +1 -1
  55. package/dist/tools/enterprise/manage-data-asset.d.ts +2 -2
  56. package/dist/tools/enterprise/manage-data-asset.js +17 -1
  57. package/dist/tools/enterprise/manage-data-asset.js.map +1 -1
  58. package/dist/tools/enterprise/manage-data-flow.d.ts +2 -2
  59. package/dist/tools/enterprise/manage-data-flow.js +19 -1
  60. package/dist/tools/enterprise/manage-data-flow.js.map +1 -1
  61. package/dist/tools/enterprise/manage-security-control.d.ts +1 -1
  62. package/dist/tools/enterprise/manage-security-control.js +18 -1
  63. package/dist/tools/enterprise/manage-security-control.js.map +1 -1
  64. package/dist/tools/enterprise/manage-test-case.d.ts +2 -2
  65. package/dist/tools/enterprise/manage-test-case.js +8 -0
  66. package/dist/tools/enterprise/manage-test-case.js.map +1 -1
  67. package/dist/tools/get-started.d.ts +1 -1
  68. package/dist/tools/get-started.js +185 -8
  69. package/dist/tools/get-started.js.map +1 -1
  70. package/dist/tools/inspect.d.ts +38 -0
  71. package/dist/tools/inspect.js +252 -0
  72. package/dist/tools/inspect.js.map +1 -0
  73. package/dist/tools/manage-application.d.ts +1 -1
  74. package/dist/tools/security-review.js +67 -50
  75. package/dist/tools/security-review.js.map +1 -1
  76. package/dist/tools/threat-get-capsule.d.ts +25 -0
  77. package/dist/tools/threat-get-capsule.js +64 -0
  78. package/dist/tools/threat-get-capsule.js.map +1 -0
  79. package/dist/tools/threat-get-inference-prompt.d.ts +32 -0
  80. package/dist/tools/threat-get-inference-prompt.js +91 -0
  81. package/dist/tools/threat-get-inference-prompt.js.map +1 -0
  82. package/dist/tools/threat-guide.d.ts +39 -0
  83. package/dist/tools/threat-guide.js +111 -0
  84. package/dist/tools/threat-guide.js.map +1 -0
  85. package/dist/tools/threat-list-relevant-capsules.d.ts +30 -0
  86. package/dist/tools/threat-list-relevant-capsules.js +176 -0
  87. package/dist/tools/threat-list-relevant-capsules.js.map +1 -0
  88. package/dist/tools/threat-run-matcher.d.ts +27 -0
  89. package/dist/tools/threat-run-matcher.js +164 -0
  90. package/dist/tools/threat-run-matcher.js.map +1 -0
  91. package/package.json +13 -3
  92. package/dist/prompts/prep-for-launch.d.ts +0 -9
  93. package/dist/prompts/prep-for-launch.js +0 -62
  94. package/dist/prompts/prep-for-launch.js.map +0 -1
  95. package/dist/prompts/secure-my-app.d.ts +0 -9
  96. package/dist/prompts/secure-my-app.js +0 -70
  97. package/dist/prompts/secure-my-app.js.map +0 -1
  98. package/dist/prompts/weekly-check.d.ts +0 -9
  99. package/dist/prompts/weekly-check.js +0 -48
  100. package/dist/prompts/weekly-check.js.map +0 -1
  101. package/dist/tools/enterprise/capture-evidence.d.ts +0 -54
  102. package/dist/tools/enterprise/capture-evidence.js +0 -72
  103. package/dist/tools/enterprise/capture-evidence.js.map +0 -1
  104. package/dist/tools/enterprise/create-report-ticket.d.ts +0 -34
  105. package/dist/tools/enterprise/create-report-ticket.js +0 -44
  106. package/dist/tools/enterprise/create-report-ticket.js.map +0 -1
  107. package/dist/tools/enterprise/end-pentest-session.d.ts +0 -33
  108. package/dist/tools/enterprise/end-pentest-session.js +0 -42
  109. package/dist/tools/enterprise/end-pentest-session.js.map +0 -1
  110. package/dist/tools/enterprise/generate-report.d.ts +0 -55
  111. package/dist/tools/enterprise/generate-report.js +0 -111
  112. package/dist/tools/enterprise/generate-report.js.map +0 -1
  113. package/dist/tools/enterprise/get-campaign.d.ts +0 -27
  114. package/dist/tools/enterprise/get-campaign.js +0 -31
  115. package/dist/tools/enterprise/get-campaign.js.map +0 -1
  116. package/dist/tools/enterprise/get-report-status.d.ts +0 -27
  117. package/dist/tools/enterprise/get-report-status.js +0 -38
  118. package/dist/tools/enterprise/get-report-status.js.map +0 -1
  119. package/dist/tools/enterprise/list-agents.d.ts +0 -42
  120. package/dist/tools/enterprise/list-agents.js +0 -95
  121. package/dist/tools/enterprise/list-agents.js.map +0 -1
  122. package/dist/tools/enterprise/list-campaigns.d.ts +0 -37
  123. package/dist/tools/enterprise/list-campaigns.js +0 -60
  124. package/dist/tools/enterprise/list-campaigns.js.map +0 -1
  125. package/dist/tools/enterprise/list-report-issues.d.ts +0 -36
  126. package/dist/tools/enterprise/list-report-issues.js +0 -50
  127. package/dist/tools/enterprise/list-report-issues.js.map +0 -1
  128. package/dist/tools/enterprise/manage-campaign-agent-instance.d.ts +0 -42
  129. package/dist/tools/enterprise/manage-campaign-agent-instance.js +0 -68
  130. package/dist/tools/enterprise/manage-campaign-agent-instance.js.map +0 -1
  131. package/dist/tools/enterprise/manage-campaign-target.d.ts +0 -44
  132. package/dist/tools/enterprise/manage-campaign-target.js +0 -70
  133. package/dist/tools/enterprise/manage-campaign-target.js.map +0 -1
  134. package/dist/tools/enterprise/manage-campaign.d.ts +0 -62
  135. package/dist/tools/enterprise/manage-campaign.js +0 -114
  136. package/dist/tools/enterprise/manage-campaign.js.map +0 -1
  137. package/dist/tools/enterprise/manage-finding.d.ts +0 -69
  138. package/dist/tools/enterprise/manage-finding.js +0 -106
  139. package/dist/tools/enterprise/manage-finding.js.map +0 -1
  140. package/dist/tools/enterprise/promote-finding-to-issue.d.ts +0 -36
  141. package/dist/tools/enterprise/promote-finding-to-issue.js +0 -65
  142. package/dist/tools/enterprise/promote-finding-to-issue.js.map +0 -1
  143. package/dist/tools/enterprise/publish-report-version.d.ts +0 -34
  144. package/dist/tools/enterprise/publish-report-version.js +0 -75
  145. package/dist/tools/enterprise/publish-report-version.js.map +0 -1
  146. package/dist/tools/enterprise/publish-test-to-library.d.ts +0 -31
  147. package/dist/tools/enterprise/publish-test-to-library.js +0 -40
  148. package/dist/tools/enterprise/publish-test-to-library.js.map +0 -1
  149. package/dist/tools/enterprise/record-test-result.d.ts +0 -67
  150. package/dist/tools/enterprise/record-test-result.js +0 -75
  151. package/dist/tools/enterprise/record-test-result.js.map +0 -1
  152. package/dist/tools/enterprise/start-pentest-session.d.ts +0 -35
  153. package/dist/tools/enterprise/start-pentest-session.js +0 -50
  154. package/dist/tools/enterprise/start-pentest-session.js.map +0 -1
  155. package/dist/tools/enterprise/sync-report-section.d.ts +0 -41
  156. package/dist/tools/enterprise/sync-report-section.js +0 -79
  157. package/dist/tools/enterprise/sync-report-section.js.map +0 -1
  158. package/dist/tools/enterprise/update-report-issue.d.ts +0 -55
  159. package/dist/tools/enterprise/update-report-issue.js +0 -69
  160. package/dist/tools/enterprise/update-report-issue.js.map +0 -1
  161. package/dist/tools/get-agent-test-results.d.ts +0 -41
  162. package/dist/tools/get-agent-test-results.js +0 -86
  163. package/dist/tools/get-agent-test-results.js.map +0 -1
  164. package/dist/tools/get-application-auth-config.d.ts +0 -27
  165. package/dist/tools/get-application-auth-config.js +0 -44
  166. package/dist/tools/get-application-auth-config.js.map +0 -1
  167. package/dist/tools/get-artifact-content.d.ts +0 -29
  168. package/dist/tools/get-artifact-content.js +0 -86
  169. package/dist/tools/get-artifact-content.js.map +0 -1
  170. package/dist/tools/get-finding-details.d.ts +0 -22
  171. package/dist/tools/get-finding-details.js +0 -61
  172. package/dist/tools/get-finding-details.js.map +0 -1
  173. package/dist/tools/get-findings.d.ts +0 -51
  174. package/dist/tools/get-findings.js +0 -124
  175. package/dist/tools/get-findings.js.map +0 -1
  176. package/dist/tools/get-recon-scan.d.ts +0 -27
  177. package/dist/tools/get-recon-scan.js +0 -46
  178. package/dist/tools/get-recon-scan.js.map +0 -1
  179. package/dist/tools/get-scan-output.d.ts +0 -27
  180. package/dist/tools/get-scan-output.js +0 -64
  181. package/dist/tools/get-scan-output.js.map +0 -1
  182. package/dist/tools/get-scenario-details.d.ts +0 -27
  183. package/dist/tools/get-scenario-details.js +0 -46
  184. package/dist/tools/get-scenario-details.js.map +0 -1
  185. package/dist/tools/get-test-case-results.d.ts +0 -37
  186. package/dist/tools/get-test-case-results.js +0 -66
  187. package/dist/tools/get-test-case-results.js.map +0 -1
  188. package/dist/tools/get-test-details.d.ts +0 -29
  189. package/dist/tools/get-test-details.js +0 -49
  190. package/dist/tools/get-test-details.js.map +0 -1
  191. package/dist/tools/list-agent-test-cases.d.ts +0 -41
  192. package/dist/tools/list-agent-test-cases.js +0 -73
  193. package/dist/tools/list-agent-test-cases.js.map +0 -1
  194. package/dist/tools/list-recon-scans.d.ts +0 -36
  195. package/dist/tools/list-recon-scans.js +0 -74
  196. package/dist/tools/list-recon-scans.js.map +0 -1
  197. package/dist/tools/list-scan-artifacts.d.ts +0 -41
  198. package/dist/tools/list-scan-artifacts.js +0 -63
  199. package/dist/tools/list-scan-artifacts.js.map +0 -1
  200. package/dist/tools/list-scans.d.ts +0 -38
  201. package/dist/tools/list-scans.js +0 -125
  202. package/dist/tools/list-scans.js.map +0 -1
  203. package/dist/tools/list-test-library.d.ts +0 -44
  204. package/dist/tools/list-test-library.js +0 -83
  205. package/dist/tools/list-test-library.js.map +0 -1
  206. package/dist/tools/list-test-scenarios.d.ts +0 -25
  207. package/dist/tools/list-test-scenarios.js +0 -94
  208. package/dist/tools/list-test-scenarios.js.map +0 -1
  209. package/dist/tools/local-scan.d.ts +0 -40
  210. package/dist/tools/local-scan.js +0 -261
  211. package/dist/tools/local-scan.js.map +0 -1
  212. package/dist/tools/run-test-scenario.d.ts +0 -37
  213. package/dist/tools/run-test-scenario.js +0 -70
  214. package/dist/tools/run-test-scenario.js.map +0 -1
  215. package/dist/tools/scan-pr.d.ts +0 -27
  216. package/dist/tools/scan-pr.js +0 -51
  217. package/dist/tools/scan-pr.js.map +0 -1
  218. package/dist/tools/setup-red-team-target.d.ts +0 -73
  219. package/dist/tools/setup-red-team-target.js +0 -461
  220. package/dist/tools/setup-red-team-target.js.map +0 -1
  221. package/dist/tools/triage-finding.d.ts +0 -41
  222. package/dist/tools/triage-finding.js +0 -125
  223. package/dist/tools/triage-finding.js.map +0 -1
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Aggregate inference candidates from matcher findings into a top-level
3
+ * bundle the host LLM can't ignore.
4
+ *
5
+ * The matcher already attaches `inference_candidate` to each finding (when
6
+ * the capsule has an INFER strategy with model_task_prompt_ref), but if
7
+ * the host LLM only reads the headline it'll never call
8
+ * `zivis_threat_get_inference_prompt` and the inference never happens.
9
+ *
10
+ * This module promotes inference candidates to a structured top-level
11
+ * `inference_candidates[]` block with the prompt text bundled inline,
12
+ * plus a `host_required_action` directive. The host LLM gets everything
13
+ * it needs to run inference in one tool result — no extra calls.
14
+ *
15
+ * This is "Option A" from the local-inference triage. Modes B (local LLM
16
+ * sidecar) and C (ZIVIS-hosted cloud inference) are roadmap items.
17
+ */
18
+ import { loadActivePack, getInferencePrompt, } from "../pattern-pack/index.js";
19
+ /**
20
+ * Build the inline inference bundle for a list of findings. Loads the pack
21
+ * once, fetches each capsule's inference prompt, and packages it with the
22
+ * deterministic-strategy evidence so the host can run inference without
23
+ * any further MCP round-trip.
24
+ */
25
+ export async function buildInferenceBundle(findings, capsuleByPatternId) {
26
+ const candidates = [];
27
+ let handle;
28
+ for (let i = 0; i < findings.length; i++) {
29
+ const f = findings[i];
30
+ if (!f.inference_candidate)
31
+ continue;
32
+ if (!handle) {
33
+ try {
34
+ handle = await loadActivePack();
35
+ }
36
+ catch {
37
+ // No pack — emit candidates without inline prompt; host falls back to get_inference_prompt.
38
+ candidates.push(toFallbackCandidate(f, i));
39
+ continue;
40
+ }
41
+ }
42
+ let promptText;
43
+ try {
44
+ promptText = await getInferencePrompt(handle, f.inference_candidate.prompt_ref);
45
+ }
46
+ catch {
47
+ candidates.push(toFallbackCandidate(f, i));
48
+ continue;
49
+ }
50
+ const cap = capsuleByPatternId?.get(f.pattern_id);
51
+ candidates.push({
52
+ candidate_id: `ic-${i + 1}`,
53
+ capsule_id: f.pattern_id,
54
+ capsule_version: f.pattern_version,
55
+ pattern_title: cap?.title,
56
+ prompt: promptText,
57
+ expected_output_schema: f.inference_candidate.expected_output_schema ?? null,
58
+ evidence_focus: f.evidence
59
+ .filter((e) => e.file !== "(synthetic)")
60
+ .map((e) => ({
61
+ file: e.file,
62
+ start_line: e.start_line,
63
+ end_line: e.end_line,
64
+ note: e.matched_text ? e.matched_text.slice(0, 200) : undefined,
65
+ })),
66
+ minimum_context_required: f.inference_candidate.minimum_context_required,
67
+ instructions_for_host: "Read the source code at each evidence_focus[*].file:start_line — pull at least minimum_context_required.lines around each span. " +
68
+ "Attach those snippets to the prompt above. Run the prompt against your model. " +
69
+ "Return JSON matching expected_output_schema. The output enters the inferred lane.",
70
+ });
71
+ }
72
+ const action = buildHostRequiredAction(candidates);
73
+ return { inference_candidates: candidates, host_required_action: action };
74
+ }
75
+ function toFallbackCandidate(f, i) {
76
+ return {
77
+ candidate_id: `ic-${i + 1}`,
78
+ capsule_id: f.pattern_id,
79
+ capsule_version: f.pattern_version,
80
+ prompt: "",
81
+ expected_output_schema: f.inference_candidate?.expected_output_schema ?? null,
82
+ evidence_focus: f.evidence
83
+ .filter((e) => e.file !== "(synthetic)")
84
+ .map((e) => ({
85
+ file: e.file,
86
+ start_line: e.start_line,
87
+ end_line: e.end_line,
88
+ })),
89
+ minimum_context_required: f.inference_candidate?.minimum_context_required,
90
+ instructions_for_host: "Inline prompt unavailable. Call zivis_threat_get_inference_prompt with capsule_id=" +
91
+ f.pattern_id +
92
+ " to retrieve it.",
93
+ };
94
+ }
95
+ function buildHostRequiredAction(candidates) {
96
+ if (candidates.length === 0) {
97
+ return "No inference candidates emitted by this run. Findings are deterministic-only.";
98
+ }
99
+ return (`MANDATORY HOST ACTION: For each of the ${candidates.length} inference_candidate${candidates.length === 1 ? "" : "s"} below, ` +
100
+ `you MUST: (1) read the source code at evidence_focus[*].file:start_line (open each file, grab at least minimum_context_required.lines of surrounding context), ` +
101
+ `(2) run the candidate's prompt against your model with that source attached, ` +
102
+ `(3) produce JSON output matching expected_output_schema. ` +
103
+ `Do this BEFORE summarizing findings to the user — the inferred-lane verdict from your inference is what the user actually wants. ` +
104
+ `Each candidate is a self-contained inference task; you do not need to call any other ZIVIS tool to execute it.`);
105
+ }
106
+ //# sourceMappingURL=inference-candidates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inference-candidates.js","sourceRoot":"","sources":["../../src/matcher/inference-candidates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Minimal source-file walker for the matcher.
3
+ *
4
+ * Mirrors the extractor's walker conventions (hard-skip dirs, file cap,
5
+ * .gitignore awareness via plain readdir) but stays self-contained inside
6
+ * the MCP package so the matcher can run without dragging in the CLI.
7
+ */
8
+ export type WalkLanguage = "typescript" | "javascript" | "python" | "go";
9
+ export interface WalkResult {
10
+ filesByLanguage: Map<WalkLanguage, string[]>;
11
+ filesScanned: number;
12
+ filesSkipped: number;
13
+ }
14
+ export declare function walkLanguageFiles(rootDir: string, languages: WalkLanguage[]): Promise<WalkResult>;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Minimal source-file walker for the matcher.
3
+ *
4
+ * Mirrors the extractor's walker conventions (hard-skip dirs, file cap,
5
+ * .gitignore awareness via plain readdir) but stays self-contained inside
6
+ * the MCP package so the matcher can run without dragging in the CLI.
7
+ */
8
+ import * as fs from "node:fs/promises";
9
+ import * as path from "node:path";
10
+ const HARD_SKIP_DIRS = new Set([
11
+ "node_modules",
12
+ ".git",
13
+ ".yarn",
14
+ ".pnpm",
15
+ "dist",
16
+ "build",
17
+ "out",
18
+ ".next",
19
+ ".nuxt",
20
+ ".turbo",
21
+ ".cache",
22
+ "coverage",
23
+ "vendor",
24
+ "__pycache__",
25
+ ".venv",
26
+ "target",
27
+ ]);
28
+ const MAX_FILES = 50_000;
29
+ const LANG_EXTENSIONS = {
30
+ typescript: [".ts", ".tsx"],
31
+ javascript: [".js", ".jsx", ".mjs", ".cjs"],
32
+ python: [".py"],
33
+ go: [".go"],
34
+ };
35
+ export async function walkLanguageFiles(rootDir, languages) {
36
+ const extToLang = new Map();
37
+ for (const lang of languages) {
38
+ for (const ext of LANG_EXTENSIONS[lang])
39
+ extToLang.set(ext, lang);
40
+ }
41
+ const filesByLanguage = new Map();
42
+ for (const lang of languages)
43
+ filesByLanguage.set(lang, []);
44
+ let filesScanned = 0;
45
+ let filesSkipped = 0;
46
+ const total = () => Array.from(filesByLanguage.values()).reduce((n, l) => n + l.length, 0);
47
+ async function visit(dirAbs) {
48
+ if (total() >= MAX_FILES)
49
+ return;
50
+ let entries;
51
+ try {
52
+ entries = await fs.readdir(dirAbs, { withFileTypes: true });
53
+ }
54
+ catch {
55
+ return;
56
+ }
57
+ for (const entry of entries) {
58
+ if (entry.isDirectory()) {
59
+ if (HARD_SKIP_DIRS.has(entry.name) || entry.name.startsWith(".")) {
60
+ filesSkipped++;
61
+ continue;
62
+ }
63
+ await visit(path.join(dirAbs, entry.name));
64
+ continue;
65
+ }
66
+ if (!entry.isFile() && !entry.isSymbolicLink())
67
+ continue;
68
+ filesScanned++;
69
+ const ext = path.extname(entry.name).toLowerCase();
70
+ const lang = extToLang.get(ext);
71
+ if (lang) {
72
+ filesByLanguage.get(lang).push(path.join(dirAbs, entry.name));
73
+ }
74
+ }
75
+ }
76
+ await visit(rootDir);
77
+ return { filesByLanguage, filesScanned, filesSkipped };
78
+ }
79
+ //# sourceMappingURL=walker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walker.js","sourceRoot":"","sources":["../../src/matcher/walker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Local pattern pack reader.
3
+ *
4
+ * The pack ships bundled inside the @zivis/mcp npm package at
5
+ * `dist/pattern-packs/<pack-id>-<version>/`. On first use we copy it to
6
+ * `~/Library/Caches/zivis/pattern-packs/<pack-id>-<version>/` so future
7
+ * runs read from the user cache directly.
8
+ *
9
+ * Both the CLI's matcher (Phase 3) and the MCP tools that surface
10
+ * relevant capsules mid-IDE-conversation read through this module.
11
+ *
12
+ * Plan: docs/plans/LOCAL-REPO-GRAPH-IMPLEMENTATION.md (Phase 2A)
13
+ * Schemas:
14
+ * - schemas/pattern-pack-manifest.schema.json (manifest.json)
15
+ * - schemas/pattern-detection-card.schema.json (capsule yaml)
16
+ */
17
+ export interface PackManifest {
18
+ schema_version: "1.0.0";
19
+ pack_id: string;
20
+ pack_name: string;
21
+ version: string;
22
+ built_at: string;
23
+ tier: "public_teaser" | "public" | "customer_safe";
24
+ description?: string;
25
+ capsules: ManifestCapsuleEntry[];
26
+ prompts: ManifestPromptEntry[];
27
+ controls?: ManifestControlEntry[];
28
+ }
29
+ export interface ManifestCapsuleEntry {
30
+ id: string;
31
+ version: string;
32
+ path: string;
33
+ sha256: string;
34
+ category?: string;
35
+ lifecycle?: string;
36
+ applicable_languages?: string[];
37
+ }
38
+ export interface ManifestPromptEntry {
39
+ path: string;
40
+ sha256: string;
41
+ capsule_id?: string;
42
+ }
43
+ export interface ManifestControlEntry {
44
+ id: string;
45
+ path: string;
46
+ sha256: string;
47
+ applicable_languages?: string[];
48
+ }
49
+ export interface ControlDetectionRule {
50
+ language: "typescript" | "javascript" | "python" | "go";
51
+ rule: unknown;
52
+ }
53
+ export interface Control {
54
+ id: string;
55
+ description?: string;
56
+ applicable_languages: string[];
57
+ detection: ControlDetectionRule[];
58
+ lifecycle?: string;
59
+ owner?: string;
60
+ }
61
+ export interface RelevanceTerm {
62
+ dependency?: string;
63
+ direct_only?: boolean;
64
+ language?: string;
65
+ framework?: string;
66
+ evidence?: string;
67
+ }
68
+ export interface RelevanceFilter {
69
+ any_of?: RelevanceTerm[];
70
+ all_of?: RelevanceTerm[];
71
+ none_of?: RelevanceTerm[];
72
+ }
73
+ export interface Capsule {
74
+ id: string;
75
+ slug: string;
76
+ version: string;
77
+ category: string;
78
+ title?: string;
79
+ headline?: string;
80
+ description?: string;
81
+ detection_tier: "public" | "proprietary";
82
+ scoring_tier: "public" | "proprietary";
83
+ applicable_languages: string[];
84
+ relevance_filter?: RelevanceFilter;
85
+ strategies: unknown[];
86
+ required_evidence_count: number;
87
+ threats?: unknown[];
88
+ lifecycle: "draft" | "active" | "deprecated";
89
+ sensitivity_level?: "public_teaser" | "customer_safe" | "zivis_confidential";
90
+ safe_summary?: string;
91
+ detect_when?: string;
92
+ risk_hints?: string[];
93
+ architectural_signals?: string[];
94
+ model_task_prompt_ref?: string;
95
+ expected_output_schema?: unknown;
96
+ minimum_context_required?: {
97
+ lines?: number;
98
+ symbols?: string[];
99
+ };
100
+ related_patterns?: string[];
101
+ repair_contract?: {
102
+ allowed?: string[];
103
+ forbidden?: string[];
104
+ };
105
+ validation_contract?: {
106
+ requires_tests_pass?: boolean;
107
+ requires_static_rules?: string[];
108
+ };
109
+ }
110
+ export interface PackHandle {
111
+ manifest: PackManifest;
112
+ rootDir: string;
113
+ }
114
+ /**
115
+ * Minimal structural interface of a RepoGraphArtifactV1 that the reader
116
+ * actually needs. Lets this module avoid a hard dep on the full graph-types
117
+ * package while preserving compatibility with `RepoGraphArtifactV1`.
118
+ */
119
+ export interface GraphArtifactView {
120
+ scope: {
121
+ languages?: string[];
122
+ };
123
+ nodes: Array<{
124
+ type: string;
125
+ evidence: Array<{
126
+ kind: string;
127
+ }>;
128
+ attributes?: {
129
+ package?: string;
130
+ };
131
+ }>;
132
+ }
133
+ /**
134
+ * Locate the active pack and ensure it's available in the user cache.
135
+ *
136
+ * Resolution order:
137
+ * 1. ZIVIS_PACK_DIR env var (override for tests / enterprise air-gap imports)
138
+ * 2. User cache, if present
139
+ * 3. Bundled pack inside @zivis/mcp (copied to user cache on first use)
140
+ */
141
+ export declare function loadActivePack(packId?: string): Promise<PackHandle>;
142
+ export declare function getCapsule(handle: PackHandle, capsuleId: string): Promise<Capsule>;
143
+ export declare function getInferencePrompt(handle: PackHandle, ref: string): Promise<string>;
144
+ export declare function listCapsuleIds(handle: PackHandle): Promise<string[]>;
145
+ export declare function listControlIds(handle: PackHandle): Promise<string[]>;
146
+ export declare function getControl(handle: PackHandle, controlId: string): Promise<Control>;
147
+ export declare function findRelevantCapsules(handle: PackHandle, artifact: GraphArtifactView): Promise<Capsule[]>;
148
+ interface EvalContext {
149
+ packageNames: Set<string>;
150
+ languages: Set<string>;
151
+ evidenceKinds: Set<string>;
152
+ }
153
+ export declare function matchesRelevance(cap: Capsule, ctx: EvalContext): boolean;
154
+ export {};
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Local pattern pack reader.
3
+ *
4
+ * The pack ships bundled inside the @zivis/mcp npm package at
5
+ * `dist/pattern-packs/<pack-id>-<version>/`. On first use we copy it to
6
+ * `~/Library/Caches/zivis/pattern-packs/<pack-id>-<version>/` so future
7
+ * runs read from the user cache directly.
8
+ *
9
+ * Both the CLI's matcher (Phase 3) and the MCP tools that surface
10
+ * relevant capsules mid-IDE-conversation read through this module.
11
+ *
12
+ * Plan: docs/plans/LOCAL-REPO-GRAPH-IMPLEMENTATION.md (Phase 2A)
13
+ * Schemas:
14
+ * - schemas/pattern-pack-manifest.schema.json (manifest.json)
15
+ * - schemas/pattern-detection-card.schema.json (capsule yaml)
16
+ */
17
+ import * as fs from "node:fs/promises";
18
+ import * as fssync from "node:fs";
19
+ import * as os from "node:os";
20
+ import * as path from "node:path";
21
+ import { fileURLToPath } from "node:url";
22
+ import * as crypto from "node:crypto";
23
+ import * as yaml from "js-yaml";
24
+ // ── Cache layout ──
25
+ function userCacheRoot() {
26
+ const home = os.homedir();
27
+ if (process.platform === "darwin") {
28
+ return path.join(home, "Library", "Caches", "zivis");
29
+ }
30
+ if (process.platform === "win32") {
31
+ const localAppData = process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local");
32
+ return path.join(localAppData, "zivis", "Cache");
33
+ }
34
+ const xdg = process.env.XDG_CACHE_HOME;
35
+ return path.join(xdg ?? path.join(home, ".cache"), "zivis");
36
+ }
37
+ function userPackRoot() {
38
+ return path.join(userCacheRoot(), "pattern-packs");
39
+ }
40
+ /**
41
+ * Locate the pack bundled inside the @zivis/mcp npm install. We resolve
42
+ * from this module's own URL so it works whether the MCP is installed
43
+ * globally, locally, or run via pnpm workspace symlink.
44
+ */
45
+ function bundledPackRoot() {
46
+ const here = path.dirname(fileURLToPath(import.meta.url));
47
+ // dist layout: dist/pattern-pack/index.js → dist/pattern-packs
48
+ return path.resolve(here, "../pattern-packs");
49
+ }
50
+ const DEFAULT_PACK_ID = "zivis-public";
51
+ // ── Loader ──
52
+ /**
53
+ * Locate the active pack and ensure it's available in the user cache.
54
+ *
55
+ * Resolution order:
56
+ * 1. ZIVIS_PACK_DIR env var (override for tests / enterprise air-gap imports)
57
+ * 2. User cache, if present
58
+ * 3. Bundled pack inside @zivis/mcp (copied to user cache on first use)
59
+ */
60
+ export async function loadActivePack(packId = DEFAULT_PACK_ID) {
61
+ if (process.env.ZIVIS_PACK_DIR) {
62
+ return readManifest(process.env.ZIVIS_PACK_DIR);
63
+ }
64
+ const cached = await findCachedPack(packId);
65
+ if (cached) {
66
+ return readManifest(cached);
67
+ }
68
+ const bundledDir = await findBundledPack(packId);
69
+ if (!bundledDir) {
70
+ throw new Error(`No pattern pack found. Looked in user cache (${userPackRoot()}) and bundled location (${bundledPackRoot()}). ` +
71
+ `Set ZIVIS_PACK_DIR to override.`);
72
+ }
73
+ const handle = await readManifest(bundledDir);
74
+ const cacheDir = path.join(userPackRoot(), `${handle.manifest.pack_id}-${handle.manifest.version}`);
75
+ await copyDir(bundledDir, cacheDir);
76
+ return { manifest: handle.manifest, rootDir: cacheDir };
77
+ }
78
+ async function findCachedPack(packId) {
79
+ const root = userPackRoot();
80
+ if (!fssync.existsSync(root))
81
+ return undefined;
82
+ const entries = await fs.readdir(root, { withFileTypes: true });
83
+ const candidates = entries
84
+ .filter((e) => e.isDirectory() && e.name.startsWith(`${packId}-`))
85
+ .map((e) => e.name)
86
+ .sort()
87
+ .reverse();
88
+ for (const name of candidates) {
89
+ const dir = path.join(root, name);
90
+ if (fssync.existsSync(path.join(dir, "manifest.json"))) {
91
+ return dir;
92
+ }
93
+ }
94
+ return undefined;
95
+ }
96
+ async function findBundledPack(packId) {
97
+ const root = bundledPackRoot();
98
+ if (!fssync.existsSync(root))
99
+ return undefined;
100
+ const entries = await fs.readdir(root, { withFileTypes: true });
101
+ const matches = entries
102
+ .filter((e) => e.isDirectory() && e.name.startsWith(`${packId}-`))
103
+ .map((e) => path.join(root, e.name))
104
+ .sort()
105
+ .reverse();
106
+ return matches[0];
107
+ }
108
+ async function readManifest(rootDir) {
109
+ const manifestPath = path.join(rootDir, "manifest.json");
110
+ const raw = await fs.readFile(manifestPath, "utf8");
111
+ const manifest = JSON.parse(raw);
112
+ return { manifest, rootDir };
113
+ }
114
+ async function copyDir(src, dst) {
115
+ await fs.mkdir(dst, { recursive: true });
116
+ const entries = await fs.readdir(src, { withFileTypes: true });
117
+ await Promise.all(entries.map(async (entry) => {
118
+ const s = path.join(src, entry.name);
119
+ const d = path.join(dst, entry.name);
120
+ if (entry.isDirectory())
121
+ await copyDir(s, d);
122
+ else if (entry.isFile())
123
+ await fs.copyFile(s, d);
124
+ }));
125
+ }
126
+ // ── Reader API ──
127
+ export async function getCapsule(handle, capsuleId) {
128
+ const entry = handle.manifest.capsules.find((c) => c.id === capsuleId);
129
+ if (!entry)
130
+ throw new Error(`Capsule not found in pack: ${capsuleId}`);
131
+ const fullPath = path.join(handle.rootDir, entry.path);
132
+ const raw = await fs.readFile(fullPath, "utf8");
133
+ await verifySha256(raw, entry.sha256, entry.path);
134
+ return yaml.load(raw);
135
+ }
136
+ export async function getInferencePrompt(handle, ref) {
137
+ const entry = handle.manifest.prompts.find((p) => p.path === ref);
138
+ if (!entry)
139
+ throw new Error(`Prompt not found in pack: ${ref}`);
140
+ const fullPath = path.join(handle.rootDir, ref);
141
+ const raw = await fs.readFile(fullPath, "utf8");
142
+ await verifySha256(raw, entry.sha256, ref);
143
+ return raw;
144
+ }
145
+ async function verifySha256(content, expected, label) {
146
+ const actual = crypto.createHash("sha256").update(content).digest("hex");
147
+ if (actual !== expected) {
148
+ throw new Error(`Pack integrity check failed for ${label}: expected ${expected.slice(0, 12)}…, got ${actual.slice(0, 12)}…`);
149
+ }
150
+ }
151
+ export async function listCapsuleIds(handle) {
152
+ return handle.manifest.capsules.map((c) => c.id);
153
+ }
154
+ export async function listControlIds(handle) {
155
+ return (handle.manifest.controls ?? []).map((c) => c.id);
156
+ }
157
+ export async function getControl(handle, controlId) {
158
+ const entry = (handle.manifest.controls ?? []).find((c) => c.id === controlId);
159
+ if (!entry)
160
+ throw new Error(`Control not found in pack: ${controlId}`);
161
+ const fullPath = path.join(handle.rootDir, entry.path);
162
+ const raw = await fs.readFile(fullPath, "utf8");
163
+ await verifySha256(raw, entry.sha256, entry.path);
164
+ return yaml.load(raw);
165
+ }
166
+ // ── Relevance evaluation ──
167
+ export async function findRelevantCapsules(handle, artifact) {
168
+ const out = [];
169
+ const ctx = buildEvalContext(artifact);
170
+ for (const entry of handle.manifest.capsules) {
171
+ const cap = await getCapsule(handle, entry.id);
172
+ if (matchesRelevance(cap, ctx))
173
+ out.push(cap);
174
+ }
175
+ return out;
176
+ }
177
+ function buildEvalContext(artifact) {
178
+ const packageNames = new Set();
179
+ for (const node of artifact.nodes) {
180
+ if (node.type === "external_dependency" && node.attributes?.package) {
181
+ packageNames.add(node.attributes.package);
182
+ }
183
+ }
184
+ const languages = new Set(artifact.scope.languages ?? []);
185
+ const evidenceKinds = new Set();
186
+ for (const node of artifact.nodes) {
187
+ for (const ev of node.evidence)
188
+ evidenceKinds.add(ev.kind);
189
+ }
190
+ return { packageNames, languages, evidenceKinds };
191
+ }
192
+ export function matchesRelevance(cap, ctx) {
193
+ if (cap.applicable_languages.length > 0) {
194
+ const hit = cap.applicable_languages.some((l) => l === "cross" || ctx.languages.has(l));
195
+ if (!hit)
196
+ return false;
197
+ }
198
+ const f = cap.relevance_filter;
199
+ if (!f)
200
+ return true;
201
+ if (f.any_of && f.any_of.length > 0) {
202
+ if (!f.any_of.some((t) => evalTerm(t, ctx)))
203
+ return false;
204
+ }
205
+ if (f.all_of && f.all_of.length > 0) {
206
+ if (!f.all_of.every((t) => evalTerm(t, ctx)))
207
+ return false;
208
+ }
209
+ if (f.none_of && f.none_of.length > 0) {
210
+ if (f.none_of.some((t) => evalTerm(t, ctx)))
211
+ return false;
212
+ }
213
+ return true;
214
+ }
215
+ function evalTerm(term, ctx) {
216
+ if (term.dependency !== undefined)
217
+ return ctx.packageNames.has(term.dependency);
218
+ if (term.language !== undefined)
219
+ return ctx.languages.has(term.language);
220
+ if (term.evidence !== undefined)
221
+ return ctx.evidenceKinds.has(term.evidence);
222
+ return false;
223
+ }
224
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pattern-pack/index.ts"],"names":[],"mappings":"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"}