preflight-dev 3.1.0 → 3.2.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/README.md +77 -16
- package/dist/cli/init.js +0 -48
- package/dist/cli/init.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/contracts.d.ts +27 -0
- package/dist/lib/contracts.js +309 -0
- package/dist/lib/contracts.js.map +1 -0
- package/dist/lib/patterns.d.ts +38 -0
- package/dist/lib/patterns.js +176 -0
- package/dist/lib/patterns.js.map +1 -0
- package/dist/lib/triage.d.ts +2 -0
- package/dist/lib/triage.js.map +1 -1
- package/dist/profiles.js +4 -0
- package/dist/profiles.js.map +1 -1
- package/dist/tools/check-patterns.d.ts +2 -0
- package/dist/tools/check-patterns.js +33 -0
- package/dist/tools/check-patterns.js.map +1 -0
- package/dist/tools/clarify-intent.js +9 -1
- package/dist/tools/clarify-intent.js.map +1 -1
- package/dist/tools/enrich-agent-task.js +132 -3
- package/dist/tools/enrich-agent-task.js.map +1 -1
- package/dist/tools/estimate-cost.d.ts +2 -0
- package/dist/tools/estimate-cost.js +261 -0
- package/dist/tools/estimate-cost.js.map +1 -0
- package/dist/tools/generate-scorecard.js +466 -14
- package/dist/tools/generate-scorecard.js.map +1 -1
- package/dist/tools/log-correction.js +7 -1
- package/dist/tools/log-correction.js.map +1 -1
- package/dist/tools/onboard-project.js +10 -1
- package/dist/tools/onboard-project.js.map +1 -1
- package/dist/tools/preflight-check.js +16 -0
- package/dist/tools/preflight-check.js.map +1 -1
- package/dist/tools/scope-work.js +6 -0
- package/dist/tools/scope-work.js.map +1 -1
- package/dist/tools/search-contracts.d.ts +2 -0
- package/dist/tools/search-contracts.js +46 -0
- package/dist/tools/search-contracts.js.map +1 -0
- package/dist/tools/session-stats.js +2 -0
- package/dist/tools/session-stats.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +7 -0
- package/src/lib/contracts.ts +354 -0
- package/src/lib/patterns.ts +210 -0
- package/src/lib/triage.ts +2 -0
- package/src/profiles.ts +4 -0
- package/src/tools/check-patterns.ts +43 -0
- package/src/tools/clarify-intent.ts +10 -1
- package/src/tools/enrich-agent-task.ts +150 -3
- package/src/tools/estimate-cost.ts +332 -0
- package/src/tools/generate-scorecard.ts +541 -14
- package/src/tools/log-correction.ts +8 -1
- package/src/tools/onboard-project.ts +10 -1
- package/src/tools/preflight-check.ts +19 -0
- package/src/tools/scope-work.ts +7 -0
- package/src/tools/search-contracts.ts +61 -0
- package/src/tools/session-stats.ts +2 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
**Preflight checks for your AI coding prompts.**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
A 24-tool MCP server for Claude Code that catches ambiguous instructions before they cost you 2-3x in wrong→fix cycles — plus semantic search across your entire session history.
|
|
8
8
|
|
|
9
9
|
[](https://www.typescriptlang.org/)
|
|
10
10
|
[](https://modelcontextprotocol.io/)
|
|
@@ -29,13 +29,15 @@ The pattern is always the same: vague prompt → Claude guesses → wrong output
|
|
|
29
29
|
|
|
30
30
|
## The Solution
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
24 tools in 4 categories that run as an MCP server inside Claude Code:
|
|
33
33
|
|
|
34
34
|
| Category | What it does |
|
|
35
35
|
|----------|-------------|
|
|
36
|
+
| ✈️ **Preflight Core** (1 tool) | Unified entry point — triages every prompt, chains the right checks automatically |
|
|
36
37
|
| 🎯 **Prompt Discipline** (12 tools) | Catches vague prompts, enforces structure, prevents waste |
|
|
37
38
|
| 🔍 **Timeline Intelligence** (4 tools) | LanceDB vector search across months of session history |
|
|
38
|
-
|
|
|
39
|
+
| 📊 **Analysis & Reporting** (4 tools) | Scorecards, cost estimation, session stats, pattern detection |
|
|
40
|
+
| ✅ **Verification & Hygiene** (3 tools) | Type-check, test, audit, and contract search |
|
|
39
41
|
|
|
40
42
|
## Before / After
|
|
41
43
|
|
|
@@ -56,20 +58,33 @@ The pattern is always the same: vague prompt → Claude guesses → wrong output
|
|
|
56
58
|
|
|
57
59
|
## Quick Start
|
|
58
60
|
|
|
61
|
+
### Option A: Claude Code CLI (fastest)
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
claude mcp add preflight -- npx tsx /path/to/preflight/src/index.ts
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Or with environment variables:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
claude mcp add preflight -e CLAUDE_PROJECT_DIR=/path/to/your/project -- npx tsx /path/to/preflight/src/index.ts
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Option B: Clone & configure manually
|
|
74
|
+
|
|
59
75
|
**1. Clone & install:**
|
|
60
76
|
```bash
|
|
61
77
|
git clone https://github.com/TerminalGravity/preflight.git
|
|
62
78
|
cd preflight && npm install
|
|
63
79
|
```
|
|
64
80
|
|
|
65
|
-
**2. Add to your
|
|
81
|
+
**2. Add to your project's `.mcp.json`:**
|
|
66
82
|
```json
|
|
67
83
|
{
|
|
68
84
|
"mcpServers": {
|
|
69
85
|
"preflight": {
|
|
70
86
|
"command": "npx",
|
|
71
87
|
"args": ["tsx", "/path/to/preflight/src/index.ts"],
|
|
72
|
-
"cwd": "/path/to/preflight",
|
|
73
88
|
"env": {
|
|
74
89
|
"CLAUDE_PROJECT_DIR": "/path/to/your/project"
|
|
75
90
|
}
|
|
@@ -78,23 +93,30 @@ cd preflight && npm install
|
|
|
78
93
|
}
|
|
79
94
|
```
|
|
80
95
|
|
|
81
|
-
**3. Restart Claude Code.**
|
|
96
|
+
**3. Restart Claude Code.** The tools activate automatically.
|
|
82
97
|
|
|
83
98
|
## Tool Reference
|
|
84
99
|
|
|
100
|
+
### ✈️ Preflight Core
|
|
101
|
+
|
|
102
|
+
| Tool | What it does |
|
|
103
|
+
|------|-------------|
|
|
104
|
+
| `preflight_check` | **The main entry point.** Triages your prompt (trivial → multi-step), then chains the right checks automatically. One tool to rule them all. |
|
|
105
|
+
|
|
85
106
|
### 🎯 Prompt Discipline
|
|
86
107
|
|
|
87
108
|
| Tool | What it does |
|
|
88
109
|
|------|-------------|
|
|
89
110
|
| `scope_work` | Creates structured execution plans before coding starts |
|
|
90
111
|
| `clarify_intent` | Gathers project context to disambiguate vague prompts |
|
|
91
|
-
| `enrich_agent_task` | Enriches sub-agent tasks with file paths and
|
|
112
|
+
| `enrich_agent_task` | Enriches sub-agent tasks with file paths, patterns, and cross-service context |
|
|
92
113
|
| `sharpen_followup` | Resolves "fix it" / "do the others" to actual file targets |
|
|
93
114
|
| `token_audit` | Detects waste patterns, grades your session A–F |
|
|
94
115
|
| `sequence_tasks` | Orders tasks by dependency, locality, and risk |
|
|
95
116
|
| `checkpoint` | Save game before compaction — commits + resumption notes |
|
|
96
117
|
| `check_session_health` | Monitors uncommitted files, time since commit, turn count |
|
|
97
118
|
| `log_correction` | Tracks corrections and identifies recurring error patterns |
|
|
119
|
+
| `check_patterns` | Checks prompts against learned correction patterns — warns about known pitfalls |
|
|
98
120
|
| `session_handoff` | Generates handoff briefs for new sessions |
|
|
99
121
|
| `what_changed` | Summarizes diffs since last checkpoint |
|
|
100
122
|
|
|
@@ -102,17 +124,27 @@ cd preflight && npm install
|
|
|
102
124
|
|
|
103
125
|
| Tool | What it does |
|
|
104
126
|
|------|-------------|
|
|
105
|
-
| `onboard_project` | Indexes a project's session history into LanceDB
|
|
106
|
-
| `search_history` | Semantic search
|
|
127
|
+
| `onboard_project` | Indexes a project's session history + contracts into per-project LanceDB |
|
|
128
|
+
| `search_history` | Semantic search with scope: current project, related, or all |
|
|
107
129
|
| `timeline` | Chronological view of events across sessions |
|
|
108
130
|
| `scan_sessions` | Live scanning of active session data |
|
|
109
131
|
|
|
132
|
+
### 📊 Analysis & Reporting
|
|
133
|
+
|
|
134
|
+
| Tool | What it does |
|
|
135
|
+
|------|-------------|
|
|
136
|
+
| `generate_scorecard` | 12-category report card — session, trend (week/month), or cross-project comparative. PDF or markdown. |
|
|
137
|
+
| `estimate_cost` | Token usage, dollar cost, waste from corrections, preflight savings |
|
|
138
|
+
| `session_stats` | Lightweight session analysis — no embeddings needed |
|
|
139
|
+
| `prompt_score` | Gamified A–F grading on specificity, scope, actionability, done-condition |
|
|
140
|
+
|
|
110
141
|
### ✅ Verification & Hygiene
|
|
111
142
|
|
|
112
143
|
| Tool | What it does |
|
|
113
144
|
|------|-------------|
|
|
114
145
|
| `verify_completion` | Runs type check + tests + build before declaring done |
|
|
115
146
|
| `audit_workspace` | Finds stale/missing workspace docs vs git activity |
|
|
147
|
+
| `search_contracts` | Search API contracts, types, and schemas across current and related projects |
|
|
116
148
|
|
|
117
149
|
## Timeline Intelligence
|
|
118
150
|
|
|
@@ -133,13 +165,13 @@ No data leaves your machine. Embeddings run locally by default (Xenova/transform
|
|
|
133
165
|
```
|
|
134
166
|
Claude Code ←→ MCP Protocol ←→ preflight server
|
|
135
167
|
│
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
168
|
+
┌───────────┬───────────┼───────────┬──────────┐
|
|
169
|
+
│ │ │ │ │
|
|
170
|
+
Preflight Discipline Timeline Analysis Verify
|
|
171
|
+
Core (1) Tools (12) Tools (4) Tools (4) (3)
|
|
172
|
+
│ │ │
|
|
173
|
+
Smart Triage Patterns LanceDB .preflight/
|
|
174
|
+
Classification Learning (per-project) (project config)
|
|
143
175
|
│
|
|
144
176
|
~/.claude/projects/
|
|
145
177
|
(session JSONL files)
|
|
@@ -147,6 +179,34 @@ Claude Code ←→ MCP Protocol ←→ preflight server
|
|
|
147
179
|
|
|
148
180
|
## Configuration
|
|
149
181
|
|
|
182
|
+
### Project Config (`.preflight/`)
|
|
183
|
+
|
|
184
|
+
Drop a `.preflight/` directory in your project root for team-shared config:
|
|
185
|
+
|
|
186
|
+
```yaml
|
|
187
|
+
# .preflight/config.yml
|
|
188
|
+
profile: standard
|
|
189
|
+
related_projects:
|
|
190
|
+
- path: /path/to/auth-service
|
|
191
|
+
alias: auth-service
|
|
192
|
+
- path: /path/to/notifications
|
|
193
|
+
alias: notifications
|
|
194
|
+
thresholds:
|
|
195
|
+
session_stale_minutes: 30
|
|
196
|
+
max_tool_calls_before_checkpoint: 100
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
```yaml
|
|
200
|
+
# .preflight/triage.yml
|
|
201
|
+
rules:
|
|
202
|
+
always_check: [rewards, permissions, migration]
|
|
203
|
+
skip: [commit, format, lint]
|
|
204
|
+
cross_service_keywords: [auth, notification, event]
|
|
205
|
+
strictness: standard
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
No config? No problem — everything works with zero configuration. Config just lets teams customize.
|
|
209
|
+
|
|
150
210
|
### Embedding Providers
|
|
151
211
|
|
|
152
212
|
| Provider | Setup | Speed | Quality |
|
|
@@ -160,6 +220,7 @@ Claude Code ←→ MCP Protocol ←→ preflight server
|
|
|
160
220
|
|----------|-------------|---------|
|
|
161
221
|
| `CLAUDE_PROJECT_DIR` | Project root to monitor | Required |
|
|
162
222
|
| `OPENAI_API_KEY` | OpenAI key for embeddings | (uses local Xenova) |
|
|
223
|
+
| `PREFLIGHT_RELATED` | Comma-separated related project paths | (none) |
|
|
163
224
|
|
|
164
225
|
## Contributing
|
|
165
226
|
|
package/dist/cli/init.js
CHANGED
|
@@ -95,54 +95,6 @@ async function main() {
|
|
|
95
95
|
env,
|
|
96
96
|
};
|
|
97
97
|
await writeFile(mcpPath, JSON.stringify(config, null, 2) + "\n");
|
|
98
|
-
// Offer to create .preflight/ config directory
|
|
99
|
-
const preflightDir = join(process.cwd(), ".preflight");
|
|
100
|
-
if (!existsSync(preflightDir)) {
|
|
101
|
-
const createConfig = await ask("\nCreate .preflight/ config directory with template files? [y/N]: ");
|
|
102
|
-
if (createConfig.trim().toLowerCase() === "y") {
|
|
103
|
-
await mkdir(preflightDir, { recursive: true });
|
|
104
|
-
const configYml = `# Preflight configuration
|
|
105
|
-
profile: ${profile}
|
|
106
|
-
|
|
107
|
-
related_projects: []
|
|
108
|
-
# - path: /path/to/related/project
|
|
109
|
-
# alias: project-name
|
|
110
|
-
|
|
111
|
-
thresholds:
|
|
112
|
-
session_stale_minutes: 30
|
|
113
|
-
max_tool_calls_before_checkpoint: 100
|
|
114
|
-
correction_pattern_threshold: 3
|
|
115
|
-
|
|
116
|
-
embeddings:
|
|
117
|
-
provider: local
|
|
118
|
-
`;
|
|
119
|
-
const triageYml = `# Triage rules for prompt classification
|
|
120
|
-
rules:
|
|
121
|
-
always_check:
|
|
122
|
-
- rewards
|
|
123
|
-
- permissions
|
|
124
|
-
- migration
|
|
125
|
-
- schema
|
|
126
|
-
skip:
|
|
127
|
-
- commit
|
|
128
|
-
- format
|
|
129
|
-
- lint
|
|
130
|
-
cross_service_keywords:
|
|
131
|
-
- auth
|
|
132
|
-
- notification
|
|
133
|
-
- event
|
|
134
|
-
- webhook
|
|
135
|
-
|
|
136
|
-
strictness: standard
|
|
137
|
-
`;
|
|
138
|
-
await writeFile(join(preflightDir, "config.yml"), configYml);
|
|
139
|
-
await writeFile(join(preflightDir, "triage.yml"), triageYml);
|
|
140
|
-
console.log("✅ Created .preflight/config.yml and .preflight/triage.yml");
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
console.log("\n.preflight/ directory already exists — skipping.");
|
|
145
|
-
}
|
|
146
98
|
console.log(`\n✅ preflight added! (profile: ${profile})`);
|
|
147
99
|
console.log("Restart Claude Code to connect.\n");
|
|
148
100
|
rl.close();
|
package/dist/cli/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -27,6 +27,8 @@ import { registerCheckpoint } from "./tools/checkpoint.js";
|
|
|
27
27
|
import { registerSessionHealth } from "./tools/session-health.js";
|
|
28
28
|
// Category 9: Error Recovery
|
|
29
29
|
import { registerLogCorrection } from "./tools/log-correction.js";
|
|
30
|
+
// Category 9b: Pattern Learning
|
|
31
|
+
import { registerCheckPatterns } from "./tools/check-patterns.js";
|
|
30
32
|
// Category 10: Workspace Hygiene
|
|
31
33
|
import { registerAuditWorkspace } from "./tools/audit-workspace.js";
|
|
32
34
|
// Category 11: Cross-Session Continuity
|
|
@@ -43,6 +45,8 @@ import { registerSearchHistory } from "./tools/search-history.js";
|
|
|
43
45
|
import { registerTimeline } from "./tools/timeline-view.js";
|
|
44
46
|
import { registerScanSessions } from "./tools/scan-sessions.js";
|
|
45
47
|
import { registerGenerateScorecard } from "./tools/generate-scorecard.js";
|
|
48
|
+
import { registerSearchContracts } from "./tools/search-contracts.js";
|
|
49
|
+
import { registerEstimateCost } from "./tools/estimate-cost.js";
|
|
46
50
|
// Validate related projects from config
|
|
47
51
|
function validateRelatedProjects() {
|
|
48
52
|
const config = getConfig();
|
|
@@ -81,6 +85,7 @@ const toolRegistry = [
|
|
|
81
85
|
["checkpoint", registerCheckpoint],
|
|
82
86
|
["check_session_health", registerSessionHealth],
|
|
83
87
|
["log_correction", registerLogCorrection],
|
|
88
|
+
["check_patterns", registerCheckPatterns],
|
|
84
89
|
["audit_workspace", registerAuditWorkspace],
|
|
85
90
|
["session_handoff", registerSessionHandoff],
|
|
86
91
|
["what_changed", registerWhatChanged],
|
|
@@ -92,6 +97,8 @@ const toolRegistry = [
|
|
|
92
97
|
["timeline_view", registerTimeline],
|
|
93
98
|
["scan_sessions", registerScanSessions],
|
|
94
99
|
["generate_scorecard", registerGenerateScorecard],
|
|
100
|
+
["estimate_cost", registerEstimateCost],
|
|
101
|
+
["search_contracts", registerSearchContracts],
|
|
95
102
|
];
|
|
96
103
|
let registered = 0;
|
|
97
104
|
for (const [name, register] of toolRegistry) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,gFAAgF;AAChF,kCAAkC;AAClC,gFAAgF;AAEhF,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAEhC,mBAAmB;AACnB,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,oBAAoB;AACpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,4BAA4B;AAC5B,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,yBAAyB;AACzB,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,oCAAoC;AACpC,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,+BAA+B;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,yBAAyB;AACzB,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,oCAAoC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,gCAAgC;AAChC,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,6BAA6B;AAC7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,iCAAiC;AACjC,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,wCAAwC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,4BAA4B;AAC5B,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,wBAAwB;AACxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,iCAAiC;AACjC,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface Contract {
|
|
2
|
+
name: string;
|
|
3
|
+
kind: "interface" | "type" | "enum" | "route" | "schema" | "event" | "model";
|
|
4
|
+
file: string;
|
|
5
|
+
definition: string;
|
|
6
|
+
project: string;
|
|
7
|
+
extractedAt: string;
|
|
8
|
+
}
|
|
9
|
+
/** Scan a project directory and extract all contracts */
|
|
10
|
+
export declare function extractContracts(projectDir: string): Contract[];
|
|
11
|
+
/** Load manual contract definitions from .preflight/contracts/ */
|
|
12
|
+
export declare function loadManualContracts(projectDir: string): Contract[];
|
|
13
|
+
/** Load stored contracts for a project */
|
|
14
|
+
export declare function loadContracts(projectHash: string): Contract[];
|
|
15
|
+
/** Save contracts to storage */
|
|
16
|
+
export declare function saveContracts(projectHash: string, contracts: Contract[]): void;
|
|
17
|
+
/** Search contracts by query string (simple relevance scoring) */
|
|
18
|
+
export declare function searchContracts(query: string, contracts: Contract[]): Contract[];
|
|
19
|
+
/** Extract and save contracts for a project, merging with manual definitions */
|
|
20
|
+
export declare function extractAndSaveContracts(projectDir: string): {
|
|
21
|
+
count: number;
|
|
22
|
+
hash: string;
|
|
23
|
+
};
|
|
24
|
+
/** Load all contracts for a list of project directories */
|
|
25
|
+
export declare function loadAllContracts(projectDirs: string[]): Contract[];
|
|
26
|
+
/** Format contracts for display in tool output */
|
|
27
|
+
export declare function formatContracts(contracts: Contract[], limit?: number): string;
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Cross-Service Contract Registry
|
|
3
|
+
// =============================================================================
|
|
4
|
+
// Extracts, stores, and searches API contracts, types, and schemas
|
|
5
|
+
// across projects for fast cross-service context lookups.
|
|
6
|
+
// =============================================================================
|
|
7
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, statSync } from "fs";
|
|
8
|
+
import { join, resolve, relative, basename, extname } from "path";
|
|
9
|
+
import { createHash } from "crypto";
|
|
10
|
+
import { homedir } from "os";
|
|
11
|
+
import { load as yamlLoad } from "js-yaml";
|
|
12
|
+
// --- Helpers ---
|
|
13
|
+
const PREFLIGHT_DIR = join(homedir(), ".preflight");
|
|
14
|
+
const PROJECTS_DIR = join(PREFLIGHT_DIR, "projects");
|
|
15
|
+
function hashProjectDir(projectDir) {
|
|
16
|
+
return createHash("sha256").update(resolve(projectDir)).digest("hex").slice(0, 12);
|
|
17
|
+
}
|
|
18
|
+
function contractsPath(projectHash) {
|
|
19
|
+
return join(PROJECTS_DIR, projectHash, "contracts.json");
|
|
20
|
+
}
|
|
21
|
+
// --- File Discovery ---
|
|
22
|
+
/** Recursively find files matching patterns, skipping node_modules/.git/dist */
|
|
23
|
+
function findFiles(dir, patterns, maxDepth = 8, depth = 0) {
|
|
24
|
+
if (depth > maxDepth)
|
|
25
|
+
return [];
|
|
26
|
+
const results = [];
|
|
27
|
+
let entries;
|
|
28
|
+
try {
|
|
29
|
+
entries = readdirSync(dir);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return results;
|
|
33
|
+
}
|
|
34
|
+
for (const entry of entries) {
|
|
35
|
+
if (entry === "node_modules" || entry === ".git" || entry === "dist" || entry === ".next" || entry === "build")
|
|
36
|
+
continue;
|
|
37
|
+
const full = join(dir, entry);
|
|
38
|
+
let st;
|
|
39
|
+
try {
|
|
40
|
+
st = statSync(full);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (st.isDirectory()) {
|
|
46
|
+
results.push(...findFiles(full, patterns, maxDepth, depth + 1));
|
|
47
|
+
}
|
|
48
|
+
else if (patterns.some(p => p.test(full))) {
|
|
49
|
+
results.push(full);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return results;
|
|
53
|
+
}
|
|
54
|
+
// --- Extraction ---
|
|
55
|
+
const TS_CONTRACT_PATTERNS = [
|
|
56
|
+
// types.ts, types/*.ts, interfaces.ts, *.d.ts
|
|
57
|
+
/\/types\.ts$/, /\/types\/[^/]+\.ts$/, /\/interfaces\.ts$/, /\.d\.ts$/,
|
|
58
|
+
// API routes
|
|
59
|
+
/\/api\/.*\.ts$/, /\/routes\/.*\.ts$/,
|
|
60
|
+
// Event schemas
|
|
61
|
+
/\/events\/.*\.ts$/, /\/schemas\/.*\.ts$/,
|
|
62
|
+
];
|
|
63
|
+
const PRISMA_PATTERN = /prisma\/schema\.prisma$/;
|
|
64
|
+
const OPENAPI_PATTERN = /\/(openapi\.ya?ml|swagger\.json)$/;
|
|
65
|
+
/** Extract TypeScript interfaces, types, and enums from source */
|
|
66
|
+
function extractTsContracts(content, filePath, projectDir) {
|
|
67
|
+
const contracts = [];
|
|
68
|
+
const relPath = relative(projectDir, filePath);
|
|
69
|
+
const now = new Date().toISOString();
|
|
70
|
+
// Match: export interface Foo { ... }
|
|
71
|
+
const interfaceRe = /export\s+interface\s+(\w+)(?:\s+extends\s+[^{]+)?\s*\{[^}]*(?:\{[^}]*\}[^}]*)*\}/g;
|
|
72
|
+
for (const m of content.matchAll(interfaceRe)) {
|
|
73
|
+
contracts.push({ name: m[1], kind: "interface", file: relPath, definition: m[0].slice(0, 500), project: projectDir, extractedAt: now });
|
|
74
|
+
}
|
|
75
|
+
// Match: export type Foo = ...
|
|
76
|
+
const typeRe = /export\s+type\s+(\w+)\s*(?:<[^>]*>)?\s*=[^;]+;/g;
|
|
77
|
+
for (const m of content.matchAll(typeRe)) {
|
|
78
|
+
contracts.push({ name: m[1], kind: "type", file: relPath, definition: m[0].slice(0, 500), project: projectDir, extractedAt: now });
|
|
79
|
+
}
|
|
80
|
+
// Match: export enum Foo { ... }
|
|
81
|
+
const enumRe = /export\s+enum\s+(\w+)\s*\{[^}]*\}/g;
|
|
82
|
+
for (const m of content.matchAll(enumRe)) {
|
|
83
|
+
contracts.push({ name: m[1], kind: "enum", file: relPath, definition: m[0].slice(0, 500), project: projectDir, extractedAt: now });
|
|
84
|
+
}
|
|
85
|
+
// Detect route definitions (Next.js/Express patterns)
|
|
86
|
+
const isRouteFile = /\/(api|routes)\//.test(filePath);
|
|
87
|
+
if (isRouteFile) {
|
|
88
|
+
// export async function GET/POST/PUT/DELETE/PATCH
|
|
89
|
+
const routeRe = /export\s+(?:async\s+)?function\s+(GET|POST|PUT|DELETE|PATCH|handler)\b[^{]*\{/g;
|
|
90
|
+
for (const m of content.matchAll(routeRe)) {
|
|
91
|
+
const routeName = `${m[1]} ${relPath.replace(/\.(ts|js)$/, "")}`;
|
|
92
|
+
const defStart = m.index;
|
|
93
|
+
contracts.push({ name: routeName, kind: "route", file: relPath, definition: content.slice(defStart, defStart + 500), project: projectDir, extractedAt: now });
|
|
94
|
+
}
|
|
95
|
+
// router.get/post/put/delete
|
|
96
|
+
const expressRe = /router\.(get|post|put|delete|patch)\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
97
|
+
for (const m of content.matchAll(expressRe)) {
|
|
98
|
+
contracts.push({ name: `${m[1].toUpperCase()} ${m[2]}`, kind: "route", file: relPath, definition: m[0].slice(0, 500), project: projectDir, extractedAt: now });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return contracts;
|
|
102
|
+
}
|
|
103
|
+
/** Extract Prisma models */
|
|
104
|
+
function extractPrismaContracts(content, filePath, projectDir) {
|
|
105
|
+
const contracts = [];
|
|
106
|
+
const relPath = relative(projectDir, filePath);
|
|
107
|
+
const now = new Date().toISOString();
|
|
108
|
+
const modelRe = /model\s+(\w+)\s*\{[^}]*\}/g;
|
|
109
|
+
for (const m of content.matchAll(modelRe)) {
|
|
110
|
+
contracts.push({ name: m[1], kind: "model", file: relPath, definition: m[0].slice(0, 500), project: projectDir, extractedAt: now });
|
|
111
|
+
}
|
|
112
|
+
const enumRe = /enum\s+(\w+)\s*\{[^}]*\}/g;
|
|
113
|
+
for (const m of content.matchAll(enumRe)) {
|
|
114
|
+
contracts.push({ name: m[1], kind: "enum", file: relPath, definition: m[0].slice(0, 500), project: projectDir, extractedAt: now });
|
|
115
|
+
}
|
|
116
|
+
return contracts;
|
|
117
|
+
}
|
|
118
|
+
/** Extract from OpenAPI/Swagger specs */
|
|
119
|
+
function extractOpenApiContracts(content, filePath, projectDir) {
|
|
120
|
+
const contracts = [];
|
|
121
|
+
const relPath = relative(projectDir, filePath);
|
|
122
|
+
const now = new Date().toISOString();
|
|
123
|
+
try {
|
|
124
|
+
const spec = filePath.endsWith(".json") ? JSON.parse(content) : yamlLoad(content);
|
|
125
|
+
if (spec?.paths) {
|
|
126
|
+
for (const [path, methods] of Object.entries(spec.paths)) {
|
|
127
|
+
for (const method of Object.keys(methods)) {
|
|
128
|
+
if (["get", "post", "put", "delete", "patch"].includes(method)) {
|
|
129
|
+
const op = methods[method];
|
|
130
|
+
const name = `${method.toUpperCase()} ${path}`;
|
|
131
|
+
const def = JSON.stringify({ summary: op.summary, parameters: op.parameters, requestBody: op.requestBody }, null, 2);
|
|
132
|
+
contracts.push({ name, kind: "route", file: relPath, definition: def.slice(0, 500), project: projectDir, extractedAt: now });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (spec?.components?.schemas) {
|
|
138
|
+
for (const [name, schema] of Object.entries(spec.components.schemas)) {
|
|
139
|
+
contracts.push({ name, kind: "schema", file: relPath, definition: JSON.stringify(schema, null, 2).slice(0, 500), project: projectDir, extractedAt: now });
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
// Invalid spec, skip
|
|
145
|
+
}
|
|
146
|
+
return contracts;
|
|
147
|
+
}
|
|
148
|
+
// --- Public API ---
|
|
149
|
+
/** Scan a project directory and extract all contracts */
|
|
150
|
+
export function extractContracts(projectDir) {
|
|
151
|
+
const absDir = resolve(projectDir);
|
|
152
|
+
const contracts = [];
|
|
153
|
+
// TypeScript files
|
|
154
|
+
const tsFiles = findFiles(absDir, TS_CONTRACT_PATTERNS);
|
|
155
|
+
for (const file of tsFiles) {
|
|
156
|
+
try {
|
|
157
|
+
const content = readFileSync(file, "utf-8");
|
|
158
|
+
contracts.push(...extractTsContracts(content, file, absDir));
|
|
159
|
+
}
|
|
160
|
+
catch { /* skip unreadable */ }
|
|
161
|
+
}
|
|
162
|
+
// Prisma
|
|
163
|
+
const prismaFiles = findFiles(absDir, [PRISMA_PATTERN], 3);
|
|
164
|
+
for (const file of prismaFiles) {
|
|
165
|
+
try {
|
|
166
|
+
const content = readFileSync(file, "utf-8");
|
|
167
|
+
contracts.push(...extractPrismaContracts(content, file, absDir));
|
|
168
|
+
}
|
|
169
|
+
catch { /* skip */ }
|
|
170
|
+
}
|
|
171
|
+
// OpenAPI
|
|
172
|
+
const openApiFiles = findFiles(absDir, [OPENAPI_PATTERN], 5);
|
|
173
|
+
for (const file of openApiFiles) {
|
|
174
|
+
try {
|
|
175
|
+
const content = readFileSync(file, "utf-8");
|
|
176
|
+
contracts.push(...extractOpenApiContracts(content, file, absDir));
|
|
177
|
+
}
|
|
178
|
+
catch { /* skip */ }
|
|
179
|
+
}
|
|
180
|
+
return contracts;
|
|
181
|
+
}
|
|
182
|
+
/** Load manual contract definitions from .preflight/contracts/ */
|
|
183
|
+
export function loadManualContracts(projectDir) {
|
|
184
|
+
const contractsDir = join(projectDir, ".preflight", "contracts");
|
|
185
|
+
if (!existsSync(contractsDir))
|
|
186
|
+
return [];
|
|
187
|
+
const contracts = [];
|
|
188
|
+
const now = new Date().toISOString();
|
|
189
|
+
let entries;
|
|
190
|
+
try {
|
|
191
|
+
entries = readdirSync(contractsDir);
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
return [];
|
|
195
|
+
}
|
|
196
|
+
for (const entry of entries) {
|
|
197
|
+
if (![".yml", ".yaml"].includes(extname(entry)))
|
|
198
|
+
continue;
|
|
199
|
+
const filePath = join(contractsDir, entry);
|
|
200
|
+
try {
|
|
201
|
+
const content = readFileSync(filePath, "utf-8");
|
|
202
|
+
const items = yamlLoad(content);
|
|
203
|
+
if (!Array.isArray(items))
|
|
204
|
+
continue;
|
|
205
|
+
for (const item of items) {
|
|
206
|
+
if (!item.name || !item.kind)
|
|
207
|
+
continue;
|
|
208
|
+
const def = item.fields
|
|
209
|
+
? `${item.description || ""}\nFields: ${item.fields.map(f => `${f.name}: ${f.type}${f.required ? " (required)" : ""}`).join(", ")}`
|
|
210
|
+
: item.description || "";
|
|
211
|
+
contracts.push({
|
|
212
|
+
name: item.name,
|
|
213
|
+
kind: item.kind,
|
|
214
|
+
file: `.preflight/contracts/${entry}`,
|
|
215
|
+
definition: def.trim().slice(0, 500),
|
|
216
|
+
project: resolve(projectDir),
|
|
217
|
+
extractedAt: now,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch { /* skip invalid */ }
|
|
222
|
+
}
|
|
223
|
+
return contracts;
|
|
224
|
+
}
|
|
225
|
+
/** Load stored contracts for a project */
|
|
226
|
+
export function loadContracts(projectHash) {
|
|
227
|
+
const p = contractsPath(projectHash);
|
|
228
|
+
if (!existsSync(p))
|
|
229
|
+
return [];
|
|
230
|
+
try {
|
|
231
|
+
return JSON.parse(readFileSync(p, "utf-8"));
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
return [];
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/** Save contracts to storage */
|
|
238
|
+
export function saveContracts(projectHash, contracts) {
|
|
239
|
+
const dir = join(PROJECTS_DIR, projectHash);
|
|
240
|
+
mkdirSync(dir, { recursive: true });
|
|
241
|
+
writeFileSync(contractsPath(projectHash), JSON.stringify(contracts, null, 2));
|
|
242
|
+
}
|
|
243
|
+
/** Search contracts by query string (simple relevance scoring) */
|
|
244
|
+
export function searchContracts(query, contracts) {
|
|
245
|
+
const terms = query.toLowerCase().split(/\s+/).filter(t => t.length > 1);
|
|
246
|
+
if (terms.length === 0)
|
|
247
|
+
return contracts;
|
|
248
|
+
const scored = contracts.map(c => {
|
|
249
|
+
const nameL = c.name.toLowerCase();
|
|
250
|
+
const defL = c.definition.toLowerCase();
|
|
251
|
+
const fileL = c.file.toLowerCase();
|
|
252
|
+
let score = 0;
|
|
253
|
+
for (const term of terms) {
|
|
254
|
+
// Exact name match is highest
|
|
255
|
+
if (nameL === term)
|
|
256
|
+
score += 10;
|
|
257
|
+
// Name contains term
|
|
258
|
+
else if (nameL.includes(term))
|
|
259
|
+
score += 5;
|
|
260
|
+
// File contains term
|
|
261
|
+
if (fileL.includes(term))
|
|
262
|
+
score += 2;
|
|
263
|
+
// Definition contains term
|
|
264
|
+
if (defL.includes(term))
|
|
265
|
+
score += 1;
|
|
266
|
+
}
|
|
267
|
+
return { contract: c, score };
|
|
268
|
+
});
|
|
269
|
+
return scored
|
|
270
|
+
.filter(s => s.score > 0)
|
|
271
|
+
.sort((a, b) => b.score - a.score)
|
|
272
|
+
.map(s => s.contract);
|
|
273
|
+
}
|
|
274
|
+
/** Extract and save contracts for a project, merging with manual definitions */
|
|
275
|
+
export function extractAndSaveContracts(projectDir) {
|
|
276
|
+
const absDir = resolve(projectDir);
|
|
277
|
+
const hash = hashProjectDir(absDir);
|
|
278
|
+
const autoContracts = extractContracts(absDir);
|
|
279
|
+
const manualContracts = loadManualContracts(absDir);
|
|
280
|
+
// Manual contracts take precedence (same name = manual wins)
|
|
281
|
+
const manualNames = new Set(manualContracts.map(c => c.name));
|
|
282
|
+
const merged = [
|
|
283
|
+
...manualContracts,
|
|
284
|
+
...autoContracts.filter(c => !manualNames.has(c.name)),
|
|
285
|
+
];
|
|
286
|
+
saveContracts(hash, merged);
|
|
287
|
+
return { count: merged.length, hash };
|
|
288
|
+
}
|
|
289
|
+
/** Load all contracts for a list of project directories */
|
|
290
|
+
export function loadAllContracts(projectDirs) {
|
|
291
|
+
const all = [];
|
|
292
|
+
for (const dir of projectDirs) {
|
|
293
|
+
const hash = hashProjectDir(resolve(dir));
|
|
294
|
+
all.push(...loadContracts(hash));
|
|
295
|
+
}
|
|
296
|
+
return all;
|
|
297
|
+
}
|
|
298
|
+
/** Format contracts for display in tool output */
|
|
299
|
+
export function formatContracts(contracts, limit = 10) {
|
|
300
|
+
if (contracts.length === 0)
|
|
301
|
+
return "";
|
|
302
|
+
const lines = contracts.slice(0, limit).map(c => {
|
|
303
|
+
const proj = basename(c.project);
|
|
304
|
+
const defPreview = c.definition.split("\n")[0].slice(0, 120);
|
|
305
|
+
return `From ${proj}: ${c.kind} ${c.name} — ${defPreview} (${c.file})`;
|
|
306
|
+
});
|
|
307
|
+
return lines.join("\n");
|
|
308
|
+
}
|
|
309
|
+
//# sourceMappingURL=contracts.js.map
|