contextos-agents 1.7.0 → 2.0.0-beta.3

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 (313) hide show
  1. package/.agents/AGENTS.md +16 -50
  2. package/.agents/adapters/aider/export.js +117 -99
  3. package/.agents/adapters/claude/export.js +68 -26
  4. package/.agents/adapters/copilot/export.js +90 -53
  5. package/.agents/adapters/cursor/export.js +100 -104
  6. package/.agents/adapters/drift-detector.js +196 -0
  7. package/.agents/adapters/gemini/export.js +76 -45
  8. package/.agents/adapters/pure-compiler.js +443 -0
  9. package/.agents/adapters/zed/export.js +104 -96
  10. package/.agents/compiled/registry.v2.json +504 -0
  11. package/.agents/compiled/registry.v2.sha256 +1 -0
  12. package/.agents/compiler/manifest-compiler.js +963 -0
  13. package/.agents/compiler/vendor/yaml.LICENSE.txt +13 -0
  14. package/.agents/compiler/vendor/yaml.SBOM.json +6 -0
  15. package/.agents/compiler/vendor/yaml.js +139 -0
  16. package/.agents/core/profiles/init.yaml +25 -0
  17. package/.agents/core/skills/context-manager/skill.yaml +3 -5
  18. package/.agents/core/skills/context-os/SKILL.md +3 -6
  19. package/.agents/core/skills/context-os/skill.yaml +3 -8
  20. package/.agents/core/skills/engineering-workflow/skill.yaml +1 -7
  21. package/.agents/core/skills/gemini-precision/skill.yaml +1 -6
  22. package/.agents/core/skills/gstack-roles/skill.yaml +3 -6
  23. package/.agents/core/skills/ponytail-mindset/skill.yaml +1 -7
  24. package/.agents/core/skills/security/skill.yaml +15 -3
  25. package/.agents/ctx.js +537 -112
  26. package/.agents/customization-dx.js +282 -0
  27. package/.agents/doctor.js +855 -66
  28. package/.agents/filesystem/index.js +71 -0
  29. package/.agents/filesystem/journaled-transaction.js +451 -0
  30. package/.agents/filesystem/lockfile-v2.js +275 -0
  31. package/.agents/filesystem/platform-hardening.js +222 -0
  32. package/.agents/filesystem/project-lock.js +218 -0
  33. package/.agents/filesystem/safe-path.js +256 -0
  34. package/.agents/generated/claude/skills/context-os/SKILL.md +1 -1
  35. package/.agents/generated/gemini/skills/context-os/SKILL.md +2 -2
  36. package/.agents/plugins/contextos/plugin.json +1 -1
  37. package/.agents/plugins.js +278 -64
  38. package/.agents/profiles.js +486 -51
  39. package/.agents/resolver/canonical-resolver.js +1348 -0
  40. package/.agents/resolver.js +50 -534
  41. package/.agents/rules/rule-catalog.js +525 -0
  42. package/.agents/schemas/attestation.review.v1.json +111 -0
  43. package/.agents/schemas/attestation.verification.v1.json +85 -0
  44. package/.agents/schemas/lockfile.v2.schema.json +134 -0
  45. package/.agents/schemas/profile.v2.schema.json +114 -0
  46. package/.agents/schemas/runtime.thread.v1.json +192 -0
  47. package/.agents/schemas/skill.manifest.v2.json +177 -0
  48. package/.agents/schemas/verification.spec.v1.json +39 -0
  49. package/.agents/schemas/workspace.graph.schema.json +106 -0
  50. package/.agents/skills-index.json +6 -166
  51. package/.agents/stats.js +9 -9
  52. package/.agents/transaction-core/event-store.js +288 -0
  53. package/.agents/transaction-core/idempotency.js +129 -0
  54. package/.agents/transaction-core/ipc-lock.js +311 -0
  55. package/.agents/transaction-core/plugin-supply-chain-bundle.js +436 -0
  56. package/.agents/validate.js +44 -1
  57. package/.agents/watch.js +354 -102
  58. package/.agents/workspace/workspace-graph.js +778 -0
  59. package/README.md +59 -387
  60. package/benchmarks/v2/analysis/statistics.js +140 -0
  61. package/benchmarks/v2/analysis/stats.js +69 -0
  62. package/benchmarks/v2/arms/arm-definitions.js +79 -0
  63. package/benchmarks/v2/dataset.schema.json +34 -0
  64. package/benchmarks/v2/evaluators/index.js +25 -0
  65. package/benchmarks/v2/evaluators/verified-success.js +116 -0
  66. package/benchmarks/v2/harness/runner.js +88 -0
  67. package/benchmarks/v2/pilot-tasks.json +392 -0
  68. package/bin/commands/recover.js +88 -0
  69. package/bin/commands/update.js +80 -17
  70. package/bin/commands.js +62 -25
  71. package/bin/index.js +138 -81
  72. package/bin/lib/lockfile.js +5 -3
  73. package/bin/lib/safe-writer.js +34 -3
  74. package/package.json +87 -72
  75. package/registry.json +2 -2
  76. package/registry.v2.schema.json +86 -0
  77. package/.agents/core/profiles/backend.yaml +0 -47
  78. package/.agents/core/profiles/enterprise.yaml +0 -46
  79. package/.agents/core/profiles/frontend.yaml +0 -46
  80. package/.agents/core/profiles/hackathon.yaml +0 -45
  81. package/.agents/core/profiles/mvp.yaml +0 -44
  82. package/.agents/core/profiles/startup.yaml +0 -48
  83. package/.agents/core/skills/adapters/EXAMPLES.md +0 -19
  84. package/.agents/core/skills/adapters/SKILL.md +0 -105
  85. package/.agents/core/skills/adapters/TROUBLESHOOTING.md +0 -7
  86. package/.agents/core/skills/adapters/VALIDATION.json +0 -12
  87. package/.agents/core/skills/adapters/skill.yaml +0 -16
  88. package/.agents/core/skills/architecture-diagrams/SKILL.md +0 -108
  89. package/.agents/core/skills/architecture-diagrams/VALIDATION.json +0 -12
  90. package/.agents/core/skills/architecture-diagrams/skill.yaml +0 -12
  91. package/.agents/core/skills/brutalist-design/SKILL.md +0 -150
  92. package/.agents/core/skills/brutalist-design/VALIDATION.json +0 -12
  93. package/.agents/core/skills/brutalist-design/skill.yaml +0 -12
  94. package/.agents/core/skills/database/EXAMPLES.md +0 -74
  95. package/.agents/core/skills/database/SKILL.md +0 -101
  96. package/.agents/core/skills/database/TROUBLESHOOTING.md +0 -18
  97. package/.agents/core/skills/database/VALIDATION.json +0 -11
  98. package/.agents/core/skills/database/skill.yaml +0 -31
  99. package/.agents/core/skills/ddd/EXAMPLES.md +0 -42
  100. package/.agents/core/skills/ddd/SKILL.md +0 -247
  101. package/.agents/core/skills/ddd/TROUBLESHOOTING.md +0 -19
  102. package/.agents/core/skills/ddd/VALIDATION.json +0 -12
  103. package/.agents/core/skills/ddd/ddd.md +0 -178
  104. package/.agents/core/skills/ddd/skill.yaml +0 -17
  105. package/.agents/core/skills/decisions/EXAMPLES.md +0 -35
  106. package/.agents/core/skills/decisions/SKILL.md +0 -90
  107. package/.agents/core/skills/decisions/TROUBLESHOOTING.md +0 -13
  108. package/.agents/core/skills/decisions/VALIDATION.json +0 -12
  109. package/.agents/core/skills/decisions/skill.yaml +0 -16
  110. package/.agents/core/skills/docker/EXAMPLES.md +0 -56
  111. package/.agents/core/skills/docker/SKILL.md +0 -63
  112. package/.agents/core/skills/docker/TROUBLESHOOTING.md +0 -18
  113. package/.agents/core/skills/docker/VALIDATION.json +0 -11
  114. package/.agents/core/skills/docker/skill.yaml +0 -29
  115. package/.agents/core/skills/fastapi/EXAMPLES.md +0 -36
  116. package/.agents/core/skills/fastapi/SKILL.md +0 -148
  117. package/.agents/core/skills/fastapi/TROUBLESHOOTING.md +0 -19
  118. package/.agents/core/skills/fastapi/VALIDATION.json +0 -12
  119. package/.agents/core/skills/fastapi/fastapi.md +0 -112
  120. package/.agents/core/skills/fastapi/skill.yaml +0 -17
  121. package/.agents/core/skills/generators/EXAMPLES.md +0 -19
  122. package/.agents/core/skills/generators/SKILL.md +0 -112
  123. package/.agents/core/skills/generators/TROUBLESHOOTING.md +0 -7
  124. package/.agents/core/skills/generators/VALIDATION.json +0 -12
  125. package/.agents/core/skills/generators/skill.yaml +0 -25
  126. package/.agents/core/skills/generators/templates/API.md +0 -77
  127. package/.agents/core/skills/generators/templates/ARCHITECTURE.md +0 -70
  128. package/.agents/core/skills/generators/templates/DATABASE.md +0 -42
  129. package/.agents/core/skills/generators/templates/DECISION.md +0 -46
  130. package/.agents/core/skills/generators/templates/PRD.md +0 -67
  131. package/.agents/core/skills/generators/templates/PROJECT_GRAPH.md +0 -56
  132. package/.agents/core/skills/generators/templates/ROADMAP.md +0 -51
  133. package/.agents/core/skills/generators/templates/TASKS.md +0 -43
  134. package/.agents/core/skills/generators/templates/UI.md +0 -73
  135. package/.agents/core/skills/graphify/EXAMPLES.md +0 -73
  136. package/.agents/core/skills/graphify/SKILL.md +0 -130
  137. package/.agents/core/skills/graphify/VALIDATION.json +0 -12
  138. package/.agents/core/skills/graphify/skill.yaml +0 -18
  139. package/.agents/core/skills/impeccable-design/EXAMPLES.md +0 -26
  140. package/.agents/core/skills/impeccable-design/SKILL.md +0 -201
  141. package/.agents/core/skills/impeccable-design/TROUBLESHOOTING.md +0 -19
  142. package/.agents/core/skills/impeccable-design/VALIDATION.json +0 -12
  143. package/.agents/core/skills/impeccable-design/skill.yaml +0 -20
  144. package/.agents/core/skills/interview-me/SKILL.md +0 -97
  145. package/.agents/core/skills/interview-me/VALIDATION.json +0 -12
  146. package/.agents/core/skills/interview-me/skill.yaml +0 -12
  147. package/.agents/core/skills/microservices/EXAMPLES.md +0 -38
  148. package/.agents/core/skills/microservices/SKILL.md +0 -164
  149. package/.agents/core/skills/microservices/TROUBLESHOOTING.md +0 -19
  150. package/.agents/core/skills/microservices/VALIDATION.json +0 -12
  151. package/.agents/core/skills/microservices/microservices.md +0 -119
  152. package/.agents/core/skills/microservices/skill.yaml +0 -17
  153. package/.agents/core/skills/minimalist-design/SKILL.md +0 -113
  154. package/.agents/core/skills/minimalist-design/VALIDATION.json +0 -12
  155. package/.agents/core/skills/minimalist-design/skill.yaml +0 -12
  156. package/.agents/core/skills/nestjs/EXAMPLES.md +0 -40
  157. package/.agents/core/skills/nestjs/SKILL.md +0 -139
  158. package/.agents/core/skills/nestjs/TROUBLESHOOTING.md +0 -19
  159. package/.agents/core/skills/nestjs/VALIDATION.json +0 -12
  160. package/.agents/core/skills/nestjs/nestjs.md +0 -103
  161. package/.agents/core/skills/nestjs/skill.yaml +0 -17
  162. package/.agents/core/skills/nextjs/EXAMPLES.md +0 -40
  163. package/.agents/core/skills/nextjs/SKILL.md +0 -163
  164. package/.agents/core/skills/nextjs/TROUBLESHOOTING.md +0 -19
  165. package/.agents/core/skills/nextjs/VALIDATION.json +0 -12
  166. package/.agents/core/skills/nextjs/nextjs.md +0 -67
  167. package/.agents/core/skills/nextjs/skill.yaml +0 -17
  168. package/.agents/core/skills/node/EXAMPLES.md +0 -80
  169. package/.agents/core/skills/node/SKILL.md +0 -128
  170. package/.agents/core/skills/node/TROUBLESHOOTING.md +0 -19
  171. package/.agents/core/skills/node/VALIDATION.json +0 -12
  172. package/.agents/core/skills/node/node.md +0 -87
  173. package/.agents/core/skills/node/skill.yaml +0 -17
  174. package/.agents/core/skills/performance/EXAMPLES.md +0 -30
  175. package/.agents/core/skills/performance/SKILL.md +0 -75
  176. package/.agents/core/skills/performance/TROUBLESHOOTING.md +0 -19
  177. package/.agents/core/skills/performance/VALIDATION.json +0 -12
  178. package/.agents/core/skills/performance/performance.md +0 -52
  179. package/.agents/core/skills/performance/skill.yaml +0 -17
  180. package/.agents/core/skills/react/EXAMPLES.md +0 -79
  181. package/.agents/core/skills/react/SKILL.md +0 -132
  182. package/.agents/core/skills/react/TROUBLESHOOTING.md +0 -19
  183. package/.agents/core/skills/react/VALIDATION.json +0 -12
  184. package/.agents/core/skills/react/react.md +0 -93
  185. package/.agents/core/skills/react/skill.yaml +0 -17
  186. package/.agents/core/skills/react-best-practices/SKILL.md +0 -155
  187. package/.agents/core/skills/react-best-practices/VALIDATION.json +0 -12
  188. package/.agents/core/skills/react-best-practices/skill.yaml +0 -14
  189. package/.agents/core/skills/redesign-audit/SKILL.md +0 -117
  190. package/.agents/core/skills/redesign-audit/VALIDATION.json +0 -12
  191. package/.agents/core/skills/redesign-audit/skill.yaml +0 -12
  192. package/.agents/core/skills/soft-design/SKILL.md +0 -108
  193. package/.agents/core/skills/soft-design/VALIDATION.json +0 -12
  194. package/.agents/core/skills/soft-design/skill.yaml +0 -12
  195. package/.agents/core/skills/state-management/EXAMPLES.md +0 -56
  196. package/.agents/core/skills/state-management/SKILL.md +0 -48
  197. package/.agents/core/skills/state-management/TROUBLESHOOTING.md +0 -18
  198. package/.agents/core/skills/state-management/VALIDATION.json +0 -11
  199. package/.agents/core/skills/state-management/skill.yaml +0 -28
  200. package/.agents/core/skills/subagent-orchestrator/SKILL.md +0 -117
  201. package/.agents/core/skills/subagent-orchestrator/VALIDATION.json +0 -12
  202. package/.agents/core/skills/subagent-orchestrator/skill.yaml +0 -12
  203. package/.agents/core/skills/system-design/EXAMPLES.md +0 -75
  204. package/.agents/core/skills/system-design/SKILL.md +0 -419
  205. package/.agents/core/skills/system-design/TROUBLESHOOTING.md +0 -19
  206. package/.agents/core/skills/system-design/VALIDATION.json +0 -12
  207. package/.agents/core/skills/system-design/skill.yaml +0 -20
  208. package/.agents/core/skills/system-design/system-design.md +0 -112
  209. package/.agents/core/skills/testing/EXAMPLES.md +0 -71
  210. package/.agents/core/skills/testing/SKILL.md +0 -70
  211. package/.agents/core/skills/testing/TROUBLESHOOTING.md +0 -18
  212. package/.agents/core/skills/testing/VALIDATION.json +0 -11
  213. package/.agents/core/skills/testing/skill.yaml +0 -32
  214. package/.agents/core/skills/typescript/EXAMPLES.md +0 -64
  215. package/.agents/core/skills/typescript/SKILL.md +0 -112
  216. package/.agents/core/skills/typescript/TROUBLESHOOTING.md +0 -19
  217. package/.agents/core/skills/typescript/VALIDATION.json +0 -12
  218. package/.agents/core/skills/typescript/skill.yaml +0 -17
  219. package/.agents/core/skills/typescript/typescript.md +0 -71
  220. package/.agents/core/skills/ui-design/EXAMPLES.md +0 -21
  221. package/.agents/core/skills/ui-design/SKILL.md +0 -124
  222. package/.agents/core/skills/ui-design/TROUBLESHOOTING.md +0 -19
  223. package/.agents/core/skills/ui-design/VALIDATION.json +0 -12
  224. package/.agents/core/skills/ui-design/skill.yaml +0 -17
  225. package/.agents/core/skills/ui-design/ui.md +0 -88
  226. package/.agents/core/skills/ui-ux-pro/EXAMPLES.md +0 -62
  227. package/.agents/core/skills/ui-ux-pro/SKILL.md +0 -375
  228. package/.agents/core/skills/ui-ux-pro/TROUBLESHOOTING.md +0 -19
  229. package/.agents/core/skills/ui-ux-pro/VALIDATION.json +0 -12
  230. package/.agents/core/skills/ui-ux-pro/skill.yaml +0 -19
  231. package/.agents/core/skills/ux-design/EXAMPLES.md +0 -36
  232. package/.agents/core/skills/ux-design/SKILL.md +0 -116
  233. package/.agents/core/skills/ux-design/TROUBLESHOOTING.md +0 -19
  234. package/.agents/core/skills/ux-design/VALIDATION.json +0 -12
  235. package/.agents/core/skills/ux-design/skill.yaml +0 -17
  236. package/.agents/core/skills/ux-design/ux.md +0 -80
  237. package/.agents/core/skills/vercel-optimize/SKILL.md +0 -83
  238. package/.agents/core/skills/vercel-optimize/VALIDATION.json +0 -12
  239. package/.agents/core/skills/vercel-optimize/scripts/collect-signals.mjs +0 -131
  240. package/.agents/core/skills/vercel-optimize/scripts/gate-investigations.mjs +0 -142
  241. package/.agents/core/skills/vercel-optimize/scripts/merge-signals.mjs +0 -143
  242. package/.agents/core/skills/vercel-optimize/scripts/scan-codebase.mjs +0 -174
  243. package/.agents/core/skills/vercel-optimize/skill.yaml +0 -18
  244. package/.agents/core/skills/web-accessibility/EXAMPLES.md +0 -39
  245. package/.agents/core/skills/web-accessibility/SKILL.md +0 -170
  246. package/.agents/core/skills/web-accessibility/TROUBLESHOOTING.md +0 -19
  247. package/.agents/core/skills/web-accessibility/VALIDATION.json +0 -12
  248. package/.agents/core/skills/web-accessibility/accessibility.md +0 -63
  249. package/.agents/core/skills/web-accessibility/skill.yaml +0 -17
  250. package/.agents/generated/claude/skills/adapters/SKILL.md +0 -126
  251. package/.agents/generated/claude/skills/architecture-diagrams/SKILL.md +0 -101
  252. package/.agents/generated/claude/skills/brutalist-design/SKILL.md +0 -145
  253. package/.agents/generated/claude/skills/database/SKILL.md +0 -191
  254. package/.agents/generated/claude/skills/ddd/SKILL.md +0 -305
  255. package/.agents/generated/claude/skills/decisions/SKILL.md +0 -134
  256. package/.agents/generated/claude/skills/docker/SKILL.md +0 -135
  257. package/.agents/generated/claude/skills/fastapi/SKILL.md +0 -200
  258. package/.agents/generated/claude/skills/generators/SKILL.md +0 -133
  259. package/.agents/generated/claude/skills/graphify/SKILL.md +0 -198
  260. package/.agents/generated/claude/skills/impeccable-design/SKILL.md +0 -241
  261. package/.agents/generated/claude/skills/interview-me/SKILL.md +0 -90
  262. package/.agents/generated/claude/skills/microservices/SKILL.md +0 -218
  263. package/.agents/generated/claude/skills/minimalist-design/SKILL.md +0 -108
  264. package/.agents/generated/claude/skills/nestjs/SKILL.md +0 -195
  265. package/.agents/generated/claude/skills/nextjs/SKILL.md +0 -219
  266. package/.agents/generated/claude/skills/node/SKILL.md +0 -224
  267. package/.agents/generated/claude/skills/performance/SKILL.md +0 -121
  268. package/.agents/generated/claude/skills/react/SKILL.md +0 -227
  269. package/.agents/generated/claude/skills/react-best-practices/SKILL.md +0 -146
  270. package/.agents/generated/claude/skills/redesign-audit/SKILL.md +0 -112
  271. package/.agents/generated/claude/skills/soft-design/SKILL.md +0 -103
  272. package/.agents/generated/claude/skills/state-management/SKILL.md +0 -120
  273. package/.agents/generated/claude/skills/subagent-orchestrator/SKILL.md +0 -110
  274. package/.agents/generated/claude/skills/system-design/SKILL.md +0 -507
  275. package/.agents/generated/claude/skills/testing/SKILL.md +0 -157
  276. package/.agents/generated/claude/skills/typescript/SKILL.md +0 -192
  277. package/.agents/generated/claude/skills/ui-design/SKILL.md +0 -161
  278. package/.agents/generated/claude/skills/ui-ux-pro/SKILL.md +0 -451
  279. package/.agents/generated/claude/skills/ux-design/SKILL.md +0 -168
  280. package/.agents/generated/claude/skills/vercel-optimize/SKILL.md +0 -76
  281. package/.agents/generated/claude/skills/web-accessibility/SKILL.md +0 -225
  282. package/.agents/generated/gemini/skills/adapters/SKILL.md +0 -135
  283. package/.agents/generated/gemini/skills/architecture-diagrams/SKILL.md +0 -107
  284. package/.agents/generated/gemini/skills/brutalist-design/SKILL.md +0 -151
  285. package/.agents/generated/gemini/skills/database/SKILL.md +0 -200
  286. package/.agents/generated/gemini/skills/ddd/SKILL.md +0 -314
  287. package/.agents/generated/gemini/skills/decisions/SKILL.md +0 -143
  288. package/.agents/generated/gemini/skills/docker/SKILL.md +0 -144
  289. package/.agents/generated/gemini/skills/fastapi/SKILL.md +0 -209
  290. package/.agents/generated/gemini/skills/generators/SKILL.md +0 -142
  291. package/.agents/generated/gemini/skills/graphify/SKILL.md +0 -205
  292. package/.agents/generated/gemini/skills/impeccable-design/SKILL.md +0 -250
  293. package/.agents/generated/gemini/skills/interview-me/SKILL.md +0 -96
  294. package/.agents/generated/gemini/skills/microservices/SKILL.md +0 -227
  295. package/.agents/generated/gemini/skills/minimalist-design/SKILL.md +0 -114
  296. package/.agents/generated/gemini/skills/nestjs/SKILL.md +0 -204
  297. package/.agents/generated/gemini/skills/nextjs/SKILL.md +0 -298
  298. package/.agents/generated/gemini/skills/node/SKILL.md +0 -323
  299. package/.agents/generated/gemini/skills/performance/SKILL.md +0 -185
  300. package/.agents/generated/gemini/skills/react/SKILL.md +0 -332
  301. package/.agents/generated/gemini/skills/react-best-practices/SKILL.md +0 -152
  302. package/.agents/generated/gemini/skills/redesign-audit/SKILL.md +0 -118
  303. package/.agents/generated/gemini/skills/soft-design/SKILL.md +0 -109
  304. package/.agents/generated/gemini/skills/state-management/SKILL.md +0 -129
  305. package/.agents/generated/gemini/skills/subagent-orchestrator/SKILL.md +0 -116
  306. package/.agents/generated/gemini/skills/system-design/SKILL.md +0 -631
  307. package/.agents/generated/gemini/skills/testing/SKILL.md +0 -166
  308. package/.agents/generated/gemini/skills/typescript/SKILL.md +0 -275
  309. package/.agents/generated/gemini/skills/ui-design/SKILL.md +0 -170
  310. package/.agents/generated/gemini/skills/ui-ux-pro/SKILL.md +0 -460
  311. package/.agents/generated/gemini/skills/ux-design/SKILL.md +0 -177
  312. package/.agents/generated/gemini/skills/vercel-optimize/SKILL.md +0 -82
  313. package/.agents/generated/gemini/skills/web-accessibility/SKILL.md +0 -300
@@ -2,564 +2,80 @@
2
2
  * .agents/resolver.js
3
3
  * ContextOS — Dynamic Skill Resolver & Progressive Index Engine
4
4
  *
5
- * Resolves the minimal set of skills required for a given task, file list, or prompt,
6
- * keeping the LLM's active context lean and fast.
5
+ * Unified facade wrapping CanonicalResolver for 100% CLI and MCP parity.
6
+ * Implements evidence-based scoring, transitive closures, token budget planning,
7
+ * and transparent explainability.
7
8
  */
8
9
 
9
10
  'use strict';
10
11
 
11
- const fs = require('fs');
12
- const path = require('path');
13
-
14
- const AGENTS_DIR = path.join(__dirname);
15
- const CORE_SKILLS_DIR = path.join(AGENTS_DIR, 'core', 'skills');
16
-
17
- /**
18
- * Keyword & Regex matching rules for dynamic resolution.
19
- */
20
- const SKILL_RULES = [
21
- {
22
- skill: 'nextjs',
23
- category: 'stack',
24
- strong: [/\bnext(?:\.js)?\b/i, /\bapp\s*router\b/i, /\bserver\s*actions?\b/i, /\brsc\b/i, /некст/i],
25
- medium: [/\bpage\.tsx\b/i, /\blayout\.tsx\b/i],
26
- weak: [],
27
- fileGlobs: [/app\/.*\.(tsx|jsx|ts|js)$/, /next\.config\./],
28
- },
29
- {
30
- skill: 'react',
31
- category: 'stack',
32
- strong: [/\breact\b/i, /\buseOptimistic\b/i, /компонент/i, /хук/i],
33
- medium: [/\bcomponent\b/i, /\bhooks?\b/i, /\buseState\b/i, /\buseEffect\b/i, /\buseMemo\b/i, /\bprops\b/i, /модал\w*/i],
34
- weak: [],
35
- fileGlobs: [/\.(tsx|jsx)$/],
36
- },
37
- {
38
- skill: 'typescript',
39
- category: 'stack',
40
- strong: [/\btypescript\b/i, /\btype-?safe\b/i, /\bgenerics?\b/i, /\binterface\b/i, /\btsconfig\b/i, /тайпскрипт/i, /типизац/i],
41
- medium: [],
42
- weak: [/\btypes?\b/i],
43
- fileGlobs: [/\.tsx?$/, /tsconfig\.json$/],
44
- },
45
- {
46
- skill: 'ui-ux-pro',
47
- category: 'ui',
48
- strong: [/\bui\b/i, /\bux\b/i, /\btailwind\b/i, /\bstyling\b/i, /дизайн/i, /верстк/i, /макет/i, /интерфейс/i],
49
- medium: [/\bcss\b/i, /\btheme\b/i, /\bmodal\b/i, /\bbutton\b/i, /модал\w*/i, /кнопк/i],
50
- weak: [/\bdesign\b/i],
51
- fileGlobs: [/\.(css|scss|sass)$/, /tailwind\.config\./],
52
- },
53
- {
54
- skill: 'web-accessibility',
55
- category: 'ui',
56
- strong: [/\baccessib\w*\b/i, /\ba11y\b/i, /\baria\b/i, /\bfocus\s*trap\b/i, /\bkeyboard\s*nav/i, /\bwcag\b/i, /\bscreen\s*reader\b/i, /доступност/i, /скринридер/i],
57
- medium: [],
58
- weak: [],
59
- fileGlobs: [],
60
- },
61
- {
62
- skill: 'impeccable-design',
63
- category: 'ui',
64
- strong: [/\bvisual\s*qa\b/i, /\bmicro-?animation\b/i, /\bglassmorphism\b/i, /\btypography\b/i, /анимац/i, /полировк/i],
65
- medium: [/\bpolish\b/i],
66
- weak: [],
67
- fileGlobs: [],
68
- },
69
- {
70
- skill: 'database',
71
- category: 'intent',
72
- strong: [/\bdatabase\b/i, /\bsql\b/i, /\bpostgres(?:ql)?\b/i, /\bprisma\b/i, /\bdrizzle\b/i, /\bmigration\b/i, /\borm\b/i, /баз.*данн/i, /миграц/i, /таблиц/i],
73
- medium: [/\bschema\b/i],
74
- weak: [/\bquery\b/i, /\bindex(?:ing)?\b/i],
75
- fileGlobs: [/\.prisma$/, /drizzle\.config\./, /\bmigrations?\/.*\.sql$/],
76
- },
77
- {
78
- skill: 'security',
79
- category: 'intent',
80
- strong: [/\bauth\b/i, /\bjwt\b/i, /\blogin\b/i, /\bcsrf\b/i, /\bxss\b/i, /\brate\s*limit\b/i, /авториз/i, /аутентифик/i, /парол/i, /безопасност/i],
81
- medium: [/\bpermission\b/i, /\bsession\b/i, /\btoken\b/i, /токен/i],
82
- weak: [],
83
- fileGlobs: [/\bauth\b/, /\bsecurity\b/],
84
- },
85
- {
86
- skill: 'performance',
87
- category: 'intent',
88
- strong: [/\bperformance\b/i, /\blatency\b/i, /\blcp\b/i, /\bcls\b/i, /\binp\b/i, /\bcore\s*web\s*vitals\b/i, /\bwaterfall\b/i, /\bbundle\s*size\b/i, /производительн/i, /ускор/i],
89
- medium: [/\boptimize\b/i, /\bslow\b/i, /оптимиз/i, /медленн/i],
90
- weak: [],
91
- fileGlobs: [],
92
- },
93
- {
94
- skill: 'testing',
95
- category: 'intent',
96
- strong: [/\bvitest\b/i, /\bjest\b/i, /\bplaywright\b/i, /\btdd\b/i, /\bbdd\b/i, /\be2e\b/i, /тестирован/i, /покрыти/i, /юнит/i],
97
- medium: [/\btest(?:s|ing)?\b/i, /\bmock\b/i, /тест/i],
98
- weak: [],
99
- fileGlobs: [/\.(test|spec)\.(ts|js|tsx|jsx|py)$/, /vitest\.config\./, /playwright\.config\./],
100
- },
101
- {
102
- skill: 'docker',
103
- category: 'intent',
104
- strong: [/\bdocker\b/i, /\bdockerfile\b/i, /\bcompose\b/i, /\bkubernetes\b/i, /\bk8s\b/i, /докер/i],
105
- medium: [],
106
- weak: [/\bcontainer\b/i, /контейнер/i],
107
- fileGlobs: [/Dockerfile/, /docker-compose\./],
108
- },
109
- {
110
- skill: 'fastapi',
111
- category: 'stack',
112
- strong: [/\bfastapi\b/i, /\bpydantic\b/i, /\buvicorn\b/i, /\bpytest\b/i, /питон/i],
113
- medium: [/\bpython\b/i],
114
- weak: [],
115
- fileGlobs: [/\.py$/, /requirements\.txt$/, /pyproject\.toml$/],
116
- },
117
- {
118
- skill: 'nestjs',
119
- category: 'stack',
120
- strong: [/\bnestjs\b/i, /\b@nestjs\b/i, /нест/i],
121
- medium: [],
122
- weak: [/\bmodule\b/i, /\bcontroller\b/i, /\binjectable\b/i],
123
- fileGlobs: [/nest-cli\.json$/],
124
- },
125
- {
126
- skill: 'node',
127
- category: 'stack',
128
- strong: [/\bnode(?:\.js)?\b/i, /\bexpress\b/i, /\bfastify\b/i],
129
- medium: [/\bbackend\b/i, /\bapi\s*route\b/i, /бэкенд/i, /эндпоинт/i],
130
- weak: [],
131
- fileGlobs: [],
132
- },
133
- {
134
- skill: 'ddd',
135
- category: 'intent',
136
- strong: [/\bddd\b/i, /\bdomain-?driven\b/i, /\baggregate\b/i, /\bvalue\s*object\b/i, /\bbounded\s*context\b/i],
137
- medium: [/\bentity\b/i, /домен/i, /агрегат/i],
138
- weak: [],
139
- fileGlobs: [],
140
- },
141
- {
142
- skill: 'microservices',
143
- category: 'intent',
144
- strong: [/\bmicroservices?\b/i, /\bevent-?driven\b/i, /\brabbitmq\b/i, /\bkafka\b/i, /\bgrpc\b/i, /микросервис/i],
145
- medium: [/\bpub\/?sub\b/i, /очеред/i],
146
- weak: [],
147
- fileGlobs: [],
148
- },
149
- {
150
- skill: 'system-design',
151
- category: 'intent',
152
- strong: [/\bsystem\s*design\b/i, /\bhigh\s*concurrency\b/i, /\bcircuit\s*breaker\b/i, /масштабируем/i],
153
- medium: [/\barchitecture\b/i, /\bscalab(?:le|ility)\b/i, /архитектур/i],
154
- weak: [],
155
- fileGlobs: [],
156
- },
157
- {
158
- skill: 'graphify',
159
- category: 'intent',
160
- strong: [/\bgraphify\b/i, /\bknowledge\s*graph\b/i, /\bcodebase\s*graph\b/i, /\bproject\s*graph\b/i, /\bblast\s*radius\b/i, /\bmap\s*(?:the\s*)?codebase\b/i, /граф\s*проект/i, /граф\s*зависимост/i],
161
- medium: [],
162
- weak: [],
163
- fileGlobs: [/graph\.json$/, /GRAPH_REPORT\.md$/],
164
- },
165
- {
166
- skill: 'architecture-diagrams',
167
- category: 'intent',
168
- strong: [/\bflowchart\b/i, /\bsequence\s*diagram\b/i],
169
- medium: [/\bdiagrams?\b/i, /диаграмм/i, /схем/i, /нарисуй/i],
170
- weak: [],
171
- fileGlobs: [],
172
- },
173
- {
174
- skill: 'subagent-orchestrator',
175
- category: 'intent',
176
- strong: [/\bsubagent\b/i, /\bparallel\s*tasks\b/i, /субагент/i, /распараллел/i],
177
- medium: [/\bdelegate\b/i, /делегируй/i],
178
- weak: [],
179
- fileGlobs: [],
180
- },
181
- {
182
- skill: 'interview-me',
183
- category: 'intent',
184
- strong: [/\binterview\b/i, /интервью/i, /расспроси/i],
185
- medium: [/\bclarify\b/i, /\bquestions\b/i, /уточни\b/i],
186
- weak: [],
187
- fileGlobs: [],
188
- },
189
- ];
190
-
191
- /**
192
- * @typedef {Object} SkillIndexItem
193
- * @property {string} name - Skill unique identifier
194
- * @property {string} description - Brief summary of the skill
195
- * @property {string} path - Relative path to the skill markdown document
196
- */
197
-
198
- /**
199
- * @typedef {Object} ResolveSkillsOptions
200
- * @property {string} [prompt] - Free-form prompt text describing the current task
201
- * @property {string[]} [files] - List of file paths currently touched or opened
202
- * @property {string} [phase] - Active lifecycle phase (Define, Plan, Build, Verify, Review, Ship)
203
- * @property {string} [domain] - Engineering domain override (Frontend, Backend, Architecture, Full-Stack, DevOps)
204
- */
205
-
206
- /**
207
- * @typedef {Object} ResolvedSkillsResult
208
- * @property {string} domain - Identified technical domain
209
- * @property {string} phase - Current pipeline phase
210
- * @property {string} role - Specialized GStack agent role
211
- * @property {string[]} skills - Resolved list of minimal skill identifiers
212
- */
213
-
214
- /**
215
- * Builds a compact, progressive index of all available skills.
216
- *
217
- * @param {string} [projectDir=process.cwd()] - Target root directory of the project
218
- * @returns {SkillIndexItem[]} Array of indexed skill metadata objects
219
- */
220
- function buildSkillIndex(projectDir = process.cwd()) {
221
- const shared = require(path.join(AGENTS_DIR, 'adapters', 'shared.js'));
222
- const skillDirs = shared.collectSkillDirectories();
223
- const index = [];
224
-
225
- for (const dir of skillDirs) {
226
- const skillName = path.basename(dir);
227
- const skillMdPath = path.join(dir, 'SKILL.md');
228
- if (!fs.existsSync(skillMdPath)) continue;
229
-
230
- const raw = fs.readFileSync(skillMdPath, 'utf8');
231
- let description = '';
232
- const descMatch = raw.match(/description:\s*(?:>)?\s*([^\n\r]+)/);
233
- if (descMatch) {
234
- description = descMatch[1].trim().replace(/^['"]|['"]$/g, '');
235
- }
236
-
237
- const relPath = path.relative(projectDir, skillMdPath).replace(/\\/g, '/');
238
-
239
- index.push({
240
- name: skillName,
241
- description: description || `ContextOS skill for ${skillName}`,
242
- path: relPath,
243
- });
244
- }
245
-
246
- return index;
247
- }
12
+ const {
13
+ CanonicalResolver,
14
+ DEFAULT_CONTEXT_BUDGET_TOKENS,
15
+ WEIGHTS,
16
+ analyzeImportGraph,
17
+ } = require('./resolver/canonical-resolver.js');
248
18
 
249
19
  /**
250
- * Phase 2: AST & Project Dependency Graph Analysis.
251
- * Scans project manifests and configs to detect active technologies
252
- * that keyword or regex matching in prompts might omit.
20
+ * Resolves the minimal set of skills for a given prompt, file list, and phase.
253
21
  *
254
- * @param {string} [projectDir=process.cwd()] - Project root directory
255
- * @returns {Map<string, number>} Map of skill name to score weight
22
+ * @param {Object} options - Context options
23
+ * @returns {Object} Resolution result
256
24
  */
257
- function analyzeImportGraph(projectDir = process.cwd()) {
258
- const techSignals = new Map();
259
- if (!projectDir || !fs.existsSync(projectDir)) return techSignals;
25
+ function resolveSkills({ prompt = '', files = [], phase = 'Build', domain = '', projectDir = process.cwd(), maxSkills, contextBudgetTokens = DEFAULT_CONTEXT_BUDGET_TOKENS } = {}) {
26
+ const resolver = new CanonicalResolver({ rootDir: projectDir });
27
+ const result = resolver.resolve({
28
+ task: prompt,
29
+ files,
30
+ explicitPhase: phase,
31
+ domain,
32
+ projectDir,
33
+ maxSkills,
34
+ contextBudgetTokens,
35
+ });
260
36
 
261
- const addSignal = (skill, weight) => {
262
- techSignals.set(skill, (techSignals.get(skill) || 0) + weight);
37
+ return {
38
+ domain: result.domain,
39
+ phase: result.phase.value,
40
+ role: result.role,
41
+ skills: result.skills,
42
+ risk: result.risk,
43
+ selected: result.selected,
44
+ excluded: result.excluded,
45
+ conflicts: result.conflicts,
46
+ warnings: result.warnings,
47
+ totalEstimatedTokens: result.totalEstimatedTokens,
48
+ registryFingerprint: result.registryFingerprint,
49
+ workspaceFingerprint: result.workspaceFingerprint,
263
50
  };
264
-
265
- // 1. Scan package.json dependencies and devDependencies
266
- const pkgPath = path.join(projectDir, 'package.json');
267
- if (fs.existsSync(pkgPath)) {
268
- try {
269
- const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
270
- const allDeps = {
271
- ...(pkg.dependencies || {}),
272
- ...(pkg.devDependencies || {}),
273
- ...(pkg.peerDependencies || {}),
274
- };
275
-
276
- const DEP_SKILL_MAP = {
277
- 'react': 'react',
278
- 'react-dom': 'react',
279
- 'next': 'nextjs',
280
- 'prisma': 'database',
281
- '@prisma/client': 'database',
282
- 'drizzle-orm': 'database',
283
- 'drizzle-kit': 'database',
284
- 'typeorm': 'database',
285
- 'mongoose': 'database',
286
- 'pg': 'database',
287
- 'mysql2': 'database',
288
- 'vitest': 'testing',
289
- 'jest': 'testing',
290
- 'playwright': 'testing',
291
- '@playwright/test': 'testing',
292
- 'cypress': 'testing',
293
- 'express': 'node',
294
- 'fastify': 'node',
295
- 'hono': 'node',
296
- '@nestjs/core': 'nestjs',
297
- 'typescript': 'typescript',
298
- 'zod': 'typescript',
299
- 'tailwindcss': 'ui-ux-pro',
300
- 'lucide-react': 'ui-ux-pro',
301
- '@radix-ui/react-dialog': 'web-accessibility',
302
- 'framer-motion': 'impeccable-design',
303
- 'dockerode': 'docker',
304
- 'ioredis': 'system-design',
305
- 'kafkajs': 'microservices',
306
- 'amqplib': 'microservices',
307
- };
308
-
309
- for (const [dep, skill] of Object.entries(DEP_SKILL_MAP)) {
310
- if (allDeps[dep]) {
311
- addSignal(skill, 15);
312
- }
313
- }
314
- } catch {
315
- // ignore malformed package.json
316
- }
317
- }
318
-
319
- // 2. Scan framework & tooling configuration files
320
- const CONFIG_FILE_MAP = [
321
- { file: 'tsconfig.json', skill: 'typescript', weight: 10 },
322
- { file: 'next.config.js', skill: 'nextjs', weight: 15 },
323
- { file: 'next.config.mjs', skill: 'nextjs', weight: 15 },
324
- { file: 'next.config.ts', skill: 'nextjs', weight: 15 },
325
- { file: 'tailwind.config.js', skill: 'ui-ux-pro', weight: 10 },
326
- { file: 'tailwind.config.ts', skill: 'ui-ux-pro', weight: 10 },
327
- { file: 'nest-cli.json', skill: 'nestjs', weight: 15 },
328
- { file: 'prisma/schema.prisma', skill: 'database', weight: 15 },
329
- { file: 'drizzle.config.ts', skill: 'database', weight: 15 },
330
- { file: 'drizzle.config.js', skill: 'database', weight: 15 },
331
- { file: 'Dockerfile', skill: 'docker', weight: 15 },
332
- { file: 'docker-compose.yml', skill: 'docker', weight: 15 },
333
- { file: 'docker-compose.yaml', skill: 'docker', weight: 15 },
334
- { file: 'requirements.txt', skill: 'fastapi', weight: 15 },
335
- { file: 'pyproject.toml', skill: 'fastapi', weight: 15 },
336
- { file: 'vitest.config.ts', skill: 'testing', weight: 15 },
337
- { file: 'vitest.config.js', skill: 'testing', weight: 15 },
338
- { file: 'playwright.config.ts', skill: 'testing', weight: 15 },
339
- { file: 'playwright.config.js', skill: 'testing', weight: 15 },
340
- ];
341
-
342
- for (const { file, skill, weight } of CONFIG_FILE_MAP) {
343
- if (fs.existsSync(path.join(projectDir, file))) {
344
- addSignal(skill, weight);
345
- }
346
- }
347
-
348
- return techSignals;
349
51
  }
350
52
 
351
53
  /**
352
- * Resolves the minimal set of skills for a given prompt, file list, and phase.
54
+ * Builds a progressive index of installed skills.
353
55
  *
354
- * @param {ResolveSkillsOptions} [options={}] - Task context options
355
- * @returns {ResolvedSkillsResult} Resolved domain, role, and activated skill names
56
+ * @param {string} [projectDir=process.cwd()]
57
+ * @returns {Array<{name: string, description: string, path: string}>}
356
58
  */
357
- function resolveSkills({ prompt = '', files = [], phase = 'Build', domain = '', projectDir = process.cwd() } = {}) {
358
- const promptText = (prompt || '').toLowerCase();
359
- const ruleMap = new Map();
360
- const promptScores = new Map();
361
- const fileScores = new Map();
362
-
363
- for (const rule of SKILL_RULES) {
364
- ruleMap.set(rule.skill, rule);
365
- let pScore = 0;
366
- let fScore = 0;
367
-
368
- // Strong triggers (10 points each match)
369
- for (const pat of rule.strong || []) {
370
- if (pat.test(promptText)) pScore += 10;
371
- }
372
-
373
- // Medium triggers (5 points each match)
374
- for (const pat of rule.medium || []) {
375
- if (pat.test(promptText)) pScore += 5;
376
- }
377
-
378
- // Weak triggers (2 points each match)
379
- for (const pat of rule.weak || []) {
380
- if (pat.test(promptText)) pScore += 2;
381
- }
382
-
383
- // File matches (10 points per matching file)
384
- for (const file of files) {
385
- const normalized = file.replace(/\\/g, '/');
386
- for (const pat of rule.fileGlobs || []) {
387
- if (pat.test(normalized)) fScore += 10;
388
- }
389
- }
390
-
391
- if (pScore > 0) promptScores.set(rule.skill, pScore);
392
- if (fScore > 0) fileScores.set(rule.skill, fScore);
393
- }
394
-
395
- // Phase 2: Merge AST & Project Dependency Graph Signals
396
- const astSignals = projectDir ? analyzeImportGraph(projectDir) : new Map();
397
-
398
- // Active Profile Resolution Enforcement
399
- const profiles = require('./profiles.js');
400
- const activeProfile = projectDir ? profiles.getActiveProfile(projectDir) : null;
401
- const profileExcluded = new Set(activeProfile?.exclude_skills || []);
402
- const profilePreferred = new Set(activeProfile?.prefer_skills || []);
403
- const profileEnforce = activeProfile?.enforce || {};
404
- const profileDefaults = activeProfile?.defaults || {};
405
-
406
- const MAX_DOMAIN_SKILLS = 4;
407
- const selectedSkills = [];
408
-
409
- // 1. INTENT SLOTS & INTENT PRECEDENCE (Immunity against eviction)
410
- // Direct user intent in prompt MUST NOT be evicted by ambient stack/file signals.
411
- // Profile-excluded skills are strictly omitted from candidate intents.
412
- const candidateIntents = [];
413
- for (const rule of SKILL_RULES) {
414
- const s = rule.skill;
415
- if (profileExcluded.has(s)) continue;
416
-
417
- const p = promptScores.get(s) || 0;
418
- const f = fileScores.get(s) || 0;
419
- if (rule.category === 'intent' && (p >= 5 || (p > 0 && f >= 10))) {
420
- candidateIntents.push({ skill: s, score: p * 2 + f, priority: 2 });
421
- } else if (p >= 10) {
422
- candidateIntents.push({ skill: s, score: p, priority: 1 });
423
- }
424
- }
425
-
426
- candidateIntents.sort((a, b) => b.priority - a.priority || b.score - a.score);
427
-
428
- // Reserve up to 2 guaranteed intent slots for directly requested capabilities
429
- for (const item of candidateIntents) {
430
- if (selectedSkills.length < 2 && !selectedSkills.includes(item.skill)) {
431
- selectedSkills.push(item.skill);
432
- }
433
- }
434
-
435
- // 2. CONTEXT SUPPRESSION
436
- // If task is purely infrastructure (e.g. docker) or pure backend/architecture,
437
- // suppress ambient UI skills from AST to avoid polluting non-UI tasks.
438
- const hasPureInfraIntent = selectedSkills.includes('docker');
439
- const hasBackendOnlyIntent = selectedSkills.some(s => ['database', 'fastapi', 'nestjs', 'ddd'].includes(s)) &&
440
- !files.some(f => /\.(tsx|jsx|css|scss|html)$/.test(f)) &&
441
- !/\b(ui|react|css|tailwind|frontend|макет|дизайн|кнопк|стил|компонент)/i.test(promptText);
442
-
443
- const suppressAmbientUI = hasPureInfraIntent || hasBackendOnlyIntent;
444
-
445
- // 3. REMAINING SLOTS: Rank candidate skills with user-intent weighting and profile preferences
446
- const candidateScores = new Map();
447
- for (const rule of SKILL_RULES) {
448
- const s = rule.skill;
449
- if (selectedSkills.includes(s) || profileExcluded.has(s)) continue;
450
-
451
- const p = promptScores.get(s) || 0;
452
- const f = fileScores.get(s) || 0;
453
- const a = astSignals.get(s) || 0;
454
-
455
- // If ambient UI is suppressed, skip UI skills unless explicitly requested in prompt
456
- if (suppressAmbientUI && (rule.category === 'ui' || s === 'react') && p < 5 && f === 0) {
457
- continue;
458
- }
459
-
460
- // Require minimum unweighted threshold of 5 points to filter casual weak mentions,
461
- // then apply multiplier for strong/medium prompt matches to prioritize user intent over ambient signals.
462
- const rawSum = p + f + a;
463
- if (rawSum >= 5 || profilePreferred.has(s)) {
464
- let weightedScore = (p >= 5 ? p * 3 : p) + f + a;
465
- if (profilePreferred.has(s)) {
466
- weightedScore += 20; // Profile prefer boost
467
- }
468
- candidateScores.set(s, weightedScore);
469
- }
470
- }
471
-
472
- const remainingSorted = Array.from(candidateScores.entries())
473
- .sort((a, b) => b[1] - a[1])
474
- .map(([skill]) => skill);
475
-
476
- for (const s of remainingSorted) {
477
- if (selectedSkills.length >= MAX_DOMAIN_SKILLS) break;
478
- if (!selectedSkills.includes(s)) {
479
- selectedSkills.push(s);
480
- }
481
- }
482
-
483
- // 4. Synergy rules (from AGENTS.md matrix)
484
- const hasSynergyPrereq = selectedSkills.includes('database') ||
485
- selectedSkills.includes('microservices') ||
486
- selectedSkills.includes('ddd') ||
487
- selectedSkills.includes('graphify');
488
-
489
- if (hasSynergyPrereq && !selectedSkills.includes('system-design') && !profileExcluded.has('system-design')) {
490
- if (selectedSkills.length < MAX_DOMAIN_SKILLS + 1) {
491
- selectedSkills.push('system-design');
492
- }
493
- }
494
-
495
- // 5. Enforce profile invariants (e.g. enterprise or startup compliance)
496
- const normPhase = (phase || '').toLowerCase();
497
- if (profileEnforce.testing === true && ['build', 'verify', 'test'].includes(normPhase)) {
498
- if (!selectedSkills.includes('testing') && !profileExcluded.has('testing')) {
499
- selectedSkills.push('testing');
500
- }
501
- }
502
-
503
- if (profileEnforce.security_audit === true && (selectedSkills.includes('database') || selectedSkills.includes('node') || selectedSkills.includes('fastapi') || selectedSkills.includes('nestjs'))) {
504
- if (!selectedSkills.includes('security') && !profileExcluded.has('security')) {
505
- selectedSkills.push('security');
506
- }
507
- }
508
-
509
- if (profileEnforce.adr === true && (normPhase === 'plan' || selectedSkills.includes('system-design') || selectedSkills.includes('microservices'))) {
510
- if (!selectedSkills.includes('decisions') && !profileExcluded.has('decisions')) {
511
- selectedSkills.push('decisions');
512
- }
513
- }
514
-
515
- if (profileEnforce.accessibility_audit === true && (selectedSkills.includes('react') || selectedSkills.includes('ui-ux-pro'))) {
516
- if (!selectedSkills.includes('web-accessibility') && !profileExcluded.has('web-accessibility')) {
517
- selectedSkills.push('web-accessibility');
518
- }
519
- }
520
-
521
- // Foundational skills (always active unless explicitly excluded)
522
- const allSkills = ['ponytail-mindset', 'engineering-workflow', ...selectedSkills];
523
- const finalSkills = Array.from(new Set(allSkills)).filter(s => !profileExcluded.has(s));
524
-
525
- // Infer Domain if not specified
526
- let inferredDomain = domain;
527
- if (!inferredDomain) {
528
- const isFrontend = finalSkills.includes('react') || finalSkills.includes('nextjs') || finalSkills.includes('ui-ux-pro');
529
- const isBackend = finalSkills.includes('database') || finalSkills.includes('fastapi') || finalSkills.includes('nestjs') || finalSkills.includes('node') || finalSkills.includes('system-design');
530
- if (isFrontend && isBackend) inferredDomain = 'Full-Stack';
531
- else if (isFrontend) inferredDomain = 'Frontend';
532
- else if (isBackend) inferredDomain = 'Backend';
533
- else inferredDomain = 'Architecture';
534
- }
535
-
536
- // Infer Role
537
- let inferredRole = 'Senior Developer';
538
- if (phase.toLowerCase() === 'define') inferredRole = 'Product Manager';
539
- else if (phase.toLowerCase() === 'plan') inferredRole = 'Architect';
540
- else if (phase.toLowerCase() === 'review') inferredRole = inferredDomain === 'Frontend' ? 'Staff Engineer + Senior Designer' : 'Staff Engineer';
541
- else if (phase.toLowerCase() === 'test') inferredRole = 'QA Lead';
542
- else if (phase.toLowerCase() === 'ship') inferredRole = 'Release Engineer';
543
-
544
- return {
545
- domain: inferredDomain,
546
- phase: phase,
547
- role: inferredRole,
548
- skills: finalSkills,
549
- };
59
+ function buildSkillIndex(projectDir = process.cwd()) {
60
+ const resolver = new CanonicalResolver({ rootDir: projectDir });
61
+ return resolver.buildSkillIndex(projectDir);
550
62
  }
551
63
 
552
64
  /**
553
- * Formats resolved skills into a clean ContextOS declaration string.
65
+ * Formats resolved skills into a clean ContextOS declaration string matching AGENTS.md.
554
66
  *
555
- * @param {ResolvedSkillsResult} resolution - Resolution result from resolveSkills
556
- * @returns {string} ContextOS formatted header string matching Step 0 format
67
+ * @param {Object} resolution
68
+ * @returns {string}
557
69
  */
558
70
  function formatDeclaration(resolution) {
559
- return `[DOMAIN: ${resolution.domain}] [PHASE: ${resolution.phase}] [ROLE: ${resolution.role}]\nSkills loaded: ${resolution.skills.join(', ')}`;
71
+ const resolver = new CanonicalResolver();
72
+ return resolver.formatDeclaration(resolution);
560
73
  }
561
74
 
562
75
  module.exports = {
76
+ CanonicalResolver,
77
+ DEFAULT_CONTEXT_BUDGET_TOKENS,
78
+ WEIGHTS,
563
79
  buildSkillIndex,
564
80
  resolveSkills,
565
81
  analyzeImportGraph,