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,467 @@
1
+ /**
2
+ * Pure, offline verification of caller-supplied release records.
3
+ *
4
+ * This module never discovers records or performs I/O. The CLI layer supplies
5
+ * the exact bytes and source labels selected by the caller.
6
+ */
7
+
8
+ import { digestBytes } from 'skill-family-harness-node';
9
+
10
+ import {
11
+ computeApprovalDigest,
12
+ validateApproval,
13
+ validateApprovalRecordSchema,
14
+ validateApprovalTimeWindow,
15
+ } from '../core/approval.mjs';
16
+ import { isMarketplaceAction, isRemoteWriteAction } from '../core/checkpoints.mjs';
17
+ import { computePlanDigest, validatePlan } from '../core/plan.mjs';
18
+ import {
19
+ computeRunDigest,
20
+ validateRun,
21
+ validateRunCheckpointMapping,
22
+ validateRunPlanDigest,
23
+ validateSourceRunEdge,
24
+ } from '../core/run.mjs';
25
+
26
+ export const VERIFY_RECORDS_EXIT_CODES = Object.freeze({
27
+ CONSISTENT: 0,
28
+ CONTRADICTED: 1,
29
+ INSUFFICIENT: 2,
30
+ });
31
+
32
+ const SUPPORTED_PLAN_VERSIONS = new Set([1, 2, 3]);
33
+ const SUPPORTED_RUN_COMMANDS = new Set(['publish', 'reconcile', 'verify']);
34
+ const SUPPORTED_TERMINAL_STATUSES = new Set(['PARTIAL', 'PUBLISHED', 'VERIFIED']);
35
+ const FINDING_ORDER = Object.freeze([
36
+ 'INPUT_MISSING',
37
+ 'INPUT_DAMAGED',
38
+ 'FORMAT_UNSUPPORTED',
39
+ 'PLAN_DIGEST_MISMATCH',
40
+ 'APPROVAL_DIGEST_MISMATCH',
41
+ 'RUN_DIGEST_MISMATCH',
42
+ 'IDENTITY_MISMATCH',
43
+ 'PLAN_BINDING_MISMATCH',
44
+ 'APPROVAL_ACTION_MISMATCH',
45
+ 'RUN_LINEAGE_MISMATCH',
46
+ 'TRANSITION_MISMATCH',
47
+ 'CHECKPOINT_MISMATCH',
48
+ 'HISTORICAL_TIME_MISSING',
49
+ 'HISTORICAL_TIME_OUTSIDE_WINDOW',
50
+ ]);
51
+ const FINDING_RANK = new Map(FINDING_ORDER.map((code, index) => [code, index]));
52
+
53
+ function sourceLabel(source) {
54
+ if (typeof source !== 'string' || source.length === 0) return null;
55
+ return source.replaceAll('\\', '/').split('/').filter(Boolean).at(-1) ?? null;
56
+ }
57
+
58
+ function parseInput(input, role, addFinding) {
59
+ const summary = { role, source: sourceLabel(input?.source) };
60
+ if (!input || input.bytes === undefined || input.bytes === null) {
61
+ addFinding('INPUT_MISSING', role, `required ${role} input was not provided`, 'INSUFFICIENT');
62
+ return { summary, digest: null, document: null, bytes: null, usable: false };
63
+ }
64
+
65
+ let bytes;
66
+ try {
67
+ bytes = Buffer.isBuffer(input.bytes)
68
+ ? Buffer.from(input.bytes)
69
+ : Buffer.from(input.bytes);
70
+ } catch {
71
+ addFinding('INPUT_DAMAGED', role, `${role} input is not byte-compatible`);
72
+ return { summary, digest: null, document: null, bytes: null, usable: false };
73
+ }
74
+
75
+ const bytesSha256 = digestBytes(bytes);
76
+ try {
77
+ const document = JSON.parse(bytes.toString('utf8'));
78
+ if (!document || typeof document !== 'object' || Array.isArray(document)) {
79
+ addFinding('INPUT_DAMAGED', role, `${role} input must be a JSON object`);
80
+ return {
81
+ summary,
82
+ digest: { bytesSha256, carriedDomainDigest: null, recomputedDomainDigest: null },
83
+ document: null,
84
+ bytes,
85
+ usable: false,
86
+ };
87
+ }
88
+ return {
89
+ summary,
90
+ digest: { bytesSha256, carriedDomainDigest: null, recomputedDomainDigest: null },
91
+ document,
92
+ bytes,
93
+ usable: true,
94
+ };
95
+ } catch {
96
+ addFinding('INPUT_DAMAGED', role, `${role} input is not valid JSON`);
97
+ return {
98
+ summary,
99
+ digest: { bytesSha256, carriedDomainDigest: null, recomputedDomainDigest: null },
100
+ document: null,
101
+ bytes,
102
+ usable: false,
103
+ };
104
+ }
105
+ }
106
+
107
+ function sameStringSet(left, right) {
108
+ return JSON.stringify([...new Set(left)].sort()) === JSON.stringify([...new Set(right)].sort());
109
+ }
110
+
111
+ function commandStatusIsValid(run) {
112
+ if (run.command === 'publish' || run.command === 'reconcile') {
113
+ return run.status === 'PARTIAL' || run.status === 'PUBLISHED';
114
+ }
115
+ return run.command === 'verify' && run.status === 'VERIFIED';
116
+ }
117
+
118
+ function checkpointStatusIsValid(run) {
119
+ if (run.status === 'VERIFIED') {
120
+ return run.checkpoints.every((checkpoint) => ['succeeded', 'skipped'].includes(checkpoint.status));
121
+ }
122
+ if (run.status === 'PUBLISHED') {
123
+ return run.checkpoints.every((checkpoint) => (
124
+ isRemoteWriteAction(checkpoint.actionType)
125
+ ? ['succeeded', 'skipped'].includes(checkpoint.status)
126
+ : isMarketplaceAction(checkpoint.actionType)
127
+ ? ['succeeded', 'skipped', 'deferred', 'failed'].includes(checkpoint.status)
128
+ : true
129
+ ));
130
+ }
131
+ if (run.status === 'PARTIAL') {
132
+ return run.checkpoints.some((checkpoint) => !['succeeded', 'skipped', 'deferred'].includes(checkpoint.status));
133
+ }
134
+ return false;
135
+ }
136
+
137
+ /**
138
+ * Verify one explicitly supplied record set without filesystem, network, or
139
+ * process access.
140
+ *
141
+ * @param {object} request
142
+ * @param {{bytes: Buffer|string, source?: string}} request.plan
143
+ * @param {{bytes: Buffer|string, source?: string}} request.approval
144
+ * @param {{bytes: Buffer|string, source?: string}} request.targetRun
145
+ * @param {Array<{bytes: Buffer|string, source?: string}>} [request.sourceRuns]
146
+ * @param {string} request.unitId
147
+ * @param {string} request.targetVersion
148
+ */
149
+ export function verifyReleaseRecords(request = {}) {
150
+ const findings = [];
151
+ const addFinding = (code, role, message, outcome = 'CONTRADICTED') => {
152
+ findings.push({ code, role, message, _outcome: outcome });
153
+ };
154
+
155
+ const planInput = parseInput(request.plan, 'plan', addFinding);
156
+ const approvalInput = parseInput(request.approval, 'approval', addFinding);
157
+ const targetInput = parseInput(request.targetRun, 'targetRun', addFinding);
158
+ const sourceInputs = Array.isArray(request.sourceRuns)
159
+ ? request.sourceRuns.map((input, index) => parseInput(input, `sourceRun[${index}]`, addFinding))
160
+ : [];
161
+
162
+ const plan = planInput.document;
163
+ const approval = approvalInput.document;
164
+ const targetRun = targetInput.document;
165
+
166
+ let planSupported = false;
167
+ if (planInput.usable) {
168
+ if (!SUPPORTED_PLAN_VERSIONS.has(plan?.planVersion)) {
169
+ addFinding('FORMAT_UNSUPPORTED', 'plan', `unsupported release plan version: ${String(plan?.planVersion)}`, 'INSUFFICIENT');
170
+ } else {
171
+ planSupported = true;
172
+ try {
173
+ validatePlan(plan);
174
+ } catch (error) {
175
+ addFinding('INPUT_DAMAGED', 'plan', error.message);
176
+ planSupported = false;
177
+ }
178
+ const recomputed = computePlanDigest(plan);
179
+ planInput.digest.carriedDomainDigest = plan?.digest ?? null;
180
+ planInput.digest.recomputedDomainDigest = recomputed;
181
+ if (!plan?.digest || plan.digest !== recomputed) {
182
+ addFinding('PLAN_DIGEST_MISMATCH', 'plan', 'plan digest does not match its binding content');
183
+ }
184
+ }
185
+ }
186
+
187
+ let approvalSupported = false;
188
+ let approvalDigest = null;
189
+ if (approvalInput.usable) {
190
+ approvalDigest = computeApprovalDigest(approvalInput.bytes);
191
+ approvalInput.digest.recomputedDomainDigest = approvalDigest;
192
+ try {
193
+ validateApprovalRecordSchema(approval);
194
+ approvalSupported = true;
195
+ } catch (error) {
196
+ addFinding('INPUT_DAMAGED', 'approval', error.message);
197
+ }
198
+ if (approvalSupported) {
199
+ try {
200
+ validateApprovalTimeWindow(approval, {
201
+ clock: () => approval.approvedAt,
202
+ requireUnexpired: false,
203
+ });
204
+ } catch (error) {
205
+ addFinding('INPUT_DAMAGED', 'approval', error.message);
206
+ approvalSupported = false;
207
+ }
208
+ }
209
+ }
210
+
211
+ const runEntries = [
212
+ { input: targetInput, role: 'targetRun', isTarget: true },
213
+ ...sourceInputs.map((input, index) => ({ input, role: `sourceRun[${index}]`, isTarget: false })),
214
+ ];
215
+ const usableRuns = [];
216
+ let trustedTargetTerminalStatus = null;
217
+ for (const entry of runEntries) {
218
+ const run = entry.input.document;
219
+ if (!entry.input.usable) continue;
220
+ entry.input.digest.carriedDomainDigest = run?.runDigest ?? null;
221
+ entry.input.digest.recomputedDomainDigest = computeRunDigest(run);
222
+
223
+ if (!SUPPORTED_RUN_COMMANDS.has(run?.command) || !SUPPORTED_TERMINAL_STATUSES.has(run?.status)) {
224
+ addFinding(
225
+ 'FORMAT_UNSUPPORTED',
226
+ entry.role,
227
+ `unsupported release run command/status: ${String(run?.command)}/${String(run?.status)}`,
228
+ 'INSUFFICIENT',
229
+ );
230
+ continue;
231
+ }
232
+
233
+ const { runDigest: _runDigest, ...unsignedRun } = run;
234
+ try {
235
+ validateRun(unsignedRun);
236
+ } catch (error) {
237
+ addFinding('INPUT_DAMAGED', entry.role, error.message);
238
+ continue;
239
+ }
240
+
241
+ const digestMatches = Boolean(run.runDigest)
242
+ && run.runDigest === entry.input.digest.recomputedDomainDigest;
243
+ const transitionIsValid = commandStatusIsValid(run);
244
+ const terminalCheckpointsAreValid = checkpointStatusIsValid(run);
245
+ if (!digestMatches) {
246
+ addFinding('RUN_DIGEST_MISMATCH', entry.role, 'run digest does not match its content');
247
+ }
248
+ if (!transitionIsValid) {
249
+ addFinding('TRANSITION_MISMATCH', entry.role, `run command ${run.command} cannot terminate as ${run.status}`);
250
+ }
251
+ if (!terminalCheckpointsAreValid) {
252
+ addFinding('CHECKPOINT_MISMATCH', entry.role, `checkpoint results do not support terminal status ${run.status}`);
253
+ }
254
+ if (entry.isTarget && digestMatches && transitionIsValid && terminalCheckpointsAreValid) {
255
+ trustedTargetTerminalStatus = run.status;
256
+ }
257
+ usableRuns.push({ ...entry, run });
258
+ }
259
+
260
+ if (planSupported && typeof request.unitId === 'string' && typeof request.targetVersion === 'string') {
261
+ const expectedUnit = (plan.units ?? []).find((unit) => unit.id === request.unitId);
262
+ if (!expectedUnit || expectedUnit.targetVersion !== request.targetVersion) {
263
+ addFinding('IDENTITY_MISMATCH', 'plan', 'expected release unit and version do not match the plan');
264
+ }
265
+ } else if (typeof request.unitId !== 'string' || typeof request.targetVersion !== 'string') {
266
+ addFinding('INPUT_MISSING', 'identity', 'unitId and targetVersion are required', 'INSUFFICIENT');
267
+ }
268
+
269
+ if (planSupported && approvalSupported) {
270
+ const planDigest = computePlanDigest(plan);
271
+ if (approval.planDigest !== planDigest) {
272
+ addFinding('PLAN_BINDING_MISMATCH', 'approval', 'approval planDigest does not match the supplied plan');
273
+ }
274
+
275
+ const expectedUnitVersions = Object.fromEntries((plan.units ?? []).map((unit) => [unit.id, unit.targetVersion]));
276
+ const approvedUnitVersions = approval.unitVersions
277
+ ?? ((plan.units ?? []).length === 1 ? { [plan.units[0].id]: approval.targetVersion } : {});
278
+ const identityMatches = sameStringSet(Object.keys(expectedUnitVersions), Object.keys(approvedUnitVersions))
279
+ && Object.entries(expectedUnitVersions).every(([unitId, version]) => approvedUnitVersions[unitId] === version)
280
+ && (approval.targetVersion === undefined
281
+ || new Set(Object.values(expectedUnitVersions)).size !== 1
282
+ || approval.targetVersion === Object.values(expectedUnitVersions)[0]);
283
+ if (!identityMatches) {
284
+ addFinding('IDENTITY_MISMATCH', 'approval', 'approval unit/version identity does not match the plan');
285
+ }
286
+
287
+ const planActions = (plan.externalActions ?? []).map((action) => action.id);
288
+ if (!sameStringSet(approval.approvedActions ?? [], planActions)) {
289
+ addFinding('APPROVAL_ACTION_MISMATCH', 'approval', 'approved actions do not exactly match the plan actions');
290
+ }
291
+
292
+ try {
293
+ validateApproval(plan, approval, {
294
+ clock: () => approval.approvedAt,
295
+ requireUnexpired: false,
296
+ });
297
+ } catch (error) {
298
+ const alreadyRepresented = (
299
+ (/planDigest/i.test(error.message)
300
+ && findings.some((finding) => finding.role === 'approval' && finding.code === 'PLAN_BINDING_MISMATCH'))
301
+ || (/version|unitVersions/i.test(error.message)
302
+ && findings.some((finding) => finding.role === 'approval' && finding.code === 'IDENTITY_MISMATCH'))
303
+ || (/approved|action/i.test(error.message)
304
+ && findings.some((finding) => finding.role === 'approval' && finding.code === 'APPROVAL_ACTION_MISMATCH'))
305
+ );
306
+ if (!alreadyRepresented) {
307
+ addFinding('INPUT_DAMAGED', 'approval', error.message);
308
+ }
309
+ }
310
+ }
311
+
312
+ if (planSupported) {
313
+ for (const entry of usableRuns) {
314
+ try {
315
+ validateRunPlanDigest(entry.run, plan);
316
+ } catch (error) {
317
+ addFinding('PLAN_BINDING_MISMATCH', entry.role, error.message);
318
+ }
319
+ try {
320
+ validateRunCheckpointMapping(entry.run, plan.externalActions ?? []);
321
+ } catch (error) {
322
+ addFinding('CHECKPOINT_MISMATCH', entry.role, error.message);
323
+ }
324
+ }
325
+ }
326
+
327
+ if (approvalDigest) {
328
+ for (const entry of usableRuns) {
329
+ if (!entry.run.approvalDigest) {
330
+ addFinding('INPUT_MISSING', entry.role, 'run does not carry the approval digest needed to bind the supplied approval', 'INSUFFICIENT');
331
+ } else if (entry.run.approvalDigest !== approvalDigest) {
332
+ addFinding('APPROVAL_DIGEST_MISMATCH', entry.role, 'run approvalDigest does not match the supplied approval bytes');
333
+ }
334
+ }
335
+ }
336
+
337
+ const supportingRuns = usableRuns.filter((entry) => !entry.isTarget);
338
+ const chain = [];
339
+ let lineageComplete = false;
340
+ if (targetRun && usableRuns.some((entry) => entry.isTarget)) {
341
+ let current = usableRuns.find((entry) => entry.isTarget);
342
+ const visited = new Set();
343
+ for (let depth = 0; depth <= 16 && current; depth += 1) {
344
+ chain.push(current.run);
345
+ const visitKey = `${current.run.runId}:${current.run.runDigest}`;
346
+ if (visited.has(visitKey)) {
347
+ addFinding('RUN_LINEAGE_MISMATCH', current.role, 'release run lineage contains a cycle');
348
+ break;
349
+ }
350
+ visited.add(visitKey);
351
+
352
+ if (current.run.command === 'publish') {
353
+ lineageComplete = true;
354
+ break;
355
+ }
356
+ if (!current.run.sourceRunId || !current.run.sourceRunDigest || !current.run.sourceRunPath) {
357
+ addFinding('INPUT_MISSING', current.role, 'run is missing complete source-run lineage fields', 'INSUFFICIENT');
358
+ break;
359
+ }
360
+ const exactParent = supportingRuns.find((candidate) => (
361
+ candidate.run.runId === current.run.sourceRunId
362
+ && candidate.run.runDigest === current.run.sourceRunDigest
363
+ ));
364
+ if (!exactParent) {
365
+ const sameId = supportingRuns.find((candidate) => candidate.run.runId === current.run.sourceRunId);
366
+ if (sameId) {
367
+ addFinding('RUN_LINEAGE_MISMATCH', current.role, 'source run id is present but its digest does not match');
368
+ } else {
369
+ addFinding('INPUT_MISSING', current.role, 'explicit source run required by lineage was not supplied', 'INSUFFICIENT');
370
+ }
371
+ break;
372
+ }
373
+ try {
374
+ validateSourceRunEdge(current.run, exactParent.run);
375
+ } catch (error) {
376
+ addFinding('TRANSITION_MISMATCH', current.role, error.message);
377
+ break;
378
+ }
379
+ current = exactParent;
380
+ }
381
+ if (!lineageComplete && chain.length > 16) {
382
+ addFinding('RUN_LINEAGE_MISMATCH', 'targetRun', 'release run lineage exceeds maximum depth');
383
+ }
384
+ }
385
+
386
+ for (const entry of usableRuns) {
387
+ const run = entry.run;
388
+ if (run.stateSequence === undefined) {
389
+ if (run.previousStateDigest !== undefined) {
390
+ addFinding('RUN_LINEAGE_MISMATCH', entry.role, 'non-state run claims a previous state digest');
391
+ }
392
+ continue;
393
+ }
394
+ if (run.stateSequence === 0) {
395
+ if (run.previousStateDigest !== undefined) {
396
+ addFinding('RUN_LINEAGE_MISMATCH', entry.role, 'initial state run claims a previous state digest');
397
+ }
398
+ continue;
399
+ }
400
+ const predecessor = supportingRuns.find((candidate) => (
401
+ candidate.run.runId === run.runId
402
+ && candidate.run.stateSequence === run.stateSequence - 1
403
+ ));
404
+ if (!predecessor) {
405
+ addFinding('INPUT_MISSING', entry.role, 'explicit predecessor state snapshot was not supplied', 'INSUFFICIENT');
406
+ } else if (
407
+ predecessor.run.runDigest !== run.previousStateDigest
408
+ || predecessor.run.command !== run.command
409
+ || predecessor.run.planDigest !== run.planDigest
410
+ ) {
411
+ addFinding('RUN_LINEAGE_MISMATCH', entry.role, 'state predecessor identity or digest does not match');
412
+ }
413
+ }
414
+
415
+ if (approvalSupported) {
416
+ const executionRun = [...chain].reverse().find((run) => (
417
+ ['publish', 'reconcile'].includes(run.command)
418
+ && (run.checkpoints ?? []).some((checkpoint) => isRemoteWriteAction(checkpoint.actionType))
419
+ ));
420
+ if (!lineageComplete || !executionRun?.startedAt || !executionRun?.finishedAt) {
421
+ addFinding('HISTORICAL_TIME_MISSING', 'approval', 'historical publish execution interval cannot be proven', 'INSUFFICIENT');
422
+ } else {
423
+ const approvedAt = Date.parse(approval.approvedAt);
424
+ const expiresAt = Date.parse(approval.expiresAt);
425
+ const startedAt = Date.parse(executionRun.startedAt);
426
+ const finishedAt = Date.parse(executionRun.finishedAt);
427
+ if (
428
+ !Number.isFinite(startedAt)
429
+ || !Number.isFinite(finishedAt)
430
+ || startedAt < approvedAt
431
+ || finishedAt > expiresAt
432
+ || finishedAt < startedAt
433
+ ) {
434
+ addFinding('HISTORICAL_TIME_OUTSIDE_WINDOW', 'approval', 'publish execution interval is outside the approval window');
435
+ }
436
+ }
437
+ }
438
+
439
+ findings.sort((left, right) => (
440
+ (FINDING_RANK.get(left.code) ?? 999) - (FINDING_RANK.get(right.code) ?? 999)
441
+ || left.role.localeCompare(right.role)
442
+ || left.message.localeCompare(right.message)
443
+ ));
444
+ const hasContradiction = findings.some((finding) => finding._outcome === 'CONTRADICTED');
445
+ const hasInsufficient = findings.some((finding) => finding._outcome === 'INSUFFICIENT');
446
+ const status = hasContradiction ? 'CONTRADICTED' : hasInsufficient ? 'INSUFFICIENT' : 'CONSISTENT';
447
+
448
+ return {
449
+ status,
450
+ unitId: typeof request.unitId === 'string' ? request.unitId : null,
451
+ targetVersion: typeof request.targetVersion === 'string' ? request.targetVersion : null,
452
+ historicalTerminalStatus: trustedTargetTerminalStatus,
453
+ inputs: {
454
+ plan: planInput.summary,
455
+ approval: approvalInput.summary,
456
+ targetRun: targetInput.summary,
457
+ sourceRuns: sourceInputs.map((input) => input.summary),
458
+ },
459
+ digests: {
460
+ plan: planInput.digest,
461
+ approval: approvalInput.digest,
462
+ targetRun: targetInput.digest,
463
+ sourceRuns: sourceInputs.map((input) => input.digest),
464
+ },
465
+ findings: findings.map(({ _outcome, ...finding }) => finding),
466
+ };
467
+ }
@@ -72,6 +72,7 @@ import {
72
72
  isFoundationPluginVerificationEligible,
73
73
  verifyFrozenPluginWithFoundation,
74
74
  } from '../core/foundation-plugin-verification.mjs';
75
+ import { verifyFrozenCursorSkillWithFoundation } from '../core/foundation-host-verification.mjs';
75
76
  import { resolveUnitScopedPath } from '../snapshot/public-path.mjs';
76
77
  import { canonicalJson } from '../core/digest.mjs';
77
78
  import {
@@ -130,6 +131,53 @@ export const VERIFICATION_RESOLVED_TYPES = Object.freeze({
130
131
  NOT_REQUIRED_UNCHANGED: 'NOT_REQUIRED_UNCHANGED',
131
132
  });
132
133
 
134
+ /** Verify actionless Cursor distributions through their frozen host contract. */
135
+ export async function verifyCursorHostDistributions({
136
+ plan,
137
+ root,
138
+ cursorHostRuntime,
139
+ runHostVerificationFn,
140
+ clock = defaultClock,
141
+ evidence,
142
+ } = {}) {
143
+ const checks = [];
144
+ for (const unit of plan?.units ?? []) {
145
+ const cursorDistribution = (unit.distributions ?? []).find(
146
+ (distribution) => distribution.type === 'cursor-plugin',
147
+ );
148
+ if (!cursorDistribution) continue;
149
+ const result = await verifyFrozenCursorSkillWithFoundation({
150
+ plan,
151
+ unitId: unit.id,
152
+ root,
153
+ cursorHostRuntime,
154
+ ...(runHostVerificationFn ? { runHostVerificationFn } : {}),
155
+ clock,
156
+ });
157
+ checks.push({
158
+ actionId: `cursor-host-verification-${unit.id}`,
159
+ actionType: 'cursor-host-verification',
160
+ unitId: unit.id,
161
+ distributionType: cursorDistribution.type,
162
+ status: VERIFICATION_RESOLVED_TYPES.PASSED_AUTOMATIC,
163
+ observation: result,
164
+ });
165
+ await evidence?.append({
166
+ phase: 'verify-host',
167
+ unitId: unit.id,
168
+ distributionType: cursorDistribution.type,
169
+ status: VERIFICATION_RESOLVED_TYPES.PASSED_AUTOMATIC,
170
+ hostId: result.hostId,
171
+ driverId: result.driverId,
172
+ requestDigest: result.requestDigest,
173
+ payloadDigest: result.payloadDigest,
174
+ entrySkill: result.entrySkill,
175
+ observation: result,
176
+ });
177
+ }
178
+ return checks;
179
+ }
180
+
133
181
  /** Re-read every frozen subject tarball before consuming the public receipt. */
134
182
  export async function verifyPublicSourceAuthorityReceiptOffline({ plan, root }) {
135
183
  const descriptor = plan.publicSourceAuthorityReceipt;
@@ -179,6 +227,7 @@ const ADAPTER_ACTION_TYPE_MAP = {
179
227
  'codex-marketplace-install': 'codex-marketplace-install',
180
228
  'kimi-marketplace-install': 'kimi-marketplace-install',
181
229
  'codebuddy-marketplace-install': 'codebuddy-marketplace-install',
230
+ 'qoder-marketplace-install': 'qoder-marketplace-install',
182
231
  };
183
232
 
184
233
  // ---------------------------------------------------------------------------
@@ -349,6 +398,7 @@ async function collectMissingManualAttestations({
349
398
  const manual = actions.filter((action) => (
350
399
  action.type === 'kimi-marketplace-install'
351
400
  || action.type === 'codebuddy-marketplace-install'
401
+ || action.type === 'qoder-marketplace-install'
352
402
  ));
353
403
  if (manual.length === 0) return [];
354
404
 
@@ -1097,6 +1147,8 @@ export async function verifyRelease(options) {
1097
1147
  execFn,
1098
1148
  configPath: configPathOpt,
1099
1149
  runPluginVerificationFn,
1150
+ runHostVerificationFn,
1151
+ cursorHostRuntime,
1100
1152
  observeFirstReleaseMarketplaceHeadFn,
1101
1153
  fetchFirstReleaseMarketplaceIndexFn,
1102
1154
  } = options ?? {};
@@ -1576,6 +1628,20 @@ export async function verifyRelease(options) {
1576
1628
  const manualFollowUps = [];
1577
1629
  const foundationPluginVerificationReceipts = [];
1578
1630
 
1631
+ // Cursor has no marketplace action or publish checkpoint. Verify each
1632
+ // declared Cursor distribution directly from its frozen unit contract,
1633
+ // using explicit runtime roots that never enter the release run record.
1634
+ // Plans without Cursor distributions do not enter
1635
+ // this branch and retain their existing action-only behavior.
1636
+ adapterChecks.push(...await verifyCursorHostDistributions({
1637
+ plan,
1638
+ root,
1639
+ cursorHostRuntime,
1640
+ runHostVerificationFn,
1641
+ clock: clockFn,
1642
+ evidence,
1643
+ }));
1644
+
1579
1645
  // Every action is identity-bound and adapters receive read-only or
1580
1646
  // per-action isolated consumer paths. Run independent checks concurrently;
1581
1647
  // the evidence writer serializes append operations and result arrays are
@@ -1710,6 +1776,7 @@ export async function verifyRelease(options) {
1710
1776
  'codex-marketplace-install': 'codex-plugin',
1711
1777
  'kimi-marketplace-install': 'kimi-plugin',
1712
1778
  'codebuddy-marketplace-install': 'codebuddy-plugin',
1779
+ 'qoder-marketplace-install': 'qoder-plugin',
1713
1780
  };
1714
1781
  const dist = unit?.distributions?.find((d) => d.type === typeToDist[action.type]);
1715
1782
 
@@ -1896,6 +1963,8 @@ export async function verifyRelease(options) {
1896
1963
  ? 'codex-plugin'
1897
1964
  : action.type === 'codebuddy-marketplace-install'
1898
1965
  ? 'codebuddy-plugin'
1966
+ : action.type === 'qoder-marketplace-install'
1967
+ ? 'qoder-plugin'
1899
1968
  : 'kimi-plugin';
1900
1969
  const installPath = verifyResult.observation?.installPath;
1901
1970
  consumerGateResults.push(...await runConsumerVerificationGates({
@@ -1919,6 +1988,10 @@ export async function verifyRelease(options) {
1919
1988
  ? {
1920
1989
  HOME: resolve(runDir, 'consumers', `codebuddy-${action.parameters.plugin}`),
1921
1990
  }
1991
+ : action.type === 'qoder-marketplace-install'
1992
+ ? {
1993
+ HOME: resolve(runDir, 'consumers', `qoder-${action.parameters.plugin}`),
1994
+ }
1922
1995
  : {
1923
1996
  HOME: resolve(runDir, 'consumers', `kimi-${action.parameters.plugin}`),
1924
1997
  },
@@ -34,6 +34,7 @@ export const CHECKPOINT_ORDER = [
34
34
  'codex-marketplace-install',
35
35
  'kimi-marketplace-install',
36
36
  'codebuddy-marketplace-install',
37
+ 'qoder-marketplace-install',
37
38
  ];
38
39
 
39
40
  /**
@@ -54,6 +55,7 @@ export const ADAPTER_ACTION_TYPE_MAP = {
54
55
  'codex-marketplace-install': 'codex-marketplace-install',
55
56
  'kimi-marketplace-install': 'kimi-marketplace-install',
56
57
  'codebuddy-marketplace-install': 'codebuddy-marketplace-install',
58
+ 'qoder-marketplace-install': 'qoder-marketplace-install',
57
59
  };
58
60
 
59
61
  /**
@@ -68,7 +70,7 @@ export const ADAPTER_ACTION_TYPE_MAP = {
68
70
  * placed in Tier 1 only for conservative scheduling.
69
71
  * - Tier 2 `github-release` depends on Tier 1 `create-tag` (release `--verify-tag`).
70
72
  *
71
- * Marketplace actions (claude/codex/kimi/codebuddy-marketplace-install) are
73
+ * Marketplace actions (claude/codex/kimi/codebuddy/qoder-marketplace-install) are
72
74
  * included in the tier table for ADAPTER_ACTION_TYPE_MAP lookup but are
73
75
  * filtered out before tier grouping in both publish and reconcile. They are
74
76
  * recorded as DEFERRED with CONSUMER_VERIFICATION_DEFERRED reason and never
@@ -82,7 +84,7 @@ export const TIER_TABLE = [
82
84
  ['push-commit', 'push-snapshot'], // Tier 0
83
85
  ['set-default-branch', 'create-tag', 'npm-publish'], // Tier 1
84
86
  ['github-release', 'claude-marketplace-install', 'codex-marketplace-install'], // Tier 2
85
- ['kimi-marketplace-install', 'codebuddy-marketplace-install'], // Tier 3
87
+ ['kimi-marketplace-install', 'codebuddy-marketplace-install', 'qoder-marketplace-install'], // Tier 3
86
88
  ];
87
89
 
88
90
  /** Fast reverse lookup: action type -> tier index (-1 when unknown). */
@@ -170,6 +172,7 @@ export const MARKETPLACE_ACTION_TYPES = new Set([
170
172
  'codex-marketplace-install',
171
173
  'kimi-marketplace-install',
172
174
  'codebuddy-marketplace-install',
175
+ 'qoder-marketplace-install',
173
176
  ]);
174
177
 
175
178
  /**
@@ -401,7 +401,7 @@ export async function loadProjectConfig({ root, configPath } = {}) {
401
401
  for (const unit of config.releaseUnits) {
402
402
  if (!unit?.distributions) continue;
403
403
  for (const dist of unit.distributions) {
404
- if (dist.type === 'npm') continue;
404
+ if (dist.type === 'npm' || dist.type === 'cursor-plugin') continue;
405
405
  if (dist.marketplaceSourceType === undefined || dist.marketplaceSourceType === null) {
406
406
  dist.marketplaceSourceType = dist.marketplaceRepo ? 'standalone-index' : 'bundled-family';
407
407
  }