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.
- {agentbundle-0.29.5 → agentbundle-0.29.6}/PKG-INFO +8 -4
- {agentbundle-0.29.5 → agentbundle-0.29.6}/README-pypi.md +7 -3
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/adapter.toml +3 -0
- agentbundle-0.29.6/agentbundle/_data/marketplace-entry.schema.json +110 -0
- agentbundle-0.29.6/agentbundle/_data/plugin-manifest.derived.schema.json +147 -0
- agentbundle-0.29.6/agentbundle/_data/plugin-manifest.schema.json +110 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/claude_code.py +27 -2
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/main.py +88 -16
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_end_to_end_build.py +11 -3
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_pipeline.py +2 -2
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_plugin_manifest_schema.py +4 -4
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_projectable_subset.py +4 -4
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_self_host_check.py +0 -1
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/verify.py +84 -25
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/upgrade.py +1 -1
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/version.py +1 -1
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle.egg-info/PKG-INFO +8 -4
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle.egg-info/SOURCES.txt +1 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/pyproject.toml +1 -1
- agentbundle-0.29.5/agentbundle/_data/plugin-manifest.derived.schema.json +0 -73
- agentbundle-0.29.5/agentbundle/_data/plugin-manifest.schema.json +0 -45
- {agentbundle-0.29.5 → agentbundle-0.29.6}/README.md +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/__init__.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/__main__.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/adapter.schema.json +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/guides/_shared/reference/catalogue-authoring-standards.md +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/guides/_shared/reference/catalogue-ci-contract.md +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/manifest.json +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/packs/AGENTS.md +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/packs/README.md +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/packs/_example/README.md +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/packs/_example/pack.toml +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/profiles/AGENTS.md +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/profiles/README.md +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/profiles/_example/README.md +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue-scaffold/profiles/_example/profile.toml +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/catalogue.schema.json +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/guide.schema.json +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/install-defaults.toml +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/install-marker.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/pack.schema.json +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/profile.schema.json +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/skill-manifest.schema.json +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/skill.schema.json +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/_data/target-vocab.toml +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/__init__.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/__main__.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapter_root_bins.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/__init__.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/codex.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/copilot.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/cursor.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/gemini.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/kiro.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/kiro_cli.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/adapters/kiro_ide.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/contract.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/lint_packs.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/phase_order.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/__init__.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/codex_agent_toml.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/copilot_agent_md.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/copilot_hooks_json.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/direct_directory.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/gemini_command_toml.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/hook_id.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/kiro_ide_hook.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/merge_into_agent_json.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/merge_json.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/projections/user_merge_json.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/recipes/composite-agents-md.toml +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/recipes/composite-marketplace.toml +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/recipes/marketplace.toml +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/recipes/per-pack-apm-package.toml +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/recipes/per-pack-claude-plugin.toml +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/recipes/per-pack-overlay.toml +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/recipes/self-host.toml +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/scope_rails.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/self_host.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/shared_libs.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/target_resolver.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/__init__.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_claude_code.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_codex.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_copilot.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_cursor.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_gemini.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_kiro.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_kiro_alias.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_kiro_cli.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_kiro_ide.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_adapter_root_bins_projection.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_architect_design_reviewer_projection.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_architect_design_reviewer_rubric_parity.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_build_ships_seeds.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_contract.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_contract_scope.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_contract_v07.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_contract_v08.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_direct_directory_cleanup.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_lint_agents_md_diataxis_block.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_lint_agents_md_legacy_block.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_lint_agents_md_risk_block.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_lint_packs.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_load_pack_hook_wiring_safely.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_pack_schema.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_pack_schema_allowed_adapters.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_pack_schema_install.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_projections_merge_json.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_scope_rails.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_security.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_self_host_fixture_guard.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_self_host_recipe_config.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_shared_libs_projection.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_shared_prefix_contract.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_shipped_packs_v07_declarations.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_shipped_packs_v08_declarations.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_user_libs_projection.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_validate.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_workspace_status_projection.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/tests/test_writers_emit_lf.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/user_libs.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/build/validate.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/__init__.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/archive.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/build.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/config.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/defaults.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/diagnostics.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/identity.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/initialise.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/initialise_self_hosted.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/lint.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/package.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/results.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/self_host.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/self_host_windows.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/skill_spec_lint.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/catalogue_tooling/toml_emit.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/categories.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/cli.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/__init__.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/_common.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/_drop_warning.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/adapt.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/catalogue_build.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/catalogue_init.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/catalogue_lint.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/catalogue_package.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/catalogue_self_host.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/catalogue_sync_defaults.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/catalogue_tooling_stub.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/catalogue_verify.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/config.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/diff.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/docs.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/init_state.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/install.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/list_installed.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/list_packs.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/list_profiles.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/list_targets.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/oplog_cmd.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/pack_config_cmd.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/pack_evals.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/package_catalogue.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/profile.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/reconcile.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/render.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/scaffold.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/show.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/uninstall.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/commands/validate.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/config.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/https_catalogue.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/local_exclude.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/oplog.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/pack_inventory.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/render.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/safety.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/scaffold.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/scope.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/source_defaults.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/statelock.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/user_config.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle/workspace_mcp.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle.egg-info/dependency_links.txt +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle.egg-info/entry_points.txt +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle.egg-info/requires.txt +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/agentbundle.egg-info/top_level.txt +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/setup.cfg +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/tests/test_adapter_permissions_projection.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/tests/test_linear_primitive.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/tests/test_workspace_mcp_elicit.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/tests/test_workspace_mcp_event_bridge.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/tests/test_workspace_mcp_git.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/tests/test_workspace_mcp_lifecycle.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.29.6}/tests/test_workspace_mcp_stdin.py +0 -0
- {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.
|
|
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.
|
|
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`, `
|
|
289
|
-
|
|
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.
|
|
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`, `
|
|
267
|
-
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
210
|
-
GitHub URL: ``{"source": "
|
|
211
|
-
"
|
|
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": "
|
|
262
|
-
"
|
|
263
|
-
"
|
|
264
|
-
"
|
|
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
|
|
704
|
-
#
|
|
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
|
-
|
|
711
|
-
if isinstance(
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
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
|
-
|
|
66
|
-
|
|
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 / "
|
|
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,
|