@promptwheel/mcp 0.6.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 (134) hide show
  1. package/README.md +178 -0
  2. package/dist/advance-helpers.d.ts +27 -0
  3. package/dist/advance-helpers.d.ts.map +1 -0
  4. package/dist/advance-helpers.js +127 -0
  5. package/dist/advance-helpers.js.map +1 -0
  6. package/dist/advance-prompts.d.ts +48 -0
  7. package/dist/advance-prompts.d.ts.map +1 -0
  8. package/dist/advance-prompts.js +420 -0
  9. package/dist/advance-prompts.js.map +1 -0
  10. package/dist/advance.d.ts +30 -0
  11. package/dist/advance.d.ts.map +1 -0
  12. package/dist/advance.js +752 -0
  13. package/dist/advance.js.map +1 -0
  14. package/dist/codebase-index.d.ts +5 -0
  15. package/dist/codebase-index.d.ts.map +1 -0
  16. package/dist/codebase-index.js +5 -0
  17. package/dist/codebase-index.js.map +1 -0
  18. package/dist/dedup-memory.d.ts +30 -0
  19. package/dist/dedup-memory.d.ts.map +1 -0
  20. package/dist/dedup-memory.js +76 -0
  21. package/dist/dedup-memory.js.map +1 -0
  22. package/dist/direct-client.d.ts +57 -0
  23. package/dist/direct-client.d.ts.map +1 -0
  24. package/dist/direct-client.js +92 -0
  25. package/dist/direct-client.js.map +1 -0
  26. package/dist/event-handlers-qa.d.ts +5 -0
  27. package/dist/event-handlers-qa.d.ts.map +1 -0
  28. package/dist/event-handlers-qa.js +186 -0
  29. package/dist/event-handlers-qa.js.map +1 -0
  30. package/dist/event-handlers-scout.d.ts +5 -0
  31. package/dist/event-handlers-scout.d.ts.map +1 -0
  32. package/dist/event-handlers-scout.js +270 -0
  33. package/dist/event-handlers-scout.js.map +1 -0
  34. package/dist/event-handlers-ticket.d.ts +5 -0
  35. package/dist/event-handlers-ticket.d.ts.map +1 -0
  36. package/dist/event-handlers-ticket.js +232 -0
  37. package/dist/event-handlers-ticket.js.map +1 -0
  38. package/dist/event-helpers.d.ts +46 -0
  39. package/dist/event-helpers.d.ts.map +1 -0
  40. package/dist/event-helpers.js +125 -0
  41. package/dist/event-helpers.js.map +1 -0
  42. package/dist/event-processor.d.ts +15 -0
  43. package/dist/event-processor.d.ts.map +1 -0
  44. package/dist/event-processor.js +111 -0
  45. package/dist/event-processor.js.map +1 -0
  46. package/dist/formulas.d.ts +27 -0
  47. package/dist/formulas.d.ts.map +1 -0
  48. package/dist/formulas.js +109 -0
  49. package/dist/formulas.js.map +1 -0
  50. package/dist/guidelines.d.ts +16 -0
  51. package/dist/guidelines.d.ts.map +1 -0
  52. package/dist/guidelines.js +44 -0
  53. package/dist/guidelines.js.map +1 -0
  54. package/dist/index.d.ts +9 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +42 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/learnings.d.ts +42 -0
  59. package/dist/learnings.d.ts.map +1 -0
  60. package/dist/learnings.js +117 -0
  61. package/dist/learnings.js.map +1 -0
  62. package/dist/project-metadata.d.ts +34 -0
  63. package/dist/project-metadata.d.ts.map +1 -0
  64. package/dist/project-metadata.js +617 -0
  65. package/dist/project-metadata.js.map +1 -0
  66. package/dist/proposals.d.ts +23 -0
  67. package/dist/proposals.d.ts.map +1 -0
  68. package/dist/proposals.js +201 -0
  69. package/dist/proposals.js.map +1 -0
  70. package/dist/qa-stats.d.ts +51 -0
  71. package/dist/qa-stats.d.ts.map +1 -0
  72. package/dist/qa-stats.js +121 -0
  73. package/dist/qa-stats.js.map +1 -0
  74. package/dist/run-manager.d.ts +97 -0
  75. package/dist/run-manager.d.ts.map +1 -0
  76. package/dist/run-manager.js +583 -0
  77. package/dist/run-manager.js.map +1 -0
  78. package/dist/run-state-bridge.d.ts +13 -0
  79. package/dist/run-state-bridge.d.ts.map +1 -0
  80. package/dist/run-state-bridge.js +101 -0
  81. package/dist/run-state-bridge.js.map +1 -0
  82. package/dist/scope-policy.d.ts +83 -0
  83. package/dist/scope-policy.d.ts.map +1 -0
  84. package/dist/scope-policy.js +278 -0
  85. package/dist/scope-policy.js.map +1 -0
  86. package/dist/server.d.ts +18 -0
  87. package/dist/server.d.ts.map +1 -0
  88. package/dist/server.js +35 -0
  89. package/dist/server.js.map +1 -0
  90. package/dist/spindle.d.ts +41 -0
  91. package/dist/spindle.d.ts.map +1 -0
  92. package/dist/spindle.js +230 -0
  93. package/dist/spindle.js.map +1 -0
  94. package/dist/state.d.ts +36 -0
  95. package/dist/state.d.ts.map +1 -0
  96. package/dist/state.js +50 -0
  97. package/dist/state.js.map +1 -0
  98. package/dist/ticket-worker.d.ts +37 -0
  99. package/dist/ticket-worker.d.ts.map +1 -0
  100. package/dist/ticket-worker.js +527 -0
  101. package/dist/ticket-worker.js.map +1 -0
  102. package/dist/tool-registry.d.ts +35 -0
  103. package/dist/tool-registry.d.ts.map +1 -0
  104. package/dist/tool-registry.js +129 -0
  105. package/dist/tool-registry.js.map +1 -0
  106. package/dist/tools/execute.d.ts +17 -0
  107. package/dist/tools/execute.d.ts.map +1 -0
  108. package/dist/tools/execute.js +418 -0
  109. package/dist/tools/execute.js.map +1 -0
  110. package/dist/tools/git.d.ts +7 -0
  111. package/dist/tools/git.d.ts.map +1 -0
  112. package/dist/tools/git.js +98 -0
  113. package/dist/tools/git.js.map +1 -0
  114. package/dist/tools/intelligence.d.ts +10 -0
  115. package/dist/tools/intelligence.d.ts.map +1 -0
  116. package/dist/tools/intelligence.js +432 -0
  117. package/dist/tools/intelligence.js.map +1 -0
  118. package/dist/tools/session.d.ts +7 -0
  119. package/dist/tools/session.d.ts.map +1 -0
  120. package/dist/tools/session.js +533 -0
  121. package/dist/tools/session.js.map +1 -0
  122. package/dist/tools/trajectory.d.ts +10 -0
  123. package/dist/tools/trajectory.d.ts.map +1 -0
  124. package/dist/tools/trajectory.js +374 -0
  125. package/dist/tools/trajectory.js.map +1 -0
  126. package/dist/trajectory-io.d.ts +21 -0
  127. package/dist/trajectory-io.d.ts.map +1 -0
  128. package/dist/trajectory-io.js +105 -0
  129. package/dist/trajectory-io.js.map +1 -0
  130. package/dist/types.d.ts +229 -0
  131. package/dist/types.d.ts.map +1 -0
  132. package/dist/types.js +13 -0
  133. package/dist/types.js.map +1 -0
  134. package/package.json +63 -0
@@ -0,0 +1,125 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { repos } from '@promptwheel/core';
4
+ import { recordDedupEntry } from './dedup-memory.js';
5
+ import { recordTicketOutcome as recordTicketOutcomeCore, } from '@promptwheel/core/sectors/shared';
6
+ // ---------------------------------------------------------------------------
7
+ // Helpers — shared sector & dedup recording
8
+ // ---------------------------------------------------------------------------
9
+ /** Atomic write: write to .tmp then rename, preventing corruption on crash */
10
+ export function atomicWriteJsonSync(filePath, data) {
11
+ const tmpPath = filePath + '.tmp';
12
+ fs.writeFileSync(tmpPath, JSON.stringify(data, null, 2), 'utf8');
13
+ fs.renameSync(tmpPath, filePath);
14
+ }
15
+ /** Load sectors.json, return null if missing/invalid. */
16
+ export function loadSectorsState(rootPath) {
17
+ try {
18
+ const filePath = path.join(rootPath, '.promptwheel', 'sectors.json');
19
+ if (!fs.existsSync(filePath))
20
+ return null;
21
+ const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
22
+ if (data?.version !== 2 || !Array.isArray(data.sectors))
23
+ return null;
24
+ return { state: data, filePath };
25
+ }
26
+ catch (err) {
27
+ console.warn(`[promptwheel] loadSectorsState: ${err instanceof Error ? err.message : String(err)}`);
28
+ return null;
29
+ }
30
+ }
31
+ export function recordSectorOutcome(rootPath, sectorPath, outcome) {
32
+ if (!sectorPath)
33
+ return;
34
+ try {
35
+ const loaded = loadSectorsState(rootPath);
36
+ if (!loaded)
37
+ return;
38
+ recordTicketOutcomeCore(loaded.state, sectorPath, outcome === 'success');
39
+ atomicWriteJsonSync(loaded.filePath, loaded.state);
40
+ }
41
+ catch (err) {
42
+ console.warn(`[promptwheel] recordSectorOutcome: ${err instanceof Error ? err.message : String(err)}`);
43
+ }
44
+ }
45
+ export async function recordTicketDedup(db, rootPath, ticketId, completed, reason,
46
+ /** Pass a pre-fetched ticket to avoid a redundant DB lookup */
47
+ prefetchedTicket) {
48
+ if (!ticketId)
49
+ return;
50
+ try {
51
+ const ticket = prefetchedTicket ?? await repos.tickets.getById(db, ticketId);
52
+ if (ticket) {
53
+ recordDedupEntry(rootPath, ticket.title, completed, reason);
54
+ }
55
+ }
56
+ catch (err) {
57
+ console.warn(`[promptwheel] recordTicketDedup: ${err instanceof Error ? err.message : String(err)}`);
58
+ }
59
+ }
60
+ /**
61
+ * Extract a normalized error signature from raw error output.
62
+ * Captures the first recognizable error pattern (TypeError, SyntaxError, assertion, etc.)
63
+ * and truncates to 120 chars for storage.
64
+ */
65
+ export function extractErrorSignature(errorOutput) {
66
+ if (!errorOutput)
67
+ return undefined;
68
+ // Match common error patterns
69
+ const patterns = [
70
+ /(?:TypeError|ReferenceError|SyntaxError|RangeError|Error):\s*[^\n]{1,100}/,
71
+ /AssertionError:\s*[^\n]{1,100}/i,
72
+ /FAIL(?:ED)?[:\s]+[^\n]{1,80}/i,
73
+ /error\[E\d+\]:\s*[^\n]{1,80}/i, // Rust errors
74
+ /panic:\s*[^\n]{1,80}/, // Go panics
75
+ /Exception[:\s]+[^\n]{1,80}/i, // Java/Python exceptions
76
+ ];
77
+ for (const p of patterns) {
78
+ const match = errorOutput.match(p);
79
+ if (match)
80
+ return match[0].slice(0, 120);
81
+ }
82
+ return undefined;
83
+ }
84
+ /**
85
+ * Classify a QA error to determine retry strategy.
86
+ * - environment: permission denied, missing tools, env vars — don't retry (will never pass)
87
+ * - timeout: command timed out — retry once (transient)
88
+ * - code: test failures, type errors, syntax errors — full retries (agent can fix)
89
+ * - unknown: can't classify — full retries (default)
90
+ */
91
+ export function classifyQaError(errorOutput) {
92
+ const lower = errorOutput.toLowerCase();
93
+ // Environment / permission issues — unrecoverable without human intervention
94
+ if (/permission denied|eacces|eperm/i.test(errorOutput))
95
+ return 'environment';
96
+ if (/command not found|enoent.*spawn/i.test(errorOutput))
97
+ return 'environment';
98
+ if (/missing.*(env|variable|credential|token|key|secret)/i.test(lower))
99
+ return 'environment';
100
+ if (/econnrefused|enotfound|cannot connect/i.test(errorOutput))
101
+ return 'environment';
102
+ // Timeout — transient, worth one retry
103
+ if (/timed?\s*out|timeout|etimedout/i.test(errorOutput))
104
+ return 'timeout';
105
+ if (/killed.*signal|sigterm|sigkill/i.test(lower))
106
+ return 'timeout';
107
+ // Code errors — agent can fix these
108
+ if (/syntaxerror|typeerror|referenceerror|rangeerror/i.test(errorOutput))
109
+ return 'code';
110
+ if (/assertion|expect|fail|error\[/i.test(lower))
111
+ return 'code';
112
+ if (/tsc.*error|type.*not assignable/i.test(lower))
113
+ return 'code';
114
+ return 'unknown';
115
+ }
116
+ /** Max retries per error class */
117
+ export function maxRetriesForClass(errorClass) {
118
+ switch (errorClass) {
119
+ case 'environment': return 1; // One retry in case it was a race, then give up
120
+ case 'timeout': return 2; // Transient — try twice
121
+ case 'code': return 3; // Agent can fix — full retries
122
+ case 'unknown': return 3; // Default — full retries
123
+ }
124
+ }
125
+ //# sourceMappingURL=event-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-helpers.js","sourceRoot":"","sources":["../src/event-helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Event Processor — handles ingested events and triggers state transitions.
3
+ *
4
+ * When the client calls `promptwheel_ingest_event`, this module processes
5
+ * the event and updates RunState accordingly (phase transitions, counters, etc).
6
+ */
7
+ import type { DatabaseAdapter } from '@promptwheel/core';
8
+ import type { Project } from '@promptwheel/core';
9
+ import { RunManager } from './run-manager.js';
10
+ import type { EventType } from './types.js';
11
+ export type { ProcessResult, QaErrorClass } from './event-helpers.js';
12
+ export { classifyQaError } from './event-helpers.js';
13
+ import type { ProcessResult } from './event-helpers.js';
14
+ export declare function processEvent(run: RunManager, db: DatabaseAdapter, type: EventType, payload: Record<string, unknown>, project?: Project): Promise<ProcessResult>;
15
+ //# sourceMappingURL=event-processor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-processor.d.ts","sourceRoot":"","sources":["../src/event-processor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAM5C,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAKxD,wBAAsB,YAAY,CAChC,GAAG,EAAE,UAAU,EACf,EAAE,EAAE,eAAe,EACnB,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,CAAC,EAAE,OAAO,GAChB,OAAO,CAAC,aAAa,CAAC,CA4GxB"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Event Processor — handles ingested events and triggers state transitions.
3
+ *
4
+ * When the client calls `promptwheel_ingest_event`, this module processes
5
+ * the event and updates RunState accordingly (phase transitions, counters, etc).
6
+ */
7
+ import { filterAndCreateTickets } from './proposals.js';
8
+ import { ingestTicketEvent } from './ticket-worker.js';
9
+ export { classifyQaError } from './event-helpers.js';
10
+ import { handleScoutOutput, handleProposalsReviewed, handleProposalsFiltered } from './event-handlers-scout.js';
11
+ import { handlePlanSubmitted, handleTicketResult, handlePrCreated } from './event-handlers-ticket.js';
12
+ import { handleQaCommandResult, handleQaPassed, handleQaFailed } from './event-handlers-qa.js';
13
+ export async function processEvent(run, db, type, payload, project) {
14
+ const s = run.require();
15
+ // Ensure learnings loaded for any event handler that might need them
16
+ run.ensureLearningsLoaded();
17
+ // ---------------------------------------------------------------------------
18
+ // Parallel execution: forward ticket-specific events to ticket workers
19
+ // ---------------------------------------------------------------------------
20
+ // When in PARALLEL_EXECUTE phase, events like PR_CREATED, TICKET_RESULT, etc.
21
+ // should be routed to the ticket worker, not processed at session level.
22
+ // This handles the case where the user calls promptwheel_ingest_event instead
23
+ // of promptwheel_ticket_event for ticket completion.
24
+ const TICKET_WORKER_EVENTS = new Set([
25
+ 'PR_CREATED', 'TICKET_RESULT', 'PLAN_SUBMITTED', 'QA_PASSED', 'QA_FAILED', 'QA_COMMAND_RESULT',
26
+ ]);
27
+ if (s.phase === 'PARALLEL_EXECUTE' && TICKET_WORKER_EVENTS.has(type)) {
28
+ const ticketId = payload['ticket_id'];
29
+ if (ticketId && run.getTicketWorker(ticketId)) {
30
+ // Forward to ticket worker
31
+ const ctx = { run, db, project: project ?? { id: s.project_id, rootPath: run.rootPath } };
32
+ const result = await ingestTicketEvent(ctx, ticketId, type, payload);
33
+ return {
34
+ processed: result.processed,
35
+ phase_changed: false,
36
+ message: result.message,
37
+ };
38
+ }
39
+ }
40
+ const ctx = { run, db, project };
41
+ switch (type) {
42
+ // -----------------------------------------------------------------
43
+ // Scout events
44
+ // -----------------------------------------------------------------
45
+ case 'SCOUT_OUTPUT': return handleScoutOutput(ctx, payload);
46
+ case 'PROPOSALS_REVIEWED': return handleProposalsReviewed(ctx, payload);
47
+ case 'PROPOSALS_FILTERED': return handleProposalsFiltered(ctx, payload);
48
+ // -----------------------------------------------------------------
49
+ // Plan events
50
+ // -----------------------------------------------------------------
51
+ case 'PLAN_SUBMITTED': return handlePlanSubmitted(ctx, payload);
52
+ // -----------------------------------------------------------------
53
+ // Execution events
54
+ // -----------------------------------------------------------------
55
+ case 'TICKET_RESULT': return handleTicketResult(ctx, payload);
56
+ // -----------------------------------------------------------------
57
+ // QA events
58
+ // -----------------------------------------------------------------
59
+ case 'QA_COMMAND_RESULT': return handleQaCommandResult(ctx, payload);
60
+ case 'QA_PASSED': return handleQaPassed(ctx, payload);
61
+ case 'QA_FAILED': return handleQaFailed(ctx, payload);
62
+ // -----------------------------------------------------------------
63
+ // PR events
64
+ // -----------------------------------------------------------------
65
+ case 'PR_CREATED': return handlePrCreated(ctx, payload);
66
+ // -----------------------------------------------------------------
67
+ // User overrides
68
+ // -----------------------------------------------------------------
69
+ case 'USER_OVERRIDE': {
70
+ if (typeof payload['hint'] === 'string') {
71
+ run.addHint(payload['hint']);
72
+ return { processed: true, phase_changed: false, message: 'Hint added' };
73
+ }
74
+ if (payload['cancel'] === true) {
75
+ run.setPhase('DONE');
76
+ return {
77
+ processed: true,
78
+ phase_changed: true,
79
+ new_phase: 'DONE',
80
+ message: 'Session cancelled by user',
81
+ };
82
+ }
83
+ if (payload['skip_review'] === true) {
84
+ s.skip_review = true;
85
+ // If there are pending proposals waiting for review, create tickets immediately
86
+ if (s.pending_proposals && s.pending_proposals.length > 0) {
87
+ const pendingProposals = s.pending_proposals;
88
+ s.pending_proposals = null;
89
+ const result = await filterAndCreateTickets(run, db, pendingProposals);
90
+ if (result.created_ticket_ids.length > 0) {
91
+ run.setPhase('NEXT_TICKET');
92
+ return {
93
+ processed: true,
94
+ phase_changed: true,
95
+ new_phase: 'NEXT_TICKET',
96
+ message: `skip_review enabled, created ${result.created_ticket_ids.length} tickets from pending proposals`,
97
+ };
98
+ }
99
+ }
100
+ return { processed: true, phase_changed: false, message: 'skip_review enabled' };
101
+ }
102
+ return { processed: true, phase_changed: false, message: 'User override recorded' };
103
+ }
104
+ // -----------------------------------------------------------------
105
+ // Default: just record
106
+ // -----------------------------------------------------------------
107
+ default:
108
+ return { processed: true, phase_changed: false, message: `Event ${type} recorded` };
109
+ }
110
+ }
111
+ //# sourceMappingURL=event-processor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-processor.js","sourceRoot":"","sources":["../src/event-processor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Formulas — typed, versioned, testable sweep recipes.
3
+ *
4
+ * Pure definitions (BUILTIN_FORMULAS, YAML parsing) live in
5
+ * @promptwheel/core/formulas/shared. This file wraps them with
6
+ * filesystem I/O and adds MCP-specific formula application logic.
7
+ */
8
+ import type { SessionConfig } from './types.js';
9
+ import { type Formula as CoreFormula } from '@promptwheel/core/formulas/shared';
10
+ export type { Formula } from '@promptwheel/core/formulas/shared';
11
+ export { BUILTIN_FORMULAS, parseSimpleYaml, parseStringList } from '@promptwheel/core/formulas/shared';
12
+ type Formula = CoreFormula;
13
+ /**
14
+ * Load a formula by name.
15
+ * Search order: user formulas in `.promptwheel/formulas/`, then built-ins.
16
+ */
17
+ export declare function loadFormula(name: string, projectPath?: string): Formula | null;
18
+ /**
19
+ * List all available formulas (user + built-in, user overrides built-in).
20
+ */
21
+ export declare function listFormulas(projectPath?: string): Formula[];
22
+ /**
23
+ * Apply a formula's settings to a SessionConfig.
24
+ * Formula values are defaults — explicit config values take precedence.
25
+ */
26
+ export declare function applyFormula(formula: Formula, config: SessionConfig): SessionConfig;
27
+ //# sourceMappingURL=formulas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formulas.d.ts","sourceRoot":"","sources":["../src/formulas.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EACL,KAAK,OAAO,IAAI,WAAW,EAI5B,MAAM,mCAAmC,CAAC;AAG3C,YAAY,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAGvG,KAAK,OAAO,GAAG,WAAW,CAAC;AAM3B;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAI9E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,EAAE,CAK5D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,GAAG,aAAa,CASnF"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Formulas — typed, versioned, testable sweep recipes.
3
+ *
4
+ * Pure definitions (BUILTIN_FORMULAS, YAML parsing) live in
5
+ * @promptwheel/core/formulas/shared. This file wraps them with
6
+ * filesystem I/O and adds MCP-specific formula application logic.
7
+ */
8
+ import * as fs from 'node:fs';
9
+ import * as path from 'node:path';
10
+ import { BUILTIN_FORMULAS as CORE_BUILTINS, parseSimpleYaml, parseStringList, } from '@promptwheel/core/formulas/shared';
11
+ export { BUILTIN_FORMULAS, parseSimpleYaml, parseStringList } from '@promptwheel/core/formulas/shared';
12
+ // ---------------------------------------------------------------------------
13
+ // Loader (wraps core with filesystem I/O)
14
+ // ---------------------------------------------------------------------------
15
+ /**
16
+ * Load a formula by name.
17
+ * Search order: user formulas in `.promptwheel/formulas/`, then built-ins.
18
+ */
19
+ export function loadFormula(name, projectPath) {
20
+ const userFormula = loadUserFormula(name, projectPath);
21
+ if (userFormula)
22
+ return userFormula;
23
+ return CORE_BUILTINS.find(f => f.name === name) ?? null;
24
+ }
25
+ /**
26
+ * List all available formulas (user + built-in, user overrides built-in).
27
+ */
28
+ export function listFormulas(projectPath) {
29
+ const userFormulas = loadAllUserFormulas(projectPath);
30
+ const userNames = new Set(userFormulas.map(f => f.name));
31
+ const builtins = CORE_BUILTINS.filter(f => !userNames.has(f.name));
32
+ return [...userFormulas, ...builtins];
33
+ }
34
+ /**
35
+ * Apply a formula's settings to a SessionConfig.
36
+ * Formula values are defaults — explicit config values take precedence.
37
+ */
38
+ export function applyFormula(formula, config) {
39
+ return {
40
+ ...config,
41
+ scope: config.scope ?? formula.scope,
42
+ categories: config.categories ?? formula.categories,
43
+ min_confidence: config.min_confidence ?? (formula.min_confidence ?? formula.minConfidence),
44
+ max_prs: config.max_prs ?? (formula.max_prs ?? formula.maxPrs),
45
+ formula: config.formula,
46
+ };
47
+ }
48
+ // ---------------------------------------------------------------------------
49
+ // User formulas (filesystem I/O)
50
+ // ---------------------------------------------------------------------------
51
+ function getFormulasDir(projectPath) {
52
+ const base = projectPath ?? process.cwd();
53
+ return path.join(base, '.promptwheel', 'formulas');
54
+ }
55
+ function loadUserFormula(name, projectPath) {
56
+ const dir = getFormulasDir(projectPath);
57
+ for (const ext of ['.yaml', '.yml']) {
58
+ const filePath = path.join(dir, `${name}${ext}`);
59
+ if (fs.existsSync(filePath)) {
60
+ return parseFormulaFile(filePath, name);
61
+ }
62
+ }
63
+ return null;
64
+ }
65
+ function loadAllUserFormulas(projectPath) {
66
+ const dir = getFormulasDir(projectPath);
67
+ if (!fs.existsSync(dir))
68
+ return [];
69
+ const files = fs.readdirSync(dir).filter(f => f.endsWith('.yaml') || f.endsWith('.yml'));
70
+ const formulas = [];
71
+ for (const file of files) {
72
+ const name = path.basename(file, path.extname(file));
73
+ const formula = parseFormulaFile(path.join(dir, file), name);
74
+ if (formula)
75
+ formulas.push(formula);
76
+ }
77
+ return formulas;
78
+ }
79
+ function parseFormulaFile(filePath, name) {
80
+ const safeInt = (val, fallback) => {
81
+ const n = parseInt(val, 10);
82
+ return Number.isNaN(n) ? fallback : n;
83
+ };
84
+ try {
85
+ const content = fs.readFileSync(filePath, 'utf-8');
86
+ const parsed = parseSimpleYaml(content);
87
+ return {
88
+ name,
89
+ version: parsed.version ? safeInt(parsed.version, 1) : 1,
90
+ description: parsed.description || `Formula: ${name}`,
91
+ scope: parsed.scope,
92
+ categories: parsed.categories ? parseStringList(parsed.categories) : undefined,
93
+ min_confidence: parsed.min_confidence ? safeInt(parsed.min_confidence, 50) : undefined,
94
+ prompt: parsed.prompt,
95
+ max_prs: parsed.max_prs ? safeInt(parsed.max_prs, 5) : undefined,
96
+ model: parsed.model,
97
+ risk_tolerance: parsed.risk_tolerance,
98
+ exclude: parsed.exclude ? parseStringList(parsed.exclude) : undefined,
99
+ tags: parsed.tags ? parseStringList(parsed.tags) : undefined,
100
+ };
101
+ }
102
+ catch (err) {
103
+ if (err instanceof Error && !('code' in err && err.code === 'ENOENT')) {
104
+ console.warn(`[promptwheel] failed to parse formula file ${filePath}: ${err.message}`);
105
+ }
106
+ return null;
107
+ }
108
+ }
109
+ //# sourceMappingURL=formulas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formulas.js","sourceRoot":"","sources":["../src/formulas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Project guidelines loader for MCP advance prompts.
3
+ *
4
+ * Pure resolution logic and formatting live in @promptwheel/core/guidelines/shared.
5
+ * This file wraps them with filesystem I/O.
6
+ */
7
+ import { type ProjectGuidelines, type GuidelinesBackend } from '@promptwheel/core/guidelines/shared';
8
+ export type { ProjectGuidelines } from '@promptwheel/core/guidelines/shared';
9
+ export type { GuidelinesBackend } from '@promptwheel/core/guidelines/shared';
10
+ export { formatGuidelinesForPrompt } from '@promptwheel/core/guidelines/shared';
11
+ export interface GuidelinesOptions {
12
+ backend?: GuidelinesBackend;
13
+ customPath?: string | false | null;
14
+ }
15
+ export declare function loadGuidelines(repoRoot: string, opts?: GuidelinesOptions): ProjectGuidelines | null;
16
+ //# sourceMappingURL=guidelines.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guidelines.d.ts","sourceRoot":"","sources":["../src/guidelines.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EAEvB,MAAM,qCAAqC,CAAC;AAG7C,YAAY,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,YAAY,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AAEhF,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC;CACpC;AAED,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,iBAAsB,GAC3B,iBAAiB,GAAG,IAAI,CAW1B"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Project guidelines loader for MCP advance prompts.
3
+ *
4
+ * Pure resolution logic and formatting live in @promptwheel/core/guidelines/shared.
5
+ * This file wraps them with filesystem I/O.
6
+ */
7
+ import * as fs from 'node:fs';
8
+ import * as path from 'node:path';
9
+ import { resolveGuidelinesPaths, } from '@promptwheel/core/guidelines/shared';
10
+ export { formatGuidelinesForPrompt } from '@promptwheel/core/guidelines/shared';
11
+ export function loadGuidelines(repoRoot, opts = {}) {
12
+ const { backend = 'claude', customPath } = opts;
13
+ if (customPath === false)
14
+ return null;
15
+ if (typeof customPath === 'string') {
16
+ return readGuidelinesFile(repoRoot, customPath);
17
+ }
18
+ const [primaryPaths, fallbackPaths] = resolveGuidelinesPaths(backend);
19
+ return searchPaths(repoRoot, primaryPaths) ?? searchPaths(repoRoot, fallbackPaths);
20
+ }
21
+ function readGuidelinesFile(repoRoot, rel) {
22
+ const full = path.join(repoRoot, rel);
23
+ if (!fs.existsSync(full))
24
+ return null;
25
+ try {
26
+ const content = fs.readFileSync(full, 'utf-8');
27
+ return { content, source: rel, loadedAt: Date.now() };
28
+ }
29
+ catch (err) {
30
+ if (err instanceof Error && !('code' in err && err.code === 'ENOENT')) {
31
+ console.warn(`[promptwheel] failed to read guidelines file ${rel}: ${err.message}`);
32
+ }
33
+ return null;
34
+ }
35
+ }
36
+ function searchPaths(repoRoot, paths) {
37
+ for (const rel of paths) {
38
+ const result = readGuidelinesFile(repoRoot, rel);
39
+ if (result)
40
+ return result;
41
+ }
42
+ return null;
43
+ }
44
+ //# sourceMappingURL=guidelines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guidelines.js","sourceRoot":"","sources":["../src/guidelines.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAGL,sBAAsB,GACvB,MAAM,qCAAqC,CAAC;AAK7C,OAAO,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AAOhF,MAAM,UAAU,cAAc,CAC5B,QAAgB,EAChB,OAA0B,EAAE;IAE5B,MAAM,EAAE,OAAO,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IAEhD,IAAI,UAAU,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IAEtC,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QACnC,OAAO,kBAAkB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,CAAC,YAAY,EAAE,aAAa,CAAC,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACtE,OAAO,WAAW,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,WAAW,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AACrF,CAAC;AAED,SAAS,kBAAkB,CAAC,QAAgB,EAAE,GAAW;IACvD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IACxD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,KAAK,IAAI,CAAC,CAAC,MAAM,IAAI,GAAG,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,CAAC,EAAE,CAAC;YACjG,OAAO,CAAC,IAAI,CAAC,gDAAgD,GAAG,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACtF,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,QAAgB,EAAE,KAAe;IACpD,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACjD,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;IAC5B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @promptwheel/mcp — MCP server entry point
4
+ *
5
+ * Runs as a stdio MCP server for Claude Code.
6
+ * Usage: npx @promptwheel/mcp
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG"}
package/dist/index.js ADDED
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @promptwheel/mcp — MCP server entry point
4
+ *
5
+ * Runs as a stdio MCP server for Claude Code.
6
+ * Usage: npx @promptwheel/mcp
7
+ */
8
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
9
+ import { createSQLiteAdapter } from '@promptwheel/sqlite';
10
+ import { createServer } from './server.js';
11
+ import * as path from 'node:path';
12
+ import * as fs from 'node:fs';
13
+ async function main() {
14
+ const projectPath = process.env.PROMPTWHEEL_PROJECT_PATH ?? process.cwd();
15
+ // Determine DB path
16
+ const bsDir = path.join(projectPath, '.promptwheel');
17
+ if (!fs.existsSync(bsDir)) {
18
+ fs.mkdirSync(bsDir, { recursive: true });
19
+ }
20
+ const dbPath = path.join(bsDir, 'state.sqlite');
21
+ const db = await createSQLiteAdapter({ url: dbPath });
22
+ const { server } = await createServer({
23
+ db,
24
+ projectPath,
25
+ });
26
+ const transport = new StdioServerTransport();
27
+ await server.connect(transport);
28
+ // Graceful shutdown
29
+ process.on('SIGINT', async () => {
30
+ await db.close();
31
+ process.exit(0);
32
+ });
33
+ process.on('SIGTERM', async () => {
34
+ await db.close();
35
+ process.exit(0);
36
+ });
37
+ }
38
+ main().catch((err) => {
39
+ console.error('PromptWheel MCP server failed to start:', err);
40
+ process.exit(1);
41
+ });
42
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,KAAK,UAAU,IAAI;IACjB,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAE1E,oBAAoB;IACpB,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IACrD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;IAEhD,MAAM,EAAE,GAAG,MAAM,mBAAmB,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;IAEtD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,YAAY,CAAC;QACpC,EAAE;QACF,WAAW;KACZ,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,oBAAoB;IACpB,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC9B,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;QAC/B,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,GAAG,CAAC,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Cross-run learning mechanism.
3
+ *
4
+ * Persists learnings to `.promptwheel/learnings.json` and provides
5
+ * decay, consolidation, relevance scoring, and prompt formatting.
6
+ *
7
+ * Pure algorithms live in @promptwheel/core/learnings/shared.
8
+ * This file wraps them with filesystem I/O.
9
+ */
10
+ import { type Learning as CoreLearning, type StructuredKnowledge } from '@promptwheel/core/learnings/shared';
11
+ export type { Learning, StructuredKnowledge } from '@promptwheel/core/learnings/shared';
12
+ export { formatLearningsForPrompt, extractKeywords, selectRelevant, extractTags, LEARNINGS_DEFAULTS, } from '@promptwheel/core/learnings/shared';
13
+ type Learning = CoreLearning;
14
+ /**
15
+ * Load learnings, apply decay, prune dead entries, write back.
16
+ * Called once per session start.
17
+ */
18
+ export declare function loadLearnings(projectRoot: string, decayRate?: number): Learning[];
19
+ /**
20
+ * Add a new learning with sensible defaults.
21
+ */
22
+ export declare function addLearning(projectRoot: string, input: {
23
+ text: string;
24
+ category: Learning['category'];
25
+ source: Learning['source'];
26
+ tags?: string[];
27
+ structured?: StructuredKnowledge;
28
+ }): Learning;
29
+ /**
30
+ * Confirm a learning: bump weight +10 and update last_confirmed_at.
31
+ */
32
+ export declare function confirmLearning(projectRoot: string, id: string): void;
33
+ /**
34
+ * Record access: increment access_count for each id.
35
+ */
36
+ export declare function recordAccess(projectRoot: string, ids: string[]): void;
37
+ /**
38
+ * Consolidate near-duplicate learnings (>70% text similarity).
39
+ * Keeps the higher weight entry, sums access counts.
40
+ */
41
+ export declare function consolidateLearnings(projectRoot: string): void;
42
+ //# sourceMappingURL=learnings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learnings.d.ts","sourceRoot":"","sources":["../src/learnings.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,EACL,KAAK,QAAQ,IAAI,YAAY,EAC7B,KAAK,mBAAmB,EAIzB,MAAM,oCAAoC,CAAC;AAG5C,YAAY,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACxF,OAAO,EACL,wBAAwB,EACxB,eAAe,EACf,cAAc,EACd,WAAW,EACX,kBAAkB,GACnB,MAAM,oCAAoC,CAAC;AAG5C,KAAK,QAAQ,GAAG,YAAY,CAAC;AAsC7B;;;GAGG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,GAAE,MAAsC,GAAG,QAAQ,EAAE,CAKhH;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE;IACL,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC/B,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,mBAAmB,CAAC;CAClC,GACA,QAAQ,CAkBV;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAOrE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,CAUrE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAM9D"}