agentbundle 0.20.1__tar.gz → 0.22.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.20.1 → agentbundle-0.22.0}/PKG-INFO +38 -1
- agentbundle-0.22.0/README-pypi.md +266 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/README.md +35 -7
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/_data/catalogue.schema.json +16 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/_data/install-marker.py +28 -35
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/self_host.py +1 -1
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_contract.py +4 -4
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_lint_agents_md_diataxis_block.py +3 -1
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_lint_agents_md_legacy_block.py +2 -1
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_lint_agents_md_risk_block.py +3 -1
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_self_host_check.py +5 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_shared_prefix_contract.py +5 -2
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/catalogue.py +7 -9
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/catalogue_tooling/archive.py +41 -10
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/catalogue_tooling/build.py +9 -8
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/catalogue_tooling/config.py +76 -3
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/catalogue_tooling/defaults.py +17 -4
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/catalogue_tooling/diagnostics.py +3 -3
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/catalogue_tooling/lint.py +50 -49
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/catalogue_tooling/package.py +29 -19
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/catalogue_tooling/self_host.py +0 -1
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/catalogue_tooling/skill_spec_lint.py +2 -3
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/catalogue_tooling/verify.py +30 -12
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/categories.py +3 -4
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/cli.py +170 -28
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/_common.py +7 -5
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/_drop_warning.py +1 -2
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/adapt.py +9 -4
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/catalogue_build.py +1 -1
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/catalogue_lint.py +1 -1
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/catalogue_package.py +1 -1
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/catalogue_self_host.py +4 -6
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/catalogue_sync_defaults.py +2 -2
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/catalogue_tooling_stub.py +1 -1
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/catalogue_verify.py +1 -1
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/docs.py +1 -1
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/init_state.py +1 -1
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/install.py +84 -65
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/list_installed.py +35 -29
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/list_packs.py +1 -1
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/list_profiles.py +1 -1
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/list_targets.py +0 -1
- agentbundle-0.22.0/agentbundle/commands/oplog_cmd.py +98 -0
- agentbundle-0.22.0/agentbundle/commands/pack_config_cmd.py +201 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/pack_evals.py +45 -17
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/package_catalogue.py +1 -2
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/reconcile.py +1 -1
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/render.py +1 -2
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/show.py +4 -4
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/uninstall.py +5 -7
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/upgrade.py +102 -103
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/validate.py +1 -4
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/config.py +165 -8
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/https_catalogue.py +34 -38
- agentbundle-0.22.0/agentbundle/oplog.py +168 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/render.py +1 -2
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/safety.py +85 -9
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/scope.py +2 -3
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/source_defaults.py +19 -22
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/statelock.py +3 -3
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/user_config.py +5 -11
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/version.py +1 -1
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle.egg-info/PKG-INFO +38 -1
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle.egg-info/SOURCES.txt +4 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/pyproject.toml +2 -2
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/__init__.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/__main__.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/_data/adapter.schema.json +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/_data/adapter.toml +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/_data/install-defaults.toml +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/_data/pack.schema.json +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/_data/plugin-manifest.derived.schema.json +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/_data/plugin-manifest.schema.json +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/_data/profile.schema.json +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/__init__.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/__main__.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/adapter_root_bins.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/adapters/__init__.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/adapters/claude_code.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/adapters/codex.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/adapters/copilot.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/adapters/cursor.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/adapters/gemini.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/adapters/kiro.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/adapters/kiro_cli.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/adapters/kiro_ide.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/contract.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/lint_packs.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/main.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/phase_order.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/projections/__init__.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/projections/codex_agent_toml.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/projections/copilot_agent_md.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/projections/copilot_hooks_json.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/projections/direct_directory.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/projections/gemini_command_toml.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/projections/hook_id.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/projections/kiro_ide_hook.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/projections/merge_into_agent_json.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/projections/merge_json.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/projections/user_merge_json.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/recipes/composite-agents-md.toml +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/recipes/composite-marketplace.toml +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/recipes/marketplace.toml +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/recipes/per-pack-apm-package.toml +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/recipes/per-pack-claude-plugin.toml +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/recipes/per-pack-overlay.toml +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/recipes/self-host.toml +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/scope_rails.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/shared_libs.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/target_resolver.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/__init__.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_adapter_claude_code.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_adapter_codex.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_adapter_copilot.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_adapter_cursor.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_adapter_gemini.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_adapter_kiro.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_adapter_kiro_alias.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_adapter_kiro_cli.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_adapter_kiro_ide.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_adapter_root_bins_projection.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_architect_design_reviewer_projection.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_architect_design_reviewer_rubric_parity.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_build_ships_seeds.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_contract_scope.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_contract_v07.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_contract_v08.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_direct_directory_cleanup.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_end_to_end_build.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_lint_packs.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_load_pack_hook_wiring_safely.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_pack_schema.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_pack_schema_allowed_adapters.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_pack_schema_install.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_pipeline.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_plugin_manifest_schema.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_projectable_subset.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_projections_merge_json.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_scope_rails.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_security.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_self_host_fixture_guard.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_self_host_recipe_config.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_shared_libs_projection.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_shipped_packs_v07_declarations.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_shipped_packs_v08_declarations.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_user_libs_projection.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_validate.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_writers_emit_lf.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/user_libs.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/validate.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/catalogue_tooling/__init__.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/catalogue_tooling/results.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/__init__.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/config.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/diff.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/profile.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/commands/scaffold.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/pack_inventory.py +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle.egg-info/dependency_links.txt +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle.egg-info/entry_points.txt +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle.egg-info/requires.txt +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle.egg-info/top_level.txt +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/setup.cfg +0 -0
- {agentbundle-0.20.1 → agentbundle-0.22.0}/tests/test_linear_primitive.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentbundle
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.22.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
|
|
@@ -175,6 +175,11 @@ Developers installing from your fork get the internal channel without a manual
|
|
|
175
175
|
A malformed `enabled = true` config fails closed — no silent fallback to the public
|
|
176
176
|
source.
|
|
177
177
|
|
|
178
|
+
**Offline and air-gapped hosts:** set `AGENTBUNDLE_NO_REMOTE=1` to skip the org
|
|
179
|
+
Artifactory bootstrap and editable-install detection entirely. `agentbundle` falls
|
|
180
|
+
straight through to the packaged default, so hosts without network access to Artifactory
|
|
181
|
+
still resolve a source without errors.
|
|
182
|
+
|
|
178
183
|
See the full enterprise adoption guide at
|
|
179
184
|
`docs/guides/_shared/how-to/use-an-artifactory-catalogue.md` for all six flows
|
|
180
185
|
(org bootstrap, repo-scope CI upgrade, user-scope MDM, source-conflict remediation,
|
|
@@ -242,6 +247,38 @@ agentbundle pack evals run --pack <pack-name> --catalogue-root .
|
|
|
242
247
|
|
|
243
248
|
See the [pack layout reference](https://github.com/eugenelim/agent-ready-repo/blob/main/docs/architecture/pack-layout.md) and [authoring a skill](https://github.com/eugenelim/agent-ready-repo/blob/main/docs/guides/_shared/how-to/author-a-skill.md).
|
|
244
249
|
|
|
250
|
+
## Catalogue defaults and pack config API
|
|
251
|
+
|
|
252
|
+
**Catalogue defaults** let operators ship sensible starting values for every pack they distribute. Add a `[pack-defaults.<pack-name>]` table to `catalogue.toml` and the defaults are baked in at publish time. They slot into the three-layer cascade: pack-source defaults → operator defaults → user config. A custom install root is also supported via `[catalogue] user-dir = "~/custom/path"`.
|
|
253
|
+
|
|
254
|
+
**Pack scripts** can resolve their user-scope directory and read the merged config at runtime using the `agentbundle.config` API:
|
|
255
|
+
|
|
256
|
+
```python
|
|
257
|
+
from agentbundle.config import pack_dir, load_pack_config
|
|
258
|
+
|
|
259
|
+
directory = pack_dir("my-pack") # ~/.agentbundle/my-pack/
|
|
260
|
+
config = load_pack_config("my-pack") # merged dict: pack defaults + operator + user
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Operation log** — scripts can append structured JSONL records to `<pack_dir>/ops.jsonl` for lightweight audit trails:
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
from agentbundle.oplog import write_entry
|
|
267
|
+
|
|
268
|
+
write_entry("my-pack", "install", src="git+https://example.com/my-pack")
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**CLI commands** to read, write, and inspect pack config and operation logs:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
agentbundle pack-config show my-pack # all config values for a pack
|
|
275
|
+
agentbundle pack-config get my-pack api-key # single value
|
|
276
|
+
agentbundle pack-config set my-pack api-key v # write to user config.toml
|
|
277
|
+
|
|
278
|
+
agentbundle oplog show my-pack # JSONL operation history
|
|
279
|
+
agentbundle oplog clear my-pack # wipe history (asks first)
|
|
280
|
+
```
|
|
281
|
+
|
|
245
282
|
## Credentials
|
|
246
283
|
|
|
247
284
|
`agentbundle` doesn't resolve secrets. Credentialed skills use [`credbroker`](https://pypi.org/project/credbroker/), a standalone resolver that keeps cleartext out of the model's reach.
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
# agentbundle
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/agentbundle/)
|
|
4
|
+
[](https://pypi.org/project/agentbundle/)
|
|
5
|
+
[](https://github.com/eugenelim/agent-ready-repo#license)
|
|
6
|
+
|
|
7
|
+
**The installer for [agent-ready-repo](https://github.com/eugenelim/agent-ready-repo).** Think npm, but for the skills, subagents, and hooks your coding agent runs on. One pack, one command, every major agent — Claude Code, Codex, Cursor, Copilot, Gemini, and Kiro (both the CLI and the IDE).
|
|
8
|
+
|
|
9
|
+
## Quick start
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install agentbundle
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Requires Python 3.11+. Runs on macOS, Linux, and Windows.
|
|
16
|
+
|
|
17
|
+
**Install into a repo** — so everyone who clones it gets the pack. `core` is the flagship pack, the loop itself:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
agentbundle install --pack core
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
No catalogue argument needed: it defaults to the agent-ready-repo catalogue. It lands in the repo's agent config — subagents and skills included — and you commit it like any other project file. This is the default scope: the pack belongs to the project and the whole team.
|
|
24
|
+
|
|
25
|
+
**Install for yourself, everywhere** — so a pack follows you across every project, with no per-repo setup:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
agentbundle install --pack desk-research --scope user
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
User-scope packs land in your home directory, not the repo — they're yours, not the team's, and they're there in every project you open.
|
|
32
|
+
|
|
33
|
+
The install auto-detects your agent (`--adapter` overrides). Multi-IDE? Install the same pack for each agent at the same scope — they coexist, and the agents that read `.agents/skills/` (codex, cursor, gemini, copilot) share one skill copy instead of fighting over it. To install from a **different** catalogue, pass it as a trailing argument — a git URL or a local path (`agentbundle install --pack core <catalogue>`); a `config set source <catalogue>` makes that the default, and an editable clone (`pip install -e`) defaults to itself.
|
|
34
|
+
|
|
35
|
+
## More commands
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# See what the catalogue offers (bare uses the default; or name one explicitly)
|
|
39
|
+
agentbundle list-packs
|
|
40
|
+
agentbundle list-profiles
|
|
41
|
+
|
|
42
|
+
# See what a single pack contains — skills and agents, derived live from its tree
|
|
43
|
+
agentbundle show core
|
|
44
|
+
agentbundle show core --format json # stable object for scripts/agents
|
|
45
|
+
|
|
46
|
+
# See what YOU have installed — pack, adapter, scope, version, and whether
|
|
47
|
+
# an upgrade is available (both scopes by default)
|
|
48
|
+
agentbundle list-installed
|
|
49
|
+
agentbundle list-installed --no-check # skip the catalogue check (offline, fast)
|
|
50
|
+
agentbundle list-installed --check-drift # also count locally edited files
|
|
51
|
+
agentbundle list-installed --format json # machine-readable JSON (schema_version 1)
|
|
52
|
+
agentbundle list-installed --updates-only # show only rows needing attention
|
|
53
|
+
|
|
54
|
+
# Install a whole curated profile — a single-scope set of packs — in one command
|
|
55
|
+
agentbundle install --profile inception
|
|
56
|
+
|
|
57
|
+
# Preview any install without writing a file
|
|
58
|
+
agentbundle install --pack core --dry-run
|
|
59
|
+
|
|
60
|
+
# Upgrade to the version the catalogue ships — shows installed → target, asks first
|
|
61
|
+
agentbundle upgrade --pack core
|
|
62
|
+
agentbundle upgrade --pack core --yes # skip the prompt (CI)
|
|
63
|
+
|
|
64
|
+
# Uninstall — previews remove (Tier-1) vs keep (your edits), asks first
|
|
65
|
+
agentbundle uninstall --pack core --dry-run
|
|
66
|
+
agentbundle uninstall --pack core --yes
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**`list-installed`** reads your state files (not the catalogue) and reports every installed `(pack, adapter)` at each scope with its version and a four-value status — `up-to-date`, `upgrade-available`, `ahead` (installed version is newer than catalogue), or `unknown`; it degrades to `unknown` (never an error) when the catalogue can't be resolved, and `--no-check` skips the check entirely. `--format json` emits a stable JSON contract (`schema_version: 1`) to stdout — useful for CI automation of upgrade decisions. `--updates-only` hides `up-to-date` rows.
|
|
70
|
+
|
|
71
|
+
**`show <pack>`** answers "what skills and agents does this pack contain?" by walking the pack's source tree live on each call — so the answer can't drift, and nothing is persisted. `--format json` emits a stable object (`name`, `version`, `description`, `skills`, `agents`, `source`) for scripts and agents. When the catalogue can't be resolved, an *installed* pack still reports its inventory from your state files (marked `source: installed-state`); a not-installed pack errors.
|
|
72
|
+
|
|
73
|
+
A **profile** is a catalogue-curated, single-scope set of packs you install in one command — it declares its own scope, so `--scope` doesn't apply. **Upgrade takes no version** — the target is whatever the catalogue you point at declares; to pin a past version, point the catalogue at that git ref. Install a pack that's **already there** and `agentbundle` offers to `upgrade` it instead (`--yes` runs it straight away).
|
|
74
|
+
|
|
75
|
+
**Mutating commands ask first.** `uninstall`, the `--force` cleanup, and the upgrade offer all preview what they'll do and confirm before touching anything; `--dry-run` previews without writing, and `--yes` skips the prompt for non-interactive / CI use (where, without it, they refuse rather than hang).
|
|
76
|
+
|
|
77
|
+
## Enterprise distribution
|
|
78
|
+
|
|
79
|
+
For organizations running an internal Artifactory mirror or any static HTTPS server,
|
|
80
|
+
agentbundle's enterprise distribution capabilities handle the full adoption loop —
|
|
81
|
+
from org-wide channel configuration to CI-driven bulk upgrades.
|
|
82
|
+
|
|
83
|
+
**Install from an internal Artifactory channel:**
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# Point agentbundle at your org's channel descriptor (one-time per machine,
|
|
87
|
+
# or pre-configured in your org fork — see Org bootstrap below)
|
|
88
|
+
agentbundle config set source catalogue+https://artifactory.example.test/agentbundle/catalogues/core/channels/stable.json
|
|
89
|
+
|
|
90
|
+
agentbundle install --pack core
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The channel descriptor points to an immutable versioned archive; agentbundle
|
|
94
|
+
fetches, verifies its SHA-256 digest, and installs. Pass a bearer token via
|
|
95
|
+
`AGENTBUNDLE_HTTP_BEARER_TOKEN` — it is never stored in state, never printed, and
|
|
96
|
+
never forwarded to a different host.
|
|
97
|
+
|
|
98
|
+
**JSON output for CI pipelines:**
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# See what's installed and what needs upgrading — machine-readable
|
|
102
|
+
agentbundle list-installed --format json
|
|
103
|
+
agentbundle list-installed --format json --updates-only
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Returns a stable JSON contract (`schema_version` 1) with per-row status
|
|
107
|
+
(`up-to-date` / `upgrade-available` / `ahead` / `unknown`) and machine-readable
|
|
108
|
+
reason codes for unknown rows. Pipe into `jq` or your CI annotation step.
|
|
109
|
+
|
|
110
|
+
**Bulk upgrade in one scoped command:**
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Upgrade all installed packs in a scope — preflights before any write
|
|
114
|
+
agentbundle upgrade --all --scope repo --yes
|
|
115
|
+
agentbundle upgrade --all --scope user --format json --yes
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Preflights all rows before writing anything; a blocked row stops the run before the
|
|
119
|
+
filesystem is touched. Partial failure is reported honestly — not described as a
|
|
120
|
+
rollback. Never silently downgrades an `ahead` row.
|
|
121
|
+
|
|
122
|
+
**Package your catalogue for Artifactory:**
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
agentbundle package-catalogue \
|
|
126
|
+
--root /path/to/catalogue \
|
|
127
|
+
--bundle my-packs \
|
|
128
|
+
--release 1.0.0 \
|
|
129
|
+
--channel stable \
|
|
130
|
+
--output dist/
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Produces a deterministic, reproducible gzip archive (versioned) and a mutable channel
|
|
134
|
+
descriptor JSON (`stable.json`), ready to upload to Artifactory. Identical inputs
|
|
135
|
+
produce byte-identical archives (honors `SOURCE_DATE_EPOCH`).
|
|
136
|
+
|
|
137
|
+
**Org bootstrap — ship the default channel in your fork:**
|
|
138
|
+
|
|
139
|
+
Add an `[organization.artifactory]` block to
|
|
140
|
+
`agentbundle/_data/install-defaults.toml` in your org's agentbundle fork:
|
|
141
|
+
|
|
142
|
+
```toml
|
|
143
|
+
[organization.artifactory]
|
|
144
|
+
enabled = true
|
|
145
|
+
base-url = "https://artifactory.example.test"
|
|
146
|
+
repository = "agentbundle"
|
|
147
|
+
bundle = "core"
|
|
148
|
+
channel = "stable"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Developers installing from your fork get the internal channel without a manual
|
|
152
|
+
`config set source` step. The block ships `enabled = false` in the public package.
|
|
153
|
+
A malformed `enabled = true` config fails closed — no silent fallback to the public
|
|
154
|
+
source.
|
|
155
|
+
|
|
156
|
+
**Offline and air-gapped hosts:** set `AGENTBUNDLE_NO_REMOTE=1` to skip the org
|
|
157
|
+
Artifactory bootstrap and editable-install detection entirely. `agentbundle` falls
|
|
158
|
+
straight through to the packaged default, so hosts without network access to Artifactory
|
|
159
|
+
still resolve a source without errors.
|
|
160
|
+
|
|
161
|
+
See the full enterprise adoption guide at
|
|
162
|
+
`docs/guides/_shared/how-to/use-an-artifactory-catalogue.md` for all six flows
|
|
163
|
+
(org bootstrap, repo-scope CI upgrade, user-scope MDM, source-conflict remediation,
|
|
164
|
+
disconnected hosts, and security controls).
|
|
165
|
+
|
|
166
|
+
## Build your own catalogue
|
|
167
|
+
|
|
168
|
+
`agentbundle` isn't tied to the agent-ready-repo catalogue. Any repo that lays its packs out the same way can use it. A pack is a directory:
|
|
169
|
+
|
|
170
|
+
```text
|
|
171
|
+
my-pack/
|
|
172
|
+
pack.toml # name, version, adapter-contract, install scope,
|
|
173
|
+
# plus rich metadata (license, maintainers, links,
|
|
174
|
+
# categories, keywords) and a README pointer
|
|
175
|
+
.claude-plugin/
|
|
176
|
+
plugin.json # Claude Code plugin manifest (hand-authored)
|
|
177
|
+
README.md # the pack's portable doc — projected with the pack
|
|
178
|
+
.apm/ # primitives — projected by the build pipeline
|
|
179
|
+
skills/<name>/
|
|
180
|
+
SKILL.md # the skill body; one folder per skill
|
|
181
|
+
references/ # progressive-disclosure docs, loaded on demand
|
|
182
|
+
assets/ # templates the skill copies into the repo
|
|
183
|
+
agents/<name>.md # subagents
|
|
184
|
+
hooks/<name>.py # lifecycle hooks
|
|
185
|
+
seeds/ # files scaffolded into the adopter repo
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
`pack.toml` is the **single source of truth** for a pack's metadata. Declare
|
|
189
|
+
`license`, `[[pack.maintainers]]`, `[pack.links]`, `categories`, and
|
|
190
|
+
`keywords` once; the build projects the cleanly-mappable subset — plus the
|
|
191
|
+
pack's `README.md` — into each distribution route's manifest (the `plugin.json`
|
|
192
|
+
/ `marketplace.json` entry), so the catalogue describes each pack richly rather
|
|
193
|
+
than with a single sentence. Extra fields stay in `pack.toml`; the projection
|
|
194
|
+
is deliberately lossy per tool.
|
|
195
|
+
|
|
196
|
+
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.
|
|
197
|
+
|
|
198
|
+
**Org adapter default:** If your org ships a private `agentbundle` wheel (or a fork pinned to your internal catalogue), you can set a default adapter for all developers without requiring them to run `agentbundle config set` or pass `--adapter` on every install. Add an `[organization]` table to `_data/install-defaults.toml` in your fork:
|
|
199
|
+
|
|
200
|
+
```toml
|
|
201
|
+
[organization]
|
|
202
|
+
preferred_adapter = "cursor"
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
The org hint fires after the user-config but before the on-disk IDE probe — so `--adapter`, user-config, and upgrade state-hints all take priority. An invalid value exits 1 before writing anything. See the [`agentbundle` reference](https://github.com/eugenelim/agent-ready-repo/blob/main/docs/guides/_shared/reference/agentbundle.md#org-adapter-default) for the full cascade.
|
|
206
|
+
|
|
207
|
+
**Lint your catalogue** — shallow structural checks run without extra dependencies:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
agentbundle catalogue lint --root .
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
For full [agentskills.io spec](https://agentskills.io/specification) compliance (frontmatter key set, description policy, encoding, evals schema), install the `lint` extra and run with `--deep`:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
pip install 'agentbundle[lint]'
|
|
217
|
+
agentbundle catalogue lint --root . --deep
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Run Tier-A activation evals** to measure whether each covered skill fires on the prompts it should:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
agentbundle pack evals run --pack <pack-name> --catalogue-root .
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
See the [pack layout reference](https://github.com/eugenelim/agent-ready-repo/blob/main/docs/architecture/pack-layout.md) and [authoring a skill](https://github.com/eugenelim/agent-ready-repo/blob/main/docs/guides/_shared/how-to/author-a-skill.md).
|
|
227
|
+
|
|
228
|
+
## Catalogue defaults and pack config API
|
|
229
|
+
|
|
230
|
+
**Catalogue defaults** let operators ship sensible starting values for every pack they distribute. Add a `[pack-defaults.<pack-name>]` table to `catalogue.toml` and the defaults are baked in at publish time. They slot into the three-layer cascade: pack-source defaults → operator defaults → user config. A custom install root is also supported via `[catalogue] user-dir = "~/custom/path"`.
|
|
231
|
+
|
|
232
|
+
**Pack scripts** can resolve their user-scope directory and read the merged config at runtime using the `agentbundle.config` API:
|
|
233
|
+
|
|
234
|
+
```python
|
|
235
|
+
from agentbundle.config import pack_dir, load_pack_config
|
|
236
|
+
|
|
237
|
+
directory = pack_dir("my-pack") # ~/.agentbundle/my-pack/
|
|
238
|
+
config = load_pack_config("my-pack") # merged dict: pack defaults + operator + user
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Operation log** — scripts can append structured JSONL records to `<pack_dir>/ops.jsonl` for lightweight audit trails:
|
|
242
|
+
|
|
243
|
+
```python
|
|
244
|
+
from agentbundle.oplog import write_entry
|
|
245
|
+
|
|
246
|
+
write_entry("my-pack", "install", src="git+https://example.com/my-pack")
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**CLI commands** to read, write, and inspect pack config and operation logs:
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
agentbundle pack-config show my-pack # all config values for a pack
|
|
253
|
+
agentbundle pack-config get my-pack api-key # single value
|
|
254
|
+
agentbundle pack-config set my-pack api-key v # write to user config.toml
|
|
255
|
+
|
|
256
|
+
agentbundle oplog show my-pack # JSONL operation history
|
|
257
|
+
agentbundle oplog clear my-pack # wipe history (asks first)
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## Credentials
|
|
261
|
+
|
|
262
|
+
`agentbundle` doesn't resolve secrets. Credentialed skills use [`credbroker`](https://pypi.org/project/credbroker/), a standalone resolver that keeps cleartext out of the model's reach.
|
|
263
|
+
|
|
264
|
+
## Learn more
|
|
265
|
+
|
|
266
|
+
The full story — the loop, the reviewers, the pack catalogue — is in the [agent-ready-repo README](https://github.com/eugenelim/agent-ready-repo#readme).
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
# agentbundle
|
|
2
2
|
|
|
3
|
-
[](https://pypi.org/project/agentbundle/)
|
|
4
|
-
[](https://pypi.org/project/agentbundle/)
|
|
5
|
-
[](https://github.com/eugenelim/agent-ready-repo#license)
|
|
6
|
-
|
|
7
3
|
**The installer for [agent-ready-repo](https://github.com/eugenelim/agent-ready-repo).** Think npm, but for the skills, subagents, and hooks your coding agent runs on. One pack, one command, every major agent — Claude Code, Codex, Cursor, Copilot, Gemini, and Kiro (both the CLI and the IDE).
|
|
8
4
|
|
|
9
5
|
## Quick start
|
|
10
6
|
|
|
11
7
|
```bash
|
|
12
|
-
pip install agentbundle
|
|
8
|
+
pip install -e packages/agentbundle
|
|
13
9
|
```
|
|
14
10
|
|
|
15
11
|
Requires Python 3.11+. Runs on macOS, Linux, and Windows.
|
|
@@ -208,7 +204,7 @@ agentbundle catalogue lint --root .
|
|
|
208
204
|
For full [agentskills.io spec](https://agentskills.io/specification) compliance (frontmatter key set, description policy, encoding, evals schema), install the `lint` extra and run with `--deep`:
|
|
209
205
|
|
|
210
206
|
```bash
|
|
211
|
-
pip install 'agentbundle[lint]'
|
|
207
|
+
pip install -e 'packages/agentbundle[lint]'
|
|
212
208
|
agentbundle catalogue lint --root . --deep
|
|
213
209
|
```
|
|
214
210
|
|
|
@@ -220,9 +216,41 @@ agentbundle pack evals run --pack <pack-name> --catalogue-root .
|
|
|
220
216
|
|
|
221
217
|
See the [pack layout reference](https://github.com/eugenelim/agent-ready-repo/blob/main/docs/architecture/pack-layout.md) and [authoring a skill](https://github.com/eugenelim/agent-ready-repo/blob/main/docs/guides/_shared/how-to/author-a-skill.md).
|
|
222
218
|
|
|
219
|
+
## Catalogue defaults and pack config API
|
|
220
|
+
|
|
221
|
+
**Catalogue defaults** let operators ship sensible starting values for every pack they distribute. Add a `[pack-defaults.<pack-name>]` table to `catalogue.toml` and the defaults are baked in at publish time. They slot into the three-layer cascade: pack-source defaults → operator defaults → user config. A custom install root is also supported via `[catalogue] user-dir = "~/custom/path"`.
|
|
222
|
+
|
|
223
|
+
**Pack scripts** can resolve their user-scope directory and read the merged config at runtime using the `agentbundle.config` API:
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
from agentbundle.config import pack_dir, load_pack_config
|
|
227
|
+
|
|
228
|
+
directory = pack_dir("my-pack") # ~/.agentbundle/my-pack/
|
|
229
|
+
config = load_pack_config("my-pack") # merged dict: pack defaults + operator + user
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Operation log** — scripts can append structured JSONL records to `<pack_dir>/ops.jsonl` for lightweight audit trails:
|
|
233
|
+
|
|
234
|
+
```python
|
|
235
|
+
from agentbundle.oplog import write_entry
|
|
236
|
+
|
|
237
|
+
write_entry("my-pack", "install", src="git+https://example.com/my-pack")
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**CLI commands** to read, write, and inspect pack config and operation logs:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
agentbundle pack-config show my-pack # all config values for a pack
|
|
244
|
+
agentbundle pack-config get my-pack api-key # single value
|
|
245
|
+
agentbundle pack-config set my-pack api-key v # write to user config.toml
|
|
246
|
+
|
|
247
|
+
agentbundle oplog show my-pack # JSONL operation history
|
|
248
|
+
agentbundle oplog clear my-pack # wipe history (asks first)
|
|
249
|
+
```
|
|
250
|
+
|
|
223
251
|
## Credentials
|
|
224
252
|
|
|
225
|
-
`agentbundle` doesn't resolve secrets. Credentialed skills use [`credbroker`](
|
|
253
|
+
`agentbundle` doesn't resolve secrets. Credentialed skills use [`credbroker`](../credbroker/README.md), a standalone resolver that keeps cleartext out of the model's reach.
|
|
226
254
|
|
|
227
255
|
## Learn more
|
|
228
256
|
|
|
@@ -12,6 +12,14 @@
|
|
|
12
12
|
"description": "Schema version — must be 1.",
|
|
13
13
|
"enum": [1]
|
|
14
14
|
},
|
|
15
|
+
"pack-defaults": {
|
|
16
|
+
"type": "object",
|
|
17
|
+
"description": "Per-pack configuration defaults baked into install-defaults.toml at build time.",
|
|
18
|
+
"additionalProperties": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"additionalProperties": { "type": "string" }
|
|
21
|
+
}
|
|
22
|
+
},
|
|
15
23
|
"catalogue": {
|
|
16
24
|
"type": "object",
|
|
17
25
|
"additionalProperties": false,
|
|
@@ -25,6 +33,10 @@
|
|
|
25
33
|
"package"
|
|
26
34
|
],
|
|
27
35
|
"properties": {
|
|
36
|
+
"user-dir": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"description": "User-scope pack directory root (must start with ~/). Defaults to ~/.agentbundle when absent."
|
|
39
|
+
},
|
|
28
40
|
"name": {
|
|
29
41
|
"type": "string",
|
|
30
42
|
"description": "Safe identifier — [A-Za-z0-9][A-Za-z0-9_-]*.",
|
|
@@ -159,6 +171,10 @@
|
|
|
159
171
|
"bundle": {
|
|
160
172
|
"type": "string",
|
|
161
173
|
"description": "Catalogue bundle name (required when enabled)."
|
|
174
|
+
},
|
|
175
|
+
"channel": {
|
|
176
|
+
"type": "string",
|
|
177
|
+
"description": "Artifactory channel name (required when enabled = true)."
|
|
162
178
|
}
|
|
163
179
|
}
|
|
164
180
|
}
|
|
@@ -48,16 +48,12 @@ Exit codes:
|
|
|
48
48
|
"""
|
|
49
49
|
|
|
50
50
|
import argparse
|
|
51
|
+
import contextlib
|
|
51
52
|
import datetime
|
|
52
53
|
import hashlib
|
|
53
54
|
import json
|
|
54
55
|
import os
|
|
55
56
|
import pathlib
|
|
56
|
-
import sys
|
|
57
|
-
import tempfile
|
|
58
|
-
import tomllib
|
|
59
|
-
from datetime import timezone
|
|
60
|
-
|
|
61
57
|
|
|
62
58
|
# ---------------------------------------------------------------------------
|
|
63
59
|
# Vendored pack-name / pack-version shape rules — copied from
|
|
@@ -69,6 +65,9 @@ from datetime import timezone
|
|
|
69
65
|
# pack.toml would pass unchecked and land phantom TOML lines in the marker.
|
|
70
66
|
# ---------------------------------------------------------------------------
|
|
71
67
|
import re as _re
|
|
68
|
+
import sys
|
|
69
|
+
import tempfile
|
|
70
|
+
import tomllib
|
|
72
71
|
|
|
73
72
|
_PACK_NAME_RE = _re.compile(r"^[a-z0-9][a-z0-9-]*$")
|
|
74
73
|
_PACK_VERSION_RE = _re.compile(
|
|
@@ -164,11 +163,11 @@ def _assert_under(target: pathlib.Path, jail: pathlib.Path) -> None:
|
|
|
164
163
|
# jail is already resolved; do not call os.path.realpath on it again.
|
|
165
164
|
try:
|
|
166
165
|
resolved_target.relative_to(jail)
|
|
167
|
-
except ValueError:
|
|
166
|
+
except ValueError as exc:
|
|
168
167
|
raise ValueError(
|
|
169
168
|
f"install-marker: marker path {resolved_target} escapes the per-scope jail "
|
|
170
169
|
f"{jail}; refusing write"
|
|
171
|
-
)
|
|
170
|
+
) from exc
|
|
172
171
|
|
|
173
172
|
|
|
174
173
|
def _assert_portable_name(component: str) -> None:
|
|
@@ -196,7 +195,7 @@ def _assert_portable_name(component: str) -> None:
|
|
|
196
195
|
f"install-marker: refusing path component with control character "
|
|
197
196
|
f"U+{ord(ch):04X}: {component!r}"
|
|
198
197
|
)
|
|
199
|
-
if component.endswith("."
|
|
198
|
+
if component.endswith((".", " ")):
|
|
200
199
|
raise ValueError(
|
|
201
200
|
f"install-marker: refusing path component with trailing dot or space: "
|
|
202
201
|
f"{component!r}"
|
|
@@ -294,7 +293,7 @@ def _marker_scope(origin: str) -> str:
|
|
|
294
293
|
def _pack_toml(plugin_root: pathlib.Path) -> dict:
|
|
295
294
|
"""Load and return the pack manifest dict from ``pack.toml``."""
|
|
296
295
|
toml_path = plugin_root / "pack.toml"
|
|
297
|
-
with open(
|
|
296
|
+
with toml_path.open("rb") as fh:
|
|
298
297
|
return tomllib.load(fh)
|
|
299
298
|
|
|
300
299
|
|
|
@@ -343,12 +342,11 @@ def _marker_path(
|
|
|
343
342
|
agentbundle.mkdir(mode=0o700, parents=True, exist_ok=True)
|
|
344
343
|
resolved_jail = pathlib.Path(os.path.realpath(agentbundle))
|
|
345
344
|
return agentbundle / ".adapt-install-marker.toml", resolved_jail
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
return project_dir / ".adapt-install-marker.toml", resolved_jail
|
|
345
|
+
# repo scope — project_dir must be set; callers ensure this.
|
|
346
|
+
if project_dir is None:
|
|
347
|
+
raise ValueError("project_dir required for repo-scope marker")
|
|
348
|
+
resolved_jail = pathlib.Path(os.path.realpath(project_dir))
|
|
349
|
+
return project_dir / ".adapt-install-marker.toml", resolved_jail
|
|
352
350
|
|
|
353
351
|
|
|
354
352
|
def _should_fire(
|
|
@@ -606,18 +604,14 @@ def _write_marker(
|
|
|
606
604
|
os.write(tmp_fd, content_bytes)
|
|
607
605
|
os.close(tmp_fd)
|
|
608
606
|
tmp_fd = -1
|
|
609
|
-
|
|
607
|
+
pathlib.Path(tmp_name).replace(marker_path)
|
|
610
608
|
except Exception:
|
|
611
609
|
# Clean up tempfile on error (best effort).
|
|
612
610
|
if tmp_fd >= 0:
|
|
613
|
-
|
|
611
|
+
with contextlib.suppress(OSError):
|
|
614
612
|
os.close(tmp_fd)
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
try:
|
|
618
|
-
os.unlink(tmp_name)
|
|
619
|
-
except OSError:
|
|
620
|
-
pass
|
|
613
|
+
with contextlib.suppress(OSError):
|
|
614
|
+
pathlib.Path(tmp_name).unlink()
|
|
621
615
|
raise
|
|
622
616
|
|
|
623
617
|
|
|
@@ -640,17 +634,13 @@ def _write_hash(plugin_data: pathlib.Path, current_hash: str) -> None:
|
|
|
640
634
|
os.write(tmp_fd, content_bytes)
|
|
641
635
|
os.close(tmp_fd)
|
|
642
636
|
tmp_fd = -1
|
|
643
|
-
|
|
637
|
+
pathlib.Path(tmp_name).replace(hash_path)
|
|
644
638
|
except Exception:
|
|
645
639
|
if tmp_fd >= 0:
|
|
646
|
-
|
|
640
|
+
with contextlib.suppress(OSError):
|
|
647
641
|
os.close(tmp_fd)
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
try:
|
|
651
|
-
os.unlink(tmp_name)
|
|
652
|
-
except OSError:
|
|
653
|
-
pass
|
|
642
|
+
with contextlib.suppress(OSError):
|
|
643
|
+
pathlib.Path(tmp_name).unlink()
|
|
654
644
|
raise
|
|
655
645
|
|
|
656
646
|
|
|
@@ -892,7 +882,7 @@ def _main_claude_plugins(args: argparse.Namespace) -> int:
|
|
|
892
882
|
new_entry: dict = {
|
|
893
883
|
"name": pack_name,
|
|
894
884
|
"version": pack_version,
|
|
895
|
-
"installed-at": datetime.datetime.now(
|
|
885
|
+
"installed-at": datetime.datetime.now(datetime.UTC),
|
|
896
886
|
"install-route": args.install_route,
|
|
897
887
|
}
|
|
898
888
|
|
|
@@ -912,7 +902,10 @@ def _main_claude_plugins(args: argparse.Namespace) -> int:
|
|
|
912
902
|
except Exception as exc:
|
|
913
903
|
# Hash write failure is non-fatal for the adopter (the marker was written),
|
|
914
904
|
# but log it so the next session retries detection rather than silently skipping.
|
|
915
|
-
print(
|
|
905
|
+
print(
|
|
906
|
+
f"install-marker: hash write failed (next session will retry): {exc}",
|
|
907
|
+
file=sys.stderr,
|
|
908
|
+
)
|
|
916
909
|
|
|
917
910
|
return 0
|
|
918
911
|
|
|
@@ -935,7 +928,7 @@ def _main_apm(args: argparse.Namespace) -> int:
|
|
|
935
928
|
home = pathlib.Path(home_str)
|
|
936
929
|
|
|
937
930
|
# --- Resolve data directory per AC3 precedence ---
|
|
938
|
-
plugin_data = _resolve_data_dir(env)
|
|
931
|
+
plugin_data = _resolve_data_dir(env) # type: ignore[arg-type]
|
|
939
932
|
if plugin_data is None:
|
|
940
933
|
# No-match fall-through (no APM data-directory token set); exit 0
|
|
941
934
|
# without writing marker or hash file (the no-partial-state rail).
|
|
@@ -1072,7 +1065,7 @@ def _main_apm(args: argparse.Namespace) -> int:
|
|
|
1072
1065
|
new_entry: dict = {
|
|
1073
1066
|
"name": pack_name,
|
|
1074
1067
|
"version": pack_version,
|
|
1075
|
-
"installed-at": datetime.datetime.now(
|
|
1068
|
+
"installed-at": datetime.datetime.now(datetime.UTC),
|
|
1076
1069
|
"install-route": args.install_route,
|
|
1077
1070
|
}
|
|
1078
1071
|
|
|
@@ -1482,7 +1482,7 @@ def run_build_check_drift_gates(
|
|
|
1482
1482
|
except _PARITY_EXPECTED_EXC as exc:
|
|
1483
1483
|
source_out = f"<{type(exc).__name__}: {exc}>"
|
|
1484
1484
|
try:
|
|
1485
|
-
template_out: object = template_emit(test_input)
|
|
1485
|
+
template_out: object = template_emit(test_input) # type: ignore[operator]
|
|
1486
1486
|
except _PARITY_EXPECTED_EXC as exc:
|
|
1487
1487
|
template_out = f"<{type(exc).__name__}: {exc}>"
|
|
1488
1488
|
if source_out != template_out:
|
|
@@ -602,10 +602,10 @@ class TestCodexSkillDirectDirectory(unittest.TestCase):
|
|
|
602
602
|
self.assertNotIn("managed-block-delimiter-end", entry)
|
|
603
603
|
|
|
604
604
|
def test_contract_files_byte_identical(self) -> None:
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
)
|
|
605
|
+
def _norm(p: Path) -> bytes:
|
|
606
|
+
return p.read_bytes().replace(b"\r\n", b"\n")
|
|
607
|
+
|
|
608
|
+
self.assertEqual(_norm(CONTRACT_PATH), _norm(DATA_CONTRACT_PATH))
|
|
609
609
|
|
|
610
610
|
def test_seed_agents_md_has_no_legacy_delimiters(self) -> None:
|
|
611
611
|
text = SEED_AGENTS_MD_PATH.read_text(encoding="utf-8")
|
|
@@ -47,12 +47,14 @@ def _make_quadrants(base: Path) -> None:
|
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
def _run_linter(cwd: Path) -> subprocess.CompletedProcess[str]:
|
|
50
|
+
env = {**os.environ, "PYTHONIOENCODING": "utf-8", "PYTHONUTF8": "1"}
|
|
50
51
|
return subprocess.run(
|
|
51
52
|
[sys.executable, str(LINTER)],
|
|
52
53
|
cwd=cwd,
|
|
53
|
-
env=
|
|
54
|
+
env=env,
|
|
54
55
|
capture_output=True,
|
|
55
56
|
text=True,
|
|
57
|
+
encoding="utf-8",
|
|
56
58
|
check=False,
|
|
57
59
|
)
|
|
58
60
|
|
|
@@ -63,13 +63,14 @@ def _seed_tree(
|
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
def _run_linter(cwd: Path) -> subprocess.CompletedProcess[str]:
|
|
66
|
-
env =
|
|
66
|
+
env = {**os.environ, "PYTHONIOENCODING": "utf-8", "PYTHONUTF8": "1"}
|
|
67
67
|
return subprocess.run(
|
|
68
68
|
[sys.executable, str(LINTER)],
|
|
69
69
|
cwd=cwd,
|
|
70
70
|
env=env,
|
|
71
71
|
capture_output=True,
|
|
72
72
|
text=True,
|
|
73
|
+
encoding="utf-8",
|
|
73
74
|
check=False,
|
|
74
75
|
)
|
|
75
76
|
|
{agentbundle-0.20.1 → agentbundle-0.22.0}/agentbundle/build/tests/test_lint_agents_md_risk_block.py
RENAMED
|
@@ -52,12 +52,14 @@ def _seed(root: Path, canonical_block: str, agents_block: str) -> None:
|
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
def _run_linter(cwd: Path) -> subprocess.CompletedProcess[str]:
|
|
55
|
+
env = {**os.environ, "PYTHONIOENCODING": "utf-8", "PYTHONUTF8": "1"}
|
|
55
56
|
return subprocess.run(
|
|
56
57
|
[sys.executable, str(LINTER)],
|
|
57
58
|
cwd=cwd,
|
|
58
|
-
env=
|
|
59
|
+
env=env,
|
|
59
60
|
capture_output=True,
|
|
60
61
|
text=True,
|
|
62
|
+
encoding="utf-8",
|
|
61
63
|
check=False,
|
|
62
64
|
)
|
|
63
65
|
|