release-skill 0.9.16 → 0.9.18

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 (356) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codebuddy-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +2 -2
  4. package/.cursor-plugin/plugin.json +10 -0
  5. package/.kimi-plugin/plugin.json +1 -1
  6. package/.qoder-plugin/plugin.json +10 -0
  7. package/CHANGELOG.md +64 -0
  8. package/INSTALL.md +104 -9
  9. package/INSTALL.zh-CN.md +78 -7
  10. package/README.md +87 -32
  11. package/README.zh-CN.md +71 -30
  12. package/adapters/claude/.claude-plugin/plugin.json +1 -1
  13. package/adapters/claude/bin/consumer-contract-vectors.json +7 -7
  14. package/adapters/claude/bin/error-codes.json +1 -1
  15. package/adapters/claude/bin/foundation-resource-binding.json +1 -1
  16. package/adapters/claude/bin/prebuild-manifest.json +8 -4
  17. package/adapters/claude/bin/prebuilds/darwin-arm64/bound_read.darwin-arm64.node +0 -0
  18. package/adapters/claude/bin/prebuilds/darwin-x64/bound_read.darwin-x64.node +0 -0
  19. package/adapters/claude/bin/prebuilds/linux-arm64-gnu/bound_read.linux-arm64-gnu.node +0 -0
  20. package/adapters/claude/bin/prebuilds/linux-x64-gnu/bound_read.linux-x64-gnu.node +0 -0
  21. package/adapters/claude/bin/registry.json +1 -1
  22. package/adapters/claude/bin/release-skill.bundle.mjs +4950 -1819
  23. package/adapters/claude/bin/rules.json +1 -1
  24. package/adapters/claude/data/hosts/cursor/host-descriptor.json +34 -0
  25. package/adapters/claude/data/hosts/registry.json +1 -0
  26. package/adapters/claude/schemas/release-plan.schema.json +255 -25
  27. package/adapters/claude/schemas/release-project.schema.json +228 -26
  28. package/adapters/claude/skills/release-finish/SKILL.md +29 -15
  29. package/adapters/claude/skills/release-help/SKILL.md +40 -39
  30. package/adapters/claude/skills/release-verify/SKILL.md +2 -2
  31. package/adapters/claude/src/schemas/host-descriptor.schema.json +9 -2
  32. package/adapters/codex/.codex-plugin/plugin.json +2 -2
  33. package/adapters/codex/bin/consumer-contract-vectors.json +7 -7
  34. package/adapters/codex/bin/error-codes.json +1 -1
  35. package/adapters/codex/bin/foundation-resource-binding.json +1 -1
  36. package/adapters/codex/bin/prebuild-manifest.json +8 -4
  37. package/adapters/codex/bin/prebuilds/darwin-arm64/bound_read.darwin-arm64.node +0 -0
  38. package/adapters/codex/bin/prebuilds/darwin-x64/bound_read.darwin-x64.node +0 -0
  39. package/adapters/codex/bin/prebuilds/linux-arm64-gnu/bound_read.linux-arm64-gnu.node +0 -0
  40. package/adapters/codex/bin/prebuilds/linux-x64-gnu/bound_read.linux-x64-gnu.node +0 -0
  41. package/adapters/codex/bin/registry.json +1 -1
  42. package/adapters/codex/bin/release-skill.bundle.mjs +4950 -1819
  43. package/adapters/codex/bin/rules.json +1 -1
  44. package/adapters/codex/data/hosts/cursor/host-descriptor.json +34 -0
  45. package/adapters/codex/data/hosts/registry.json +1 -0
  46. package/adapters/codex/schemas/release-plan.schema.json +255 -25
  47. package/adapters/codex/schemas/release-project.schema.json +228 -26
  48. package/adapters/codex/skills/release-finish/SKILL.md +29 -15
  49. package/adapters/codex/skills/release-help/SKILL.md +40 -39
  50. package/adapters/codex/skills/release-verify/SKILL.md +2 -2
  51. package/adapters/codex/src/schemas/host-descriptor.schema.json +9 -2
  52. package/adapters/cursor/.cursor-plugin/plugin.json +10 -0
  53. package/adapters/cursor/bin/consumer-contract-vectors.json +110 -0
  54. package/adapters/cursor/bin/error-codes.json +161 -0
  55. package/adapters/cursor/bin/foundation-legal/skill-family-contracts/LICENSE +202 -0
  56. package/adapters/cursor/bin/foundation-legal/skill-family-contracts/NOTICE +10 -0
  57. package/adapters/cursor/bin/foundation-legal/skill-family-engineering-kit/LICENSE +202 -0
  58. package/adapters/cursor/bin/foundation-legal/skill-family-engineering-kit/NOTICE +10 -0
  59. package/adapters/cursor/bin/foundation-legal/skill-family-engineering-kit/THIRD_PARTY_NOTICES +142 -0
  60. package/adapters/cursor/bin/foundation-legal/skill-family-harness-node/LICENSE +202 -0
  61. package/adapters/cursor/bin/foundation-legal/skill-family-harness-node/NOTICE +10 -0
  62. package/adapters/cursor/bin/foundation-legal/skill-family-harness-node/native-NOTICE +2 -0
  63. package/adapters/cursor/bin/foundation-resource-binding.json +1 -0
  64. package/adapters/cursor/bin/kernel-protocol.json +60 -0
  65. package/adapters/cursor/bin/license-texts/Apache-2.0.txt +201 -0
  66. package/adapters/cursor/bin/license-texts/MIT.txt +21 -0
  67. package/adapters/cursor/bin/prebuild-manifest.json +83 -0
  68. package/adapters/cursor/bin/prebuilds/darwin-arm64/bound_read.darwin-arm64.node +0 -0
  69. package/adapters/cursor/bin/prebuilds/darwin-x64/bound_read.darwin-x64.node +0 -0
  70. package/adapters/cursor/bin/prebuilds/linux-arm64-gnu/bound_read.linux-arm64-gnu.node +0 -0
  71. package/adapters/cursor/bin/prebuilds/linux-x64-gnu/bound_read.linux-x64-gnu.node +0 -0
  72. package/adapters/cursor/bin/registry.json +347 -0
  73. package/adapters/cursor/bin/release-skill-local-finish.mjs +4 -0
  74. package/adapters/cursor/bin/release-skill.bundle.mjs +151806 -0
  75. package/adapters/cursor/bin/release-skill.mjs +54 -0
  76. package/adapters/cursor/bin/rules.json +104 -0
  77. package/adapters/cursor/bin/schemas/consumer-contract-vector.schema.json +149 -0
  78. package/adapters/cursor/data/hosts/claude/host-descriptor.json +45 -0
  79. package/adapters/cursor/data/hosts/codebuddy/host-descriptor.json +26 -0
  80. package/adapters/cursor/data/hosts/codex/host-descriptor.json +45 -0
  81. package/adapters/cursor/data/hosts/cursor/host-descriptor.json +34 -0
  82. package/adapters/cursor/data/hosts/deepseek-harness/host-descriptor.json +23 -0
  83. package/adapters/cursor/data/hosts/kimi-code/host-descriptor.json +36 -0
  84. package/adapters/cursor/data/hosts/qoder/host-descriptor.json +26 -0
  85. package/adapters/cursor/data/hosts/registry.json +14 -0
  86. package/adapters/cursor/data/hosts/workbuddy/host-descriptor.json +34 -0
  87. package/adapters/cursor/data/licensing/registry.json +211 -0
  88. package/adapters/cursor/data/licensing/schema.json +207 -0
  89. package/adapters/cursor/native/safe-write/binding.gyp +41 -0
  90. package/adapters/cursor/native/safe-write/prebuilds/darwin-arm64/safe_write.node +0 -0
  91. package/adapters/cursor/native/safe-write/prebuilds.json +24 -0
  92. package/adapters/cursor/native/safe-write/src/safe_write.cc +2032 -0
  93. package/adapters/cursor/schemas/.render-manifest.json +41 -0
  94. package/adapters/cursor/schemas/approval-record.schema.json +115 -0
  95. package/adapters/cursor/schemas/artifact-lock.schema.json +111 -0
  96. package/adapters/cursor/schemas/artifact-plan.schema.json +52 -0
  97. package/adapters/cursor/schemas/artifact-policy.schema.json +76 -0
  98. package/adapters/cursor/schemas/evidence-event-v2.schema.json +164 -0
  99. package/adapters/cursor/schemas/evidence-event.schema.json +89 -0
  100. package/adapters/cursor/schemas/postpublish-approval-record.schema.json +47 -0
  101. package/adapters/cursor/schemas/release-plan.schema.json +2226 -0
  102. package/adapters/cursor/schemas/release-project.schema.json +1815 -0
  103. package/adapters/cursor/schemas/release-run.schema.json +777 -0
  104. package/adapters/cursor/skills/release-assess/SKILL.md +61 -0
  105. package/adapters/cursor/skills/release-config/SKILL.md +151 -0
  106. package/adapters/cursor/skills/release-docs/SKILL.md +120 -0
  107. package/adapters/cursor/skills/release-finish/SKILL.md +155 -0
  108. package/adapters/cursor/skills/release-help/SKILL.md +155 -0
  109. package/adapters/cursor/skills/release-marketplace/SKILL.md +157 -0
  110. package/adapters/cursor/skills/release-prepare/SKILL.md +136 -0
  111. package/adapters/cursor/skills/release-publish/SKILL.md +92 -0
  112. package/adapters/cursor/skills/release-reconcile/SKILL.md +81 -0
  113. package/adapters/cursor/skills/release-setup/SKILL.md +132 -0
  114. package/adapters/cursor/skills/release-verify/SKILL.md +110 -0
  115. package/adapters/cursor/src/schemas/adapter-build-manifest.schema.json +41 -0
  116. package/adapters/cursor/src/schemas/adapter-peer-verification-request.schema.json +54 -0
  117. package/adapters/cursor/src/schemas/adapter-peer-verification-result.schema.json +54 -0
  118. package/adapters/cursor/src/schemas/adapter-source.schema.json +47 -0
  119. package/adapters/cursor/src/schemas/audit-baseline-pin.schema.json +163 -0
  120. package/adapters/cursor/src/schemas/declared-read-surface-result.schema.json +61 -0
  121. package/adapters/cursor/src/schemas/engineering-baseline.schema.json +77 -0
  122. package/adapters/cursor/src/schemas/executable-identity-observation.schema.json +162 -0
  123. package/adapters/cursor/src/schemas/filesystem-root-binding.schema.json +14 -0
  124. package/adapters/cursor/src/schemas/filesystem-tree-observation.schema.json +71 -0
  125. package/adapters/cursor/src/schemas/fixed-set-publication-manifest.schema.json +108 -0
  126. package/adapters/cursor/src/schemas/fixed-set-publication-receipt.schema.json +148 -0
  127. package/adapters/cursor/src/schemas/host-capability-fact.schema.json +31 -0
  128. package/adapters/cursor/src/schemas/host-descriptor.schema.json +144 -0
  129. package/adapters/cursor/src/schemas/host-operation-plan.schema.json +57 -0
  130. package/adapters/cursor/src/schemas/host-operation-receipt.schema.json +81 -0
  131. package/adapters/cursor/src/schemas/host-probe-result.schema.json +30 -0
  132. package/adapters/cursor/src/schemas/host-registry.schema.json +18 -0
  133. package/adapters/cursor/src/schemas/host-verification-request.schema.json +67 -0
  134. package/adapters/cursor/src/schemas/host-verification-result.schema.json +149 -0
  135. package/adapters/cursor/src/schemas/managed-file-lock.schema.json +77 -0
  136. package/adapters/cursor/src/schemas/migration-manifest.schema.json +412 -0
  137. package/adapters/cursor/src/schemas/observation-scope.schema.json +91 -0
  138. package/adapters/cursor/src/schemas/operation-request.schema.json +58 -0
  139. package/adapters/cursor/src/schemas/operation-result.schema.json +130 -0
  140. package/adapters/cursor/src/schemas/platform-difference-registry.schema.json +110 -0
  141. package/adapters/cursor/src/schemas/plugin-verification-request.schema.json +499 -0
  142. package/adapters/cursor/src/schemas/plugin-verification-result.schema.json +1217 -0
  143. package/adapters/cursor/src/schemas/profile-adoption-declaration.schema.json +111 -0
  144. package/adapters/cursor/src/schemas/profile-descriptor.schema.json +99 -0
  145. package/adapters/cursor/src/schemas/project-manifest.schema.json +67 -0
  146. package/adapters/cursor/src/schemas/project-profile.schema.json +25 -0
  147. package/adapters/cursor/src/schemas/public-boundary-declaration.schema.json +73 -0
  148. package/adapters/cursor/src/schemas/report-binding.schema.json +42 -0
  149. package/adapters/cursor/src/schemas/report-model.schema.json +308 -0
  150. package/adapters/cursor/src/schemas/skill-family-directory-verification-request.schema.json +100 -0
  151. package/adapters/cursor/src/schemas/skill-family-directory-verification-result.schema.json +193 -0
  152. package/adapters/cursor/src/schemas/source-authority-receipt.schema.json +31 -0
  153. package/adapters/cursor/src/schemas/state-event-envelope.schema.json +38 -0
  154. package/adapters/cursor/src/schemas/state-snapshot-metadata.schema.json +25 -0
  155. package/adapters/cursor/src/schemas/structured-scan-policy.schema.json +97 -0
  156. package/adapters/cursor/src/schemas/surface-scan-policy.schema.json +42 -0
  157. package/adapters/cursor/src/schemas/timeout-policy.schema.json +24 -0
  158. package/adapters/cursor/src/schemas/token-estimate-record.schema.json +75 -0
  159. package/adapters/cursor/src/schemas/token-estimate-result.schema.json +43 -0
  160. package/adapters/cursor/src/schemas/watchdog-termination-envelope.schema.json +156 -0
  161. package/adapters/kimi/.kimi-plugin/plugin.json +1 -1
  162. package/adapters/kimi/bin/consumer-contract-vectors.json +7 -7
  163. package/adapters/kimi/bin/error-codes.json +1 -1
  164. package/adapters/kimi/bin/foundation-resource-binding.json +1 -1
  165. package/adapters/kimi/bin/prebuild-manifest.json +8 -4
  166. package/adapters/kimi/bin/prebuilds/darwin-arm64/bound_read.darwin-arm64.node +0 -0
  167. package/adapters/kimi/bin/prebuilds/darwin-x64/bound_read.darwin-x64.node +0 -0
  168. package/adapters/kimi/bin/prebuilds/linux-arm64-gnu/bound_read.linux-arm64-gnu.node +0 -0
  169. package/adapters/kimi/bin/prebuilds/linux-x64-gnu/bound_read.linux-x64-gnu.node +0 -0
  170. package/adapters/kimi/bin/registry.json +1 -1
  171. package/adapters/kimi/bin/release-skill.bundle.mjs +4950 -1819
  172. package/adapters/kimi/bin/rules.json +1 -1
  173. package/adapters/kimi/data/hosts/cursor/host-descriptor.json +34 -0
  174. package/adapters/kimi/data/hosts/registry.json +1 -0
  175. package/adapters/kimi/schemas/release-plan.schema.json +255 -25
  176. package/adapters/kimi/schemas/release-project.schema.json +228 -26
  177. package/adapters/kimi/skills/release-finish/SKILL.md +29 -15
  178. package/adapters/kimi/skills/release-help/SKILL.md +40 -39
  179. package/adapters/kimi/skills/release-verify/SKILL.md +2 -2
  180. package/adapters/kimi/src/schemas/host-descriptor.schema.json +9 -2
  181. package/adapters/qoder/.qoder-plugin/plugin.json +10 -0
  182. package/adapters/qoder/bin/consumer-contract-vectors.json +110 -0
  183. package/adapters/qoder/bin/error-codes.json +161 -0
  184. package/adapters/qoder/bin/foundation-legal/skill-family-contracts/LICENSE +202 -0
  185. package/adapters/qoder/bin/foundation-legal/skill-family-contracts/NOTICE +10 -0
  186. package/adapters/qoder/bin/foundation-legal/skill-family-engineering-kit/LICENSE +202 -0
  187. package/adapters/qoder/bin/foundation-legal/skill-family-engineering-kit/NOTICE +10 -0
  188. package/adapters/qoder/bin/foundation-legal/skill-family-engineering-kit/THIRD_PARTY_NOTICES +142 -0
  189. package/adapters/qoder/bin/foundation-legal/skill-family-harness-node/LICENSE +202 -0
  190. package/adapters/qoder/bin/foundation-legal/skill-family-harness-node/NOTICE +10 -0
  191. package/adapters/qoder/bin/foundation-legal/skill-family-harness-node/native-NOTICE +2 -0
  192. package/adapters/qoder/bin/foundation-resource-binding.json +1 -0
  193. package/adapters/qoder/bin/kernel-protocol.json +60 -0
  194. package/adapters/qoder/bin/license-texts/Apache-2.0.txt +201 -0
  195. package/adapters/qoder/bin/license-texts/MIT.txt +21 -0
  196. package/adapters/qoder/bin/prebuild-manifest.json +83 -0
  197. package/adapters/qoder/bin/prebuilds/darwin-arm64/bound_read.darwin-arm64.node +0 -0
  198. package/adapters/qoder/bin/prebuilds/darwin-x64/bound_read.darwin-x64.node +0 -0
  199. package/adapters/qoder/bin/prebuilds/linux-arm64-gnu/bound_read.linux-arm64-gnu.node +0 -0
  200. package/adapters/qoder/bin/prebuilds/linux-x64-gnu/bound_read.linux-x64-gnu.node +0 -0
  201. package/adapters/qoder/bin/registry.json +347 -0
  202. package/adapters/qoder/bin/release-skill-local-finish.mjs +4 -0
  203. package/adapters/qoder/bin/release-skill.bundle.mjs +151806 -0
  204. package/adapters/qoder/bin/release-skill.mjs +54 -0
  205. package/adapters/qoder/bin/rules.json +104 -0
  206. package/adapters/qoder/bin/schemas/consumer-contract-vector.schema.json +149 -0
  207. package/adapters/qoder/data/hosts/claude/host-descriptor.json +45 -0
  208. package/adapters/qoder/data/hosts/codebuddy/host-descriptor.json +26 -0
  209. package/adapters/qoder/data/hosts/codex/host-descriptor.json +45 -0
  210. package/adapters/qoder/data/hosts/cursor/host-descriptor.json +34 -0
  211. package/adapters/qoder/data/hosts/deepseek-harness/host-descriptor.json +23 -0
  212. package/adapters/qoder/data/hosts/kimi-code/host-descriptor.json +36 -0
  213. package/adapters/qoder/data/hosts/qoder/host-descriptor.json +26 -0
  214. package/adapters/qoder/data/hosts/registry.json +14 -0
  215. package/adapters/qoder/data/hosts/workbuddy/host-descriptor.json +34 -0
  216. package/adapters/qoder/data/licensing/registry.json +211 -0
  217. package/adapters/qoder/data/licensing/schema.json +207 -0
  218. package/adapters/qoder/native/safe-write/binding.gyp +41 -0
  219. package/adapters/qoder/native/safe-write/prebuilds/darwin-arm64/safe_write.node +0 -0
  220. package/adapters/qoder/native/safe-write/prebuilds.json +24 -0
  221. package/adapters/qoder/native/safe-write/src/safe_write.cc +2032 -0
  222. package/adapters/qoder/schemas/.render-manifest.json +41 -0
  223. package/adapters/qoder/schemas/approval-record.schema.json +115 -0
  224. package/adapters/qoder/schemas/artifact-lock.schema.json +111 -0
  225. package/adapters/qoder/schemas/artifact-plan.schema.json +52 -0
  226. package/adapters/qoder/schemas/artifact-policy.schema.json +76 -0
  227. package/adapters/qoder/schemas/evidence-event-v2.schema.json +164 -0
  228. package/adapters/qoder/schemas/evidence-event.schema.json +89 -0
  229. package/adapters/qoder/schemas/postpublish-approval-record.schema.json +47 -0
  230. package/adapters/qoder/schemas/release-plan.schema.json +2226 -0
  231. package/adapters/qoder/schemas/release-project.schema.json +1815 -0
  232. package/adapters/qoder/schemas/release-run.schema.json +777 -0
  233. package/adapters/qoder/skills/release-assess/SKILL.md +60 -0
  234. package/adapters/qoder/skills/release-config/SKILL.md +150 -0
  235. package/adapters/qoder/skills/release-docs/SKILL.md +119 -0
  236. package/adapters/qoder/skills/release-finish/SKILL.md +154 -0
  237. package/adapters/qoder/skills/release-help/SKILL.md +154 -0
  238. package/adapters/qoder/skills/release-marketplace/SKILL.md +156 -0
  239. package/adapters/qoder/skills/release-prepare/SKILL.md +135 -0
  240. package/adapters/qoder/skills/release-publish/SKILL.md +91 -0
  241. package/adapters/qoder/skills/release-reconcile/SKILL.md +80 -0
  242. package/adapters/qoder/skills/release-setup/SKILL.md +131 -0
  243. package/adapters/qoder/skills/release-verify/SKILL.md +109 -0
  244. package/adapters/qoder/src/schemas/adapter-build-manifest.schema.json +41 -0
  245. package/adapters/qoder/src/schemas/adapter-peer-verification-request.schema.json +54 -0
  246. package/adapters/qoder/src/schemas/adapter-peer-verification-result.schema.json +54 -0
  247. package/adapters/qoder/src/schemas/adapter-source.schema.json +47 -0
  248. package/adapters/qoder/src/schemas/audit-baseline-pin.schema.json +163 -0
  249. package/adapters/qoder/src/schemas/declared-read-surface-result.schema.json +61 -0
  250. package/adapters/qoder/src/schemas/engineering-baseline.schema.json +77 -0
  251. package/adapters/qoder/src/schemas/executable-identity-observation.schema.json +162 -0
  252. package/adapters/qoder/src/schemas/filesystem-root-binding.schema.json +14 -0
  253. package/adapters/qoder/src/schemas/filesystem-tree-observation.schema.json +71 -0
  254. package/adapters/qoder/src/schemas/fixed-set-publication-manifest.schema.json +108 -0
  255. package/adapters/qoder/src/schemas/fixed-set-publication-receipt.schema.json +148 -0
  256. package/adapters/qoder/src/schemas/host-capability-fact.schema.json +31 -0
  257. package/adapters/qoder/src/schemas/host-descriptor.schema.json +144 -0
  258. package/adapters/qoder/src/schemas/host-operation-plan.schema.json +57 -0
  259. package/adapters/qoder/src/schemas/host-operation-receipt.schema.json +81 -0
  260. package/adapters/qoder/src/schemas/host-probe-result.schema.json +30 -0
  261. package/adapters/qoder/src/schemas/host-registry.schema.json +18 -0
  262. package/adapters/qoder/src/schemas/host-verification-request.schema.json +67 -0
  263. package/adapters/qoder/src/schemas/host-verification-result.schema.json +149 -0
  264. package/adapters/qoder/src/schemas/managed-file-lock.schema.json +77 -0
  265. package/adapters/qoder/src/schemas/migration-manifest.schema.json +412 -0
  266. package/adapters/qoder/src/schemas/observation-scope.schema.json +91 -0
  267. package/adapters/qoder/src/schemas/operation-request.schema.json +58 -0
  268. package/adapters/qoder/src/schemas/operation-result.schema.json +130 -0
  269. package/adapters/qoder/src/schemas/platform-difference-registry.schema.json +110 -0
  270. package/adapters/qoder/src/schemas/plugin-verification-request.schema.json +499 -0
  271. package/adapters/qoder/src/schemas/plugin-verification-result.schema.json +1217 -0
  272. package/adapters/qoder/src/schemas/profile-adoption-declaration.schema.json +111 -0
  273. package/adapters/qoder/src/schemas/profile-descriptor.schema.json +99 -0
  274. package/adapters/qoder/src/schemas/project-manifest.schema.json +67 -0
  275. package/adapters/qoder/src/schemas/project-profile.schema.json +25 -0
  276. package/adapters/qoder/src/schemas/public-boundary-declaration.schema.json +73 -0
  277. package/adapters/qoder/src/schemas/report-binding.schema.json +42 -0
  278. package/adapters/qoder/src/schemas/report-model.schema.json +308 -0
  279. package/adapters/qoder/src/schemas/skill-family-directory-verification-request.schema.json +100 -0
  280. package/adapters/qoder/src/schemas/skill-family-directory-verification-result.schema.json +193 -0
  281. package/adapters/qoder/src/schemas/source-authority-receipt.schema.json +31 -0
  282. package/adapters/qoder/src/schemas/state-event-envelope.schema.json +38 -0
  283. package/adapters/qoder/src/schemas/state-snapshot-metadata.schema.json +25 -0
  284. package/adapters/qoder/src/schemas/structured-scan-policy.schema.json +97 -0
  285. package/adapters/qoder/src/schemas/surface-scan-policy.schema.json +42 -0
  286. package/adapters/qoder/src/schemas/timeout-policy.schema.json +24 -0
  287. package/adapters/qoder/src/schemas/token-estimate-record.schema.json +75 -0
  288. package/adapters/qoder/src/schemas/token-estimate-result.schema.json +43 -0
  289. package/adapters/qoder/src/schemas/watchdog-termination-envelope.schema.json +156 -0
  290. package/adapters/workbuddy/.codebuddy-plugin/plugin.json +1 -1
  291. package/adapters/workbuddy/bin/consumer-contract-vectors.json +7 -7
  292. package/adapters/workbuddy/bin/error-codes.json +1 -1
  293. package/adapters/workbuddy/bin/foundation-resource-binding.json +1 -1
  294. package/adapters/workbuddy/bin/prebuild-manifest.json +8 -4
  295. package/adapters/workbuddy/bin/prebuilds/darwin-arm64/bound_read.darwin-arm64.node +0 -0
  296. package/adapters/workbuddy/bin/prebuilds/darwin-x64/bound_read.darwin-x64.node +0 -0
  297. package/adapters/workbuddy/bin/prebuilds/linux-arm64-gnu/bound_read.linux-arm64-gnu.node +0 -0
  298. package/adapters/workbuddy/bin/prebuilds/linux-x64-gnu/bound_read.linux-x64-gnu.node +0 -0
  299. package/adapters/workbuddy/bin/registry.json +1 -1
  300. package/adapters/workbuddy/bin/release-skill.bundle.mjs +4950 -1819
  301. package/adapters/workbuddy/bin/rules.json +1 -1
  302. package/adapters/workbuddy/data/hosts/cursor/host-descriptor.json +34 -0
  303. package/adapters/workbuddy/data/hosts/registry.json +1 -0
  304. package/adapters/workbuddy/schemas/release-plan.schema.json +255 -25
  305. package/adapters/workbuddy/schemas/release-project.schema.json +228 -26
  306. package/adapters/workbuddy/skills/release-finish/SKILL.md +29 -15
  307. package/adapters/workbuddy/skills/release-help/SKILL.md +40 -39
  308. package/adapters/workbuddy/skills/release-verify/SKILL.md +2 -2
  309. package/adapters/workbuddy/src/schemas/host-descriptor.schema.json +9 -2
  310. package/bin/consumer-contract-vectors.json +7 -7
  311. package/bin/error-codes.json +1 -1
  312. package/bin/foundation-resource-binding.json +1 -1
  313. package/bin/prebuild-manifest.json +8 -4
  314. package/bin/prebuilds/darwin-arm64/bound_read.darwin-arm64.node +0 -0
  315. package/bin/prebuilds/darwin-x64/bound_read.darwin-x64.node +0 -0
  316. package/bin/prebuilds/linux-arm64-gnu/bound_read.linux-arm64-gnu.node +0 -0
  317. package/bin/prebuilds/linux-x64-gnu/bound_read.linux-x64-gnu.node +0 -0
  318. package/bin/registry.json +1 -1
  319. package/bin/release-skill-cli.mjs +148 -6
  320. package/bin/release-skill.bundle.mjs +4950 -1819
  321. package/bin/rules.json +1 -1
  322. package/data/hosts/cursor/host-descriptor.json +34 -0
  323. package/data/hosts/registry.json +1 -0
  324. package/package.json +9 -5
  325. package/platform-manifest.json +140 -8
  326. package/references/02-project-config.md +9 -2
  327. package/schemas/release-plan.schema.json +255 -25
  328. package/schemas/release-project.schema.json +228 -26
  329. package/scripts/sync-public-files.mjs +3 -22
  330. package/skills/release-finish/SKILL.md +29 -15
  331. package/skills/release-help/SKILL.md +40 -39
  332. package/skills/release-verify/SKILL.md +2 -2
  333. package/skills-src/release-finish/SKILL.md +29 -15
  334. package/skills-src/release-help/SKILL.md +40 -39
  335. package/skills-src/release-verify/SKILL.md +2 -2
  336. package/src/adapters/contract.mjs +1 -0
  337. package/src/adapters/plugin-marketplace.mjs +201 -9
  338. package/src/commands/post-release-local.mjs +618 -53
  339. package/src/commands/prepare.mjs +74 -9
  340. package/src/commands/publish.mjs +4 -1
  341. package/src/commands/ship.mjs +2 -0
  342. package/src/commands/verify-records.mjs +467 -0
  343. package/src/commands/verify.mjs +73 -0
  344. package/src/core/checkpoints.mjs +5 -2
  345. package/src/core/config.mjs +1 -1
  346. package/src/core/foundation-host-verification.mjs +168 -0
  347. package/src/core/plan.mjs +19 -1
  348. package/src/core/postpublish.mjs +9 -1
  349. package/src/core/run-retention.mjs +1 -1
  350. package/src/core/run.mjs +1 -1
  351. package/src/core/surface-host-bindings.mjs +1 -0
  352. package/src/core/verification-gates.mjs +1 -1
  353. package/src/platforms/registry.mjs +225 -16
  354. package/src/producers/build-adapters.mjs +43 -25
  355. package/src/producers/foundation-resource-projection.mjs +3 -3
  356. package/src/schemas/host-descriptor.schema.json +9 -2
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Release-domain mapping for one frozen Cursor Skill. Foundation owns request
3
+ * preparation, installation, process supervision and bound stream reads.
4
+ */
5
+ import { basename, join, isAbsolute } from 'node:path';
6
+ import { mkdir } from 'node:fs/promises';
7
+ import { prepareHostVerification, runHostVerification } from 'skill-family-engineering-kit';
8
+ import { canonicalJson } from 'skill-family-contracts';
9
+ import { createTemporaryWorkspace } from 'skill-family-harness-node';
10
+
11
+ import { verifyFrozenSnapshot } from '../snapshot/frozen.mjs';
12
+ import { canonicalPublicPath, publicPathCollisionKey } from '../snapshot/public-path.mjs';
13
+ import { CONSUMER_VERIFICATION_DEFERRED, POST_PUBLISH_VERIFY_FAILED, ReleaseError } from './errors.mjs';
14
+
15
+ function fail(message, details = {}) {
16
+ return new ReleaseError(POST_PUBLISH_VERIFY_FAILED, message, details);
17
+ }
18
+
19
+ /** Release-owned scenario policy, shared by freezing and consuming the contract. */
20
+ export function assertCursorHostScenario(scenario) {
21
+ const keys = ['workloadDocument', 'fixtureFiles', 'protectedWorkspaceFiles', 'platformManifest', 'effectivePrompt', 'expectedResult'];
22
+ if (!scenario || typeof scenario !== 'object' || Array.isArray(scenario)
23
+ || Object.keys(scenario).length !== keys.length || keys.some((key) => !Object.hasOwn(scenario, key))) {
24
+ throw fail('Cursor host verification requires the complete frozen scenario');
25
+ }
26
+ for (const key of ['workloadDocument', 'effectivePrompt', 'expectedResult']) {
27
+ if (typeof scenario[key] !== 'string' || !scenario[key].isWellFormed()
28
+ || (key !== 'expectedResult' && scenario[key].length === 0)
29
+ || (key === 'effectivePrompt' && scenario[key].includes('\0'))) {
30
+ throw fail('Cursor scenario requires valid UTF-8 text', { field: key });
31
+ }
32
+ }
33
+ if (!scenario.platformManifest || typeof scenario.platformManifest !== 'object' || Array.isArray(scenario.platformManifest)) {
34
+ throw fail('Cursor scenario platformManifest must be a JSON object');
35
+ }
36
+ canonicalJson(scenario.platformManifest);
37
+ for (const field of ['fixtureFiles', 'protectedWorkspaceFiles']) {
38
+ const files = scenario[field];
39
+ if (!Array.isArray(files) || files.length === 0) throw fail('Cursor scenario files must be non-empty', { field });
40
+ const paths = [];
41
+ for (const file of files) {
42
+ if (!file || Object.keys(file).length !== 2 || typeof file.content !== 'string' || !file.content.isWellFormed()) {
43
+ throw fail('Cursor scenario file requires path and UTF-8 content', { field });
44
+ }
45
+ let path;
46
+ try { path = canonicalPublicPath(file.path).path; } catch { throw fail('Cursor scenario file path is unsafe', { field }); }
47
+ const key = publicPathCollisionKey(path);
48
+ if (path !== file.path || key.split('/').includes('.cursor')
49
+ || paths.some((other) => other === key || other.startsWith(key + '/') || key.startsWith(other + '/'))) {
50
+ throw fail('Cursor scenario files conflict or target a Cursor control path', { field });
51
+ }
52
+ paths.push(key);
53
+ }
54
+ }
55
+ }
56
+
57
+ /** Consume only frozen domain facts and this invocation's explicit private roots. */
58
+ export async function verifyFrozenCursorSkillWithFoundation({
59
+ plan, unitId, root, cursorHostRuntime,
60
+ runHostVerificationFn = runHostVerification,
61
+ clock = () => new Date().toISOString(),
62
+ } = {}) {
63
+ const unit = (plan?.units ?? []).find((candidate) => candidate.id === unitId);
64
+ const distribution = unit?.distributions?.find((candidate) => candidate.type === 'cursor-plugin');
65
+ const contract = distribution?.hostVerificationContract;
66
+ if (!unit?.frozenSnapshot?.path || !unit.frozenSnapshot.commit || !unit.frozenSnapshot.manifestDigest) {
67
+ throw fail('Cursor host verification requires a frozen unit snapshot', { unitId });
68
+ }
69
+ if (contract?.contractVersion !== 1 || contract.hostId !== 'cursor'
70
+ || contract.entrySkill !== distribution.entrySkill
71
+ || contract.payloadDigest !== unit.frozenSnapshot.manifestDigest
72
+ || contract.manifestRelativePath !== 'skills/' + contract.entrySkill + '/SKILL.md') {
73
+ throw fail('Cursor host verification contract does not bind the frozen payload and entry Skill', { unitId });
74
+ }
75
+ assertCursorHostScenario(contract.scenario);
76
+ if (!cursorHostRuntime || Object.keys(cursorHostRuntime).length !== 2
77
+ || !['executableRoot', 'existingUserStateRoot'].every((key) =>
78
+ typeof cursorHostRuntime[key] === 'string' && isAbsolute(cursorHostRuntime[key]))) {
79
+ throw fail('Cursor host verification requires explicit absolute executableRoot and existingUserStateRoot', { unitId });
80
+ }
81
+ const frozen = await verifyFrozenSnapshot({ root, snapshotPath: unit.frozenSnapshot.path, expectedDigest: contract.payloadDigest });
82
+ const prefix = 'skills/' + contract.entrySkill + '/';
83
+ const members = frozen.entries.filter((entry) => entry.type === 'file' && entry.path.startsWith(prefix))
84
+ .map((entry) => entry.path.slice(prefix.length));
85
+ if (!members.includes('SKILL.md')) throw fail('Cursor frozen entry Skill is missing SKILL.md', { unitId });
86
+ const scenario = contract.scenario;
87
+ const owned = await createTemporaryWorkspace({ prefix: 'release-skill-cursor-' });
88
+ let retain = false;
89
+ let prepared;
90
+ let result;
91
+ try {
92
+ const repositoryRoot = await owned.resolve('repository');
93
+ const workspaceRoot = join(repositoryRoot, 'workspace');
94
+ const sessionRoot = await owned.resolve('session');
95
+ await mkdir(workspaceRoot, { recursive: true, mode: 0o700 });
96
+ await mkdir(sessionRoot, { mode: 0o700 });
97
+ for (const file of scenario.protectedWorkspaceFiles) {
98
+ await owned.writeFile('repository/workspace/' + file.path, file.content, { mode: 0o600 });
99
+ }
100
+ prepared = await prepareHostVerification({
101
+ hostId: 'cursor',
102
+ verificationSetId: plan.digest + ':' + unitId + ':cursor',
103
+ candidate: {
104
+ ref: unit.frozenSnapshot.commit,
105
+ manifest: canonicalJson({
106
+ contractVersion: contract.contractVersion, unitId, candidateRef: unit.frozenSnapshot.commit,
107
+ payloadDigest: contract.payloadDigest, entrySkill: contract.entrySkill,
108
+ manifestRelativePath: contract.manifestRelativePath,
109
+ }),
110
+ },
111
+ skill: { root: join(frozen.snapshotDir, 'skills', contract.entrySkill), entrySkill: contract.entrySkill, members },
112
+ workloadDocument: scenario.workloadDocument,
113
+ fixtureFiles: scenario.fixtureFiles,
114
+ workspace: { repositoryRoot, root: workspaceRoot, protectedMembers: scenario.protectedWorkspaceFiles.map((file) => file.path) },
115
+ platformManifest: canonicalJson(scenario.platformManifest),
116
+ effectivePrompt: scenario.effectivePrompt,
117
+ executable: { root: cursorHostRuntime.executableRoot, relPath: 'cursor-agent' },
118
+ existingUserStateRoot: cursorHostRuntime.existingUserStateRoot,
119
+ sessionRoot,
120
+ timeoutPolicy: {
121
+ schemaVersion: 1, kind: 'skill-family.timeout-policy',
122
+ maxSeconds: (distribution.timeoutMs ?? 300000) / 1000, killGraceSeconds: 1,
123
+ },
124
+ });
125
+ // An unexpected exception after dispatch cannot establish process termination.
126
+ retain = true;
127
+ result = await runHostVerificationFn(prepared);
128
+ retain = !['observed', 'failed', 'rejected'].includes(result?.status);
129
+ if (retain) {
130
+ throw new ReleaseError(CONSUMER_VERIFICATION_DEFERRED,
131
+ 'Cursor invocation is indeterminate; inspect the retained private scene before retrying with fresh runtime inputs', {
132
+ unitId,
133
+ requirements: [{ unitId, hostId: 'cursor', action: 'inspect-retained-cursor-scene', sceneId: basename(owned.root) }],
134
+ });
135
+ }
136
+ const stdout = result.streams ? await prepared.readInvocationStream(result, 'stdout') : null;
137
+ if (result.status !== 'observed') {
138
+ throw fail('Foundation Cursor invocation did not reach an observed result', { unitId, status: result.status, reason: result.reason });
139
+ }
140
+ if (!stdout) throw fail('Cursor invocation has no bound stdout evidence', { unitId });
141
+ let answer;
142
+ try { answer = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(stdout)); } catch {
143
+ throw fail('Cursor invocation did not return valid UTF-8 success JSON', { unitId });
144
+ }
145
+ if (answer?.type !== 'result' || answer.subtype !== 'success' || answer.is_error !== false
146
+ || typeof answer.result !== 'string' || answer.result !== scenario.expectedResult) {
147
+ throw fail('Cursor result does not match the frozen expected result', { unitId });
148
+ }
149
+ return {
150
+ planDigest: plan.digest, unitId, distributionType: 'cursor-plugin',
151
+ candidateRef: unit.frozenSnapshot.commit, payloadDigest: contract.payloadDigest,
152
+ manifestRelativePath: contract.manifestRelativePath, entrySkill: contract.entrySkill,
153
+ hostId: result.host.hostId, driverId: result.host.driverId, foundationStatus: result.status,
154
+ requestDigest: result.requestDigest, runtimeIdentities: result.runtimeIdentities,
155
+ execution: result.execution, snapshots: result.snapshots, streams: result.streams, observedAt: clock(),
156
+ };
157
+ } catch (error) {
158
+ if (error instanceof ReleaseError) throw error;
159
+ if (retain) {
160
+ throw new ReleaseError(CONSUMER_VERIFICATION_DEFERRED, 'Cursor invocation outcome is unknown; inspect the retained private scene', {
161
+ unitId, requirements: [{ unitId, hostId: 'cursor', action: 'inspect-retained-cursor-scene', sceneId: basename(owned.root) }],
162
+ });
163
+ }
164
+ throw fail('Foundation Cursor host verification failed closed', { unitId, foundationCode: error?.code ?? null });
165
+ } finally {
166
+ if (!retain) await owned.dispose();
167
+ }
168
+ }
package/src/core/plan.mjs CHANGED
@@ -413,7 +413,9 @@ function buildExpectedAdapterMap() {
413
413
  'create-tag': 'git-github',
414
414
  'github-release': 'github',
415
415
  'npm-publish': 'npm',
416
- ...Object.fromEntries(PLATFORMS.map((p) => [p.actionType, p.adapter])),
416
+ ...Object.fromEntries(PLATFORMS
417
+ .filter((platform) => platform.actionType !== null)
418
+ .map((platform) => [platform.actionType, platform.adapter])),
417
419
  'set-default-branch': 'git-github',
418
420
  };
419
421
  }
@@ -857,6 +859,22 @@ export function validatePlanActionCompleteness(plan, options = {}) {
857
859
  for (const platform of PLATFORMS) {
858
860
  const dist = distributions.find((d) => d.type === platform.distributionType);
859
861
  if (!dist) continue;
862
+ if (platform.actionType === null) {
863
+ if (!dist.entrySkill) {
864
+ failures.push(`unit "${unitId}": ${platform.distributionType} distribution requires entrySkill`);
865
+ }
866
+ const contract = dist.hostVerificationContract;
867
+ if (
868
+ !contract
869
+ || contract.hostId !== platform.id
870
+ || contract.entrySkill !== dist.entrySkill
871
+ || contract.manifestRelativePath !== `skills/${dist.entrySkill}/SKILL.md`
872
+ || contract.payloadDigest !== frozen?.manifestDigest
873
+ ) {
874
+ failures.push(`unit "${unitId}": ${platform.distributionType} distribution host verification contract does not match the frozen payload`);
875
+ }
876
+ continue;
877
+ }
860
878
  const plugin = dist.plugin;
861
879
  const marketplace = dist.marketplace;
862
880
  const entrySkill = dist.entrySkill;
@@ -30,6 +30,7 @@ import {
30
30
  resolvePresetRequiresApproval,
31
31
  } from './presets.mjs';
32
32
  import { checkGitRemoteUrl, describeGitRemoteUrlFailure } from './git-url-policy.mjs';
33
+ import { classifyPathInput } from 'skill-family-harness-node';
33
34
 
34
35
  /** Secret-ish environment variable denylist (R3 credential hygiene). */
35
36
  export const ENV_ALLOWLIST_DENYLIST = /TOKEN|SECRET|PASSWORD|PASSPHRASE|API_KEY|CREDENTIAL/i;
@@ -42,7 +43,7 @@ const SAFE_ID_RE = /^[a-z0-9][a-z0-9._-]*$/;
42
43
 
43
44
  /** Branch pattern (leading alphanumeric blocks option-like names). */
44
45
  const BRANCH_RE = /^[A-Za-z0-9][A-Za-z0-9._/-]*$/;
45
- const LOCAL_HOSTS = new Set(['claude', 'codex', 'kimi', 'codebuddy', 'workbuddy']);
46
+ const LOCAL_HOSTS = new Set(['claude', 'codex', 'kimi', 'codebuddy', 'workbuddy', 'qoder', 'cursor']);
46
47
  const HUB_HOST_RE = /^[A-Za-z0-9](?:[A-Za-z0-9.-]*[A-Za-z0-9])?$/u;
47
48
  const HUB_REF_RE = /^refs\/heads\/[A-Za-z0-9][A-Za-z0-9._-]*(?:\/[A-Za-z0-9][A-Za-z0-9._-]*)*$/u;
48
49
 
@@ -500,6 +501,13 @@ export function validatePostPublishDeclaration(postPublish, options = {}) {
500
501
  if (hosts.has(host)) fail(`${unitLabel}localHostUpdate.hosts contains duplicate host "${host}"`);
501
502
  hosts.add(host);
502
503
  }
504
+ if (hosts.has('cursor')) {
505
+ if (!/^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/u.test(localHostUpdate.plugin)) fail(`${unitLabel}Cursor plugin name must match the Cursor naming convention`);
506
+ const cursor = localHostUpdate.cursor;
507
+ if (!cursor || typeof cursor !== 'object' || Array.isArray(cursor)) fail(`${unitLabel}localHostUpdate.cursor is required`);
508
+ if (!classifyPathInput(cursor.sourcePath).ok) fail(`${unitLabel}localHostUpdate.cursor.sourcePath must be a safe relative path`);
509
+ if (cursor.dependencyInstall !== undefined && cursor.dependencyInstall !== 'npm-ci-ignore-scripts') fail(`${unitLabel}localHostUpdate.cursor.dependencyInstall is unsupported`);
510
+ } else if (localHostUpdate.cursor !== undefined) fail(`${unitLabel}localHostUpdate.cursor requires cursor in hosts`);
503
511
  const hub = localHostUpdate.hub;
504
512
  if (!hub || typeof hub !== 'object' || Array.isArray(hub)) {
505
513
  fail(`${unitLabel}localHostUpdate.hub must be a non-null object`);
@@ -67,7 +67,7 @@ function postVerificationComplete(run) {
67
67
  function publicationComplete(run) {
68
68
  return run.checkpoints.every((cp) => COMPLETED_CHECKPOINTS.has(cp.status)
69
69
  || (['failed', 'deferred'].includes(cp.status)
70
- && ['claude-marketplace-install', 'codex-marketplace-install', 'kimi-marketplace-install', 'codebuddy-marketplace-install'].includes(cp.actionType)));
70
+ && ['claude-marketplace-install', 'codex-marketplace-install', 'kimi-marketplace-install', 'codebuddy-marketplace-install', 'qoder-marketplace-install'].includes(cp.actionType)));
71
71
  }
72
72
 
73
73
  async function lineagePathsContained(run, runsRoot) {
package/src/core/run.mjs CHANGED
@@ -464,7 +464,7 @@ async function validateStatePredecessorChain(run, runPath, options = {}) {
464
464
  }
465
465
  }
466
466
 
467
- function validateSourceRunEdge(child, parent) {
467
+ export function validateSourceRunEdge(child, parent) {
468
468
  if (child.command === 'reconcile') {
469
469
  if (!['publish', 'reconcile'].includes(parent.command) || parent.status !== 'PARTIAL') {
470
470
  throw new ReleaseError(
@@ -91,6 +91,7 @@ export function normalizeGenericSkillsRel(skillsRaw) {
91
91
  const SKILLS_NORMALIZERS = {
92
92
  claude: normalizeGenericSkillsRel,
93
93
  codex: normalizeGenericSkillsRel,
94
+ qoder: normalizeGenericSkillsRel,
94
95
  kimi: normalizeKimiSkillsRel,
95
96
  codebuddy: normalizeCodeBuddySkillsRel,
96
97
  };
@@ -57,7 +57,7 @@ function validateGate(gate) {
57
57
  if (!gate.scope || typeof gate.scope.unit !== 'string') {
58
58
  throw gateError(gate, 'must declare scope.unit');
59
59
  }
60
- if (gate.phase === 'consumer-verify' && !['npm', 'claude-plugin', 'codex-plugin', 'kimi-plugin', 'codebuddy-plugin'].includes(gate.scope.distribution)) {
60
+ if (gate.phase === 'consumer-verify' && !['npm', 'claude-plugin', 'codex-plugin', 'kimi-plugin', 'codebuddy-plugin', 'qoder-plugin'].includes(gate.scope.distribution)) {
61
61
  throw gateError(gate, 'consumer-verify must declare a supported scope.distribution');
62
62
  }
63
63
  if (!Array.isArray(gate.command) || gate.command.length === 0 || gate.command.some((value) => typeof value !== 'string')) {
@@ -132,6 +132,70 @@ function codexCrossValidateListEntry(found, action) {
132
132
  return { ok: true };
133
133
  }
134
134
 
135
+ // --- qoder strategy -------------------------------------------------------
136
+
137
+ function qoderParseListOutput(listOutput, pluginId) {
138
+ if (!Array.isArray(listOutput)) {
139
+ return { ok: false, error: 'Qoder plugin list did not return an array' };
140
+ }
141
+ const matches = listOutput.filter((entry) => entry?.id === pluginId);
142
+ if (matches.length === 0) {
143
+ return { ok: false, error: `plugin "${pluginId}" not found in Qoder plugin list` };
144
+ }
145
+ if (matches.length !== 1) {
146
+ return { ok: false, error: `plugin "${pluginId}" has duplicate Qoder list entries` };
147
+ }
148
+ const [found] = matches;
149
+ if (typeof found.installPath !== 'string' || found.installPath.length === 0) {
150
+ return { ok: false, error: `plugin "${pluginId}" found but missing installPath` };
151
+ }
152
+ return { ok: true, found, installPath: found.installPath };
153
+ }
154
+
155
+ function qoderParseMarketplaceListOutput(listOutput, marketplace) {
156
+ if (!Array.isArray(listOutput)) {
157
+ return { ok: false, error: 'Qoder marketplace list did not return an array' };
158
+ }
159
+ const matches = listOutput.filter((entry) => entry?.name === marketplace);
160
+ if (matches.length === 0) {
161
+ return { ok: false, error: `marketplace "${marketplace}" not found in Qoder marketplace list` };
162
+ }
163
+ if (matches.length !== 1) {
164
+ return { ok: false, error: `marketplace "${marketplace}" has duplicate Qoder list entries` };
165
+ }
166
+ const [found] = matches;
167
+ if (found.source?.source !== 'git' || typeof found.source.url !== 'string' || found.source.url.length === 0) {
168
+ return { ok: false, error: `marketplace "${marketplace}" has invalid Qoder git source` };
169
+ }
170
+ if (typeof found.installLocation !== 'string' || found.installLocation.length === 0) {
171
+ return { ok: false, error: `marketplace "${marketplace}" found but missing installLocation` };
172
+ }
173
+ return { ok: true, found, installPath: found.installLocation };
174
+ }
175
+
176
+ function qoderExtractInstallPath({ listParsed }) {
177
+ return { ok: true, installPath: listParsed?.installPath };
178
+ }
179
+
180
+ function qoderExtractListIdentity(found) {
181
+ return {
182
+ plugin: found.name,
183
+ marketplace: String(found.id ?? '').split('@').slice(1).join('@'),
184
+ version: found.version,
185
+ };
186
+ }
187
+
188
+ function qoderCrossValidateListEntry(found, action) {
189
+ const selector = `${action.plugin}@${action.marketplace}`;
190
+ if (found.name !== action.plugin || found.source !== selector || found.scope !== 'user') {
191
+ return { ok: false, error: `Qoder plugin "${selector}" does not match its frozen user-scope identity` };
192
+ }
193
+ if (found.version !== action.version) {
194
+ return { ok: false, error: `list version "${found.version}" does not match action version "${action.version}"` };
195
+ }
196
+ return { ok: true };
197
+ }
198
+
135
199
  // --- platform descriptors --------------------------------------------------
136
200
 
137
201
  const CLAUDE = Object.freeze({
@@ -188,6 +252,7 @@ const CLAUDE = Object.freeze({
188
252
  pluginDirName: '.claude-plugin',
189
253
  templateFileName: 'plugin.json',
190
254
  hasMarketplace: false,
255
+ enabled: true,
191
256
  }),
192
257
  strategy: Object.freeze({
193
258
  parseListOutput: claudeParseListOutput,
@@ -249,6 +314,7 @@ const CODEX = Object.freeze({
249
314
  templateFileName: 'plugin.json',
250
315
  marketplaceFileName: null,
251
316
  hasMarketplace: false,
317
+ enabled: true,
252
318
  }),
253
319
  strategy: Object.freeze({
254
320
  parseListOutput: codexParseListOutput,
@@ -309,6 +375,7 @@ const KIMI = Object.freeze({
309
375
  templateFileName: 'plugin.json',
310
376
  marketplaceFileName: null,
311
377
  hasMarketplace: false,
378
+ enabled: true,
312
379
  }),
313
380
  strategy: Object.freeze({
314
381
  parseListOutput: null,
@@ -395,6 +462,7 @@ const CODEBUDDY = Object.freeze({
395
462
  templateFileName: 'plugin.json',
396
463
  marketplaceFileName: null,
397
464
  hasMarketplace: false,
465
+ enabled: true,
398
466
  }),
399
467
  strategy: Object.freeze({
400
468
  parseListOutput: null,
@@ -408,20 +476,126 @@ const CODEBUDDY = Object.freeze({
408
476
  }),
409
477
  });
410
478
 
411
- /** Ordered platform registry. Order is significant (claude, codex, kimi, codebuddy). */
412
- export const PLATFORMS = Object.freeze([CLAUDE, CODEX, KIMI, CODEBUDDY]);
479
+ const QODER = Object.freeze({
480
+ id: 'qoder',
481
+ skillProjectionSurface: 'platforms/qoder',
482
+ distributionType: 'qoder-plugin',
483
+ actionType: 'qoder-marketplace-install',
484
+ adapter: 'plugin-marketplace',
485
+ automatable: true,
486
+ installMethod: 'structured-cli',
487
+ // Qoder's marketplace-add command follows the marketplace default branch;
488
+ // the frozen commit is checked from the materialized Hub checkout before
489
+ // installation, so marketplace add itself is not treated as a ref pin.
490
+ refStrength: 'commit-sha',
491
+ outputProtocol: 'structured',
492
+ identityEvidence: 'list-record',
493
+ degradationPolicy: 'block',
494
+ cli: Object.freeze({
495
+ binary: 'qodercli',
496
+ binaryAliases: Object.freeze(['qoder']),
497
+ marketplaceAdd: (repo) => ['plugins', 'marketplace', 'add', repo, '--scope', 'user'],
498
+ install: (plugin, marketplace) => ['plugins', 'install', `${plugin}@${marketplace}`, '--scope', 'user', '--json'],
499
+ marketplaceList: () => ['plugins', 'marketplace', 'list', '--json'],
500
+ list: () => ['plugins', 'list', '--json'],
501
+ }),
502
+ jsonProtocol: Object.freeze({
503
+ listOutput: 'array',
504
+ installPathSource: 'list',
505
+ marketplaceAddOutput: null,
506
+ pluginInstallOutput: null,
507
+ }),
508
+ isolationEnv: (home) => ({ HOME: home }),
509
+ isolationSubdirs: Object.freeze(['.qoder']),
510
+ manifestPaths: Object.freeze({
511
+ plugin: '.qoder-plugin/plugin.json',
512
+ marketplace: null,
513
+ }),
514
+ marketplaceSourceForm: null,
515
+ marketplaceEntryCarriesVersion: false,
516
+ marketplaceRefForm: null,
517
+ knownHostArtifacts: Object.freeze(['.git']),
518
+ schemaRequiredFields: Object.freeze(['plugin', 'marketplace', 'entrySkill']),
519
+ skillRendering: Object.freeze({ mode: 'substitute', preamble: 'qoder', placeholder: '${CLAUDE_PLUGIN_ROOT}' }),
520
+ buildAdapter: Object.freeze({
521
+ name: 'qoder',
522
+ pluginDirName: '.qoder-plugin',
523
+ templateFileName: 'plugin.json',
524
+ marketplaceFileName: null,
525
+ hasMarketplace: false,
526
+ enabled: true,
527
+ }),
528
+ strategy: Object.freeze({
529
+ parseListOutput: qoderParseListOutput,
530
+ parseMarketplaceListOutput: qoderParseMarketplaceListOutput,
531
+ extractInstallPath: qoderExtractInstallPath,
532
+ extractListIdentity: qoderExtractListIdentity,
533
+ crossValidateListEntry: qoderCrossValidateListEntry,
534
+ buildManualRequirement: null,
535
+ readManifest: null,
536
+ }),
537
+ });
413
538
 
414
- const VALID_DISTRIBUTION_TYPES = new Set(['claude-plugin', 'codex-plugin', 'kimi-plugin', 'codebuddy-plugin']);
415
- const VALID_ACTION_TYPES = new Set(['claude-marketplace-install', 'codex-marketplace-install', 'kimi-marketplace-install', 'codebuddy-marketplace-install']);
539
+ const CURSOR = Object.freeze({
540
+ id: 'cursor',
541
+ skillProjectionSurface: 'platforms/cursor',
542
+ distributionType: 'cursor-plugin',
543
+ actionType: null,
544
+ adapter: null,
545
+ automatable: true,
546
+ installMethod: 'foundation-host-verification',
547
+ refStrength: 'local-payload',
548
+ outputProtocol: 'structured',
549
+ identityEvidence: 'host-verification-result',
550
+ degradationPolicy: 'block',
551
+ cli: null,
552
+ jsonProtocol: Object.freeze({
553
+ listOutput: null,
554
+ installPathSource: null,
555
+ marketplaceAddOutput: null,
556
+ pluginInstallOutput: null,
557
+ }),
558
+ isolationEnv: null,
559
+ isolationSubdirs: Object.freeze([]),
560
+ manifestPaths: Object.freeze({ plugin: null, marketplace: null }),
561
+ marketplaceSourceForm: null,
562
+ marketplaceEntryCarriesVersion: null,
563
+ marketplaceRefForm: null,
564
+ knownHostArtifacts: Object.freeze([]),
565
+ schemaRequiredFields: Object.freeze(['entrySkill']),
566
+ skillRendering: null,
567
+ buildAdapter: Object.freeze({
568
+ name: 'cursor',
569
+ pluginDirName: '.cursor-plugin',
570
+ templateFileName: 'plugin.json',
571
+ marketplaceFileName: null,
572
+ hasMarketplace: false,
573
+ enabled: true,
574
+ }),
575
+ strategy: Object.freeze({
576
+ parseListOutput: null,
577
+ extractInstallPath: null,
578
+ extractListIdentity: null,
579
+ crossValidateListEntry: null,
580
+ buildManualRequirement: null,
581
+ readManifest: null,
582
+ }),
583
+ });
584
+
585
+ /** Ordered platform registry. Order is significant. */
586
+ export const PLATFORMS = Object.freeze([CLAUDE, CODEX, KIMI, CODEBUDDY, QODER, CURSOR]);
587
+
588
+ const VALID_DISTRIBUTION_TYPES = new Set(['claude-plugin', 'codex-plugin', 'kimi-plugin', 'codebuddy-plugin', 'qoder-plugin', 'cursor-plugin']);
589
+ const VALID_ACTION_TYPES = new Set(['claude-marketplace-install', 'codex-marketplace-install', 'kimi-marketplace-install', 'codebuddy-marketplace-install', 'qoder-marketplace-install', null]);
416
590
  const VALID_SOURCE_FORMS = new Set(['string', 'local-path-object', null]);
417
591
  const VALID_MARKETPLACE_REF_FORMS = new Set(['sha', 'name', null]);
418
592
  const VALID_LIST_OUTPUTS = new Set(['array', 'installed-object', null]);
419
593
  const VALID_CLI_OUTPUTS = new Set(['json', null]);
420
594
  const VALID_ENTRY_VERSION_BINDING = new Set([true, false, null]);
421
- const VALID_INSTALL_METHODS = new Set(['structured-cli', 'interactive-only', 'human-attestation']);
422
- const VALID_REF_STRENGTHS = new Set(['commit-sha', 'name-ref', 'unfixable']);
595
+ const VALID_INSTALL_METHODS = new Set(['structured-cli', 'interactive-only', 'human-attestation', 'foundation-host-verification']);
596
+ const VALID_REF_STRENGTHS = new Set(['commit-sha', 'name-ref', 'unfixable', 'local-payload']);
423
597
  const VALID_OUTPUT_PROTOCOLS = new Set(['structured', 'text', 'none']);
424
- const VALID_IDENTITY_EVIDENCE = new Set(['list-record', 'install-output', 'filesystem-payload', 'human-attestation']);
598
+ const VALID_IDENTITY_EVIDENCE = new Set(['list-record', 'install-output', 'filesystem-payload', 'human-attestation', 'host-verification-result']);
425
599
  const VALID_DEGRADATION_POLICIES = new Set(['block', 'human-attestation', 'human-attestation-with-fallback']);
426
600
  const SKILL_PROJECTION_SURFACE_PATTERN = /^platforms\/[a-z0-9]+(?:-[a-z0-9]+)*$/u;
427
601
 
@@ -442,19 +616,19 @@ const STANDALONE_SHA_RE = /^[0-9a-f]{40}$/u;
442
616
  function standaloneIdentityCore(platformOrId, fields) {
443
617
  const platform = typeof platformOrId === 'string' ? getPlatform(platformOrId) : platformOrId;
444
618
  const id = platform?.id;
445
- if (id !== 'claude' && id !== 'codex') {
619
+ if (!['claude', 'codex', 'qoder'].includes(id)) {
446
620
  throw new Error(`standalone-index install identity is unsupported for platform "${id ?? '<unknown>'}"`);
447
621
  }
448
622
  const { name, source, version } = fields;
449
623
  if (typeof name !== 'string' || name.length === 0
450
624
  || !source || typeof source !== 'object' || Array.isArray(source)
451
625
  || typeof source.source !== 'string'
452
- || typeof source.ref !== 'string' || source.ref.length === 0
453
626
  || typeof source.sha !== 'string' || !STANDALONE_SHA_RE.test(source.sha)) {
454
627
  throw new Error(`${id} standalone-index install identity has invalid owned fields`);
455
628
  }
456
629
  if (id === 'claude') {
457
- if (source.source !== 'github' || typeof source.repo !== 'string' || source.repo.length === 0
630
+ if (typeof source.ref !== 'string' || source.ref.length === 0
631
+ || source.source !== 'github' || typeof source.repo !== 'string' || source.repo.length === 0
458
632
  || typeof version !== 'string' || version.length === 0) {
459
633
  throw new Error('Claude standalone-index install identity requires github repo, ref, sha, and version');
460
634
  }
@@ -465,6 +639,12 @@ function standaloneIdentityCore(platformOrId, fields) {
465
639
  };
466
640
  }
467
641
  if (source.source !== 'url' || typeof source.url !== 'string' || source.url.length === 0) {
642
+ throw new Error(`${id === 'qoder' ? 'Qoder' : 'Codex'} standalone-index install identity requires url and sha`);
643
+ }
644
+ if (id === 'qoder') {
645
+ return { name, source: { source: 'url', url: source.url, sha: source.sha } };
646
+ }
647
+ if (typeof source.ref !== 'string' || source.ref.length === 0) {
468
648
  throw new Error('Codex standalone-index install identity requires url, ref, and sha');
469
649
  }
470
650
  return {
@@ -494,6 +674,12 @@ export function buildExpectedStandaloneIndexInstallIdentity(platformOrId, frozen
494
674
  source: { source: 'url', url: `https://github.com/${repo}.git`, ref: `refs/tags/${tag}`, sha },
495
675
  });
496
676
  }
677
+ if (id === 'qoder') {
678
+ return standaloneIdentityCore(platform, {
679
+ name,
680
+ source: { source: 'url', url: `https://github.com/${repo}.git`, sha },
681
+ });
682
+ }
497
683
  return standaloneIdentityCore(platform, { name, source: {}, version });
498
684
  }
499
685
 
@@ -531,6 +717,12 @@ export function projectObservedStandaloneIndexInstallIdentity(platformOrId, entr
531
717
  },
532
718
  });
533
719
  }
720
+ if (id === 'qoder') {
721
+ return standaloneIdentityCore(platform, {
722
+ name: entry.name,
723
+ source: { source: source.source, url: source.url, sha: source.sha },
724
+ });
725
+ }
534
726
  return standaloneIdentityCore(platform, { name: entry.name, source });
535
727
  }
536
728
 
@@ -573,16 +765,22 @@ export function assertRegistry(registry = PLATFORMS) {
573
765
  if (!VALID_ACTION_TYPES.has(platform.actionType)) {
574
766
  throw new Error(`platform registry: ${label} has illegal actionType "${platform.actionType}"`);
575
767
  }
576
- if (typeof platform.adapter !== 'string' || platform.adapter.length === 0) {
768
+ if (platform.installMethod !== 'foundation-host-verification'
769
+ && (typeof platform.adapter !== 'string' || platform.adapter.length === 0)) {
577
770
  throw new Error(`platform registry: ${label} needs a non-empty adapter id`);
578
771
  }
772
+ if (platform.installMethod === 'foundation-host-verification'
773
+ && (platform.actionType !== null || platform.adapter !== null)) {
774
+ throw new Error(`platform registry: ${label} host verification must not declare a checkpoint action or adapter`);
775
+ }
579
776
  if (!VALID_ENTRY_VERSION_BINDING.has(platform.marketplaceEntryCarriesVersion)) {
580
777
  throw new Error(`platform registry: ${label} has illegal marketplaceEntryCarriesVersion "${platform.marketplaceEntryCarriesVersion}"`);
581
778
  }
582
779
  if (typeof platform.automatable !== 'boolean') {
583
780
  throw new Error(`platform registry: ${label} automatable must be boolean`);
584
781
  }
585
- if (typeof platform.isolationEnv !== 'function') {
782
+ if (platform.installMethod !== 'foundation-host-verification'
783
+ && typeof platform.isolationEnv !== 'function') {
586
784
  throw new Error(`platform registry: ${label} isolationEnv must be a function`);
587
785
  }
588
786
  if (!VALID_SOURCE_FORMS.has(platform.marketplaceSourceForm)) {
@@ -603,6 +801,9 @@ export function assertRegistry(registry = PLATFORMS) {
603
801
  if (!platform.buildAdapter || typeof platform.buildAdapter !== 'object') {
604
802
  throw new Error(`platform registry: ${label} buildAdapter must be an object`);
605
803
  }
804
+ if (typeof platform.buildAdapter.enabled !== 'boolean') {
805
+ throw new Error(`platform registry: ${label} buildAdapter.enabled must be boolean`);
806
+ }
606
807
  // D6: the adapter directory name is always explicit — prepare's G4
607
808
  // declared-host reconciliation and the build producer both key on it.
608
809
  if (typeof platform.buildAdapter.name !== 'string' || platform.buildAdapter.name.length === 0) {
@@ -649,7 +850,11 @@ export function assertRegistry(registry = PLATFORMS) {
649
850
  throw new Error(`platform registry: ${label} has illegal degradationPolicy "${platform.degradationPolicy}"`);
650
851
  }
651
852
 
652
- if (platform.automatable) {
853
+ if (platform.installMethod === 'foundation-host-verification') {
854
+ if (platform.cli !== null) {
855
+ throw new Error(`platform registry: ${label} Foundation host verification must have cli === null`);
856
+ }
857
+ } else if (platform.automatable) {
653
858
  if (!platform.cli || typeof platform.cli.marketplaceAdd !== 'function'
654
859
  || typeof platform.cli.install !== 'function' || typeof platform.cli.list !== 'function') {
655
860
  throw new Error(`platform registry: automatable platform ${label} needs cli template functions`);
@@ -690,7 +895,8 @@ export function assertRegistry(registry = PLATFORMS) {
690
895
 
691
896
  // --- capability contract consistency rules (能力契约一致性规则) -----------
692
897
  // automatable === true 必须有 installMethod === 'structured-cli'
693
- if (platform.automatable === true && platform.installMethod !== 'structured-cli') {
898
+ if (platform.automatable === true
899
+ && !['structured-cli', 'foundation-host-verification'].includes(platform.installMethod)) {
694
900
  throw new Error(`platform registry: ${label} is automatable but installMethod is "${platform.installMethod}" (expected "structured-cli")`);
695
901
  }
696
902
  // automatable === false 必须有 installMethod !== 'structured-cli'
@@ -728,6 +934,9 @@ export function resolvePlatformRoute(platform) {
728
934
  if (installMethod === 'interactive-only' || installMethod === 'human-attestation') {
729
935
  return { route: 'human-attestation', reason: `installMethod is ${installMethod}` };
730
936
  }
937
+ if (installMethod === 'foundation-host-verification') {
938
+ return { route: 'host-verification', reason: 'installMethod is foundation-host-verification' };
939
+ }
731
940
  throw new Error(
732
941
  `platform "${platform?.id ?? '<unknown>'}" with installMethod="${installMethod}" cannot be routed`,
733
942
  );
@@ -745,7 +954,7 @@ export function resolveCapabilityConflicts(platform) {
745
954
  const { id, automatable, installMethod, refStrength, identityEvidence, cli, strategy } = platform;
746
955
 
747
956
  // automatable <-> installMethod 一致性
748
- if (automatable === true && installMethod !== 'structured-cli') {
957
+ if (automatable === true && !['structured-cli', 'foundation-host-verification'].includes(installMethod)) {
749
958
  conflicts.push(`automatable=true but installMethod="${installMethod}"`);
750
959
  }
751
960
  if (automatable === false && installMethod === 'structured-cli') {
@@ -763,7 +972,7 @@ export function resolveCapabilityConflicts(platform) {
763
972
  }
764
973
 
765
974
  // 自动化平台必须有 cli 和策略解析函数
766
- if (automatable === true) {
975
+ if (automatable === true && installMethod !== 'foundation-host-verification') {
767
976
  if (!cli || typeof cli !== 'object') {
768
977
  conflicts.push(`automatable=true but cli is missing`);
769
978
  }