agentbundle 0.29.5__tar.gz → 0.29.6__tar.gz

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 (200) hide show
  1. {agentbundle-0.29.5 → agentbundle-0.29.6}/PKG-INFO +8 -4
  2. {agentbundle-0.29.5 → agentbundle-0.29.6}/README-pypi.md +7 -3
  3. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/adapter.toml +3 -0
  4. agentbundle-0.29.6/agentbundle/_data/marketplace-entry.schema.json +110 -0
  5. agentbundle-0.29.6/agentbundle/_data/plugin-manifest.derived.schema.json +147 -0
  6. agentbundle-0.29.6/agentbundle/_data/plugin-manifest.schema.json +110 -0
  7. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/claude_code.py +27 -2
  8. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/main.py +88 -16
  9. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_end_to_end_build.py +11 -3
  10. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_pipeline.py +2 -2
  11. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_plugin_manifest_schema.py +4 -4
  12. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_projectable_subset.py +4 -4
  13. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_self_host_check.py +0 -1
  14. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/verify.py +84 -25
  15. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/upgrade.py +1 -1
  16. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/version.py +1 -1
  17. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle.egg-info/PKG-INFO +8 -4
  18. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle.egg-info/SOURCES.txt +1 -0
  19. {agentbundle-0.29.5 → agentbundle-0.29.6}/pyproject.toml +1 -1
  20. agentbundle-0.29.5/agentbundle/_data/plugin-manifest.derived.schema.json +0 -73
  21. agentbundle-0.29.5/agentbundle/_data/plugin-manifest.schema.json +0 -45
  22. {agentbundle-0.29.5 → agentbundle-0.29.6}/README.md +0 -0
  23. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/__init__.py +0 -0
  24. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/__main__.py +0 -0
  25. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/adapter.schema.json +0 -0
  26. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/guides/_shared/reference/catalogue-authoring-standards.md +0 -0
  27. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/guides/_shared/reference/catalogue-ci-contract.md +0 -0
  28. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/manifest.json +0 -0
  29. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/packs/AGENTS.md +0 -0
  30. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/packs/README.md +0 -0
  31. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/packs/_example/README.md +0 -0
  32. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/packs/_example/pack.toml +0 -0
  33. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/profiles/AGENTS.md +0 -0
  34. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/profiles/README.md +0 -0
  35. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/profiles/_example/README.md +0 -0
  36. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/profiles/_example/profile.toml +0 -0
  37. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue.schema.json +0 -0
  38. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/guide.schema.json +0 -0
  39. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/install-defaults.toml +0 -0
  40. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/install-marker.py +0 -0
  41. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/pack.schema.json +0 -0
  42. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/profile.schema.json +0 -0
  43. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/skill-manifest.schema.json +0 -0
  44. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/skill.schema.json +0 -0
  45. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/target-vocab.toml +0 -0
  46. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/__init__.py +0 -0
  47. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/__main__.py +0 -0
  48. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapter_root_bins.py +0 -0
  49. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/__init__.py +0 -0
  50. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/codex.py +0 -0
  51. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/copilot.py +0 -0
  52. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/cursor.py +0 -0
  53. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/gemini.py +0 -0
  54. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/kiro.py +0 -0
  55. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/kiro_cli.py +0 -0
  56. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/kiro_ide.py +0 -0
  57. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/contract.py +0 -0
  58. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/lint_packs.py +0 -0
  59. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/phase_order.py +0 -0
  60. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/__init__.py +0 -0
  61. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/codex_agent_toml.py +0 -0
  62. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/copilot_agent_md.py +0 -0
  63. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/copilot_hooks_json.py +0 -0
  64. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/direct_directory.py +0 -0
  65. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/gemini_command_toml.py +0 -0
  66. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/hook_id.py +0 -0
  67. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/kiro_ide_hook.py +0 -0
  68. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/merge_into_agent_json.py +0 -0
  69. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/merge_json.py +0 -0
  70. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/user_merge_json.py +0 -0
  71. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/recipes/composite-agents-md.toml +0 -0
  72. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/recipes/composite-marketplace.toml +0 -0
  73. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/recipes/marketplace.toml +0 -0
  74. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/recipes/per-pack-apm-package.toml +0 -0
  75. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/recipes/per-pack-claude-plugin.toml +0 -0
  76. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/recipes/per-pack-overlay.toml +0 -0
  77. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/recipes/self-host.toml +0 -0
  78. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/scope_rails.py +0 -0
  79. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/self_host.py +0 -0
  80. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/shared_libs.py +0 -0
  81. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/target_resolver.py +0 -0
  82. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/__init__.py +0 -0
  83. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_claude_code.py +0 -0
  84. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_codex.py +0 -0
  85. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_copilot.py +0 -0
  86. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_cursor.py +0 -0
  87. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_gemini.py +0 -0
  88. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_kiro.py +0 -0
  89. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_kiro_alias.py +0 -0
  90. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_kiro_cli.py +0 -0
  91. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_kiro_ide.py +0 -0
  92. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_root_bins_projection.py +0 -0
  93. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_architect_design_reviewer_projection.py +0 -0
  94. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_architect_design_reviewer_rubric_parity.py +0 -0
  95. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_build_ships_seeds.py +0 -0
  96. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_contract.py +0 -0
  97. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_contract_scope.py +0 -0
  98. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_contract_v07.py +0 -0
  99. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_contract_v08.py +0 -0
  100. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_direct_directory_cleanup.py +0 -0
  101. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_lint_agents_md_diataxis_block.py +0 -0
  102. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_lint_agents_md_legacy_block.py +0 -0
  103. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_lint_agents_md_risk_block.py +0 -0
  104. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_lint_packs.py +0 -0
  105. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_load_pack_hook_wiring_safely.py +0 -0
  106. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_pack_schema.py +0 -0
  107. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_pack_schema_allowed_adapters.py +0 -0
  108. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_pack_schema_install.py +0 -0
  109. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_projections_merge_json.py +0 -0
  110. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_scope_rails.py +0 -0
  111. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_security.py +0 -0
  112. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_self_host_fixture_guard.py +0 -0
  113. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_self_host_recipe_config.py +0 -0
  114. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_shared_libs_projection.py +0 -0
  115. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_shared_prefix_contract.py +0 -0
  116. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_shipped_packs_v07_declarations.py +0 -0
  117. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_shipped_packs_v08_declarations.py +0 -0
  118. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_user_libs_projection.py +0 -0
  119. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_validate.py +0 -0
  120. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_workspace_status_projection.py +0 -0
  121. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_writers_emit_lf.py +0 -0
  122. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/user_libs.py +0 -0
  123. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/validate.py +0 -0
  124. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue.py +0 -0
  125. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/__init__.py +0 -0
  126. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/archive.py +0 -0
  127. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/build.py +0 -0
  128. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/config.py +0 -0
  129. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/defaults.py +0 -0
  130. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/diagnostics.py +0 -0
  131. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/identity.py +0 -0
  132. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/initialise.py +0 -0
  133. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/initialise_self_hosted.py +0 -0
  134. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/lint.py +0 -0
  135. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/package.py +0 -0
  136. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/results.py +0 -0
  137. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/self_host.py +0 -0
  138. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/self_host_windows.py +0 -0
  139. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/skill_spec_lint.py +0 -0
  140. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/toml_emit.py +0 -0
  141. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/categories.py +0 -0
  142. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/cli.py +0 -0
  143. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/__init__.py +0 -0
  144. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/_common.py +0 -0
  145. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/_drop_warning.py +0 -0
  146. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/adapt.py +0 -0
  147. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/catalogue_build.py +0 -0
  148. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/catalogue_init.py +0 -0
  149. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/catalogue_lint.py +0 -0
  150. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/catalogue_package.py +0 -0
  151. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/catalogue_self_host.py +0 -0
  152. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/catalogue_sync_defaults.py +0 -0
  153. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/catalogue_tooling_stub.py +0 -0
  154. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/catalogue_verify.py +0 -0
  155. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/config.py +0 -0
  156. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/diff.py +0 -0
  157. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/docs.py +0 -0
  158. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/init_state.py +0 -0
  159. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/install.py +0 -0
  160. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/list_installed.py +0 -0
  161. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/list_packs.py +0 -0
  162. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/list_profiles.py +0 -0
  163. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/list_targets.py +0 -0
  164. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/oplog_cmd.py +0 -0
  165. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/pack_config_cmd.py +0 -0
  166. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/pack_evals.py +0 -0
  167. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/package_catalogue.py +0 -0
  168. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/profile.py +0 -0
  169. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/reconcile.py +0 -0
  170. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/render.py +0 -0
  171. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/scaffold.py +0 -0
  172. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/show.py +0 -0
  173. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/uninstall.py +0 -0
  174. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/validate.py +0 -0
  175. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/config.py +0 -0
  176. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/https_catalogue.py +0 -0
  177. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/local_exclude.py +0 -0
  178. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/oplog.py +0 -0
  179. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/pack_inventory.py +0 -0
  180. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/render.py +0 -0
  181. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/safety.py +0 -0
  182. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/scaffold.py +0 -0
  183. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/scope.py +0 -0
  184. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/source_defaults.py +0 -0
  185. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/statelock.py +0 -0
  186. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/user_config.py +0 -0
  187. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/workspace_mcp.py +0 -0
  188. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle.egg-info/dependency_links.txt +0 -0
  189. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle.egg-info/entry_points.txt +0 -0
  190. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle.egg-info/requires.txt +0 -0
  191. {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle.egg-info/top_level.txt +0 -0
  192. {agentbundle-0.29.5 → agentbundle-0.29.6}/setup.cfg +0 -0
  193. {agentbundle-0.29.5 → agentbundle-0.29.6}/tests/test_adapter_permissions_projection.py +0 -0
  194. {agentbundle-0.29.5 → agentbundle-0.29.6}/tests/test_linear_primitive.py +0 -0
  195. {agentbundle-0.29.5 → agentbundle-0.29.6}/tests/test_workspace_mcp_elicit.py +0 -0
  196. {agentbundle-0.29.5 → agentbundle-0.29.6}/tests/test_workspace_mcp_event_bridge.py +0 -0
  197. {agentbundle-0.29.5 → agentbundle-0.29.6}/tests/test_workspace_mcp_git.py +0 -0
  198. {agentbundle-0.29.5 → agentbundle-0.29.6}/tests/test_workspace_mcp_lifecycle.py +0 -0
  199. {agentbundle-0.29.5 → agentbundle-0.29.6}/tests/test_workspace_mcp_stdin.py +0 -0
  200. {agentbundle-0.29.5 → agentbundle-0.29.6}/tests/test_workspace_mcp_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentbundle
3
- Version: 0.29.5
3
+ Version: 0.29.6
4
4
  Summary: npm for your coding agent. Install packs of skills, subagents, and hooks into any repo, for every major agent.
5
5
  Author-email: eugenelim <eugenelim@users.noreply.github.com>
6
6
  License: Apache-2.0 OR MIT
@@ -269,7 +269,10 @@ ignore them there; the separation is structural, not incidental.
269
269
  `keywords` once; the build projects the cleanly-mappable subset — plus the
270
270
  pack's `README.md` — into each distribution route's manifest (the `plugin.json`
271
271
  / `marketplace.json` entry), so the catalogue describes each pack richly rather
272
- than with a single sentence. Extra fields stay in `pack.toml`; the projection
272
+ than with a single sentence. A marketplace entry's `source` is a `git-subdir`
273
+ object (`url`, `path`, and one of `ref`/`sha`) pointing at the pack's directory
274
+ on the published distribution branch, and every entry is schema-validated at
275
+ build time against `marketplace-entry.schema.json`. Extra fields stay in `pack.toml`; the projection
273
276
  is deliberately lossy per tool.
274
277
 
275
278
  Point a catalogue URI (a git URL or a local path) at the repo that holds your packs. Then `validate` a pack against the adapter contract, `render` it to preview the projection, and `install` it into a target repo. `scaffold` drops a pack's seeds into a fresh directory to start from. The build pipeline (`agentbundle.build`) is the same engine `make build` runs.
@@ -285,8 +288,9 @@ The org hint fires after the user-config but before the on-disk IDE probe — so
285
288
 
286
289
  **Bundled contracts** — the wheel ships the machine contracts used for offline validation:
287
290
  `pack.schema.json`, `skill.schema.json`, `guide.schema.json`, `skill-manifest.schema.json`,
288
- `profile.schema.json`, `catalogue.schema.json`, `target-vocab.toml`, and the adapter
289
- contract files. All are available without network access via `importlib.resources`.
291
+ `profile.schema.json`, `catalogue.schema.json`, `plugin-manifest.schema.json`,
292
+ `plugin-manifest.derived.schema.json`, `marketplace-entry.schema.json`,
293
+ `target-vocab.toml`, and the adapter contract files. All are available without network access via `importlib.resources`.
290
294
 
291
295
  **Lint your catalogue** — shallow structural checks run without extra dependencies:
292
296
 
@@ -247,7 +247,10 @@ ignore them there; the separation is structural, not incidental.
247
247
  `keywords` once; the build projects the cleanly-mappable subset — plus the
248
248
  pack's `README.md` — into each distribution route's manifest (the `plugin.json`
249
249
  / `marketplace.json` entry), so the catalogue describes each pack richly rather
250
- than with a single sentence. Extra fields stay in `pack.toml`; the projection
250
+ than with a single sentence. A marketplace entry's `source` is a `git-subdir`
251
+ object (`url`, `path`, and one of `ref`/`sha`) pointing at the pack's directory
252
+ on the published distribution branch, and every entry is schema-validated at
253
+ build time against `marketplace-entry.schema.json`. Extra fields stay in `pack.toml`; the projection
251
254
  is deliberately lossy per tool.
252
255
 
253
256
  Point a catalogue URI (a git URL or a local path) at the repo that holds your packs. Then `validate` a pack against the adapter contract, `render` it to preview the projection, and `install` it into a target repo. `scaffold` drops a pack's seeds into a fresh directory to start from. The build pipeline (`agentbundle.build`) is the same engine `make build` runs.
@@ -263,8 +266,9 @@ The org hint fires after the user-config but before the on-disk IDE probe — so
263
266
 
264
267
  **Bundled contracts** — the wheel ships the machine contracts used for offline validation:
265
268
  `pack.schema.json`, `skill.schema.json`, `guide.schema.json`, `skill-manifest.schema.json`,
266
- `profile.schema.json`, `catalogue.schema.json`, `target-vocab.toml`, and the adapter
267
- contract files. All are available without network access via `importlib.resources`.
269
+ `profile.schema.json`, `catalogue.schema.json`, `plugin-manifest.schema.json`,
270
+ `plugin-manifest.derived.schema.json`, `marketplace-entry.schema.json`,
271
+ `target-vocab.toml`, and the adapter contract files. All are available without network access via `importlib.resources`.
268
272
 
269
273
  **Lint your catalogue** — shallow structural checks run without extra dependencies:
270
274
 
@@ -188,12 +188,14 @@ install-routes = ["cli", "claude-plugins", "apm"]
188
188
  primitive = "skill"
189
189
  mode = "direct-directory"
190
190
  target-path = ".claude/skills/"
191
+ plugin-target-path = "skills/"
191
192
  on-conflict = "prompt-then-preserve"
192
193
 
193
194
  [[adapter."claude-code".projection]]
194
195
  primitive = "agent"
195
196
  mode = "direct-file"
196
197
  target-path = ".claude/agents/"
198
+ plugin-target-path = "agents/"
197
199
  on-conflict = "prompt-then-preserve"
198
200
 
199
201
  [[adapter."claude-code".projection]]
@@ -213,6 +215,7 @@ on-conflict = "merge-managed-key-only"
213
215
  primitive = "command"
214
216
  mode = "direct-file"
215
217
  target-path = ".claude/commands/"
218
+ plugin-target-path = "commands/"
216
219
  on-conflict = "prompt-then-preserve"
217
220
 
218
221
  # hook-body — scope-conditional target.
@@ -0,0 +1,110 @@
1
+ {
2
+ "x-spec": "docs/specs/claude-plugins-manifest-correctness",
3
+ "type": "object",
4
+ "required": [
5
+ "name",
6
+ "version",
7
+ "description"
8
+ ],
9
+ "additionalProperties": false,
10
+ "properties": {
11
+ "name": {
12
+ "type": "string"
13
+ },
14
+ "version": {
15
+ "type": "string"
16
+ },
17
+ "description": {
18
+ "type": "string"
19
+ },
20
+ "skills": {
21
+ "type": "array",
22
+ "items": {
23
+ "type": "string"
24
+ }
25
+ },
26
+ "agents": {
27
+ "type": "array",
28
+ "items": {
29
+ "type": "string"
30
+ }
31
+ },
32
+ "author": {
33
+ "type": "object",
34
+ "required": [
35
+ "name"
36
+ ],
37
+ "properties": {
38
+ "name": {
39
+ "type": "string"
40
+ },
41
+ "email": {
42
+ "type": "string"
43
+ }
44
+ }
45
+ },
46
+ "license": {
47
+ "type": "string"
48
+ },
49
+ "homepage": {
50
+ "type": "string"
51
+ },
52
+ "repository": {
53
+ "type": "string"
54
+ },
55
+ "keywords": {
56
+ "type": "array",
57
+ "items": {
58
+ "type": "string"
59
+ }
60
+ },
61
+ "displayName": {
62
+ "type": "string"
63
+ },
64
+ "category": {
65
+ "type": "string"
66
+ },
67
+ "source": {
68
+ "type": "object",
69
+ "required": [
70
+ "source",
71
+ "url",
72
+ "path"
73
+ ],
74
+ "additionalProperties": false,
75
+ "properties": {
76
+ "source": {
77
+ "type": "string",
78
+ "enum": [
79
+ "git-subdir"
80
+ ]
81
+ },
82
+ "url": {
83
+ "type": "string",
84
+ "pattern": "^https://github\\.com/[^/]+/[^/]+\\.git$"
85
+ },
86
+ "path": {
87
+ "type": "string",
88
+ "pattern": "^[a-z0-9][a-z0-9-]*$"
89
+ },
90
+ "ref": {
91
+ "type": "string"
92
+ },
93
+ "sha": {
94
+ "type": "string"
95
+ }
96
+ },
97
+ "if": {
98
+ "required": [
99
+ "ref"
100
+ ]
101
+ },
102
+ "then": {},
103
+ "else": {
104
+ "required": [
105
+ "sha"
106
+ ]
107
+ }
108
+ }
109
+ }
110
+ }
@@ -0,0 +1,147 @@
1
+ {
2
+ "x-spec": "docs/specs/claude-plugins-manifest-correctness",
3
+ "type": "object",
4
+ "required": [
5
+ "name",
6
+ "version",
7
+ "description"
8
+ ],
9
+ "additionalProperties": false,
10
+ "properties": {
11
+ "name": {
12
+ "type": "string"
13
+ },
14
+ "version": {
15
+ "type": "string"
16
+ },
17
+ "description": {
18
+ "type": "string"
19
+ },
20
+ "skills": {
21
+ "type": "array",
22
+ "items": {
23
+ "type": "string"
24
+ }
25
+ },
26
+ "agents": {
27
+ "type": "array",
28
+ "items": {
29
+ "type": "string"
30
+ }
31
+ },
32
+ "author": {
33
+ "type": "object",
34
+ "required": [
35
+ "name"
36
+ ],
37
+ "properties": {
38
+ "name": {
39
+ "type": "string"
40
+ },
41
+ "email": {
42
+ "type": "string"
43
+ }
44
+ }
45
+ },
46
+ "license": {
47
+ "type": "string"
48
+ },
49
+ "homepage": {
50
+ "type": "string"
51
+ },
52
+ "repository": {
53
+ "type": "string"
54
+ },
55
+ "keywords": {
56
+ "type": "array",
57
+ "items": {
58
+ "type": "string"
59
+ }
60
+ },
61
+ "displayName": {
62
+ "type": "string"
63
+ },
64
+ "source": {
65
+ "type": "object",
66
+ "required": [
67
+ "source",
68
+ "url",
69
+ "path"
70
+ ],
71
+ "additionalProperties": false,
72
+ "properties": {
73
+ "source": {
74
+ "type": "string",
75
+ "enum": [
76
+ "git-subdir"
77
+ ]
78
+ },
79
+ "url": {
80
+ "type": "string",
81
+ "pattern": "^https://github\\.com/[^/]+/[^/]+\\.git$"
82
+ },
83
+ "path": {
84
+ "type": "string",
85
+ "pattern": "^[a-z0-9][a-z0-9-]*$"
86
+ },
87
+ "ref": {
88
+ "type": "string"
89
+ },
90
+ "sha": {
91
+ "type": "string"
92
+ }
93
+ },
94
+ "if": {
95
+ "required": [
96
+ "ref"
97
+ ]
98
+ },
99
+ "then": {},
100
+ "else": {
101
+ "required": [
102
+ "sha"
103
+ ]
104
+ }
105
+ },
106
+ "hooks": {
107
+ "type": "object",
108
+ "additionalProperties": false,
109
+ "properties": {
110
+ "SessionStart": {
111
+ "type": "array",
112
+ "items": {
113
+ "type": "object",
114
+ "additionalProperties": false,
115
+ "properties": {
116
+ "hooks": {
117
+ "type": "array",
118
+ "items": {
119
+ "type": "object",
120
+ "required": [
121
+ "type",
122
+ "command"
123
+ ],
124
+ "additionalProperties": false,
125
+ "properties": {
126
+ "type": {
127
+ "type": "string",
128
+ "enum": [
129
+ "command"
130
+ ]
131
+ },
132
+ "command": {
133
+ "type": "string"
134
+ },
135
+ "timeout": {
136
+ "type": "integer"
137
+ }
138
+ }
139
+ }
140
+ }
141
+ }
142
+ }
143
+ }
144
+ }
145
+ }
146
+ }
147
+ }
@@ -0,0 +1,110 @@
1
+ {
2
+ "x-spec": "docs/specs/claude-plugins-manifest-correctness",
3
+ "type": "object",
4
+ "required": [
5
+ "name",
6
+ "version",
7
+ "description"
8
+ ],
9
+ "additionalProperties": false,
10
+ "properties": {
11
+ "name": {
12
+ "type": "string"
13
+ },
14
+ "version": {
15
+ "type": "string"
16
+ },
17
+ "description": {
18
+ "type": "string"
19
+ },
20
+ "skills": {
21
+ "type": "array",
22
+ "items": {
23
+ "type": "string"
24
+ }
25
+ },
26
+ "agents": {
27
+ "type": "array",
28
+ "items": {
29
+ "type": "string"
30
+ }
31
+ },
32
+ "author": {
33
+ "type": "object",
34
+ "required": [
35
+ "name"
36
+ ],
37
+ "properties": {
38
+ "name": {
39
+ "type": "string"
40
+ },
41
+ "email": {
42
+ "type": "string"
43
+ }
44
+ }
45
+ },
46
+ "license": {
47
+ "type": "string"
48
+ },
49
+ "homepage": {
50
+ "type": "string"
51
+ },
52
+ "repository": {
53
+ "type": "string"
54
+ },
55
+ "keywords": {
56
+ "type": "array",
57
+ "items": {
58
+ "type": "string"
59
+ }
60
+ },
61
+ "category": {
62
+ "type": "string"
63
+ },
64
+ "displayName": {
65
+ "type": "string"
66
+ },
67
+ "source": {
68
+ "type": "object",
69
+ "required": [
70
+ "source",
71
+ "url",
72
+ "path"
73
+ ],
74
+ "additionalProperties": false,
75
+ "properties": {
76
+ "source": {
77
+ "type": "string",
78
+ "enum": [
79
+ "git-subdir"
80
+ ]
81
+ },
82
+ "url": {
83
+ "type": "string",
84
+ "pattern": "^https://github\\.com/[^/]+/[^/]+\\.git$"
85
+ },
86
+ "path": {
87
+ "type": "string",
88
+ "pattern": "^[a-z0-9][a-z0-9-]*$"
89
+ },
90
+ "ref": {
91
+ "type": "string"
92
+ },
93
+ "sha": {
94
+ "type": "string"
95
+ }
96
+ },
97
+ "if": {
98
+ "required": [
99
+ "ref"
100
+ ]
101
+ },
102
+ "then": {},
103
+ "else": {
104
+ "required": [
105
+ "sha"
106
+ ]
107
+ }
108
+ }
109
+ }
110
+ }
@@ -62,11 +62,33 @@ def project_packs(pack_paths: list[Path], contract: dict, output_root: Path) ->
62
62
  # Mirror of kiro.py:_skill_direct_directory_target — keep in sync.
63
63
  # A shared helper is barred by the spec's `Never do` boundary (no
64
64
  # expansion of projections/direct_directory.py beyond `sweep_orphans`).
65
+ def _resolve_target(output_root: Path, target_path: str) -> Path:
66
+ """Join a contract ``target-path`` onto ``output_root``, confined.
67
+
68
+ ``target-path`` (and its route-scoped sibling ``plugin-target-path``) are
69
+ contract *data*. An absolute value discards the base entirely on join
70
+ (``Path("/a/b") / "/etc/x"`` is ``/etc/x``) and a ``..``-bearing one walks
71
+ out of it — and because the orphan sweep resolves the same value, an
72
+ escaped target becomes the root of a ``shutil.rmtree``. Confine after
73
+ resolution rather than trusting the string (CWE-73, not just CWE-22).
74
+ """
75
+ candidate = output_root / target_path.rstrip("/")
76
+ root_resolved = output_root.resolve()
77
+ try:
78
+ candidate.resolve().relative_to(root_resolved)
79
+ except ValueError:
80
+ raise ValueError(
81
+ f"claude-code: target-path {target_path!r} escapes the output root "
82
+ f"{output_root}"
83
+ ) from None
84
+ return candidate
85
+
86
+
65
87
  def _skill_direct_directory_target(contract: dict, output_root: Path) -> Path | None:
66
88
  adapter_block = contract["adapter"]["claude-code"]
67
89
  for entry in adapter_block.get("projection", []):
68
90
  if entry.get("primitive") == "skill" and entry.get("mode") == "direct-directory":
69
- return output_root / entry["target-path"].rstrip("/")
91
+ return _resolve_target(output_root, entry["target-path"])
70
92
  return None
71
93
 
72
94
 
@@ -128,8 +150,11 @@ def _project_single(pack_path: Path, contract: dict, output_root: Path) -> None:
128
150
  continue
129
151
 
130
152
  if mode == "direct-directory":
131
- _project_direct_directory(source_dir, output_root / rule["target-path"].rstrip("/"))
153
+ _project_direct_directory(
154
+ source_dir, _resolve_target(output_root, rule["target-path"])
155
+ )
132
156
  elif mode == "direct-file":
157
+ _resolve_target(output_root, rule["target-path"]) # confinement check
133
158
  _project_direct_file(source_dir, output_root, rule["target-path"])
134
159
  elif mode == "merge-json":
135
160
  project_merge_json(source_dir, output_root, rule)
@@ -46,8 +46,15 @@ _MARKETPLACE_DESCRIPTION = (
46
46
  )
47
47
 
48
48
  # Match https://github.com/owner/repo (optional trailing .git and slash).
49
+ # HTTPS only: an `http://` link is rejected outright rather than upgraded,
50
+ # because `git-subdir` moves the fetch host from the schema into data.
49
51
  _GITHUB_URL_RE = re.compile(
50
- r"^https?://github\.com/([^/]+/[^/]+?)(?:\.git)?/?$"
52
+ r"^https://github\.com/([^/]+/[^/]+?)(?:\.git)?/?$"
53
+ )
54
+ # Matched separately so an insecure link raises instead of silently falling
55
+ # through the "not a GitHub URL" branch, which emits no `source` at all.
56
+ _INSECURE_GITHUB_URL_RE = re.compile(
57
+ r"^http://github\.com/([^/]+/[^/]+?)(?:\.git)?/?$"
51
58
  )
52
59
 
53
60
 
@@ -206,9 +213,17 @@ def derive_projectable_subset(pack_toml: dict) -> dict:
206
213
 
207
214
  - ``author`` ← first ``[[pack.maintainers]]``, as object
208
215
  ``{"name": ..., "email": ...}`` (email omitted when absent).
209
- - ``source`` ← derived from ``[pack.links].repository`` when it is a
210
- GitHub URL: ``{"source": "github", "repo": "owner/name",
211
- "branch": _DIST_BRANCH, "directory": pack.name}``.
216
+ - ``source`` ← derived from ``[pack.links].repository`` when it is an
217
+ **https** GitHub URL: ``{"source": "git-subdir",
218
+ "url": "https://github.com/owner/name.git", "path": pack.name,
219
+ "ref": _DIST_BRANCH}``. Claude Code's ``github`` source accepts only
220
+ ``repo``/``ref``/``sha`` and has no subdirectory support, so the former
221
+ ``branch``/``directory`` keys were silently dropped and the installer
222
+ cloned the default branch at repo root — every adopter received an
223
+ empty plugin. An ``http://`` repository link **raises**: silently
224
+ upgrading it to ``https`` would fabricate a URL the author did not
225
+ write, and silently omitting ``source`` would reintroduce the same
226
+ class of quiet failure.
212
227
  - ``license`` ← ``[pack].license`` (verbatim).
213
228
  - ``homepage`` ← ``[pack.links].homepage`` (verbatim).
214
229
  - ``repository`` ← ``[pack.links].repository`` (verbatim).
@@ -255,13 +270,20 @@ def derive_projectable_subset(pack_toml: dict) -> dict:
255
270
  # from the canonical distribution branch.
256
271
  pack_name = pack.get("name", "")
257
272
  if isinstance(pack_name, str) and pack_name:
273
+ if _INSECURE_GITHUB_URL_RE.match(repository):
274
+ raise ValueError(
275
+ f"[pack.links].repository must be https, got "
276
+ f"{repository!r}. Refusing to upgrade it silently: the "
277
+ f"emitted url is what an adopter's client clones and "
278
+ f"then executes."
279
+ )
258
280
  m = _GITHUB_URL_RE.match(repository)
259
281
  if m:
260
282
  out["source"] = {
261
- "source": "github",
262
- "repo": m.group(1),
263
- "branch": _DIST_BRANCH,
264
- "directory": pack_name,
283
+ "source": "git-subdir",
284
+ "url": f"https://github.com/{m.group(1)}.git",
285
+ "path": pack_name,
286
+ "ref": _DIST_BRANCH,
265
287
  }
266
288
 
267
289
  keywords = pack.get("keywords")
@@ -485,6 +507,49 @@ def _run_per_pack(
485
507
  return {"recipe": recipe.name, "type": recipe.type, "produced": produced}
486
508
 
487
509
 
510
+ def _resolve_contract_for_route(contract: dict, recipe: Recipe) -> dict:
511
+ """Return the contract with route-scoped projection targets applied.
512
+
513
+ Claude Code *plugins* load ``skills/``, ``agents/`` and ``commands/`` from
514
+ the plugin root; a repo or user install lands the same primitives under
515
+ ``.claude/``. Rather than widen every adapter's ``project`` signature with a
516
+ route argument, the dispatcher swaps ``target-path`` for the entry's
517
+ ``plugin-target-path`` on the claude-plugins recipe only. The adapter keeps
518
+ reading ``target-path``, so the orphan sweep
519
+ (``_skill_direct_directory_target``) resolves the same route-correct target
520
+ for free — had the route reached the projection but not the sweep, the sweep
521
+ would silently target a nonexistent directory.
522
+ """
523
+ if recipe.name != "per-pack-claude-plugin" or recipe.adapter != "claude-code":
524
+ return contract
525
+ entries = contract["adapter"]["claude-code"].get("projection", [])
526
+ missing = [
527
+ e["primitive"] for e in entries
528
+ if e.get("primitive") in ("skill", "agent", "command")
529
+ and "plugin-target-path" not in e
530
+ ]
531
+ if missing:
532
+ # Fail loud. Returning the un-rerouted contract here would silently
533
+ # restore the `.claude/` layout — the empty-plugin defect this exists
534
+ # to prevent — for a typo'd key or a stale bundled adapter.toml.
535
+ raise ValueError(
536
+ "claude-plugins recipe: claude-code contract is missing "
537
+ f"'plugin-target-path' for {missing}; components would be "
538
+ "published under .claude/ where the plugin loader cannot see them"
539
+ )
540
+ rerouted = [
541
+ {**entry, "target-path": entry["plugin-target-path"]}
542
+ if "plugin-target-path" in entry
543
+ else entry
544
+ for entry in entries
545
+ ]
546
+ adapters = dict(contract["adapter"])
547
+ adapters["claude-code"] = {
548
+ **contract["adapter"]["claude-code"], "projection": rerouted
549
+ }
550
+ return {**contract, "adapter": adapters}
551
+
552
+
488
553
  def _run_per_pack_single(
489
554
  pack: Pack,
490
555
  recipe: Recipe,
@@ -494,6 +559,7 @@ def _run_per_pack_single(
494
559
  produced: dict[str, str],
495
560
  ) -> None:
496
561
  """Execute the derivation pipeline for a single pack."""
562
+ contract = _resolve_contract_for_route(contract, recipe)
497
563
  per_pack_output = output_dir / recipe.output_subdir / pack.name
498
564
  _assert_under(per_pack_output, output_dir)
499
565
  # Transactional cleanup (Blocker-4): remove any prior partial or
@@ -700,19 +766,25 @@ def _run_aggregate(recipe: Recipe, output_dir: Path) -> dict:
700
766
  _assert_under(output_path, output_dir)
701
767
  output_path.parent.mkdir(parents=True, exist_ok=True)
702
768
 
703
- # Derive marketplace name and owner from the first entry that carries a
704
- # source.repo field (populated above from pack.toml via derive_projectable_subset).
769
+ # Derive marketplace name and owner from the first entry's `source.url`
770
+ # (populated above from pack.toml via derive_projectable_subset). This
771
+ # reads `url` rather than the former `repo`: a `git-subdir` source carries
772
+ # no `repo`, so leaving the old split in place would silently drop the
773
+ # envelope's `name`, `owner` and `description` — the same defect the
774
+ # 2026-07 "marketplace missing top-level name" fix already corrected once.
705
775
  marketplace_name: str | None = None
706
776
  marketplace_owner: dict | None = None
707
777
  for entry in entries:
708
778
  src = entry.get("source")
709
779
  if isinstance(src, dict):
710
- repo = src.get("repo", "")
711
- if isinstance(repo, str) and "/" in repo:
712
- owner_part, name_part = repo.split("/", 1)
713
- marketplace_name = name_part
714
- marketplace_owner = {"name": owner_part}
715
- break
780
+ url = src.get("url", "")
781
+ if isinstance(url, str):
782
+ m = _GITHUB_URL_RE.match(url)
783
+ if m:
784
+ owner_part, name_part = m.group(1).split("/", 1)
785
+ marketplace_name = name_part
786
+ marketplace_owner = {"name": owner_part}
787
+ break
716
788
 
717
789
  payload: dict = {}
718
790
  if marketplace_name:
@@ -62,14 +62,22 @@ class EndToEndBuildTests(unittest.TestCase):
62
62
  # primitives lands at its declared output under the `core` pack
63
63
  # — the only fixture that exercises every primitive type.
64
64
  core_plugin = tmp_path / "claude-plugins" / "core"
65
- self.assertTrue((core_plugin / ".claude" / "skills" / "example").exists())
66
- self.assertTrue((core_plugin / ".claude" / "agents" / "bar.md").exists())
65
+ # Components land at the PLUGIN ROOT on this route: Claude Code
66
+ # plugins load skills/, agents/ and commands/ from there, not from
67
+ # `.claude/`. Hook wiring is the exception — it stays at
68
+ # `.claude/settings.local.json`, which is where the harness reads it.
69
+ self.assertTrue((core_plugin / "skills" / "example").exists())
70
+ self.assertTrue((core_plugin / "agents" / "bar.md").exists())
67
71
  self.assertTrue((core_plugin / "tools" / "hooks" / "baz.sh").exists())
68
72
  self.assertTrue((core_plugin / "tools" / "hooks" / "baz.py").exists())
69
73
  self.assertTrue(
70
74
  (core_plugin / ".claude" / "settings.local.json").exists()
71
75
  )
72
- self.assertTrue((core_plugin / ".claude" / "commands" / "qux.md").exists())
76
+ self.assertTrue((core_plugin / "commands" / "qux.md").exists())
77
+ # …and the old locations are gone, so a half-applied move fails.
78
+ self.assertFalse((core_plugin / ".claude" / "skills").exists())
79
+ self.assertFalse((core_plugin / ".claude" / "agents").exists())
80
+ self.assertFalse((core_plugin / ".claude" / "commands").exists())
73
81
 
74
82
  def test_plain_build_does_not_invoke_self_host_recipes(self) -> None:
75
83
  """AC: plain `make build` produces only dist/apm, dist/claude-plugins,