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