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.
Files changed (142) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +172 -0
  3. package/bin/cli.js +11 -0
  4. package/dist/cli/init.d.ts +2 -0
  5. package/dist/cli/init.js +154 -0
  6. package/dist/cli/init.js.map +1 -0
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.js +122 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/lib/config.d.ts +34 -0
  11. package/dist/lib/config.js +118 -0
  12. package/dist/lib/config.js.map +1 -0
  13. package/dist/lib/embeddings.d.ts +11 -0
  14. package/dist/lib/embeddings.js +88 -0
  15. package/dist/lib/embeddings.js.map +1 -0
  16. package/dist/lib/files.d.ts +15 -0
  17. package/dist/lib/files.js +60 -0
  18. package/dist/lib/files.js.map +1 -0
  19. package/dist/lib/git-extractor.d.ts +9 -0
  20. package/dist/lib/git-extractor.js +116 -0
  21. package/dist/lib/git-extractor.js.map +1 -0
  22. package/dist/lib/git.d.ts +29 -0
  23. package/dist/lib/git.js +86 -0
  24. package/dist/lib/git.js.map +1 -0
  25. package/dist/lib/session-parser.d.ts +45 -0
  26. package/dist/lib/session-parser.js +267 -0
  27. package/dist/lib/session-parser.js.map +1 -0
  28. package/dist/lib/state.d.ts +21 -0
  29. package/dist/lib/state.js +86 -0
  30. package/dist/lib/state.js.map +1 -0
  31. package/dist/lib/timeline-db.d.ts +67 -0
  32. package/dist/lib/timeline-db.js +380 -0
  33. package/dist/lib/timeline-db.js.map +1 -0
  34. package/dist/lib/triage.d.ts +29 -0
  35. package/dist/lib/triage.js +193 -0
  36. package/dist/lib/triage.js.map +1 -0
  37. package/dist/profiles.d.ts +3 -0
  38. package/dist/profiles.js +65 -0
  39. package/dist/profiles.js.map +1 -0
  40. package/dist/tools/audit-workspace.d.ts +2 -0
  41. package/dist/tools/audit-workspace.js +86 -0
  42. package/dist/tools/audit-workspace.js.map +1 -0
  43. package/dist/tools/checkpoint.d.ts +2 -0
  44. package/dist/tools/checkpoint.js +108 -0
  45. package/dist/tools/checkpoint.js.map +1 -0
  46. package/dist/tools/clarify-intent.d.ts +2 -0
  47. package/dist/tools/clarify-intent.js +180 -0
  48. package/dist/tools/clarify-intent.js.map +1 -0
  49. package/dist/tools/enrich-agent-task.d.ts +2 -0
  50. package/dist/tools/enrich-agent-task.js +97 -0
  51. package/dist/tools/enrich-agent-task.js.map +1 -0
  52. package/dist/tools/generate-scorecard.d.ts +2 -0
  53. package/dist/tools/generate-scorecard.js +617 -0
  54. package/dist/tools/generate-scorecard.js.map +1 -0
  55. package/dist/tools/log-correction.d.ts +2 -0
  56. package/dist/tools/log-correction.js +76 -0
  57. package/dist/tools/log-correction.js.map +1 -0
  58. package/dist/tools/onboard-project.d.ts +2 -0
  59. package/dist/tools/onboard-project.js +179 -0
  60. package/dist/tools/onboard-project.js.map +1 -0
  61. package/dist/tools/preflight-check.d.ts +2 -0
  62. package/dist/tools/preflight-check.js +229 -0
  63. package/dist/tools/preflight-check.js.map +1 -0
  64. package/dist/tools/prompt-score.d.ts +2 -0
  65. package/dist/tools/prompt-score.js +132 -0
  66. package/dist/tools/prompt-score.js.map +1 -0
  67. package/dist/tools/scan-sessions.d.ts +2 -0
  68. package/dist/tools/scan-sessions.js +182 -0
  69. package/dist/tools/scan-sessions.js.map +1 -0
  70. package/dist/tools/scope-work.d.ts +2 -0
  71. package/dist/tools/scope-work.js +214 -0
  72. package/dist/tools/scope-work.js.map +1 -0
  73. package/dist/tools/search-history.d.ts +2 -0
  74. package/dist/tools/search-history.js +130 -0
  75. package/dist/tools/search-history.js.map +1 -0
  76. package/dist/tools/sequence-tasks.d.ts +2 -0
  77. package/dist/tools/sequence-tasks.js +165 -0
  78. package/dist/tools/sequence-tasks.js.map +1 -0
  79. package/dist/tools/session-handoff.d.ts +2 -0
  80. package/dist/tools/session-handoff.js +113 -0
  81. package/dist/tools/session-handoff.js.map +1 -0
  82. package/dist/tools/session-health.d.ts +2 -0
  83. package/dist/tools/session-health.js +111 -0
  84. package/dist/tools/session-health.js.map +1 -0
  85. package/dist/tools/session-stats.d.ts +2 -0
  86. package/dist/tools/session-stats.js +112 -0
  87. package/dist/tools/session-stats.js.map +1 -0
  88. package/dist/tools/sharpen-followup.d.ts +2 -0
  89. package/dist/tools/sharpen-followup.js +192 -0
  90. package/dist/tools/sharpen-followup.js.map +1 -0
  91. package/dist/tools/timeline-view.d.ts +2 -0
  92. package/dist/tools/timeline-view.js +165 -0
  93. package/dist/tools/timeline-view.js.map +1 -0
  94. package/dist/tools/token-audit.d.ts +2 -0
  95. package/dist/tools/token-audit.js +227 -0
  96. package/dist/tools/token-audit.js.map +1 -0
  97. package/dist/tools/verify-completion.d.ts +2 -0
  98. package/dist/tools/verify-completion.js +154 -0
  99. package/dist/tools/verify-completion.js.map +1 -0
  100. package/dist/tools/what-changed.d.ts +2 -0
  101. package/dist/tools/what-changed.js +40 -0
  102. package/dist/tools/what-changed.js.map +1 -0
  103. package/dist/types.d.ts +78 -0
  104. package/dist/types.js +2 -0
  105. package/dist/types.js.map +1 -0
  106. package/package.json +52 -0
  107. package/src/cli/init.ts +133 -0
  108. package/src/index.ts +135 -0
  109. package/src/lib/config.ts +157 -0
  110. package/src/lib/embeddings.ts +118 -0
  111. package/src/lib/files.ts +59 -0
  112. package/src/lib/git-extractor.ts +137 -0
  113. package/src/lib/git.ts +89 -0
  114. package/src/lib/session-parser.ts +325 -0
  115. package/src/lib/state.ts +86 -0
  116. package/src/lib/timeline-db.ts +490 -0
  117. package/src/lib/triage.ts +255 -0
  118. package/src/profiles.ts +70 -0
  119. package/src/templates/config.yml +23 -0
  120. package/src/templates/triage.yml +27 -0
  121. package/src/tools/audit-workspace.ts +97 -0
  122. package/src/tools/checkpoint.ts +119 -0
  123. package/src/tools/clarify-intent.ts +191 -0
  124. package/src/tools/enrich-agent-task.ts +108 -0
  125. package/src/tools/generate-scorecard.ts +673 -0
  126. package/src/tools/log-correction.ts +89 -0
  127. package/src/tools/onboard-project.ts +214 -0
  128. package/src/tools/preflight-check.ts +263 -0
  129. package/src/tools/prompt-score.ts +150 -0
  130. package/src/tools/scan-sessions.ts +209 -0
  131. package/src/tools/scope-work.ts +238 -0
  132. package/src/tools/search-history.ts +145 -0
  133. package/src/tools/sequence-tasks.ts +182 -0
  134. package/src/tools/session-handoff.ts +125 -0
  135. package/src/tools/session-health.ts +107 -0
  136. package/src/tools/session-stats.ts +134 -0
  137. package/src/tools/sharpen-followup.ts +200 -0
  138. package/src/tools/timeline-view.ts +181 -0
  139. package/src/tools/token-audit.ts +259 -0
  140. package/src/tools/verify-completion.ts +159 -0
  141. package/src/tools/what-changed.ts +48 -0
  142. 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
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
10
+ [![MCP](https://img.shields.io/badge/MCP-Compatible-blueviolet)](https://modelcontextprotocol.io/)
11
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](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);
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -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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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
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