agentbundle 0.29.5__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.
- {agentbundle-0.29.5 → agentbundle-0.31.0}/PKG-INFO +30 -6
- {agentbundle-0.29.5 → agentbundle-0.31.0}/README-pypi.md +29 -5
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/adapter.toml +3 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/guides/_shared/reference/catalogue-authoring-standards.md +56 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/manifest.json +4 -4
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/packs/AGENTS.md +38 -38
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/packs/_example/pack.toml +1 -1
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/install-marker.py +95 -21
- agentbundle-0.31.0/agentbundle/_data/marketplace-entry.schema.json +110 -0
- agentbundle-0.31.0/agentbundle/_data/plugin-manifest.derived.schema.json +147 -0
- agentbundle-0.31.0/agentbundle/_data/plugin-manifest.schema.json +110 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/adapter_root_bins.py +146 -30
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/adapters/claude_code.py +27 -2
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/main.py +353 -26
- agentbundle-0.31.0/agentbundle/build/projection_io.py +226 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/recipes/composite-marketplace.toml +1 -1
- agentbundle-0.31.0/agentbundle/build/recipes/marketplace.toml +9 -0
- agentbundle-0.31.0/agentbundle/build/recipes/per-pack-claude-plugin.toml +9 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/recipes/self-host.toml +1 -1
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/self_host.py +258 -96
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/user_libs.py +209 -26
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/initialise_self_hosted.py +66 -1
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/self_host.py +31 -2
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/self_host_windows.py +19 -6
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/verify.py +84 -25
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/cli.py +4 -3
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/install.py +11 -4
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/upgrade.py +9 -6
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/render.py +6 -2
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/version.py +1 -1
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle.egg-info/PKG-INFO +30 -6
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle.egg-info/SOURCES.txt +2 -45
- {agentbundle-0.29.5 → agentbundle-0.31.0}/pyproject.toml +2 -2
- 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/build/recipes/marketplace.toml +0 -8
- agentbundle-0.29.5/agentbundle/build/recipes/per-pack-claude-plugin.toml +0 -7
- agentbundle-0.29.5/agentbundle/build/tests/__init__.py +0 -0
- agentbundle-0.29.5/agentbundle/build/tests/test_adapter_claude_code.py +0 -281
- agentbundle-0.29.5/agentbundle/build/tests/test_adapter_codex.py +0 -743
- agentbundle-0.29.5/agentbundle/build/tests/test_adapter_copilot.py +0 -120
- agentbundle-0.29.5/agentbundle/build/tests/test_adapter_cursor.py +0 -418
- agentbundle-0.29.5/agentbundle/build/tests/test_adapter_gemini.py +0 -636
- agentbundle-0.29.5/agentbundle/build/tests/test_adapter_kiro.py +0 -464
- agentbundle-0.29.5/agentbundle/build/tests/test_adapter_kiro_alias.py +0 -106
- agentbundle-0.29.5/agentbundle/build/tests/test_adapter_kiro_cli.py +0 -143
- agentbundle-0.29.5/agentbundle/build/tests/test_adapter_kiro_ide.py +0 -214
- agentbundle-0.29.5/agentbundle/build/tests/test_adapter_root_bins_projection.py +0 -491
- agentbundle-0.29.5/agentbundle/build/tests/test_architect_design_reviewer_projection.py +0 -88
- agentbundle-0.29.5/agentbundle/build/tests/test_architect_design_reviewer_rubric_parity.py +0 -74
- agentbundle-0.29.5/agentbundle/build/tests/test_build_ships_seeds.py +0 -81
- agentbundle-0.29.5/agentbundle/build/tests/test_contract.py +0 -617
- agentbundle-0.29.5/agentbundle/build/tests/test_contract_scope.py +0 -224
- agentbundle-0.29.5/agentbundle/build/tests/test_contract_v07.py +0 -196
- agentbundle-0.29.5/agentbundle/build/tests/test_contract_v08.py +0 -266
- agentbundle-0.29.5/agentbundle/build/tests/test_direct_directory_cleanup.py +0 -65
- agentbundle-0.29.5/agentbundle/build/tests/test_end_to_end_build.py +0 -225
- agentbundle-0.29.5/agentbundle/build/tests/test_lint_agents_md_diataxis_block.py +0 -95
- agentbundle-0.29.5/agentbundle/build/tests/test_lint_agents_md_legacy_block.py +0 -136
- agentbundle-0.29.5/agentbundle/build/tests/test_lint_agents_md_risk_block.py +0 -119
- agentbundle-0.29.5/agentbundle/build/tests/test_lint_packs.py +0 -716
- agentbundle-0.29.5/agentbundle/build/tests/test_load_pack_hook_wiring_safely.py +0 -176
- agentbundle-0.29.5/agentbundle/build/tests/test_pack_schema.py +0 -494
- agentbundle-0.29.5/agentbundle/build/tests/test_pack_schema_allowed_adapters.py +0 -258
- agentbundle-0.29.5/agentbundle/build/tests/test_pack_schema_install.py +0 -305
- agentbundle-0.29.5/agentbundle/build/tests/test_pipeline.py +0 -275
- agentbundle-0.29.5/agentbundle/build/tests/test_plugin_manifest_schema.py +0 -422
- agentbundle-0.29.5/agentbundle/build/tests/test_projectable_subset.py +0 -202
- agentbundle-0.29.5/agentbundle/build/tests/test_projections_merge_json.py +0 -151
- agentbundle-0.29.5/agentbundle/build/tests/test_scope_rails.py +0 -401
- agentbundle-0.29.5/agentbundle/build/tests/test_security.py +0 -102
- agentbundle-0.29.5/agentbundle/build/tests/test_self_host_check.py +0 -2278
- agentbundle-0.29.5/agentbundle/build/tests/test_self_host_fixture_guard.py +0 -88
- agentbundle-0.29.5/agentbundle/build/tests/test_self_host_recipe_config.py +0 -113
- agentbundle-0.29.5/agentbundle/build/tests/test_shared_libs_projection.py +0 -218
- agentbundle-0.29.5/agentbundle/build/tests/test_shared_prefix_contract.py +0 -114
- agentbundle-0.29.5/agentbundle/build/tests/test_shipped_packs_v07_declarations.py +0 -109
- agentbundle-0.29.5/agentbundle/build/tests/test_shipped_packs_v08_declarations.py +0 -92
- agentbundle-0.29.5/agentbundle/build/tests/test_user_libs_projection.py +0 -285
- agentbundle-0.29.5/agentbundle/build/tests/test_validate.py +0 -250
- agentbundle-0.29.5/agentbundle/build/tests/test_workspace_status_projection.py +0 -273
- agentbundle-0.29.5/agentbundle/build/tests/test_writers_emit_lf.py +0 -171
- {agentbundle-0.29.5 → agentbundle-0.31.0}/README.md +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/__init__.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/__main__.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/adapter.schema.json +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/guides/_shared/reference/catalogue-ci-contract.md +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/packs/README.md +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/packs/_example/README.md +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/profiles/AGENTS.md +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/profiles/README.md +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/profiles/_example/README.md +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/profiles/_example/profile.toml +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/catalogue.schema.json +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/guide.schema.json +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/install-defaults.toml +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/pack.schema.json +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/profile.schema.json +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/skill-manifest.schema.json +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/skill.schema.json +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/target-vocab.toml +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/__init__.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/__main__.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/adapters/__init__.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/adapters/codex.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/adapters/copilot.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/adapters/cursor.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/adapters/gemini.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/adapters/kiro.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/adapters/kiro_cli.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/adapters/kiro_ide.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/contract.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/lint_packs.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/phase_order.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/projections/__init__.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/projections/codex_agent_toml.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/projections/copilot_agent_md.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/projections/copilot_hooks_json.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/projections/direct_directory.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/projections/gemini_command_toml.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/projections/hook_id.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/projections/kiro_ide_hook.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/projections/merge_into_agent_json.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/projections/merge_json.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/projections/user_merge_json.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/recipes/composite-agents-md.toml +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/recipes/per-pack-apm-package.toml +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/recipes/per-pack-overlay.toml +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/scope_rails.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/shared_libs.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/target_resolver.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/build/validate.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/__init__.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/archive.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/build.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/config.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/defaults.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/diagnostics.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/identity.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/initialise.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/lint.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/package.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/results.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/skill_spec_lint.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/catalogue_tooling/toml_emit.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/categories.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/__init__.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/_common.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/_drop_warning.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/adapt.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/catalogue_build.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/catalogue_init.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/catalogue_lint.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/catalogue_package.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/catalogue_self_host.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/catalogue_sync_defaults.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/catalogue_tooling_stub.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/catalogue_verify.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/config.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/diff.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/docs.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/init_state.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/list_installed.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/list_packs.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/list_profiles.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/list_targets.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/oplog_cmd.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/pack_config_cmd.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/pack_evals.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/package_catalogue.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/profile.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/reconcile.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/render.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/scaffold.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/show.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/uninstall.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/commands/validate.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/config.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/https_catalogue.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/local_exclude.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/oplog.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/pack_inventory.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/safety.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/scaffold.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/scope.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/source_defaults.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/statelock.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/user_config.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/workspace_mcp.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle.egg-info/dependency_links.txt +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle.egg-info/entry_points.txt +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle.egg-info/requires.txt +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle.egg-info/top_level.txt +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/setup.cfg +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/tests/test_adapter_permissions_projection.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/tests/test_linear_primitive.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/tests/test_workspace_mcp_elicit.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/tests/test_workspace_mcp_event_bridge.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/tests/test_workspace_mcp_git.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/tests/test_workspace_mcp_lifecycle.py +0 -0
- {agentbundle-0.29.5 → agentbundle-0.31.0}/tests/test_workspace_mcp_stdin.py +0 -0
- {agentbundle-0.29.5 → 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.
|
|
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,13 @@ 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. 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`
|
|
276
|
+
object (`url`, `path`, and one of `ref`/`sha`) pointing at the pack's directory
|
|
277
|
+
on the published distribution branch, and every entry is schema-validated at
|
|
278
|
+
build time against `marketplace-entry.schema.json`. Extra fields stay in `pack.toml`; the projection
|
|
273
279
|
is deliberately lossy per tool.
|
|
274
280
|
|
|
275
281
|
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 +291,9 @@ The org hint fires after the user-config but before the on-disk IDE probe — so
|
|
|
285
291
|
|
|
286
292
|
**Bundled contracts** — the wheel ships the machine contracts used for offline validation:
|
|
287
293
|
`pack.schema.json`, `skill.schema.json`, `guide.schema.json`, `skill-manifest.schema.json`,
|
|
288
|
-
`profile.schema.json`, `catalogue.schema.json`, `
|
|
289
|
-
|
|
294
|
+
`profile.schema.json`, `catalogue.schema.json`, `plugin-manifest.schema.json`,
|
|
295
|
+
`plugin-manifest.derived.schema.json`, `marketplace-entry.schema.json`,
|
|
296
|
+
`target-vocab.toml`, and the adapter contract files. All are available without network access via `importlib.resources`.
|
|
290
297
|
|
|
291
298
|
**Lint your catalogue** — shallow structural checks run without extra dependencies:
|
|
292
299
|
|
|
@@ -301,13 +308,30 @@ pip install 'agentbundle[lint]'
|
|
|
301
308
|
agentbundle catalogue lint --root . --deep
|
|
302
309
|
```
|
|
303
310
|
|
|
304
|
-
**
|
|
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:
|
|
305
328
|
|
|
306
329
|
```bash
|
|
307
330
|
agentbundle catalogue self-host --check --root .
|
|
331
|
+
agentbundle catalogue self-host --write --root .
|
|
308
332
|
```
|
|
309
333
|
|
|
310
|
-
|
|
334
|
+
Both check commands are safe to run in CI. The write command changes projected files.
|
|
311
335
|
|
|
312
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:
|
|
313
337
|
|
|
@@ -247,7 +247,13 @@ 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. 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`
|
|
254
|
+
object (`url`, `path`, and one of `ref`/`sha`) pointing at the pack's directory
|
|
255
|
+
on the published distribution branch, and every entry is schema-validated at
|
|
256
|
+
build time against `marketplace-entry.schema.json`. Extra fields stay in `pack.toml`; the projection
|
|
251
257
|
is deliberately lossy per tool.
|
|
252
258
|
|
|
253
259
|
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 +269,9 @@ The org hint fires after the user-config but before the on-disk IDE probe — so
|
|
|
263
269
|
|
|
264
270
|
**Bundled contracts** — the wheel ships the machine contracts used for offline validation:
|
|
265
271
|
`pack.schema.json`, `skill.schema.json`, `guide.schema.json`, `skill-manifest.schema.json`,
|
|
266
|
-
`profile.schema.json`, `catalogue.schema.json`, `
|
|
267
|
-
|
|
272
|
+
`profile.schema.json`, `catalogue.schema.json`, `plugin-manifest.schema.json`,
|
|
273
|
+
`plugin-manifest.derived.schema.json`, `marketplace-entry.schema.json`,
|
|
274
|
+
`target-vocab.toml`, and the adapter contract files. All are available without network access via `importlib.resources`.
|
|
268
275
|
|
|
269
276
|
**Lint your catalogue** — shallow structural checks run without extra dependencies:
|
|
270
277
|
|
|
@@ -279,13 +286,30 @@ pip install 'agentbundle[lint]'
|
|
|
279
286
|
agentbundle catalogue lint --root . --deep
|
|
280
287
|
```
|
|
281
288
|
|
|
282
|
-
**
|
|
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:
|
|
283
306
|
|
|
284
307
|
```bash
|
|
285
308
|
agentbundle catalogue self-host --check --root .
|
|
309
|
+
agentbundle catalogue self-host --write --root .
|
|
286
310
|
```
|
|
287
311
|
|
|
288
|
-
|
|
312
|
+
Both check commands are safe to run in CI. The write command changes projected files.
|
|
289
313
|
|
|
290
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:
|
|
291
315
|
|
|
@@ -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.
|
|
@@ -36,6 +36,62 @@ and `version`; `[pack.adapter-contract]` with `version`.
|
|
|
36
36
|
- [packs/README.md](../../../packs/README.md) — pack layout, versioning rules, lint commands.
|
|
37
37
|
- [packs/AGENTS.md](../../../packs/AGENTS.md) — agent-facing schema map and primary workflow.
|
|
38
38
|
|
|
39
|
+
### `[pack].description` — display copy
|
|
40
|
+
|
|
41
|
+
`[pack].description` is read by a **person** deciding whether to install: in a
|
|
42
|
+
marketplace browser, a catalogue listing, or CLI output. It is not read by the model.
|
|
43
|
+
|
|
44
|
+
That makes it a different artifact from a skill's or agent's `description`, which the
|
|
45
|
+
model reads to decide whether to **activate** the primitive. Length is load-bearing
|
|
46
|
+
there and shortening it degrades activation; per-target caps in
|
|
47
|
+
`contracts/target-vocab.toml` govern it. Do not carry habits from one to the other.
|
|
48
|
+
|
|
49
|
+
**Shape.** Open on the job the adopter accomplishes, in their words. Say what they
|
|
50
|
+
get. Then stop.
|
|
51
|
+
|
|
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.
|
|
74
|
+
|
|
75
|
+
**Anti-patterns**, each of which has shipped here before:
|
|
76
|
+
|
|
77
|
+
| Anti-pattern | Instead |
|
|
78
|
+
| --- | --- |
|
|
79
|
+
| Opening with a component inventory (`Core: work-loop, new-spec, bug-fix, …`) | Lead with the outcome; the inventory belongs in the README |
|
|
80
|
+
| Repo-insider vocabulary (`forked-context`, `the grown-up successor to X`) | Words a first-time reader resolves without this repo |
|
|
81
|
+
| Cross-pack references (`co-installs with X`, `feeds Y's queue`) | Nothing that assumes another pack is known |
|
|
82
|
+
| Provenance name-drops (`(STORM, PRISMA, ACH, GRADE)`) | Name a framework only when the reader is buying it |
|
|
83
|
+
| Negative space (`no stack, no values tables, no pixel comps`) | Say what it does; the README can scope what it doesn't |
|
|
84
|
+
| Internal paths (`~/.agentbundle/bin/`) | Nothing an adopter cannot act on from a listing |
|
|
85
|
+
|
|
86
|
+
**Discoverability is carried elsewhere** — `[pack].keywords` and `[pack].categories`
|
|
87
|
+
— so prose does not need to be keyword-dense to stay findable.
|
|
88
|
+
|
|
89
|
+
There is no target-imposed length limit. `tools/lint-pack-descriptions.py` fails the
|
|
90
|
+
build past a deliberately loose backstop, which exists only to stop runaway drift (the
|
|
91
|
+
field once reached 1122 characters); it is not the quality bar. **This section is.** A
|
|
92
|
+
description inside the backstop can still be bad, and a length check cannot tell —
|
|
93
|
+
review against the shape and the table above.
|
|
94
|
+
|
|
39
95
|
---
|
|
40
96
|
|
|
41
97
|
## 3. Pack README standard
|
{agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/manifest.json
RENAMED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": {
|
|
3
|
-
"guides/_shared/reference/catalogue-authoring-standards.md": "
|
|
3
|
+
"guides/_shared/reference/catalogue-authoring-standards.md": "ff4bdc203affda0a2f41641c1155b3f4e90aade022e122999a82e7093e94d2ee",
|
|
4
4
|
"guides/_shared/reference/catalogue-ci-contract.md": "fae793ab47989b6dd3c731afcb0b4cda21c7d08bbe7fa40fca6d3abb3d158141",
|
|
5
|
-
"packs/AGENTS.md": "
|
|
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": "
|
|
9
|
+
"packs/_example/.claude-plugin/plugin.json": "7f94084a56260eed225ec47ac82042fe9029c594557cca760a459885d03ccc26",
|
|
10
10
|
"packs/_example/README.md": "ef130c9c1f97a75a07cc59fc55fc5b3bf71846dd2f06c3cddf5a1154023b6ef6",
|
|
11
|
-
"packs/_example/pack.toml": "
|
|
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",
|
{agentbundle-0.29.5 → agentbundle-0.31.0}/agentbundle/_data/catalogue-scaffold/packs/AGENTS.md
RENAMED
|
@@ -6,9 +6,11 @@ Read `packs/AGENTS.local.md` when present — it carries host-specific overrides
|
|
|
6
6
|
## Pack layout
|
|
7
7
|
|
|
8
8
|
The pack is the ownership and test-execution boundary; `.apm/` is the runtime export boundary; a skill is the
|
|
9
|
-
evaluation-fixture boundary.
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
evaluation-fixture boundary. Skill tests go in `packs/<pack>/tests/skills/<skill>/` and hook tests in
|
|
10
|
+
`packs/<pack>/tests/hooks/` — never under `.apm/`, which adapters project verbatim into an installed tree.
|
|
11
|
+
Evals stay skill-local at `.apm/skills/<skill>/evals/` and project with the skill. Run **one pytest process
|
|
12
|
+
per skill test directory**: two skills may ship the same test basename, and a shared `sys.path` binds one
|
|
13
|
+
skill's module for both suites and passes green.
|
|
12
14
|
|
|
13
15
|
| Path | Purpose |
|
|
14
16
|
|------|---------|
|
|
@@ -28,14 +30,13 @@ every pack, plus one pytest process per skill test dir. Shape: `docs/architectur
|
|
|
28
30
|
|
|
29
31
|
## Reserved authoring assets
|
|
30
32
|
|
|
31
|
-
Any immediate child of the packs root whose name begins with `_` is a reserved authoring asset
|
|
32
|
-
|
|
33
|
-
installed, and are not included in packaged archives. See `packs/README.md`.
|
|
33
|
+
Any immediate child of the packs root whose name begins with `_` is a reserved authoring asset: not
|
|
34
|
+
catalogue payload, absent from `list-packs`, never installed or packaged. See `packs/README.md`.
|
|
34
35
|
|
|
35
36
|
## pack.toml schema map
|
|
36
37
|
|
|
37
|
-
> The
|
|
38
|
-
> The table below is a navigational summary
|
|
38
|
+
> The normative source for pack.toml format is the `pack` JSON Schema that ships inside `agentbundle`;
|
|
39
|
+
> `agentbundle catalogue lint --root .` validates against it. The table below is a navigational summary.
|
|
39
40
|
|
|
40
41
|
| Table | Required fields | Notable optional fields |
|
|
41
42
|
|-------|----------------|------------------------|
|
|
@@ -64,14 +65,14 @@ For CI pipeline orchestration — publication ordering, exit codes, JSON output
|
|
|
64
65
|
|
|
65
66
|
## Version bump rule
|
|
66
67
|
|
|
67
|
-
Every **non-cosmetic** change to pack content requires a version bump in both
|
|
68
|
-
|
|
69
|
-
2. `.claude-plugin/plugin.json` → `"version"`
|
|
68
|
+
Every **non-cosmetic** change to pack content requires a version bump in **both** `pack.toml` →
|
|
69
|
+
`[pack] version` and `.claude-plugin/plugin.json` → `"version"`.
|
|
70
70
|
|
|
71
71
|
Which increment: **patch** for changed bodies/directives/conventions; **minor** for new primitives;
|
|
72
72
|
**major** for removals. Never ride an unreleased version from another in-flight PR.
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
Further post-bump steps (changelog, marketplace regeneration) are host-specific — see `AGENTS.local.md` if
|
|
75
|
+
your catalogue has one.
|
|
75
76
|
|
|
76
77
|
## Self-hosting projection
|
|
77
78
|
|
|
@@ -80,52 +81,50 @@ projects them to every shipped adapter's layout. Never edit a projected output d
|
|
|
80
81
|
|
|
81
82
|
On a dirty working tree: `agentbundle catalogue self-host --root . --write --force`.
|
|
82
83
|
|
|
83
|
-
**Critical ordering:** when a session edits both seeds and non-seed pack sources (`.apm/**`,
|
|
84
|
-
|
|
84
|
+
**Critical ordering:** when a session edits both seeds and non-seed pack sources (`.apm/**`, `pack.toml`),
|
|
85
|
+
run self-host AFTER all edits — not between them.
|
|
85
86
|
|
|
86
87
|
## Claude plugin JSON format
|
|
87
88
|
|
|
88
|
-
Each pack's `.claude-plugin/plugin.json` is validated against
|
|
89
|
-
Non-compliant manifests
|
|
89
|
+
Each pack's `.claude-plugin/plugin.json` is validated against the plugin-manifest JSON Schema that ships
|
|
90
|
+
inside `agentbundle`; `agentbundle catalogue lint --root .` reports violations. Non-compliant manifests
|
|
91
|
+
block publishing.
|
|
90
92
|
|
|
91
93
|
**Required:** `name` (string), `version` (string matching `pack.toml`), `description` (string).
|
|
92
94
|
|
|
93
|
-
**Allowed optional fields** — `skills`, `agents` (arrays of strings); `author` (`{name, email?}`);
|
|
94
|
-
`
|
|
95
|
-
|
|
95
|
+
**Allowed optional fields** — `skills`, `agents` (arrays of strings); `author` (`{name, email?}`); `license`,
|
|
96
|
+
`homepage`, `repository`, `category`, `displayName` (strings); `keywords` (array); `source`
|
|
97
|
+
(`{source, repo, branch, directory}`).
|
|
96
98
|
|
|
97
99
|
`additionalProperties: false` — any unknown key fails validation.
|
|
98
100
|
|
|
99
101
|
## Authoring or editing a skill
|
|
100
102
|
|
|
101
|
-
`README.md` states pack intent and the user journey it serves — not a contributor capability list.
|
|
102
|
-
|
|
103
|
-
`agentbundle catalogue lint --root . --deep` to confirm spec compliance.
|
|
103
|
+
`README.md` states pack intent and the user journey it serves — not a contributor capability list. Edit
|
|
104
|
+
`.apm/skills/<name>/SKILL.md`, run self-host to project, then `agentbundle catalogue lint --root . --deep`.
|
|
104
105
|
|
|
105
|
-
Full authoring standards — frontmatter key whitelist, body structure, naming, three-tier dependency
|
|
106
|
-
|
|
106
|
+
Full authoring standards — frontmatter key whitelist, body structure, naming, three-tier dependency policy,
|
|
107
|
+
evals — live in [`catalogue-authoring-standards.md`](../guides/_shared/reference/catalogue-authoring-standards.md).
|
|
107
108
|
|
|
108
109
|
## Eval coverage
|
|
109
110
|
|
|
110
111
|
A non-cosmetic pack update must also update the pack's eval harness:
|
|
111
|
-
- **Tier-A activation** — `evals/eval_queries.json` (~8–10 should-trigger + ~8–10 near-miss) and
|
|
112
|
-
|
|
112
|
+
- **Tier-A activation** — `evals/eval_queries.json` (~8–10 should-trigger + ~8–10 near-miss) and a
|
|
113
|
+
`[pack.evals]` block in `pack.toml` listing every user-triggered skill.
|
|
113
114
|
- **Tier-4 LLM-judge rubric** — `evals/evals.json` for judgment/authoring skills.
|
|
114
115
|
- **Tier-B-lite behavior check** — add an `expect` block to an `evals/evals.json` entry (non-destructive,
|
|
115
|
-
non-credentialed skills only). Four things
|
|
116
|
-
-
|
|
117
|
-
(
|
|
118
|
-
with these files before invoking the skill.
|
|
116
|
+
non-credentialed skills only). Four things must be explicit, or the format churns:
|
|
117
|
+
- The field is **`files`**, not `fixture`, and its paths are relative to the **skill root**
|
|
118
|
+
(`"evals/files/sample.md"`) — not to `evals/`. The runner seeds a temp workspace with them first.
|
|
119
119
|
- `expect.produces`: filenames the run must create in the workspace.
|
|
120
120
|
- `expect.output_contains` / `expect.output_excludes`: substrings in captured output.
|
|
121
|
-
- **Your skill script must accept the workspace path** —
|
|
122
|
-
|
|
123
|
-
Full procedure: [`guides/_shared/
|
|
121
|
+
- **Your skill script must accept the workspace path** — a `--fixture`/`--root` flag, or treat CWD as
|
|
122
|
+
the workspace — so the runner can confine writes and verify `produces`.
|
|
123
|
+
Full procedure: [`guides/_shared/reference/catalogue-authoring-standards.md`](../guides/_shared/reference/catalogue-authoring-standards.md).
|
|
124
124
|
|
|
125
125
|
## Windows-safe Python scripts
|
|
126
126
|
|
|
127
|
-
Any script under `.apm/` that prints to stdout or stderr must include the UTF-8 reconfigure guard
|
|
128
|
-
immediately after `import sys`, before any `print()` call:
|
|
127
|
+
Any script under `.apm/` that prints to stdout or stderr must include the UTF-8 reconfigure guard immediately after `import sys`, before any `print()` call:
|
|
129
128
|
|
|
130
129
|
```python
|
|
131
130
|
sys.stdout.reconfigure(encoding="utf-8", errors="strict")
|
|
@@ -145,6 +144,7 @@ Stubs in `plan.md` tasks must be `raise NotImplementedError # STUB: ACn` — no
|
|
|
145
144
|
|
|
146
145
|
## Shipped pack content carries no internal-governance citations
|
|
147
146
|
|
|
148
|
-
Anywhere under `packs/` — `.apm/**`, `pack.toml`, `README`/`JOURNEY`/`DESIGN`, `seeds/**` —
|
|
149
|
-
|
|
150
|
-
|
|
147
|
+
Anywhere under `packs/` — `.apm/**`, `pack.toml`, `README`/`JOURNEY`/`DESIGN`, `seeds/**` — never cite your
|
|
148
|
+
catalogue's own governance: decision-record or proposal numbers, spec/plan or acceptance-criterion citations,
|
|
149
|
+
or repository-only paths. Shipped content lands in someone else's tree, where each is a dead end. **Keep the
|
|
150
|
+
rule, drop the citation** — state what the reader must do, in full.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[pack]
|
|
2
2
|
name = "example-pack"
|
|
3
3
|
version = "0.1.0"
|
|
4
|
-
description = "
|
|
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
|
|
5
|
-
- ``dist/claude-plugins/<pack>/.claude-plugin/plugin.json`` — claude-plugins
|
|
6
|
-
|
|
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
|
|
@@ -213,11 +217,66 @@ def _assert_portable_name(component: str) -> None:
|
|
|
213
217
|
# ---------------------------------------------------------------------------
|
|
214
218
|
|
|
215
219
|
|
|
220
|
+
# Settings files are read under an adopter's ``${CLAUDE_PROJECT_DIR}``, whose
|
|
221
|
+
# contents a cloned repo controls. Bound the read itself — measuring after
|
|
222
|
+
# `read_text()` has already pulled the whole file in is no bound at all.
|
|
223
|
+
_SETTINGS_READ_CAP = 1_048_576 # 1 MiB
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def _plugin_marketplace(
|
|
227
|
+
plugin_root: pathlib.Path,
|
|
228
|
+
plugin_name: str,
|
|
229
|
+
) -> "str | None":
|
|
230
|
+
"""Return the marketplace this pack was installed from, or ``None``.
|
|
231
|
+
|
|
232
|
+
The Claude-plugins client installs into
|
|
233
|
+
``<config>/plugins/cache/<marketplace>/<plugin>/<version>``, so the pack
|
|
234
|
+
can read its own marketplace identity back out of ``${CLAUDE_PLUGIN_ROOT}``.
|
|
235
|
+
Verified against Claude Code 2.1.223.
|
|
236
|
+
|
|
237
|
+
Returns ``None`` when ``plugin_root`` does not have that shape. The caller
|
|
238
|
+
then matches on bare pack name alone — a layout we do not recognise must
|
|
239
|
+
degrade to the historical behaviour, not to "never opted in" (that is the
|
|
240
|
+
very failure this function's caller exists to fix).
|
|
241
|
+
"""
|
|
242
|
+
parts = plugin_root.parts
|
|
243
|
+
if len(parts) < 4:
|
|
244
|
+
return None
|
|
245
|
+
if parts[-4] != "cache" or parts[-2] != plugin_name:
|
|
246
|
+
return None
|
|
247
|
+
return parts[-3] or None
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def _entry_matches(
|
|
251
|
+
entry: str,
|
|
252
|
+
plugin_name: str,
|
|
253
|
+
marketplace: "str | None",
|
|
254
|
+
) -> bool:
|
|
255
|
+
"""Does one ``enabledPlugins`` identifier name *this* pack?
|
|
256
|
+
|
|
257
|
+
Current clients write a qualified ``name@marketplace``; older ones wrote a
|
|
258
|
+
bare ``name``. A qualified identifier must agree on *both* halves whenever
|
|
259
|
+
we know our own marketplace, so another vendor's ``core@other-marketplace``
|
|
260
|
+
does not opt in a ``core`` that came from somewhere else.
|
|
261
|
+
"""
|
|
262
|
+
name, sep, entry_marketplace = entry.strip().partition("@")
|
|
263
|
+
if name.strip() != plugin_name:
|
|
264
|
+
return False
|
|
265
|
+
if not sep:
|
|
266
|
+
# Bare name — the identifier makes no marketplace claim to check.
|
|
267
|
+
return True
|
|
268
|
+
if marketplace is None:
|
|
269
|
+
# Our own identity is unknown; the name is all there is to compare.
|
|
270
|
+
return True
|
|
271
|
+
return entry_marketplace.strip() == marketplace
|
|
272
|
+
|
|
273
|
+
|
|
216
274
|
def _detect_origin(
|
|
217
275
|
*,
|
|
218
276
|
plugin_name: str,
|
|
219
277
|
home: pathlib.Path,
|
|
220
278
|
project_dir: pathlib.Path | None,
|
|
279
|
+
marketplace: "str | None",
|
|
221
280
|
) -> str | None:
|
|
222
281
|
"""Walk the three ``enabledPlugins`` settings files in precedence order.
|
|
223
282
|
|
|
@@ -226,9 +285,17 @@ def _detect_origin(
|
|
|
226
285
|
(pack is not enabled at any scope).
|
|
227
286
|
|
|
228
287
|
Precedence: local → project → user (most-specific wins).
|
|
229
|
-
|
|
230
|
-
``enabledPlugins``
|
|
231
|
-
|
|
288
|
+
|
|
289
|
+
``enabledPlugins`` carries two shapes. Current clients write an **object**
|
|
290
|
+
keyed by plugin identifier whose boolean value is the enabled state — only
|
|
291
|
+
``true`` counts as opted in, since ``false`` is an adopter who deliberately
|
|
292
|
+
disabled the pack. Older clients wrote a **JSON array** of identifiers;
|
|
293
|
+
both are accepted.
|
|
294
|
+
|
|
295
|
+
Every other outcome is "not opted in at that scope" and falls through: a
|
|
296
|
+
missing file, a non-regular path, a file past ``_SETTINGS_READ_CAP``,
|
|
297
|
+
undecodable bytes, malformed JSON, an absent ``enabledPlugins`` key, or a
|
|
298
|
+
value of any other type. A hostile settings file must never raise.
|
|
232
299
|
"""
|
|
233
300
|
candidates: list[tuple[str, pathlib.Path]] = []
|
|
234
301
|
|
|
@@ -239,32 +306,38 @@ def _detect_origin(
|
|
|
239
306
|
candidates.append(("user", home / ".claude" / "settings.json"))
|
|
240
307
|
|
|
241
308
|
for origin, settings_path in candidates:
|
|
242
|
-
|
|
309
|
+
# `.is_file()` where the old code used `.exists()`: a FIFO exists, and
|
|
310
|
+
# opening one for reading blocks until a writer appears. A character
|
|
311
|
+
# device such as /dev/zero exists too, and reads forever.
|
|
312
|
+
if not settings_path.is_file():
|
|
243
313
|
continue
|
|
244
314
|
try:
|
|
245
|
-
|
|
315
|
+
with settings_path.open("rb") as fh:
|
|
316
|
+
blob = fh.read(_SETTINGS_READ_CAP + 1)
|
|
246
317
|
except OSError:
|
|
247
318
|
continue
|
|
248
|
-
|
|
249
|
-
if len(read_text) > 1_048_576:
|
|
319
|
+
if len(blob) > _SETTINGS_READ_CAP:
|
|
250
320
|
continue
|
|
251
321
|
try:
|
|
252
|
-
|
|
253
|
-
|
|
322
|
+
# `json.loads` decodes UTF-8 itself; undecodable bytes raise
|
|
323
|
+
# UnicodeDecodeError and malformed JSON raises JSONDecodeError,
|
|
324
|
+
# both subclasses of ValueError.
|
|
325
|
+
raw = json.loads(blob)
|
|
326
|
+
except ValueError:
|
|
254
327
|
continue
|
|
255
328
|
if not isinstance(raw, dict):
|
|
256
329
|
continue
|
|
257
330
|
enabled = raw.get("enabledPlugins")
|
|
258
|
-
if
|
|
331
|
+
if isinstance(enabled, dict):
|
|
332
|
+
entries: list = [key for key, value in enabled.items() if value is True]
|
|
333
|
+
elif isinstance(enabled, list):
|
|
334
|
+
entries = enabled
|
|
335
|
+
else:
|
|
259
336
|
continue
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
continue
|
|
265
|
-
# Match by pack name as a prefix component (before '@').
|
|
266
|
-
entry_name = entry.split("@")[0].strip()
|
|
267
|
-
if entry_name == plugin_name:
|
|
337
|
+
for entry in entries:
|
|
338
|
+
if isinstance(entry, str) and _entry_matches(
|
|
339
|
+
entry, plugin_name, marketplace
|
|
340
|
+
):
|
|
268
341
|
return origin
|
|
269
342
|
|
|
270
343
|
return None
|
|
@@ -837,6 +910,7 @@ def _main_claude_plugins(args: argparse.Namespace) -> int:
|
|
|
837
910
|
plugin_name=pack_name,
|
|
838
911
|
home=home,
|
|
839
912
|
project_dir=project_dir,
|
|
913
|
+
marketplace=_plugin_marketplace(plugin_root, pack_name),
|
|
840
914
|
)
|
|
841
915
|
|
|
842
916
|
if origin is None:
|