contextos-agents 1.7.0 → 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 (309) hide show
  1. package/.agents/AGENTS.md +1 -1
  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 +80 -101
  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 +574 -111
  26. package/.agents/customization-dx.js +282 -0
  27. package/.agents/doctor.js +719 -64
  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 +259 -60
  38. package/.agents/profiles.js +486 -51
  39. package/.agents/resolver.js +50 -534
  40. package/.agents/schemas/attestation.review.v1.json +111 -0
  41. package/.agents/schemas/attestation.verification.v1.json +85 -0
  42. package/.agents/schemas/lockfile.v2.schema.json +134 -0
  43. package/.agents/schemas/profile.v2.schema.json +114 -0
  44. package/.agents/schemas/runtime.thread.v1.json +192 -0
  45. package/.agents/schemas/skill.manifest.v2.json +177 -0
  46. package/.agents/schemas/verification.spec.v1.json +39 -0
  47. package/.agents/schemas/workspace.graph.schema.json +106 -0
  48. package/.agents/transaction-core/event-store.js +288 -0
  49. package/.agents/transaction-core/idempotency.js +129 -0
  50. package/.agents/transaction-core/ipc-lock.js +311 -0
  51. package/.agents/transaction-core/plugin-supply-chain-bundle.js +436 -0
  52. package/.agents/validate.js +44 -1
  53. package/.agents/watch.js +354 -102
  54. package/.agents/workspace/workspace-graph.js +778 -0
  55. package/README.md +59 -387
  56. package/benchmarks/v2/analysis/statistics.js +140 -0
  57. package/benchmarks/v2/analysis/stats.js +69 -0
  58. package/benchmarks/v2/arms/arm-definitions.js +79 -0
  59. package/benchmarks/v2/dataset.schema.json +34 -0
  60. package/benchmarks/v2/evaluators/index.js +25 -0
  61. package/benchmarks/v2/evaluators/verified-success.js +116 -0
  62. package/benchmarks/v2/harness/runner.js +88 -0
  63. package/benchmarks/v2/pilot-tasks.json +392 -0
  64. package/bin/commands/recover.js +88 -0
  65. package/bin/commands/update.js +80 -17
  66. package/bin/commands.js +62 -25
  67. package/bin/index.js +138 -81
  68. package/bin/lib/lockfile.js +5 -3
  69. package/bin/lib/safe-writer.js +34 -3
  70. package/package.json +85 -72
  71. package/registry.json +2 -2
  72. package/registry.v2.schema.json +86 -0
  73. package/.agents/core/profiles/backend.yaml +0 -47
  74. package/.agents/core/profiles/enterprise.yaml +0 -46
  75. package/.agents/core/profiles/frontend.yaml +0 -46
  76. package/.agents/core/profiles/hackathon.yaml +0 -45
  77. package/.agents/core/profiles/mvp.yaml +0 -44
  78. package/.agents/core/profiles/startup.yaml +0 -48
  79. package/.agents/core/skills/adapters/EXAMPLES.md +0 -19
  80. package/.agents/core/skills/adapters/SKILL.md +0 -105
  81. package/.agents/core/skills/adapters/TROUBLESHOOTING.md +0 -7
  82. package/.agents/core/skills/adapters/VALIDATION.json +0 -12
  83. package/.agents/core/skills/adapters/skill.yaml +0 -16
  84. package/.agents/core/skills/architecture-diagrams/SKILL.md +0 -108
  85. package/.agents/core/skills/architecture-diagrams/VALIDATION.json +0 -12
  86. package/.agents/core/skills/architecture-diagrams/skill.yaml +0 -12
  87. package/.agents/core/skills/brutalist-design/SKILL.md +0 -150
  88. package/.agents/core/skills/brutalist-design/VALIDATION.json +0 -12
  89. package/.agents/core/skills/brutalist-design/skill.yaml +0 -12
  90. package/.agents/core/skills/database/EXAMPLES.md +0 -74
  91. package/.agents/core/skills/database/SKILL.md +0 -101
  92. package/.agents/core/skills/database/TROUBLESHOOTING.md +0 -18
  93. package/.agents/core/skills/database/VALIDATION.json +0 -11
  94. package/.agents/core/skills/database/skill.yaml +0 -31
  95. package/.agents/core/skills/ddd/EXAMPLES.md +0 -42
  96. package/.agents/core/skills/ddd/SKILL.md +0 -247
  97. package/.agents/core/skills/ddd/TROUBLESHOOTING.md +0 -19
  98. package/.agents/core/skills/ddd/VALIDATION.json +0 -12
  99. package/.agents/core/skills/ddd/ddd.md +0 -178
  100. package/.agents/core/skills/ddd/skill.yaml +0 -17
  101. package/.agents/core/skills/decisions/EXAMPLES.md +0 -35
  102. package/.agents/core/skills/decisions/SKILL.md +0 -90
  103. package/.agents/core/skills/decisions/TROUBLESHOOTING.md +0 -13
  104. package/.agents/core/skills/decisions/VALIDATION.json +0 -12
  105. package/.agents/core/skills/decisions/skill.yaml +0 -16
  106. package/.agents/core/skills/docker/EXAMPLES.md +0 -56
  107. package/.agents/core/skills/docker/SKILL.md +0 -63
  108. package/.agents/core/skills/docker/TROUBLESHOOTING.md +0 -18
  109. package/.agents/core/skills/docker/VALIDATION.json +0 -11
  110. package/.agents/core/skills/docker/skill.yaml +0 -29
  111. package/.agents/core/skills/fastapi/EXAMPLES.md +0 -36
  112. package/.agents/core/skills/fastapi/SKILL.md +0 -148
  113. package/.agents/core/skills/fastapi/TROUBLESHOOTING.md +0 -19
  114. package/.agents/core/skills/fastapi/VALIDATION.json +0 -12
  115. package/.agents/core/skills/fastapi/fastapi.md +0 -112
  116. package/.agents/core/skills/fastapi/skill.yaml +0 -17
  117. package/.agents/core/skills/generators/EXAMPLES.md +0 -19
  118. package/.agents/core/skills/generators/SKILL.md +0 -112
  119. package/.agents/core/skills/generators/TROUBLESHOOTING.md +0 -7
  120. package/.agents/core/skills/generators/VALIDATION.json +0 -12
  121. package/.agents/core/skills/generators/skill.yaml +0 -25
  122. package/.agents/core/skills/generators/templates/API.md +0 -77
  123. package/.agents/core/skills/generators/templates/ARCHITECTURE.md +0 -70
  124. package/.agents/core/skills/generators/templates/DATABASE.md +0 -42
  125. package/.agents/core/skills/generators/templates/DECISION.md +0 -46
  126. package/.agents/core/skills/generators/templates/PRD.md +0 -67
  127. package/.agents/core/skills/generators/templates/PROJECT_GRAPH.md +0 -56
  128. package/.agents/core/skills/generators/templates/ROADMAP.md +0 -51
  129. package/.agents/core/skills/generators/templates/TASKS.md +0 -43
  130. package/.agents/core/skills/generators/templates/UI.md +0 -73
  131. package/.agents/core/skills/graphify/EXAMPLES.md +0 -73
  132. package/.agents/core/skills/graphify/SKILL.md +0 -130
  133. package/.agents/core/skills/graphify/VALIDATION.json +0 -12
  134. package/.agents/core/skills/graphify/skill.yaml +0 -18
  135. package/.agents/core/skills/impeccable-design/EXAMPLES.md +0 -26
  136. package/.agents/core/skills/impeccable-design/SKILL.md +0 -201
  137. package/.agents/core/skills/impeccable-design/TROUBLESHOOTING.md +0 -19
  138. package/.agents/core/skills/impeccable-design/VALIDATION.json +0 -12
  139. package/.agents/core/skills/impeccable-design/skill.yaml +0 -20
  140. package/.agents/core/skills/interview-me/SKILL.md +0 -97
  141. package/.agents/core/skills/interview-me/VALIDATION.json +0 -12
  142. package/.agents/core/skills/interview-me/skill.yaml +0 -12
  143. package/.agents/core/skills/microservices/EXAMPLES.md +0 -38
  144. package/.agents/core/skills/microservices/SKILL.md +0 -164
  145. package/.agents/core/skills/microservices/TROUBLESHOOTING.md +0 -19
  146. package/.agents/core/skills/microservices/VALIDATION.json +0 -12
  147. package/.agents/core/skills/microservices/microservices.md +0 -119
  148. package/.agents/core/skills/microservices/skill.yaml +0 -17
  149. package/.agents/core/skills/minimalist-design/SKILL.md +0 -113
  150. package/.agents/core/skills/minimalist-design/VALIDATION.json +0 -12
  151. package/.agents/core/skills/minimalist-design/skill.yaml +0 -12
  152. package/.agents/core/skills/nestjs/EXAMPLES.md +0 -40
  153. package/.agents/core/skills/nestjs/SKILL.md +0 -139
  154. package/.agents/core/skills/nestjs/TROUBLESHOOTING.md +0 -19
  155. package/.agents/core/skills/nestjs/VALIDATION.json +0 -12
  156. package/.agents/core/skills/nestjs/nestjs.md +0 -103
  157. package/.agents/core/skills/nestjs/skill.yaml +0 -17
  158. package/.agents/core/skills/nextjs/EXAMPLES.md +0 -40
  159. package/.agents/core/skills/nextjs/SKILL.md +0 -163
  160. package/.agents/core/skills/nextjs/TROUBLESHOOTING.md +0 -19
  161. package/.agents/core/skills/nextjs/VALIDATION.json +0 -12
  162. package/.agents/core/skills/nextjs/nextjs.md +0 -67
  163. package/.agents/core/skills/nextjs/skill.yaml +0 -17
  164. package/.agents/core/skills/node/EXAMPLES.md +0 -80
  165. package/.agents/core/skills/node/SKILL.md +0 -128
  166. package/.agents/core/skills/node/TROUBLESHOOTING.md +0 -19
  167. package/.agents/core/skills/node/VALIDATION.json +0 -12
  168. package/.agents/core/skills/node/node.md +0 -87
  169. package/.agents/core/skills/node/skill.yaml +0 -17
  170. package/.agents/core/skills/performance/EXAMPLES.md +0 -30
  171. package/.agents/core/skills/performance/SKILL.md +0 -75
  172. package/.agents/core/skills/performance/TROUBLESHOOTING.md +0 -19
  173. package/.agents/core/skills/performance/VALIDATION.json +0 -12
  174. package/.agents/core/skills/performance/performance.md +0 -52
  175. package/.agents/core/skills/performance/skill.yaml +0 -17
  176. package/.agents/core/skills/react/EXAMPLES.md +0 -79
  177. package/.agents/core/skills/react/SKILL.md +0 -132
  178. package/.agents/core/skills/react/TROUBLESHOOTING.md +0 -19
  179. package/.agents/core/skills/react/VALIDATION.json +0 -12
  180. package/.agents/core/skills/react/react.md +0 -93
  181. package/.agents/core/skills/react/skill.yaml +0 -17
  182. package/.agents/core/skills/react-best-practices/SKILL.md +0 -155
  183. package/.agents/core/skills/react-best-practices/VALIDATION.json +0 -12
  184. package/.agents/core/skills/react-best-practices/skill.yaml +0 -14
  185. package/.agents/core/skills/redesign-audit/SKILL.md +0 -117
  186. package/.agents/core/skills/redesign-audit/VALIDATION.json +0 -12
  187. package/.agents/core/skills/redesign-audit/skill.yaml +0 -12
  188. package/.agents/core/skills/soft-design/SKILL.md +0 -108
  189. package/.agents/core/skills/soft-design/VALIDATION.json +0 -12
  190. package/.agents/core/skills/soft-design/skill.yaml +0 -12
  191. package/.agents/core/skills/state-management/EXAMPLES.md +0 -56
  192. package/.agents/core/skills/state-management/SKILL.md +0 -48
  193. package/.agents/core/skills/state-management/TROUBLESHOOTING.md +0 -18
  194. package/.agents/core/skills/state-management/VALIDATION.json +0 -11
  195. package/.agents/core/skills/state-management/skill.yaml +0 -28
  196. package/.agents/core/skills/subagent-orchestrator/SKILL.md +0 -117
  197. package/.agents/core/skills/subagent-orchestrator/VALIDATION.json +0 -12
  198. package/.agents/core/skills/subagent-orchestrator/skill.yaml +0 -12
  199. package/.agents/core/skills/system-design/EXAMPLES.md +0 -75
  200. package/.agents/core/skills/system-design/SKILL.md +0 -419
  201. package/.agents/core/skills/system-design/TROUBLESHOOTING.md +0 -19
  202. package/.agents/core/skills/system-design/VALIDATION.json +0 -12
  203. package/.agents/core/skills/system-design/skill.yaml +0 -20
  204. package/.agents/core/skills/system-design/system-design.md +0 -112
  205. package/.agents/core/skills/testing/EXAMPLES.md +0 -71
  206. package/.agents/core/skills/testing/SKILL.md +0 -70
  207. package/.agents/core/skills/testing/TROUBLESHOOTING.md +0 -18
  208. package/.agents/core/skills/testing/VALIDATION.json +0 -11
  209. package/.agents/core/skills/testing/skill.yaml +0 -32
  210. package/.agents/core/skills/typescript/EXAMPLES.md +0 -64
  211. package/.agents/core/skills/typescript/SKILL.md +0 -112
  212. package/.agents/core/skills/typescript/TROUBLESHOOTING.md +0 -19
  213. package/.agents/core/skills/typescript/VALIDATION.json +0 -12
  214. package/.agents/core/skills/typescript/skill.yaml +0 -17
  215. package/.agents/core/skills/typescript/typescript.md +0 -71
  216. package/.agents/core/skills/ui-design/EXAMPLES.md +0 -21
  217. package/.agents/core/skills/ui-design/SKILL.md +0 -124
  218. package/.agents/core/skills/ui-design/TROUBLESHOOTING.md +0 -19
  219. package/.agents/core/skills/ui-design/VALIDATION.json +0 -12
  220. package/.agents/core/skills/ui-design/skill.yaml +0 -17
  221. package/.agents/core/skills/ui-design/ui.md +0 -88
  222. package/.agents/core/skills/ui-ux-pro/EXAMPLES.md +0 -62
  223. package/.agents/core/skills/ui-ux-pro/SKILL.md +0 -375
  224. package/.agents/core/skills/ui-ux-pro/TROUBLESHOOTING.md +0 -19
  225. package/.agents/core/skills/ui-ux-pro/VALIDATION.json +0 -12
  226. package/.agents/core/skills/ui-ux-pro/skill.yaml +0 -19
  227. package/.agents/core/skills/ux-design/EXAMPLES.md +0 -36
  228. package/.agents/core/skills/ux-design/SKILL.md +0 -116
  229. package/.agents/core/skills/ux-design/TROUBLESHOOTING.md +0 -19
  230. package/.agents/core/skills/ux-design/VALIDATION.json +0 -12
  231. package/.agents/core/skills/ux-design/skill.yaml +0 -17
  232. package/.agents/core/skills/ux-design/ux.md +0 -80
  233. package/.agents/core/skills/vercel-optimize/SKILL.md +0 -83
  234. package/.agents/core/skills/vercel-optimize/VALIDATION.json +0 -12
  235. package/.agents/core/skills/vercel-optimize/scripts/collect-signals.mjs +0 -131
  236. package/.agents/core/skills/vercel-optimize/scripts/gate-investigations.mjs +0 -142
  237. package/.agents/core/skills/vercel-optimize/scripts/merge-signals.mjs +0 -143
  238. package/.agents/core/skills/vercel-optimize/scripts/scan-codebase.mjs +0 -174
  239. package/.agents/core/skills/vercel-optimize/skill.yaml +0 -18
  240. package/.agents/core/skills/web-accessibility/EXAMPLES.md +0 -39
  241. package/.agents/core/skills/web-accessibility/SKILL.md +0 -170
  242. package/.agents/core/skills/web-accessibility/TROUBLESHOOTING.md +0 -19
  243. package/.agents/core/skills/web-accessibility/VALIDATION.json +0 -12
  244. package/.agents/core/skills/web-accessibility/accessibility.md +0 -63
  245. package/.agents/core/skills/web-accessibility/skill.yaml +0 -17
  246. package/.agents/generated/claude/skills/adapters/SKILL.md +0 -126
  247. package/.agents/generated/claude/skills/architecture-diagrams/SKILL.md +0 -101
  248. package/.agents/generated/claude/skills/brutalist-design/SKILL.md +0 -145
  249. package/.agents/generated/claude/skills/database/SKILL.md +0 -191
  250. package/.agents/generated/claude/skills/ddd/SKILL.md +0 -305
  251. package/.agents/generated/claude/skills/decisions/SKILL.md +0 -134
  252. package/.agents/generated/claude/skills/docker/SKILL.md +0 -135
  253. package/.agents/generated/claude/skills/fastapi/SKILL.md +0 -200
  254. package/.agents/generated/claude/skills/generators/SKILL.md +0 -133
  255. package/.agents/generated/claude/skills/graphify/SKILL.md +0 -198
  256. package/.agents/generated/claude/skills/impeccable-design/SKILL.md +0 -241
  257. package/.agents/generated/claude/skills/interview-me/SKILL.md +0 -90
  258. package/.agents/generated/claude/skills/microservices/SKILL.md +0 -218
  259. package/.agents/generated/claude/skills/minimalist-design/SKILL.md +0 -108
  260. package/.agents/generated/claude/skills/nestjs/SKILL.md +0 -195
  261. package/.agents/generated/claude/skills/nextjs/SKILL.md +0 -219
  262. package/.agents/generated/claude/skills/node/SKILL.md +0 -224
  263. package/.agents/generated/claude/skills/performance/SKILL.md +0 -121
  264. package/.agents/generated/claude/skills/react/SKILL.md +0 -227
  265. package/.agents/generated/claude/skills/react-best-practices/SKILL.md +0 -146
  266. package/.agents/generated/claude/skills/redesign-audit/SKILL.md +0 -112
  267. package/.agents/generated/claude/skills/soft-design/SKILL.md +0 -103
  268. package/.agents/generated/claude/skills/state-management/SKILL.md +0 -120
  269. package/.agents/generated/claude/skills/subagent-orchestrator/SKILL.md +0 -110
  270. package/.agents/generated/claude/skills/system-design/SKILL.md +0 -507
  271. package/.agents/generated/claude/skills/testing/SKILL.md +0 -157
  272. package/.agents/generated/claude/skills/typescript/SKILL.md +0 -192
  273. package/.agents/generated/claude/skills/ui-design/SKILL.md +0 -161
  274. package/.agents/generated/claude/skills/ui-ux-pro/SKILL.md +0 -451
  275. package/.agents/generated/claude/skills/ux-design/SKILL.md +0 -168
  276. package/.agents/generated/claude/skills/vercel-optimize/SKILL.md +0 -76
  277. package/.agents/generated/claude/skills/web-accessibility/SKILL.md +0 -225
  278. package/.agents/generated/gemini/skills/adapters/SKILL.md +0 -135
  279. package/.agents/generated/gemini/skills/architecture-diagrams/SKILL.md +0 -107
  280. package/.agents/generated/gemini/skills/brutalist-design/SKILL.md +0 -151
  281. package/.agents/generated/gemini/skills/database/SKILL.md +0 -200
  282. package/.agents/generated/gemini/skills/ddd/SKILL.md +0 -314
  283. package/.agents/generated/gemini/skills/decisions/SKILL.md +0 -143
  284. package/.agents/generated/gemini/skills/docker/SKILL.md +0 -144
  285. package/.agents/generated/gemini/skills/fastapi/SKILL.md +0 -209
  286. package/.agents/generated/gemini/skills/generators/SKILL.md +0 -142
  287. package/.agents/generated/gemini/skills/graphify/SKILL.md +0 -205
  288. package/.agents/generated/gemini/skills/impeccable-design/SKILL.md +0 -250
  289. package/.agents/generated/gemini/skills/interview-me/SKILL.md +0 -96
  290. package/.agents/generated/gemini/skills/microservices/SKILL.md +0 -227
  291. package/.agents/generated/gemini/skills/minimalist-design/SKILL.md +0 -114
  292. package/.agents/generated/gemini/skills/nestjs/SKILL.md +0 -204
  293. package/.agents/generated/gemini/skills/nextjs/SKILL.md +0 -298
  294. package/.agents/generated/gemini/skills/node/SKILL.md +0 -323
  295. package/.agents/generated/gemini/skills/performance/SKILL.md +0 -185
  296. package/.agents/generated/gemini/skills/react/SKILL.md +0 -332
  297. package/.agents/generated/gemini/skills/react-best-practices/SKILL.md +0 -152
  298. package/.agents/generated/gemini/skills/redesign-audit/SKILL.md +0 -118
  299. package/.agents/generated/gemini/skills/soft-design/SKILL.md +0 -109
  300. package/.agents/generated/gemini/skills/state-management/SKILL.md +0 -129
  301. package/.agents/generated/gemini/skills/subagent-orchestrator/SKILL.md +0 -116
  302. package/.agents/generated/gemini/skills/system-design/SKILL.md +0 -631
  303. package/.agents/generated/gemini/skills/testing/SKILL.md +0 -166
  304. package/.agents/generated/gemini/skills/typescript/SKILL.md +0 -275
  305. package/.agents/generated/gemini/skills/ui-design/SKILL.md +0 -170
  306. package/.agents/generated/gemini/skills/ui-ux-pro/SKILL.md +0 -460
  307. package/.agents/generated/gemini/skills/ux-design/SKILL.md +0 -177
  308. package/.agents/generated/gemini/skills/vercel-optimize/SKILL.md +0 -82
  309. package/.agents/generated/gemini/skills/web-accessibility/SKILL.md +0 -300
@@ -25,6 +25,17 @@ const path = require('path');
25
25
  const https = require('https');
26
26
  const crypto = require('crypto');
27
27
  const { execFileSync } = require('child_process');
28
+ const { ProjectMutationLock } = require('./filesystem/project-lock.js');
29
+ const JournaledTransaction = require('./filesystem/journaled-transaction.js');
30
+ const {
31
+ calculateTreeDigest,
32
+ validateArchiveEntry,
33
+ validatePluginPinning,
34
+ ScriptGrantManager,
35
+ AtomicPluginUpdater,
36
+ THREAT_CODES,
37
+ verifyNpmTarballIntegrity,
38
+ } = require('./transaction-core/plugin-supply-chain-bundle.js');
28
39
 
29
40
  // ── Paths ─────────────────────────────────────────────────────────────────────
30
41
  const ROOT = process.cwd();
@@ -214,9 +225,19 @@ function readLock() {
214
225
  }
215
226
  }
216
227
 
217
- function writeLock(lock) {
218
- fs.mkdirSync(AGENTS_DIR, { recursive: true });
219
- fs.writeFileSync(PLUGINS_JSON, JSON.stringify(lock, null, 2) + '\n');
228
+ function writeLock(lock, tx = null) {
229
+ if (tx) {
230
+ const relLockPath = toPosix(path.relative(ROOT, PLUGINS_JSON));
231
+ tx.stageWrite(relLockPath, JSON.stringify(lock, null, 2) + '\n');
232
+ } else {
233
+ fs.mkdirSync(AGENTS_DIR, { recursive: true });
234
+ fs.writeFileSync(PLUGINS_JSON, JSON.stringify(lock, null, 2) + '\n');
235
+ }
236
+ }
237
+
238
+ // POSIX path helper
239
+ function toPosix(p) {
240
+ return p.replace(/\\/g, '/');
220
241
  }
221
242
 
222
243
  // ── HTTP fetch helper (no deps) ───────────────────────────────────────────────
@@ -293,7 +314,17 @@ function parseRef(ref) {
293
314
  throw new Error('Invalid GitHub plugin reference');
294
315
  }
295
316
 
296
- return { type: 'github', owner, repo, gitRef, isPinned: repoRef.includes('@'), subPath, raw: ref };
317
+ const isPinned = repoRef.includes('@');
318
+ return {
319
+ type: 'github',
320
+ owner,
321
+ repo,
322
+ gitRef,
323
+ commit: isPinned ? gitRef : undefined,
324
+ isPinned,
325
+ subPath,
326
+ raw: ref,
327
+ };
297
328
  }
298
329
  // npm package
299
330
  if (!isValidNpmPackage(ref)) {
@@ -303,7 +334,7 @@ function parseRef(ref) {
303
334
  }
304
335
 
305
336
  // ── GitHub installer ──────────────────────────────────────────────────────────
306
- async function installFromGitHub(descriptor, skillName, dryRun, checksum, forceUnsafe = false) {
337
+ async function installFromGitHub(descriptor, skillName, dryRun, checksum, forceUnsafe = false, tx = null) {
307
338
  const { owner, repo, gitRef, isPinned, subPath } = descriptor;
308
339
  const skillPath = subPath || '';
309
340
  const base = `https://raw.githubusercontent.com/${owner}/${repo}/${gitRef}`;
@@ -350,6 +381,7 @@ async function installFromGitHub(descriptor, skillName, dryRun, checksum, forceU
350
381
  }
351
382
 
352
383
  const targetDir = path.join(PLUGINS_DIR, skillName);
384
+ const relTargetDir = path.relative(ROOT, targetDir).replace(/\\/g, '/');
353
385
 
354
386
  if (dryRun) {
355
387
  console.log(c.yellow(` [DRY-RUN] Would install to: ${targetDir}`));
@@ -357,22 +389,30 @@ async function installFromGitHub(descriptor, skillName, dryRun, checksum, forceU
357
389
  return sha256;
358
390
  }
359
391
 
360
- fs.mkdirSync(targetDir, { recursive: true });
361
- fs.writeFileSync(path.join(targetDir, 'SKILL.md'), skillMdContent);
362
- if (yamlContent) {
363
- fs.writeFileSync(path.join(targetDir, 'skill.yaml'), yamlContent);
392
+ // Pre-scan using temp dir to keep `scanPluginDirectory` happy, as it reads from disk
393
+ const temporaryPrefix = fs.mkdtempSync(path.join(os.tmpdir(), 'contextos-github-'));
394
+ try {
395
+ fs.writeFileSync(path.join(temporaryPrefix, 'SKILL.md'), skillMdContent);
396
+ if (yamlContent) fs.writeFileSync(path.join(temporaryPrefix, 'skill.yaml'), yamlContent);
397
+ scanPluginDirectory(temporaryPrefix, { throwOnMatch: !forceUnsafe, forceUnsafe });
398
+ } finally {
399
+ fs.rmSync(temporaryPrefix, { recursive: true, force: true });
364
400
  }
365
401
 
366
- // Deep security scan before writing source marker
367
- try {
368
- scanPluginDirectory(targetDir, { throwOnMatch: !forceUnsafe, forceUnsafe });
369
- } catch (err) {
370
- fs.rmSync(targetDir, { recursive: true, force: true });
371
- throw err;
402
+ const manifest = {};
403
+
404
+ const skillMdHash = crypto.createHash('sha256').update(skillMdContent).digest('hex');
405
+ tx.stageWrite(`${relTargetDir}/SKILL.md`, skillMdContent);
406
+ manifest['SKILL.md'] = skillMdHash;
407
+
408
+ if (yamlContent) {
409
+ const yamlHash = crypto.createHash('sha256').update(yamlContent).digest('hex');
410
+ tx.stageWrite(`${relTargetDir}/skill.yaml`, yamlContent);
411
+ manifest['skill.yaml'] = yamlHash;
372
412
  }
373
413
 
374
- // Write a source marker so we know where to update from
375
- fs.writeFileSync(path.join(targetDir, '.source'), JSON.stringify({
414
+ // Write a source marker with manifest
415
+ const sourceContent = JSON.stringify({
376
416
  type: 'github',
377
417
  owner,
378
418
  repo,
@@ -381,7 +421,9 @@ async function installFromGitHub(descriptor, skillName, dryRun, checksum, forceU
381
421
  ref: descriptor.raw,
382
422
  sha256,
383
423
  installedAt: new Date().toISOString(),
384
- }, null, 2));
424
+ manifest,
425
+ }, null, 2);
426
+ tx.stageWrite(`${relTargetDir}/.source`, sourceContent);
385
427
 
386
428
  console.log(c.green(` ✓ Installed SKILL.md (${skillMdContent.length} bytes, sha256: ${sha256.slice(0, 12)}...)`));
387
429
  if (yamlContent) console.log(c.green(` ✓ Installed skill.yaml`));
@@ -389,12 +431,15 @@ async function installFromGitHub(descriptor, skillName, dryRun, checksum, forceU
389
431
  }
390
432
 
391
433
  // ── npm installer ─────────────────────────────────────────────────────────────
392
- function installFromNpm(descriptor, skillName, dryRun, checksum, forceUnsafe = false) {
434
+ function installFromNpm(descriptor, skillName, dryRun, checksum, forceUnsafe = false, tx = null) {
393
435
  const pkgName = descriptor.package;
394
436
 
437
+ const targetDir = path.join(PLUGINS_DIR, skillName);
438
+ const relTargetDir = path.relative(ROOT, targetDir).replace(/\\/g, '/');
439
+
395
440
  if (dryRun) {
396
441
  console.log(c.yellow(` [DRY-RUN] Would run: npm install ${pkgName}`));
397
- console.log(c.yellow(` [DRY-RUN] Would copy skill to: ${path.join(PLUGINS_DIR, skillName)}`));
442
+ console.log(c.yellow(` [DRY-RUN] Would copy skill to: ${targetDir}`));
398
443
  return null;
399
444
  }
400
445
 
@@ -428,19 +473,39 @@ function installFromNpm(descriptor, skillName, dryRun, checksum, forceUnsafe = f
428
473
  // Deep security scan across all plugin files (EXAMPLES.md, TROUBLESHOOTING.md, references/, symlinks)
429
474
  scanPluginDirectory(skillSrc, { throwOnMatch: !forceUnsafe, forceUnsafe });
430
475
 
431
- const targetDir = path.join(PLUGINS_DIR, skillName);
432
- fs.rmSync(targetDir, { recursive: true, force: true });
433
- fs.mkdirSync(targetDir, { recursive: true });
434
- fs.cpSync(skillSrc, targetDir, { recursive: true, force: true });
476
+ const manifest = {};
477
+
478
+ // Helper to walk and stage all files
479
+ const stageRecursive = (dir, relBase) => {
480
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
481
+ if (entry.name === '.git' || entry.name === 'node_modules') continue;
482
+ const fullPath = path.join(dir, entry.name);
483
+ const entryRel = relBase ? `${relBase}/${entry.name}` : entry.name;
484
+
485
+ if (entry.isDirectory()) {
486
+ stageRecursive(fullPath, entryRel);
487
+ } else if (entry.isFile() || entry.isSymbolicLink()) {
488
+ // Read content to stage it
489
+ const content = fs.readFileSync(fullPath);
490
+ const hash = crypto.createHash('sha256').update(content).digest('hex');
491
+ tx.stageWrite(`${relTargetDir}/${entryRel}`, content);
492
+ manifest[entryRel] = hash;
493
+ }
494
+ }
495
+ };
496
+
497
+ stageRecursive(skillSrc, '');
435
498
 
436
499
  // Write source marker
437
- fs.writeFileSync(path.join(targetDir, '.source'), JSON.stringify({
500
+ const sourceContent = JSON.stringify({
438
501
  type: 'npm',
439
502
  package: pkgName,
440
503
  ref: descriptor.raw,
441
504
  sha256,
442
505
  installedAt: new Date().toISOString(),
443
- }, null, 2));
506
+ manifest,
507
+ }, null, 2);
508
+ tx.stageWrite(`${relTargetDir}/.source`, sourceContent);
444
509
  } finally {
445
510
  fs.rmSync(temporaryPrefix, { recursive: true, force: true });
446
511
  }
@@ -473,6 +538,8 @@ async function add(ref, options = {}) {
473
538
  const dryRun = Boolean(options.dryRun || options['dry-run']);
474
539
  const checksum = options.checksum || null;
475
540
  const forceUnsafe = Boolean(options.forceUnsafe || options['force-unsafe-prompts']);
541
+ const allowFloating = Boolean(options.allowFloating || options['allow-floating']);
542
+ const force = Boolean(options.force);
476
543
 
477
544
  if (!ref) {
478
545
  console.error(c.red('Usage: ctx.js skill add <ref> [--checksum <sha256>]'));
@@ -487,6 +554,27 @@ async function add(ref, options = {}) {
487
554
  throw new Error(`Invalid plugin name derived from reference: '${skillName}'`);
488
555
  }
489
556
 
557
+ // Supply-chain source pinning check (Wave 6)
558
+ if (!dryRun) {
559
+ const pinning = validatePluginPinning(
560
+ {
561
+ type: descriptor.type,
562
+ commit: descriptor.commit,
563
+ version: descriptor.version,
564
+ integrity: descriptor.integrity,
565
+ },
566
+ { allowFloating }
567
+ );
568
+
569
+ if (!pinning.valid) {
570
+ console.error(c.red(`\n[ERROR] Supply-chain pinning check failed: ${pinning.error}`));
571
+ if (pinning.code === THREAT_CODES.FLOATING_SOURCE_BLOCKED) {
572
+ console.error(c.yellow(' Pass --allow-floating to override this check with explicit user consent.'));
573
+ }
574
+ process.exit(1);
575
+ }
576
+ }
577
+
490
578
  console.log('');
491
579
  console.log(c.bold(`Installing skill: ${c.cyan(skillName)}`));
492
580
  console.log(c.dim(` Source: ${ref} (${descriptor.type})`));
@@ -503,45 +591,86 @@ async function add(ref, options = {}) {
503
591
  // Check if already installed
504
592
  const lock = readLock();
505
593
  const existing = lock.plugins.find(p => p.name === skillName);
594
+ const targetDir = path.join(PLUGINS_DIR, skillName);
595
+
506
596
  if (existing && !dryRun) {
597
+ // Check for local modifications (Wave 6 / Section 20.7)
598
+ if (fs.existsSync(targetDir) && existing.treeDigest && !force) {
599
+ if (AtomicPluginUpdater.isModifiedLocally(targetDir, existing.treeDigest)) {
600
+ const conflictFile = path.join(targetDir, 'CONFLICT_LOCAL_MODIFICATIONS.md');
601
+ fs.writeFileSync(
602
+ conflictFile,
603
+ `# Conflict: Local Modifications Detected\n\nPlugin "${skillName}" contains local uncommitted modifications.\nAutomatic update was blocked to preserve your changes.\n\nTo overwrite local modifications, re-run with --force.\n`,
604
+ 'utf8'
605
+ );
606
+ console.error(c.red(`\n[ERROR] Plugin in "${targetDir}" has local modifications.`));
607
+ console.error(c.red(` Update blocked to prevent overwriting user changes.`));
608
+ console.error(c.yellow(` Conflict artifact written to: ${conflictFile}`));
609
+ console.error(c.yellow(` Pass --force to overwrite.`));
610
+ process.exit(1);
611
+ }
612
+ }
507
613
  console.log(c.yellow(`\n[WARN] '${skillName}' is already installed (from: ${existing.ref})`));
508
614
  console.log(c.yellow(' Re-installing will overwrite it. Continuing...'));
509
615
  }
510
616
 
511
- let installedSha256 = null;
617
+ const projectLock = new ProjectMutationLock(ROOT);
618
+ const tx = new JournaledTransaction(ROOT);
619
+ let lockToken = null;
620
+
512
621
  try {
622
+ lockToken = projectLock.acquire({ command: 'skill:add' });
623
+
624
+ let installedSha256 = null;
513
625
  if (descriptor.type === 'github') {
514
- installedSha256 = await installFromGitHub(descriptor, skillName, dryRun, checksum, forceUnsafe);
626
+ installedSha256 = await installFromGitHub(descriptor, skillName, dryRun, checksum, forceUnsafe, tx);
515
627
  } else {
516
- installedSha256 = installFromNpm(descriptor, skillName, dryRun, checksum, forceUnsafe);
628
+ installedSha256 = installFromNpm(descriptor, skillName, dryRun, checksum, forceUnsafe, tx);
629
+ }
630
+
631
+ if (!dryRun) {
632
+ // Update lock file
633
+ const idx = lock.plugins.findIndex(p => p.name === skillName);
634
+ const entry = {
635
+ name: skillName,
636
+ ref,
637
+ type: descriptor.type,
638
+ commit: descriptor.commit,
639
+ version: descriptor.version,
640
+ integrity: descriptor.integrity,
641
+ sha256: installedSha256,
642
+ installedAt: new Date().toISOString(),
643
+ };
644
+ if (idx >= 0) lock.plugins[idx] = entry;
645
+ else lock.plugins.push(entry);
646
+
647
+ writeLock(lock, tx);
648
+ tx.commit();
649
+
650
+ // Compute and record full-tree digest into lock
651
+ if (fs.existsSync(targetDir)) {
652
+ const digestResult = calculateTreeDigest(targetDir);
653
+ entry.treeDigest = digestResult.treeDigest;
654
+ writeLock(lock);
655
+ }
656
+
657
+ console.log('');
658
+ console.log(c.green(c.bold('✓ Skill installed successfully!')));
659
+ console.log(c.dim(` Location: .agents/plugins/${skillName}/`));
660
+ console.log('');
661
+ console.log(' Next steps:');
662
+ console.log(` node .agents/ctx.js export all # recompile with new skill`);
663
+ console.log(` node .agents/ctx.js validate # verify everything is consistent`);
664
+ console.log('');
517
665
  }
518
666
  } catch (err) {
667
+ if (tx && tx.state === 'PLANNED') {
668
+ // We don't need to do anything since it wasn't committed
669
+ }
519
670
  console.error(c.red(`\n[ERROR] Failed to install '${skillName}': ${err.message}`));
520
671
  process.exit(1);
521
- }
522
-
523
- if (!dryRun) {
524
- // Update lock file
525
- const idx = lock.plugins.findIndex(p => p.name === skillName);
526
- const entry = {
527
- name: skillName,
528
- ref,
529
- type: descriptor.type,
530
- sha256: installedSha256,
531
- installedAt: new Date().toISOString(),
532
- };
533
- if (idx >= 0) lock.plugins[idx] = entry;
534
- else lock.plugins.push(entry);
535
- writeLock(lock);
536
-
537
- console.log('');
538
- console.log(c.green(c.bold('✓ Skill installed successfully!')));
539
- console.log(c.dim(` Location: .agents/plugins/${skillName}/`));
540
- console.log('');
541
- console.log(' Next steps:');
542
- console.log(` node .agents/ctx.js export all # recompile with new skill`);
543
- console.log(` node .agents/ctx.js validate # verify everything is consistent`);
544
- console.log('');
672
+ } finally {
673
+ if (lockToken) projectLock.release(lockToken);
545
674
  }
546
675
  }
547
676
 
@@ -576,15 +705,85 @@ function remove(skillName) {
576
705
  process.exit(1);
577
706
  }
578
707
 
579
- if (fs.existsSync(skillDir)) {
580
- fs.rmSync(skillDir, { recursive: true, force: true });
581
- }
708
+ const projectLock = new ProjectMutationLock(ROOT);
709
+ const tx = new JournaledTransaction(ROOT);
710
+ let lockToken = null;
711
+
712
+ try {
713
+ lockToken = projectLock.acquire({ command: 'skill:remove' });
714
+
715
+ if (fs.existsSync(skillDir)) {
716
+ // Find the manifest if it exists
717
+ const sourceFile = path.join(skillDir, '.source');
718
+ let manifest = null;
719
+ if (fs.existsSync(sourceFile)) {
720
+ try {
721
+ const sourceData = JSON.parse(fs.readFileSync(sourceFile, 'utf8'));
722
+ manifest = sourceData.manifest || null;
723
+ } catch {}
724
+ }
725
+
726
+ const stageRecursiveDeletes = (dir, relBase) => {
727
+ let hasPreservedFiles = false;
728
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
729
+ const fullPath = path.join(dir, entry.name);
730
+ const entryRel = relBase ? `${relBase}/${entry.name}` : entry.name;
731
+
732
+ if (entry.isDirectory()) {
733
+ const preserved = stageRecursiveDeletes(fullPath, entryRel);
734
+ if (preserved) hasPreservedFiles = true;
735
+ else tx.stageDeleteDir(toPosix(path.relative(ROOT, fullPath)));
736
+ } else {
737
+ // Check against manifest
738
+ let shouldDelete = false;
739
+ if (manifest && manifest[entryRel]) {
740
+ const currentHash = crypto.createHash('sha256').update(fs.readFileSync(fullPath)).digest('hex');
741
+ if (currentHash === manifest[entryRel]) {
742
+ shouldDelete = true;
743
+ }
744
+ } else if (!manifest) {
745
+ // If we have NO manifest, we fallback to W3.4 "Remove не удаляет modified/unmanaged files"
746
+ // But without a manifest, we don't know what was installed vs modified.
747
+ // We'll safely skip all files unless we can confidently delete them, OR we can just assume
748
+ // if it's the exact SHA256 of SKILL.md, delete it. But it's safer to only delete known things.
749
+ // We'll just delete SKILL.md and skill.yaml if they match the lockfile hash
750
+ if (entry.name === 'SKILL.md' || entry.name === 'skill.yaml' || entry.name === '.source') {
751
+ shouldDelete = true;
752
+ }
753
+ }
754
+
755
+ if (entry.name === '.source') shouldDelete = true;
756
+
757
+ if (shouldDelete) {
758
+ tx.stageDelete(toPosix(path.relative(ROOT, fullPath)));
759
+ } else {
760
+ hasPreservedFiles = true;
761
+ console.log(c.yellow(` [WARN] Preserving modified/unmanaged file: ${entryRel}`));
762
+ }
763
+ }
764
+ }
765
+ return hasPreservedFiles;
766
+ };
767
+
768
+ const preserved = stageRecursiveDeletes(skillDir, '');
769
+ if (!preserved) {
770
+ tx.stageDeleteDir(toPosix(path.relative(ROOT, skillDir)));
771
+ }
772
+ }
582
773
 
583
- lock.plugins = lock.plugins.filter(p => p.name !== skillName);
584
- writeLock(lock);
774
+ lock.plugins = lock.plugins.filter(p => p.name !== skillName);
775
+ writeLock(lock, tx);
776
+
777
+ tx.commit();
585
778
 
586
- console.log(c.green(`✓ Removed plugin: ${skillName}`));
587
- console.log(c.dim(' Run: node .agents/ctx.js export all (to recompile)'));
779
+ console.log(c.green(`✓ Removed plugin: ${skillName}`));
780
+ console.log(c.dim(' Run: node .agents/ctx.js export all (to recompile)'));
781
+ } catch (err) {
782
+ console.error(c.red(`\n[ERROR] Failed to remove '${skillName}': ${err.message}`));
783
+ process.exit(1);
784
+ } finally {
785
+ if (lockToken) projectLock.release(lockToken);
786
+ }
588
787
  }
589
788
 
590
789
  /**