ctxinit 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.
Files changed (221) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +484 -0
  3. package/bin/ctx.js +3 -0
  4. package/dist/analysis/index.d.ts +2 -0
  5. package/dist/analysis/index.d.ts.map +1 -0
  6. package/dist/analysis/index.js +18 -0
  7. package/dist/analysis/index.js.map +1 -0
  8. package/dist/analysis/static-analysis.d.ts +79 -0
  9. package/dist/analysis/static-analysis.d.ts.map +1 -0
  10. package/dist/analysis/static-analysis.js +279 -0
  11. package/dist/analysis/static-analysis.js.map +1 -0
  12. package/dist/bootstrap/index.d.ts +8 -0
  13. package/dist/bootstrap/index.d.ts.map +1 -0
  14. package/dist/bootstrap/index.js +13 -0
  15. package/dist/bootstrap/index.js.map +1 -0
  16. package/dist/bootstrap/orchestrator.d.ts +48 -0
  17. package/dist/bootstrap/orchestrator.d.ts.map +1 -0
  18. package/dist/bootstrap/orchestrator.js +363 -0
  19. package/dist/bootstrap/orchestrator.js.map +1 -0
  20. package/dist/bootstrap/validator.d.ts +25 -0
  21. package/dist/bootstrap/validator.d.ts.map +1 -0
  22. package/dist/bootstrap/validator.js +412 -0
  23. package/dist/bootstrap/validator.js.map +1 -0
  24. package/dist/build/atomic.d.ts +74 -0
  25. package/dist/build/atomic.d.ts.map +1 -0
  26. package/dist/build/atomic.js +235 -0
  27. package/dist/build/atomic.js.map +1 -0
  28. package/dist/build/index.d.ts +10 -0
  29. package/dist/build/index.d.ts.map +1 -0
  30. package/dist/build/index.js +26 -0
  31. package/dist/build/index.js.map +1 -0
  32. package/dist/build/lock.d.ts +102 -0
  33. package/dist/build/lock.d.ts.map +1 -0
  34. package/dist/build/lock.js +297 -0
  35. package/dist/build/lock.js.map +1 -0
  36. package/dist/build/manifest.d.ts +138 -0
  37. package/dist/build/manifest.d.ts.map +1 -0
  38. package/dist/build/manifest.js +269 -0
  39. package/dist/build/manifest.js.map +1 -0
  40. package/dist/build/orchestrator.d.ts +103 -0
  41. package/dist/build/orchestrator.d.ts.map +1 -0
  42. package/dist/build/orchestrator.js +524 -0
  43. package/dist/build/orchestrator.js.map +1 -0
  44. package/dist/cli/bootstrap.d.ts +77 -0
  45. package/dist/cli/bootstrap.d.ts.map +1 -0
  46. package/dist/cli/bootstrap.js +527 -0
  47. package/dist/cli/bootstrap.js.map +1 -0
  48. package/dist/cli/build.d.ts +32 -0
  49. package/dist/cli/build.d.ts.map +1 -0
  50. package/dist/cli/build.js +156 -0
  51. package/dist/cli/build.js.map +1 -0
  52. package/dist/cli/diff.d.ts +23 -0
  53. package/dist/cli/diff.d.ts.map +1 -0
  54. package/dist/cli/diff.js +226 -0
  55. package/dist/cli/diff.js.map +1 -0
  56. package/dist/cli/hooks.d.ts +29 -0
  57. package/dist/cli/hooks.d.ts.map +1 -0
  58. package/dist/cli/hooks.js +176 -0
  59. package/dist/cli/hooks.js.map +1 -0
  60. package/dist/cli/init.d.ts +53 -0
  61. package/dist/cli/init.d.ts.map +1 -0
  62. package/dist/cli/init.js +254 -0
  63. package/dist/cli/init.js.map +1 -0
  64. package/dist/cli/lint.d.ts +46 -0
  65. package/dist/cli/lint.d.ts.map +1 -0
  66. package/dist/cli/lint.js +210 -0
  67. package/dist/cli/lint.js.map +1 -0
  68. package/dist/cli/migrate.d.ts +28 -0
  69. package/dist/cli/migrate.d.ts.map +1 -0
  70. package/dist/cli/migrate.js +350 -0
  71. package/dist/cli/migrate.js.map +1 -0
  72. package/dist/cli/verify.d.ts +21 -0
  73. package/dist/cli/verify.d.ts.map +1 -0
  74. package/dist/cli/verify.js +209 -0
  75. package/dist/cli/verify.js.map +1 -0
  76. package/dist/cli.d.ts +8 -0
  77. package/dist/cli.d.ts.map +1 -0
  78. package/dist/cli.js +262 -0
  79. package/dist/cli.js.map +1 -0
  80. package/dist/compiler/agents-compiler.d.ts +24 -0
  81. package/dist/compiler/agents-compiler.d.ts.map +1 -0
  82. package/dist/compiler/agents-compiler.js +192 -0
  83. package/dist/compiler/agents-compiler.js.map +1 -0
  84. package/dist/compiler/base-compiler.d.ts +152 -0
  85. package/dist/compiler/base-compiler.d.ts.map +1 -0
  86. package/dist/compiler/base-compiler.js +180 -0
  87. package/dist/compiler/base-compiler.js.map +1 -0
  88. package/dist/compiler/claude-compiler.d.ts +24 -0
  89. package/dist/compiler/claude-compiler.d.ts.map +1 -0
  90. package/dist/compiler/claude-compiler.js +182 -0
  91. package/dist/compiler/claude-compiler.js.map +1 -0
  92. package/dist/compiler/cursor-compiler.d.ts +33 -0
  93. package/dist/compiler/cursor-compiler.d.ts.map +1 -0
  94. package/dist/compiler/cursor-compiler.js +136 -0
  95. package/dist/compiler/cursor-compiler.js.map +1 -0
  96. package/dist/compiler/index.d.ts +7 -0
  97. package/dist/compiler/index.d.ts.map +1 -0
  98. package/dist/compiler/index.js +24 -0
  99. package/dist/compiler/index.js.map +1 -0
  100. package/dist/compiler/rule-selector.d.ts +115 -0
  101. package/dist/compiler/rule-selector.d.ts.map +1 -0
  102. package/dist/compiler/rule-selector.js +273 -0
  103. package/dist/compiler/rule-selector.js.map +1 -0
  104. package/dist/compiler/token-estimator.d.ts +74 -0
  105. package/dist/compiler/token-estimator.d.ts.map +1 -0
  106. package/dist/compiler/token-estimator.js +191 -0
  107. package/dist/compiler/token-estimator.js.map +1 -0
  108. package/dist/config/index.d.ts +2 -0
  109. package/dist/config/index.d.ts.map +1 -0
  110. package/dist/config/index.js +18 -0
  111. package/dist/config/index.js.map +1 -0
  112. package/dist/config/loader.d.ts +48 -0
  113. package/dist/config/loader.d.ts.map +1 -0
  114. package/dist/config/loader.js +175 -0
  115. package/dist/config/loader.js.map +1 -0
  116. package/dist/git/gitignore.d.ts +59 -0
  117. package/dist/git/gitignore.d.ts.map +1 -0
  118. package/dist/git/gitignore.js +268 -0
  119. package/dist/git/gitignore.js.map +1 -0
  120. package/dist/git/hooks.d.ts +34 -0
  121. package/dist/git/hooks.d.ts.map +1 -0
  122. package/dist/git/hooks.js +129 -0
  123. package/dist/git/hooks.js.map +1 -0
  124. package/dist/git/husky.d.ts +52 -0
  125. package/dist/git/husky.d.ts.map +1 -0
  126. package/dist/git/husky.js +219 -0
  127. package/dist/git/husky.js.map +1 -0
  128. package/dist/git/index.d.ts +9 -0
  129. package/dist/git/index.d.ts.map +1 -0
  130. package/dist/git/index.js +15 -0
  131. package/dist/git/index.js.map +1 -0
  132. package/dist/index.d.ts +6 -0
  133. package/dist/index.d.ts.map +1 -0
  134. package/dist/index.js +23 -0
  135. package/dist/index.js.map +1 -0
  136. package/dist/llm/base-provider.d.ts +43 -0
  137. package/dist/llm/base-provider.d.ts.map +1 -0
  138. package/dist/llm/base-provider.js +91 -0
  139. package/dist/llm/base-provider.js.map +1 -0
  140. package/dist/llm/index.d.ts +17 -0
  141. package/dist/llm/index.d.ts.map +1 -0
  142. package/dist/llm/index.js +36 -0
  143. package/dist/llm/index.js.map +1 -0
  144. package/dist/llm/prompts/bootstrap-prompt.d.ts +27 -0
  145. package/dist/llm/prompts/bootstrap-prompt.d.ts.map +1 -0
  146. package/dist/llm/prompts/bootstrap-prompt.js +278 -0
  147. package/dist/llm/prompts/bootstrap-prompt.js.map +1 -0
  148. package/dist/llm/prompts/index.d.ts +5 -0
  149. package/dist/llm/prompts/index.d.ts.map +1 -0
  150. package/dist/llm/prompts/index.js +11 -0
  151. package/dist/llm/prompts/index.js.map +1 -0
  152. package/dist/llm/provider-factory.d.ts +27 -0
  153. package/dist/llm/provider-factory.d.ts.map +1 -0
  154. package/dist/llm/provider-factory.js +213 -0
  155. package/dist/llm/provider-factory.js.map +1 -0
  156. package/dist/llm/providers/claude-api.d.ts +21 -0
  157. package/dist/llm/providers/claude-api.d.ts.map +1 -0
  158. package/dist/llm/providers/claude-api.js +110 -0
  159. package/dist/llm/providers/claude-api.js.map +1 -0
  160. package/dist/llm/providers/claude-code.d.ts +21 -0
  161. package/dist/llm/providers/claude-code.d.ts.map +1 -0
  162. package/dist/llm/providers/claude-code.js +120 -0
  163. package/dist/llm/providers/claude-code.js.map +1 -0
  164. package/dist/llm/providers/codex-cli.d.ts +25 -0
  165. package/dist/llm/providers/codex-cli.d.ts.map +1 -0
  166. package/dist/llm/providers/codex-cli.js +129 -0
  167. package/dist/llm/providers/codex-cli.js.map +1 -0
  168. package/dist/llm/providers/cursor-cli.d.ts +24 -0
  169. package/dist/llm/providers/cursor-cli.d.ts.map +1 -0
  170. package/dist/llm/providers/cursor-cli.js +106 -0
  171. package/dist/llm/providers/cursor-cli.js.map +1 -0
  172. package/dist/llm/providers/gemini-api.d.ts +20 -0
  173. package/dist/llm/providers/gemini-api.d.ts.map +1 -0
  174. package/dist/llm/providers/gemini-api.js +121 -0
  175. package/dist/llm/providers/gemini-api.js.map +1 -0
  176. package/dist/llm/providers/gemini-cli.d.ts +20 -0
  177. package/dist/llm/providers/gemini-cli.d.ts.map +1 -0
  178. package/dist/llm/providers/gemini-cli.js +109 -0
  179. package/dist/llm/providers/gemini-cli.js.map +1 -0
  180. package/dist/llm/providers/interactive.d.ts +42 -0
  181. package/dist/llm/providers/interactive.d.ts.map +1 -0
  182. package/dist/llm/providers/interactive.js +200 -0
  183. package/dist/llm/providers/interactive.js.map +1 -0
  184. package/dist/llm/providers/openai-api.d.ts +21 -0
  185. package/dist/llm/providers/openai-api.d.ts.map +1 -0
  186. package/dist/llm/providers/openai-api.js +107 -0
  187. package/dist/llm/providers/openai-api.js.map +1 -0
  188. package/dist/llm/types.d.ts +128 -0
  189. package/dist/llm/types.d.ts.map +1 -0
  190. package/dist/llm/types.js +8 -0
  191. package/dist/llm/types.js.map +1 -0
  192. package/dist/parser/index.d.ts +3 -0
  193. package/dist/parser/index.d.ts.map +1 -0
  194. package/dist/parser/index.js +19 -0
  195. package/dist/parser/index.js.map +1 -0
  196. package/dist/parser/path-security.d.ts +40 -0
  197. package/dist/parser/path-security.d.ts.map +1 -0
  198. package/dist/parser/path-security.js +183 -0
  199. package/dist/parser/path-security.js.map +1 -0
  200. package/dist/parser/rule-parser.d.ts +50 -0
  201. package/dist/parser/rule-parser.d.ts.map +1 -0
  202. package/dist/parser/rule-parser.js +203 -0
  203. package/dist/parser/rule-parser.js.map +1 -0
  204. package/dist/schemas/config.d.ts +202 -0
  205. package/dist/schemas/config.d.ts.map +1 -0
  206. package/dist/schemas/config.js +96 -0
  207. package/dist/schemas/config.js.map +1 -0
  208. package/dist/schemas/index.d.ts +3 -0
  209. package/dist/schemas/index.d.ts.map +1 -0
  210. package/dist/schemas/index.js +19 -0
  211. package/dist/schemas/index.js.map +1 -0
  212. package/dist/schemas/rule.d.ts +67 -0
  213. package/dist/schemas/rule.d.ts.map +1 -0
  214. package/dist/schemas/rule.js +44 -0
  215. package/dist/schemas/rule.js.map +1 -0
  216. package/package.json +69 -0
  217. package/templates/architecture.md +35 -0
  218. package/templates/bootstrap-prompt.md +242 -0
  219. package/templates/config.yaml +25 -0
  220. package/templates/project.md +44 -0
  221. package/templates/rules/example.md +36 -0
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Rule selection strategies for compilation
3
+ *
4
+ * Supports filtering and ordering rules by:
5
+ * - Directory: Include rules from specific directories
6
+ * - Glob: Include rules whose globs match current context
7
+ * - Priority: Order rules by priority, select until budget exhausted
8
+ * - Tag: Include rules with specific tags
9
+ */
10
+ import { ParsedRule } from '../schemas/rule';
11
+ import { SelectionStrategy } from '../schemas/config';
12
+ /**
13
+ * Selection context for glob-based matching
14
+ */
15
+ export interface SelectionContext {
16
+ /** Project root directory */
17
+ projectRoot: string;
18
+ /** Files in current context (for glob matching) */
19
+ contextFiles?: string[];
20
+ }
21
+ /**
22
+ * Selection options for filtering rules
23
+ */
24
+ export interface SelectionOptions {
25
+ /** Selection strategy */
26
+ strategy: SelectionStrategy;
27
+ /** Directories to include (for 'directory' strategy) */
28
+ includeDirs?: string[];
29
+ /** Tags to include (for 'tag' strategy) */
30
+ includeTags?: string[];
31
+ /** Maximum token budget */
32
+ maxTokens?: number;
33
+ /** Always include these rule IDs */
34
+ alwaysInclude?: string[];
35
+ }
36
+ /**
37
+ * Result of rule selection
38
+ */
39
+ export interface SelectionResult {
40
+ /** Selected rules */
41
+ rules: ParsedRule[];
42
+ /** Total estimated tokens */
43
+ totalTokens: number;
44
+ /** Rules excluded due to budget */
45
+ excludedByBudget: ParsedRule[];
46
+ /** Rules excluded by filter */
47
+ excludedByFilter: ParsedRule[];
48
+ }
49
+ /**
50
+ * Filter rules by directory
51
+ *
52
+ * @param rules - Rules to filter
53
+ * @param includeDirs - Directories to include
54
+ * @returns Filtered rules
55
+ */
56
+ export declare function filterByDirectory(rules: ParsedRule[], includeDirs: string[]): ParsedRule[];
57
+ /**
58
+ * Filter rules by glob matching against context files
59
+ *
60
+ * @param rules - Rules to filter
61
+ * @param context - Selection context with project root and context files
62
+ * @returns Filtered rules
63
+ */
64
+ export declare function filterByGlob(rules: ParsedRule[], context: SelectionContext): ParsedRule[];
65
+ /**
66
+ * Filter rules by tag
67
+ *
68
+ * @param rules - Rules to filter
69
+ * @param includeTags - Tags to include (at least one must match)
70
+ * @returns Filtered rules
71
+ */
72
+ export declare function filterByTag(rules: ParsedRule[], includeTags: string[]): ParsedRule[];
73
+ /**
74
+ * Sort rules by priority (highest first), then alphabetically by ID
75
+ *
76
+ * @param rules - Rules to sort
77
+ * @returns Sorted rules
78
+ */
79
+ export declare function sortByPriority(rules: ParsedRule[]): ParsedRule[];
80
+ /**
81
+ * Select rules until token budget is exhausted
82
+ *
83
+ * @param rules - Rules to select from (already sorted)
84
+ * @param maxTokens - Maximum token budget
85
+ * @param alwaysIncludeIds - Rule IDs to always include first
86
+ * @returns Selection result with selected rules and metadata
87
+ */
88
+ export declare function selectByBudget(rules: ParsedRule[], maxTokens: number, alwaysIncludeIds?: string[]): SelectionResult;
89
+ /**
90
+ * Select rules using the specified strategy
91
+ *
92
+ * @param rules - All available rules
93
+ * @param options - Selection options
94
+ * @param context - Selection context
95
+ * @returns Selection result
96
+ */
97
+ export declare function selectRules(rules: ParsedRule[], options: SelectionOptions, context: SelectionContext): SelectionResult;
98
+ /**
99
+ * Get rules with always_apply flag set to true
100
+ *
101
+ * @param rules - All rules
102
+ * @returns Rules with always_apply: true
103
+ */
104
+ export declare function getAlwaysApplyRules(rules: ParsedRule[]): ParsedRule[];
105
+ /**
106
+ * Partition rules into always-apply and conditional
107
+ *
108
+ * @param rules - All rules
109
+ * @returns Object with alwaysApply and conditional arrays
110
+ */
111
+ export declare function partitionRules(rules: ParsedRule[]): {
112
+ alwaysApply: ParsedRule[];
113
+ conditional: ParsedRule[];
114
+ };
115
+ //# sourceMappingURL=rule-selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-selector.d.ts","sourceRoot":"","sources":["../../src/compiler/rule-selector.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGtD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yBAAyB;IACzB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,qBAAqB;IACrB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,gBAAgB,EAAE,UAAU,EAAE,CAAC;IAC/B,+BAA+B;IAC/B,gBAAgB,EAAE,UAAU,EAAE,CAAC;CAChC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,CAgB1F;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,gBAAgB,GAAG,UAAU,EAAE,CAqBzF;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,CASpF;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAShE;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,UAAU,EAAE,EACnB,SAAS,EAAE,MAAM,EACjB,gBAAgB,GAAE,MAAM,EAAO,GAC9B,eAAe,CAkCjB;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,gBAAgB,GACxB,eAAe,CA0EjB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAErE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG;IACnD,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B,CAaA"}
@@ -0,0 +1,273 @@
1
+ "use strict";
2
+ /**
3
+ * Rule selection strategies for compilation
4
+ *
5
+ * Supports filtering and ordering rules by:
6
+ * - Directory: Include rules from specific directories
7
+ * - Glob: Include rules whose globs match current context
8
+ * - Priority: Order rules by priority, select until budget exhausted
9
+ * - Tag: Include rules with specific tags
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.filterByDirectory = filterByDirectory;
46
+ exports.filterByGlob = filterByGlob;
47
+ exports.filterByTag = filterByTag;
48
+ exports.sortByPriority = sortByPriority;
49
+ exports.selectByBudget = selectByBudget;
50
+ exports.selectRules = selectRules;
51
+ exports.getAlwaysApplyRules = getAlwaysApplyRules;
52
+ exports.partitionRules = partitionRules;
53
+ const path = __importStar(require("path"));
54
+ const minimatch_1 = require("minimatch");
55
+ const token_estimator_1 = require("./token-estimator");
56
+ /**
57
+ * Filter rules by directory
58
+ *
59
+ * @param rules - Rules to filter
60
+ * @param includeDirs - Directories to include
61
+ * @returns Filtered rules
62
+ */
63
+ function filterByDirectory(rules, includeDirs) {
64
+ if (!includeDirs || includeDirs.length === 0) {
65
+ return rules;
66
+ }
67
+ return rules.filter(rule => {
68
+ const ruleDir = path.dirname(rule.path);
69
+ return includeDirs.some(dir => {
70
+ // Match exact directory or nested subdirectories
71
+ const normalizedDir = dir.replace(/^\/|\/$/g, '');
72
+ const normalizedRuleDir = ruleDir.replace(/^\/|\/$/g, '');
73
+ return normalizedRuleDir === normalizedDir ||
74
+ normalizedRuleDir.startsWith(normalizedDir + '/') ||
75
+ normalizedDir === '.';
76
+ });
77
+ });
78
+ }
79
+ /**
80
+ * Filter rules by glob matching against context files
81
+ *
82
+ * @param rules - Rules to filter
83
+ * @param context - Selection context with project root and context files
84
+ * @returns Filtered rules
85
+ */
86
+ function filterByGlob(rules, context) {
87
+ if (!context.contextFiles || context.contextFiles.length === 0) {
88
+ return rules;
89
+ }
90
+ return rules.filter(rule => {
91
+ // Check if any of the rule's globs match any context file
92
+ for (const glob of rule.effectiveGlobs) {
93
+ try {
94
+ // Use minimatch to check if any context file matches the glob
95
+ for (const contextFile of context.contextFiles) {
96
+ if ((0, minimatch_1.minimatch)(contextFile, glob, { matchBase: true })) {
97
+ return true;
98
+ }
99
+ }
100
+ }
101
+ catch {
102
+ // Invalid glob, skip
103
+ }
104
+ }
105
+ return false;
106
+ });
107
+ }
108
+ /**
109
+ * Filter rules by tag
110
+ *
111
+ * @param rules - Rules to filter
112
+ * @param includeTags - Tags to include (at least one must match)
113
+ * @returns Filtered rules
114
+ */
115
+ function filterByTag(rules, includeTags) {
116
+ if (!includeTags || includeTags.length === 0) {
117
+ return rules;
118
+ }
119
+ return rules.filter(rule => {
120
+ const ruleTags = rule.frontmatter.tags || [];
121
+ return ruleTags.some(tag => includeTags.includes(tag));
122
+ });
123
+ }
124
+ /**
125
+ * Sort rules by priority (highest first), then alphabetically by ID
126
+ *
127
+ * @param rules - Rules to sort
128
+ * @returns Sorted rules
129
+ */
130
+ function sortByPriority(rules) {
131
+ return [...rules].sort((a, b) => {
132
+ const priorityDiff = b.frontmatter.priority - a.frontmatter.priority;
133
+ if (priorityDiff !== 0) {
134
+ return priorityDiff;
135
+ }
136
+ // Equal priority: sort alphabetically by ID
137
+ return a.frontmatter.id.localeCompare(b.frontmatter.id);
138
+ });
139
+ }
140
+ /**
141
+ * Select rules until token budget is exhausted
142
+ *
143
+ * @param rules - Rules to select from (already sorted)
144
+ * @param maxTokens - Maximum token budget
145
+ * @param alwaysIncludeIds - Rule IDs to always include first
146
+ * @returns Selection result with selected rules and metadata
147
+ */
148
+ function selectByBudget(rules, maxTokens, alwaysIncludeIds = []) {
149
+ const effectiveBudget = (0, token_estimator_1.applyBudgetMargin)(maxTokens);
150
+ const selected = [];
151
+ const excludedByBudget = [];
152
+ let totalTokens = 0;
153
+ // First, add always-include rules
154
+ const alwaysInclude = rules.filter(r => alwaysIncludeIds.includes(r.frontmatter.id));
155
+ const remaining = rules.filter(r => !alwaysIncludeIds.includes(r.frontmatter.id));
156
+ for (const rule of alwaysInclude) {
157
+ const tokens = (0, token_estimator_1.estimateTokens)(rule.content).tokens;
158
+ totalTokens += tokens;
159
+ selected.push(rule);
160
+ }
161
+ // Then add remaining rules until budget exhausted
162
+ for (const rule of remaining) {
163
+ const tokens = (0, token_estimator_1.estimateTokens)(rule.content).tokens;
164
+ if (totalTokens + tokens <= effectiveBudget) {
165
+ totalTokens += tokens;
166
+ selected.push(rule);
167
+ }
168
+ else {
169
+ excludedByBudget.push(rule);
170
+ }
171
+ }
172
+ return {
173
+ rules: selected,
174
+ totalTokens,
175
+ excludedByBudget,
176
+ excludedByFilter: [],
177
+ };
178
+ }
179
+ /**
180
+ * Select rules using the specified strategy
181
+ *
182
+ * @param rules - All available rules
183
+ * @param options - Selection options
184
+ * @param context - Selection context
185
+ * @returns Selection result
186
+ */
187
+ function selectRules(rules, options, context) {
188
+ let filtered = [...rules];
189
+ const excludedByFilter = [];
190
+ // Apply strategy-based filtering
191
+ switch (options.strategy) {
192
+ case 'directory':
193
+ if (options.includeDirs) {
194
+ filtered = filterByDirectory(filtered, options.includeDirs);
195
+ excludedByFilter.push(...rules.filter(r => !filtered.includes(r)));
196
+ }
197
+ break;
198
+ case 'glob':
199
+ if (context.contextFiles) {
200
+ filtered = filterByGlob(filtered, context);
201
+ excludedByFilter.push(...rules.filter(r => !filtered.includes(r)));
202
+ }
203
+ break;
204
+ case 'tag':
205
+ if (options.includeTags) {
206
+ filtered = filterByTag(filtered, options.includeTags);
207
+ excludedByFilter.push(...rules.filter(r => !filtered.includes(r)));
208
+ }
209
+ break;
210
+ case 'priority':
211
+ // Priority strategy: sort by priority, no filtering
212
+ break;
213
+ case 'all':
214
+ // Include all rules
215
+ break;
216
+ }
217
+ // Always sort by priority for consistent ordering
218
+ filtered = sortByPriority(filtered);
219
+ // Apply token budget if specified
220
+ if (options.maxTokens !== undefined) {
221
+ // If budget is zero or negative, exclude all rules
222
+ if (options.maxTokens <= 0) {
223
+ return {
224
+ rules: [],
225
+ totalTokens: 0,
226
+ excludedByBudget: filtered,
227
+ excludedByFilter,
228
+ };
229
+ }
230
+ const result = selectByBudget(filtered, options.maxTokens, options.alwaysInclude);
231
+ return {
232
+ ...result,
233
+ excludedByFilter,
234
+ };
235
+ }
236
+ // No budget constraint
237
+ const totalTokens = filtered.reduce((sum, rule) => sum + (0, token_estimator_1.estimateTokens)(rule.content).tokens, 0);
238
+ return {
239
+ rules: filtered,
240
+ totalTokens,
241
+ excludedByBudget: [],
242
+ excludedByFilter,
243
+ };
244
+ }
245
+ /**
246
+ * Get rules with always_apply flag set to true
247
+ *
248
+ * @param rules - All rules
249
+ * @returns Rules with always_apply: true
250
+ */
251
+ function getAlwaysApplyRules(rules) {
252
+ return rules.filter(rule => rule.frontmatter.always_apply === true);
253
+ }
254
+ /**
255
+ * Partition rules into always-apply and conditional
256
+ *
257
+ * @param rules - All rules
258
+ * @returns Object with alwaysApply and conditional arrays
259
+ */
260
+ function partitionRules(rules) {
261
+ const alwaysApply = [];
262
+ const conditional = [];
263
+ for (const rule of rules) {
264
+ if (rule.frontmatter.always_apply) {
265
+ alwaysApply.push(rule);
266
+ }
267
+ else {
268
+ conditional.push(rule);
269
+ }
270
+ }
271
+ return { alwaysApply, conditional };
272
+ }
273
+ //# sourceMappingURL=rule-selector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-selector.js","sourceRoot":"","sources":["../../src/compiler/rule-selector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Content-aware token estimation for AI context budget control
3
+ *
4
+ * Uses character-to-token ratios based on content type:
5
+ * - Prose (English text): 3.5 chars/token
6
+ * - Code (programming languages): 2.5 chars/token
7
+ * - Mixed content: 3.0 chars/token
8
+ * - CJK (Chinese, Japanese, Korean): 1.5 chars/token
9
+ */
10
+ /**
11
+ * Content type for token estimation
12
+ */
13
+ export type ContentType = 'prose' | 'code' | 'mixed' | 'cjk';
14
+ /**
15
+ * Token estimation result
16
+ */
17
+ export interface TokenEstimation {
18
+ /** Estimated token count */
19
+ tokens: number;
20
+ /** Detected content type */
21
+ contentType: ContentType;
22
+ /** Character count */
23
+ characters: number;
24
+ /** Ratio used for estimation */
25
+ ratio: number;
26
+ }
27
+ /**
28
+ * Detect content type from text content
29
+ *
30
+ * @param content - Text content to analyze
31
+ * @returns Detected content type
32
+ */
33
+ export declare function detectContentType(content: string): ContentType;
34
+ /**
35
+ * Estimate token count for content
36
+ *
37
+ * @param content - Text content to estimate
38
+ * @returns Token estimation with count, type, and ratio
39
+ */
40
+ export declare function estimateTokens(content: string): TokenEstimation;
41
+ /**
42
+ * Estimate tokens with a specific content type override
43
+ *
44
+ * @param content - Text content to estimate
45
+ * @param contentType - Override content type
46
+ * @returns Token estimation
47
+ */
48
+ export declare function estimateTokensWithType(content: string, contentType: ContentType): TokenEstimation;
49
+ /**
50
+ * Apply budget margin for metadata overhead
51
+ *
52
+ * @param budget - Original token budget
53
+ * @param marginPercent - Margin percentage (default: 5%)
54
+ * @returns Effective budget after margin
55
+ */
56
+ export declare function applyBudgetMargin(budget: number, marginPercent?: number): number;
57
+ /**
58
+ * Check if adding content would exceed budget
59
+ *
60
+ * @param currentTokens - Current token count
61
+ * @param additionalContent - Content to add
62
+ * @param budget - Token budget
63
+ * @param marginPercent - Margin percentage (default: 5%)
64
+ * @returns true if budget would be exceeded
65
+ */
66
+ export declare function wouldExceedBudget(currentTokens: number, additionalContent: string, budget: number, marginPercent?: number): boolean;
67
+ /**
68
+ * Get the character-to-token ratio for a content type
69
+ *
70
+ * @param contentType - Content type
71
+ * @returns Character-to-token ratio
72
+ */
73
+ export declare function getRatio(contentType: ContentType): number;
74
+ //# sourceMappingURL=token-estimator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-estimator.d.ts","sourceRoot":"","sources":["../../src/compiler/token-estimator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,WAAW,EAAE,WAAW,CAAC;IACzB,sBAAsB;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;CACf;AAmDD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAoD9D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAsB/D;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,GAAG,eAAe,CAWjG;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,GAAE,MAAU,GAAG,MAAM,CAEnF;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,MAAM,EACrB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,aAAa,GAAE,MAAU,GACxB,OAAO,CAIT;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CAEzD"}
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ /**
3
+ * Content-aware token estimation for AI context budget control
4
+ *
5
+ * Uses character-to-token ratios based on content type:
6
+ * - Prose (English text): 3.5 chars/token
7
+ * - Code (programming languages): 2.5 chars/token
8
+ * - Mixed content: 3.0 chars/token
9
+ * - CJK (Chinese, Japanese, Korean): 1.5 chars/token
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.detectContentType = detectContentType;
13
+ exports.estimateTokens = estimateTokens;
14
+ exports.estimateTokensWithType = estimateTokensWithType;
15
+ exports.applyBudgetMargin = applyBudgetMargin;
16
+ exports.wouldExceedBudget = wouldExceedBudget;
17
+ exports.getRatio = getRatio;
18
+ /**
19
+ * Character-to-token ratios by content type
20
+ */
21
+ const TOKEN_RATIOS = {
22
+ prose: 3.5,
23
+ code: 2.5,
24
+ mixed: 3.0,
25
+ cjk: 1.5,
26
+ };
27
+ /**
28
+ * Code indicators for content type detection
29
+ */
30
+ const CODE_INDICATORS = [
31
+ /\bimport\s+/,
32
+ /\bexport\s+/,
33
+ /\bfunction\s+/,
34
+ /\bclass\s+/,
35
+ /\bconst\s+/,
36
+ /\blet\s+/,
37
+ /\bvar\s+/,
38
+ /\bdef\s+/,
39
+ /\basync\s+/,
40
+ /=>/,
41
+ /\breturn\s+/,
42
+ /\bif\s*\(/,
43
+ /\bfor\s*\(/,
44
+ /\bwhile\s*\(/,
45
+ /\bswitch\s*\(/,
46
+ /\{\s*$/m,
47
+ /^\s*\}/m,
48
+ ];
49
+ /**
50
+ * CJK Unicode ranges
51
+ * - CJK Unified Ideographs: U+4E00-U+9FFF
52
+ * - CJK Extension A: U+3400-U+4DBF
53
+ * - Hiragana: U+3040-U+309F
54
+ * - Katakana: U+30A0-U+30FF
55
+ * - Hangul Syllables: U+AC00-U+D7AF
56
+ */
57
+ const CJK_PATTERN = /[\u4E00-\u9FFF\u3400-\u4DBF\u3040-\u309F\u30A0-\u30FF\uAC00-\uD7AF]/g;
58
+ /**
59
+ * Threshold for content type detection (percentage of content)
60
+ */
61
+ const CODE_INDICATOR_THRESHOLD = 3; // Minimum matches to consider code
62
+ const CJK_RATIO_THRESHOLD = 0.3; // 30% CJK characters
63
+ /**
64
+ * Detect content type from text content
65
+ *
66
+ * @param content - Text content to analyze
67
+ * @returns Detected content type
68
+ */
69
+ function detectContentType(content) {
70
+ if (!content || content.length === 0) {
71
+ return 'mixed';
72
+ }
73
+ // Check for CJK content first
74
+ const cjkMatches = content.match(CJK_PATTERN) || [];
75
+ const cjkRatio = cjkMatches.length / content.length;
76
+ if (cjkRatio >= CJK_RATIO_THRESHOLD) {
77
+ return 'cjk';
78
+ }
79
+ // Count code indicators
80
+ let codeIndicatorCount = 0;
81
+ for (const indicator of CODE_INDICATORS) {
82
+ const matches = content.match(new RegExp(indicator, 'g')) || [];
83
+ codeIndicatorCount += matches.length;
84
+ }
85
+ // If enough code indicators, consider it code
86
+ if (codeIndicatorCount >= CODE_INDICATOR_THRESHOLD) {
87
+ return 'code';
88
+ }
89
+ // Check if it looks like markdown prose
90
+ const lines = content.split('\n');
91
+ const proseIndicators = [
92
+ /^#+\s+/, // Markdown headers
93
+ /^\s*[-*]\s+/, // Bullet points
94
+ /^\d+\.\s+/, // Numbered lists
95
+ /\*\*[^*]+\*\*/, // Bold text
96
+ /\*[^*]+\*/, // Italic text
97
+ ];
98
+ let proseCount = 0;
99
+ for (const line of lines) {
100
+ for (const indicator of proseIndicators) {
101
+ if (indicator.test(line)) {
102
+ proseCount++;
103
+ break;
104
+ }
105
+ }
106
+ }
107
+ // If significant prose indicators and low code indicators
108
+ if (proseCount >= 3 && codeIndicatorCount < CODE_INDICATOR_THRESHOLD) {
109
+ return 'prose';
110
+ }
111
+ // Default to mixed
112
+ return 'mixed';
113
+ }
114
+ /**
115
+ * Estimate token count for content
116
+ *
117
+ * @param content - Text content to estimate
118
+ * @returns Token estimation with count, type, and ratio
119
+ */
120
+ function estimateTokens(content) {
121
+ const characters = content.length;
122
+ if (characters === 0) {
123
+ return {
124
+ tokens: 0,
125
+ contentType: 'mixed',
126
+ characters: 0,
127
+ ratio: TOKEN_RATIOS.mixed,
128
+ };
129
+ }
130
+ const contentType = detectContentType(content);
131
+ const ratio = TOKEN_RATIOS[contentType];
132
+ const tokens = Math.ceil(characters / ratio);
133
+ return {
134
+ tokens,
135
+ contentType,
136
+ characters,
137
+ ratio,
138
+ };
139
+ }
140
+ /**
141
+ * Estimate tokens with a specific content type override
142
+ *
143
+ * @param content - Text content to estimate
144
+ * @param contentType - Override content type
145
+ * @returns Token estimation
146
+ */
147
+ function estimateTokensWithType(content, contentType) {
148
+ const characters = content.length;
149
+ const ratio = TOKEN_RATIOS[contentType];
150
+ const tokens = Math.ceil(characters / ratio);
151
+ return {
152
+ tokens,
153
+ contentType,
154
+ characters,
155
+ ratio,
156
+ };
157
+ }
158
+ /**
159
+ * Apply budget margin for metadata overhead
160
+ *
161
+ * @param budget - Original token budget
162
+ * @param marginPercent - Margin percentage (default: 5%)
163
+ * @returns Effective budget after margin
164
+ */
165
+ function applyBudgetMargin(budget, marginPercent = 5) {
166
+ return Math.floor(budget * (1 - marginPercent / 100));
167
+ }
168
+ /**
169
+ * Check if adding content would exceed budget
170
+ *
171
+ * @param currentTokens - Current token count
172
+ * @param additionalContent - Content to add
173
+ * @param budget - Token budget
174
+ * @param marginPercent - Margin percentage (default: 5%)
175
+ * @returns true if budget would be exceeded
176
+ */
177
+ function wouldExceedBudget(currentTokens, additionalContent, budget, marginPercent = 5) {
178
+ const effectiveBudget = applyBudgetMargin(budget, marginPercent);
179
+ const additionalTokens = estimateTokens(additionalContent).tokens;
180
+ return currentTokens + additionalTokens > effectiveBudget;
181
+ }
182
+ /**
183
+ * Get the character-to-token ratio for a content type
184
+ *
185
+ * @param contentType - Content type
186
+ * @returns Character-to-token ratio
187
+ */
188
+ function getRatio(contentType) {
189
+ return TOKEN_RATIOS[contentType];
190
+ }
191
+ //# sourceMappingURL=token-estimator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-estimator.js","sourceRoot":"","sources":["../../src/compiler/token-estimator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from './loader';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}