agentbundle 0.6.0__tar.gz → 0.8.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.6.0 → agentbundle-0.8.0}/PKG-INFO +35 -21
- {agentbundle-0.6.0 → agentbundle-0.8.0}/README.md +34 -20
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/_data/adapter.toml +8 -1
- agentbundle-0.8.0/agentbundle/_data/install-defaults.toml +10 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/_data/pack.schema.json +19 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/adapters/codex.py +1 -1
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/adapters/cursor.py +2 -2
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/adapters/gemini.py +2 -2
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/adapters/kiro.py +1 -1
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/adapters/kiro_ide.py +1 -1
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/main.py +4 -4
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/projections/codex_agent_toml.py +1 -1
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/projections/copilot_agent_md.py +1 -1
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/projections/copilot_hooks_json.py +1 -1
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/projections/gemini_command_toml.py +1 -1
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/projections/kiro_ide_hook.py +1 -1
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/projections/merge_into_agent_json.py +1 -1
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/projections/merge_json.py +1 -1
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/projections/user_merge_json.py +1 -1
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/self_host.py +106 -22
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_adapter_cursor.py +4 -3
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_adapter_gemini.py +3 -3
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_adapter_kiro_ide.py +4 -4
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_contract.py +7 -7
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_pack_schema.py +79 -0
- agentbundle-0.8.0/agentbundle/build/tests/test_self_host_fixture_guard.py +88 -0
- agentbundle-0.8.0/agentbundle/build/tests/test_self_host_recipe_config.py +113 -0
- agentbundle-0.8.0/agentbundle/build/tests/test_writers_emit_lf.py +169 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/cli.py +97 -18
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/_common.py +167 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/config.py +6 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/install.py +316 -10
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/list_packs.py +20 -30
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/list_profiles.py +12 -16
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/reconcile.py +5 -12
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/uninstall.py +80 -13
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/upgrade.py +105 -7
- agentbundle-0.8.0/agentbundle/source_defaults.py +342 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/user_config.py +53 -5
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/version.py +1 -1
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle.egg-info/PKG-INFO +35 -21
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle.egg-info/SOURCES.txt +5 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/pyproject.toml +1 -1
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/__init__.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/__main__.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/_data/adapter.schema.json +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/_data/install-marker.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/_data/plugin-manifest.derived.schema.json +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/_data/plugin-manifest.schema.json +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/_data/profile.schema.json +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/__init__.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/__main__.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/adapter_root_bins.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/adapters/__init__.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/adapters/claude_code.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/adapters/copilot.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/adapters/kiro_cli.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/contract.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/lint_packs.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/phase_order.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/projections/__init__.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/projections/direct_directory.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/projections/hook_id.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/scope_rails.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/shared_libs.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/target_resolver.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/__init__.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_adapter_claude_code.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_adapter_codex.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_adapter_copilot.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_adapter_kiro.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_adapter_kiro_alias.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_adapter_kiro_cli.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_adapter_root_bins_projection.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_architect_design_reviewer_projection.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_architect_design_reviewer_rubric_parity.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_build_ships_seeds.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_contract_scope.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_contract_v07.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_contract_v08.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_direct_directory_cleanup.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_end_to_end_build.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_lint_agents_md_diataxis_block.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_lint_agents_md_legacy_block.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_lint_agents_md_risk_block.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_lint_packs.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_load_pack_hook_wiring_safely.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_pack_schema_allowed_adapters.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_pack_schema_install.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_pipeline.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_plugin_manifest_schema.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_projectable_subset.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_projections_merge_json.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_scope_rails.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_security.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_self_host_check.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_shared_libs_projection.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_shipped_packs_v07_declarations.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_shipped_packs_v08_declarations.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_user_libs_projection.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/tests/test_validate.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/user_libs.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/validate.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/catalogue.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/categories.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/__init__.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/_drop_warning.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/adapt.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/diff.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/init_state.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/list_targets.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/profile.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/render.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/scaffold.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/commands/validate.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/config.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/render.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/safety.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/scope.py +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle.egg-info/dependency_links.txt +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle.egg-info/entry_points.txt +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle.egg-info/top_level.txt +0 -0
- {agentbundle-0.6.0 → agentbundle-0.8.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentbundle
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.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
|
|
@@ -22,43 +22,57 @@ Description-Content-Type: text/markdown
|
|
|
22
22
|
[](https://pypi.org/project/agentbundle/)
|
|
23
23
|
[](https://github.com/eugenelim/agent-ready-repo#license)
|
|
24
24
|
|
|
25
|
-
**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.
|
|
25
|
+
**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).
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
## Quick start
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
30
|
pip install agentbundle
|
|
31
|
-
agentbundle install --pack core git+https://github.com/eugenelim/agent-ready-repo
|
|
32
31
|
```
|
|
33
32
|
|
|
34
|
-
|
|
33
|
+
**Install into a repo** — so everyone who clones it gets the pack. `core` is the flagship pack, the loop itself:
|
|
35
34
|
|
|
36
|
-
|
|
35
|
+
```bash
|
|
36
|
+
agentbundle install --pack core
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
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.
|
|
40
|
+
|
|
41
|
+
**Install for yourself, everywhere** — so a pack follows you across every project, with no per-repo setup:
|
|
37
42
|
|
|
38
43
|
```bash
|
|
39
|
-
|
|
40
|
-
|
|
44
|
+
agentbundle install --pack research --scope user
|
|
45
|
+
```
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
agentbundle list-profiles git+https://github.com/eugenelim/agent-ready-repo
|
|
47
|
+
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.
|
|
44
48
|
|
|
45
|
-
|
|
46
|
-
agentbundle install --profile inception git+https://github.com/eugenelim/agent-ready-repo
|
|
49
|
+
The install auto-detects your agent (`--adapter` overrides). 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.
|
|
47
50
|
|
|
48
|
-
|
|
49
|
-
agentbundle install --pack core git+https://github.com/eugenelim/agent-ready-repo
|
|
51
|
+
## More commands
|
|
50
52
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
+
```bash
|
|
54
|
+
# See what the catalogue offers (bare uses the default; or name one explicitly)
|
|
55
|
+
agentbundle list-packs
|
|
56
|
+
agentbundle list-profiles
|
|
57
|
+
|
|
58
|
+
# Install a whole curated profile — a single-scope set of packs — in one command
|
|
59
|
+
agentbundle install --profile inception
|
|
53
60
|
|
|
54
|
-
# Preview
|
|
55
|
-
agentbundle install --pack core
|
|
61
|
+
# Preview any install without writing a file
|
|
62
|
+
agentbundle install --pack core --dry-run
|
|
56
63
|
|
|
57
|
-
# Upgrade
|
|
58
|
-
agentbundle upgrade --pack core
|
|
64
|
+
# Upgrade to the version the catalogue ships — shows installed → target, asks first
|
|
65
|
+
agentbundle upgrade --pack core
|
|
66
|
+
agentbundle upgrade --pack core --yes # skip the prompt (CI)
|
|
67
|
+
|
|
68
|
+
# Uninstall — previews remove (Tier-1) vs keep (your edits), asks first
|
|
69
|
+
agentbundle uninstall --pack core --dry-run
|
|
70
|
+
agentbundle uninstall --pack core --yes
|
|
59
71
|
```
|
|
60
72
|
|
|
61
|
-
A
|
|
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).
|
|
62
76
|
|
|
63
77
|
## Build your own catalogue
|
|
64
78
|
|
|
@@ -4,43 +4,57 @@
|
|
|
4
4
|
[](https://pypi.org/project/agentbundle/)
|
|
5
5
|
[](https://github.com/eugenelim/agent-ready-repo#license)
|
|
6
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.
|
|
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
8
|
|
|
9
|
-
|
|
9
|
+
## Quick start
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
12
|
pip install agentbundle
|
|
13
|
-
agentbundle install --pack core git+https://github.com/eugenelim/agent-ready-repo
|
|
14
13
|
```
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
**Install into a repo** — so everyone who clones it gets the pack. `core` is the flagship pack, the loop itself:
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
```bash
|
|
18
|
+
agentbundle install --pack core
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
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.
|
|
22
|
+
|
|
23
|
+
**Install for yourself, everywhere** — so a pack follows you across every project, with no per-repo setup:
|
|
19
24
|
|
|
20
25
|
```bash
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
agentbundle install --pack research --scope user
|
|
27
|
+
```
|
|
23
28
|
|
|
24
|
-
|
|
25
|
-
agentbundle list-profiles git+https://github.com/eugenelim/agent-ready-repo
|
|
29
|
+
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.
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
agentbundle install --profile inception git+https://github.com/eugenelim/agent-ready-repo
|
|
31
|
+
The install auto-detects your agent (`--adapter` overrides). 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.
|
|
29
32
|
|
|
30
|
-
|
|
31
|
-
agentbundle install --pack core git+https://github.com/eugenelim/agent-ready-repo
|
|
33
|
+
## More commands
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
```bash
|
|
36
|
+
# See what the catalogue offers (bare uses the default; or name one explicitly)
|
|
37
|
+
agentbundle list-packs
|
|
38
|
+
agentbundle list-profiles
|
|
39
|
+
|
|
40
|
+
# Install a whole curated profile — a single-scope set of packs — in one command
|
|
41
|
+
agentbundle install --profile inception
|
|
35
42
|
|
|
36
|
-
# Preview
|
|
37
|
-
agentbundle install --pack core
|
|
43
|
+
# Preview any install without writing a file
|
|
44
|
+
agentbundle install --pack core --dry-run
|
|
38
45
|
|
|
39
|
-
# Upgrade
|
|
40
|
-
agentbundle upgrade --pack core
|
|
46
|
+
# Upgrade to the version the catalogue ships — shows installed → target, asks first
|
|
47
|
+
agentbundle upgrade --pack core
|
|
48
|
+
agentbundle upgrade --pack core --yes # skip the prompt (CI)
|
|
49
|
+
|
|
50
|
+
# Uninstall — previews remove (Tier-1) vs keep (your edits), asks first
|
|
51
|
+
agentbundle uninstall --pack core --dry-run
|
|
52
|
+
agentbundle uninstall --pack core --yes
|
|
41
53
|
```
|
|
42
54
|
|
|
43
|
-
A
|
|
55
|
+
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).
|
|
56
|
+
|
|
57
|
+
**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).
|
|
44
58
|
|
|
45
59
|
## Build your own catalogue
|
|
46
60
|
|
|
@@ -77,7 +77,14 @@
|
|
|
77
77
|
# the default agent's `.kiro/skills` auto-discovery (RFC-0022 E4; kiro
|
|
78
78
|
# #6887/#6888/#4993). Additive `inject-resources` on BOTH the kiro-cli and
|
|
79
79
|
# kiro-ide agent projections (CLI → agent JSON, IDE → quoted .md frontmatter).
|
|
80
|
-
|
|
80
|
+
# RFC-0040 / ADR-0030 / docs/specs/consolidated-pack-layout (v0.16): pack.toml
|
|
81
|
+
# gains an optional scope-keyed [pack.layout] table (optional .repo / .user
|
|
82
|
+
# sub-tables, each a `parent` base and/or a within-pack template-path) naming
|
|
83
|
+
# where a consuming pack's durable output lands. Consumed by the new installer
|
|
84
|
+
# `_append_layout_section` step (append-if-exists / never-create / never-
|
|
85
|
+
# overwrite) into an adopter-owned `agentbundle-layout.toml`. Additive +
|
|
86
|
+
# optional — packs pinned below v0.16 build and validate unchanged.
|
|
87
|
+
version = "0.16"
|
|
81
88
|
|
|
82
89
|
# Sibling schemas this contract references — pack metadata and the
|
|
83
90
|
# per-pack Claude-plugin manifest. Defined by spec AC #3 + #4.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Packaged install default — layer 4 of the catalogue-source resolution chain
|
|
2
|
+
# (RFC-0046 / ADR-0036). When `agentbundle install`/`upgrade` is run with no
|
|
3
|
+
# `catalogue` positional and layers 1–3 (explicit arg, user config, editable
|
|
4
|
+
# detection) yield nothing, this source is used.
|
|
5
|
+
#
|
|
6
|
+
# Private-fork pattern: blank the `source` value below (or delete this file
|
|
7
|
+
# entirely) to disable the packaged GitHub default — layers 1–3 still apply, so
|
|
8
|
+
# an editable clone or a `config set source` still resolves.
|
|
9
|
+
[defaults]
|
|
10
|
+
source = "git+https://github.com/eugenelim/agent-ready-repo"
|
|
@@ -131,6 +131,25 @@
|
|
|
131
131
|
"type": "string",
|
|
132
132
|
"pattern": "^[^/].*"
|
|
133
133
|
}
|
|
134
|
+
},
|
|
135
|
+
"layout": {
|
|
136
|
+
"type": "object",
|
|
137
|
+
"properties": {
|
|
138
|
+
"repo": {
|
|
139
|
+
"type": "object",
|
|
140
|
+
"properties": {
|
|
141
|
+
"parent": {"type": "string"},
|
|
142
|
+
"template": {"type": "string"}
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
"user": {
|
|
146
|
+
"type": "object",
|
|
147
|
+
"properties": {
|
|
148
|
+
"parent": {"type": "string"},
|
|
149
|
+
"template": {"type": "string"}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
134
153
|
}
|
|
135
154
|
},
|
|
136
155
|
"if": {
|
|
@@ -72,7 +72,7 @@ def project_packs(pack_paths: list[Path], contract: dict, output_root: Path) ->
|
|
|
72
72
|
dir=str(agents_md.parent),
|
|
73
73
|
)
|
|
74
74
|
try:
|
|
75
|
-
with os.fdopen(fd, "w", encoding="utf-8") as handle:
|
|
75
|
+
with os.fdopen(fd, "w", encoding="utf-8", newline="\n") as handle:
|
|
76
76
|
handle.write(stripped)
|
|
77
77
|
os.replace(tmp_path, agents_md)
|
|
78
78
|
except BaseException:
|
|
@@ -251,7 +251,7 @@ def _project_agent_as_md(
|
|
|
251
251
|
out_fm["readonly"] = readonly
|
|
252
252
|
|
|
253
253
|
output_text = _serialize_frontmatter_md(out_fm) + body
|
|
254
|
-
(target_dir / entry.name).write_text(output_text, encoding="utf-8")
|
|
254
|
+
(target_dir / entry.name).write_text(output_text, encoding="utf-8", newline="\n")
|
|
255
255
|
|
|
256
256
|
|
|
257
257
|
def _derive_readonly(frontmatter: dict[str, Any]) -> bool | None:
|
|
@@ -357,7 +357,7 @@ def _project_hooks_json(source_dir: Path, output_root: Path, rule: dict) -> None
|
|
|
357
357
|
target_path.parent.mkdir(parents=True, exist_ok=True)
|
|
358
358
|
target_path.write_text(
|
|
359
359
|
json.dumps(existing, indent=2, sort_keys=True) + "\n",
|
|
360
|
-
encoding="utf-8",
|
|
360
|
+
encoding="utf-8", newline="\n",
|
|
361
361
|
)
|
|
362
362
|
|
|
363
363
|
|
|
@@ -220,7 +220,7 @@ def _project_agent_as_md(
|
|
|
220
220
|
frontmatter, body = _split_frontmatter(entry.read_text(encoding="utf-8"))
|
|
221
221
|
out_fm = _apply_mapping(frontmatter, mapping, entry.stem)
|
|
222
222
|
output_text = _serialize_frontmatter_md(out_fm) + body
|
|
223
|
-
(target_dir / entry.name).write_text(output_text, encoding="utf-8")
|
|
223
|
+
(target_dir / entry.name).write_text(output_text, encoding="utf-8", newline="\n")
|
|
224
224
|
|
|
225
225
|
|
|
226
226
|
def _apply_mapping(
|
|
@@ -386,7 +386,7 @@ def _project_settings_json(
|
|
|
386
386
|
target_path.parent.mkdir(parents=True, exist_ok=True)
|
|
387
387
|
target_path.write_text(
|
|
388
388
|
json.dumps(existing, indent=2, sort_keys=True) + "\n",
|
|
389
|
-
encoding="utf-8",
|
|
389
|
+
encoding="utf-8", newline="\n",
|
|
390
390
|
)
|
|
391
391
|
|
|
392
392
|
|
|
@@ -255,7 +255,7 @@ def _project_agent_as_md(
|
|
|
255
255
|
|
|
256
256
|
output_text = _serialize_frontmatter_md(rewritten) + body
|
|
257
257
|
destination = target_dir / entry.name # preserves .md extension
|
|
258
|
-
destination.write_text(output_text, encoding="utf-8")
|
|
258
|
+
destination.write_text(output_text, encoding="utf-8", newline="\n")
|
|
259
259
|
|
|
260
260
|
|
|
261
261
|
def _serialize_frontmatter_md(fields: dict[str, Any]) -> str:
|
|
@@ -498,7 +498,7 @@ def _run_per_pack_single(
|
|
|
498
498
|
)
|
|
499
499
|
destination.write_text(
|
|
500
500
|
json.dumps(derived, indent=2, sort_keys=False) + "\n",
|
|
501
|
-
encoding="utf-8",
|
|
501
|
+
encoding="utf-8", newline="\n",
|
|
502
502
|
)
|
|
503
503
|
# Defence-in-depth: re-validate the written file against the schema
|
|
504
504
|
# to catch any serialise/parse divergence introduced by json.dumps.
|
|
@@ -547,7 +547,7 @@ def _run_per_pack_apm(recipe: Recipe, packs: list[Pack], output_dir: Path) -> di
|
|
|
547
547
|
pack_metadata = tomllib.loads((pack.path / "pack.toml").read_text(encoding="utf-8"))
|
|
548
548
|
(per_pack_output / "apm.yml").write_text(
|
|
549
549
|
_render_apm_yml(pack_metadata.get("pack", {})),
|
|
550
|
-
encoding="utf-8",
|
|
550
|
+
encoding="utf-8", newline="\n",
|
|
551
551
|
)
|
|
552
552
|
apm_source = pack.path / ".apm"
|
|
553
553
|
if apm_source.exists():
|
|
@@ -568,7 +568,7 @@ def _run_per_pack_apm(recipe: Recipe, packs: list[Pack], output_dir: Path) -> di
|
|
|
568
568
|
(hooks_dir / "install-marker.py").write_bytes(writer_bytes)
|
|
569
569
|
(hooks_dir / "install-marker.json").write_text(
|
|
570
570
|
json.dumps(_APM_INSTALL_MARKER_HOOK_JSON, indent=2) + "\n",
|
|
571
|
-
encoding="utf-8",
|
|
571
|
+
encoding="utf-8", newline="\n",
|
|
572
572
|
)
|
|
573
573
|
|
|
574
574
|
# Project pack.toml verbatim. The writer reads it for
|
|
@@ -630,7 +630,7 @@ def _run_aggregate(recipe: Recipe, output_dir: Path) -> dict:
|
|
|
630
630
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
631
631
|
output_path.write_text(
|
|
632
632
|
json.dumps({"plugins": entries}, indent=2, sort_keys=True) + "\n",
|
|
633
|
-
encoding="utf-8",
|
|
633
|
+
encoding="utf-8", newline="\n",
|
|
634
634
|
)
|
|
635
635
|
return {"recipe": recipe.name, "type": recipe.type, "entries": len(entries)}
|
|
636
636
|
|
|
@@ -331,4 +331,4 @@ def project_codex_agent_toml(
|
|
|
331
331
|
)
|
|
332
332
|
toml_lines = _emit_fields(rewritten, body)
|
|
333
333
|
destination = target_dir / (entry.stem + ".toml")
|
|
334
|
-
destination.write_text("\n".join(toml_lines) + "\n", encoding="utf-8")
|
|
334
|
+
destination.write_text("\n".join(toml_lines) + "\n", encoding="utf-8", newline="\n")
|
|
@@ -208,4 +208,4 @@ def project_copilot_agent_md(
|
|
|
208
208
|
_validate_tools(frontmatter["tools"])
|
|
209
209
|
emitted["tools"] = frontmatter["tools"]
|
|
210
210
|
destination = target_dir / (entry.stem + ".agent.md")
|
|
211
|
-
destination.write_text(_emit(emitted, body), encoding="utf-8")
|
|
211
|
+
destination.write_text(_emit(emitted, body), encoding="utf-8", newline="\n")
|
{agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/projections/gemini_command_toml.py
RENAMED
|
@@ -227,4 +227,4 @@ def project_gemini_command_toml(
|
|
|
227
227
|
|
|
228
228
|
destination = target_root / relative.with_suffix(".toml")
|
|
229
229
|
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
230
|
-
destination.write_text("\n".join(lines) + "\n", encoding="utf-8")
|
|
230
|
+
destination.write_text("\n".join(lines) + "\n", encoding="utf-8", newline="\n")
|
{agentbundle-0.6.0 → agentbundle-0.8.0}/agentbundle/build/projections/merge_into_agent_json.py
RENAMED
|
@@ -243,7 +243,7 @@ def _atomic_write(target_path: Path, data: dict) -> None:
|
|
|
243
243
|
serialised = json.dumps(data, indent=2, sort_keys=False) + "\n"
|
|
244
244
|
with tempfile.NamedTemporaryFile(
|
|
245
245
|
mode="w",
|
|
246
|
-
encoding="utf-8",
|
|
246
|
+
encoding="utf-8", newline="\n",
|
|
247
247
|
dir=str(target_path.parent),
|
|
248
248
|
prefix=target_path.name + ".",
|
|
249
249
|
suffix=".tmp",
|
|
@@ -54,5 +54,5 @@ def project_merge_json(source_dir: Path, output_root: Path, rule: dict) -> None:
|
|
|
54
54
|
target_path.parent.mkdir(parents=True, exist_ok=True)
|
|
55
55
|
target_path.write_text(
|
|
56
56
|
json.dumps(existing, indent=2, sort_keys=True) + "\n",
|
|
57
|
-
encoding="utf-8",
|
|
57
|
+
encoding="utf-8", newline="\n",
|
|
58
58
|
)
|
|
@@ -296,7 +296,7 @@ def _atomic_write(target_path: Path, data: dict) -> None:
|
|
|
296
296
|
serialised = json.dumps(data, indent=2, sort_keys=False) + "\n"
|
|
297
297
|
with tempfile.NamedTemporaryFile(
|
|
298
298
|
mode="w",
|
|
299
|
-
encoding="utf-8",
|
|
299
|
+
encoding="utf-8", newline="\n",
|
|
300
300
|
dir=str(target_path.parent),
|
|
301
301
|
prefix=target_path.name + ".",
|
|
302
302
|
suffix=".tmp",
|
|
@@ -24,7 +24,9 @@ consumer.
|
|
|
24
24
|
Self-host scope (see docs/specs/self-hosting/spec.md § Phased rollout):
|
|
25
25
|
the `SELF_HOST_ADAPTERS` allow-list runs `claude-code` and `codex`.
|
|
26
26
|
Kiro and Copilot stay distribution-only so self-host does not project
|
|
27
|
-
`.kiro/` or `.github/instructions/`.
|
|
27
|
+
`.kiro/` or `.github/instructions/`. Both `SELF_HOST_ADAPTERS` and
|
|
28
|
+
`SELF_HOST_PACKS` are sourced from `recipes/self-host.toml` (see the
|
|
29
|
+
`_DEFAULT_*` block below); the values named here are the current defaults.
|
|
28
30
|
"""
|
|
29
31
|
|
|
30
32
|
from __future__ import annotations
|
|
@@ -79,27 +81,76 @@ TARGET_PATHS = (
|
|
|
79
81
|
Path("AGENTS.md"),
|
|
80
82
|
)
|
|
81
83
|
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
# are
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
#
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
# `monorepo-extras` is repo-only by metadata but the bundle is not a
|
|
94
|
-
# canonical monorepo consumer of `new-package`, so it's left out too.
|
|
95
|
-
# `_aggregate_marketplace` intentionally ignores this filter — the
|
|
96
|
-
# catalogue advertises every pack.
|
|
97
|
-
SELF_HOST_PACKS: tuple[str, ...] = (
|
|
84
|
+
# Built-in fallbacks for the self-host pack / adapter allow-lists. The
|
|
85
|
+
# authoritative values live in `recipes/self-host.toml` (read at import below);
|
|
86
|
+
# these are used only when that recipe is missing a key or can't be read, so
|
|
87
|
+
# module import stays total. Kiro and Copilot remain in the contract for
|
|
88
|
+
# distribution builds but are excluded from the self-host runner. This repo is
|
|
89
|
+
# the catalogue's home, not an adopter, so `make build-self` only projects the
|
|
90
|
+
# in-house packs; `_aggregate_marketplace` intentionally ignores the pack
|
|
91
|
+
# filter — the catalogue advertises every pack. See the recipe for the full
|
|
92
|
+
# rationale behind the pack selection.
|
|
93
|
+
_DEFAULT_SELF_HOST_ADAPTERS: tuple[str, ...] = ("claude-code", "codex")
|
|
94
|
+
_DEFAULT_SELF_HOST_PACKS: tuple[str, ...] = (
|
|
98
95
|
"core",
|
|
99
96
|
"governance-extras",
|
|
100
97
|
"user-guide-diataxis",
|
|
101
98
|
)
|
|
102
99
|
|
|
100
|
+
_SELF_HOST_RECIPE = "self-host"
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _read_recipe_text(name: str) -> str | None:
|
|
104
|
+
"""Return the text of `recipes/<name>.toml`, or None if unreadable.
|
|
105
|
+
|
|
106
|
+
Mirrors `build.main`'s recipe resolution: filesystem first (dev / editable
|
|
107
|
+
install), then `importlib.resources` (zipapp, where the package lives inside
|
|
108
|
+
a `.pyz` archive that `Path.exists()` cannot traverse).
|
|
109
|
+
"""
|
|
110
|
+
recipe_path = Path(__file__).resolve().parent / "recipes" / f"{name}.toml"
|
|
111
|
+
if recipe_path.exists():
|
|
112
|
+
return recipe_path.read_text(encoding="utf-8")
|
|
113
|
+
try:
|
|
114
|
+
from importlib.resources import files
|
|
115
|
+
|
|
116
|
+
resource = files("agentbundle.build").joinpath(f"recipes/{name}.toml")
|
|
117
|
+
if resource.is_file():
|
|
118
|
+
return resource.read_text(encoding="utf-8")
|
|
119
|
+
except (FileNotFoundError, ModuleNotFoundError):
|
|
120
|
+
pass
|
|
121
|
+
return None
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _extract_self_host_lists(
|
|
125
|
+
recipe: dict,
|
|
126
|
+
) -> tuple[tuple[str, ...], tuple[str, ...]]:
|
|
127
|
+
"""Pull `(packs, adapters)` from a parsed self-host recipe, substituting the
|
|
128
|
+
built-in defaults for any list that is absent or empty."""
|
|
129
|
+
body = recipe.get("recipe", {})
|
|
130
|
+
packs = tuple(body.get("packs", {}).get("include", ())) or _DEFAULT_SELF_HOST_PACKS
|
|
131
|
+
adapters = (
|
|
132
|
+
tuple(body.get("adapters", {}).get("targets", ()))
|
|
133
|
+
or _DEFAULT_SELF_HOST_ADAPTERS
|
|
134
|
+
)
|
|
135
|
+
return packs, adapters
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _load_self_host_lists() -> tuple[tuple[str, ...], tuple[str, ...]]:
|
|
139
|
+
"""Read the self-host allow-lists from the recipe. Total: any read or parse
|
|
140
|
+
failure falls back to the built-in defaults so module import never raises."""
|
|
141
|
+
try:
|
|
142
|
+
text = _read_recipe_text(_SELF_HOST_RECIPE)
|
|
143
|
+
if text is None:
|
|
144
|
+
return _DEFAULT_SELF_HOST_PACKS, _DEFAULT_SELF_HOST_ADAPTERS
|
|
145
|
+
return _extract_self_host_lists(tomllib.loads(text))
|
|
146
|
+
except Exception:
|
|
147
|
+
# Unreadable (non-UTF-8 / permission / IO) or malformed recipe — fall
|
|
148
|
+
# back so module import is total (AC3).
|
|
149
|
+
return _DEFAULT_SELF_HOST_PACKS, _DEFAULT_SELF_HOST_ADAPTERS
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
SELF_HOST_PACKS, SELF_HOST_ADAPTERS = _load_self_host_lists()
|
|
153
|
+
|
|
103
154
|
|
|
104
155
|
def _filter_self_host_packs(pack_paths: list[Path]) -> list[Path]:
|
|
105
156
|
"""Return the subset of *pack_paths* whose directory name is in
|
|
@@ -195,7 +246,7 @@ def resolve_markers(
|
|
|
195
246
|
text,
|
|
196
247
|
)
|
|
197
248
|
if replaced != text:
|
|
198
|
-
path.write_text(replaced, encoding="utf-8")
|
|
249
|
+
path.write_text(replaced, encoding="utf-8", newline="\n")
|
|
199
250
|
modified += 1
|
|
200
251
|
return modified
|
|
201
252
|
|
|
@@ -270,7 +321,7 @@ def _compose_agents_md(
|
|
|
270
321
|
body = body_path.read_text(encoding="utf-8").replace("\r\n", "\n")
|
|
271
322
|
if body and not body.endswith("\n"):
|
|
272
323
|
body += "\n"
|
|
273
|
-
target_path.write_text(body, encoding="utf-8")
|
|
324
|
+
target_path.write_text(body, encoding="utf-8", newline="\n")
|
|
274
325
|
|
|
275
326
|
if footer_path.exists():
|
|
276
327
|
text = target_path.read_text(encoding="utf-8")
|
|
@@ -279,7 +330,7 @@ def _compose_agents_md(
|
|
|
279
330
|
text += "\n"
|
|
280
331
|
if footer and not footer.endswith("\n"):
|
|
281
332
|
footer += "\n"
|
|
282
|
-
target_path.write_text(text + footer, encoding="utf-8")
|
|
333
|
+
target_path.write_text(text + footer, encoding="utf-8", newline="\n")
|
|
283
334
|
return target_path
|
|
284
335
|
|
|
285
336
|
|
|
@@ -329,6 +380,7 @@ EXCLUDED_PATTERNS: tuple[str, ...] = (
|
|
|
329
380
|
"README.md", # root-level; nested README.md not excluded
|
|
330
381
|
"LICENSE-*",
|
|
331
382
|
".gitignore",
|
|
383
|
+
".gitattributes",
|
|
332
384
|
".github/**",
|
|
333
385
|
"AGENTS.local.md",
|
|
334
386
|
"AGENTS.md", # root-level; nested AGENTS.md not excluded
|
|
@@ -535,7 +587,7 @@ def _aggregate_marketplace(
|
|
|
535
587
|
}
|
|
536
588
|
target.write_text(
|
|
537
589
|
json.dumps(payload, indent=2, sort_keys=True) + "\n",
|
|
538
|
-
encoding="utf-8",
|
|
590
|
+
encoding="utf-8", newline="\n",
|
|
539
591
|
)
|
|
540
592
|
return target
|
|
541
593
|
|
|
@@ -1463,10 +1515,42 @@ def run_build_check_drift_gates(
|
|
|
1463
1515
|
return 0
|
|
1464
1516
|
|
|
1465
1517
|
|
|
1518
|
+
def _refuse_fixture_packs_dir(packs_dir: Path, *, dry_run: bool) -> int | None:
|
|
1519
|
+
"""Refuse a real-write self-host whose `packs_dir` points into
|
|
1520
|
+
`tests/fixtures/` (which would overwrite the working tree with fixture
|
|
1521
|
+
data), unless `ALLOW_FIXTURE_PACKS` is set.
|
|
1522
|
+
|
|
1523
|
+
This is the cross-platform home of the guard that used to live only in the
|
|
1524
|
+
Makefile `build-self` recipe — so the make-free entry
|
|
1525
|
+
`python -m agentbundle.build self` (the only way to run build-self on
|
|
1526
|
+
Windows) is protected too. Returns a non-zero exit code to refuse, or
|
|
1527
|
+
`None` to proceed. Dry-run writes to a shadow temp dir, so it is never
|
|
1528
|
+
guarded (matching the `run_self_host` dirty-tree check). `as_posix()`
|
|
1529
|
+
normalises separators so the match is Windows-safe.
|
|
1530
|
+
"""
|
|
1531
|
+
if dry_run or os.environ.get("ALLOW_FIXTURE_PACKS"):
|
|
1532
|
+
return None
|
|
1533
|
+
# Trailing slash mirrors the historical Makefile glob `*tests/fixtures/*`
|
|
1534
|
+
# exactly — so a sibling like `my-tests/fixtures-backup/` doesn't over-match.
|
|
1535
|
+
if "tests/fixtures/" in packs_dir.as_posix():
|
|
1536
|
+
print(
|
|
1537
|
+
"self-host: refusing — --packs-dir points into tests/fixtures/; "
|
|
1538
|
+
"this would overwrite your working tree with fixture data. Set "
|
|
1539
|
+
"ALLOW_FIXTURE_PACKS=1 to override, or use --packs-dir packs.",
|
|
1540
|
+
file=sys.stderr,
|
|
1541
|
+
)
|
|
1542
|
+
return 2
|
|
1543
|
+
return None
|
|
1544
|
+
|
|
1545
|
+
|
|
1466
1546
|
def cmd_self(args) -> int:
|
|
1547
|
+
packs_dir = Path(args.packs_dir).resolve()
|
|
1548
|
+
refusal = _refuse_fixture_packs_dir(packs_dir, dry_run=args.dry_run)
|
|
1549
|
+
if refusal is not None:
|
|
1550
|
+
return refusal
|
|
1467
1551
|
return run_self_host(
|
|
1468
1552
|
working_tree=Path(args.output_dir).resolve(),
|
|
1469
|
-
packs_dir=
|
|
1553
|
+
packs_dir=packs_dir,
|
|
1470
1554
|
dry_run=args.dry_run,
|
|
1471
1555
|
force=args.force,
|
|
1472
1556
|
no_symlink=getattr(args, "no_symlink", False),
|
|
@@ -53,10 +53,11 @@ class CursorContractTests(unittest.TestCase):
|
|
|
53
53
|
def test_contract_version_is_0_11(self) -> None:
|
|
54
54
|
"""AC1 — contract bumped to 0.11 by cursor-full-parity; subsequently
|
|
55
55
|
0.12 (copilot-skills-and-web), 0.13 (docs/specs/gemini-full-parity),
|
|
56
|
-
0.14 (docs/specs/enriched-pack-manifest),
|
|
57
|
-
(docs/specs/kiro-cli-agent-skill-resources).
|
|
56
|
+
0.14 (docs/specs/enriched-pack-manifest), 0.15
|
|
57
|
+
(docs/specs/kiro-cli-agent-skill-resources), then 0.16
|
|
58
|
+
(docs/specs/consolidated-pack-layout).
|
|
58
59
|
Name preserved to keep the diff small."""
|
|
59
|
-
self.assertEqual(self.contract["contract"]["version"], "0.
|
|
60
|
+
self.assertEqual(self.contract["contract"]["version"], "0.16")
|
|
60
61
|
|
|
61
62
|
def test_cursor_block_projects_five_primitives(self) -> None:
|
|
62
63
|
"""AC2 — the five standard primitives are in the projection array."""
|
|
@@ -151,9 +151,9 @@ class GeminiContractTests(unittest.TestCase):
|
|
|
151
151
|
cls.contract = load_contract(CONTRACT_PATH)
|
|
152
152
|
|
|
153
153
|
def test_contract_version_is_0_14(self) -> None:
|
|
154
|
-
"""Contract version is 0.
|
|
155
|
-
bumped it from
|
|
156
|
-
self.assertEqual(self.contract["contract"]["version"], "0.
|
|
154
|
+
"""Contract version is 0.16 (docs/specs/consolidated-pack-layout
|
|
155
|
+
bumped it from kiro-cli-agent-skill-resources' 0.15). Name preserved."""
|
|
156
|
+
self.assertEqual(self.contract["contract"]["version"], "0.16")
|
|
157
157
|
|
|
158
158
|
def test_gemini_block_projects_five_primitives(self) -> None:
|
|
159
159
|
"""AC2 — five standard primitives with their gemini targets."""
|