@promptwheel/core 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 (169) hide show
  1. package/dist/codebase-index/index.d.ts +23 -0
  2. package/dist/codebase-index/index.d.ts.map +1 -0
  3. package/dist/codebase-index/index.js +361 -0
  4. package/dist/codebase-index/index.js.map +1 -0
  5. package/dist/codebase-index/shared.d.ts +95 -0
  6. package/dist/codebase-index/shared.d.ts.map +1 -0
  7. package/dist/codebase-index/shared.js +319 -0
  8. package/dist/codebase-index/shared.js.map +1 -0
  9. package/dist/config/defaults.d.ts +45 -0
  10. package/dist/config/defaults.d.ts.map +1 -0
  11. package/dist/config/defaults.js +79 -0
  12. package/dist/config/defaults.js.map +1 -0
  13. package/dist/critic/shared.d.ts +49 -0
  14. package/dist/critic/shared.d.ts.map +1 -0
  15. package/dist/critic/shared.js +204 -0
  16. package/dist/critic/shared.js.map +1 -0
  17. package/dist/db/adapter.d.ts +191 -0
  18. package/dist/db/adapter.d.ts.map +1 -0
  19. package/dist/db/adapter.js +40 -0
  20. package/dist/db/adapter.js.map +1 -0
  21. package/dist/db/contract.d.ts +47 -0
  22. package/dist/db/contract.d.ts.map +1 -0
  23. package/dist/db/contract.js +258 -0
  24. package/dist/db/contract.js.map +1 -0
  25. package/dist/db/index.d.ts +6 -0
  26. package/dist/db/index.d.ts.map +1 -0
  27. package/dist/db/index.js +7 -0
  28. package/dist/db/index.js.map +1 -0
  29. package/dist/dedup/shared.d.ts +82 -0
  30. package/dist/dedup/shared.d.ts.map +1 -0
  31. package/dist/dedup/shared.js +215 -0
  32. package/dist/dedup/shared.js.map +1 -0
  33. package/dist/exec/index.d.ts +5 -0
  34. package/dist/exec/index.d.ts.map +1 -0
  35. package/dist/exec/index.js +5 -0
  36. package/dist/exec/index.js.map +1 -0
  37. package/dist/exec/types.d.ts +64 -0
  38. package/dist/exec/types.d.ts.map +1 -0
  39. package/dist/exec/types.js +8 -0
  40. package/dist/exec/types.js.map +1 -0
  41. package/dist/formulas/shared.d.ts +42 -0
  42. package/dist/formulas/shared.d.ts.map +1 -0
  43. package/dist/formulas/shared.js +204 -0
  44. package/dist/formulas/shared.js.map +1 -0
  45. package/dist/guidelines/shared.d.ts +46 -0
  46. package/dist/guidelines/shared.d.ts.map +1 -0
  47. package/dist/guidelines/shared.js +128 -0
  48. package/dist/guidelines/shared.js.map +1 -0
  49. package/dist/index.d.ts +35 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +51 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/learnings/shared.d.ts +112 -0
  54. package/dist/learnings/shared.d.ts.map +1 -0
  55. package/dist/learnings/shared.js +402 -0
  56. package/dist/learnings/shared.js.map +1 -0
  57. package/dist/proposals/shared.d.ts +137 -0
  58. package/dist/proposals/shared.d.ts.map +1 -0
  59. package/dist/proposals/shared.js +254 -0
  60. package/dist/proposals/shared.js.map +1 -0
  61. package/dist/repos/index.d.ts +15 -0
  62. package/dist/repos/index.d.ts.map +1 -0
  63. package/dist/repos/index.js +11 -0
  64. package/dist/repos/index.js.map +1 -0
  65. package/dist/repos/projects.d.ts +41 -0
  66. package/dist/repos/projects.d.ts.map +1 -0
  67. package/dist/repos/projects.js +75 -0
  68. package/dist/repos/projects.js.map +1 -0
  69. package/dist/repos/run_steps.d.ts +152 -0
  70. package/dist/repos/run_steps.d.ts.map +1 -0
  71. package/dist/repos/run_steps.js +328 -0
  72. package/dist/repos/run_steps.js.map +1 -0
  73. package/dist/repos/runs.d.ts +92 -0
  74. package/dist/repos/runs.d.ts.map +1 -0
  75. package/dist/repos/runs.js +185 -0
  76. package/dist/repos/runs.js.map +1 -0
  77. package/dist/repos/tickets.d.ts +71 -0
  78. package/dist/repos/tickets.d.ts.map +1 -0
  79. package/dist/repos/tickets.js +158 -0
  80. package/dist/repos/tickets.js.map +1 -0
  81. package/dist/scope/shared.d.ts +67 -0
  82. package/dist/scope/shared.d.ts.map +1 -0
  83. package/dist/scope/shared.js +355 -0
  84. package/dist/scope/shared.js.map +1 -0
  85. package/dist/scout/index.d.ts +18 -0
  86. package/dist/scout/index.d.ts.map +1 -0
  87. package/dist/scout/index.js +445 -0
  88. package/dist/scout/index.js.map +1 -0
  89. package/dist/scout/kimi-runner.d.ts +21 -0
  90. package/dist/scout/kimi-runner.d.ts.map +1 -0
  91. package/dist/scout/kimi-runner.js +76 -0
  92. package/dist/scout/kimi-runner.js.map +1 -0
  93. package/dist/scout/mcp-batch-server.d.ts +37 -0
  94. package/dist/scout/mcp-batch-server.d.ts.map +1 -0
  95. package/dist/scout/mcp-batch-server.js +144 -0
  96. package/dist/scout/mcp-batch-server.js.map +1 -0
  97. package/dist/scout/openai-local-runner.d.ts +20 -0
  98. package/dist/scout/openai-local-runner.d.ts.map +1 -0
  99. package/dist/scout/openai-local-runner.js +82 -0
  100. package/dist/scout/openai-local-runner.js.map +1 -0
  101. package/dist/scout/prompt.d.ts +49 -0
  102. package/dist/scout/prompt.d.ts.map +1 -0
  103. package/dist/scout/prompt.js +153 -0
  104. package/dist/scout/prompt.js.map +1 -0
  105. package/dist/scout/runner.d.ts +101 -0
  106. package/dist/scout/runner.d.ts.map +1 -0
  107. package/dist/scout/runner.js +521 -0
  108. package/dist/scout/runner.js.map +1 -0
  109. package/dist/scout/scanner.d.ts +61 -0
  110. package/dist/scout/scanner.d.ts.map +1 -0
  111. package/dist/scout/scanner.js +315 -0
  112. package/dist/scout/scanner.js.map +1 -0
  113. package/dist/scout/types.d.ts +221 -0
  114. package/dist/scout/types.d.ts.map +1 -0
  115. package/dist/scout/types.js +44 -0
  116. package/dist/scout/types.js.map +1 -0
  117. package/dist/sectors/shared.d.ts +146 -0
  118. package/dist/sectors/shared.d.ts.map +1 -0
  119. package/dist/sectors/shared.js +408 -0
  120. package/dist/sectors/shared.js.map +1 -0
  121. package/dist/services/index.d.ts +10 -0
  122. package/dist/services/index.d.ts.map +1 -0
  123. package/dist/services/index.js +9 -0
  124. package/dist/services/index.js.map +1 -0
  125. package/dist/services/qa.d.ts +76 -0
  126. package/dist/services/qa.d.ts.map +1 -0
  127. package/dist/services/qa.js +228 -0
  128. package/dist/services/qa.js.map +1 -0
  129. package/dist/services/scout.d.ts +164 -0
  130. package/dist/services/scout.d.ts.map +1 -0
  131. package/dist/services/scout.js +215 -0
  132. package/dist/services/scout.js.map +1 -0
  133. package/dist/spindle/shared.d.ts +14 -0
  134. package/dist/spindle/shared.d.ts.map +1 -0
  135. package/dist/spindle/shared.js +65 -0
  136. package/dist/spindle/shared.js.map +1 -0
  137. package/dist/tools/shared.d.ts +35 -0
  138. package/dist/tools/shared.d.ts.map +1 -0
  139. package/dist/tools/shared.js +247 -0
  140. package/dist/tools/shared.js.map +1 -0
  141. package/dist/trace/shared.d.ts +147 -0
  142. package/dist/trace/shared.d.ts.map +1 -0
  143. package/dist/trace/shared.js +414 -0
  144. package/dist/trace/shared.js.map +1 -0
  145. package/dist/trajectory/shared.d.ts +69 -0
  146. package/dist/trajectory/shared.d.ts.map +1 -0
  147. package/dist/trajectory/shared.js +336 -0
  148. package/dist/trajectory/shared.js.map +1 -0
  149. package/dist/utils/id.d.ts +12 -0
  150. package/dist/utils/id.d.ts.map +1 -0
  151. package/dist/utils/id.js +24 -0
  152. package/dist/utils/id.js.map +1 -0
  153. package/dist/utils/id.test.d.ts +5 -0
  154. package/dist/utils/id.test.d.ts.map +1 -0
  155. package/dist/utils/id.test.js +173 -0
  156. package/dist/utils/id.test.js.map +1 -0
  157. package/dist/utils/index.d.ts +6 -0
  158. package/dist/utils/index.d.ts.map +1 -0
  159. package/dist/utils/index.js +6 -0
  160. package/dist/utils/index.js.map +1 -0
  161. package/dist/utils/json.d.ts +9 -0
  162. package/dist/utils/json.d.ts.map +1 -0
  163. package/dist/utils/json.js +19 -0
  164. package/dist/utils/json.js.map +1 -0
  165. package/dist/waves/shared.d.ts +106 -0
  166. package/dist/waves/shared.d.ts.map +1 -0
  167. package/dist/waves/shared.js +356 -0
  168. package/dist/waves/shared.js.map +1 -0
  169. package/package.json +126 -0
@@ -0,0 +1,215 @@
1
+ /**
2
+ * Scout Service - Orchestrates codebase scanning and ticket creation
3
+ *
4
+ * This is pure orchestration - it coordinates between:
5
+ * - File scanning (scanner.ts)
6
+ * - LLM analysis (runner.ts)
7
+ * - Data persistence (repos/*)
8
+ *
9
+ * It accepts dependencies via ScoutDeps, making it testable and adapter-agnostic.
10
+ */
11
+ import * as projects from '../repos/projects.js';
12
+ import * as tickets from '../repos/tickets.js';
13
+ import * as runs from '../repos/runs.js';
14
+ import { scout as scanAndPropose, } from '../scout/index.js';
15
+ /**
16
+ * Scout a repository for improvement opportunities
17
+ *
18
+ * This is the main entry point for the scout service. It:
19
+ * 1. Resolves the repository root
20
+ * 2. Ensures the project exists in the database
21
+ * 3. Creates a scout run
22
+ * 4. Scans files and generates proposals
23
+ * 5. Optionally creates tickets from proposals
24
+ * 6. Records the run outcome
25
+ */
26
+ export async function scoutRepo(deps, opts = {}) {
27
+ const { db, git, logger } = deps;
28
+ const startTime = Date.now();
29
+ const errors = [];
30
+ const report = (progress) => {
31
+ opts.onProgress?.({
32
+ phase: 'init',
33
+ ...progress,
34
+ });
35
+ };
36
+ // Phase 1: Resolve repository
37
+ report({ phase: 'init', message: 'Resolving repository...' });
38
+ const targetPath = opts.path ?? process.cwd();
39
+ const repoRoot = await git.findRepoRoot(targetPath);
40
+ if (!repoRoot) {
41
+ throw new Error(`Not a git repository: ${targetPath}`);
42
+ }
43
+ const remoteUrl = await git.getRemoteUrl(repoRoot);
44
+ const projectId = git.getProjectId(repoRoot, remoteUrl);
45
+ logger?.debug('Resolved repository', { repoRoot, remoteUrl, projectId });
46
+ // Phase 2: Ensure project exists
47
+ const project = await projects.ensureForRepo(db, {
48
+ id: projectId,
49
+ name: repoRoot.split('/').pop() || 'unknown',
50
+ repoUrl: remoteUrl,
51
+ rootPath: repoRoot,
52
+ });
53
+ logger?.info('Project ensured', { projectId: project.id, name: project.name });
54
+ // Phase 3: Create scout run
55
+ const run = await runs.create(db, {
56
+ projectId: project.id,
57
+ type: 'scout',
58
+ metadata: {
59
+ scope: opts.scope ?? 'src/**',
60
+ maxProposals: opts.maxProposals ?? 10,
61
+ model: opts.model ?? (opts.backend ? undefined : 'opus'),
62
+ },
63
+ });
64
+ logger?.debug('Scout run created', { runId: run.id });
65
+ try {
66
+ // Phase 4: Get dedup context
67
+ const recentTickets = await tickets.getRecentlyCompleted(db, project.id, 20);
68
+ const recentTitles = recentTickets.map(t => t.title);
69
+ // Phase 5: Scan and generate proposals
70
+ report({ phase: 'scanning', message: 'Scanning files...' });
71
+ const scanResult = await scanAndPropose({
72
+ scope: opts.scope ?? 'src/**',
73
+ types: opts.types,
74
+ excludeTypes: opts.excludeTypes,
75
+ maxProposals: opts.maxProposals ?? 10,
76
+ minConfidence: opts.minConfidence ?? 50,
77
+ projectPath: repoRoot,
78
+ model: opts.model ?? (opts.backend ? undefined : 'opus'),
79
+ timeoutMs: opts.timeoutMs ?? 120000,
80
+ signal: opts.signal,
81
+ recentlyCompletedTitles: recentTitles,
82
+ customPrompt: opts.customPrompt,
83
+ backend: opts.backend,
84
+ protectedFiles: opts.protectedFiles,
85
+ batchTokenBudget: opts.batchTokenBudget,
86
+ maxFiles: opts.maxFiles,
87
+ scoutConcurrency: opts.scoutConcurrency,
88
+ moduleGroups: opts.moduleGroups,
89
+ coverageContext: opts.coverageContext,
90
+ onRawOutput: opts.onRawOutput,
91
+ onProgress: (p) => {
92
+ report({
93
+ phase: 'analyzing',
94
+ filesScanned: p.filesScanned,
95
+ totalFiles: p.totalFiles,
96
+ proposalsFound: p.proposalsFound,
97
+ message: `Analyzing batch ${p.currentBatch}/${p.totalBatches}`,
98
+ batchStatuses: p.batchStatuses,
99
+ totalBatches: p.totalBatches,
100
+ });
101
+ },
102
+ });
103
+ if (!scanResult.success) {
104
+ errors.push(...scanResult.errors);
105
+ }
106
+ logger?.info('Scan complete', {
107
+ files: scanResult.scannedFiles,
108
+ proposals: scanResult.proposals.length,
109
+ });
110
+ // Phase 6: Create tickets if auto-approve
111
+ const createdTickets = [];
112
+ if (opts.autoApprove && scanResult.proposals.length > 0) {
113
+ report({
114
+ phase: 'storing',
115
+ proposalsFound: scanResult.proposals.length,
116
+ message: 'Creating tickets...',
117
+ });
118
+ const ticketInputs = scanResult.proposals.map(proposal => ({
119
+ projectId: project.id,
120
+ title: proposal.title,
121
+ description: formatProposalDescription(proposal),
122
+ status: 'ready',
123
+ priority: proposal.confidence,
124
+ category: proposal.category,
125
+ allowedPaths: proposal.allowed_paths,
126
+ verificationCommands: proposal.verification_commands,
127
+ }));
128
+ const created = await tickets.createMany(db, ticketInputs);
129
+ createdTickets.push(...created);
130
+ logger?.info('Tickets created', { count: created.length });
131
+ }
132
+ // Phase 7: Mark run success
133
+ await runs.markSuccess(db, run.id, {
134
+ scannedFiles: scanResult.scannedFiles,
135
+ proposalCount: scanResult.proposals.length,
136
+ ticketCount: createdTickets.length,
137
+ durationMs: Date.now() - startTime,
138
+ });
139
+ report({
140
+ phase: 'complete',
141
+ filesScanned: scanResult.scannedFiles,
142
+ proposalsFound: scanResult.proposals.length,
143
+ ticketsCreated: createdTickets.length,
144
+ });
145
+ return {
146
+ success: true,
147
+ project,
148
+ run: (await runs.getById(db, run.id)),
149
+ proposals: scanResult.proposals,
150
+ tickets: createdTickets,
151
+ errors: scanResult.errors,
152
+ scannedFiles: scanResult.scannedFiles,
153
+ durationMs: Date.now() - startTime,
154
+ sectorReclassification: scanResult.sectorReclassification,
155
+ };
156
+ }
157
+ catch (error) {
158
+ // Mark run as failed
159
+ await runs.markFailure(db, run.id, error, {
160
+ durationMs: Date.now() - startTime,
161
+ });
162
+ logger?.error('Scout failed', { error: error.message });
163
+ return {
164
+ success: false,
165
+ project,
166
+ run: (await runs.getById(db, run.id)),
167
+ proposals: [],
168
+ tickets: [],
169
+ errors: [...errors, error.message],
170
+ scannedFiles: 0,
171
+ durationMs: Date.now() - startTime,
172
+ };
173
+ }
174
+ }
175
+ /**
176
+ * Format a proposal into ticket description markdown
177
+ */
178
+ function formatProposalDescription(proposal) {
179
+ const parts = [
180
+ proposal.description,
181
+ '',
182
+ '## Acceptance Criteria',
183
+ ...proposal.acceptance_criteria.map(c => `- ${c}`),
184
+ '',
185
+ '## Rationale',
186
+ proposal.rationale,
187
+ '',
188
+ '## Files',
189
+ ...proposal.files.map(f => `- \`${f}\``),
190
+ '',
191
+ `**Complexity:** ${proposal.estimated_complexity}`,
192
+ `**Confidence:** ${proposal.confidence}%`,
193
+ ];
194
+ return parts.join('\n');
195
+ }
196
+ /**
197
+ * Approve specific proposals and create tickets
198
+ */
199
+ export async function approveProposals(deps, projectId, proposals) {
200
+ const { db, logger } = deps;
201
+ const ticketInputs = proposals.map(proposal => ({
202
+ projectId,
203
+ title: proposal.title,
204
+ description: formatProposalDescription(proposal),
205
+ status: 'ready',
206
+ priority: proposal.confidence,
207
+ category: proposal.category,
208
+ allowedPaths: proposal.allowed_paths,
209
+ verificationCommands: proposal.verification_commands,
210
+ }));
211
+ const created = await tickets.createMany(db, ticketInputs);
212
+ logger?.info('Proposals approved', { count: created.length });
213
+ return created;
214
+ }
215
+ //# sourceMappingURL=scout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scout.js","sourceRoot":"","sources":["../../src/services/scout.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Shared Spindle detection functions used by both CLI and MCP spindle.
3
+ */
4
+ /** Short hash for signature tracking */
5
+ export declare function shortHash(s: string): string;
6
+ /** Detect alternating failure signatures: A→B→A→B pattern */
7
+ export declare function detectQaPingPong(sigs: string[], cycles: number): string | null;
8
+ /** Detect same command failing N times */
9
+ export declare function detectCommandFailure(sigs: string[], threshold: number): string | null;
10
+ /** Extract file paths from a unified diff */
11
+ export declare function extractFilesFromDiff(diff: string): string[];
12
+ /** Get file edit frequency warnings (state-shape-agnostic) */
13
+ export declare function getFileEditWarnings(counts: Record<string, number>, threshold?: number): string[];
14
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/spindle/shared.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wCAAwC;AACxC,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,6DAA6D;AAC7D,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsB9E;AAED,0CAA0C;AAC1C,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAarF;AAED,6CAA6C;AAC7C,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ3D;AAED,8DAA8D;AAC9D,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAE,MAAU,GAAG,MAAM,EAAE,CAQnG"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Shared Spindle detection functions used by both CLI and MCP spindle.
3
+ */
4
+ import { createHash } from 'node:crypto';
5
+ /** Short hash for signature tracking */
6
+ export function shortHash(s) {
7
+ return createHash('sha256').update(s).digest('hex').slice(0, 12);
8
+ }
9
+ /** Detect alternating failure signatures: A→B→A→B pattern */
10
+ export function detectQaPingPong(sigs, cycles) {
11
+ if (sigs.length < cycles * 2)
12
+ return null;
13
+ const recent = sigs.slice(-(cycles * 2));
14
+ const a = recent[0];
15
+ const b = recent[1];
16
+ if (a === b)
17
+ return null;
18
+ let alternating = true;
19
+ for (let i = 0; i < recent.length; i++) {
20
+ const expected = i % 2 === 0 ? a : b;
21
+ if (recent[i] !== expected) {
22
+ alternating = false;
23
+ break;
24
+ }
25
+ }
26
+ if (alternating) {
27
+ return `Alternating failures: ${a} ↔ ${b} (${cycles} cycles)`;
28
+ }
29
+ return null;
30
+ }
31
+ /** Detect same command failing N times */
32
+ export function detectCommandFailure(sigs, threshold) {
33
+ if (sigs.length < threshold)
34
+ return null;
35
+ const counts = new Map();
36
+ for (const sig of sigs) {
37
+ counts.set(sig, (counts.get(sig) ?? 0) + 1);
38
+ }
39
+ for (const [sig, count] of counts) {
40
+ if (count >= threshold)
41
+ return sig;
42
+ }
43
+ return null;
44
+ }
45
+ /** Extract file paths from a unified diff */
46
+ export function extractFilesFromDiff(diff) {
47
+ const files = [];
48
+ for (const line of diff.split('\n')) {
49
+ if (line.startsWith('+++ b/')) {
50
+ files.push(line.slice(6));
51
+ }
52
+ }
53
+ return files;
54
+ }
55
+ /** Get file edit frequency warnings (state-shape-agnostic) */
56
+ export function getFileEditWarnings(counts, threshold = 3) {
57
+ const warnings = [];
58
+ for (const [file, count] of Object.entries(counts)) {
59
+ if (count >= threshold) {
60
+ warnings.push(`${file} edited ${count} times`);
61
+ }
62
+ }
63
+ return warnings;
64
+ }
65
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/spindle/shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Tool Registry — pure types, built-in specs, and filtering algorithms.
3
+ *
4
+ * Replaces hardcoded auto-approve arrays with a queryable set of tool specs.
5
+ * No I/O — the ToolRegistry class in @promptwheel/mcp handles custom tool loading.
6
+ */
7
+ export type TrustLevel = 'safe' | 'default' | 'full';
8
+ export type ToolPhase = 'SCOUT' | 'PLAN' | 'EXECUTE' | 'QA' | 'PR';
9
+ export interface ToolSpec {
10
+ name: string;
11
+ description: string;
12
+ approve_patterns: string[];
13
+ phase_access: ToolPhase[];
14
+ trust_levels: TrustLevel[];
15
+ category_access: string[] | null;
16
+ constraint_note?: string;
17
+ custom?: boolean;
18
+ }
19
+ export declare const BUILTIN_TOOL_SPECS: ToolSpec[];
20
+ /**
21
+ * Filter tool specs by phase, category, and trust level.
22
+ * Category-specific tools (e.g. Edit:docs) exclude their generic counterpart
23
+ * (Edit) for that category to prevent overly-broad auto-approve.
24
+ */
25
+ export declare function filterToolSpecs(specs: ToolSpec[], phase: ToolPhase, category: string | null, trustLevel?: TrustLevel): ToolSpec[];
26
+ /**
27
+ * Collect all auto-approve patterns from a set of filtered specs.
28
+ */
29
+ export declare function collectApprovePatterns(specs: ToolSpec[]): string[];
30
+ /**
31
+ * Collect constraint notes from filtered specs.
32
+ * Returns undefined if no constraint notes exist.
33
+ */
34
+ export declare function collectConstraintNotes(specs: ToolSpec[]): string | undefined;
35
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/tools/shared.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AACrD,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnE,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,EAAE,SAAS,EAAE,CAAC;IAC1B,YAAY,EAAE,UAAU,EAAE,CAAC;IAC3B,eAAe,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAUD,eAAO,MAAM,kBAAkB,EAAE,QAAQ,EA6KxC,CAAC;AAMF;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,QAAQ,EAAE,EACjB,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,UAAU,GAAE,UAAsB,GACjC,QAAQ,EAAE,CAoCZ;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,EAAE,CAUlE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,GAAG,SAAS,CAK5E"}
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Tool Registry — pure types, built-in specs, and filtering algorithms.
3
+ *
4
+ * Replaces hardcoded auto-approve arrays with a queryable set of tool specs.
5
+ * No I/O — the ToolRegistry class in @promptwheel/mcp handles custom tool loading.
6
+ */
7
+ // ---------------------------------------------------------------------------
8
+ // Built-in tool specs (reproducing current hardcoded behavior exactly)
9
+ // ---------------------------------------------------------------------------
10
+ const ALL_PHASES = ['SCOUT', 'PLAN', 'EXECUTE', 'QA', 'PR'];
11
+ const ALL_TRUST = ['safe', 'default', 'full'];
12
+ const DEFAULT_PLUS = ['default', 'full'];
13
+ export const BUILTIN_TOOL_SPECS = [
14
+ // Read-only tools — all phases, all trust
15
+ {
16
+ name: 'Read',
17
+ description: 'Read file contents',
18
+ approve_patterns: ['Read(*)'],
19
+ phase_access: ALL_PHASES,
20
+ trust_levels: ALL_TRUST,
21
+ category_access: null,
22
+ },
23
+ {
24
+ name: 'Glob',
25
+ description: 'Search for files by pattern',
26
+ approve_patterns: ['Glob(*)'],
27
+ phase_access: ALL_PHASES,
28
+ trust_levels: ALL_TRUST,
29
+ category_access: null,
30
+ },
31
+ {
32
+ name: 'Grep',
33
+ description: 'Search file contents',
34
+ approve_patterns: ['Grep(*)'],
35
+ phase_access: ALL_PHASES,
36
+ trust_levels: ALL_TRUST,
37
+ category_access: null,
38
+ },
39
+ // Scout/Plan bash — read-only commands
40
+ {
41
+ name: 'Bash:scout',
42
+ description: 'Read-only shell commands for scouting',
43
+ approve_patterns: ['Bash(ls *)', 'Bash(find *)', 'Bash(cat *)', 'Bash(head *)', 'Bash(wc *)'],
44
+ phase_access: ['SCOUT', 'PLAN'],
45
+ trust_levels: ALL_TRUST,
46
+ category_access: null,
47
+ },
48
+ // Generic Edit/Write — EXECUTE only, default+ trust
49
+ {
50
+ name: 'Edit',
51
+ description: 'Edit files (generic)',
52
+ approve_patterns: ['Edit(*)'],
53
+ phase_access: ['EXECUTE'],
54
+ trust_levels: DEFAULT_PLUS,
55
+ category_access: null,
56
+ },
57
+ {
58
+ name: 'Write',
59
+ description: 'Write files (generic)',
60
+ approve_patterns: ['Write(*)'],
61
+ phase_access: ['EXECUTE'],
62
+ trust_levels: DEFAULT_PLUS,
63
+ category_access: null,
64
+ },
65
+ // Docs Edit/Write — narrowed patterns, safe+ trust
66
+ {
67
+ name: 'Edit:docs',
68
+ description: 'Edit documentation files only',
69
+ approve_patterns: ['Edit(*.md)', 'Edit(*.mdx)', 'Edit(*.txt)', 'Edit(*.rst)'],
70
+ phase_access: ['EXECUTE'],
71
+ trust_levels: ALL_TRUST,
72
+ category_access: ['docs'],
73
+ },
74
+ {
75
+ name: 'Write:docs',
76
+ description: 'Write documentation files only',
77
+ approve_patterns: ['Write(*.md)', 'Write(*.mdx)', 'Write(*.txt)', 'Write(*.rst)'],
78
+ phase_access: ['EXECUTE'],
79
+ trust_levels: ALL_TRUST,
80
+ category_access: ['docs'],
81
+ },
82
+ // Test Edit/Write — narrowed patterns, safe+ trust
83
+ {
84
+ name: 'Edit:test',
85
+ description: 'Edit test files only',
86
+ approve_patterns: [
87
+ 'Edit(*.test.*)', 'Edit(*.spec.*)', 'Edit(*__tests__*)',
88
+ 'Edit(test_*)', 'Edit(*_test.go)', 'Edit(*_test.py)', 'Edit(*Test.java)', 'Edit(*Test.kt)',
89
+ 'Edit(*_test.exs)', 'Edit(*Tests.swift)', 'Edit(*_spec.rb)',
90
+ ],
91
+ phase_access: ['EXECUTE'],
92
+ trust_levels: ALL_TRUST,
93
+ category_access: ['test'],
94
+ },
95
+ {
96
+ name: 'Write:test',
97
+ description: 'Write test files only',
98
+ approve_patterns: [
99
+ 'Write(*.test.*)', 'Write(*.spec.*)', 'Write(*__tests__*)',
100
+ 'Write(test_*)', 'Write(*_test.go)', 'Write(*_test.py)', 'Write(*Test.java)', 'Write(*Test.kt)',
101
+ 'Write(*_test.exs)', 'Write(*Tests.swift)', 'Write(*_spec.rb)',
102
+ ],
103
+ phase_access: ['EXECUTE'],
104
+ trust_levels: ALL_TRUST,
105
+ category_access: ['test'],
106
+ },
107
+ // Test/build commands — EXECUTE + QA
108
+ {
109
+ name: 'Bash:test',
110
+ description: 'Run tests and type checks',
111
+ approve_patterns: [
112
+ // JS/TS
113
+ 'Bash(npm test*)', 'Bash(npx vitest*)', 'Bash(npx jest*)', 'Bash(npx tsc*)',
114
+ 'Bash(yarn test*)', 'Bash(pnpm test*)', 'Bash(bun test*)',
115
+ // Python
116
+ 'Bash(pytest*)', 'Bash(python -m pytest*)', 'Bash(tox*)', 'Bash(python -m unittest*)',
117
+ // Rust
118
+ 'Bash(cargo test*)', 'Bash(cargo check*)', 'Bash(cargo clippy*)',
119
+ // Go
120
+ 'Bash(go test*)', 'Bash(go vet*)',
121
+ // Java/Kotlin
122
+ 'Bash(mvn test*)', 'Bash(./gradlew test*)', 'Bash(gradle test*)',
123
+ // Ruby
124
+ 'Bash(bundle exec rspec*)', 'Bash(bundle exec rake test*)',
125
+ // Elixir
126
+ 'Bash(mix test*)',
127
+ // .NET
128
+ 'Bash(dotnet test*)',
129
+ // PHP
130
+ 'Bash(./vendor/bin/phpunit*)', 'Bash(phpunit*)',
131
+ // Swift
132
+ 'Bash(swift test*)',
133
+ // Make
134
+ 'Bash(make test*)', 'Bash(make check*)',
135
+ ],
136
+ phase_access: ['EXECUTE', 'QA'],
137
+ trust_levels: ALL_TRUST,
138
+ category_access: null,
139
+ },
140
+ // Git status — EXECUTE + QA
141
+ {
142
+ name: 'Bash:git-status',
143
+ description: 'Git diff and status commands',
144
+ approve_patterns: ['Bash(git diff*)', 'Bash(git status*)'],
145
+ phase_access: ['EXECUTE', 'QA'],
146
+ trust_levels: ALL_TRUST,
147
+ category_access: null,
148
+ },
149
+ // Git operations — PR phase
150
+ {
151
+ name: 'Bash:git-ops',
152
+ description: 'Git operations for PR creation',
153
+ approve_patterns: ['Bash(git *)'],
154
+ phase_access: ['PR'],
155
+ trust_levels: DEFAULT_PLUS,
156
+ category_access: null,
157
+ },
158
+ // GitHub CLI — PR phase
159
+ {
160
+ name: 'Bash:gh',
161
+ description: 'GitHub CLI for PR creation',
162
+ approve_patterns: ['Bash(gh pr *)'],
163
+ phase_access: ['PR'],
164
+ trust_levels: DEFAULT_PLUS,
165
+ category_access: null,
166
+ },
167
+ // Security constraint (no patterns, just a constraint note)
168
+ {
169
+ name: 'constraint:security',
170
+ description: 'Security ticket constraints',
171
+ approve_patterns: [],
172
+ phase_access: ['EXECUTE'],
173
+ trust_levels: ALL_TRUST,
174
+ category_access: ['security'],
175
+ constraint_note: 'This is a **security** ticket. You have full read/edit access but MUST NOT install new dependencies (`npm install`, `pip install`, `cargo add`, `go get`, `bundle add`, `composer require`, etc.). Do NOT run arbitrary shell commands beyond testing and type-checking.',
176
+ },
177
+ ];
178
+ // ---------------------------------------------------------------------------
179
+ // Filtering
180
+ // ---------------------------------------------------------------------------
181
+ /**
182
+ * Filter tool specs by phase, category, and trust level.
183
+ * Category-specific tools (e.g. Edit:docs) exclude their generic counterpart
184
+ * (Edit) for that category to prevent overly-broad auto-approve.
185
+ */
186
+ export function filterToolSpecs(specs, phase, category, trustLevel = 'default') {
187
+ const trustOrder = { safe: 0, default: 1, full: 2 };
188
+ const requestedLevel = trustOrder[trustLevel];
189
+ // First pass: find which generic tools have category-specific overrides
190
+ const categoryOverrides = new Set();
191
+ for (const spec of specs) {
192
+ if (spec.category_access !== null && category && spec.category_access.includes(category)) {
193
+ // e.g., Edit:docs → overrides 'Edit'
194
+ const baseName = spec.name.split(':')[0];
195
+ categoryOverrides.add(baseName);
196
+ }
197
+ }
198
+ return specs.filter(spec => {
199
+ // Phase check
200
+ if (!spec.phase_access.includes(phase))
201
+ return false;
202
+ // Trust level check
203
+ const minLevel = trustOrder[spec.trust_levels[0]];
204
+ if (requestedLevel < minLevel)
205
+ return false;
206
+ // Category check
207
+ if (spec.category_access !== null) {
208
+ if (!category || !spec.category_access.includes(category))
209
+ return false;
210
+ }
211
+ else {
212
+ // Generic tool — exclude if a category-specific override exists
213
+ const baseName = spec.name.split(':')[0];
214
+ if (categoryOverrides.has(baseName) && !spec.name.includes(':')) {
215
+ // Only exclude Edit/Write, not Read/Glob/Grep/Bash
216
+ if (baseName === 'Edit' || baseName === 'Write')
217
+ return false;
218
+ }
219
+ }
220
+ return true;
221
+ });
222
+ }
223
+ /**
224
+ * Collect all auto-approve patterns from a set of filtered specs.
225
+ */
226
+ export function collectApprovePatterns(specs) {
227
+ const patterns = [];
228
+ for (const spec of specs) {
229
+ for (const p of spec.approve_patterns) {
230
+ if (!patterns.includes(p)) {
231
+ patterns.push(p);
232
+ }
233
+ }
234
+ }
235
+ return patterns;
236
+ }
237
+ /**
238
+ * Collect constraint notes from filtered specs.
239
+ * Returns undefined if no constraint notes exist.
240
+ */
241
+ export function collectConstraintNotes(specs) {
242
+ const notes = specs
243
+ .filter(s => s.constraint_note)
244
+ .map(s => s.constraint_note);
245
+ return notes.length > 0 ? notes.join('\n\n') : undefined;
246
+ }
247
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/tools/shared.ts"],"names":[],"mappings":"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"}