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
@@ -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();
@@ -51,12 +62,10 @@ const c = {
51
62
  const PROMPT_INJECTION_PATTERNS = [
52
63
  /ignore\s+(all\s+)?previous\s+instructions/i,
53
64
  /forget\s+(all\s+)?previous/i,
54
- /you\s+are\s+now/i,
55
- /system\s*:\s*/i,
65
+ /you\s+are\s+now\s+(?:an?\s+)?(?:unrestricted|jailbreak|evil|dan|developer\s+mode|bypassed)/i,
56
66
  /\[SYSTEM\]/i,
57
- /base64\s*,\s*[A-Za-z0-9+/=]{40,}/i,
58
- /https?:\/\/[^\s)]+\/(?:exfil|steal|leak|webhook|collect)/i,
59
- /\b(?:eval|exec|Function)\s*\(/i,
67
+ /(?:^|[\r\n])\s*system\s*:\s*/i,
68
+ /https?:\/\/[^\s)]+\/(?:exfil|steal|leak|webhook|collect)\b/i,
60
69
  ];
61
70
 
62
71
  // ── Shell Escapes & Script Injection Scanner ──────────────────────────────────
@@ -214,9 +223,19 @@ function readLock() {
214
223
  }
215
224
  }
216
225
 
217
- function writeLock(lock) {
218
- fs.mkdirSync(AGENTS_DIR, { recursive: true });
219
- fs.writeFileSync(PLUGINS_JSON, JSON.stringify(lock, null, 2) + '\n');
226
+ function writeLock(lock, tx = null) {
227
+ if (tx) {
228
+ const relLockPath = toPosix(path.relative(ROOT, PLUGINS_JSON));
229
+ tx.stageWrite(relLockPath, JSON.stringify(lock, null, 2) + '\n');
230
+ } else {
231
+ fs.mkdirSync(AGENTS_DIR, { recursive: true });
232
+ fs.writeFileSync(PLUGINS_JSON, JSON.stringify(lock, null, 2) + '\n');
233
+ }
234
+ }
235
+
236
+ // POSIX path helper
237
+ function toPosix(p) {
238
+ return p.replace(/\\/g, '/');
220
239
  }
221
240
 
222
241
  // ── HTTP fetch helper (no deps) ───────────────────────────────────────────────
@@ -293,7 +312,17 @@ function parseRef(ref) {
293
312
  throw new Error('Invalid GitHub plugin reference');
294
313
  }
295
314
 
296
- return { type: 'github', owner, repo, gitRef, isPinned: repoRef.includes('@'), subPath, raw: ref };
315
+ const isPinned = repoRef.includes('@');
316
+ return {
317
+ type: 'github',
318
+ owner,
319
+ repo,
320
+ gitRef,
321
+ commit: isPinned ? gitRef : undefined,
322
+ isPinned,
323
+ subPath,
324
+ raw: ref,
325
+ };
297
326
  }
298
327
  // npm package
299
328
  if (!isValidNpmPackage(ref)) {
@@ -303,7 +332,7 @@ function parseRef(ref) {
303
332
  }
304
333
 
305
334
  // ── GitHub installer ──────────────────────────────────────────────────────────
306
- async function installFromGitHub(descriptor, skillName, dryRun, checksum, forceUnsafe = false) {
335
+ async function installFromGitHub(descriptor, skillName, dryRun, checksum, forceUnsafe = false, tx = null) {
307
336
  const { owner, repo, gitRef, isPinned, subPath } = descriptor;
308
337
  const skillPath = subPath || '';
309
338
  const base = `https://raw.githubusercontent.com/${owner}/${repo}/${gitRef}`;
@@ -350,6 +379,7 @@ async function installFromGitHub(descriptor, skillName, dryRun, checksum, forceU
350
379
  }
351
380
 
352
381
  const targetDir = path.join(PLUGINS_DIR, skillName);
382
+ const relTargetDir = path.relative(ROOT, targetDir).replace(/\\/g, '/');
353
383
 
354
384
  if (dryRun) {
355
385
  console.log(c.yellow(` [DRY-RUN] Would install to: ${targetDir}`));
@@ -357,22 +387,47 @@ async function installFromGitHub(descriptor, skillName, dryRun, checksum, forceU
357
387
  return sha256;
358
388
  }
359
389
 
360
- fs.mkdirSync(targetDir, { recursive: true });
361
- fs.writeFileSync(path.join(targetDir, 'SKILL.md'), skillMdContent);
390
+ // Pre-scan using temp dir to keep `scanPluginDirectory` happy, as it reads from disk
391
+ const temporaryPrefix = fs.mkdtempSync(path.join(os.tmpdir(), 'contextos-github-'));
392
+ try {
393
+ fs.writeFileSync(path.join(temporaryPrefix, 'SKILL.md'), skillMdContent);
394
+ if (yamlContent) fs.writeFileSync(path.join(temporaryPrefix, 'skill.yaml'), yamlContent);
395
+ scanPluginDirectory(temporaryPrefix, { throwOnMatch: !forceUnsafe, forceUnsafe });
396
+ } finally {
397
+ fs.rmSync(temporaryPrefix, { recursive: true, force: true });
398
+ }
399
+
400
+ const manifest = {};
401
+
402
+ const skillMdHash = crypto.createHash('sha256').update(skillMdContent).digest('hex');
403
+ tx.stageWrite(`${relTargetDir}/SKILL.md`, skillMdContent);
404
+ manifest['SKILL.md'] = skillMdHash;
405
+
362
406
  if (yamlContent) {
363
- fs.writeFileSync(path.join(targetDir, 'skill.yaml'), yamlContent);
407
+ const yamlHash = crypto.createHash('sha256').update(yamlContent).digest('hex');
408
+ tx.stageWrite(`${relTargetDir}/skill.yaml`, yamlContent);
409
+ manifest['skill.yaml'] = yamlHash;
364
410
  }
365
411
 
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;
412
+ // Also try to fetch standard ancillary files if present
413
+ const ancillaryFiles = ['EXAMPLES.md', 'TROUBLESHOOTING.md', 'VALIDATION.json'];
414
+ for (const f of ancillaryFiles) {
415
+ const fUrl = skillPath ? `${base}/${skillPath}/${f}` : `${base}/${f}`;
416
+ try {
417
+ const fContent = await fetchText(fUrl);
418
+ if (fContent && fContent.length > 0) {
419
+ scanForPromptInjection(fContent, { throwOnMatch: !forceUnsafe });
420
+ const fHash = crypto.createHash('sha256').update(fContent).digest('hex');
421
+ tx.stageWrite(`${relTargetDir}/${f}`, fContent);
422
+ manifest[f] = fHash;
423
+ }
424
+ } catch {
425
+ // Ancillary files are optional
426
+ }
372
427
  }
373
428
 
374
- // Write a source marker so we know where to update from
375
- fs.writeFileSync(path.join(targetDir, '.source'), JSON.stringify({
429
+ // Write a source marker with manifest
430
+ const sourceContent = JSON.stringify({
376
431
  type: 'github',
377
432
  owner,
378
433
  repo,
@@ -381,7 +436,9 @@ async function installFromGitHub(descriptor, skillName, dryRun, checksum, forceU
381
436
  ref: descriptor.raw,
382
437
  sha256,
383
438
  installedAt: new Date().toISOString(),
384
- }, null, 2));
439
+ manifest,
440
+ }, null, 2);
441
+ tx.stageWrite(`${relTargetDir}/.source`, sourceContent);
385
442
 
386
443
  console.log(c.green(` ✓ Installed SKILL.md (${skillMdContent.length} bytes, sha256: ${sha256.slice(0, 12)}...)`));
387
444
  if (yamlContent) console.log(c.green(` ✓ Installed skill.yaml`));
@@ -389,12 +446,15 @@ async function installFromGitHub(descriptor, skillName, dryRun, checksum, forceU
389
446
  }
390
447
 
391
448
  // ── npm installer ─────────────────────────────────────────────────────────────
392
- function installFromNpm(descriptor, skillName, dryRun, checksum, forceUnsafe = false) {
449
+ function installFromNpm(descriptor, skillName, dryRun, checksum, forceUnsafe = false, tx = null) {
393
450
  const pkgName = descriptor.package;
394
451
 
452
+ const targetDir = path.join(PLUGINS_DIR, skillName);
453
+ const relTargetDir = path.relative(ROOT, targetDir).replace(/\\/g, '/');
454
+
395
455
  if (dryRun) {
396
456
  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)}`));
457
+ console.log(c.yellow(` [DRY-RUN] Would copy skill to: ${targetDir}`));
398
458
  return null;
399
459
  }
400
460
 
@@ -428,19 +488,39 @@ function installFromNpm(descriptor, skillName, dryRun, checksum, forceUnsafe = f
428
488
  // Deep security scan across all plugin files (EXAMPLES.md, TROUBLESHOOTING.md, references/, symlinks)
429
489
  scanPluginDirectory(skillSrc, { throwOnMatch: !forceUnsafe, forceUnsafe });
430
490
 
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 });
491
+ const manifest = {};
492
+
493
+ // Helper to walk and stage all files
494
+ const stageRecursive = (dir, relBase) => {
495
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
496
+ if (entry.name === '.git' || entry.name === 'node_modules') continue;
497
+ const fullPath = path.join(dir, entry.name);
498
+ const entryRel = relBase ? `${relBase}/${entry.name}` : entry.name;
499
+
500
+ if (entry.isDirectory()) {
501
+ stageRecursive(fullPath, entryRel);
502
+ } else if (entry.isFile() || entry.isSymbolicLink()) {
503
+ // Read content to stage it
504
+ const content = fs.readFileSync(fullPath);
505
+ const hash = crypto.createHash('sha256').update(content).digest('hex');
506
+ tx.stageWrite(`${relTargetDir}/${entryRel}`, content);
507
+ manifest[entryRel] = hash;
508
+ }
509
+ }
510
+ };
511
+
512
+ stageRecursive(skillSrc, '');
435
513
 
436
514
  // Write source marker
437
- fs.writeFileSync(path.join(targetDir, '.source'), JSON.stringify({
515
+ const sourceContent = JSON.stringify({
438
516
  type: 'npm',
439
517
  package: pkgName,
440
518
  ref: descriptor.raw,
441
519
  sha256,
442
520
  installedAt: new Date().toISOString(),
443
- }, null, 2));
521
+ manifest,
522
+ }, null, 2);
523
+ tx.stageWrite(`${relTargetDir}/.source`, sourceContent);
444
524
  } finally {
445
525
  fs.rmSync(temporaryPrefix, { recursive: true, force: true });
446
526
  }
@@ -473,6 +553,8 @@ async function add(ref, options = {}) {
473
553
  const dryRun = Boolean(options.dryRun || options['dry-run']);
474
554
  const checksum = options.checksum || null;
475
555
  const forceUnsafe = Boolean(options.forceUnsafe || options['force-unsafe-prompts']);
556
+ const allowFloating = Boolean(options.allowFloating || options['allow-floating']);
557
+ const force = Boolean(options.force);
476
558
 
477
559
  if (!ref) {
478
560
  console.error(c.red('Usage: ctx.js skill add <ref> [--checksum <sha256>]'));
@@ -487,6 +569,27 @@ async function add(ref, options = {}) {
487
569
  throw new Error(`Invalid plugin name derived from reference: '${skillName}'`);
488
570
  }
489
571
 
572
+ // Supply-chain source pinning check (Wave 6)
573
+ if (!dryRun) {
574
+ const pinning = validatePluginPinning(
575
+ {
576
+ type: descriptor.type,
577
+ commit: descriptor.commit,
578
+ version: descriptor.version,
579
+ integrity: descriptor.integrity,
580
+ },
581
+ { allowFloating }
582
+ );
583
+
584
+ if (!pinning.valid) {
585
+ console.error(c.red(`\n[ERROR] Supply-chain pinning check failed: ${pinning.error}`));
586
+ if (pinning.code === THREAT_CODES.FLOATING_SOURCE_BLOCKED) {
587
+ console.error(c.yellow(' Pass --allow-floating to override this check with explicit user consent.'));
588
+ }
589
+ process.exit(1);
590
+ }
591
+ }
592
+
490
593
  console.log('');
491
594
  console.log(c.bold(`Installing skill: ${c.cyan(skillName)}`));
492
595
  console.log(c.dim(` Source: ${ref} (${descriptor.type})`));
@@ -503,45 +606,86 @@ async function add(ref, options = {}) {
503
606
  // Check if already installed
504
607
  const lock = readLock();
505
608
  const existing = lock.plugins.find(p => p.name === skillName);
609
+ const targetDir = path.join(PLUGINS_DIR, skillName);
610
+
506
611
  if (existing && !dryRun) {
612
+ // Check for local modifications (Wave 6 / Section 20.7)
613
+ if (fs.existsSync(targetDir) && existing.treeDigest && !force) {
614
+ if (AtomicPluginUpdater.isModifiedLocally(targetDir, existing.treeDigest)) {
615
+ const conflictFile = path.join(targetDir, 'CONFLICT_LOCAL_MODIFICATIONS.md');
616
+ fs.writeFileSync(
617
+ conflictFile,
618
+ `# 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`,
619
+ 'utf8'
620
+ );
621
+ console.error(c.red(`\n[ERROR] Plugin in "${targetDir}" has local modifications.`));
622
+ console.error(c.red(` Update blocked to prevent overwriting user changes.`));
623
+ console.error(c.yellow(` Conflict artifact written to: ${conflictFile}`));
624
+ console.error(c.yellow(` Pass --force to overwrite.`));
625
+ process.exit(1);
626
+ }
627
+ }
507
628
  console.log(c.yellow(`\n[WARN] '${skillName}' is already installed (from: ${existing.ref})`));
508
629
  console.log(c.yellow(' Re-installing will overwrite it. Continuing...'));
509
630
  }
510
631
 
511
- let installedSha256 = null;
632
+ const projectLock = new ProjectMutationLock(ROOT);
633
+ const tx = new JournaledTransaction(ROOT);
634
+ let lockToken = null;
635
+
512
636
  try {
637
+ lockToken = projectLock.acquire({ command: 'skill:add' });
638
+
639
+ let installedSha256 = null;
513
640
  if (descriptor.type === 'github') {
514
- installedSha256 = await installFromGitHub(descriptor, skillName, dryRun, checksum, forceUnsafe);
641
+ installedSha256 = await installFromGitHub(descriptor, skillName, dryRun, checksum, forceUnsafe, tx);
515
642
  } else {
516
- installedSha256 = installFromNpm(descriptor, skillName, dryRun, checksum, forceUnsafe);
643
+ installedSha256 = installFromNpm(descriptor, skillName, dryRun, checksum, forceUnsafe, tx);
644
+ }
645
+
646
+ if (!dryRun) {
647
+ // Update lock file
648
+ const idx = lock.plugins.findIndex(p => p.name === skillName);
649
+ const entry = {
650
+ name: skillName,
651
+ ref,
652
+ type: descriptor.type,
653
+ commit: descriptor.commit,
654
+ version: descriptor.version,
655
+ integrity: descriptor.integrity,
656
+ sha256: installedSha256,
657
+ installedAt: new Date().toISOString(),
658
+ };
659
+ if (idx >= 0) lock.plugins[idx] = entry;
660
+ else lock.plugins.push(entry);
661
+
662
+ writeLock(lock, tx);
663
+ tx.commit();
664
+
665
+ // Compute and record full-tree digest into lock
666
+ if (fs.existsSync(targetDir)) {
667
+ const digestResult = calculateTreeDigest(targetDir);
668
+ entry.treeDigest = digestResult.treeDigest;
669
+ writeLock(lock);
670
+ }
671
+
672
+ console.log('');
673
+ console.log(c.green(c.bold('✓ Skill installed successfully!')));
674
+ console.log(c.dim(` Location: .agents/plugins/${skillName}/`));
675
+ console.log('');
676
+ console.log(' Next steps:');
677
+ console.log(` node .agents/ctx.js export all # recompile with new skill`);
678
+ console.log(` node .agents/ctx.js validate # verify everything is consistent`);
679
+ console.log('');
517
680
  }
518
681
  } catch (err) {
682
+ if (tx && tx.state === 'PLANNED') {
683
+ // We don't need to do anything since it wasn't committed
684
+ }
519
685
  console.error(c.red(`\n[ERROR] Failed to install '${skillName}': ${err.message}`));
520
686
  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('');
687
+ } finally {
688
+ if (lockToken) projectLock.release(lockToken);
545
689
  }
546
690
  }
547
691
 
@@ -576,15 +720,85 @@ function remove(skillName) {
576
720
  process.exit(1);
577
721
  }
578
722
 
579
- if (fs.existsSync(skillDir)) {
580
- fs.rmSync(skillDir, { recursive: true, force: true });
581
- }
723
+ const projectLock = new ProjectMutationLock(ROOT);
724
+ const tx = new JournaledTransaction(ROOT);
725
+ let lockToken = null;
726
+
727
+ try {
728
+ lockToken = projectLock.acquire({ command: 'skill:remove' });
582
729
 
583
- lock.plugins = lock.plugins.filter(p => p.name !== skillName);
584
- writeLock(lock);
730
+ if (fs.existsSync(skillDir)) {
731
+ // Find the manifest if it exists
732
+ const sourceFile = path.join(skillDir, '.source');
733
+ let manifest = null;
734
+ if (fs.existsSync(sourceFile)) {
735
+ try {
736
+ const sourceData = JSON.parse(fs.readFileSync(sourceFile, 'utf8'));
737
+ manifest = sourceData.manifest || null;
738
+ } catch {}
739
+ }
740
+
741
+ const stageRecursiveDeletes = (dir, relBase) => {
742
+ let hasPreservedFiles = false;
743
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
744
+ const fullPath = path.join(dir, entry.name);
745
+ const entryRel = relBase ? `${relBase}/${entry.name}` : entry.name;
746
+
747
+ if (entry.isDirectory()) {
748
+ const preserved = stageRecursiveDeletes(fullPath, entryRel);
749
+ if (preserved) hasPreservedFiles = true;
750
+ else tx.stageDeleteDir(toPosix(path.relative(ROOT, fullPath)));
751
+ } else {
752
+ // Check against manifest
753
+ let shouldDelete = false;
754
+ if (manifest && manifest[entryRel]) {
755
+ const currentHash = crypto.createHash('sha256').update(fs.readFileSync(fullPath)).digest('hex');
756
+ if (currentHash === manifest[entryRel]) {
757
+ shouldDelete = true;
758
+ }
759
+ } else if (!manifest) {
760
+ // If we have NO manifest, we fallback to W3.4 "Remove не удаляет modified/unmanaged files"
761
+ // But without a manifest, we don't know what was installed vs modified.
762
+ // We'll safely skip all files unless we can confidently delete them, OR we can just assume
763
+ // if it's the exact SHA256 of SKILL.md, delete it. But it's safer to only delete known things.
764
+ // We'll just delete SKILL.md and skill.yaml if they match the lockfile hash
765
+ if (entry.name === 'SKILL.md' || entry.name === 'skill.yaml' || entry.name === '.source') {
766
+ shouldDelete = true;
767
+ }
768
+ }
769
+
770
+ if (entry.name === '.source') shouldDelete = true;
771
+
772
+ if (shouldDelete) {
773
+ tx.stageDelete(toPosix(path.relative(ROOT, fullPath)));
774
+ } else {
775
+ hasPreservedFiles = true;
776
+ console.log(c.yellow(` [WARN] Preserving modified/unmanaged file: ${entryRel}`));
777
+ }
778
+ }
779
+ }
780
+ return hasPreservedFiles;
781
+ };
585
782
 
586
- console.log(c.green(`✓ Removed plugin: ${skillName}`));
587
- console.log(c.dim(' Run: node .agents/ctx.js export all (to recompile)'));
783
+ const preserved = stageRecursiveDeletes(skillDir, '');
784
+ if (!preserved) {
785
+ tx.stageDeleteDir(toPosix(path.relative(ROOT, skillDir)));
786
+ }
787
+ }
788
+
789
+ lock.plugins = lock.plugins.filter(p => p.name !== skillName);
790
+ writeLock(lock, tx);
791
+
792
+ tx.commit();
793
+
794
+ console.log(c.green(`✓ Removed plugin: ${skillName}`));
795
+ console.log(c.dim(' Run: node .agents/ctx.js export all (to recompile)'));
796
+ } catch (err) {
797
+ console.error(c.red(`\n[ERROR] Failed to remove '${skillName}': ${err.message}`));
798
+ process.exit(1);
799
+ } finally {
800
+ if (lockToken) projectLock.release(lockToken);
801
+ }
588
802
  }
589
803
 
590
804
  /**