@cdoing/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/coordinator.d.ts +114 -0
- package/dist/agents/coordinator.d.ts.map +1 -0
- package/dist/agents/coordinator.js +158 -0
- package/dist/agents/coordinator.js.map +1 -0
- package/dist/context-providers/clipboard.d.ts +13 -0
- package/dist/context-providers/clipboard.d.ts.map +1 -0
- package/dist/context-providers/clipboard.js +53 -0
- package/dist/context-providers/clipboard.js.map +1 -0
- package/dist/context-providers/codebase.d.ts +46 -0
- package/dist/context-providers/codebase.d.ts.map +1 -0
- package/dist/context-providers/codebase.js +273 -0
- package/dist/context-providers/codebase.js.map +1 -0
- package/dist/context-providers/diff.d.ts +18 -0
- package/dist/context-providers/diff.d.ts.map +1 -0
- package/dist/context-providers/diff.js +63 -0
- package/dist/context-providers/diff.js.map +1 -0
- package/dist/context-providers/docs.d.ts +21 -0
- package/dist/context-providers/docs.d.ts.map +1 -0
- package/dist/context-providers/docs.js +180 -0
- package/dist/context-providers/docs.js.map +1 -0
- package/dist/context-providers/file-include.d.ts +13 -0
- package/dist/context-providers/file-include.d.ts.map +1 -0
- package/dist/context-providers/file-include.js +82 -0
- package/dist/context-providers/file-include.js.map +1 -0
- package/dist/context-providers/folder.d.ts +19 -0
- package/dist/context-providers/folder.d.ts.map +1 -0
- package/dist/context-providers/folder.js +130 -0
- package/dist/context-providers/folder.js.map +1 -0
- package/dist/context-providers/git.d.ts +19 -0
- package/dist/context-providers/git.d.ts.map +1 -0
- package/dist/context-providers/git.js +74 -0
- package/dist/context-providers/git.js.map +1 -0
- package/dist/context-providers/index.d.ts +26 -0
- package/dist/context-providers/index.d.ts.map +1 -0
- package/dist/context-providers/index.js +37 -0
- package/dist/context-providers/index.js.map +1 -0
- package/dist/context-providers/open-files.d.ts +25 -0
- package/dist/context-providers/open-files.d.ts.map +1 -0
- package/dist/context-providers/open-files.js +134 -0
- package/dist/context-providers/open-files.js.map +1 -0
- package/dist/context-providers/problems.d.ts +24 -0
- package/dist/context-providers/problems.d.ts.map +1 -0
- package/dist/context-providers/problems.js +97 -0
- package/dist/context-providers/problems.js.map +1 -0
- package/dist/context-providers/registry.d.ts +61 -0
- package/dist/context-providers/registry.d.ts.map +1 -0
- package/dist/context-providers/registry.js +92 -0
- package/dist/context-providers/registry.js.map +1 -0
- package/dist/context-providers/terminal.d.ts +25 -0
- package/dist/context-providers/terminal.d.ts.map +1 -0
- package/dist/context-providers/terminal.js +55 -0
- package/dist/context-providers/terminal.js.map +1 -0
- package/dist/context-providers/tree.d.ts +29 -0
- package/dist/context-providers/tree.d.ts.map +1 -0
- package/dist/context-providers/tree.js +172 -0
- package/dist/context-providers/tree.js.map +1 -0
- package/dist/context-providers/types.d.ts +72 -0
- package/dist/context-providers/types.d.ts.map +1 -0
- package/dist/context-providers/types.js +10 -0
- package/dist/context-providers/types.js.map +1 -0
- package/dist/context-providers/url.d.ts +27 -0
- package/dist/context-providers/url.d.ts.map +1 -0
- package/dist/context-providers/url.js +131 -0
- package/dist/context-providers/url.js.map +1 -0
- package/dist/effort/index.d.ts +78 -0
- package/dist/effort/index.d.ts.map +1 -0
- package/dist/effort/index.js +146 -0
- package/dist/effort/index.js.map +1 -0
- package/dist/hooks/index.d.ts +47 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +151 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.d.ts +75 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +152 -0
- package/dist/index.js.map +1 -0
- package/dist/indexing/chunker.d.ts +25 -0
- package/dist/indexing/chunker.d.ts.map +1 -0
- package/dist/indexing/chunker.js +217 -0
- package/dist/indexing/chunker.js.map +1 -0
- package/dist/indexing/database.d.ts +49 -0
- package/dist/indexing/database.d.ts.map +1 -0
- package/dist/indexing/database.js +287 -0
- package/dist/indexing/database.js.map +1 -0
- package/dist/indexing/index.d.ts +9 -0
- package/dist/indexing/index.d.ts.map +1 -0
- package/dist/indexing/index.js +13 -0
- package/dist/indexing/index.js.map +1 -0
- package/dist/indexing/indexer.d.ts +63 -0
- package/dist/indexing/indexer.d.ts.map +1 -0
- package/dist/indexing/indexer.js +352 -0
- package/dist/indexing/indexer.js.map +1 -0
- package/dist/indexing/recent-edits-cache.d.ts +77 -0
- package/dist/indexing/recent-edits-cache.d.ts.map +1 -0
- package/dist/indexing/recent-edits-cache.js +123 -0
- package/dist/indexing/recent-edits-cache.js.map +1 -0
- package/dist/indexing/types.d.ts +39 -0
- package/dist/indexing/types.d.ts.map +1 -0
- package/dist/indexing/types.js +6 -0
- package/dist/indexing/types.js.map +1 -0
- package/dist/mcp/index.d.ts +33 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +37 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/manager.d.ts +123 -0
- package/dist/mcp/manager.d.ts.map +1 -0
- package/dist/mcp/manager.js +331 -0
- package/dist/mcp/manager.js.map +1 -0
- package/dist/oauth.d.ts +33 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +312 -0
- package/dist/oauth.js.map +1 -0
- package/dist/permissions/index.d.ts +216 -0
- package/dist/permissions/index.d.ts.map +1 -0
- package/dist/permissions/index.js +938 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/plan/index.d.ts +20 -0
- package/dist/plan/index.d.ts.map +1 -0
- package/dist/plan/index.js +24 -0
- package/dist/plan/index.js.map +1 -0
- package/dist/plan/manager.d.ts +101 -0
- package/dist/plan/manager.d.ts.map +1 -0
- package/dist/plan/manager.js +170 -0
- package/dist/plan/manager.js.map +1 -0
- package/dist/rules/index.d.ts +28 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +31 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/manager.d.ts +77 -0
- package/dist/rules/manager.d.ts.map +1 -0
- package/dist/rules/manager.js +279 -0
- package/dist/rules/manager.js.map +1 -0
- package/dist/rules/types.d.ts +34 -0
- package/dist/rules/types.d.ts.map +1 -0
- package/dist/rules/types.js +9 -0
- package/dist/rules/types.js.map +1 -0
- package/dist/sandbox/filesystem.d.ts +20 -0
- package/dist/sandbox/filesystem.d.ts.map +1 -0
- package/dist/sandbox/filesystem.js +141 -0
- package/dist/sandbox/filesystem.js.map +1 -0
- package/dist/sandbox/index.d.ts +4 -0
- package/dist/sandbox/index.d.ts.map +1 -0
- package/dist/sandbox/index.js +8 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/sandbox/manager.d.ts +47 -0
- package/dist/sandbox/manager.d.ts.map +1 -0
- package/dist/sandbox/manager.js +220 -0
- package/dist/sandbox/manager.js.map +1 -0
- package/dist/sandbox/network.d.ts +14 -0
- package/dist/sandbox/network.d.ts.map +1 -0
- package/dist/sandbox/network.js +87 -0
- package/dist/sandbox/network.js.map +1 -0
- package/dist/sandbox/types.d.ts +42 -0
- package/dist/sandbox/types.d.ts.map +1 -0
- package/dist/sandbox/types.js +25 -0
- package/dist/sandbox/types.js.map +1 -0
- package/dist/tools/ast-edit.d.ts +57 -0
- package/dist/tools/ast-edit.d.ts.map +1 -0
- package/dist/tools/ast-edit.js +443 -0
- package/dist/tools/ast-edit.js.map +1 -0
- package/dist/tools/code-verify.d.ts +8 -0
- package/dist/tools/code-verify.d.ts.map +1 -0
- package/dist/tools/code-verify.js +159 -0
- package/dist/tools/code-verify.js.map +1 -0
- package/dist/tools/codebase-search.d.ts +17 -0
- package/dist/tools/codebase-search.d.ts.map +1 -0
- package/dist/tools/codebase-search.js +104 -0
- package/dist/tools/codebase-search.js.map +1 -0
- package/dist/tools/file-delete.d.ts +26 -0
- package/dist/tools/file-delete.d.ts.map +1 -0
- package/dist/tools/file-delete.js +179 -0
- package/dist/tools/file-delete.js.map +1 -0
- package/dist/tools/file-edit.d.ts +10 -0
- package/dist/tools/file-edit.d.ts.map +1 -0
- package/dist/tools/file-edit.js +138 -0
- package/dist/tools/file-edit.js.map +1 -0
- package/dist/tools/file-read.d.ts +12 -0
- package/dist/tools/file-read.d.ts.map +1 -0
- package/dist/tools/file-read.js +211 -0
- package/dist/tools/file-read.js.map +1 -0
- package/dist/tools/file-run.d.ts +10 -0
- package/dist/tools/file-run.d.ts.map +1 -0
- package/dist/tools/file-run.js +179 -0
- package/dist/tools/file-run.js.map +1 -0
- package/dist/tools/file-write.d.ts +10 -0
- package/dist/tools/file-write.d.ts.map +1 -0
- package/dist/tools/file-write.js +134 -0
- package/dist/tools/file-write.js.map +1 -0
- package/dist/tools/glob-search.d.ts +8 -0
- package/dist/tools/glob-search.d.ts.map +1 -0
- package/dist/tools/glob-search.js +108 -0
- package/dist/tools/glob-search.js.map +1 -0
- package/dist/tools/grep-search.d.ts +8 -0
- package/dist/tools/grep-search.d.ts.map +1 -0
- package/dist/tools/grep-search.js +139 -0
- package/dist/tools/grep-search.js.map +1 -0
- package/dist/tools/list-dir.d.ts +16 -0
- package/dist/tools/list-dir.d.ts.map +1 -0
- package/dist/tools/list-dir.js +183 -0
- package/dist/tools/list-dir.js.map +1 -0
- package/dist/tools/multi-edit.d.ts +16 -0
- package/dist/tools/multi-edit.d.ts.map +1 -0
- package/dist/tools/multi-edit.js +163 -0
- package/dist/tools/multi-edit.js.map +1 -0
- package/dist/tools/notebook-edit.d.ts +31 -0
- package/dist/tools/notebook-edit.d.ts.map +1 -0
- package/dist/tools/notebook-edit.js +321 -0
- package/dist/tools/notebook-edit.js.map +1 -0
- package/dist/tools/registry.d.ts +16 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +41 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/shell-exec.d.ts +12 -0
- package/dist/tools/shell-exec.d.ts.map +1 -0
- package/dist/tools/shell-exec.js +261 -0
- package/dist/tools/shell-exec.js.map +1 -0
- package/dist/tools/sub-agent-manager.d.ts +57 -0
- package/dist/tools/sub-agent-manager.d.ts.map +1 -0
- package/dist/tools/sub-agent-manager.js +153 -0
- package/dist/tools/sub-agent-manager.js.map +1 -0
- package/dist/tools/sub-agent-status.d.ts +12 -0
- package/dist/tools/sub-agent-status.d.ts.map +1 -0
- package/dist/tools/sub-agent-status.js +59 -0
- package/dist/tools/sub-agent-status.js.map +1 -0
- package/dist/tools/sub-agent-terminate.d.ts +12 -0
- package/dist/tools/sub-agent-terminate.d.ts.map +1 -0
- package/dist/tools/sub-agent-terminate.js +55 -0
- package/dist/tools/sub-agent-terminate.js.map +1 -0
- package/dist/tools/sub-agent.d.ts +34 -0
- package/dist/tools/sub-agent.d.ts.map +1 -0
- package/dist/tools/sub-agent.js +140 -0
- package/dist/tools/sub-agent.js.map +1 -0
- package/dist/tools/system-info.d.ts +24 -0
- package/dist/tools/system-info.d.ts.map +1 -0
- package/dist/tools/system-info.js +220 -0
- package/dist/tools/system-info.js.map +1 -0
- package/dist/tools/todo.d.ts +16 -0
- package/dist/tools/todo.d.ts.map +1 -0
- package/dist/tools/todo.js +144 -0
- package/dist/tools/todo.js.map +1 -0
- package/dist/tools/types.d.ts +20 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +3 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/view-diff.d.ts +11 -0
- package/dist/tools/view-diff.d.ts.map +1 -0
- package/dist/tools/view-diff.js +88 -0
- package/dist/tools/view-diff.js.map +1 -0
- package/dist/tools/view-repo-map.d.ts +18 -0
- package/dist/tools/view-repo-map.d.ts.map +1 -0
- package/dist/tools/view-repo-map.js +245 -0
- package/dist/tools/view-repo-map.js.map +1 -0
- package/dist/tools/web-fetch.d.ts +13 -0
- package/dist/tools/web-fetch.d.ts.map +1 -0
- package/dist/tools/web-fetch.js +106 -0
- package/dist/tools/web-fetch.js.map +1 -0
- package/dist/tools/web-search.d.ts +10 -0
- package/dist/tools/web-search.d.ts.map +1 -0
- package/dist/tools/web-search.js +106 -0
- package/dist/tools/web-search.js.map +1 -0
- package/dist/utils/gitignore.d.ts +10 -0
- package/dist/utils/gitignore.d.ts.map +1 -0
- package/dist/utils/gitignore.js +104 -0
- package/dist/utils/gitignore.js.map +1 -0
- package/dist/utils/lazy-apply.d.ts +45 -0
- package/dist/utils/lazy-apply.d.ts.map +1 -0
- package/dist/utils/lazy-apply.js +164 -0
- package/dist/utils/lazy-apply.js.map +1 -0
- package/dist/utils/memory.d.ts +36 -0
- package/dist/utils/memory.d.ts.map +1 -0
- package/dist/utils/memory.js +136 -0
- package/dist/utils/memory.js.map +1 -0
- package/dist/utils/path-matching.d.ts +24 -0
- package/dist/utils/path-matching.d.ts.map +1 -0
- package/dist/utils/path-matching.js +116 -0
- package/dist/utils/path-matching.js.map +1 -0
- package/dist/utils/path-safety.d.ts +13 -0
- package/dist/utils/path-safety.d.ts.map +1 -0
- package/dist/utils/path-safety.js +54 -0
- package/dist/utils/path-safety.js.map +1 -0
- package/dist/utils/project-config.d.ts +18 -0
- package/dist/utils/project-config.d.ts.map +1 -0
- package/dist/utils/project-config.js +76 -0
- package/dist/utils/project-config.js.map +1 -0
- package/dist/utils/search-match.d.ts +63 -0
- package/dist/utils/search-match.d.ts.map +1 -0
- package/dist/utils/search-match.js +426 -0
- package/dist/utils/search-match.js.map +1 -0
- package/dist/utils/shell-paths.d.ts +17 -0
- package/dist/utils/shell-paths.d.ts.map +1 -0
- package/dist/utils/shell-paths.js +107 -0
- package/dist/utils/shell-paths.js.map +1 -0
- package/dist/utils/streaming-diff.d.ts +45 -0
- package/dist/utils/streaming-diff.d.ts.map +1 -0
- package/dist/utils/streaming-diff.js +230 -0
- package/dist/utils/streaming-diff.js.map +1 -0
- package/dist/utils/todo.d.ts +47 -0
- package/dist/utils/todo.d.ts.map +1 -0
- package/dist/utils/todo.js +102 -0
- package/dist/utils/todo.js.map +1 -0
- package/package.json +23 -0
- package/src/agents/coordinator.ts +240 -0
- package/src/context-providers/clipboard.ts +48 -0
- package/src/context-providers/codebase.ts +274 -0
- package/src/context-providers/diff.ts +66 -0
- package/src/context-providers/docs.ts +160 -0
- package/src/context-providers/file-include.ts +54 -0
- package/src/context-providers/folder.ts +106 -0
- package/src/context-providers/git.ts +72 -0
- package/src/context-providers/index.ts +26 -0
- package/src/context-providers/open-files.ts +113 -0
- package/src/context-providers/problems.ts +100 -0
- package/src/context-providers/registry.ts +99 -0
- package/src/context-providers/terminal.ts +58 -0
- package/src/context-providers/tree.ts +161 -0
- package/src/context-providers/types.ts +84 -0
- package/src/context-providers/url.ts +138 -0
- package/src/effort/index.ts +177 -0
- package/src/hooks/index.ts +148 -0
- package/src/index.ts +114 -0
- package/src/indexing/README.md +267 -0
- package/src/indexing/chunker.ts +206 -0
- package/src/indexing/database.ts +299 -0
- package/src/indexing/index.ts +15 -0
- package/src/indexing/indexer.ts +383 -0
- package/src/indexing/recent-edits-cache.ts +150 -0
- package/src/indexing/types.ts +44 -0
- package/src/mcp/index.ts +33 -0
- package/src/mcp/manager.ts +385 -0
- package/src/oauth.ts +330 -0
- package/src/permissions/index.ts +1011 -0
- package/src/plan/index.ts +20 -0
- package/src/plan/manager.ts +233 -0
- package/src/rules/index.ts +28 -0
- package/src/rules/manager.ts +276 -0
- package/src/rules/types.ts +40 -0
- package/src/sandbox/filesystem.ts +135 -0
- package/src/sandbox/index.ts +9 -0
- package/src/sandbox/manager.ts +213 -0
- package/src/sandbox/network.ts +101 -0
- package/src/sandbox/types.ts +63 -0
- package/src/tools/ast-edit.ts +493 -0
- package/src/tools/code-verify.ts +143 -0
- package/src/tools/codebase-search.ts +117 -0
- package/src/tools/file-delete.ts +155 -0
- package/src/tools/file-edit.ts +115 -0
- package/src/tools/file-read.ts +195 -0
- package/src/tools/file-run.ts +158 -0
- package/src/tools/file-write.ts +104 -0
- package/src/tools/glob-search.ts +80 -0
- package/src/tools/grep-search.ts +120 -0
- package/src/tools/list-dir.ts +172 -0
- package/src/tools/multi-edit.ts +138 -0
- package/src/tools/notebook-edit.ts +342 -0
- package/src/tools/registry.ts +43 -0
- package/src/tools/shell-exec.ts +251 -0
- package/src/tools/sub-agent-manager.ts +183 -0
- package/src/tools/sub-agent-status.ts +67 -0
- package/src/tools/sub-agent-terminate.ts +62 -0
- package/src/tools/sub-agent.ts +162 -0
- package/src/tools/system-info.ts +248 -0
- package/src/tools/todo.ts +149 -0
- package/src/tools/types.ts +21 -0
- package/src/tools/view-diff.ts +99 -0
- package/src/tools/view-repo-map.ts +249 -0
- package/src/tools/web-fetch.ts +118 -0
- package/src/tools/web-search.ts +129 -0
- package/src/utils/gitignore.ts +73 -0
- package/src/utils/lazy-apply.ts +189 -0
- package/src/utils/memory.ts +124 -0
- package/src/utils/path-matching.ts +84 -0
- package/src/utils/path-safety.ts +19 -0
- package/src/utils/project-config.ts +41 -0
- package/src/utils/search-match.ts +495 -0
- package/src/utils/shell-paths.ts +79 -0
- package/src/utils/streaming-diff.ts +260 -0
- package/src/utils/todo.ts +115 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Mode — Read-only planning before execution.
|
|
3
|
+
*
|
|
4
|
+
* When activated (/plan command), the agent:
|
|
5
|
+
* 1. Analyzes the request using read-only tools (file_read, grep, glob)
|
|
6
|
+
* 2. Generates a step-by-step implementation plan as markdown
|
|
7
|
+
* 3. Presents the plan for user review
|
|
8
|
+
* 4. User can approve, edit, or reject before execution
|
|
9
|
+
*
|
|
10
|
+
* The plan is stored as a structured object so it can be:
|
|
11
|
+
* - Displayed as an interactive checklist in VS Code
|
|
12
|
+
* - Edited by the user before approval
|
|
13
|
+
* - Executed step-by-step with progress tracking
|
|
14
|
+
*
|
|
15
|
+
* Learning note: Plan mode is a form of "chain of thought" for the AI.
|
|
16
|
+
* By forcing the agent to plan before acting, it produces better results
|
|
17
|
+
* and gives the user a chance to course-correct before any files change.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
export { PlanManager, type Plan, type PlanStep, type PlanStatus } from "./manager";
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Manager — Creates, stores, and executes implementation plans.
|
|
3
|
+
*
|
|
4
|
+
* A plan is a structured breakdown of what the agent intends to do.
|
|
5
|
+
* Each step has a description, status, and optional tool call info.
|
|
6
|
+
*
|
|
7
|
+
* Learning note: This follows the Command Pattern — each plan step
|
|
8
|
+
* is a serializable command that can be reviewed before execution.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Status of the overall plan.
|
|
13
|
+
*/
|
|
14
|
+
export type PlanStatus = "drafting" | "pending_approval" | "approved" | "executing" | "completed" | "rejected";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A single step in the plan.
|
|
18
|
+
*/
|
|
19
|
+
export interface PlanStep {
|
|
20
|
+
/** Step number (1-based) */
|
|
21
|
+
number: number;
|
|
22
|
+
|
|
23
|
+
/** What this step will do (human-readable) */
|
|
24
|
+
description: string;
|
|
25
|
+
|
|
26
|
+
/** Which tool to use (e.g., "file_edit", "shell_exec") */
|
|
27
|
+
tool?: string;
|
|
28
|
+
|
|
29
|
+
/** Target file or resource */
|
|
30
|
+
target?: string;
|
|
31
|
+
|
|
32
|
+
/** Current status of this step */
|
|
33
|
+
status: "pending" | "in_progress" | "completed" | "skipped";
|
|
34
|
+
|
|
35
|
+
/** Optional details or notes */
|
|
36
|
+
details?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A complete implementation plan.
|
|
41
|
+
*/
|
|
42
|
+
export interface Plan {
|
|
43
|
+
/** Unique plan ID */
|
|
44
|
+
id: string;
|
|
45
|
+
|
|
46
|
+
/** One-line summary of what the plan achieves */
|
|
47
|
+
summary: string;
|
|
48
|
+
|
|
49
|
+
/** Ordered list of steps */
|
|
50
|
+
steps: PlanStep[];
|
|
51
|
+
|
|
52
|
+
/** Current plan status */
|
|
53
|
+
status: PlanStatus;
|
|
54
|
+
|
|
55
|
+
/** When the plan was created */
|
|
56
|
+
createdAt: number;
|
|
57
|
+
|
|
58
|
+
/** The original user request that generated this plan */
|
|
59
|
+
originalRequest: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export class PlanManager {
|
|
63
|
+
/** The current active plan (only one at a time) */
|
|
64
|
+
private currentPlan: Plan | null = null;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Create a new plan from the agent's analysis.
|
|
68
|
+
*
|
|
69
|
+
* @param request - The original user request
|
|
70
|
+
* @param summary - One-line summary
|
|
71
|
+
* @param steps - Ordered list of step descriptions
|
|
72
|
+
* @returns The created plan
|
|
73
|
+
*/
|
|
74
|
+
createPlan(request: string, summary: string, steps: string[]): Plan {
|
|
75
|
+
this.currentPlan = {
|
|
76
|
+
id: `plan_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`,
|
|
77
|
+
summary,
|
|
78
|
+
steps: steps.map((desc, i) => ({
|
|
79
|
+
number: i + 1,
|
|
80
|
+
description: desc,
|
|
81
|
+
status: "pending",
|
|
82
|
+
})),
|
|
83
|
+
status: "pending_approval",
|
|
84
|
+
createdAt: Date.now(),
|
|
85
|
+
originalRequest: request,
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
return this.currentPlan;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get the current active plan.
|
|
93
|
+
*/
|
|
94
|
+
getCurrentPlan(): Plan | null {
|
|
95
|
+
return this.currentPlan;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Approve the plan for execution.
|
|
100
|
+
*/
|
|
101
|
+
approvePlan(): boolean {
|
|
102
|
+
if (!this.currentPlan || this.currentPlan.status !== "pending_approval") {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
this.currentPlan.status = "approved";
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Reject the plan.
|
|
111
|
+
*/
|
|
112
|
+
rejectPlan(): boolean {
|
|
113
|
+
if (!this.currentPlan) return false;
|
|
114
|
+
this.currentPlan.status = "rejected";
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Mark the plan as executing.
|
|
120
|
+
*/
|
|
121
|
+
startExecution(): boolean {
|
|
122
|
+
if (!this.currentPlan || this.currentPlan.status !== "approved") {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
this.currentPlan.status = "executing";
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Update a step's status.
|
|
131
|
+
*/
|
|
132
|
+
updateStep(stepNumber: number, status: PlanStep["status"], details?: string): boolean {
|
|
133
|
+
if (!this.currentPlan) return false;
|
|
134
|
+
|
|
135
|
+
const step = this.currentPlan.steps.find((s) => s.number === stepNumber);
|
|
136
|
+
if (!step) return false;
|
|
137
|
+
|
|
138
|
+
step.status = status;
|
|
139
|
+
if (details) step.details = details;
|
|
140
|
+
|
|
141
|
+
// Check if all steps are completed
|
|
142
|
+
const allDone = this.currentPlan.steps.every(
|
|
143
|
+
(s) => s.status === "completed" || s.status === "skipped"
|
|
144
|
+
);
|
|
145
|
+
if (allDone) {
|
|
146
|
+
this.currentPlan.status = "completed";
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Format the plan as markdown for display.
|
|
154
|
+
*
|
|
155
|
+
* Learning note: We use checkbox syntax (- [ ] / - [x]) so the
|
|
156
|
+
* plan looks like an interactive checklist in the chat.
|
|
157
|
+
*/
|
|
158
|
+
formatPlan(): string {
|
|
159
|
+
if (!this.currentPlan) return "No active plan.";
|
|
160
|
+
|
|
161
|
+
const plan = this.currentPlan;
|
|
162
|
+
const lines: string[] = [
|
|
163
|
+
`## Plan: ${plan.summary}`,
|
|
164
|
+
"",
|
|
165
|
+
`**Status:** ${this.formatStatus(plan.status)}`,
|
|
166
|
+
"",
|
|
167
|
+
];
|
|
168
|
+
|
|
169
|
+
for (const step of plan.steps) {
|
|
170
|
+
const checkbox = step.status === "completed" ? "[x]"
|
|
171
|
+
: step.status === "skipped" ? "[-]"
|
|
172
|
+
: step.status === "in_progress" ? "[~]"
|
|
173
|
+
: "[ ]";
|
|
174
|
+
|
|
175
|
+
let line = `${step.number}. ${checkbox} ${step.description}`;
|
|
176
|
+
if (step.tool) line += ` _(${step.tool})_`;
|
|
177
|
+
if (step.target) line += ` → \`${step.target}\``;
|
|
178
|
+
lines.push(line);
|
|
179
|
+
|
|
180
|
+
if (step.details) {
|
|
181
|
+
lines.push(` _${step.details}_`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return lines.join("\n");
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Get the plan as a system prompt addition.
|
|
190
|
+
* Used to guide the agent during execution.
|
|
191
|
+
*/
|
|
192
|
+
getPlanPrompt(): string {
|
|
193
|
+
if (!this.currentPlan) return "";
|
|
194
|
+
|
|
195
|
+
const plan = this.currentPlan;
|
|
196
|
+
const stepList = plan.steps
|
|
197
|
+
.map((s) => `${s.number}. [${s.status}] ${s.description}`)
|
|
198
|
+
.join("\n");
|
|
199
|
+
|
|
200
|
+
return [
|
|
201
|
+
"# Active Plan",
|
|
202
|
+
"",
|
|
203
|
+
`Goal: ${plan.summary}`,
|
|
204
|
+
"",
|
|
205
|
+
"Steps:",
|
|
206
|
+
stepList,
|
|
207
|
+
"",
|
|
208
|
+
"Execute the next pending step. After completing each step, update its status.",
|
|
209
|
+
"If a step fails, explain why and suggest alternatives.",
|
|
210
|
+
].join("\n");
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Clear the current plan.
|
|
215
|
+
*/
|
|
216
|
+
clearPlan(): void {
|
|
217
|
+
this.currentPlan = null;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Format a plan status as a human-readable string.
|
|
222
|
+
*/
|
|
223
|
+
private formatStatus(status: PlanStatus): string {
|
|
224
|
+
switch (status) {
|
|
225
|
+
case "drafting": return "Drafting...";
|
|
226
|
+
case "pending_approval": return "Waiting for approval";
|
|
227
|
+
case "approved": return "Approved";
|
|
228
|
+
case "executing": return "Executing...";
|
|
229
|
+
case "completed": return "Completed";
|
|
230
|
+
case "rejected": return "Rejected";
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project Rules — Hierarchical rule system for project-specific AI behavior.
|
|
3
|
+
*
|
|
4
|
+
* Similar to Cursor's .cursor/rules/ and Claude Code's CLAUDE.md,
|
|
5
|
+
* but with glob-based path scoping.
|
|
6
|
+
*
|
|
7
|
+
* Rule hierarchy (highest priority first):
|
|
8
|
+
* 1. Path-specific rules (.cdoing/rules/*.md with glob patterns)
|
|
9
|
+
* 2. Project rules (.cdoing/config.md or CDOING.md)
|
|
10
|
+
* 3. Global rules (~/.cdoing/rules/*.md)
|
|
11
|
+
*
|
|
12
|
+
* Each rule file is a markdown file with optional frontmatter:
|
|
13
|
+
*
|
|
14
|
+
* ---
|
|
15
|
+
* globs: ["*.ts", "src/api/**"]
|
|
16
|
+
* description: Rules for TypeScript API files
|
|
17
|
+
* ---
|
|
18
|
+
*
|
|
19
|
+
* Always use async/await instead of callbacks.
|
|
20
|
+
* Prefer named exports over default exports.
|
|
21
|
+
*
|
|
22
|
+
* Learning note: Glob-based scoping lets you have different coding
|
|
23
|
+
* standards for different parts of your project. For example, strict
|
|
24
|
+
* type rules for API code but relaxed rules for scripts.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
export { RulesManager } from "./manager";
|
|
28
|
+
export type { Rule, RuleSource } from "./types";
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rules Manager — Loads, caches, and resolves project rules.
|
|
3
|
+
*
|
|
4
|
+
* Scans rule directories in priority order and returns rules
|
|
5
|
+
* that match the current file context.
|
|
6
|
+
*
|
|
7
|
+
* Learning note: The manager uses lazy loading — rules are only
|
|
8
|
+
* read from disk when first needed, then cached until the file
|
|
9
|
+
* system changes. This prevents slow startup on large projects.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import * as fs from "fs";
|
|
13
|
+
import * as path from "path";
|
|
14
|
+
import * as os from "os";
|
|
15
|
+
import { minimatch } from "minimatch";
|
|
16
|
+
import type { Rule, RuleSource, RuleFrontmatter } from "./types";
|
|
17
|
+
|
|
18
|
+
export class RulesManager {
|
|
19
|
+
/** Cached rules, indexed by source directory */
|
|
20
|
+
private cache = new Map<string, Rule[]>();
|
|
21
|
+
|
|
22
|
+
/** Working directory (project root) */
|
|
23
|
+
private workingDir: string;
|
|
24
|
+
|
|
25
|
+
constructor(workingDir: string) {
|
|
26
|
+
this.workingDir = workingDir;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get all rules that apply to a given file path.
|
|
31
|
+
* Rules are returned in priority order (most specific first).
|
|
32
|
+
*
|
|
33
|
+
* @param filePath - The file being edited/created (for glob matching)
|
|
34
|
+
* @returns Array of matching rules
|
|
35
|
+
*/
|
|
36
|
+
getRulesForFile(filePath?: string): Rule[] {
|
|
37
|
+
const allRules = this.loadAllRules();
|
|
38
|
+
|
|
39
|
+
if (!filePath) {
|
|
40
|
+
// No file context — return all rules without glob restrictions
|
|
41
|
+
return allRules.filter((r) => r.globs.length === 0);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Resolve to relative path for glob matching
|
|
45
|
+
const relativePath = path.isAbsolute(filePath)
|
|
46
|
+
? path.relative(this.workingDir, filePath)
|
|
47
|
+
: filePath;
|
|
48
|
+
|
|
49
|
+
return allRules.filter((rule) => {
|
|
50
|
+
// Rules without globs apply to everything
|
|
51
|
+
if (rule.globs.length === 0) return true;
|
|
52
|
+
|
|
53
|
+
// Check if any glob pattern matches the file
|
|
54
|
+
return rule.globs.some((glob) => this.matchGlob(relativePath, glob));
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Get all rules formatted as a single string for the system prompt.
|
|
60
|
+
*
|
|
61
|
+
* @param filePath - Optional file context for filtering
|
|
62
|
+
* @returns Formatted rules text, or empty string if no rules
|
|
63
|
+
*/
|
|
64
|
+
formatForPrompt(filePath?: string): string {
|
|
65
|
+
const rules = this.getRulesForFile(filePath);
|
|
66
|
+
if (rules.length === 0) return "";
|
|
67
|
+
|
|
68
|
+
const sections = rules.map((rule) => {
|
|
69
|
+
const header = rule.description
|
|
70
|
+
? `### ${rule.description}`
|
|
71
|
+
: `### Rule from ${path.basename(rule.filePath)}`;
|
|
72
|
+
|
|
73
|
+
const scope = rule.globs.length > 0
|
|
74
|
+
? `_Applies to: ${rule.globs.join(", ")}_\n`
|
|
75
|
+
: "";
|
|
76
|
+
|
|
77
|
+
return `${header}\n${scope}\n${rule.content}`;
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
return `# Project Rules\n\n${sections.join("\n\n---\n\n")}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Load all rules from all sources.
|
|
85
|
+
* Results are cached — call invalidateCache() to refresh.
|
|
86
|
+
*/
|
|
87
|
+
private loadAllRules(): Rule[] {
|
|
88
|
+
const rules: Rule[] = [];
|
|
89
|
+
|
|
90
|
+
// 1. Global rules (~/.cdoing/rules/)
|
|
91
|
+
const globalDir = path.join(os.homedir(), ".cdoing", "rules");
|
|
92
|
+
rules.push(...this.loadRulesFromDir(globalDir, "global"));
|
|
93
|
+
|
|
94
|
+
// 2. Project rules (.cdoing/rules/)
|
|
95
|
+
const projectDir = path.join(this.workingDir, ".cdoing", "rules");
|
|
96
|
+
rules.push(...this.loadRulesFromDir(projectDir, "path-specific"));
|
|
97
|
+
|
|
98
|
+
return rules;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Load rules from a directory of markdown files.
|
|
103
|
+
*
|
|
104
|
+
* Learning note: Each .md file in the rules directory becomes a rule.
|
|
105
|
+
* YAML frontmatter is parsed for glob patterns and descriptions.
|
|
106
|
+
*/
|
|
107
|
+
private loadRulesFromDir(dir: string, source: RuleSource): Rule[] {
|
|
108
|
+
// Check cache
|
|
109
|
+
const cached = this.cache.get(dir);
|
|
110
|
+
if (cached) return cached;
|
|
111
|
+
|
|
112
|
+
const rules: Rule[] = [];
|
|
113
|
+
|
|
114
|
+
if (!fs.existsSync(dir)) {
|
|
115
|
+
this.cache.set(dir, rules);
|
|
116
|
+
return rules;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
let entries: string[];
|
|
120
|
+
try {
|
|
121
|
+
entries = fs.readdirSync(dir).filter((f) => f.endsWith(".md"));
|
|
122
|
+
} catch {
|
|
123
|
+
this.cache.set(dir, rules);
|
|
124
|
+
return rules;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
for (const file of entries) {
|
|
128
|
+
const filePath = path.join(dir, file);
|
|
129
|
+
try {
|
|
130
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
131
|
+
const parsed = this.parseRuleFile(content);
|
|
132
|
+
|
|
133
|
+
rules.push({
|
|
134
|
+
source,
|
|
135
|
+
filePath,
|
|
136
|
+
globs: parsed.globs,
|
|
137
|
+
description: parsed.description || file.replace(/\.md$/, ""),
|
|
138
|
+
content: parsed.content,
|
|
139
|
+
});
|
|
140
|
+
} catch {
|
|
141
|
+
// Skip unreadable files
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
this.cache.set(dir, rules);
|
|
146
|
+
return rules;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Parse a rule markdown file, extracting frontmatter and content.
|
|
151
|
+
*
|
|
152
|
+
* Frontmatter format:
|
|
153
|
+
* ---
|
|
154
|
+
* globs: ["*.ts", "src/**"]
|
|
155
|
+
* description: TypeScript coding rules
|
|
156
|
+
* ---
|
|
157
|
+
*
|
|
158
|
+
* Learning note: We use a simple regex-based parser instead of
|
|
159
|
+
* a YAML library to avoid adding dependencies. This handles
|
|
160
|
+
* the common cases well enough.
|
|
161
|
+
*/
|
|
162
|
+
private parseRuleFile(raw: string): { globs: string[]; description: string; content: string } {
|
|
163
|
+
const frontmatterMatch = raw.match(/^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/);
|
|
164
|
+
|
|
165
|
+
if (!frontmatterMatch) {
|
|
166
|
+
// No frontmatter — entire file is content
|
|
167
|
+
return { globs: [], description: "", content: raw.trim() };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const [, frontmatterStr, content] = frontmatterMatch;
|
|
171
|
+
|
|
172
|
+
// Simple key-value parsing for frontmatter
|
|
173
|
+
let globs: string[] = [];
|
|
174
|
+
let description = "";
|
|
175
|
+
|
|
176
|
+
for (const line of frontmatterStr.split("\n")) {
|
|
177
|
+
const globMatch = line.match(/^globs:\s*\[(.+)\]$/);
|
|
178
|
+
if (globMatch) {
|
|
179
|
+
// Parse glob array: ["*.ts", "src/**"]
|
|
180
|
+
globs = globMatch[1]
|
|
181
|
+
.split(",")
|
|
182
|
+
.map((g) => g.trim().replace(/^["']|["']$/g, ""))
|
|
183
|
+
.filter(Boolean);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const globSingle = line.match(/^globs:\s*["'](.+)["']$/);
|
|
187
|
+
if (globSingle) {
|
|
188
|
+
globs = [globSingle[1]];
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const descMatch = line.match(/^description:\s*(.+)$/);
|
|
192
|
+
if (descMatch) {
|
|
193
|
+
description = descMatch[1].trim().replace(/^["']|["']$/g, "");
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return { globs, description, content: content.trim() };
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Check if a file path matches a glob pattern.
|
|
202
|
+
* Uses minimatch for proper glob matching.
|
|
203
|
+
*/
|
|
204
|
+
private matchGlob(filePath: string, pattern: string): boolean {
|
|
205
|
+
try {
|
|
206
|
+
return minimatch(filePath, pattern, { matchBase: true });
|
|
207
|
+
} catch {
|
|
208
|
+
// If minimatch isn't available, fall back to simple extension matching
|
|
209
|
+
if (pattern.startsWith("*.")) {
|
|
210
|
+
const ext = pattern.slice(1); // e.g., ".ts"
|
|
211
|
+
return filePath.endsWith(ext);
|
|
212
|
+
}
|
|
213
|
+
return filePath.includes(pattern);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Format rules for CLI display, showing file paths and sources.
|
|
219
|
+
*/
|
|
220
|
+
formatForDisplay(): string {
|
|
221
|
+
const allRules = this.loadAllRules();
|
|
222
|
+
if (allRules.length === 0) return "No rules defined.";
|
|
223
|
+
|
|
224
|
+
const globalDir = path.join(os.homedir(), ".cdoing", "rules");
|
|
225
|
+
const projectDir = path.join(this.workingDir, ".cdoing", "rules");
|
|
226
|
+
|
|
227
|
+
const lines: string[] = ["# Rules\n"];
|
|
228
|
+
|
|
229
|
+
// Group by source
|
|
230
|
+
const globalRules = allRules.filter((r) => r.source === "global");
|
|
231
|
+
const projectRules = allRules.filter((r) => r.source === "path-specific");
|
|
232
|
+
|
|
233
|
+
if (globalRules.length > 0) {
|
|
234
|
+
lines.push(`## Global rules (${globalDir}/)`);
|
|
235
|
+
for (const rule of globalRules) {
|
|
236
|
+
const globs = rule.globs.length > 0 ? ` [${rule.globs.join(", ")}]` : "";
|
|
237
|
+
lines.push(` - ${rule.filePath}${globs}`);
|
|
238
|
+
}
|
|
239
|
+
lines.push("");
|
|
240
|
+
} else {
|
|
241
|
+
lines.push(`## Global rules — none found`);
|
|
242
|
+
lines.push(` Directory: ${globalDir}/`);
|
|
243
|
+
lines.push("");
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (projectRules.length > 0) {
|
|
247
|
+
lines.push(`## Project rules (${projectDir}/)`);
|
|
248
|
+
for (const rule of projectRules) {
|
|
249
|
+
const globs = rule.globs.length > 0 ? ` [${rule.globs.join(", ")}]` : "";
|
|
250
|
+
lines.push(` - ${rule.filePath}${globs}`);
|
|
251
|
+
}
|
|
252
|
+
lines.push("");
|
|
253
|
+
} else {
|
|
254
|
+
lines.push(`## Project rules — none found`);
|
|
255
|
+
lines.push(` Directory: ${projectDir}/`);
|
|
256
|
+
lines.push("");
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return lines.join("\n");
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Clear the rule cache (call after file changes).
|
|
264
|
+
*/
|
|
265
|
+
invalidateCache(): void {
|
|
266
|
+
this.cache.clear();
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Update the working directory.
|
|
271
|
+
*/
|
|
272
|
+
setWorkingDir(dir: string): void {
|
|
273
|
+
this.workingDir = dir;
|
|
274
|
+
this.invalidateCache();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule Types — Shared type definitions for the rules system.
|
|
3
|
+
*
|
|
4
|
+
* Learning note: Separating types from implementation keeps
|
|
5
|
+
* the codebase clean and prevents circular imports.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A single rule definition loaded from a .md file.
|
|
10
|
+
*/
|
|
11
|
+
export interface Rule {
|
|
12
|
+
/** Where the rule was loaded from */
|
|
13
|
+
source: RuleSource;
|
|
14
|
+
|
|
15
|
+
/** Absolute path to the rule file */
|
|
16
|
+
filePath: string;
|
|
17
|
+
|
|
18
|
+
/** Glob patterns this rule applies to (empty = applies to all files) */
|
|
19
|
+
globs: string[];
|
|
20
|
+
|
|
21
|
+
/** Human-readable description of what the rule enforces */
|
|
22
|
+
description: string;
|
|
23
|
+
|
|
24
|
+
/** The actual rule content (markdown text) */
|
|
25
|
+
content: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Where a rule was loaded from — determines priority.
|
|
30
|
+
* path-specific > project > global
|
|
31
|
+
*/
|
|
32
|
+
export type RuleSource = "global" | "project" | "path-specific";
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Frontmatter parsed from a rule markdown file.
|
|
36
|
+
*/
|
|
37
|
+
export interface RuleFrontmatter {
|
|
38
|
+
globs?: string | string[];
|
|
39
|
+
description?: string;
|
|
40
|
+
}
|