release-skill 0.9.17 → 0.9.19

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 (266) 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 +1 -1
  7. package/CHANGELOG.md +70 -2
  8. package/INSTALL.md +66 -9
  9. package/INSTALL.zh-CN.md +49 -8
  10. package/README.md +41 -20
  11. package/README.zh-CN.md +31 -19
  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 +4425 -1519
  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 +46 -7
  29. package/adapters/claude/skills/release-help/SKILL.md +47 -103
  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 +4425 -1519
  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 +46 -7
  49. package/adapters/codex/skills/release-help/SKILL.md +49 -105
  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 +152352 -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 +181 -0
  108. package/adapters/cursor/skills/release-help/SKILL.md +98 -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 +4425 -1519
  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 +46 -7
  178. package/adapters/kimi/skills/release-help/SKILL.md +49 -105
  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 +1 -1
  182. package/adapters/qoder/bin/consumer-contract-vectors.json +7 -7
  183. package/adapters/qoder/bin/error-codes.json +1 -1
  184. package/adapters/qoder/bin/foundation-resource-binding.json +1 -1
  185. package/adapters/qoder/bin/prebuild-manifest.json +8 -4
  186. package/adapters/qoder/bin/prebuilds/darwin-arm64/bound_read.darwin-arm64.node +0 -0
  187. package/adapters/qoder/bin/prebuilds/darwin-x64/bound_read.darwin-x64.node +0 -0
  188. package/adapters/qoder/bin/prebuilds/linux-arm64-gnu/bound_read.linux-arm64-gnu.node +0 -0
  189. package/adapters/qoder/bin/prebuilds/linux-x64-gnu/bound_read.linux-x64-gnu.node +0 -0
  190. package/adapters/qoder/bin/registry.json +1 -1
  191. package/adapters/qoder/bin/release-skill.bundle.mjs +4425 -1519
  192. package/adapters/qoder/bin/rules.json +1 -1
  193. package/adapters/qoder/data/hosts/cursor/host-descriptor.json +34 -0
  194. package/adapters/qoder/data/hosts/registry.json +1 -0
  195. package/adapters/qoder/schemas/release-plan.schema.json +255 -25
  196. package/adapters/qoder/schemas/release-project.schema.json +228 -26
  197. package/adapters/qoder/skills/release-finish/SKILL.md +46 -7
  198. package/adapters/qoder/skills/release-help/SKILL.md +49 -105
  199. package/adapters/qoder/skills/release-verify/SKILL.md +2 -2
  200. package/adapters/qoder/src/schemas/host-descriptor.schema.json +9 -2
  201. package/adapters/workbuddy/.codebuddy-plugin/plugin.json +1 -1
  202. package/adapters/workbuddy/bin/consumer-contract-vectors.json +7 -7
  203. package/adapters/workbuddy/bin/error-codes.json +1 -1
  204. package/adapters/workbuddy/bin/foundation-resource-binding.json +1 -1
  205. package/adapters/workbuddy/bin/prebuild-manifest.json +8 -4
  206. package/adapters/workbuddy/bin/prebuilds/darwin-arm64/bound_read.darwin-arm64.node +0 -0
  207. package/adapters/workbuddy/bin/prebuilds/darwin-x64/bound_read.darwin-x64.node +0 -0
  208. package/adapters/workbuddy/bin/prebuilds/linux-arm64-gnu/bound_read.linux-arm64-gnu.node +0 -0
  209. package/adapters/workbuddy/bin/prebuilds/linux-x64-gnu/bound_read.linux-x64-gnu.node +0 -0
  210. package/adapters/workbuddy/bin/registry.json +1 -1
  211. package/adapters/workbuddy/bin/release-skill.bundle.mjs +4425 -1519
  212. package/adapters/workbuddy/bin/rules.json +1 -1
  213. package/adapters/workbuddy/data/hosts/cursor/host-descriptor.json +34 -0
  214. package/adapters/workbuddy/data/hosts/registry.json +1 -0
  215. package/adapters/workbuddy/schemas/release-plan.schema.json +255 -25
  216. package/adapters/workbuddy/schemas/release-project.schema.json +228 -26
  217. package/adapters/workbuddy/skills/release-finish/SKILL.md +46 -7
  218. package/adapters/workbuddy/skills/release-help/SKILL.md +47 -103
  219. package/adapters/workbuddy/skills/release-verify/SKILL.md +2 -2
  220. package/adapters/workbuddy/src/schemas/host-descriptor.schema.json +9 -2
  221. package/bin/consumer-contract-vectors.json +7 -7
  222. package/bin/error-codes.json +1 -1
  223. package/bin/foundation-resource-binding.json +1 -1
  224. package/bin/prebuild-manifest.json +8 -4
  225. package/bin/prebuilds/darwin-arm64/bound_read.darwin-arm64.node +0 -0
  226. package/bin/prebuilds/darwin-x64/bound_read.darwin-x64.node +0 -0
  227. package/bin/prebuilds/linux-arm64-gnu/bound_read.linux-arm64-gnu.node +0 -0
  228. package/bin/prebuilds/linux-x64-gnu/bound_read.linux-x64-gnu.node +0 -0
  229. package/bin/registry.json +1 -1
  230. package/bin/release-skill-cli.mjs +115 -15
  231. package/bin/release-skill.bundle.mjs +4425 -1519
  232. package/bin/rules.json +1 -1
  233. package/data/hosts/cursor/host-descriptor.json +34 -0
  234. package/data/hosts/registry.json +1 -0
  235. package/package.json +7 -5
  236. package/platform-manifest.json +75 -9
  237. package/references/02-project-config.md +4 -0
  238. package/schemas/release-plan.schema.json +255 -25
  239. package/schemas/release-project.schema.json +228 -26
  240. package/scripts/sync-public-files.mjs +3 -22
  241. package/skills/release-finish/SKILL.md +46 -7
  242. package/skills/release-help/SKILL.md +47 -103
  243. package/skills/release-verify/SKILL.md +2 -2
  244. package/skills-src/release-finish/SKILL.md +46 -7
  245. package/skills-src/release-help/SKILL.md +47 -103
  246. package/skills-src/release-verify/SKILL.md +2 -2
  247. package/src/adapters/contract.mjs +1 -0
  248. package/src/adapters/plugin-marketplace.mjs +201 -9
  249. package/src/commands/post-release-finish.mjs +448 -0
  250. package/src/commands/post-release-local.mjs +312 -36
  251. package/src/commands/prepare.mjs +74 -9
  252. package/src/commands/publish.mjs +4 -1
  253. package/src/commands/ship.mjs +3 -0
  254. package/src/commands/verify.mjs +73 -0
  255. package/src/core/checkpoints.mjs +5 -2
  256. package/src/core/config.mjs +1 -1
  257. package/src/core/foundation-host-verification.mjs +168 -0
  258. package/src/core/plan.mjs +19 -1
  259. package/src/core/postpublish.mjs +9 -1
  260. package/src/core/run-retention.mjs +1 -1
  261. package/src/core/surface-host-bindings.mjs +1 -0
  262. package/src/core/verification-gates.mjs +1 -1
  263. package/src/platforms/registry.mjs +225 -16
  264. package/src/producers/build-adapters.mjs +21 -26
  265. package/src/producers/foundation-resource-projection.mjs +3 -3
  266. package/src/schemas/host-descriptor.schema.json +9 -2
@@ -16,6 +16,7 @@ import { execFile as execFileCb } from 'node:child_process';
16
16
  import { promisify } from 'node:util';
17
17
  import { readFile, stat, mkdir, readdir, realpath, lstat } from 'node:fs/promises';
18
18
  import { join, resolve, relative, isAbsolute, basename } from 'node:path';
19
+ import { resolveContained } from 'skill-family-harness-node';
19
20
 
20
21
  import {
21
22
  ActionType,
@@ -37,7 +38,13 @@ import {
37
38
  import { createHash } from 'node:crypto';
38
39
  import { createFilesystemRootBinding, observeFilesystemTree } from 'skill-family-harness-node';
39
40
  import { computeFrozenSnapshot, resolveFrozenPath } from '../snapshot/frozen.mjs';
40
- import { PLATFORMS, getPlatform, resolvePlatformRoute, resolveCapabilityConflicts } from '../platforms/registry.mjs';
41
+ import {
42
+ PLATFORMS,
43
+ getPlatform,
44
+ projectObservedStandaloneIndexInstallIdentity,
45
+ resolvePlatformRoute,
46
+ resolveCapabilityConflicts,
47
+ } from '../platforms/registry.mjs';
41
48
  import {
42
49
  KIMI_REQUIREMENT_FILE,
43
50
  KIMI_ATTESTATION_FILE,
@@ -895,8 +902,100 @@ const SUPPORTED_TYPES = [
895
902
  ActionType.CODEX_MARKETPLACE_INSTALL,
896
903
  ActionType.KIMI_MARKETPLACE_INSTALL,
897
904
  ActionType.CODEBUDDY_MARKETPLACE_INSTALL,
905
+ ActionType.QODER_MARKETPLACE_INSTALL,
898
906
  ];
899
907
 
908
+ async function runPlatformCli(exec, platform, args, options, selectedBinary = null) {
909
+ const candidates = selectedBinary
910
+ ? [selectedBinary]
911
+ : [platform.cli.binary, ...(platform.cli.binaryAliases ?? [])];
912
+ let lastError;
913
+ for (const command of candidates) {
914
+ try {
915
+ return { command, result: await exec(command, args, options) };
916
+ } catch (error) {
917
+ lastError = error;
918
+ if (error?.code !== 'ENOENT' || command === candidates.at(-1)) throw error;
919
+ }
920
+ }
921
+ throw lastError;
922
+ }
923
+
924
+ function normalizeGitRepository(value) {
925
+ const source = String(value ?? '').replace(/^git\+/u, '');
926
+ let host;
927
+ let pathname;
928
+ const scp = /^git@([^:]+):(.+)$/u.exec(source);
929
+ if (scp) {
930
+ [, host, pathname] = scp;
931
+ } else {
932
+ let parsed;
933
+ try {
934
+ parsed = new URL(source);
935
+ } catch {
936
+ return null;
937
+ }
938
+ if (!['https:', 'ssh:'].includes(parsed.protocol) || !parsed.hostname) return null;
939
+ // Only the standard HTTPS/SSH endpoints belong to this channel contract.
940
+ if (parsed.port && parsed.port !== (parsed.protocol === 'ssh:' ? '22' : '443')) return null;
941
+ host = parsed.hostname;
942
+ pathname = parsed.pathname.replace(/^\/+/, '');
943
+ }
944
+ const repository = pathname.replace(/\/+$/u, '').replace(/\.git$/u, '');
945
+ if (!/^[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$/iu.test(repository)) return null;
946
+ return `${host.toLowerCase()}/${repository}`;
947
+ }
948
+
949
+ async function observeQoderHubAfterAdd({ exec, platform, action, env, cwd, timeout, isolatedHome, command }) {
950
+ const listed = await runPlatformCli(exec, platform, platform.cli.marketplaceList(), {
951
+ env, cwd, timeout,
952
+ }, command);
953
+ let parsed;
954
+ try {
955
+ parsed = JSON.parse(listed.result.stdout);
956
+ } catch {
957
+ throw new Error('Qoder marketplace list returned malformed JSON');
958
+ }
959
+ const observed = platform.strategy.parseMarketplaceListOutput(parsed, action.marketplace);
960
+ if (!observed.ok) throw new Error(observed.error);
961
+ const expectedRepository = normalizeGitRepository(
962
+ action.marketplaceSource ?? `https://github.com/${action.repo}.git`,
963
+ );
964
+ if (!expectedRepository || normalizeGitRepository(observed.found.source.url) !== expectedRepository) {
965
+ throw new Error(`Qoder marketplace "${action.marketplace}" does not point to frozen repository ${expectedRepository ?? action.repo}`);
966
+ }
967
+ let marketplaceRoot;
968
+ try {
969
+ const homeRoot = await realpath(isolatedHome);
970
+ const observedRoot = await realpath(observed.installPath);
971
+ const installRelative = relative(homeRoot, observedRoot);
972
+ marketplaceRoot = await resolveContained(homeRoot, installRelative);
973
+ } catch {
974
+ throw new Error(`Qoder marketplace checkout escapes isolated HOME: ${observed.installPath}`);
975
+ }
976
+ const head = await exec('git', ['-C', marketplaceRoot, 'rev-parse', 'HEAD'], {
977
+ env, cwd, timeout,
978
+ });
979
+ const marketplaceCommitSha = String(head.stdout ?? '').trim();
980
+ if (marketplaceCommitSha !== action.marketplaceCommitSha) {
981
+ throw new Error(`Qoder marketplace checkout SHA "${marketplaceCommitSha}" does not match frozen SHA "${action.marketplaceCommitSha}"`);
982
+ }
983
+ const index = await validateManifestFile(resolve(marketplaceRoot, action.marketplaceIndexPath), ['name', 'plugins']);
984
+ if (!index.valid || index.manifest.name !== action.marketplace || !Array.isArray(index.manifest.plugins)) {
985
+ throw new Error('Qoder Hub marketplace index is missing or invalid');
986
+ }
987
+ const matches = index.manifest.plugins.filter((entry) => entry?.name === action.plugin);
988
+ if (matches.length !== 1) {
989
+ throw new Error(`Qoder Hub marketplace index must contain exactly one "${action.plugin}" entry`);
990
+ }
991
+ const frozenIdentity = projectObservedStandaloneIndexInstallIdentity('qoder', action.selectedEntry);
992
+ const observedIdentity = projectObservedStandaloneIndexInstallIdentity('qoder', matches[0]);
993
+ if (JSON.stringify(observedIdentity) !== JSON.stringify(frozenIdentity)) {
994
+ throw new Error('Qoder Hub entry does not match the frozen source URL and SHA');
995
+ }
996
+ return { command: listed.command, marketplaceCommitSha, marketplaceRoot, selectedEntry: observedIdentity };
997
+ }
998
+
900
999
  /**
901
1000
  * Classify whether an error indicates CLI/transport unavailability.
902
1001
  *
@@ -1138,6 +1237,7 @@ const PLATFORM_SUPPORTED_SOURCES = Object.freeze({
1138
1237
  codex: new Set([MARKETPLACE_SOURCE_TYPES.BUNDLED_FAMILY, MARKETPLACE_SOURCE_TYPES.STANDALONE_INDEX]),
1139
1238
  kimi: new Set([MARKETPLACE_SOURCE_TYPES.BUNDLED_FAMILY, MARKETPLACE_SOURCE_TYPES.STANDALONE_INDEX]),
1140
1239
  codebuddy: new Set([MARKETPLACE_SOURCE_TYPES.BUNDLED_FAMILY, MARKETPLACE_SOURCE_TYPES.STANDALONE_INDEX]),
1240
+ qoder: new Set([MARKETPLACE_SOURCE_TYPES.STANDALONE_INDEX]),
1141
1241
  });
1142
1242
 
1143
1243
  /**
@@ -1298,6 +1398,7 @@ export function createPluginMarketplaceAdapter(deps = {}) {
1298
1398
  actionType === ActionType.CODEX_MARKETPLACE_INSTALL ||
1299
1399
  actionType === ActionType.KIMI_MARKETPLACE_INSTALL ||
1300
1400
  actionType === ActionType.CODEBUDDY_MARKETPLACE_INSTALL
1401
+ || actionType === ActionType.QODER_MARKETPLACE_INSTALL
1301
1402
  ) {
1302
1403
  // 1. Validate all parameters for injection safety
1303
1404
  const validation = validateMarketplaceParams(action);
@@ -1731,6 +1832,17 @@ export function createPluginMarketplaceAdapter(deps = {}) {
1731
1832
  error: `selectedEntry.version "${action.selectedEntry.version}" does not match action.version "${action.version}"`,
1732
1833
  });
1733
1834
  }
1835
+ if (consumer === 'qoder') {
1836
+ try {
1837
+ projectObservedStandaloneIndexInstallIdentity('qoder', action.selectedEntry);
1838
+ } catch (identityError) {
1839
+ return createResult({
1840
+ actionType,
1841
+ status: ActionStatus.PREFLIGHT_FAILED,
1842
+ error: `Qoder selectedEntry identity is invalid: ${identityError.message}`,
1843
+ });
1844
+ }
1845
+ }
1734
1846
  }
1735
1847
  } else {
1736
1848
  // 6b. 旧路径:sourceDescriptor 必须存在且为对象
@@ -2435,6 +2547,7 @@ export function createPluginMarketplaceAdapter(deps = {}) {
2435
2547
  actionType === ActionType.CODEX_MARKETPLACE_INSTALL ||
2436
2548
  actionType === ActionType.KIMI_MARKETPLACE_INSTALL ||
2437
2549
  actionType === ActionType.CODEBUDDY_MARKETPLACE_INSTALL
2550
+ || actionType === ActionType.QODER_MARKETPLACE_INSTALL
2438
2551
  ) {
2439
2552
  try {
2440
2553
  assertIsolatedConsumerWritesAuthorized(context, actionType);
@@ -2500,7 +2613,7 @@ export function createPluginMarketplaceAdapter(deps = {}) {
2500
2613
  await mkdir(resolve(isolatedHome, subdir), { recursive: true, mode: 0o700 });
2501
2614
  }
2502
2615
 
2503
- const cliCmd = platform.cli.binary;
2616
+ let cliCmd = null;
2504
2617
  const baseEnv = { ...process.env, ...context.env };
2505
2618
  const env = {
2506
2619
  ...baseEnv,
@@ -2530,9 +2643,17 @@ export function createPluginMarketplaceAdapter(deps = {}) {
2530
2643
  // non-automatable manual-requirement path returned above)
2531
2644
  const ref = action.ref ?? `v${action.version}`;
2532
2645
  let addOutput = null;
2646
+ let qoderMarketplaceObservation = null;
2533
2647
  const marketplaceArgs = platform.cli.marketplaceAdd(action.repo, ref);
2534
2648
  try {
2535
- const addResult = await exec(cliCmd, marketplaceArgs, { env, cwd: context.root, timeout: frozenTimeoutMs });
2649
+ const addInvocation = await runPlatformCli(
2650
+ exec,
2651
+ platform,
2652
+ marketplaceArgs,
2653
+ { env, cwd: context.root, timeout: frozenTimeoutMs },
2654
+ );
2655
+ cliCmd = addInvocation.command;
2656
+ const addResult = addInvocation.result;
2536
2657
  if (platform.jsonProtocol.marketplaceAddOutput === 'json') {
2537
2658
  try {
2538
2659
  addOutput = JSON.parse(addResult.stdout);
@@ -2558,6 +2679,18 @@ export function createPluginMarketplaceAdapter(deps = {}) {
2558
2679
  });
2559
2680
  }
2560
2681
  }
2682
+ if (consumer === 'qoder') {
2683
+ qoderMarketplaceObservation = await observeQoderHubAfterAdd({
2684
+ exec,
2685
+ platform,
2686
+ action,
2687
+ env,
2688
+ cwd: context.root,
2689
+ timeout: frozenTimeoutMs,
2690
+ isolatedHome,
2691
+ command: cliCmd,
2692
+ });
2693
+ }
2561
2694
  } catch (addErr) {
2562
2695
  // Re-throw CLI/transport unavailability errors to outer catch
2563
2696
  // for human-attestation fallback classification
@@ -2576,7 +2709,15 @@ export function createPluginMarketplaceAdapter(deps = {}) {
2576
2709
  let installOutput;
2577
2710
  const installArgs = platform.cli.install(action.plugin, action.marketplace);
2578
2711
  try {
2579
- const installResult = await exec(cliCmd, installArgs, { env, cwd: context.root, timeout: frozenTimeoutMs });
2712
+ const installInvocation = await runPlatformCli(
2713
+ exec,
2714
+ platform,
2715
+ installArgs,
2716
+ { env, cwd: context.root, timeout: frozenTimeoutMs },
2717
+ cliCmd,
2718
+ );
2719
+ cliCmd = installInvocation.command;
2720
+ const installResult = installInvocation.result;
2580
2721
  if (platform.jsonProtocol.pluginInstallOutput === 'json') {
2581
2722
  try {
2582
2723
  installOutput = JSON.parse(installResult.stdout);
@@ -2682,8 +2823,10 @@ export function createPluginMarketplaceAdapter(deps = {}) {
2682
2823
  repo: action.repo,
2683
2824
  ref,
2684
2825
  version: action.version,
2826
+ cliCommand: cliCmd,
2685
2827
  addOutput,
2686
2828
  installOutput,
2829
+ qoderMarketplaceObservation,
2687
2830
  executedAt: new Date().toISOString(),
2688
2831
  ...extraInstalledPathsAudit(executeBinding),
2689
2832
  };
@@ -2801,6 +2944,7 @@ export function createPluginMarketplaceAdapter(deps = {}) {
2801
2944
  actionType === ActionType.CODEX_MARKETPLACE_INSTALL ||
2802
2945
  actionType === ActionType.KIMI_MARKETPLACE_INSTALL ||
2803
2946
  actionType === ActionType.CODEBUDDY_MARKETPLACE_INSTALL
2947
+ || actionType === ActionType.QODER_MARKETPLACE_INSTALL
2804
2948
  ) {
2805
2949
  const consumer = action.consumer;
2806
2950
  const runDir = context.runDir;
@@ -2823,7 +2967,7 @@ export function createPluginMarketplaceAdapter(deps = {}) {
2823
2967
  + `Registered platforms: ${PLATFORMS.map((p) => p.id).join(', ')}`,
2824
2968
  );
2825
2969
  }
2826
- const cliCmd = platform.cli ? platform.cli.binary : null;
2970
+ let cliCmd = platform.cli ? platform.cli.binary : null;
2827
2971
  const baseEnv = { ...process.env, ...(context.env ?? {}) };
2828
2972
  const env = {
2829
2973
  ...baseEnv,
@@ -3433,6 +3577,45 @@ export function createPluginMarketplaceAdapter(deps = {}) {
3433
3577
  });
3434
3578
  }
3435
3579
 
3580
+ if (consumer === 'qoder') {
3581
+ const qoderObservation = evidence.qoderMarketplaceObservation;
3582
+ const permittedCliCommands = [platform.cli.binary, ...(platform.cli.binaryAliases ?? [])];
3583
+ if (!permittedCliCommands.includes(evidence.cliCommand)) {
3584
+ return createResult({
3585
+ actionType,
3586
+ status: ActionStatus.OBSERVED,
3587
+ observation: {
3588
+ installed: false,
3589
+ error: `Qoder execute evidence cliCommand must be one of: ${permittedCliCommands.join(', ')}`,
3590
+ },
3591
+ });
3592
+ }
3593
+ let frozenEntryIdentity;
3594
+ try {
3595
+ frozenEntryIdentity = projectObservedStandaloneIndexInstallIdentity('qoder', action.selectedEntry);
3596
+ } catch (identityErr) {
3597
+ return createResult({
3598
+ actionType,
3599
+ status: ActionStatus.OBSERVED,
3600
+ observation: { installed: false, error: identityErr.message },
3601
+ });
3602
+ }
3603
+ if (
3604
+ qoderObservation?.marketplaceCommitSha !== action.marketplaceCommitSha
3605
+ || JSON.stringify(qoderObservation?.selectedEntry) !== JSON.stringify(frozenEntryIdentity)
3606
+ ) {
3607
+ return createResult({
3608
+ actionType,
3609
+ status: ActionStatus.OBSERVED,
3610
+ observation: {
3611
+ installed: false,
3612
+ error: 'Qoder execute evidence is not bound to the frozen Hub SHA and selected entry',
3613
+ },
3614
+ });
3615
+ }
3616
+ cliCmd = evidence.cliCommand;
3617
+ }
3618
+
3436
3619
  if (
3437
3620
  evidence.consumer !== consumer ||
3438
3621
  evidence.plugin !== action.plugin ||
@@ -3455,12 +3638,19 @@ export function createPluginMarketplaceAdapter(deps = {}) {
3455
3638
  // Run list command to verify installation (automatable platforms
3456
3639
  // only; a non-automatable platform has no list CLI and returned via
3457
3640
  // the attestation path above).
3458
- const listArgs = ['plugin', 'list', '--json'];
3641
+ const listArgs = platform.cli.list();
3459
3642
 
3460
3643
  let listOutput;
3461
3644
  try {
3462
- const result = await exec(cliCmd, listArgs, { env, cwd: context.root, timeout: frozenTimeoutMs });
3463
- listOutput = JSON.parse(result.stdout);
3645
+ const invocation = await runPlatformCli(
3646
+ exec,
3647
+ platform,
3648
+ listArgs,
3649
+ { env, cwd: context.root, timeout: frozenTimeoutMs },
3650
+ cliCmd,
3651
+ );
3652
+ cliCmd = invocation.command;
3653
+ listOutput = JSON.parse(invocation.result.stdout);
3464
3654
  } catch (listErr) {
3465
3655
  return createResult({
3466
3656
  actionType,
@@ -3745,7 +3935,9 @@ export function createPluginMarketplaceAdapter(deps = {}) {
3745
3935
  // (CLI list version binding) compensates for the weak name-freeze.
3746
3936
  if (action.marketplaceLocation === 'external') {
3747
3937
  observation.marketplaceLocation = action.marketplaceLocation;
3748
- observation.marketplaceCommitSha = action.marketplaceCommitSha;
3938
+ observation.marketplaceCommitSha = consumer === 'qoder'
3939
+ ? evidence.qoderMarketplaceObservation.marketplaceCommitSha
3940
+ : action.marketplaceCommitSha;
3749
3941
  }
3750
3942
 
3751
3943
  return createResult({