agentbundle 0.29.8__tar.gz → 0.31.0__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 (201) hide show
  1. {agentbundle-0.29.8 → agentbundle-0.31.0}/PKG-INFO +24 -4
  2. {agentbundle-0.29.8 → agentbundle-0.31.0}/README-pypi.md +23 -3
  3. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/guides/_shared/reference/catalogue-authoring-standards.md +24 -5
  4. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/manifest.json +3 -3
  5. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/packs/_example/pack.toml +1 -1
  6. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/install-marker.py +7 -3
  7. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/adapter_root_bins.py +146 -30
  8. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/main.py +275 -20
  9. agentbundle-0.31.0/agentbundle/build/projection_io.py +226 -0
  10. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/recipes/composite-marketplace.toml +1 -1
  11. agentbundle-0.31.0/agentbundle/build/recipes/marketplace.toml +9 -0
  12. agentbundle-0.31.0/agentbundle/build/recipes/per-pack-claude-plugin.toml +9 -0
  13. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/recipes/self-host.toml +1 -1
  14. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/self_host.py +258 -96
  15. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/user_libs.py +209 -26
  16. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/initialise_self_hosted.py +66 -1
  17. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/self_host.py +31 -2
  18. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/self_host_windows.py +4 -4
  19. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/cli.py +4 -3
  20. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/install.py +11 -4
  21. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/upgrade.py +9 -6
  22. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/render.py +6 -2
  23. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/version.py +1 -1
  24. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle.egg-info/PKG-INFO +24 -4
  25. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle.egg-info/SOURCES.txt +1 -45
  26. {agentbundle-0.29.8 → agentbundle-0.31.0}/pyproject.toml +2 -2
  27. agentbundle-0.29.8/agentbundle/build/recipes/marketplace.toml +0 -8
  28. agentbundle-0.29.8/agentbundle/build/recipes/per-pack-claude-plugin.toml +0 -7
  29. agentbundle-0.29.8/agentbundle/build/tests/__init__.py +0 -0
  30. agentbundle-0.29.8/agentbundle/build/tests/test_adapter_claude_code.py +0 -281
  31. agentbundle-0.29.8/agentbundle/build/tests/test_adapter_codex.py +0 -743
  32. agentbundle-0.29.8/agentbundle/build/tests/test_adapter_copilot.py +0 -120
  33. agentbundle-0.29.8/agentbundle/build/tests/test_adapter_cursor.py +0 -418
  34. agentbundle-0.29.8/agentbundle/build/tests/test_adapter_gemini.py +0 -636
  35. agentbundle-0.29.8/agentbundle/build/tests/test_adapter_kiro.py +0 -464
  36. agentbundle-0.29.8/agentbundle/build/tests/test_adapter_kiro_alias.py +0 -106
  37. agentbundle-0.29.8/agentbundle/build/tests/test_adapter_kiro_cli.py +0 -143
  38. agentbundle-0.29.8/agentbundle/build/tests/test_adapter_kiro_ide.py +0 -214
  39. agentbundle-0.29.8/agentbundle/build/tests/test_adapter_root_bins_projection.py +0 -491
  40. agentbundle-0.29.8/agentbundle/build/tests/test_architect_design_reviewer_projection.py +0 -88
  41. agentbundle-0.29.8/agentbundle/build/tests/test_architect_design_reviewer_rubric_parity.py +0 -74
  42. agentbundle-0.29.8/agentbundle/build/tests/test_build_ships_seeds.py +0 -81
  43. agentbundle-0.29.8/agentbundle/build/tests/test_contract.py +0 -617
  44. agentbundle-0.29.8/agentbundle/build/tests/test_contract_scope.py +0 -224
  45. agentbundle-0.29.8/agentbundle/build/tests/test_contract_v07.py +0 -196
  46. agentbundle-0.29.8/agentbundle/build/tests/test_contract_v08.py +0 -266
  47. agentbundle-0.29.8/agentbundle/build/tests/test_direct_directory_cleanup.py +0 -65
  48. agentbundle-0.29.8/agentbundle/build/tests/test_end_to_end_build.py +0 -233
  49. agentbundle-0.29.8/agentbundle/build/tests/test_lint_agents_md_diataxis_block.py +0 -95
  50. agentbundle-0.29.8/agentbundle/build/tests/test_lint_agents_md_legacy_block.py +0 -136
  51. agentbundle-0.29.8/agentbundle/build/tests/test_lint_agents_md_risk_block.py +0 -119
  52. agentbundle-0.29.8/agentbundle/build/tests/test_lint_packs.py +0 -716
  53. agentbundle-0.29.8/agentbundle/build/tests/test_load_pack_hook_wiring_safely.py +0 -176
  54. agentbundle-0.29.8/agentbundle/build/tests/test_pack_schema.py +0 -494
  55. agentbundle-0.29.8/agentbundle/build/tests/test_pack_schema_allowed_adapters.py +0 -258
  56. agentbundle-0.29.8/agentbundle/build/tests/test_pack_schema_install.py +0 -305
  57. agentbundle-0.29.8/agentbundle/build/tests/test_pipeline.py +0 -275
  58. agentbundle-0.29.8/agentbundle/build/tests/test_plugin_manifest_schema.py +0 -422
  59. agentbundle-0.29.8/agentbundle/build/tests/test_projectable_subset.py +0 -202
  60. agentbundle-0.29.8/agentbundle/build/tests/test_projections_merge_json.py +0 -151
  61. agentbundle-0.29.8/agentbundle/build/tests/test_scope_rails.py +0 -401
  62. agentbundle-0.29.8/agentbundle/build/tests/test_security.py +0 -102
  63. agentbundle-0.29.8/agentbundle/build/tests/test_self_host_check.py +0 -2277
  64. agentbundle-0.29.8/agentbundle/build/tests/test_self_host_fixture_guard.py +0 -88
  65. agentbundle-0.29.8/agentbundle/build/tests/test_self_host_recipe_config.py +0 -113
  66. agentbundle-0.29.8/agentbundle/build/tests/test_shared_libs_projection.py +0 -218
  67. agentbundle-0.29.8/agentbundle/build/tests/test_shared_prefix_contract.py +0 -114
  68. agentbundle-0.29.8/agentbundle/build/tests/test_shipped_packs_v07_declarations.py +0 -109
  69. agentbundle-0.29.8/agentbundle/build/tests/test_shipped_packs_v08_declarations.py +0 -92
  70. agentbundle-0.29.8/agentbundle/build/tests/test_user_libs_projection.py +0 -285
  71. agentbundle-0.29.8/agentbundle/build/tests/test_validate.py +0 -250
  72. agentbundle-0.29.8/agentbundle/build/tests/test_workspace_status_projection.py +0 -273
  73. agentbundle-0.29.8/agentbundle/build/tests/test_writers_emit_lf.py +0 -171
  74. {agentbundle-0.29.8 → agentbundle-0.31.0}/README.md +0 -0
  75. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/__init__.py +0 -0
  76. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/__main__.py +0 -0
  77. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/adapter.schema.json +0 -0
  78. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/adapter.toml +0 -0
  79. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/guides/_shared/reference/catalogue-ci-contract.md +0 -0
  80. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/packs/AGENTS.md +0 -0
  81. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/packs/README.md +0 -0
  82. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/packs/_example/README.md +0 -0
  83. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/profiles/AGENTS.md +0 -0
  84. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/profiles/README.md +0 -0
  85. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/profiles/_example/README.md +0 -0
  86. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/profiles/_example/profile.toml +0 -0
  87. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/catalogue.schema.json +0 -0
  88. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/guide.schema.json +0 -0
  89. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/install-defaults.toml +0 -0
  90. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/marketplace-entry.schema.json +0 -0
  91. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/pack.schema.json +0 -0
  92. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/plugin-manifest.derived.schema.json +0 -0
  93. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/plugin-manifest.schema.json +0 -0
  94. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/profile.schema.json +0 -0
  95. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/skill-manifest.schema.json +0 -0
  96. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/skill.schema.json +0 -0
  97. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/_data/target-vocab.toml +0 -0
  98. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/__init__.py +0 -0
  99. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/__main__.py +0 -0
  100. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/adapters/__init__.py +0 -0
  101. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/adapters/claude_code.py +0 -0
  102. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/adapters/codex.py +0 -0
  103. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/adapters/copilot.py +0 -0
  104. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/adapters/cursor.py +0 -0
  105. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/adapters/gemini.py +0 -0
  106. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/adapters/kiro.py +0 -0
  107. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/adapters/kiro_cli.py +0 -0
  108. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/adapters/kiro_ide.py +0 -0
  109. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/contract.py +0 -0
  110. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/lint_packs.py +0 -0
  111. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/phase_order.py +0 -0
  112. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/projections/__init__.py +0 -0
  113. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/projections/codex_agent_toml.py +0 -0
  114. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/projections/copilot_agent_md.py +0 -0
  115. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/projections/copilot_hooks_json.py +0 -0
  116. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/projections/direct_directory.py +0 -0
  117. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/projections/gemini_command_toml.py +0 -0
  118. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/projections/hook_id.py +0 -0
  119. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/projections/kiro_ide_hook.py +0 -0
  120. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/projections/merge_into_agent_json.py +0 -0
  121. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/projections/merge_json.py +0 -0
  122. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/projections/user_merge_json.py +0 -0
  123. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/recipes/composite-agents-md.toml +0 -0
  124. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/recipes/per-pack-apm-package.toml +0 -0
  125. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/recipes/per-pack-overlay.toml +0 -0
  126. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/scope_rails.py +0 -0
  127. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/shared_libs.py +0 -0
  128. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/target_resolver.py +0 -0
  129. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/build/validate.py +0 -0
  130. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue.py +0 -0
  131. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/__init__.py +0 -0
  132. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/archive.py +0 -0
  133. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/build.py +0 -0
  134. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/config.py +0 -0
  135. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/defaults.py +0 -0
  136. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/diagnostics.py +0 -0
  137. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/identity.py +0 -0
  138. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/initialise.py +0 -0
  139. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/lint.py +0 -0
  140. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/package.py +0 -0
  141. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/results.py +0 -0
  142. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/skill_spec_lint.py +0 -0
  143. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/toml_emit.py +0 -0
  144. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/verify.py +0 -0
  145. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/categories.py +0 -0
  146. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/__init__.py +0 -0
  147. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/_common.py +0 -0
  148. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/_drop_warning.py +0 -0
  149. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/adapt.py +0 -0
  150. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/catalogue_build.py +0 -0
  151. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/catalogue_init.py +0 -0
  152. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/catalogue_lint.py +0 -0
  153. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/catalogue_package.py +0 -0
  154. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/catalogue_self_host.py +0 -0
  155. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/catalogue_sync_defaults.py +0 -0
  156. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/catalogue_tooling_stub.py +0 -0
  157. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/catalogue_verify.py +0 -0
  158. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/config.py +0 -0
  159. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/diff.py +0 -0
  160. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/docs.py +0 -0
  161. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/init_state.py +0 -0
  162. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/list_installed.py +0 -0
  163. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/list_packs.py +0 -0
  164. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/list_profiles.py +0 -0
  165. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/list_targets.py +0 -0
  166. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/oplog_cmd.py +0 -0
  167. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/pack_config_cmd.py +0 -0
  168. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/pack_evals.py +0 -0
  169. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/package_catalogue.py +0 -0
  170. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/profile.py +0 -0
  171. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/reconcile.py +0 -0
  172. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/render.py +0 -0
  173. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/scaffold.py +0 -0
  174. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/show.py +0 -0
  175. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/uninstall.py +0 -0
  176. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/commands/validate.py +0 -0
  177. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/config.py +0 -0
  178. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/https_catalogue.py +0 -0
  179. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/local_exclude.py +0 -0
  180. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/oplog.py +0 -0
  181. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/pack_inventory.py +0 -0
  182. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/safety.py +0 -0
  183. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/scaffold.py +0 -0
  184. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/scope.py +0 -0
  185. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/source_defaults.py +0 -0
  186. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/statelock.py +0 -0
  187. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/user_config.py +0 -0
  188. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle/workspace_mcp.py +0 -0
  189. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle.egg-info/dependency_links.txt +0 -0
  190. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle.egg-info/entry_points.txt +0 -0
  191. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle.egg-info/requires.txt +0 -0
  192. {agentbundle-0.29.8 → agentbundle-0.31.0}/agentbundle.egg-info/top_level.txt +0 -0
  193. {agentbundle-0.29.8 → agentbundle-0.31.0}/setup.cfg +0 -0
  194. {agentbundle-0.29.8 → agentbundle-0.31.0}/tests/test_adapter_permissions_projection.py +0 -0
  195. {agentbundle-0.29.8 → agentbundle-0.31.0}/tests/test_linear_primitive.py +0 -0
  196. {agentbundle-0.29.8 → agentbundle-0.31.0}/tests/test_workspace_mcp_elicit.py +0 -0
  197. {agentbundle-0.29.8 → agentbundle-0.31.0}/tests/test_workspace_mcp_event_bridge.py +0 -0
  198. {agentbundle-0.29.8 → agentbundle-0.31.0}/tests/test_workspace_mcp_git.py +0 -0
  199. {agentbundle-0.29.8 → agentbundle-0.31.0}/tests/test_workspace_mcp_lifecycle.py +0 -0
  200. {agentbundle-0.29.8 → agentbundle-0.31.0}/tests/test_workspace_mcp_stdin.py +0 -0
  201. {agentbundle-0.29.8 → agentbundle-0.31.0}/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.8
3
+ Version: 0.31.0
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. A marketplace entry's `source` is a `git-subdir`
272
+ than with a single sentence. The Claude-plugin route carries only packs whose
273
+ `[pack.install] allowed-scopes` admits `user`: a plugin's code lands in the
274
+ adopter's global cache, so a repo-only pack gets no `marketplace.json` entry
275
+ and is reached with `agentbundle install` instead. A marketplace entry's `source` is a `git-subdir`
273
276
  object (`url`, `path`, and one of `ref`/`sha`) pointing at the pack's directory
274
277
  on the published distribution branch, and every entry is schema-validated at
275
278
  build time against `marketplace-entry.schema.json`. Extra fields stay in `pack.toml`; the projection
@@ -305,13 +308,30 @@ pip install 'agentbundle[lint]'
305
308
  agentbundle catalogue lint --root . --deep
306
309
  ```
307
310
 
308
- **Check self-host projection drift** — verifies that adapter-projected files (skills, agents, hooks) match their `.apm/` sources without writing anything:
311
+ **Verify a catalogue before you ship it** — runs the full read-only contract and
312
+ self-host checks in one command:
313
+
314
+ ```bash
315
+ agentbundle catalogue verify --root .
316
+ ```
317
+
318
+ For a self-host-enabled catalogue with `.adapt-discovery.toml`, that includes the
319
+ self-host classifier. It treats generated targets as projected and known
320
+ repository-owned paths as excluded from projection. A genuinely unknown Git-visible
321
+ path remains an informational `unclassified` notice; it does not fail an otherwise
322
+ clean catalogue. Missing, modified, or orphaned projections do fail verification,
323
+ including generated executables under `.agentbundle/bin/` and vendored user libraries
324
+ under `.agentbundle/lib/`. Git filenames are read losslessly, and a failed Git listing
325
+ is reported as a warning rather than mistaken for a fully classified inventory.
326
+
327
+ To check only self-host projection drift, or to regenerate projected files locally:
309
328
 
310
329
  ```bash
311
330
  agentbundle catalogue self-host --check --root .
331
+ agentbundle catalogue self-host --write --root .
312
332
  ```
313
333
 
314
- Exits non-zero if any projected file is out of date. Safe to run in CI as a required check; use `--write` locally to regenerate.
334
+ Both check commands are safe to run in CI. The write command changes projected files.
315
335
 
316
336
  By default projects for `claude-code` and `codex`. Downstream repos that use a single adapter (e.g. `kiro-ide`) can declare it in `catalogue.toml` — only that adapter is then projected, and its output files participate in the drift check:
317
337
 
@@ -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. A marketplace entry's `source` is a `git-subdir`
250
+ than with a single sentence. The Claude-plugin route carries only packs whose
251
+ `[pack.install] allowed-scopes` admits `user`: a plugin's code lands in the
252
+ adopter's global cache, so a repo-only pack gets no `marketplace.json` entry
253
+ and is reached with `agentbundle install` instead. A marketplace entry's `source` is a `git-subdir`
251
254
  object (`url`, `path`, and one of `ref`/`sha`) pointing at the pack's directory
252
255
  on the published distribution branch, and every entry is schema-validated at
253
256
  build time against `marketplace-entry.schema.json`. Extra fields stay in `pack.toml`; the projection
@@ -283,13 +286,30 @@ pip install 'agentbundle[lint]'
283
286
  agentbundle catalogue lint --root . --deep
284
287
  ```
285
288
 
286
- **Check self-host projection drift** — verifies that adapter-projected files (skills, agents, hooks) match their `.apm/` sources without writing anything:
289
+ **Verify a catalogue before you ship it** — runs the full read-only contract and
290
+ self-host checks in one command:
291
+
292
+ ```bash
293
+ agentbundle catalogue verify --root .
294
+ ```
295
+
296
+ For a self-host-enabled catalogue with `.adapt-discovery.toml`, that includes the
297
+ self-host classifier. It treats generated targets as projected and known
298
+ repository-owned paths as excluded from projection. A genuinely unknown Git-visible
299
+ path remains an informational `unclassified` notice; it does not fail an otherwise
300
+ clean catalogue. Missing, modified, or orphaned projections do fail verification,
301
+ including generated executables under `.agentbundle/bin/` and vendored user libraries
302
+ under `.agentbundle/lib/`. Git filenames are read losslessly, and a failed Git listing
303
+ is reported as a warning rather than mistaken for a fully classified inventory.
304
+
305
+ To check only self-host projection drift, or to regenerate projected files locally:
287
306
 
288
307
  ```bash
289
308
  agentbundle catalogue self-host --check --root .
309
+ agentbundle catalogue self-host --write --root .
290
310
  ```
291
311
 
292
- Exits non-zero if any projected file is out of date. Safe to run in CI as a required check; use `--write` locally to regenerate.
312
+ Both check commands are safe to run in CI. The write command changes projected files.
293
313
 
294
314
  By default projects for `claude-code` and `codex`. Downstream repos that use a single adapter (e.g. `kiro-ide`) can declare it in `catalogue.toml` — only that adapter is then projected, and its output files participate in the drift check:
295
315
 
@@ -46,12 +46,31 @@ model reads to decide whether to **activate** the primitive. Length is load-bear
46
46
  there and shortening it degrades activation; per-target caps in
47
47
  `contracts/target-vocab.toml` govern it. Do not carry habits from one to the other.
48
48
 
49
- **Shape.** First sentence names the job the adopter accomplishes — verb-first, and
50
- readable on its own. An optional second sentence carries a compressed capability list
51
- or the one thing that distinguishes this pack. Then stop.
49
+ **Shape.** Open on the job the adopter accomplishes, in their words. Say what they
50
+ get. Then stop.
52
51
 
53
- > Supervised coding from brief to merged PR. A plan, execute, verify, review loop with
54
- > spec-driven development, adversarial and security reviewers, and pre-commit gates.
52
+ Beyond that, let the pack decide the shape. Some need one sentence:
53
+
54
+ > Write the OpenAPI or AsyncAPI contract before anyone writes a handler.
55
+
56
+ Others earn three:
57
+
58
+ > Ship it the way production will see it. Deploy to a throwaway environment, run
59
+ > the tests, read the telemetry, and go round again until it holds. Then it stops
60
+ > and asks, because the next step is the one you cannot undo.
61
+
62
+ **Do not run every description through one mould.** An earlier pass here applied a
63
+ single shape — verb-first sentence, then a comma-list of capabilities — to all
64
+ 22 packs. The result measured as 20 of 22 at exactly two sentences, 14 with a
65
+ comma-list second sentence, four opening on the identical "Turn X into Y" frame.
66
+ Every fact was right and the set still read as machine-written, because uniform
67
+ rhythm and symmetrical construction are themselves the tell. Vary sentence count
68
+ and length to match what each pack actually is.
69
+
70
+ Reach for the concrete. A real thing the user says (`"convert this PDF to
71
+ Markdown"`), a real artifact (`a Google-style design doc`), or a real check
72
+ (`the empty state and the focus ring you forgot`) all beat an abstract capability
73
+ noun.
55
74
 
56
75
  **Anti-patterns**, each of which has shipped here before:
57
76
 
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "files": {
3
- "guides/_shared/reference/catalogue-authoring-standards.md": "f5e41498139ca335b8a679644eb02d2a35abb2234a77b5b14e7ff90da02722b9",
3
+ "guides/_shared/reference/catalogue-authoring-standards.md": "ff4bdc203affda0a2f41641c1155b3f4e90aade022e122999a82e7093e94d2ee",
4
4
  "guides/_shared/reference/catalogue-ci-contract.md": "fae793ab47989b6dd3c731afcb0b4cda21c7d08bbe7fa40fca6d3abb3d158141",
5
5
  "packs/AGENTS.md": "9bfeda4069826e518a4f4fdae45bd40f4393c1c5aaf146149d3eb4aece30be83",
6
6
  "packs/README.md": "d2de5f9556f4c8e521103474bde74636e02cc805f9bf5312a3a61a1f3eb45d8f",
7
7
  "packs/_example/.apm/skills/example-skill/SKILL.md": "33be8cbf4b2c014a5a63e788b7d0b350ad8061c6c4b2579369a3e984135bf9f1",
8
8
  "packs/_example/.apm/skills/example-skill/evals/eval_queries.json": "f41ecda0834a22f3b4823c81ab02e58b0e4beba610e3b40c185579abff9cfeee",
9
- "packs/_example/.claude-plugin/plugin.json": "d38c8456640d5e2f9296361f7e3e675e368ddd3eb22a6245267560f460155f41",
9
+ "packs/_example/.claude-plugin/plugin.json": "7f94084a56260eed225ec47ac82042fe9029c594557cca760a459885d03ccc26",
10
10
  "packs/_example/README.md": "ef130c9c1f97a75a07cc59fc55fc5b3bf71846dd2f06c3cddf5a1154023b6ef6",
11
- "packs/_example/pack.toml": "94e2c7fd25d4d115858728c7ecb8f739adfd0f594b29596c106daba0791a4b94",
11
+ "packs/_example/pack.toml": "f19a0be9fca99a6a0e3ce2d5cd188bf98000f0a4f186954fb42a0c99c6859701",
12
12
  "profiles/AGENTS.md": "8950438d9e0f57c13613104c88c90b598b53196c91bfdced6d63e4e01b5e9254",
13
13
  "profiles/README.md": "a0b0268edc57fc575f7fea08f3363ba7da9f6e67dc4a0a6f8bd38c9668c97922",
14
14
  "profiles/_example/README.md": "164494df049ddce3e57cb44ed604cb3d39be0a6ec2072e609ea3fa4bbfc74c72",
@@ -1,7 +1,7 @@
1
1
  [pack]
2
2
  name = "example-pack"
3
3
  version = "0.1.0"
4
- description = "A minimal example pack demonstrating the standard authoring layout."
4
+ description = "The skeleton to copy when you start a new pack."
5
5
  display_name = "Example Pack"
6
6
  categories = ["productivity"]
7
7
  keywords = ["example", "template"]
@@ -1,9 +1,13 @@
1
1
  """Canonical stdlib-only install-marker writer for the Claude-plugins and APM install routes.
2
2
 
3
3
  This script is invoked by a ``SessionStart`` hook derived by ``agentbundle build``
4
- into every pack's projected output:
5
- - ``dist/claude-plugins/<pack>/.claude-plugin/plugin.json`` — claude-plugins route
6
- - ``dist/apm/<pack>/.apm/hooks/install-marker.json`` — APM route
4
+ into each pack's projected output:
5
+ - ``dist/claude-plugins/<pack>/.claude-plugin/plugin.json`` — claude-plugins
6
+ route, for user-capable packs only (a plugin's code lands in the adopter's
7
+ global cache, so a pack whose ``allowed-scopes`` omits ``user`` is not
8
+ projected onto this route at all)
9
+ - ``dist/apm/<pack>/.apm/hooks/install-marker.json`` — APM route,
10
+ every pack
7
11
 
8
12
  It detects first-install-or-update and writes a ``[[packs-installed]]`` entry
9
13
  to the scope-correct ``.adapt-install-marker.toml`` file so the existing core
@@ -36,11 +36,19 @@ from __future__ import annotations
36
36
 
37
37
  import contextlib
38
38
  import os
39
- import shutil
39
+ import stat
40
40
  from dataclasses import dataclass
41
41
  from pathlib import Path
42
42
 
43
43
  from . import shared_libs
44
+ from .projection_io import (
45
+ ProjectionTypeError,
46
+ copy_file_atomic_no_follow,
47
+ ensure_directory_no_follow,
48
+ open_directory_no_follow,
49
+ read_regular_file_no_follow,
50
+ render_diagnostic_path,
51
+ )
44
52
 
45
53
  # Pin the source path so a downstream consumer that wants to enumerate
46
54
  # sources doesn't hardcode the literal repeatedly.
@@ -72,6 +80,11 @@ SHIM_COMPANION_BASENAME = "credentials_shim.py"
72
80
  SHIM_IMPORT_GREP = b"from .credentials_shim import"
73
81
 
74
82
 
83
+ def _display(path: Path, base: Path) -> str:
84
+ """Render one path relative to its diagnostic base on one line."""
85
+ return render_diagnostic_path(path.relative_to(base))
86
+
87
+
75
88
  @dataclass(frozen=True)
76
89
  class AdapterRootBinProjection:
77
90
  """One concrete projection: copy ``source`` to ``target``."""
@@ -100,9 +113,12 @@ def collect_sources(packs_dir: Path) -> dict[str, Path]:
100
113
  continue
101
114
  for src in sorted(bins.glob("*.py")):
102
115
  if src.name in sources:
116
+ basename = render_diagnostic_path(Path(src.name))
117
+ first_source = _display(sources[src.name], packs_dir.parent)
118
+ second_source = _display(src, packs_dir.parent)
103
119
  raise ValueError(
104
- f"adapter-root-bins collision: '{src.name}' shipped by both "
105
- f"{sources[src.name]} and {src}"
120
+ f"adapter-root-bins collision: {basename} shipped by both "
121
+ f"{first_source} and {second_source}"
106
122
  )
107
123
  sources[src.name] = src
108
124
  return sources
@@ -155,9 +171,12 @@ def _assert_shim_companion_present(packs_dir: Path) -> None:
155
171
  if SHIM_IMPORT_GREP in body:
156
172
  offenders.append(src.name)
157
173
  if offenders:
158
- offender_list = ", ".join(offenders)
174
+ offender_list = ", ".join(
175
+ render_diagnostic_path(Path(SOURCE_SUBDIR) / offender)
176
+ for offender in offenders
177
+ )
159
178
  raise ValueError(
160
- f"adapter-root-bins/{{{offender_list}}} imports "
179
+ f"{offender_list} imports "
161
180
  f".credentials_shim but .apm/shared-libs/credentials_shim.py "
162
181
  f"is missing in pack {pack.name!r} — the importing module's "
163
182
  f"Tier-2 dispatch would degrade silently on macOS/Windows"
@@ -286,6 +305,27 @@ def _is_companion_projection(proj: AdapterRootBinProjection) -> bool:
286
305
  return proj.source.parent.name == shared_libs_leaf
287
306
 
288
307
 
308
+ def _target_python_names(target_dir: Path, target_fd: int | None) -> list[str]:
309
+ """List non-directory ``*.py`` entries through an already-held directory."""
310
+ if target_fd is None:
311
+ return [
312
+ path.name for path in target_dir.glob("*.py") if not path.is_dir()
313
+ ]
314
+ names: list[str] = []
315
+ for name in os.listdir(target_fd): # noqa: PTH208 — directory descriptor
316
+ if not name.endswith(".py"):
317
+ continue
318
+ try:
319
+ entry_stat = os.stat(
320
+ name, dir_fd=target_fd, follow_symlinks=False
321
+ )
322
+ except FileNotFoundError:
323
+ continue
324
+ if not stat.S_ISDIR(entry_stat.st_mode):
325
+ names.append(name)
326
+ return names
327
+
328
+
289
329
  def apply_projection(working_tree: Path, packs_dir: Path) -> None:
290
330
  """Write every projection target and remove orphans.
291
331
 
@@ -307,20 +347,28 @@ def apply_projection(working_tree: Path, packs_dir: Path) -> None:
307
347
  _assert_shim_companion_present(packs_dir)
308
348
  projections = compute_projections(working_tree, packs_dir)
309
349
  expected_targets = {p.target for p in projections}
350
+ ensure_directory_no_follow(working_tree, TARGET_SUBDIR)
310
351
  for proj in projections:
311
- proj.target.parent.mkdir(parents=True, exist_ok=True)
312
- shutil.copyfile(proj.source, proj.target)
313
- if os.name == "posix":
314
- with contextlib.suppress(OSError):
315
- proj.target.chmod(EXECUTABLE_MODE)
352
+ copy_file_atomic_no_follow(
353
+ proj.source,
354
+ proj.target,
355
+ base=working_tree,
356
+ mode=EXECUTABLE_MODE,
357
+ )
316
358
  # Orphan removal: any *.py file under <working_tree>/.agentbundle/bin/
317
359
  # not claimed by an expected target.
318
360
  target_dir = working_tree / TARGET_SUBDIR
319
- if target_dir.is_dir():
320
- for existing in sorted(target_dir.glob("*.py")):
321
- if existing not in expected_targets:
322
- with contextlib.suppress(FileNotFoundError): # pragma: no cover — race-only
361
+ with open_directory_no_follow(working_tree, TARGET_SUBDIR) as target_fd:
362
+ for name in sorted(_target_python_names(target_dir, target_fd)):
363
+ existing = target_dir / name
364
+ if existing in expected_targets:
365
+ continue
366
+ if target_fd is None:
367
+ with contextlib.suppress(FileNotFoundError): # pragma: no cover
323
368
  existing.unlink()
369
+ else:
370
+ with contextlib.suppress(FileNotFoundError): # pragma: no cover
371
+ os.unlink(name, dir_fd=target_fd)
324
372
 
325
373
 
326
374
  def check_drift(working_tree: Path, packs_dir: Path) -> list[str]:
@@ -348,6 +396,33 @@ def check_drift(working_tree: Path, packs_dir: Path) -> list[str]:
348
396
  target_dir = working_tree / TARGET_SUBDIR
349
397
  expected_targets: set[Path] = set()
350
398
 
399
+ current = working_tree
400
+ for part in TARGET_SUBDIR.parts:
401
+ current /= part
402
+ try:
403
+ current_stat = current.lstat()
404
+ except FileNotFoundError:
405
+ break
406
+ except OSError as exc:
407
+ drifts.append(
408
+ f"[adapter-root-bins] unreadable: "
409
+ f"{_display(current, working_tree)}: {exc}"
410
+ )
411
+ return drifts
412
+ if not stat.S_ISDIR(current_stat.st_mode):
413
+ kind = (
414
+ "a symlink"
415
+ if stat.S_ISLNK(current_stat.st_mode)
416
+ else "not a directory"
417
+ )
418
+ drifts.append(
419
+ f"[adapter-root-bins] type mismatch: "
420
+ f"{_display(current, working_tree)} is {kind}; "
421
+ f"expected a directory inside the working tree; "
422
+ f"run: make build-self FORCE=1"
423
+ )
424
+ return drifts
425
+
351
426
  for proj in compute_projections(working_tree, packs_dir):
352
427
  expected_targets.add(proj.target)
353
428
  prefix = (
@@ -360,34 +435,75 @@ def check_drift(working_tree: Path, packs_dir: Path) -> list[str]:
360
435
  except OSError as exc: # pragma: no cover — defensive
361
436
  drifts.append(f"{prefix} source unreadable: {exc}")
362
437
  continue
363
- if not proj.target.exists():
438
+ try:
439
+ target_bytes, target_stat = read_regular_file_no_follow(
440
+ proj.target,
441
+ base=working_tree,
442
+ )
443
+ except FileNotFoundError:
364
444
  drifts.append(
365
445
  f"{prefix} missing: "
366
- f"{proj.target.relative_to(working_tree).as_posix()} "
446
+ f"{_display(proj.target, working_tree)} "
367
447
  f"(source: "
368
- f"{proj.source.relative_to(packs_dir.parent).as_posix()}); "
448
+ f"{_display(proj.source, packs_dir.parent)}); "
369
449
  f"run: make build-self FORCE=1"
370
450
  )
371
451
  continue
372
- if proj.target.read_bytes() != source_bytes:
452
+ except ProjectionTypeError as exc:
453
+ drifts.append(
454
+ f"{prefix} type mismatch: "
455
+ f"{_display(proj.target, working_tree)} {exc}; "
456
+ f"expected a regular projected file; run: make build-self FORCE=1"
457
+ )
458
+ continue
459
+ except OSError as exc:
460
+ drifts.append(
461
+ f"{prefix} unreadable: "
462
+ f"{_display(proj.target, working_tree)}: {exc}"
463
+ )
464
+ continue
465
+ if (
466
+ os.name == "posix"
467
+ and stat.S_IMODE(target_stat.st_mode) != EXECUTABLE_MODE
468
+ ):
469
+ drifts.append(
470
+ f"{prefix} mode drift: "
471
+ f"{_display(proj.target, working_tree)} has "
472
+ f"{oct(stat.S_IMODE(target_stat.st_mode))}, expected "
473
+ f"{oct(EXECUTABLE_MODE)}; run: make build-self FORCE=1"
474
+ )
475
+ if target_bytes != source_bytes:
373
476
  drifts.append(
374
477
  f"{prefix} modified: "
375
- f"{proj.target.relative_to(working_tree).as_posix()} "
478
+ f"{_display(proj.target, working_tree)} "
376
479
  f"diverges from "
377
- f"{proj.source.relative_to(packs_dir.parent).as_posix()}; "
480
+ f"{_display(proj.source, packs_dir.parent)}; "
378
481
  f"run: make build-self FORCE=1"
379
482
  )
380
483
 
381
484
  # Orphan check.
382
- if target_dir.is_dir():
383
- for existing in sorted(target_dir.glob("*.py")):
384
- if existing not in expected_targets:
385
- drifts.append(
386
- f"[adapter-root-bins] orphaned: "
387
- f"{existing.relative_to(working_tree).as_posix()} "
388
- f"present but no pack ships "
389
- f"adapter-root-bins/{existing.name}; "
390
- f"run: make build-self FORCE=1"
391
- )
485
+ try:
486
+ with open_directory_no_follow(working_tree, TARGET_SUBDIR) as target_fd:
487
+ target_names = _target_python_names(target_dir, target_fd)
488
+ except FileNotFoundError:
489
+ target_names = []
490
+ except OSError as exc:
491
+ drifts.append(
492
+ f"[adapter-root-bins] unreadable: "
493
+ f"{render_diagnostic_path(TARGET_SUBDIR)}: {exc}; "
494
+ f"run: make build-self FORCE=1"
495
+ )
496
+ target_names = []
497
+ for name in sorted(target_names):
498
+ existing = target_dir / name
499
+ if existing not in expected_targets:
500
+ source_hint = render_diagnostic_path(Path("adapter-root-bins") / name)
501
+ drifts.append(
502
+ f"[adapter-root-bins] orphaned: "
503
+ f"{render_diagnostic_path(existing.relative_to(working_tree))} "
504
+ f"present but no pack ships "
505
+ f"{source_hint}; "
506
+ f"run: make build-self FORCE=1"
507
+ )
392
508
 
393
509
  return drifts