preflight-dev 3.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.
- package/LICENSE +21 -0
- package/README.md +172 -0
- package/bin/cli.js +11 -0
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.js +154 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +122 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config.d.ts +34 -0
- package/dist/lib/config.js +118 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/embeddings.d.ts +11 -0
- package/dist/lib/embeddings.js +88 -0
- package/dist/lib/embeddings.js.map +1 -0
- package/dist/lib/files.d.ts +15 -0
- package/dist/lib/files.js +60 -0
- package/dist/lib/files.js.map +1 -0
- package/dist/lib/git-extractor.d.ts +9 -0
- package/dist/lib/git-extractor.js +116 -0
- package/dist/lib/git-extractor.js.map +1 -0
- package/dist/lib/git.d.ts +29 -0
- package/dist/lib/git.js +86 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/session-parser.d.ts +45 -0
- package/dist/lib/session-parser.js +267 -0
- package/dist/lib/session-parser.js.map +1 -0
- package/dist/lib/state.d.ts +21 -0
- package/dist/lib/state.js +86 -0
- package/dist/lib/state.js.map +1 -0
- package/dist/lib/timeline-db.d.ts +67 -0
- package/dist/lib/timeline-db.js +380 -0
- package/dist/lib/timeline-db.js.map +1 -0
- package/dist/lib/triage.d.ts +29 -0
- package/dist/lib/triage.js +193 -0
- package/dist/lib/triage.js.map +1 -0
- package/dist/profiles.d.ts +3 -0
- package/dist/profiles.js +65 -0
- package/dist/profiles.js.map +1 -0
- package/dist/tools/audit-workspace.d.ts +2 -0
- package/dist/tools/audit-workspace.js +86 -0
- package/dist/tools/audit-workspace.js.map +1 -0
- package/dist/tools/checkpoint.d.ts +2 -0
- package/dist/tools/checkpoint.js +108 -0
- package/dist/tools/checkpoint.js.map +1 -0
- package/dist/tools/clarify-intent.d.ts +2 -0
- package/dist/tools/clarify-intent.js +180 -0
- package/dist/tools/clarify-intent.js.map +1 -0
- package/dist/tools/enrich-agent-task.d.ts +2 -0
- package/dist/tools/enrich-agent-task.js +97 -0
- package/dist/tools/enrich-agent-task.js.map +1 -0
- package/dist/tools/generate-scorecard.d.ts +2 -0
- package/dist/tools/generate-scorecard.js +617 -0
- package/dist/tools/generate-scorecard.js.map +1 -0
- package/dist/tools/log-correction.d.ts +2 -0
- package/dist/tools/log-correction.js +76 -0
- package/dist/tools/log-correction.js.map +1 -0
- package/dist/tools/onboard-project.d.ts +2 -0
- package/dist/tools/onboard-project.js +179 -0
- package/dist/tools/onboard-project.js.map +1 -0
- package/dist/tools/preflight-check.d.ts +2 -0
- package/dist/tools/preflight-check.js +229 -0
- package/dist/tools/preflight-check.js.map +1 -0
- package/dist/tools/prompt-score.d.ts +2 -0
- package/dist/tools/prompt-score.js +132 -0
- package/dist/tools/prompt-score.js.map +1 -0
- package/dist/tools/scan-sessions.d.ts +2 -0
- package/dist/tools/scan-sessions.js +182 -0
- package/dist/tools/scan-sessions.js.map +1 -0
- package/dist/tools/scope-work.d.ts +2 -0
- package/dist/tools/scope-work.js +214 -0
- package/dist/tools/scope-work.js.map +1 -0
- package/dist/tools/search-history.d.ts +2 -0
- package/dist/tools/search-history.js +130 -0
- package/dist/tools/search-history.js.map +1 -0
- package/dist/tools/sequence-tasks.d.ts +2 -0
- package/dist/tools/sequence-tasks.js +165 -0
- package/dist/tools/sequence-tasks.js.map +1 -0
- package/dist/tools/session-handoff.d.ts +2 -0
- package/dist/tools/session-handoff.js +113 -0
- package/dist/tools/session-handoff.js.map +1 -0
- package/dist/tools/session-health.d.ts +2 -0
- package/dist/tools/session-health.js +111 -0
- package/dist/tools/session-health.js.map +1 -0
- package/dist/tools/session-stats.d.ts +2 -0
- package/dist/tools/session-stats.js +112 -0
- package/dist/tools/session-stats.js.map +1 -0
- package/dist/tools/sharpen-followup.d.ts +2 -0
- package/dist/tools/sharpen-followup.js +192 -0
- package/dist/tools/sharpen-followup.js.map +1 -0
- package/dist/tools/timeline-view.d.ts +2 -0
- package/dist/tools/timeline-view.js +165 -0
- package/dist/tools/timeline-view.js.map +1 -0
- package/dist/tools/token-audit.d.ts +2 -0
- package/dist/tools/token-audit.js +227 -0
- package/dist/tools/token-audit.js.map +1 -0
- package/dist/tools/verify-completion.d.ts +2 -0
- package/dist/tools/verify-completion.js +154 -0
- package/dist/tools/verify-completion.js.map +1 -0
- package/dist/tools/what-changed.d.ts +2 -0
- package/dist/tools/what-changed.js +40 -0
- package/dist/tools/what-changed.js.map +1 -0
- package/dist/types.d.ts +78 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +52 -0
- package/src/cli/init.ts +133 -0
- package/src/index.ts +135 -0
- package/src/lib/config.ts +157 -0
- package/src/lib/embeddings.ts +118 -0
- package/src/lib/files.ts +59 -0
- package/src/lib/git-extractor.ts +137 -0
- package/src/lib/git.ts +89 -0
- package/src/lib/session-parser.ts +325 -0
- package/src/lib/state.ts +86 -0
- package/src/lib/timeline-db.ts +490 -0
- package/src/lib/triage.ts +255 -0
- package/src/profiles.ts +70 -0
- package/src/templates/config.yml +23 -0
- package/src/templates/triage.yml +27 -0
- package/src/tools/audit-workspace.ts +97 -0
- package/src/tools/checkpoint.ts +119 -0
- package/src/tools/clarify-intent.ts +191 -0
- package/src/tools/enrich-agent-task.ts +108 -0
- package/src/tools/generate-scorecard.ts +673 -0
- package/src/tools/log-correction.ts +89 -0
- package/src/tools/onboard-project.ts +214 -0
- package/src/tools/preflight-check.ts +263 -0
- package/src/tools/prompt-score.ts +150 -0
- package/src/tools/scan-sessions.ts +209 -0
- package/src/tools/scope-work.ts +238 -0
- package/src/tools/search-history.ts +145 -0
- package/src/tools/sequence-tasks.ts +182 -0
- package/src/tools/session-handoff.ts +125 -0
- package/src/tools/session-health.ts +107 -0
- package/src/tools/session-stats.ts +134 -0
- package/src/tools/sharpen-followup.ts +200 -0
- package/src/tools/timeline-view.ts +181 -0
- package/src/tools/token-audit.ts +259 -0
- package/src/tools/verify-completion.ts +159 -0
- package/src/tools/what-changed.ts +48 -0
- package/src/types.ts +87 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jack Felke
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# ✈️ preflight
|
|
4
|
+
|
|
5
|
+
**Preflight checks for your AI coding prompts.**
|
|
6
|
+
|
|
7
|
+
An 18-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
|
+
|
|
9
|
+
[](https://www.typescriptlang.org/)
|
|
10
|
+
[](https://modelcontextprotocol.io/)
|
|
11
|
+
[](LICENSE)
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## The Problem
|
|
18
|
+
|
|
19
|
+
We built this after analyzing **9 months of real Claude Code usage** — 512 sessions, 32,000+ events, 3,200+ prompts, 1,642 commits, and 258 sub-agent spawns across a production Next.js/Prisma/Supabase app. The findings were brutal:
|
|
20
|
+
|
|
21
|
+
- **41% of prompts were under 50 characters** — things like `fix the tests`, `commit this`, `remove them`
|
|
22
|
+
- Each vague prompt triggers a **wrong→fix cycle costing 2-3x tokens**
|
|
23
|
+
- **~33K characters/day** duplicated from repeated context pastes
|
|
24
|
+
- **124 corrections logged** — places where Claude went the wrong direction and had to be steered back
|
|
25
|
+
- **94 context compactions** from unbounded session scope blowing past the context window
|
|
26
|
+
- Estimated **30-40% of tokens wasted** on avoidable back-and-forth
|
|
27
|
+
|
|
28
|
+
The pattern is always the same: vague prompt → Claude guesses → wrong output → you correct → repeat. That's your money evaporating.
|
|
29
|
+
|
|
30
|
+
## The Solution
|
|
31
|
+
|
|
32
|
+
18 tools in 3 categories that run as an MCP server inside Claude Code:
|
|
33
|
+
|
|
34
|
+
| Category | What it does |
|
|
35
|
+
|----------|-------------|
|
|
36
|
+
| 🎯 **Prompt Discipline** (12 tools) | Catches vague prompts, enforces structure, prevents waste |
|
|
37
|
+
| 🔍 **Timeline Intelligence** (4 tools) | LanceDB vector search across months of session history |
|
|
38
|
+
| ✅ **Verification & Hygiene** (2 tools) | Type-check, test, and audit before declaring done |
|
|
39
|
+
|
|
40
|
+
## Before / After
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
❌ "fix the auth bug"
|
|
44
|
+
→ Claude guesses which auth bug, edits wrong file
|
|
45
|
+
→ You correct it, 3 more rounds
|
|
46
|
+
→ 12,000 tokens burned
|
|
47
|
+
|
|
48
|
+
✅ preflight intercepts → clarify_intent fires
|
|
49
|
+
→ "Which auth bug? I see 3 open issues:
|
|
50
|
+
1. JWT expiry not refreshing (src/auth/jwt.ts)
|
|
51
|
+
2. OAuth callback 404 (src/auth/oauth.ts)
|
|
52
|
+
3. Session cookie SameSite (src/middleware/session.ts)
|
|
53
|
+
Pick one and I'll scope the fix."
|
|
54
|
+
→ 4,000 tokens, done right the first time
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Quick Start
|
|
58
|
+
|
|
59
|
+
**1. Clone & install:**
|
|
60
|
+
```bash
|
|
61
|
+
git clone https://github.com/TerminalGravity/preflight.git
|
|
62
|
+
cd preflight && npm install
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**2. Add to your Claude Code config** (`.claude/settings.json` or project `.mcp.json`):
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"mcpServers": {
|
|
69
|
+
"preflight": {
|
|
70
|
+
"command": "npx",
|
|
71
|
+
"args": ["tsx", "/path/to/preflight/src/index.ts"],
|
|
72
|
+
"cwd": "/path/to/preflight",
|
|
73
|
+
"env": {
|
|
74
|
+
"CLAUDE_PROJECT_DIR": "/path/to/your/project"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**3. Restart Claude Code.** That's it. The tools activate automatically.
|
|
82
|
+
|
|
83
|
+
## Tool Reference
|
|
84
|
+
|
|
85
|
+
### 🎯 Prompt Discipline
|
|
86
|
+
|
|
87
|
+
| Tool | What it does |
|
|
88
|
+
|------|-------------|
|
|
89
|
+
| `scope_work` | Creates structured execution plans before coding starts |
|
|
90
|
+
| `clarify_intent` | Gathers project context to disambiguate vague prompts |
|
|
91
|
+
| `enrich_agent_task` | Enriches sub-agent tasks with file paths and patterns |
|
|
92
|
+
| `sharpen_followup` | Resolves "fix it" / "do the others" to actual file targets |
|
|
93
|
+
| `token_audit` | Detects waste patterns, grades your session A–F |
|
|
94
|
+
| `sequence_tasks` | Orders tasks by dependency, locality, and risk |
|
|
95
|
+
| `checkpoint` | Save game before compaction — commits + resumption notes |
|
|
96
|
+
| `check_session_health` | Monitors uncommitted files, time since commit, turn count |
|
|
97
|
+
| `log_correction` | Tracks corrections and identifies recurring error patterns |
|
|
98
|
+
| `session_handoff` | Generates handoff briefs for new sessions |
|
|
99
|
+
| `what_changed` | Summarizes diffs since last checkpoint |
|
|
100
|
+
|
|
101
|
+
### 🔍 Timeline Intelligence
|
|
102
|
+
|
|
103
|
+
| Tool | What it does |
|
|
104
|
+
|------|-------------|
|
|
105
|
+
| `onboard_project` | Indexes a project's session history into LanceDB vectors |
|
|
106
|
+
| `search_history` | Semantic search across all indexed sessions |
|
|
107
|
+
| `timeline` | Chronological view of events across sessions |
|
|
108
|
+
| `scan_sessions` | Live scanning of active session data |
|
|
109
|
+
|
|
110
|
+
### ✅ Verification & Hygiene
|
|
111
|
+
|
|
112
|
+
| Tool | What it does |
|
|
113
|
+
|------|-------------|
|
|
114
|
+
| `verify_completion` | Runs type check + tests + build before declaring done |
|
|
115
|
+
| `audit_workspace` | Finds stale/missing workspace docs vs git activity |
|
|
116
|
+
|
|
117
|
+
## Timeline Intelligence
|
|
118
|
+
|
|
119
|
+
This is the feature that makes preflight more than a linter.
|
|
120
|
+
|
|
121
|
+
When you run `onboard_project` for a specific project, the server finds that project's session history (JSONL files in `~/.claude/projects/<encoded-path>/`) and indexes its events into a local [LanceDB](https://lancedb.github.io/lancedb/) database with vector embeddings. Run it once per project you want to search — each project's data stays tagged so you can query across them or filter to one.
|
|
122
|
+
|
|
123
|
+
**What that gives you:**
|
|
124
|
+
- 🔎 **Semantic search** — "How did I set up the auth middleware last month?" actually works
|
|
125
|
+
- 📊 **32K+ events** indexed across 9 months of real production sessions
|
|
126
|
+
- 🧭 **Timeline view** — see what happened across sessions chronologically
|
|
127
|
+
- 🔄 **Live scanning** — index new sessions as they happen
|
|
128
|
+
|
|
129
|
+
No data leaves your machine. Embeddings run locally by default (Xenova/transformers.js) or via OpenAI if configured.
|
|
130
|
+
|
|
131
|
+
## Architecture
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
Claude Code ←→ MCP Protocol ←→ preflight server
|
|
135
|
+
│
|
|
136
|
+
┌─────────────────┼─────────────────┐
|
|
137
|
+
│ │ │
|
|
138
|
+
Discipline Tools Timeline Tools Verification
|
|
139
|
+
(12 tools) (4 tools) (2 tools)
|
|
140
|
+
│
|
|
141
|
+
LanceDB
|
|
142
|
+
(local vectors)
|
|
143
|
+
│
|
|
144
|
+
~/.claude/projects/
|
|
145
|
+
(session JSONL files)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Configuration
|
|
149
|
+
|
|
150
|
+
### Embedding Providers
|
|
151
|
+
|
|
152
|
+
| Provider | Setup | Speed | Quality |
|
|
153
|
+
|----------|-------|-------|---------|
|
|
154
|
+
| **Local (Xenova)** | Zero config, default | ~50 events/sec | Good |
|
|
155
|
+
| **OpenAI** | Set `OPENAI_API_KEY` env var | ~200 events/sec | Excellent |
|
|
156
|
+
|
|
157
|
+
### Environment Variables
|
|
158
|
+
|
|
159
|
+
| Variable | Description | Default |
|
|
160
|
+
|----------|-------------|---------|
|
|
161
|
+
| `CLAUDE_PROJECT_DIR` | Project root to monitor | Required |
|
|
162
|
+
| `OPENAI_API_KEY` | OpenAI key for embeddings | (uses local Xenova) |
|
|
163
|
+
|
|
164
|
+
## Contributing
|
|
165
|
+
|
|
166
|
+
This project is young and there's plenty to do. Check the [issues](https://github.com/TerminalGravity/preflight/issues) — several are tagged `good first issue`.
|
|
167
|
+
|
|
168
|
+
PRs welcome. No CLA, no bureaucracy. If it makes the tool better, it gets merged.
|
|
169
|
+
|
|
170
|
+
## License
|
|
171
|
+
|
|
172
|
+
MIT — do whatever you want with it.
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// This is a shim that loads the compiled TypeScript CLI
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { dirname, join } from 'path';
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
|
|
9
|
+
// Load the compiled CLI
|
|
10
|
+
const cliPath = join(__dirname, '../dist/cli/init.js');
|
|
11
|
+
await import(cliPath);
|
package/dist/cli/init.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// =============================================================================
|
|
3
|
+
// preflight init — Zero-config MCP server setup for Claude Code
|
|
4
|
+
// =============================================================================
|
|
5
|
+
import { createInterface } from "node:readline";
|
|
6
|
+
import { readFile, writeFile, mkdir, copyFile } from "node:fs/promises";
|
|
7
|
+
import { join, dirname } from "node:path";
|
|
8
|
+
import { existsSync } from "node:fs";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
11
|
+
function ask(question) {
|
|
12
|
+
return new Promise((resolve) => rl.question(question, resolve));
|
|
13
|
+
}
|
|
14
|
+
/** Create .preflight/ directory with template files */
|
|
15
|
+
async function createPreflightConfig() {
|
|
16
|
+
const preflightDir = join(process.cwd(), ".preflight");
|
|
17
|
+
if (existsSync(preflightDir)) {
|
|
18
|
+
console.log("⚠️ .preflight/ directory already exists, skipping...\n");
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
await mkdir(preflightDir, { recursive: true });
|
|
23
|
+
// Get the current module's directory to find templates
|
|
24
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
25
|
+
const srcDir = dirname(dirname(currentFile)); // Go up from cli/ to src/
|
|
26
|
+
const templatesDir = join(srcDir, "templates");
|
|
27
|
+
// Copy template files
|
|
28
|
+
await copyFile(join(templatesDir, "config.yml"), join(preflightDir, "config.yml"));
|
|
29
|
+
await copyFile(join(templatesDir, "triage.yml"), join(preflightDir, "triage.yml"));
|
|
30
|
+
console.log("✅ Created .preflight/ directory with template config files");
|
|
31
|
+
console.log(" Edit .preflight/config.yml to configure your project settings");
|
|
32
|
+
console.log(" Edit .preflight/triage.yml to customize prompt triage rules\n");
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
console.error(`❌ Failed to create .preflight/ directory: ${error}\n`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async function main() {
|
|
39
|
+
console.log("\n✈️ preflight — MCP server setup\n");
|
|
40
|
+
const mcpPath = join(process.cwd(), ".mcp.json");
|
|
41
|
+
let config;
|
|
42
|
+
try {
|
|
43
|
+
const existing = await readFile(mcpPath, "utf-8");
|
|
44
|
+
config = JSON.parse(existing);
|
|
45
|
+
if (!config.mcpServers)
|
|
46
|
+
config.mcpServers = {};
|
|
47
|
+
console.log("Found existing .mcp.json\n");
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
config = { mcpServers: {} };
|
|
51
|
+
console.log("Creating new .mcp.json\n");
|
|
52
|
+
}
|
|
53
|
+
console.log("Choose a profile:\n");
|
|
54
|
+
console.log(" 1) minimal — 4 tools: clarify_intent, check_session_health, session_stats, prompt_score");
|
|
55
|
+
console.log(" 2) standard — 16 tools: all prompt discipline + session_stats + prompt_score");
|
|
56
|
+
console.log(" 3) full — 20 tools: everything + timeline/vector search (needs LanceDB)\n");
|
|
57
|
+
const choice = await ask("Profile [1/2/3] (default: 2): ");
|
|
58
|
+
const profileMap = { "1": "minimal", "2": "standard", "3": "full" };
|
|
59
|
+
const profile = profileMap[choice.trim()] || "standard";
|
|
60
|
+
// Ask about creating .preflight/ directory
|
|
61
|
+
console.log("\nPreflight can use either environment variables or a .preflight/ directory for configuration.");
|
|
62
|
+
console.log("The .preflight/ directory allows you to configure related projects, custom triage rules, and thresholds.\n");
|
|
63
|
+
const createConfig = await ask("Create .preflight/ directory with template config? [y/N]: ");
|
|
64
|
+
if (createConfig.trim().toLowerCase() === "y" || createConfig.trim().toLowerCase() === "yes") {
|
|
65
|
+
await createPreflightConfig();
|
|
66
|
+
}
|
|
67
|
+
const env = {
|
|
68
|
+
PROMPT_DISCIPLINE_PROFILE: profile,
|
|
69
|
+
};
|
|
70
|
+
if (profile === "full") {
|
|
71
|
+
console.log("\nFull profile uses embeddings for vector search.");
|
|
72
|
+
const provider = await ask("Embedding provider [local/openai] (default: local): ");
|
|
73
|
+
if (provider.trim().toLowerCase() === "openai") {
|
|
74
|
+
const key = await ask("OpenAI API key (or set OPENAI_API_KEY later): ");
|
|
75
|
+
if (key.trim()) {
|
|
76
|
+
env.OPENAI_API_KEY = key.trim();
|
|
77
|
+
}
|
|
78
|
+
env.EMBEDDING_PROVIDER = "openai";
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
env.EMBEDDING_PROVIDER = "local";
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
config.mcpServers["preflight"] = {
|
|
85
|
+
command: "npx",
|
|
86
|
+
args: ["-y", "preflight-dev@latest"],
|
|
87
|
+
env,
|
|
88
|
+
};
|
|
89
|
+
// For the actual server entry point, we need to point to index.ts via tsx
|
|
90
|
+
// But npx will resolve the bin entry which is the init script
|
|
91
|
+
// So use a different approach: command runs the server
|
|
92
|
+
config.mcpServers["preflight"] = {
|
|
93
|
+
command: "npx",
|
|
94
|
+
args: ["-y", "tsx", "node_modules/preflight/src/index.ts"],
|
|
95
|
+
env,
|
|
96
|
+
};
|
|
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
|
+
console.log(`\n✅ preflight added! (profile: ${profile})`);
|
|
147
|
+
console.log("Restart Claude Code to connect.\n");
|
|
148
|
+
rl.close();
|
|
149
|
+
}
|
|
150
|
+
main().catch((err) => {
|
|
151
|
+
console.error("Error:", err);
|
|
152
|
+
process.exit(1);
|
|
153
|
+
});
|
|
154
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// =============================================================================
|
|
3
|
+
// Preflight-Dev MCP Server — v3.0
|
|
4
|
+
// =============================================================================
|
|
5
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
|
+
import { isToolEnabled, getProfile } from "./profiles.js";
|
|
8
|
+
import { getConfig, hasPreflightConfig } from "./lib/config.js";
|
|
9
|
+
import { existsSync } from "fs";
|
|
10
|
+
// Main entry point
|
|
11
|
+
import { registerPreflightCheck } from "./tools/preflight-check.js";
|
|
12
|
+
// Category 1: Plans
|
|
13
|
+
import { registerScopeWork } from "./tools/scope-work.js";
|
|
14
|
+
// Category 2: Clarification
|
|
15
|
+
import { registerClarifyIntent } from "./tools/clarify-intent.js";
|
|
16
|
+
// Category 3: Delegation
|
|
17
|
+
import { registerEnrichAgentTask } from "./tools/enrich-agent-task.js";
|
|
18
|
+
// Category 4: Follow-up Specificity
|
|
19
|
+
import { registerSharpenFollowup } from "./tools/sharpen-followup.js";
|
|
20
|
+
// Category 5: Token Efficiency
|
|
21
|
+
import { registerTokenAudit } from "./tools/token-audit.js";
|
|
22
|
+
// Category 6: Sequencing
|
|
23
|
+
import { registerSequenceTasks } from "./tools/sequence-tasks.js";
|
|
24
|
+
// Category 7: Compaction Management
|
|
25
|
+
import { registerCheckpoint } from "./tools/checkpoint.js";
|
|
26
|
+
// Category 8: Session Lifecycle
|
|
27
|
+
import { registerSessionHealth } from "./tools/session-health.js";
|
|
28
|
+
// Category 9: Error Recovery
|
|
29
|
+
import { registerLogCorrection } from "./tools/log-correction.js";
|
|
30
|
+
// Category 10: Workspace Hygiene
|
|
31
|
+
import { registerAuditWorkspace } from "./tools/audit-workspace.js";
|
|
32
|
+
// Category 11: Cross-Session Continuity
|
|
33
|
+
import { registerSessionHandoff } from "./tools/session-handoff.js";
|
|
34
|
+
import { registerWhatChanged } from "./tools/what-changed.js";
|
|
35
|
+
// Category 12: Verification
|
|
36
|
+
import { registerVerifyCompletion } from "./tools/verify-completion.js";
|
|
37
|
+
// New lightweight tools
|
|
38
|
+
import { registerSessionStats } from "./tools/session-stats.js";
|
|
39
|
+
import { registerPromptScore } from "./tools/prompt-score.js";
|
|
40
|
+
// Timeline: Project Intelligence
|
|
41
|
+
import { registerOnboardProject } from "./tools/onboard-project.js";
|
|
42
|
+
import { registerSearchHistory } from "./tools/search-history.js";
|
|
43
|
+
import { registerTimeline } from "./tools/timeline-view.js";
|
|
44
|
+
import { registerScanSessions } from "./tools/scan-sessions.js";
|
|
45
|
+
import { registerGenerateScorecard } from "./tools/generate-scorecard.js";
|
|
46
|
+
// Validate related projects from config
|
|
47
|
+
function validateRelatedProjects() {
|
|
48
|
+
const config = getConfig();
|
|
49
|
+
const projects = config.related_projects;
|
|
50
|
+
if (projects.length === 0)
|
|
51
|
+
return;
|
|
52
|
+
const invalid = [];
|
|
53
|
+
for (const project of projects) {
|
|
54
|
+
if (!existsSync(project.path)) {
|
|
55
|
+
invalid.push(`${project.alias} (${project.path})`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (invalid.length > 0) {
|
|
59
|
+
process.stderr.write(`preflight-dev: warning - related projects contain invalid paths: ${invalid.join(", ")}\n`);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
process.stderr.write(`preflight-dev: related projects: ${projects.length} configured\n`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Load config and validate related projects on startup
|
|
66
|
+
const config = getConfig();
|
|
67
|
+
validateRelatedProjects();
|
|
68
|
+
const profile = getProfile();
|
|
69
|
+
const server = new McpServer({
|
|
70
|
+
name: "preflight",
|
|
71
|
+
version: "3.0.0",
|
|
72
|
+
});
|
|
73
|
+
const toolRegistry = [
|
|
74
|
+
["preflight_check", registerPreflightCheck],
|
|
75
|
+
["scope_work", registerScopeWork],
|
|
76
|
+
["clarify_intent", registerClarifyIntent],
|
|
77
|
+
["enrich_agent_task", registerEnrichAgentTask],
|
|
78
|
+
["sharpen_followup", registerSharpenFollowup],
|
|
79
|
+
["token_audit", registerTokenAudit],
|
|
80
|
+
["sequence_tasks", registerSequenceTasks],
|
|
81
|
+
["checkpoint", registerCheckpoint],
|
|
82
|
+
["check_session_health", registerSessionHealth],
|
|
83
|
+
["log_correction", registerLogCorrection],
|
|
84
|
+
["audit_workspace", registerAuditWorkspace],
|
|
85
|
+
["session_handoff", registerSessionHandoff],
|
|
86
|
+
["what_changed", registerWhatChanged],
|
|
87
|
+
["verify_completion", registerVerifyCompletion],
|
|
88
|
+
["session_stats", registerSessionStats],
|
|
89
|
+
["prompt_score", registerPromptScore],
|
|
90
|
+
["onboard_project", registerOnboardProject],
|
|
91
|
+
["search_history", registerSearchHistory],
|
|
92
|
+
["timeline_view", registerTimeline],
|
|
93
|
+
["scan_sessions", registerScanSessions],
|
|
94
|
+
["generate_scorecard", registerGenerateScorecard],
|
|
95
|
+
];
|
|
96
|
+
let registered = 0;
|
|
97
|
+
for (const [name, register] of toolRegistry) {
|
|
98
|
+
if (isToolEnabled(name)) {
|
|
99
|
+
register(server);
|
|
100
|
+
registered++;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const configSource = hasPreflightConfig() ? ".preflight/" : "env vars";
|
|
104
|
+
process.stderr.write(`preflight: profile=${profile}, tools=${registered}, config=${configSource}\n`);
|
|
105
|
+
// Graceful shutdown
|
|
106
|
+
function shutdown() {
|
|
107
|
+
process.stderr.write("preflight: shutting down\n");
|
|
108
|
+
process.exit(0);
|
|
109
|
+
}
|
|
110
|
+
process.on("SIGINT", shutdown);
|
|
111
|
+
process.on("SIGTERM", shutdown);
|
|
112
|
+
// Connect transport
|
|
113
|
+
try {
|
|
114
|
+
const transport = new StdioServerTransport();
|
|
115
|
+
await server.connect(transport);
|
|
116
|
+
process.stderr.write("preflight: server started\n");
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
process.stderr.write(`preflight: failed to start — ${err}\n`);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export type Profile = "minimal" | "standard" | "full";
|
|
2
|
+
export type EmbeddingProvider = "local" | "openai";
|
|
3
|
+
export type TriageStrictness = "relaxed" | "standard" | "strict";
|
|
4
|
+
export interface RelatedProject {
|
|
5
|
+
path: string;
|
|
6
|
+
alias: string;
|
|
7
|
+
}
|
|
8
|
+
export interface PreflightConfig {
|
|
9
|
+
profile: Profile;
|
|
10
|
+
related_projects: RelatedProject[];
|
|
11
|
+
thresholds: {
|
|
12
|
+
session_stale_minutes: number;
|
|
13
|
+
max_tool_calls_before_checkpoint: number;
|
|
14
|
+
correction_pattern_threshold: number;
|
|
15
|
+
};
|
|
16
|
+
embeddings: {
|
|
17
|
+
provider: EmbeddingProvider;
|
|
18
|
+
openai_api_key?: string;
|
|
19
|
+
};
|
|
20
|
+
triage: {
|
|
21
|
+
rules: {
|
|
22
|
+
always_check: string[];
|
|
23
|
+
skip: string[];
|
|
24
|
+
cross_service_keywords: string[];
|
|
25
|
+
};
|
|
26
|
+
strictness: TriageStrictness;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Get the singleton configuration object */
|
|
30
|
+
export declare function getConfig(): PreflightConfig;
|
|
31
|
+
/** Get related projects as simple path array (backward compatibility) */
|
|
32
|
+
export declare function getRelatedProjects(): string[];
|
|
33
|
+
/** Check if .preflight/ directory exists */
|
|
34
|
+
export declare function hasPreflightConfig(): boolean;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Preflight Configuration System
|
|
3
|
+
// =============================================================================
|
|
4
|
+
// Loads configuration from .preflight/ directory if present,
|
|
5
|
+
// falls back to environment variables.
|
|
6
|
+
// =============================================================================
|
|
7
|
+
import { existsSync, readFileSync } from "fs";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
import { load as yamlLoad } from "js-yaml";
|
|
10
|
+
import { PROJECT_DIR } from "./files.js";
|
|
11
|
+
// Default configuration (env var fallback)
|
|
12
|
+
const DEFAULT_CONFIG = {
|
|
13
|
+
profile: "standard",
|
|
14
|
+
related_projects: [],
|
|
15
|
+
thresholds: {
|
|
16
|
+
session_stale_minutes: 30,
|
|
17
|
+
max_tool_calls_before_checkpoint: 100,
|
|
18
|
+
correction_pattern_threshold: 3,
|
|
19
|
+
},
|
|
20
|
+
embeddings: {
|
|
21
|
+
provider: "local",
|
|
22
|
+
},
|
|
23
|
+
triage: {
|
|
24
|
+
rules: {
|
|
25
|
+
always_check: ["rewards", "permissions", "migration", "schema"],
|
|
26
|
+
skip: ["commit", "format", "lint"],
|
|
27
|
+
cross_service_keywords: ["auth", "notification", "event", "webhook"],
|
|
28
|
+
},
|
|
29
|
+
strictness: "standard",
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
let _config = null;
|
|
33
|
+
/** Load config from .preflight/ directory or fall back to env vars */
|
|
34
|
+
function loadConfig() {
|
|
35
|
+
const preflightDir = join(PROJECT_DIR, ".preflight");
|
|
36
|
+
const configPath = join(preflightDir, "config.yml");
|
|
37
|
+
const triagePath = join(preflightDir, "triage.yml");
|
|
38
|
+
// Start with defaults
|
|
39
|
+
let config = JSON.parse(JSON.stringify(DEFAULT_CONFIG));
|
|
40
|
+
// Load .preflight/config.yml if it exists
|
|
41
|
+
if (existsSync(configPath)) {
|
|
42
|
+
try {
|
|
43
|
+
const configYaml = readFileSync(configPath, "utf-8");
|
|
44
|
+
const configData = yamlLoad(configYaml);
|
|
45
|
+
if (configData) {
|
|
46
|
+
// Merge config data with defaults
|
|
47
|
+
if (configData.profile)
|
|
48
|
+
config.profile = configData.profile;
|
|
49
|
+
if (configData.related_projects)
|
|
50
|
+
config.related_projects = configData.related_projects;
|
|
51
|
+
if (configData.thresholds)
|
|
52
|
+
config.thresholds = { ...config.thresholds, ...configData.thresholds };
|
|
53
|
+
if (configData.embeddings)
|
|
54
|
+
config.embeddings = { ...config.embeddings, ...configData.embeddings };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
console.warn(`preflight: warning - failed to parse .preflight/config.yml: ${error}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Load .preflight/triage.yml if it exists
|
|
62
|
+
if (existsSync(triagePath)) {
|
|
63
|
+
try {
|
|
64
|
+
const triageYaml = readFileSync(triagePath, "utf-8");
|
|
65
|
+
const triageData = yamlLoad(triageYaml);
|
|
66
|
+
if (triageData) {
|
|
67
|
+
if (triageData.rules)
|
|
68
|
+
config.triage.rules = { ...config.triage.rules, ...triageData.rules };
|
|
69
|
+
if (triageData.strictness)
|
|
70
|
+
config.triage.strictness = triageData.strictness;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
console.warn(`preflight: warning - failed to parse .preflight/triage.yml: ${error}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Apply environment variable overrides (env vars are fallback, .preflight/ takes precedence)
|
|
78
|
+
// Only use env vars if .preflight/ directory doesn't exist
|
|
79
|
+
if (!existsSync(preflightDir)) {
|
|
80
|
+
// Profile
|
|
81
|
+
const envProfile = process.env.PROMPT_DISCIPLINE_PROFILE?.toLowerCase();
|
|
82
|
+
if (envProfile === "minimal" || envProfile === "standard" || envProfile === "full") {
|
|
83
|
+
config.profile = envProfile;
|
|
84
|
+
}
|
|
85
|
+
// Related projects
|
|
86
|
+
const envRelated = process.env.PREFLIGHT_RELATED;
|
|
87
|
+
if (envRelated) {
|
|
88
|
+
const projects = envRelated.split(",").map(p => p.trim()).filter(Boolean);
|
|
89
|
+
config.related_projects = projects.map(path => ({ path, alias: path.split("/").pop() || path }));
|
|
90
|
+
}
|
|
91
|
+
// Embedding provider
|
|
92
|
+
const envProvider = process.env.EMBEDDING_PROVIDER?.toLowerCase();
|
|
93
|
+
if (envProvider === "local" || envProvider === "openai") {
|
|
94
|
+
config.embeddings.provider = envProvider;
|
|
95
|
+
}
|
|
96
|
+
// OpenAI API key
|
|
97
|
+
if (process.env.OPENAI_API_KEY) {
|
|
98
|
+
config.embeddings.openai_api_key = process.env.OPENAI_API_KEY;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return config;
|
|
102
|
+
}
|
|
103
|
+
/** Get the singleton configuration object */
|
|
104
|
+
export function getConfig() {
|
|
105
|
+
if (_config === null) {
|
|
106
|
+
_config = loadConfig();
|
|
107
|
+
}
|
|
108
|
+
return _config;
|
|
109
|
+
}
|
|
110
|
+
/** Get related projects as simple path array (backward compatibility) */
|
|
111
|
+
export function getRelatedProjects() {
|
|
112
|
+
return getConfig().related_projects.map(p => p.path);
|
|
113
|
+
}
|
|
114
|
+
/** Check if .preflight/ directory exists */
|
|
115
|
+
export function hasPreflightConfig() {
|
|
116
|
+
return existsSync(join(PROJECT_DIR, ".preflight"));
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=config.js.map
|