contextos-agents 1.6.1 → 2.0.0-beta.2

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 (323) hide show
  1. package/.agents/AGENTS.md +6 -1
  2. package/.agents/adapters/aider/export.js +117 -97
  3. package/.agents/adapters/claude/export.js +68 -26
  4. package/.agents/adapters/copilot/export.js +90 -51
  5. package/.agents/adapters/cursor/export.js +83 -68
  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 +109 -62
  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/references/context-rules.md +59 -0
  18. package/.agents/core/skills/context-manager/skill.yaml +10 -5
  19. package/.agents/core/skills/context-os/SKILL.md +3 -6
  20. package/.agents/core/skills/context-os/skill.yaml +14 -8
  21. package/.agents/core/skills/engineering-workflow/SKILL.md +1 -1
  22. package/.agents/core/skills/engineering-workflow/skill.yaml +7 -7
  23. package/.agents/core/skills/gemini-precision/SKILL.md +4 -0
  24. package/.agents/core/skills/gemini-precision/skill.yaml +5 -6
  25. package/.agents/core/skills/gstack-roles/SKILL.md +3 -1
  26. package/.agents/core/skills/gstack-roles/skill.yaml +9 -6
  27. package/.agents/core/skills/ponytail-mindset/skill.yaml +7 -7
  28. package/.agents/core/skills/security/skill.yaml +21 -2
  29. package/.agents/ctx.js +587 -111
  30. package/.agents/customization-dx.js +282 -0
  31. package/.agents/doctor.js +877 -33
  32. package/.agents/filesystem/index.js +71 -0
  33. package/.agents/filesystem/journaled-transaction.js +451 -0
  34. package/.agents/filesystem/lockfile-v2.js +275 -0
  35. package/.agents/filesystem/platform-hardening.js +222 -0
  36. package/.agents/filesystem/project-lock.js +218 -0
  37. package/.agents/filesystem/safe-path.js +256 -0
  38. package/.agents/generated/claude/skills/context-os/SKILL.md +1 -1
  39. package/.agents/generated/claude/skills/engineering-workflow/SKILL.md +1 -1
  40. package/.agents/generated/claude/skills/gemini-precision/SKILL.md +4 -0
  41. package/.agents/generated/claude/skills/gstack-roles/SKILL.md +3 -1
  42. package/.agents/generated/gemini/skills/context-os/SKILL.md +2 -2
  43. package/.agents/generated/gemini/skills/engineering-workflow/SKILL.md +1 -1
  44. package/.agents/generated/gemini/skills/gemini-precision/SKILL.md +4 -0
  45. package/.agents/generated/gemini/skills/gstack-roles/SKILL.md +3 -1
  46. package/.agents/plugins/contextos/hooks.json +25 -0
  47. package/.agents/plugins/contextos/plugin.json +19 -0
  48. package/.agents/plugins.js +432 -73
  49. package/.agents/profiles.js +507 -46
  50. package/.agents/resolver.js +50 -414
  51. package/.agents/schemas/attestation.review.v1.json +111 -0
  52. package/.agents/schemas/attestation.verification.v1.json +85 -0
  53. package/.agents/schemas/lockfile.v2.schema.json +134 -0
  54. package/.agents/schemas/profile.v2.schema.json +114 -0
  55. package/.agents/schemas/runtime.thread.v1.json +192 -0
  56. package/.agents/schemas/skill.manifest.v2.json +177 -0
  57. package/.agents/schemas/verification.spec.v1.json +39 -0
  58. package/.agents/schemas/workspace.graph.schema.json +106 -0
  59. package/.agents/stats.js +22 -9
  60. package/.agents/transaction-core/event-store.js +288 -0
  61. package/.agents/transaction-core/idempotency.js +129 -0
  62. package/.agents/transaction-core/ipc-lock.js +311 -0
  63. package/.agents/transaction-core/plugin-supply-chain-bundle.js +436 -0
  64. package/.agents/validate.js +143 -14
  65. package/.agents/watch.js +354 -102
  66. package/.agents/workspace/workspace-graph.js +778 -0
  67. package/README.md +59 -387
  68. package/benchmarks/v2/analysis/statistics.js +140 -0
  69. package/benchmarks/v2/analysis/stats.js +69 -0
  70. package/benchmarks/v2/arms/arm-definitions.js +79 -0
  71. package/benchmarks/v2/dataset.schema.json +34 -0
  72. package/benchmarks/v2/evaluators/index.js +25 -0
  73. package/benchmarks/v2/evaluators/verified-success.js +116 -0
  74. package/benchmarks/v2/harness/runner.js +88 -0
  75. package/benchmarks/v2/pilot-tasks.json +392 -0
  76. package/bin/commands/recover.js +88 -0
  77. package/bin/commands/uninstall.js +207 -0
  78. package/bin/commands/update.js +325 -0
  79. package/bin/commands.js +342 -0
  80. package/bin/index.js +326 -149
  81. package/bin/lib/detector.js +106 -0
  82. package/bin/lib/lockfile.js +253 -0
  83. package/bin/lib/safe-writer.js +290 -0
  84. package/package.json +85 -73
  85. package/registry.json +15 -7
  86. package/registry.schema.json +3 -1
  87. package/registry.v2.schema.json +86 -0
  88. package/.agents/core/profiles/backend.yaml +0 -47
  89. package/.agents/core/profiles/enterprise.yaml +0 -46
  90. package/.agents/core/profiles/frontend.yaml +0 -46
  91. package/.agents/core/profiles/hackathon.yaml +0 -45
  92. package/.agents/core/profiles/mvp.yaml +0 -44
  93. package/.agents/core/profiles/startup.yaml +0 -48
  94. package/.agents/core/skills/adapters/EXAMPLES.md +0 -19
  95. package/.agents/core/skills/adapters/SKILL.md +0 -105
  96. package/.agents/core/skills/adapters/TROUBLESHOOTING.md +0 -7
  97. package/.agents/core/skills/adapters/VALIDATION.json +0 -12
  98. package/.agents/core/skills/adapters/skill.yaml +0 -10
  99. package/.agents/core/skills/architecture-diagrams/SKILL.md +0 -108
  100. package/.agents/core/skills/architecture-diagrams/VALIDATION.json +0 -12
  101. package/.agents/core/skills/architecture-diagrams/skill.yaml +0 -8
  102. package/.agents/core/skills/brutalist-design/SKILL.md +0 -150
  103. package/.agents/core/skills/brutalist-design/VALIDATION.json +0 -12
  104. package/.agents/core/skills/brutalist-design/skill.yaml +0 -8
  105. package/.agents/core/skills/database/EXAMPLES.md +0 -74
  106. package/.agents/core/skills/database/SKILL.md +0 -101
  107. package/.agents/core/skills/database/TROUBLESHOOTING.md +0 -18
  108. package/.agents/core/skills/database/VALIDATION.json +0 -11
  109. package/.agents/core/skills/database/skill.yaml +0 -25
  110. package/.agents/core/skills/ddd/EXAMPLES.md +0 -42
  111. package/.agents/core/skills/ddd/SKILL.md +0 -247
  112. package/.agents/core/skills/ddd/TROUBLESHOOTING.md +0 -19
  113. package/.agents/core/skills/ddd/VALIDATION.json +0 -12
  114. package/.agents/core/skills/ddd/ddd.md +0 -178
  115. package/.agents/core/skills/ddd/skill.yaml +0 -10
  116. package/.agents/core/skills/decisions/EXAMPLES.md +0 -35
  117. package/.agents/core/skills/decisions/SKILL.md +0 -90
  118. package/.agents/core/skills/decisions/TROUBLESHOOTING.md +0 -13
  119. package/.agents/core/skills/decisions/VALIDATION.json +0 -12
  120. package/.agents/core/skills/decisions/skill.yaml +0 -10
  121. package/.agents/core/skills/docker/EXAMPLES.md +0 -56
  122. package/.agents/core/skills/docker/SKILL.md +0 -63
  123. package/.agents/core/skills/docker/TROUBLESHOOTING.md +0 -18
  124. package/.agents/core/skills/docker/VALIDATION.json +0 -11
  125. package/.agents/core/skills/docker/skill.yaml +0 -23
  126. package/.agents/core/skills/fastapi/EXAMPLES.md +0 -36
  127. package/.agents/core/skills/fastapi/SKILL.md +0 -148
  128. package/.agents/core/skills/fastapi/TROUBLESHOOTING.md +0 -19
  129. package/.agents/core/skills/fastapi/VALIDATION.json +0 -12
  130. package/.agents/core/skills/fastapi/fastapi.md +0 -112
  131. package/.agents/core/skills/fastapi/skill.yaml +0 -10
  132. package/.agents/core/skills/generators/EXAMPLES.md +0 -19
  133. package/.agents/core/skills/generators/SKILL.md +0 -112
  134. package/.agents/core/skills/generators/TROUBLESHOOTING.md +0 -7
  135. package/.agents/core/skills/generators/VALIDATION.json +0 -12
  136. package/.agents/core/skills/generators/skill.yaml +0 -10
  137. package/.agents/core/skills/generators/templates/API.md +0 -77
  138. package/.agents/core/skills/generators/templates/ARCHITECTURE.md +0 -70
  139. package/.agents/core/skills/generators/templates/DATABASE.md +0 -42
  140. package/.agents/core/skills/generators/templates/DECISION.md +0 -46
  141. package/.agents/core/skills/generators/templates/PRD.md +0 -67
  142. package/.agents/core/skills/generators/templates/PROJECT_GRAPH.md +0 -56
  143. package/.agents/core/skills/generators/templates/ROADMAP.md +0 -51
  144. package/.agents/core/skills/generators/templates/TASKS.md +0 -43
  145. package/.agents/core/skills/generators/templates/UI.md +0 -73
  146. package/.agents/core/skills/graphify/EXAMPLES.md +0 -73
  147. package/.agents/core/skills/graphify/SKILL.md +0 -130
  148. package/.agents/core/skills/graphify/VALIDATION.json +0 -12
  149. package/.agents/core/skills/graphify/skill.yaml +0 -13
  150. package/.agents/core/skills/impeccable-design/EXAMPLES.md +0 -26
  151. package/.agents/core/skills/impeccable-design/SKILL.md +0 -201
  152. package/.agents/core/skills/impeccable-design/TROUBLESHOOTING.md +0 -19
  153. package/.agents/core/skills/impeccable-design/VALIDATION.json +0 -12
  154. package/.agents/core/skills/impeccable-design/skill.yaml +0 -14
  155. package/.agents/core/skills/interview-me/SKILL.md +0 -97
  156. package/.agents/core/skills/interview-me/VALIDATION.json +0 -12
  157. package/.agents/core/skills/interview-me/skill.yaml +0 -8
  158. package/.agents/core/skills/microservices/EXAMPLES.md +0 -38
  159. package/.agents/core/skills/microservices/SKILL.md +0 -164
  160. package/.agents/core/skills/microservices/TROUBLESHOOTING.md +0 -19
  161. package/.agents/core/skills/microservices/VALIDATION.json +0 -12
  162. package/.agents/core/skills/microservices/microservices.md +0 -119
  163. package/.agents/core/skills/microservices/skill.yaml +0 -10
  164. package/.agents/core/skills/minimalist-design/SKILL.md +0 -113
  165. package/.agents/core/skills/minimalist-design/VALIDATION.json +0 -12
  166. package/.agents/core/skills/minimalist-design/skill.yaml +0 -8
  167. package/.agents/core/skills/nestjs/EXAMPLES.md +0 -40
  168. package/.agents/core/skills/nestjs/SKILL.md +0 -139
  169. package/.agents/core/skills/nestjs/TROUBLESHOOTING.md +0 -19
  170. package/.agents/core/skills/nestjs/VALIDATION.json +0 -12
  171. package/.agents/core/skills/nestjs/nestjs.md +0 -103
  172. package/.agents/core/skills/nestjs/skill.yaml +0 -10
  173. package/.agents/core/skills/nextjs/EXAMPLES.md +0 -40
  174. package/.agents/core/skills/nextjs/SKILL.md +0 -163
  175. package/.agents/core/skills/nextjs/TROUBLESHOOTING.md +0 -19
  176. package/.agents/core/skills/nextjs/VALIDATION.json +0 -12
  177. package/.agents/core/skills/nextjs/nextjs.md +0 -67
  178. package/.agents/core/skills/nextjs/skill.yaml +0 -10
  179. package/.agents/core/skills/node/EXAMPLES.md +0 -80
  180. package/.agents/core/skills/node/SKILL.md +0 -128
  181. package/.agents/core/skills/node/TROUBLESHOOTING.md +0 -19
  182. package/.agents/core/skills/node/VALIDATION.json +0 -12
  183. package/.agents/core/skills/node/node.md +0 -87
  184. package/.agents/core/skills/node/skill.yaml +0 -10
  185. package/.agents/core/skills/performance/EXAMPLES.md +0 -30
  186. package/.agents/core/skills/performance/SKILL.md +0 -75
  187. package/.agents/core/skills/performance/TROUBLESHOOTING.md +0 -19
  188. package/.agents/core/skills/performance/VALIDATION.json +0 -12
  189. package/.agents/core/skills/performance/performance.md +0 -52
  190. package/.agents/core/skills/performance/skill.yaml +0 -10
  191. package/.agents/core/skills/react/EXAMPLES.md +0 -79
  192. package/.agents/core/skills/react/SKILL.md +0 -132
  193. package/.agents/core/skills/react/TROUBLESHOOTING.md +0 -19
  194. package/.agents/core/skills/react/VALIDATION.json +0 -12
  195. package/.agents/core/skills/react/react.md +0 -93
  196. package/.agents/core/skills/react/skill.yaml +0 -10
  197. package/.agents/core/skills/react-best-practices/SKILL.md +0 -155
  198. package/.agents/core/skills/react-best-practices/VALIDATION.json +0 -12
  199. package/.agents/core/skills/react-best-practices/skill.yaml +0 -10
  200. package/.agents/core/skills/redesign-audit/SKILL.md +0 -117
  201. package/.agents/core/skills/redesign-audit/VALIDATION.json +0 -12
  202. package/.agents/core/skills/redesign-audit/skill.yaml +0 -8
  203. package/.agents/core/skills/soft-design/SKILL.md +0 -108
  204. package/.agents/core/skills/soft-design/VALIDATION.json +0 -12
  205. package/.agents/core/skills/soft-design/skill.yaml +0 -8
  206. package/.agents/core/skills/state-management/EXAMPLES.md +0 -56
  207. package/.agents/core/skills/state-management/SKILL.md +0 -48
  208. package/.agents/core/skills/state-management/TROUBLESHOOTING.md +0 -18
  209. package/.agents/core/skills/state-management/VALIDATION.json +0 -11
  210. package/.agents/core/skills/state-management/skill.yaml +0 -22
  211. package/.agents/core/skills/subagent-orchestrator/SKILL.md +0 -100
  212. package/.agents/core/skills/subagent-orchestrator/VALIDATION.json +0 -12
  213. package/.agents/core/skills/subagent-orchestrator/skill.yaml +0 -8
  214. package/.agents/core/skills/system-design/EXAMPLES.md +0 -75
  215. package/.agents/core/skills/system-design/SKILL.md +0 -419
  216. package/.agents/core/skills/system-design/TROUBLESHOOTING.md +0 -19
  217. package/.agents/core/skills/system-design/VALIDATION.json +0 -12
  218. package/.agents/core/skills/system-design/skill.yaml +0 -13
  219. package/.agents/core/skills/system-design/system-design.md +0 -112
  220. package/.agents/core/skills/testing/EXAMPLES.md +0 -71
  221. package/.agents/core/skills/testing/SKILL.md +0 -70
  222. package/.agents/core/skills/testing/TROUBLESHOOTING.md +0 -18
  223. package/.agents/core/skills/testing/VALIDATION.json +0 -11
  224. package/.agents/core/skills/testing/skill.yaml +0 -26
  225. package/.agents/core/skills/typescript/EXAMPLES.md +0 -64
  226. package/.agents/core/skills/typescript/SKILL.md +0 -112
  227. package/.agents/core/skills/typescript/TROUBLESHOOTING.md +0 -19
  228. package/.agents/core/skills/typescript/VALIDATION.json +0 -12
  229. package/.agents/core/skills/typescript/skill.yaml +0 -10
  230. package/.agents/core/skills/typescript/typescript.md +0 -71
  231. package/.agents/core/skills/ui-design/EXAMPLES.md +0 -21
  232. package/.agents/core/skills/ui-design/SKILL.md +0 -124
  233. package/.agents/core/skills/ui-design/TROUBLESHOOTING.md +0 -19
  234. package/.agents/core/skills/ui-design/VALIDATION.json +0 -12
  235. package/.agents/core/skills/ui-design/skill.yaml +0 -10
  236. package/.agents/core/skills/ui-design/ui.md +0 -88
  237. package/.agents/core/skills/ui-ux-pro/EXAMPLES.md +0 -62
  238. package/.agents/core/skills/ui-ux-pro/SKILL.md +0 -375
  239. package/.agents/core/skills/ui-ux-pro/TROUBLESHOOTING.md +0 -19
  240. package/.agents/core/skills/ui-ux-pro/VALIDATION.json +0 -12
  241. package/.agents/core/skills/ui-ux-pro/skill.yaml +0 -13
  242. package/.agents/core/skills/ux-design/EXAMPLES.md +0 -36
  243. package/.agents/core/skills/ux-design/SKILL.md +0 -116
  244. package/.agents/core/skills/ux-design/TROUBLESHOOTING.md +0 -19
  245. package/.agents/core/skills/ux-design/VALIDATION.json +0 -12
  246. package/.agents/core/skills/ux-design/skill.yaml +0 -10
  247. package/.agents/core/skills/ux-design/ux.md +0 -80
  248. package/.agents/core/skills/vercel-optimize/SKILL.md +0 -83
  249. package/.agents/core/skills/vercel-optimize/VALIDATION.json +0 -12
  250. package/.agents/core/skills/vercel-optimize/skill.yaml +0 -10
  251. package/.agents/core/skills/web-accessibility/EXAMPLES.md +0 -39
  252. package/.agents/core/skills/web-accessibility/SKILL.md +0 -170
  253. package/.agents/core/skills/web-accessibility/TROUBLESHOOTING.md +0 -19
  254. package/.agents/core/skills/web-accessibility/VALIDATION.json +0 -12
  255. package/.agents/core/skills/web-accessibility/accessibility.md +0 -63
  256. package/.agents/core/skills/web-accessibility/skill.yaml +0 -10
  257. package/.agents/generated/claude/skills/adapters/SKILL.md +0 -126
  258. package/.agents/generated/claude/skills/architecture-diagrams/SKILL.md +0 -101
  259. package/.agents/generated/claude/skills/brutalist-design/SKILL.md +0 -145
  260. package/.agents/generated/claude/skills/database/SKILL.md +0 -191
  261. package/.agents/generated/claude/skills/ddd/SKILL.md +0 -305
  262. package/.agents/generated/claude/skills/decisions/SKILL.md +0 -134
  263. package/.agents/generated/claude/skills/docker/SKILL.md +0 -135
  264. package/.agents/generated/claude/skills/fastapi/SKILL.md +0 -200
  265. package/.agents/generated/claude/skills/generators/SKILL.md +0 -133
  266. package/.agents/generated/claude/skills/graphify/SKILL.md +0 -198
  267. package/.agents/generated/claude/skills/impeccable-design/SKILL.md +0 -241
  268. package/.agents/generated/claude/skills/interview-me/SKILL.md +0 -90
  269. package/.agents/generated/claude/skills/microservices/SKILL.md +0 -218
  270. package/.agents/generated/claude/skills/minimalist-design/SKILL.md +0 -108
  271. package/.agents/generated/claude/skills/nestjs/SKILL.md +0 -195
  272. package/.agents/generated/claude/skills/nextjs/SKILL.md +0 -219
  273. package/.agents/generated/claude/skills/node/SKILL.md +0 -224
  274. package/.agents/generated/claude/skills/performance/SKILL.md +0 -121
  275. package/.agents/generated/claude/skills/react/SKILL.md +0 -227
  276. package/.agents/generated/claude/skills/react-best-practices/SKILL.md +0 -146
  277. package/.agents/generated/claude/skills/redesign-audit/SKILL.md +0 -112
  278. package/.agents/generated/claude/skills/soft-design/SKILL.md +0 -103
  279. package/.agents/generated/claude/skills/state-management/SKILL.md +0 -120
  280. package/.agents/generated/claude/skills/subagent-orchestrator/SKILL.md +0 -93
  281. package/.agents/generated/claude/skills/system-design/SKILL.md +0 -507
  282. package/.agents/generated/claude/skills/testing/SKILL.md +0 -157
  283. package/.agents/generated/claude/skills/typescript/SKILL.md +0 -192
  284. package/.agents/generated/claude/skills/ui-design/SKILL.md +0 -161
  285. package/.agents/generated/claude/skills/ui-ux-pro/SKILL.md +0 -451
  286. package/.agents/generated/claude/skills/ux-design/SKILL.md +0 -168
  287. package/.agents/generated/claude/skills/vercel-optimize/SKILL.md +0 -76
  288. package/.agents/generated/claude/skills/web-accessibility/SKILL.md +0 -225
  289. package/.agents/generated/gemini/skills/adapters/SKILL.md +0 -135
  290. package/.agents/generated/gemini/skills/architecture-diagrams/SKILL.md +0 -107
  291. package/.agents/generated/gemini/skills/brutalist-design/SKILL.md +0 -151
  292. package/.agents/generated/gemini/skills/database/SKILL.md +0 -200
  293. package/.agents/generated/gemini/skills/ddd/SKILL.md +0 -314
  294. package/.agents/generated/gemini/skills/decisions/SKILL.md +0 -143
  295. package/.agents/generated/gemini/skills/docker/SKILL.md +0 -144
  296. package/.agents/generated/gemini/skills/fastapi/SKILL.md +0 -209
  297. package/.agents/generated/gemini/skills/generators/SKILL.md +0 -142
  298. package/.agents/generated/gemini/skills/graphify/SKILL.md +0 -205
  299. package/.agents/generated/gemini/skills/impeccable-design/SKILL.md +0 -250
  300. package/.agents/generated/gemini/skills/interview-me/SKILL.md +0 -96
  301. package/.agents/generated/gemini/skills/microservices/SKILL.md +0 -227
  302. package/.agents/generated/gemini/skills/minimalist-design/SKILL.md +0 -114
  303. package/.agents/generated/gemini/skills/nestjs/SKILL.md +0 -204
  304. package/.agents/generated/gemini/skills/nextjs/SKILL.md +0 -298
  305. package/.agents/generated/gemini/skills/node/SKILL.md +0 -323
  306. package/.agents/generated/gemini/skills/performance/SKILL.md +0 -185
  307. package/.agents/generated/gemini/skills/react/SKILL.md +0 -332
  308. package/.agents/generated/gemini/skills/react-best-practices/SKILL.md +0 -152
  309. package/.agents/generated/gemini/skills/redesign-audit/SKILL.md +0 -118
  310. package/.agents/generated/gemini/skills/soft-design/SKILL.md +0 -109
  311. package/.agents/generated/gemini/skills/state-management/SKILL.md +0 -129
  312. package/.agents/generated/gemini/skills/subagent-orchestrator/SKILL.md +0 -99
  313. package/.agents/generated/gemini/skills/system-design/SKILL.md +0 -631
  314. package/.agents/generated/gemini/skills/testing/SKILL.md +0 -166
  315. package/.agents/generated/gemini/skills/typescript/SKILL.md +0 -275
  316. package/.agents/generated/gemini/skills/ui-design/SKILL.md +0 -170
  317. package/.agents/generated/gemini/skills/ui-ux-pro/SKILL.md +0 -460
  318. package/.agents/generated/gemini/skills/ux-design/SKILL.md +0 -177
  319. package/.agents/generated/gemini/skills/vercel-optimize/SKILL.md +0 -82
  320. package/.agents/generated/gemini/skills/web-accessibility/SKILL.md +0 -300
  321. package/.agents/mcp/runtime.py +0 -470
  322. package/.agents/mcp/server.mjs +0 -189271
  323. package/benchmarks/gemini-issues.js +0 -533
@@ -12,21 +12,28 @@
12
12
 
13
13
  const fs = require('fs');
14
14
  const path = require('path');
15
+ const { ProjectMutationLock, JournaledTransaction } = require('./filesystem/index.js');
15
16
 
16
17
  const AGENTS_DIR = path.join(__dirname);
17
18
  const PROFILES_DIR = path.join(AGENTS_DIR, 'core', 'profiles');
18
19
 
19
20
  /**
20
21
  * @typedef {Object} ProfileConfig
22
+ * @property {number} [schemaVersion] - Profile schema version
21
23
  * @property {string} id - Profile unique slug
22
24
  * @property {string} name - Human-readable profile title
23
25
  * @property {string} description - Summary of the profile's purpose
24
- * @property {string[]} prefer_skills - Priority skills favored by this profile
25
- * @property {string[]} exclude_skills - Skills filtered out for this profile
26
- * @property {string[]} generate_docs - Documentation templates to generate
27
- * @property {string[]} skip_docs - Documentation to skip
28
- * @property {Object} enforce - Invariant rules to enforce
29
- * @property {Object} defaults - Default parameters
26
+ * @property {Object} skills - Profile skill groups (required, preferred, excluded)
27
+ * @property {Object} policy - Quality gate policies
28
+ * @property {Object} generation - Document templates to generate
29
+ * @property {Object} technologyDefaults - Default framework/tool selections
30
+ * @property {string[]} prefer_skills - Legacy priority skills
31
+ * @property {string[]} exclude_skills - Legacy filtered out skills
32
+ * @property {string[]} require_skills - Legacy mandatory skills
33
+ * @property {string[]} generate_docs - Legacy documentation templates
34
+ * @property {string[]} skip_docs - Legacy documentation to skip
35
+ * @property {Object} enforce - Legacy invariant rules
36
+ * @property {Object} defaults - Legacy default parameters
30
37
  */
31
38
 
32
39
  /**
@@ -37,17 +44,39 @@ const PROFILES_DIR = path.join(AGENTS_DIR, 'core', 'profiles');
37
44
  */
38
45
  function parseYamlProfile(text) {
39
46
  const result = {
47
+ schemaVersion: 1,
40
48
  id: '',
41
49
  name: '',
42
50
  description: '',
51
+ skills: {
52
+ required: [],
53
+ preferred: [],
54
+ excluded: [],
55
+ },
56
+ policy: {
57
+ verification: 'recommended',
58
+ review: 'recommended',
59
+ security: 'recommended',
60
+ adr: 'off',
61
+ testing: 'recommended',
62
+ accessibility: 'off',
63
+ },
64
+ generation: {
65
+ documents: [],
66
+ },
67
+ technologyDefaults: {},
43
68
  prefer_skills: [],
44
69
  exclude_skills: [],
70
+ require_skills: [],
45
71
  generate_docs: [],
46
72
  skip_docs: [],
47
73
  enforce: {},
48
74
  defaults: {},
49
75
  };
50
76
 
77
+ const schemaMatch = text.match(/^schemaVersion:\s*(\d+)/m);
78
+ if (schemaMatch) result.schemaVersion = parseInt(schemaMatch[1], 10);
79
+
51
80
  const idMatch = text.match(/^id:\s*(.+)$/m);
52
81
  if (idMatch) result.id = idMatch[1].trim().replace(/^['"]|['"]$/g, '');
53
82
 
@@ -57,12 +86,12 @@ function parseYamlProfile(text) {
57
86
  const descMatch = text.match(/^description:\s*(.+)$/m);
58
87
  if (descMatch) result.description = descMatch[1].trim().replace(/^['"]|['"]$/g, '');
59
88
 
60
- function parseList(field) {
61
- const blockRegex = new RegExp(`^${field}:\\s*\\n((?:[ \\t]+-[^\\n]*\\n?)+)`, 'm');
62
- const match = text.match(blockRegex);
89
+ function parseList(field, sourceText = text) {
90
+ const blockRegex = new RegExp(`^[ \\t]*${field}:\\s*\\n((?:[ \\t]+-[^\\n]*\\n?)+)`, 'm');
91
+ const match = sourceText.match(blockRegex);
63
92
  if (!match) {
64
- const inlineRegex = new RegExp(`^${field}:\\s*\\[([^\\]]*)]`, 'm');
65
- const inlineMatch = text.match(inlineRegex);
93
+ const inlineRegex = new RegExp(`^[ \t]*${field}:\\s*\\[([^\\]]*)]`, 'm');
94
+ const inlineMatch = sourceText.match(inlineRegex);
66
95
  if (!inlineMatch || !inlineMatch[1].trim()) return [];
67
96
  return inlineMatch[1].split(',').map(s => s.trim().replace(/^['"]|['"]$/g, '')).filter(Boolean);
68
97
  }
@@ -72,29 +101,223 @@ function parseYamlProfile(text) {
72
101
  .filter(Boolean);
73
102
  }
74
103
 
104
+ function parseMap(field, sourceText = text) {
105
+ const blockRegex = new RegExp(`^[ \t]*${field}:\\s*\\n((?:[ \t]+[a-zA-Z0-9_-]+:[^\\n]*\\n?)+)`, 'm');
106
+ const match = sourceText.match(blockRegex);
107
+ if (!match) return {};
108
+ const map = {};
109
+ const lines = match[1].split('\n');
110
+ for (const line of lines) {
111
+ const lineClean = line.replace(/#.*$/, '').trim();
112
+ if (!lineClean) continue;
113
+ const kv = lineClean.match(/^([a-zA-Z0-9_-]+):\s*(.*)$/);
114
+ if (kv) {
115
+ const key = kv[1].trim();
116
+ let val = kv[2].trim().replace(/^['"]|['"]$/g, '');
117
+ if (val === 'true') val = true;
118
+ else if (val === 'false') val = false;
119
+ else if (/^\d+$/.test(val)) val = parseInt(val, 10);
120
+ map[key] = val;
121
+ }
122
+ }
123
+ return map;
124
+ }
125
+
126
+ function getSectionBlock(sectionKey) {
127
+ const blockRegex = new RegExp(`^${sectionKey}:\\s*\\n((?:[ \t]+[^\\n]*\\n?)+)`, 'm');
128
+ const match = text.match(blockRegex);
129
+ return match ? match[1] : '';
130
+ }
131
+
132
+ // Parse ProfileV2 sections
133
+ const skillsBlock = getSectionBlock('skills');
134
+ if (skillsBlock) {
135
+ result.schemaVersion = 2;
136
+ result.skills.required = parseList('required', skillsBlock);
137
+ result.skills.preferred = parseList('preferred', skillsBlock);
138
+ result.skills.excluded = parseList('excluded', skillsBlock);
139
+ }
140
+
141
+ const policyBlock = getSectionBlock('policy');
142
+ if (policyBlock) {
143
+ result.schemaVersion = 2;
144
+ result.policy = { ...result.policy, ...parseMap('policy', `policy:\n${policyBlock}`) };
145
+ }
146
+
147
+ const genBlock = getSectionBlock('generation');
148
+ if (genBlock) {
149
+ result.schemaVersion = 2;
150
+ result.generation.documents = parseList('documents', genBlock);
151
+ }
152
+
153
+ const techDefaultsBlock = getSectionBlock('technologyDefaults');
154
+ if (techDefaultsBlock) {
155
+ result.schemaVersion = 2;
156
+ result.technologyDefaults = parseMap('technologyDefaults', `technologyDefaults:\n${techDefaultsBlock}`);
157
+ }
158
+
159
+ // Legacy fields
75
160
  result.prefer_skills = parseList('prefer_skills');
76
161
  result.exclude_skills = parseList('exclude_skills');
162
+ result.require_skills = parseList('require_skills');
77
163
  result.generate_docs = parseList('generate_docs');
78
164
  result.skip_docs = parseList('skip_docs');
165
+ result.enforce = parseMap('enforce');
166
+ result.defaults = parseMap('defaults');
167
+
168
+ // Normalization and bidirectional sync
169
+ if (result.skills.preferred.length === 0 && result.prefer_skills.length > 0) {
170
+ result.skills.preferred = [...result.prefer_skills];
171
+ } else if (result.prefer_skills.length === 0 && result.skills.preferred.length > 0) {
172
+ result.prefer_skills = [...result.skills.preferred];
173
+ }
174
+
175
+ if (result.skills.excluded.length === 0 && result.exclude_skills.length > 0) {
176
+ result.skills.excluded = [...result.exclude_skills];
177
+ } else if (result.exclude_skills.length === 0 && result.skills.excluded.length > 0) {
178
+ result.exclude_skills = [...result.skills.excluded];
179
+ }
180
+
181
+ if (result.skills.required.length === 0 && result.require_skills.length > 0) {
182
+ result.skills.required = [...result.require_skills];
183
+ } else if (result.require_skills.length === 0 && result.skills.required.length > 0) {
184
+ result.require_skills = [...result.skills.required];
185
+ }
186
+
187
+ if (Object.keys(result.technologyDefaults).length === 0 && Object.keys(result.defaults).length > 0) {
188
+ result.technologyDefaults = { ...result.defaults };
189
+ } else if (Object.keys(result.defaults).length === 0 && Object.keys(result.technologyDefaults).length > 0) {
190
+ result.defaults = { ...result.technologyDefaults };
191
+ }
192
+
193
+ if (result.generation.documents.length === 0 && result.generate_docs.length > 0) {
194
+ result.generation.documents = [...result.generate_docs];
195
+ } else if (result.generate_docs.length === 0 && result.generation.documents.length > 0) {
196
+ result.generate_docs = [...result.generation.documents];
197
+ }
198
+
199
+ // Policy <-> Enforce sync
200
+ if (policyBlock) {
201
+ result.enforce.testing = result.policy.testing === 'required' || result.policy.verification === 'required';
202
+ result.enforce.adr = result.policy.adr === 'required';
203
+ result.enforce.code_review = result.policy.review === 'required';
204
+ result.enforce.security_audit = result.policy.security === 'required';
205
+ result.enforce.accessibility_audit = result.policy.accessibility === 'required';
206
+ } else if (Object.keys(result.enforce).length > 0) {
207
+ if (result.enforce.testing !== undefined) {
208
+ result.policy.testing = result.enforce.testing ? 'required' : 'off';
209
+ result.policy.verification = result.enforce.testing ? 'required' : 'off';
210
+ }
211
+ if (result.enforce.adr !== undefined) {
212
+ result.policy.adr = result.enforce.adr ? 'required' : 'off';
213
+ }
214
+ if (result.enforce.code_review !== undefined) {
215
+ result.policy.review = result.enforce.code_review ? 'required' : 'off';
216
+ }
217
+ if (result.enforce.security_audit !== undefined) {
218
+ result.policy.security = result.enforce.security_audit ? 'required' : 'off';
219
+ }
220
+ if (result.enforce.accessibility_audit !== undefined) {
221
+ result.policy.accessibility = result.enforce.accessibility_audit ? 'required' : 'off';
222
+ }
223
+ }
79
224
 
80
225
  return result;
81
226
  }
82
227
 
228
+ /**
229
+ * Validates a profile configuration for contradictions and unknown skills.
230
+ *
231
+ * @param {ProfileConfig} profile - Profile to validate
232
+ * @param {Object} [registry] - Compiled skill registry
233
+ * @returns {{ valid: boolean }} Validation result
234
+ */
235
+ function validateProfile(profile, registry = null) {
236
+ if (!profile || typeof profile !== 'object') {
237
+ const err = new Error('Invalid profile: expected an object');
238
+ err.code = 'CTX_PROFILE_INVALID';
239
+ throw err;
240
+ }
241
+ if (!profile.id || typeof profile.id !== 'string') {
242
+ const err = new Error('Invalid profile: missing profile id');
243
+ err.code = 'CTX_PROFILE_INVALID';
244
+ throw err;
245
+ }
246
+
247
+ const required = profile.skills?.required || profile.require_skills || [];
248
+ const preferred = profile.skills?.preferred || profile.prefer_skills || [];
249
+ const excluded = profile.skills?.excluded || profile.exclude_skills || [];
250
+
251
+ // Check contradictions between required and excluded
252
+ const excSet = new Set(excluded);
253
+ for (const s of required) {
254
+ if (excSet.has(s)) {
255
+ const err = new Error(`Profile contradiction in '${profile.id}': skill '${s}' cannot be both required and excluded.`);
256
+ err.code = 'CTX_PROFILE_CONTRADICTION';
257
+ err.skill = s;
258
+ throw err;
259
+ }
260
+ }
261
+
262
+ // Check contradictions between preferred and excluded
263
+ for (const s of preferred) {
264
+ if (excSet.has(s)) {
265
+ const err = new Error(`Profile contradiction in '${profile.id}': skill '${s}' cannot be both preferred and excluded.`);
266
+ err.code = 'CTX_PROFILE_CONTRADICTION';
267
+ err.skill = s;
268
+ throw err;
269
+ }
270
+ }
271
+
272
+ // Validate skill IDs against registry if provided
273
+ if (registry && registry.skills) {
274
+ const validSkillIds = new Set(Object.keys(registry.skills));
275
+ const allSkills = [...required, ...preferred, ...excluded];
276
+ for (const s of allSkills) {
277
+ if (!validSkillIds.has(s)) {
278
+ const err = new Error(`Unknown skill ID '${s}' in profile '${profile.id}'. Real registered skill IDs only.`);
279
+ err.code = 'CTX_PROFILE_UNKNOWN_SKILL';
280
+ err.skill = s;
281
+ throw err;
282
+ }
283
+ }
284
+ }
285
+
286
+ // Validate policy values
287
+ const validPolicyValues = new Set(['required', 'recommended', 'off']);
288
+ const policy = profile.policy || {};
289
+ for (const [key, val] of Object.entries(policy)) {
290
+ if (typeof val === 'string' && !validPolicyValues.has(val)) {
291
+ const err = new Error(`Invalid policy value '${val}' for '${key}' in profile '${profile.id}'. Expected: required, recommended, off.`);
292
+ err.code = 'CTX_PROFILE_INVALID_POLICY';
293
+ throw err;
294
+ }
295
+ }
296
+
297
+ return { valid: true };
298
+ }
299
+
83
300
  /**
84
301
  * Lists all available project profiles defined in core/profiles.
85
302
  *
86
303
  * @returns {ProfileConfig[]} Array of profile configurations
87
304
  */
88
305
  function listProfiles() {
89
- if (!fs.existsSync(PROFILES_DIR)) return [];
90
- const files = fs.readdirSync(PROFILES_DIR).filter(f => f.endsWith('.yaml') || f.endsWith('.yml'));
91
- return files.map(file => {
92
- const content = fs.readFileSync(path.join(PROFILES_DIR, file), 'utf8');
93
- const parsed = parseYamlProfile(content);
94
- if (!parsed.id) parsed.id = path.basename(file, path.extname(file));
95
- if (!parsed.name) parsed.name = parsed.id;
96
- return parsed;
97
- });
306
+ const profiles = [];
307
+ const searchDirs = [PROFILES_DIR, path.join(AGENTS_DIR, 'catalog', 'presets')];
308
+
309
+ for (const dir of searchDirs) {
310
+ if (!fs.existsSync(dir)) continue;
311
+ const files = fs.readdirSync(dir).filter(f => f.endsWith('.yaml') || f.endsWith('.yml'));
312
+ for (const file of files) {
313
+ const content = fs.readFileSync(path.join(dir, file), 'utf8');
314
+ const parsed = parseYamlProfile(content);
315
+ if (!parsed.id) parsed.id = path.basename(file, path.extname(file));
316
+ if (!parsed.name) parsed.name = parsed.id;
317
+ profiles.push(parsed);
318
+ }
319
+ }
320
+ return profiles;
98
321
  }
99
322
 
100
323
  /**
@@ -114,46 +337,289 @@ function getProfileLockPath(projectDir = process.cwd()) {
114
337
  return path.join(projectDir, '.agents', 'profile.json');
115
338
  }
116
339
 
117
- function getActiveProfile(projectDir = process.cwd()) {
340
+ /**
341
+ * Gets the active profile, taking package overrides into account when a file or scope is passed.
342
+ *
343
+ * @param {string} [projectDir=process.cwd()] - Project directory
344
+ * @param {string} [targetFileOrScope] - Optional file path or package scope
345
+ * @returns {Object|null} Active profile config or null
346
+ */
347
+ function getActiveProfile(projectDir = process.cwd(), targetFileOrScope = null) {
118
348
  const lockPath = getProfileLockPath(projectDir);
119
349
  if (!fs.existsSync(lockPath)) return null;
350
+ let lockData = null;
120
351
  try {
121
352
  const raw = fs.readFileSync(lockPath, 'utf8');
122
- return JSON.parse(raw);
353
+ lockData = JSON.parse(raw);
123
354
  } catch {
124
355
  return null;
125
356
  }
357
+ if (!lockData) return null;
358
+
359
+ // Check for monorepo package override
360
+ if (targetFileOrScope && lockData.overrides && typeof lockData.overrides === 'object') {
361
+ const normalizedScope = targetFileOrScope.replace(/\\/g, '/').replace(/^\.\//, '');
362
+
363
+ // 1. Direct key match in overrides
364
+ let matchedProfileName = lockData.overrides[normalizedScope];
365
+ let matchedScope = normalizedScope;
366
+
367
+ // 2. Prefix match in overrides
368
+ if (!matchedProfileName) {
369
+ for (const [scopeKey, profName] of Object.entries(lockData.overrides)) {
370
+ const cleanScope = scopeKey.replace(/\\/g, '/').replace(/^\.\//, '').replace(/\/$/, '');
371
+ if (normalizedScope === cleanScope || normalizedScope.startsWith(cleanScope + '/')) {
372
+ matchedProfileName = profName;
373
+ matchedScope = cleanScope;
374
+ break;
375
+ }
376
+ }
377
+ }
378
+
379
+ // 3. Nearest package match via WorkspaceGraphBuilder
380
+ if (!matchedProfileName) {
381
+ try {
382
+ const { WorkspaceGraphBuilder } = require('./workspace/workspace-graph.js');
383
+ const builder = new WorkspaceGraphBuilder();
384
+ const graph = builder.build(projectDir);
385
+ const nearestPkg = builder.findNearestPackage(normalizedScope, graph);
386
+ if (nearestPkg) {
387
+ if (lockData.overrides[nearestPkg.name]) {
388
+ matchedProfileName = lockData.overrides[nearestPkg.name];
389
+ matchedScope = nearestPkg.name;
390
+ } else if (lockData.overrides[nearestPkg.root]) {
391
+ matchedProfileName = lockData.overrides[nearestPkg.root];
392
+ matchedScope = nearestPkg.root;
393
+ }
394
+ }
395
+ } catch {
396
+ // ignore workspace graph failure
397
+ }
398
+ }
399
+
400
+ if (matchedProfileName) {
401
+ const overrideProf = getProfile(matchedProfileName);
402
+ if (overrideProf) {
403
+ return {
404
+ ...overrideProf,
405
+ profile: overrideProf.id,
406
+ isOverride: true,
407
+ scope: matchedScope,
408
+ rootProfile: lockData.profile,
409
+ overrides: lockData.overrides,
410
+ };
411
+ }
412
+ }
413
+ }
414
+
415
+ return lockData;
126
416
  }
127
417
 
128
- function applyProfile(profileName, projectDir = process.cwd()) {
418
+ /**
419
+ * Applies a profile to the project, supporting root apply or package-scoped overrides.
420
+ *
421
+ * @param {string} profileName - Profile slug or name
422
+ * @param {string} [projectDir=process.cwd()] - Project directory
423
+ * @param {Object} [options={}] - Options (scope, noExport)
424
+ * @returns {Object} Updated profile lock data
425
+ */
426
+ function applyProfile(profileName, projectDir = process.cwd(), options = {}) {
129
427
  const profile = getProfile(profileName);
130
428
  if (!profile) {
131
429
  throw new Error(`Profile '${profileName}' not found. Available profiles: ${listProfiles().map(p => p.id).join(', ')}`);
132
430
  }
133
431
 
432
+ validateProfile(profile);
433
+
134
434
  const lockPath = getProfileLockPath(projectDir);
135
435
  fs.mkdirSync(path.dirname(lockPath), { recursive: true });
136
436
 
137
- const lockData = {
138
- profile: profile.id,
139
- name: profile.name,
140
- description: profile.description,
141
- exclude_skills: profile.exclude_skills || [],
142
- prefer_skills: profile.prefer_skills || [],
143
- appliedAt: new Date().toISOString(),
144
- };
437
+ let existing = {};
438
+ if (fs.existsSync(lockPath)) {
439
+ try {
440
+ existing = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
441
+ } catch {
442
+ existing = {};
443
+ }
444
+ }
445
+
446
+ let lockData;
447
+ if (options.scope) {
448
+ const scope = options.scope.replace(/\\/g, '/').replace(/^\.\//, '').replace(/\/$/, '');
449
+ const overrides = existing.overrides || {};
450
+ overrides[scope] = profile.id;
451
+
452
+ lockData = {
453
+ ...existing,
454
+ overrides,
455
+ updatedAt: new Date().toISOString(),
456
+ };
457
+ if (!lockData.profile) {
458
+ lockData.profile = profile.id;
459
+ lockData.name = profile.name;
460
+ lockData.description = profile.description;
461
+ lockData.skills = profile.skills;
462
+ lockData.policy = profile.policy;
463
+ lockData.generation = profile.generation;
464
+ lockData.technologyDefaults = profile.technologyDefaults;
465
+ lockData.exclude_skills = profile.exclude_skills || [];
466
+ lockData.prefer_skills = profile.prefer_skills || [];
467
+ lockData.require_skills = profile.require_skills || [];
468
+ lockData.enforce = profile.enforce || {};
469
+ lockData.defaults = profile.defaults || {};
470
+ }
471
+ } else {
472
+ lockData = {
473
+ schemaVersion: 2,
474
+ profile: profile.id,
475
+ name: profile.name,
476
+ description: profile.description,
477
+ skills: profile.skills || {
478
+ required: profile.require_skills || [],
479
+ preferred: profile.prefer_skills || [],
480
+ excluded: profile.exclude_skills || [],
481
+ },
482
+ policy: profile.policy || {},
483
+ generation: profile.generation || {
484
+ documents: profile.generate_docs || [],
485
+ },
486
+ technologyDefaults: profile.technologyDefaults || profile.defaults || {},
487
+ exclude_skills: profile.exclude_skills || [],
488
+ prefer_skills: profile.prefer_skills || [],
489
+ require_skills: profile.require_skills || [],
490
+ enforce: profile.enforce || {},
491
+ defaults: profile.defaults || {},
492
+ overrides: existing.overrides || {},
493
+ appliedAt: new Date().toISOString(),
494
+ };
495
+ }
496
+
497
+ const lock = new ProjectMutationLock(projectDir);
498
+ const lockToken = lock.acquire({ command: `profile apply ${profile.id}` });
499
+
500
+ try {
501
+ const tx = new JournaledTransaction(projectDir);
502
+ tx.stageWrite(path.relative(projectDir, lockPath).replace(/\\/g, '/'), JSON.stringify(lockData, null, 2) + '\n');
503
+ tx.commit();
504
+ } finally {
505
+ lock.release(lockToken);
506
+ }
145
507
 
146
- fs.writeFileSync(lockPath, JSON.stringify(lockData, null, 2) + '\n');
147
508
  return lockData;
148
509
  }
149
510
 
150
- function removeActiveProfile(projectDir = process.cwd()) {
511
+ /**
512
+ * Removes active profile lock or a specific package override.
513
+ *
514
+ * @param {string} [projectDir=process.cwd()] - Project directory
515
+ * @param {Object} [options={}] - Options (scope)
516
+ * @returns {boolean} True if removed
517
+ */
518
+ function removeActiveProfile(projectDir = process.cwd(), options = {}) {
151
519
  const lockPath = getProfileLockPath(projectDir);
152
- if (fs.existsSync(lockPath)) {
153
- fs.unlinkSync(lockPath);
154
- return true;
520
+ if (!fs.existsSync(lockPath)) return false;
521
+
522
+ if (options && options.scope) {
523
+ try {
524
+ const lockData = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
525
+ const cleanScope = options.scope.replace(/\\/g, '/').replace(/^\.\//, '').replace(/\/$/, '');
526
+ if (lockData.overrides && lockData.overrides[cleanScope]) {
527
+ delete lockData.overrides[cleanScope];
528
+
529
+ const lock = new ProjectMutationLock(projectDir);
530
+ const lockToken = lock.acquire({ command: 'profile remove override' });
531
+ try {
532
+ const tx = new JournaledTransaction(projectDir);
533
+ tx.stageWrite(path.relative(projectDir, lockPath).replace(/\\/g, '/'), JSON.stringify(lockData, null, 2) + '\n');
534
+ tx.commit();
535
+ } finally {
536
+ lock.release(lockToken);
537
+ }
538
+ return true;
539
+ }
540
+ } catch {
541
+ return false;
542
+ }
543
+ return false;
155
544
  }
156
- return false;
545
+
546
+ const lock = new ProjectMutationLock(projectDir);
547
+ const lockToken = lock.acquire({ command: 'profile remove' });
548
+ try {
549
+ const tx = new JournaledTransaction(projectDir);
550
+ tx.stageDelete(path.relative(projectDir, lockPath).replace(/\\/g, '/'));
551
+ tx.commit();
552
+ } finally {
553
+ lock.release(lockToken);
554
+ }
555
+ return true;
556
+ }
557
+
558
+ /**
559
+ * Returns structured explanation of a profile.
560
+ *
561
+ * @param {string} profileName - Profile slug or name
562
+ * @param {string} [projectDir=process.cwd()] - Project directory
563
+ * @returns {Object} Explanation structure
564
+ */
565
+ function explainProfile(profileName, projectDir = process.cwd()) {
566
+ const profile = getProfile(profileName);
567
+ if (!profile) {
568
+ throw new Error(`Profile '${profileName}' not found. Available profiles: ${listProfiles().map(p => p.id).join(', ')}`);
569
+ }
570
+
571
+ return {
572
+ schemaVersion: profile.schemaVersion || 2,
573
+ id: profile.id,
574
+ name: profile.name,
575
+ description: profile.description,
576
+ skills: {
577
+ required: profile.skills?.required || profile.require_skills || [],
578
+ preferred: profile.skills?.preferred || profile.prefer_skills || [],
579
+ excluded: profile.skills?.excluded || profile.exclude_skills || [],
580
+ },
581
+ policy: profile.policy || {},
582
+ technologyDefaults: profile.technologyDefaults || profile.defaults || {},
583
+ generation: {
584
+ documents: profile.generation?.documents || profile.generate_docs || [],
585
+ },
586
+ };
587
+ }
588
+
589
+ /**
590
+ * Formats structured profile explanation into human-readable text.
591
+ *
592
+ * @param {Object} explanation - Profile explanation object
593
+ * @returns {string} Formatted text
594
+ */
595
+ function formatProfileExplanation(explanation) {
596
+ const lines = [];
597
+ lines.push(`Profile: ${explanation.name} (${explanation.id})`);
598
+ lines.push(`Description: ${explanation.description}`);
599
+ lines.push('');
600
+ lines.push('Skills:');
601
+ lines.push(` Required: ${explanation.skills.required.length > 0 ? explanation.skills.required.join(', ') : 'none'}`);
602
+ lines.push(` Preferred: ${explanation.skills.preferred.length > 0 ? explanation.skills.preferred.join(', ') : 'none'}`);
603
+ lines.push(` Excluded: ${explanation.skills.excluded.length > 0 ? explanation.skills.excluded.join(', ') : 'none'}`);
604
+ lines.push('');
605
+ lines.push('Policy:');
606
+ for (const [key, val] of Object.entries(explanation.policy)) {
607
+ lines.push(` ${(key.charAt(0).toUpperCase() + key.slice(1)).padEnd(14)}: ${val}`);
608
+ }
609
+ lines.push('');
610
+ lines.push('Technology Defaults:');
611
+ const techKeys = Object.keys(explanation.technologyDefaults);
612
+ if (techKeys.length === 0) {
613
+ lines.push(' none');
614
+ } else {
615
+ for (const [key, val] of Object.entries(explanation.technologyDefaults)) {
616
+ lines.push(` ${key.padEnd(14)}: ${val}`);
617
+ }
618
+ }
619
+ lines.push('');
620
+ lines.push('Generation Documents:');
621
+ lines.push(` ${explanation.generation.documents.join(', ') || 'none'}`);
622
+ return lines.join('\n');
157
623
  }
158
624
 
159
625
  /**
@@ -237,18 +703,10 @@ function detectStack(projectDir = process.cwd()) {
237
703
  }
238
704
 
239
705
  // Infer recommended profile
240
- let recommendedProfile = 'startup';
706
+ let recommendedProfile = 'init';
241
707
  const hasFrontend = detected.some(d => ['React', 'Next.js', 'Tailwind CSS'].includes(d));
242
708
  const hasBackend = detected.some(d => ['Node.js Backend', 'NestJS', 'Python'].includes(d));
243
709
 
244
- if (hasFrontend && !hasBackend) {
245
- recommendedProfile = 'frontend';
246
- } else if (!hasFrontend && hasBackend) {
247
- recommendedProfile = 'backend';
248
- } else if (hasFrontend && hasBackend) {
249
- recommendedProfile = 'startup';
250
- }
251
-
252
710
  return {
253
711
  detected,
254
712
  recommendedProfile,
@@ -264,4 +722,7 @@ module.exports = {
264
722
  removeActiveProfile,
265
723
  detectStack,
266
724
  parseYamlProfile,
725
+ validateProfile,
726
+ explainProfile,
727
+ formatProfileExplanation,
267
728
  };