@maintainabilityai/research-runner 0.1.1

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 (102) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +82 -0
  3. package/bin/research-runner.js +2 -0
  4. package/dist/cli.d.ts +1 -0
  5. package/dist/cli.js +209 -0
  6. package/dist/llm/anthropic-client.d.ts +39 -0
  7. package/dist/llm/anthropic-client.js +74 -0
  8. package/dist/llm/github-models-client.d.ts +46 -0
  9. package/dist/llm/github-models-client.js +78 -0
  10. package/dist/llm/llm-router.d.ts +46 -0
  11. package/dist/llm/llm-router.js +60 -0
  12. package/dist/mesh/get-mesh-sha.d.ts +1 -0
  13. package/dist/mesh/get-mesh-sha.js +27 -0
  14. package/dist/mesh/mesh-reader.d.ts +14 -0
  15. package/dist/mesh/mesh-reader.js +392 -0
  16. package/dist/mesh/prompt-loader.d.ts +22 -0
  17. package/dist/mesh/prompt-loader.js +119 -0
  18. package/dist/mesh/threat-model-reader.d.ts +33 -0
  19. package/dist/mesh/threat-model-reader.js +123 -0
  20. package/dist/runner/archeologist.d.ts +39 -0
  21. package/dist/runner/archeologist.js +620 -0
  22. package/dist/runner/audit-emitter.d.ts +62 -0
  23. package/dist/runner/audit-emitter.js +210 -0
  24. package/dist/runner/hatters-tag-builder.d.ts +52 -0
  25. package/dist/runner/hatters-tag-builder.js +40 -0
  26. package/dist/runner/nodes/analyze-architecture.d.ts +10 -0
  27. package/dist/runner/nodes/analyze-architecture.js +447 -0
  28. package/dist/runner/nodes/arxiv-search.d.ts +12 -0
  29. package/dist/runner/nodes/arxiv-search.js +52 -0
  30. package/dist/runner/nodes/clone-and-index.d.ts +32 -0
  31. package/dist/runner/nodes/clone-and-index.js +158 -0
  32. package/dist/runner/nodes/dedupe-and-rank.d.ts +27 -0
  33. package/dist/runner/nodes/dedupe-and-rank.js +98 -0
  34. package/dist/runner/nodes/deterministic-review.d.ts +55 -0
  35. package/dist/runner/nodes/deterministic-review.js +206 -0
  36. package/dist/runner/nodes/expert-review.d.ts +68 -0
  37. package/dist/runner/nodes/expert-review.js +197 -0
  38. package/dist/runner/nodes/gap-analysis.d.ts +48 -0
  39. package/dist/runner/nodes/gap-analysis.js +153 -0
  40. package/dist/runner/nodes/generate-prd-manifest.d.ts +53 -0
  41. package/dist/runner/nodes/generate-prd-manifest.js +209 -0
  42. package/dist/runner/nodes/hackernews-search.d.ts +12 -0
  43. package/dist/runner/nodes/hackernews-search.js +63 -0
  44. package/dist/runner/nodes/identify-gaps.d.ts +33 -0
  45. package/dist/runner/nodes/identify-gaps.js +185 -0
  46. package/dist/runner/nodes/plan-queries.d.ts +28 -0
  47. package/dist/runner/nodes/plan-queries.js +120 -0
  48. package/dist/runner/nodes/prd-validator.d.ts +51 -0
  49. package/dist/runner/nodes/prd-validator.js +203 -0
  50. package/dist/runner/nodes/synthesis-archaeology-validator.d.ts +22 -0
  51. package/dist/runner/nodes/synthesis-archaeology-validator.js +131 -0
  52. package/dist/runner/nodes/synthesis-validator.d.ts +51 -0
  53. package/dist/runner/nodes/synthesis-validator.js +185 -0
  54. package/dist/runner/nodes/synthesize-prd.d.ts +84 -0
  55. package/dist/runner/nodes/synthesize-prd.js +202 -0
  56. package/dist/runner/nodes/synthesize-report.d.ts +53 -0
  57. package/dist/runner/nodes/synthesize-report.js +188 -0
  58. package/dist/runner/nodes/tavily-search.d.ts +21 -0
  59. package/dist/runner/nodes/tavily-search.js +57 -0
  60. package/dist/runner/nodes/uspto-search.d.ts +13 -0
  61. package/dist/runner/nodes/uspto-search.js +62 -0
  62. package/dist/runner/nodes/verify-grounding.d.ts +54 -0
  63. package/dist/runner/nodes/verify-grounding.js +134 -0
  64. package/dist/runner/prd.d.ts +28 -0
  65. package/dist/runner/prd.js +494 -0
  66. package/dist/schemas/audit-event.d.ts +1151 -0
  67. package/dist/schemas/audit-event.js +141 -0
  68. package/dist/schemas/index.d.ts +17 -0
  69. package/dist/schemas/index.js +33 -0
  70. package/dist/schemas/mesh-context.d.ts +415 -0
  71. package/dist/schemas/mesh-context.js +95 -0
  72. package/dist/schemas/observed-architecture.d.ts +262 -0
  73. package/dist/schemas/observed-architecture.js +90 -0
  74. package/dist/schemas/prd-brief.d.ts +111 -0
  75. package/dist/schemas/prd-brief.js +37 -0
  76. package/dist/schemas/prd-doc.d.ts +249 -0
  77. package/dist/schemas/prd-doc.js +42 -0
  78. package/dist/schemas/prd-manifest.d.ts +171 -0
  79. package/dist/schemas/prd-manifest.js +73 -0
  80. package/dist/schemas/primitives.d.ts +47 -0
  81. package/dist/schemas/primitives.js +41 -0
  82. package/dist/schemas/query-plan.d.ts +33 -0
  83. package/dist/schemas/query-plan.js +25 -0
  84. package/dist/schemas/ranked-source.d.ts +82 -0
  85. package/dist/schemas/ranked-source.js +29 -0
  86. package/dist/schemas/research-brief.d.ts +114 -0
  87. package/dist/schemas/research-brief.js +49 -0
  88. package/dist/schemas/research-doc.d.ts +104 -0
  89. package/dist/schemas/research-doc.js +37 -0
  90. package/dist/search/arxiv-client.d.ts +41 -0
  91. package/dist/search/arxiv-client.js +88 -0
  92. package/dist/search/hackernews-client.d.ts +33 -0
  93. package/dist/search/hackernews-client.js +44 -0
  94. package/dist/search/provider-result.d.ts +25 -0
  95. package/dist/search/provider-result.js +2 -0
  96. package/dist/search/tavily-client.d.ts +38 -0
  97. package/dist/search/tavily-client.js +53 -0
  98. package/dist/search/uspto-client.d.ts +50 -0
  99. package/dist/search/uspto-client.js +112 -0
  100. package/dist/utils/run-id.d.ts +2 -0
  101. package/dist/utils/run-id.js +22 -0
  102. package/package.json +53 -0
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.parseThreatModelYaml = parseThreatModelYaml;
37
+ exports.summarizeThreatModel = summarizeThreatModel;
38
+ exports.readThreatModelFromBar = readThreatModelFromBar;
39
+ /**
40
+ * threat-model-reader — parse `<bar>/security/threat-model.yaml` into structured
41
+ * STRIDE entries the LLM nodes can ground against.
42
+ *
43
+ * Uses js-yaml directly (the file is valid YAML — we don't need the
44
+ * line-by-line parser that the vscode-extension uses for its writer-specific
45
+ * format). We DO normalise the field names to camelCase to match the shape
46
+ * the LLM prompts expect.
47
+ */
48
+ const fs = __importStar(require("node:fs"));
49
+ const path = __importStar(require("node:path"));
50
+ const yaml = __importStar(require("js-yaml"));
51
+ /** Snake-case YAML keys → camelCase TS fields. Missing fields get safe defaults. */
52
+ function normalizeThreat(raw, fallbackIndex) {
53
+ if (!raw || typeof raw !== 'object') {
54
+ return null;
55
+ }
56
+ const r = raw;
57
+ return {
58
+ id: typeof r.id === 'string' ? r.id : `THR-${String(fallbackIndex + 1).padStart(3, '0')}`,
59
+ category: r.category || 'spoofing',
60
+ target: typeof r.target === 'string' ? r.target : '',
61
+ targetName: typeof r.target_name === 'string' ? r.target_name : '',
62
+ dataClassification: typeof r.data_classification === 'string' ? r.data_classification : '',
63
+ description: typeof r.description === 'string' ? r.description : '',
64
+ attackVector: typeof r.attack_vector === 'string' ? r.attack_vector : '',
65
+ impact: r.impact || 'medium',
66
+ likelihood: r.likelihood || 'medium',
67
+ existingControls: Array.isArray(r.existing_controls) ? r.existing_controls.filter(s => typeof s === 'string') : [],
68
+ controlEffectiveness: r.control_effectiveness || 'none',
69
+ residualRisk: r.residual_risk || 'medium',
70
+ recommendedMitigations: Array.isArray(r.recommended_mitigations) ? r.recommended_mitigations.filter(s => typeof s === 'string') : [],
71
+ nistReferences: Array.isArray(r.nist_references) ? r.nist_references.filter(s => typeof s === 'string') : [],
72
+ };
73
+ }
74
+ function parseThreatModelYaml(content) {
75
+ let doc;
76
+ try {
77
+ doc = yaml.load(content);
78
+ }
79
+ catch {
80
+ return [];
81
+ }
82
+ if (!doc || typeof doc !== 'object') {
83
+ return [];
84
+ }
85
+ const threatsRaw = doc.threats;
86
+ if (!Array.isArray(threatsRaw)) {
87
+ return [];
88
+ }
89
+ return threatsRaw
90
+ .map((t, i) => normalizeThreat(t, i))
91
+ .filter((t) => t !== null);
92
+ }
93
+ function summarizeThreatModel(threats) {
94
+ const byCategory = {};
95
+ const byRisk = {};
96
+ let unmitigatedCount = 0;
97
+ for (const t of threats) {
98
+ byCategory[t.category] = (byCategory[t.category] || 0) + 1;
99
+ byRisk[t.residualRisk] = (byRisk[t.residualRisk] || 0) + 1;
100
+ if (t.controlEffectiveness === 'none') {
101
+ unmitigatedCount++;
102
+ }
103
+ }
104
+ return { byCategory, byRisk, unmitigatedCount };
105
+ }
106
+ function readThreatModelFromBar(barPath) {
107
+ const yamlPath = path.join(barPath, 'security', 'threat-model.yaml');
108
+ if (!fs.existsSync(yamlPath)) {
109
+ return null;
110
+ }
111
+ let content;
112
+ try {
113
+ content = fs.readFileSync(yamlPath, 'utf8');
114
+ }
115
+ catch {
116
+ return null;
117
+ }
118
+ const threats = parseThreatModelYaml(content);
119
+ if (threats.length === 0) {
120
+ return null;
121
+ }
122
+ return { threats, summary: summarizeThreatModel(threats) };
123
+ }
@@ -0,0 +1,39 @@
1
+ export interface ArcheologistOptions {
2
+ brief: unknown;
3
+ meshDir: string;
4
+ outputDir: string;
5
+ auditDir: string;
6
+ emitPrBodyPath?: string;
7
+ agentVersion: string;
8
+ /** Provider keys — supply only the one your brief.llm_provider needs. Default from process.env. */
9
+ anthropicApiKey?: string;
10
+ /** GITHUB_TOKEN — used when brief.llm_provider === 'github-models'. */
11
+ githubToken?: string;
12
+ tavilyApiKey?: string;
13
+ /** Optional — when absent, uspto_search emits a node_error envelope and the run continues without patent coverage. */
14
+ usptoApiKey?: string;
15
+ /** Test injection point. */
16
+ fetchImpl?: typeof fetch;
17
+ }
18
+ export interface ArcheologistResult {
19
+ run_id: string;
20
+ topic: string;
21
+ artifact_path: string;
22
+ audit_log_path: string;
23
+ chain_root_hash: string;
24
+ pr_body_path: string | null;
25
+ total_input_tokens: number;
26
+ total_output_tokens: number;
27
+ total_cost_usd: number;
28
+ source_count: number;
29
+ /** Per-provider counts of raw results (post-dedupe deltas — useful for reviewer summary). */
30
+ provider_result_counts: Record<string, number>;
31
+ /** Whether gap_analysis fired this run. Research path only. */
32
+ gap_analysis_ran: boolean;
33
+ /** Number of archaeology gaps identified. Undefined on research-path runs. */
34
+ archaeology_gap_count?: number;
35
+ /** Synthesis structural validator outputs — quick reviewer signal. */
36
+ conclusion_count: number;
37
+ recommendation_count: number;
38
+ }
39
+ export declare function runArcheologist(opts: ArcheologistOptions): Promise<ArcheologistResult>;