@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.
- package/README.md +178 -0
- package/dist/advance-helpers.d.ts +27 -0
- package/dist/advance-helpers.d.ts.map +1 -0
- package/dist/advance-helpers.js +127 -0
- package/dist/advance-helpers.js.map +1 -0
- package/dist/advance-prompts.d.ts +48 -0
- package/dist/advance-prompts.d.ts.map +1 -0
- package/dist/advance-prompts.js +420 -0
- package/dist/advance-prompts.js.map +1 -0
- package/dist/advance.d.ts +30 -0
- package/dist/advance.d.ts.map +1 -0
- package/dist/advance.js +752 -0
- package/dist/advance.js.map +1 -0
- package/dist/codebase-index.d.ts +5 -0
- package/dist/codebase-index.d.ts.map +1 -0
- package/dist/codebase-index.js +5 -0
- package/dist/codebase-index.js.map +1 -0
- package/dist/dedup-memory.d.ts +30 -0
- package/dist/dedup-memory.d.ts.map +1 -0
- package/dist/dedup-memory.js +76 -0
- package/dist/dedup-memory.js.map +1 -0
- package/dist/direct-client.d.ts +57 -0
- package/dist/direct-client.d.ts.map +1 -0
- package/dist/direct-client.js +92 -0
- package/dist/direct-client.js.map +1 -0
- package/dist/event-handlers-qa.d.ts +5 -0
- package/dist/event-handlers-qa.d.ts.map +1 -0
- package/dist/event-handlers-qa.js +186 -0
- package/dist/event-handlers-qa.js.map +1 -0
- package/dist/event-handlers-scout.d.ts +5 -0
- package/dist/event-handlers-scout.d.ts.map +1 -0
- package/dist/event-handlers-scout.js +270 -0
- package/dist/event-handlers-scout.js.map +1 -0
- package/dist/event-handlers-ticket.d.ts +5 -0
- package/dist/event-handlers-ticket.d.ts.map +1 -0
- package/dist/event-handlers-ticket.js +232 -0
- package/dist/event-handlers-ticket.js.map +1 -0
- package/dist/event-helpers.d.ts +46 -0
- package/dist/event-helpers.d.ts.map +1 -0
- package/dist/event-helpers.js +125 -0
- package/dist/event-helpers.js.map +1 -0
- package/dist/event-processor.d.ts +15 -0
- package/dist/event-processor.d.ts.map +1 -0
- package/dist/event-processor.js +111 -0
- package/dist/event-processor.js.map +1 -0
- package/dist/formulas.d.ts +27 -0
- package/dist/formulas.d.ts.map +1 -0
- package/dist/formulas.js +109 -0
- package/dist/formulas.js.map +1 -0
- package/dist/guidelines.d.ts +16 -0
- package/dist/guidelines.d.ts.map +1 -0
- package/dist/guidelines.js +44 -0
- package/dist/guidelines.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/learnings.d.ts +42 -0
- package/dist/learnings.d.ts.map +1 -0
- package/dist/learnings.js +117 -0
- package/dist/learnings.js.map +1 -0
- package/dist/project-metadata.d.ts +34 -0
- package/dist/project-metadata.d.ts.map +1 -0
- package/dist/project-metadata.js +617 -0
- package/dist/project-metadata.js.map +1 -0
- package/dist/proposals.d.ts +23 -0
- package/dist/proposals.d.ts.map +1 -0
- package/dist/proposals.js +201 -0
- package/dist/proposals.js.map +1 -0
- package/dist/qa-stats.d.ts +51 -0
- package/dist/qa-stats.d.ts.map +1 -0
- package/dist/qa-stats.js +121 -0
- package/dist/qa-stats.js.map +1 -0
- package/dist/run-manager.d.ts +97 -0
- package/dist/run-manager.d.ts.map +1 -0
- package/dist/run-manager.js +583 -0
- package/dist/run-manager.js.map +1 -0
- package/dist/run-state-bridge.d.ts +13 -0
- package/dist/run-state-bridge.d.ts.map +1 -0
- package/dist/run-state-bridge.js +101 -0
- package/dist/run-state-bridge.js.map +1 -0
- package/dist/scope-policy.d.ts +83 -0
- package/dist/scope-policy.d.ts.map +1 -0
- package/dist/scope-policy.js +278 -0
- package/dist/scope-policy.js.map +1 -0
- package/dist/server.d.ts +18 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +35 -0
- package/dist/server.js.map +1 -0
- package/dist/spindle.d.ts +41 -0
- package/dist/spindle.d.ts.map +1 -0
- package/dist/spindle.js +230 -0
- package/dist/spindle.js.map +1 -0
- package/dist/state.d.ts +36 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +50 -0
- package/dist/state.js.map +1 -0
- package/dist/ticket-worker.d.ts +37 -0
- package/dist/ticket-worker.d.ts.map +1 -0
- package/dist/ticket-worker.js +527 -0
- package/dist/ticket-worker.js.map +1 -0
- package/dist/tool-registry.d.ts +35 -0
- package/dist/tool-registry.d.ts.map +1 -0
- package/dist/tool-registry.js +129 -0
- package/dist/tool-registry.js.map +1 -0
- package/dist/tools/execute.d.ts +17 -0
- package/dist/tools/execute.d.ts.map +1 -0
- package/dist/tools/execute.js +418 -0
- package/dist/tools/execute.js.map +1 -0
- package/dist/tools/git.d.ts +7 -0
- package/dist/tools/git.d.ts.map +1 -0
- package/dist/tools/git.js +98 -0
- package/dist/tools/git.js.map +1 -0
- package/dist/tools/intelligence.d.ts +10 -0
- package/dist/tools/intelligence.d.ts.map +1 -0
- package/dist/tools/intelligence.js +432 -0
- package/dist/tools/intelligence.js.map +1 -0
- package/dist/tools/session.d.ts +7 -0
- package/dist/tools/session.d.ts.map +1 -0
- package/dist/tools/session.js +533 -0
- package/dist/tools/session.js.map +1 -0
- package/dist/tools/trajectory.d.ts +10 -0
- package/dist/tools/trajectory.d.ts.map +1 -0
- package/dist/tools/trajectory.js +374 -0
- package/dist/tools/trajectory.js.map +1 -0
- package/dist/trajectory-io.d.ts +21 -0
- package/dist/trajectory-io.d.ts.map +1 -0
- package/dist/trajectory-io.js +105 -0
- package/dist/trajectory-io.js.map +1 -0
- package/dist/types.d.ts +229 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin bridge for recording quality signals from the MCP/plugin path.
|
|
3
|
+
*
|
|
4
|
+
* Reads and writes `.promptwheel/run-state.json` directly using the same
|
|
5
|
+
* format as CLI's `packages/cli/src/lib/run-state.ts`. Uses tmp+rename
|
|
6
|
+
* atomic write pattern. No mutex needed — MCP and CLI don't run
|
|
7
|
+
* simultaneously on the same project.
|
|
8
|
+
*/
|
|
9
|
+
import * as fs from 'node:fs';
|
|
10
|
+
import * as path from 'node:path';
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// File I/O
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
const RUN_STATE_FILE = 'run-state.json';
|
|
15
|
+
function statePath(projectRoot) {
|
|
16
|
+
return path.join(projectRoot, '.promptwheel', RUN_STATE_FILE);
|
|
17
|
+
}
|
|
18
|
+
function readRunState(projectRoot) {
|
|
19
|
+
const fp = statePath(projectRoot);
|
|
20
|
+
if (!fs.existsSync(fp)) {
|
|
21
|
+
return {
|
|
22
|
+
totalCycles: 0,
|
|
23
|
+
lastDocsAuditCycle: 0,
|
|
24
|
+
lastRunAt: 0,
|
|
25
|
+
deferredProposals: [],
|
|
26
|
+
formulaStats: {},
|
|
27
|
+
recentCycles: [],
|
|
28
|
+
recentDiffs: [],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const raw = fs.readFileSync(fp, 'utf-8');
|
|
33
|
+
const parsed = JSON.parse(raw);
|
|
34
|
+
return {
|
|
35
|
+
totalCycles: parsed.totalCycles ?? 0,
|
|
36
|
+
lastDocsAuditCycle: parsed.lastDocsAuditCycle ?? 0,
|
|
37
|
+
lastRunAt: parsed.lastRunAt ?? 0,
|
|
38
|
+
deferredProposals: Array.isArray(parsed.deferredProposals) ? parsed.deferredProposals : [],
|
|
39
|
+
formulaStats: parsed.formulaStats ?? {},
|
|
40
|
+
recentCycles: parsed.recentCycles,
|
|
41
|
+
recentDiffs: parsed.recentDiffs,
|
|
42
|
+
qualitySignals: parsed.qualitySignals ?? undefined,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
console.warn(`[promptwheel] failed to parse run-state.json: ${err instanceof Error ? err.message : String(err)}`);
|
|
47
|
+
return {
|
|
48
|
+
totalCycles: 0,
|
|
49
|
+
lastDocsAuditCycle: 0,
|
|
50
|
+
lastRunAt: 0,
|
|
51
|
+
deferredProposals: [],
|
|
52
|
+
formulaStats: {},
|
|
53
|
+
recentCycles: [],
|
|
54
|
+
recentDiffs: [],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function writeRunState(projectRoot, state) {
|
|
59
|
+
const fp = statePath(projectRoot);
|
|
60
|
+
const dir = path.dirname(fp);
|
|
61
|
+
if (!fs.existsSync(dir)) {
|
|
62
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
63
|
+
}
|
|
64
|
+
const tmp = fp + '.tmp';
|
|
65
|
+
fs.writeFileSync(tmp, JSON.stringify(state, null, 2) + '\n');
|
|
66
|
+
fs.renameSync(tmp, fp);
|
|
67
|
+
}
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// Public API
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
/**
|
|
72
|
+
* Record an execution quality signal. Same format as CLI's recordQualitySignal.
|
|
73
|
+
*/
|
|
74
|
+
export function recordQualitySignal(projectRoot, signal) {
|
|
75
|
+
const state = readRunState(projectRoot);
|
|
76
|
+
const qs = state.qualitySignals ??= {
|
|
77
|
+
totalTickets: 0,
|
|
78
|
+
firstPassSuccess: 0,
|
|
79
|
+
retriedSuccess: 0,
|
|
80
|
+
qaPassed: 0,
|
|
81
|
+
qaFailed: 0,
|
|
82
|
+
};
|
|
83
|
+
switch (signal) {
|
|
84
|
+
case 'first_pass':
|
|
85
|
+
qs.totalTickets++;
|
|
86
|
+
qs.firstPassSuccess++;
|
|
87
|
+
break;
|
|
88
|
+
case 'retried':
|
|
89
|
+
qs.totalTickets++;
|
|
90
|
+
qs.retriedSuccess++;
|
|
91
|
+
break;
|
|
92
|
+
case 'qa_pass':
|
|
93
|
+
qs.qaPassed++;
|
|
94
|
+
break;
|
|
95
|
+
case 'qa_fail':
|
|
96
|
+
qs.qaFailed++;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
writeRunState(projectRoot, state);
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=run-state-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-state-bridge.js","sourceRoot":"","sources":["../src/run-state-bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scope Policy — derives and enforces file-level constraints for tickets.
|
|
3
|
+
*
|
|
4
|
+
* Used by the plan validator and PreToolUse hook to ensure
|
|
5
|
+
* agents only touch files they're allowed to.
|
|
6
|
+
*
|
|
7
|
+
* Shared constants (ALWAYS_DENIED, CREDENTIAL_PATTERNS, FILE_DENY_PATTERNS)
|
|
8
|
+
* and pure algorithms live in @promptwheel/core/scope/shared.
|
|
9
|
+
* This file adds MCP-specific policy derivation and minimatch-based validation.
|
|
10
|
+
*/
|
|
11
|
+
import { type Learning, type AdaptiveRiskAssessment } from '@promptwheel/core/learnings/shared';
|
|
12
|
+
export { detectCredentialInContent as containsCredentials } from '@promptwheel/core/scope/shared';
|
|
13
|
+
export interface ScopePolicy {
|
|
14
|
+
allowed_paths: string[];
|
|
15
|
+
denied_paths: string[];
|
|
16
|
+
denied_patterns: RegExp[];
|
|
17
|
+
max_files: number;
|
|
18
|
+
max_lines: number;
|
|
19
|
+
plan_required: boolean;
|
|
20
|
+
/** When set, file writes are only allowed inside this worktree directory */
|
|
21
|
+
worktree_root?: string;
|
|
22
|
+
/** Adaptive risk assessment when learnings are provided */
|
|
23
|
+
risk_assessment?: AdaptiveRiskAssessment;
|
|
24
|
+
}
|
|
25
|
+
export interface DeriveScopeInput {
|
|
26
|
+
allowedPaths: string[];
|
|
27
|
+
category: string;
|
|
28
|
+
maxLinesPerTicket: number;
|
|
29
|
+
/** When set, restricts file writes to this worktree directory */
|
|
30
|
+
worktreeRoot?: string;
|
|
31
|
+
/** Cross-run learnings for adaptive trust (optional, backward compatible) */
|
|
32
|
+
learnings?: Learning[];
|
|
33
|
+
}
|
|
34
|
+
export declare function deriveScopePolicy(input: DeriveScopeInput): ScopePolicy;
|
|
35
|
+
export interface PlanFile {
|
|
36
|
+
path: string;
|
|
37
|
+
action: string;
|
|
38
|
+
reason: string;
|
|
39
|
+
}
|
|
40
|
+
export interface PlanValidationResult {
|
|
41
|
+
valid: boolean;
|
|
42
|
+
reason: string | null;
|
|
43
|
+
/** All violations found (empty when valid). Joined into `reason` for backward compat. */
|
|
44
|
+
violations: string[];
|
|
45
|
+
}
|
|
46
|
+
export declare function validatePlanScope(files: PlanFile[], estimatedLines: number, riskLevel: string, policy: ScopePolicy): PlanValidationResult;
|
|
47
|
+
/**
|
|
48
|
+
* Check if a file path is inside a worktree directory.
|
|
49
|
+
* Normalizes both paths before comparison.
|
|
50
|
+
*/
|
|
51
|
+
export declare function isFileInWorktree(filePath: string, worktreeRoot: string): boolean;
|
|
52
|
+
export declare function isFileAllowed(filePath: string, policy: ScopePolicy): boolean;
|
|
53
|
+
export interface CategoryToolPolicy {
|
|
54
|
+
auto_approve_patterns: string[];
|
|
55
|
+
constraint_note?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Per-category tool restrictions. Categories not listed here use defaults.
|
|
59
|
+
* - docs: can only edit markdown/text files
|
|
60
|
+
* - test: can only edit test files
|
|
61
|
+
* - security: full edit access but no npm install / arbitrary bash
|
|
62
|
+
*
|
|
63
|
+
* @deprecated Use ToolRegistry from @promptwheel/mcp/tool-registry instead.
|
|
64
|
+
* Kept for backward compatibility during migration.
|
|
65
|
+
*/
|
|
66
|
+
export declare const CATEGORY_TOOL_POLICIES: Record<string, CategoryToolPolicy>;
|
|
67
|
+
/**
|
|
68
|
+
* Get the tool policy for a given category.
|
|
69
|
+
* Returns null if the category has no specific policy (use defaults).
|
|
70
|
+
*
|
|
71
|
+
* @deprecated Use ToolRegistry.getConstraintNote() instead.
|
|
72
|
+
*/
|
|
73
|
+
export declare function getCategoryToolPolicy(category: string | null): CategoryToolPolicy | null;
|
|
74
|
+
/**
|
|
75
|
+
* Check if a file path is allowed by the category tool policy.
|
|
76
|
+
* Returns true if no category policy exists (= everything allowed).
|
|
77
|
+
* For docs: only *.md, *.mdx, *.txt, *.rst files.
|
|
78
|
+
* For test: only *.test.*, *.spec.*, __tests__/** files.
|
|
79
|
+
* Security has no file-type restrictions (only command restrictions).
|
|
80
|
+
*/
|
|
81
|
+
export declare function isCategoryFileAllowed(filePath: string, category: string | null): boolean;
|
|
82
|
+
export declare function serializeScopePolicy(policy: ScopePolicy): Record<string, unknown>;
|
|
83
|
+
//# sourceMappingURL=scope-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-policy.d.ts","sourceRoot":"","sources":["../src/scope-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,sBAAsB,EAC5B,MAAM,oCAAoC,CAAC;AAG5C,OAAO,EAAE,yBAAyB,IAAI,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAiBlG,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,OAAO,CAAC;IACvB,4EAA4E;IAC5E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,sBAAsB,CAAC;CAC1C;AAMD,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;CACxB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAwCtE;AAMD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,yFAAyF;IACzF,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,QAAQ,EAAE,EACjB,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,GAClB,oBAAoB,CAyDtB;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAIhF;AAMD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CA8B5E;AAQD,MAAM,WAAW,kBAAkB;IACjC,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CA0CrE,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,kBAAkB,GAAG,IAAI,CAGxF;AAMD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CA+BxF;AAMD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgBjF"}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scope Policy — derives and enforces file-level constraints for tickets.
|
|
3
|
+
*
|
|
4
|
+
* Used by the plan validator and PreToolUse hook to ensure
|
|
5
|
+
* agents only touch files they're allowed to.
|
|
6
|
+
*
|
|
7
|
+
* Shared constants (ALWAYS_DENIED, CREDENTIAL_PATTERNS, FILE_DENY_PATTERNS)
|
|
8
|
+
* and pure algorithms live in @promptwheel/core/scope/shared.
|
|
9
|
+
* This file adds MCP-specific policy derivation and minimatch-based validation.
|
|
10
|
+
*/
|
|
11
|
+
import * as nodePath from 'node:path';
|
|
12
|
+
import { minimatch } from 'minimatch';
|
|
13
|
+
import { ALWAYS_DENIED, FILE_DENY_PATTERNS, } from '@promptwheel/core/scope/shared';
|
|
14
|
+
import { assessAdaptiveRisk, } from '@promptwheel/core/learnings/shared';
|
|
15
|
+
// Re-export for existing consumers
|
|
16
|
+
export { detectCredentialInContent as containsCredentials } from '@promptwheel/core/scope/shared';
|
|
17
|
+
/**
|
|
18
|
+
* Normalize an allowed_path for minimatch:
|
|
19
|
+
* - Directory-style paths ending with `/` become `dir/**` (match anything inside)
|
|
20
|
+
* - Paths without globs or extensions that look like directories get `/**` appended
|
|
21
|
+
* - Everything else is left as-is
|
|
22
|
+
*/
|
|
23
|
+
function normalizeAllowedGlob(glob) {
|
|
24
|
+
if (glob.endsWith('/'))
|
|
25
|
+
return glob + '**';
|
|
26
|
+
return glob;
|
|
27
|
+
}
|
|
28
|
+
export function deriveScopePolicy(input) {
|
|
29
|
+
let maxFiles = 10;
|
|
30
|
+
let maxLines = input.category === 'test' ? 1000 : input.maxLinesPerTicket;
|
|
31
|
+
let planRequired = input.category !== 'docs';
|
|
32
|
+
let riskAssessment;
|
|
33
|
+
// Adaptive trust: adjust constraints based on failure history in learnings
|
|
34
|
+
if (input.learnings && input.learnings.length > 0) {
|
|
35
|
+
riskAssessment = assessAdaptiveRisk(input.learnings, input.allowedPaths);
|
|
36
|
+
switch (riskAssessment.level) {
|
|
37
|
+
case 'low':
|
|
38
|
+
maxFiles = 15;
|
|
39
|
+
maxLines = Math.round(maxLines * 1.5);
|
|
40
|
+
break;
|
|
41
|
+
case 'normal':
|
|
42
|
+
// No change — defaults
|
|
43
|
+
break;
|
|
44
|
+
case 'elevated':
|
|
45
|
+
maxFiles = 7;
|
|
46
|
+
planRequired = true;
|
|
47
|
+
break;
|
|
48
|
+
case 'high':
|
|
49
|
+
maxFiles = 5;
|
|
50
|
+
maxLines = Math.round(maxLines * 0.5);
|
|
51
|
+
planRequired = true;
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
allowed_paths: input.allowedPaths,
|
|
57
|
+
denied_paths: ALWAYS_DENIED,
|
|
58
|
+
denied_patterns: FILE_DENY_PATTERNS,
|
|
59
|
+
max_files: maxFiles,
|
|
60
|
+
max_lines: maxLines,
|
|
61
|
+
plan_required: planRequired,
|
|
62
|
+
worktree_root: input.worktreeRoot,
|
|
63
|
+
risk_assessment: riskAssessment,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export function validatePlanScope(files, estimatedLines, riskLevel, policy) {
|
|
67
|
+
const violations = [];
|
|
68
|
+
// 1. Must have files
|
|
69
|
+
if (!files || files.length === 0) {
|
|
70
|
+
return { valid: false, reason: 'Plan must include at least one file to touch', violations: ['Plan must include at least one file to touch'] };
|
|
71
|
+
}
|
|
72
|
+
// 2. Check estimated lines
|
|
73
|
+
if (estimatedLines > policy.max_lines) {
|
|
74
|
+
violations.push(`Estimated lines (${estimatedLines}) exceeds max (${policy.max_lines})`);
|
|
75
|
+
}
|
|
76
|
+
// 3. Check max files
|
|
77
|
+
if (files.length > policy.max_files) {
|
|
78
|
+
violations.push(`Plan touches ${files.length} files, max allowed is ${policy.max_files}`);
|
|
79
|
+
}
|
|
80
|
+
// 4. Valid risk level
|
|
81
|
+
if (!riskLevel || !['low', 'medium', 'high'].includes(riskLevel)) {
|
|
82
|
+
violations.push('Plan must specify risk_level: low, medium, or high');
|
|
83
|
+
}
|
|
84
|
+
// 5. Check each file against denied paths
|
|
85
|
+
for (const f of files) {
|
|
86
|
+
for (const deniedGlob of policy.denied_paths) {
|
|
87
|
+
if (minimatch(f.path, deniedGlob, { dot: true })) {
|
|
88
|
+
violations.push(`Plan touches denied path: ${f.path} (matches ${deniedGlob})`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// 6. Check each file against denied patterns
|
|
93
|
+
for (const f of files) {
|
|
94
|
+
for (const pattern of policy.denied_patterns) {
|
|
95
|
+
if (pattern.test(f.path)) {
|
|
96
|
+
violations.push(`Plan touches sensitive file: ${f.path}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// 7. Check each file is within allowed_paths (if any specified)
|
|
101
|
+
if (policy.allowed_paths.length > 0) {
|
|
102
|
+
for (const f of files) {
|
|
103
|
+
const isAllowed = policy.allowed_paths.some(glob => minimatch(f.path, normalizeAllowedGlob(glob), { dot: true }));
|
|
104
|
+
if (!isAllowed) {
|
|
105
|
+
violations.push(`File ${f.path} is outside allowed paths: ${policy.allowed_paths.join(', ')}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (violations.length > 0) {
|
|
110
|
+
return { valid: false, reason: violations.join('; '), violations };
|
|
111
|
+
}
|
|
112
|
+
return { valid: true, reason: null, violations: [] };
|
|
113
|
+
}
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// Worktree isolation check
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
/**
|
|
118
|
+
* Check if a file path is inside a worktree directory.
|
|
119
|
+
* Normalizes both paths before comparison.
|
|
120
|
+
*/
|
|
121
|
+
export function isFileInWorktree(filePath, worktreeRoot) {
|
|
122
|
+
const normalizedFile = nodePath.normalize(filePath).replace(/\\/g, '/');
|
|
123
|
+
const normalizedRoot = nodePath.normalize(worktreeRoot).replace(/\\/g, '/').replace(/\/$/, '');
|
|
124
|
+
return normalizedFile === normalizedRoot || normalizedFile.startsWith(normalizedRoot + '/');
|
|
125
|
+
}
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
// Check a single file path (used by PreToolUse hook)
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
export function isFileAllowed(filePath, policy) {
|
|
130
|
+
// Worktree enforcement: if set, reject files outside the worktree
|
|
131
|
+
if (policy.worktree_root) {
|
|
132
|
+
if (!isFileInWorktree(filePath, policy.worktree_root)) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Check denied paths
|
|
137
|
+
for (const deniedGlob of policy.denied_paths) {
|
|
138
|
+
if (minimatch(filePath, deniedGlob, { dot: true })) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Check denied patterns
|
|
143
|
+
for (const pattern of policy.denied_patterns) {
|
|
144
|
+
if (pattern.test(filePath)) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// Check allowed paths (empty = everything allowed)
|
|
149
|
+
if (policy.allowed_paths.length > 0) {
|
|
150
|
+
return policy.allowed_paths.some(glob => minimatch(filePath, normalizeAllowedGlob(glob), { dot: true }));
|
|
151
|
+
}
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Per-category tool restrictions. Categories not listed here use defaults.
|
|
156
|
+
* - docs: can only edit markdown/text files
|
|
157
|
+
* - test: can only edit test files
|
|
158
|
+
* - security: full edit access but no npm install / arbitrary bash
|
|
159
|
+
*
|
|
160
|
+
* @deprecated Use ToolRegistry from @promptwheel/mcp/tool-registry instead.
|
|
161
|
+
* Kept for backward compatibility during migration.
|
|
162
|
+
*/
|
|
163
|
+
export const CATEGORY_TOOL_POLICIES = {
|
|
164
|
+
docs: {
|
|
165
|
+
auto_approve_patterns: [
|
|
166
|
+
'Read(*)', 'Glob(*)', 'Grep(*)',
|
|
167
|
+
'Edit(*.md)', 'Edit(*.mdx)', 'Edit(*.txt)', 'Edit(*.rst)',
|
|
168
|
+
'Write(*.md)', 'Write(*.mdx)', 'Write(*.txt)', 'Write(*.rst)',
|
|
169
|
+
'Bash(git diff*)', 'Bash(git status*)',
|
|
170
|
+
],
|
|
171
|
+
constraint_note: 'This is a **docs** ticket. You may ONLY edit markdown and text files (*.md, *.mdx, *.txt, *.rst). Do NOT modify source code, config files, or any other file types.',
|
|
172
|
+
},
|
|
173
|
+
test: {
|
|
174
|
+
auto_approve_patterns: [
|
|
175
|
+
'Read(*)', 'Glob(*)', 'Grep(*)',
|
|
176
|
+
'Edit(*.test.*)', 'Edit(*.spec.*)', 'Edit(*__tests__*)',
|
|
177
|
+
'Edit(test_*)', 'Edit(*_test.go)', 'Edit(*_test.py)', 'Edit(*Test.java)',
|
|
178
|
+
'Write(*.test.*)', 'Write(*.spec.*)', 'Write(*__tests__*)',
|
|
179
|
+
'Write(test_*)', 'Write(*_test.go)', 'Write(*_test.py)', 'Write(*Test.java)',
|
|
180
|
+
'Bash(npm test*)', 'Bash(npx vitest*)', 'Bash(npx jest*)', 'Bash(npx tsc*)',
|
|
181
|
+
'Bash(pytest*)', 'Bash(cargo test*)', 'Bash(go test*)', 'Bash(mvn test*)',
|
|
182
|
+
'Bash(./gradlew test*)', 'Bash(bundle exec rspec*)', 'Bash(mix test*)',
|
|
183
|
+
'Bash(dotnet test*)', 'Bash(swift test*)', 'Bash(make test*)',
|
|
184
|
+
'Bash(dart test*)', 'Bash(flutter test*)', 'Bash(sbt test*)',
|
|
185
|
+
'Bash(stack test*)', 'Bash(cabal test*)', 'Bash(zig build test*)',
|
|
186
|
+
'Bash(ctest*)', 'Bash(phpunit*)',
|
|
187
|
+
'Bash(git diff*)', 'Bash(git status*)',
|
|
188
|
+
],
|
|
189
|
+
constraint_note: 'This is a **test** ticket. You may ONLY edit test files (*.test.*, *.spec.*, __tests__/**, test_*.py, *_test.go, *Test.java, etc.). Do NOT modify production source code.',
|
|
190
|
+
},
|
|
191
|
+
security: {
|
|
192
|
+
auto_approve_patterns: [
|
|
193
|
+
'Read(*)', 'Glob(*)', 'Grep(*)', 'Edit(*)', 'Write(*)',
|
|
194
|
+
'Bash(npm test*)', 'Bash(npx vitest*)', 'Bash(npx tsc*)',
|
|
195
|
+
'Bash(pytest*)', 'Bash(cargo test*)', 'Bash(go test*)', 'Bash(mvn test*)',
|
|
196
|
+
'Bash(./gradlew test*)', 'Bash(make test*)',
|
|
197
|
+
'Bash(dart test*)', 'Bash(flutter test*)', 'Bash(sbt test*)',
|
|
198
|
+
'Bash(stack test*)', 'Bash(cabal test*)', 'Bash(zig build test*)',
|
|
199
|
+
'Bash(ctest*)', 'Bash(dotnet test*)', 'Bash(swift test*)',
|
|
200
|
+
'Bash(mix test*)', 'Bash(bundle exec rspec*)', 'Bash(phpunit*)',
|
|
201
|
+
'Bash(git diff*)', 'Bash(git status*)',
|
|
202
|
+
],
|
|
203
|
+
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.',
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
/**
|
|
207
|
+
* Get the tool policy for a given category.
|
|
208
|
+
* Returns null if the category has no specific policy (use defaults).
|
|
209
|
+
*
|
|
210
|
+
* @deprecated Use ToolRegistry.getConstraintNote() instead.
|
|
211
|
+
*/
|
|
212
|
+
export function getCategoryToolPolicy(category) {
|
|
213
|
+
if (!category)
|
|
214
|
+
return null;
|
|
215
|
+
return CATEGORY_TOOL_POLICIES[category] ?? null;
|
|
216
|
+
}
|
|
217
|
+
// ---------------------------------------------------------------------------
|
|
218
|
+
// Enforce category file-type restrictions
|
|
219
|
+
// ---------------------------------------------------------------------------
|
|
220
|
+
/**
|
|
221
|
+
* Check if a file path is allowed by the category tool policy.
|
|
222
|
+
* Returns true if no category policy exists (= everything allowed).
|
|
223
|
+
* For docs: only *.md, *.mdx, *.txt, *.rst files.
|
|
224
|
+
* For test: only *.test.*, *.spec.*, __tests__/** files.
|
|
225
|
+
* Security has no file-type restrictions (only command restrictions).
|
|
226
|
+
*/
|
|
227
|
+
export function isCategoryFileAllowed(filePath, category) {
|
|
228
|
+
if (!category)
|
|
229
|
+
return true;
|
|
230
|
+
const CATEGORY_FILE_PATTERNS = {
|
|
231
|
+
docs: ['*.md', '*.mdx', '*.txt', '*.rst', '**/*.md', '**/*.mdx', '**/*.txt', '**/*.rst'],
|
|
232
|
+
test: [
|
|
233
|
+
// JS/TS
|
|
234
|
+
'*.test.*', '*.spec.*', '**/*.test.*', '**/*.spec.*', '**/__tests__/**', '__tests__/**',
|
|
235
|
+
// Python
|
|
236
|
+
'test_*', '**/test_*', '*_test.py', '**/*_test.py', '**/tests/**', 'tests/**', '**/conftest.py',
|
|
237
|
+
// Go
|
|
238
|
+
'*_test.go', '**/*_test.go',
|
|
239
|
+
// Rust (tests/ dir)
|
|
240
|
+
'tests/**', '**/tests/**',
|
|
241
|
+
// Java/Kotlin
|
|
242
|
+
'*Test.java', '**/*Test.java', '*Test.kt', '**/*Test.kt', '**/src/test/**',
|
|
243
|
+
// Ruby
|
|
244
|
+
'*_spec.rb', '**/*_spec.rb', '**/spec/**',
|
|
245
|
+
// Elixir
|
|
246
|
+
'*_test.exs', '**/*_test.exs',
|
|
247
|
+
// Swift
|
|
248
|
+
'*Tests.swift', '**/*Tests.swift',
|
|
249
|
+
// PHP
|
|
250
|
+
'*Test.php', '**/*Test.php',
|
|
251
|
+
],
|
|
252
|
+
};
|
|
253
|
+
const patterns = CATEGORY_FILE_PATTERNS[category];
|
|
254
|
+
if (!patterns)
|
|
255
|
+
return true; // no restrictions for this category (e.g. security, fix, refactor)
|
|
256
|
+
return patterns.some(glob => minimatch(filePath, glob, { dot: true }));
|
|
257
|
+
}
|
|
258
|
+
// ---------------------------------------------------------------------------
|
|
259
|
+
// Serialize policy for MCP tool response (RegExp → string)
|
|
260
|
+
// ---------------------------------------------------------------------------
|
|
261
|
+
export function serializeScopePolicy(policy) {
|
|
262
|
+
const result = {
|
|
263
|
+
allowed_paths: policy.allowed_paths,
|
|
264
|
+
denied_paths: policy.denied_paths,
|
|
265
|
+
denied_patterns: policy.denied_patterns.map(r => r.source),
|
|
266
|
+
max_files: policy.max_files,
|
|
267
|
+
max_lines: policy.max_lines,
|
|
268
|
+
plan_required: policy.plan_required,
|
|
269
|
+
};
|
|
270
|
+
if (policy.worktree_root) {
|
|
271
|
+
result.worktree_root = policy.worktree_root;
|
|
272
|
+
}
|
|
273
|
+
if (policy.risk_assessment) {
|
|
274
|
+
result.risk_assessment = policy.risk_assessment;
|
|
275
|
+
}
|
|
276
|
+
return result;
|
|
277
|
+
}
|
|
278
|
+
//# sourceMappingURL=scope-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-policy.js","sourceRoot":"","sources":["../src/scope-policy.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server setup and tool registration
|
|
3
|
+
*/
|
|
4
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
import type { DatabaseAdapter } from '@promptwheel/core';
|
|
6
|
+
import { SessionManager } from './state.js';
|
|
7
|
+
export interface ServerOptions {
|
|
8
|
+
db: DatabaseAdapter;
|
|
9
|
+
projectPath: string;
|
|
10
|
+
projectName?: string;
|
|
11
|
+
/** Register trajectory tools (default: true for backward compat, plugins may set false) */
|
|
12
|
+
trajectoryTools?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function createServer(options: ServerOptions): Promise<{
|
|
15
|
+
server: McpServer;
|
|
16
|
+
state: SessionManager;
|
|
17
|
+
}>;
|
|
18
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAO5C,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,eAAe,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2FAA2F;IAC3F,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC;IAClE,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,cAAc,CAAC;CACvB,CAAC,CA2BD"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server setup and tool registration
|
|
3
|
+
*/
|
|
4
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
import { repos } from '@promptwheel/core';
|
|
6
|
+
import { SessionManager } from './state.js';
|
|
7
|
+
import { registerSessionTools } from './tools/session.js';
|
|
8
|
+
import { registerExecuteTools } from './tools/execute.js';
|
|
9
|
+
import { registerGitTools } from './tools/git.js';
|
|
10
|
+
import { registerIntelligenceTools } from './tools/intelligence.js';
|
|
11
|
+
import { registerTrajectoryTools } from './tools/trajectory.js';
|
|
12
|
+
export async function createServer(options) {
|
|
13
|
+
const { db, projectPath, projectName } = options;
|
|
14
|
+
// Ensure project exists
|
|
15
|
+
const project = await repos.projects.ensureForRepo(db, {
|
|
16
|
+
name: projectName ?? projectPath.split('/').pop() ?? 'unknown',
|
|
17
|
+
rootPath: projectPath,
|
|
18
|
+
});
|
|
19
|
+
const state = new SessionManager(db, project, projectPath);
|
|
20
|
+
const getState = () => state;
|
|
21
|
+
const server = new McpServer({
|
|
22
|
+
name: 'promptwheel',
|
|
23
|
+
version: '0.6.0',
|
|
24
|
+
});
|
|
25
|
+
// Register tool groups
|
|
26
|
+
registerSessionTools(server, getState);
|
|
27
|
+
registerExecuteTools(server, getState);
|
|
28
|
+
registerGitTools(server, getState);
|
|
29
|
+
registerIntelligenceTools(server, getState);
|
|
30
|
+
if (options.trajectoryTools !== false) {
|
|
31
|
+
registerTrajectoryTools(server, getState);
|
|
32
|
+
}
|
|
33
|
+
return { server, state };
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAUhE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAsB;IAIvD,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IAEjD,wBAAwB;IACxB,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,EAAE;QACrD,IAAI,EAAE,WAAW,IAAI,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,SAAS;QAC9D,QAAQ,EAAE,WAAW;KACtB,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,IAAI,cAAc,CAAC,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC;IAE7B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,uBAAuB;IACvB,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvC,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvC,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,yBAAyB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC5C,IAAI,OAAO,CAAC,eAAe,KAAK,KAAK,EAAE,CAAC;QACtC,uBAAuB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spindle Loop Detection — MCP server adaptation.
|
|
3
|
+
*
|
|
4
|
+
* Monitors agent execution for unproductive patterns:
|
|
5
|
+
* - Oscillation: diffs flip-flopping (A→B→A)
|
|
6
|
+
* - Repetition: similar outputs repeated
|
|
7
|
+
* - Stalling: no file changes for N iterations
|
|
8
|
+
* - QA ping-pong: alternating test/lint failures
|
|
9
|
+
* - Command signature: same command fails repeatedly
|
|
10
|
+
*
|
|
11
|
+
* Ported from packages/cli/src/lib/spindle.ts, adapted for the
|
|
12
|
+
* event-driven MCP architecture.
|
|
13
|
+
*/
|
|
14
|
+
import type { SpindleState } from './types.js';
|
|
15
|
+
export interface SpindleConfig {
|
|
16
|
+
similarityThreshold: number;
|
|
17
|
+
maxSimilarOutputs: number;
|
|
18
|
+
maxStallIterations: number;
|
|
19
|
+
maxCommandFailures: number;
|
|
20
|
+
maxQaPingPong: number;
|
|
21
|
+
maxFileEdits: number;
|
|
22
|
+
}
|
|
23
|
+
export declare const DEFAULT_SPINDLE_CONFIG: SpindleConfig;
|
|
24
|
+
export type SpindleReason = 'oscillation' | 'repetition' | 'stalling' | 'qa_ping_pong' | 'command_failure';
|
|
25
|
+
export interface SpindleCheckResult {
|
|
26
|
+
shouldAbort: boolean;
|
|
27
|
+
shouldBlock: boolean;
|
|
28
|
+
reason?: SpindleReason;
|
|
29
|
+
confidence: number;
|
|
30
|
+
diagnostics: Record<string, unknown>;
|
|
31
|
+
risk: 'none' | 'low' | 'medium' | 'high';
|
|
32
|
+
}
|
|
33
|
+
export declare function checkSpindle(spindle: SpindleState, config?: SpindleConfig): SpindleCheckResult;
|
|
34
|
+
export declare function recordOutput(spindle: SpindleState, output: string): void;
|
|
35
|
+
export declare function recordDiff(spindle: SpindleState, diff: string | null): void;
|
|
36
|
+
export declare function recordCommandFailure(spindle: SpindleState, command: string, error: string): void;
|
|
37
|
+
export declare function recordPlanHash(spindle: SpindleState, plan: unknown): void;
|
|
38
|
+
export declare function recordTicketResult(spindle: SpindleState, changedFiles: string[], diff: string | null): void;
|
|
39
|
+
/** Get file edit frequency warnings — wraps shared function, handles optional field */
|
|
40
|
+
export declare function getFileEditWarnings(spindle: SpindleState, threshold?: number): string[];
|
|
41
|
+
//# sourceMappingURL=spindle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spindle.d.ts","sourceRoot":"","sources":["../src/spindle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAa/C,MAAM,WAAW,aAAa;IAC5B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,sBAAsB,EAAE,aAOpC,CAAC;AAMF,MAAM,MAAM,aAAa,GACrB,aAAa,GACb,YAAY,GACZ,UAAU,GACV,cAAc,GACd,iBAAiB,CAAC;AAEtB,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC1C;AAcD,wBAAgB,YAAY,CAC1B,OAAO,EAAE,YAAY,EACrB,MAAM,GAAE,aAAsC,GAC7C,kBAAkB,CA8EpB;AAMD,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAKxE;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CA4B3E;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAIhG;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAIzE;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAE3G;AA8ED,uFAAuF;AACvF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,EAAE,SAAS,GAAE,MAAU,GAAG,MAAM,EAAE,CAG1F"}
|