agentbundle 0.2.0__py3-none-any.whl

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.
Files changed (99) hide show
  1. agentbundle/__init__.py +14 -0
  2. agentbundle/__main__.py +5 -0
  3. agentbundle/_data/adapter.schema.json +270 -0
  4. agentbundle/_data/adapter.toml +584 -0
  5. agentbundle/_data/install-marker.py +1099 -0
  6. agentbundle/_data/pack.schema.json +152 -0
  7. agentbundle/_data/plugin-manifest.derived.schema.json +33 -0
  8. agentbundle/_data/plugin-manifest.schema.json +18 -0
  9. agentbundle/build/__init__.py +206 -0
  10. agentbundle/build/__main__.py +8 -0
  11. agentbundle/build/adapter_root_bins.py +336 -0
  12. agentbundle/build/adapters/__init__.py +46 -0
  13. agentbundle/build/adapters/claude_code.py +142 -0
  14. agentbundle/build/adapters/codex.py +227 -0
  15. agentbundle/build/adapters/copilot.py +149 -0
  16. agentbundle/build/adapters/kiro.py +608 -0
  17. agentbundle/build/adapters/kiro_cli.py +53 -0
  18. agentbundle/build/adapters/kiro_ide.py +275 -0
  19. agentbundle/build/contract.py +20 -0
  20. agentbundle/build/lint_packs.py +555 -0
  21. agentbundle/build/main.py +596 -0
  22. agentbundle/build/phase_order.py +40 -0
  23. agentbundle/build/projections/__init__.py +13 -0
  24. agentbundle/build/projections/codex_agent_toml.py +232 -0
  25. agentbundle/build/projections/copilot_agent_md.py +206 -0
  26. agentbundle/build/projections/copilot_hooks_json.py +142 -0
  27. agentbundle/build/projections/direct_directory.py +41 -0
  28. agentbundle/build/projections/hook_id.py +27 -0
  29. agentbundle/build/projections/kiro_ide_hook.py +256 -0
  30. agentbundle/build/projections/merge_into_agent_json.py +264 -0
  31. agentbundle/build/projections/merge_json.py +58 -0
  32. agentbundle/build/projections/user_merge_json.py +324 -0
  33. agentbundle/build/scope_rails.py +728 -0
  34. agentbundle/build/self_host.py +1486 -0
  35. agentbundle/build/shared_libs.py +309 -0
  36. agentbundle/build/target_resolver.py +85 -0
  37. agentbundle/build/tests/__init__.py +0 -0
  38. agentbundle/build/tests/test_adapter_claude_code.py +275 -0
  39. agentbundle/build/tests/test_adapter_codex.py +699 -0
  40. agentbundle/build/tests/test_adapter_copilot.py +91 -0
  41. agentbundle/build/tests/test_adapter_kiro.py +449 -0
  42. agentbundle/build/tests/test_adapter_kiro_alias.py +105 -0
  43. agentbundle/build/tests/test_adapter_kiro_cli.py +102 -0
  44. agentbundle/build/tests/test_adapter_kiro_ide.py +173 -0
  45. agentbundle/build/tests/test_adapter_root_bins_projection.py +429 -0
  46. agentbundle/build/tests/test_build_ships_seeds.py +78 -0
  47. agentbundle/build/tests/test_contract.py +582 -0
  48. agentbundle/build/tests/test_contract_scope.py +224 -0
  49. agentbundle/build/tests/test_contract_v07.py +191 -0
  50. agentbundle/build/tests/test_contract_v08.py +230 -0
  51. agentbundle/build/tests/test_direct_directory_cleanup.py +65 -0
  52. agentbundle/build/tests/test_end_to_end_build.py +227 -0
  53. agentbundle/build/tests/test_lint_agents_md_legacy_block.py +135 -0
  54. agentbundle/build/tests/test_lint_agents_md_risk_block.py +116 -0
  55. agentbundle/build/tests/test_lint_packs.py +703 -0
  56. agentbundle/build/tests/test_load_pack_hook_wiring_safely.py +176 -0
  57. agentbundle/build/tests/test_pack_schema.py +265 -0
  58. agentbundle/build/tests/test_pack_schema_allowed_adapters.py +258 -0
  59. agentbundle/build/tests/test_pack_schema_install.py +305 -0
  60. agentbundle/build/tests/test_pipeline.py +272 -0
  61. agentbundle/build/tests/test_plugin_manifest_schema.py +327 -0
  62. agentbundle/build/tests/test_projections_merge_json.py +148 -0
  63. agentbundle/build/tests/test_scope_rails.py +398 -0
  64. agentbundle/build/tests/test_security.py +97 -0
  65. agentbundle/build/tests/test_self_host_check.py +2100 -0
  66. agentbundle/build/tests/test_shared_libs_projection.py +415 -0
  67. agentbundle/build/tests/test_shipped_packs_v07_declarations.py +100 -0
  68. agentbundle/build/tests/test_shipped_packs_v08_declarations.py +80 -0
  69. agentbundle/build/tests/test_validate.py +250 -0
  70. agentbundle/build/validate.py +141 -0
  71. agentbundle/catalogue.py +164 -0
  72. agentbundle/cli.py +486 -0
  73. agentbundle/commands/__init__.py +5 -0
  74. agentbundle/commands/_common.py +174 -0
  75. agentbundle/commands/_drop_warning.py +329 -0
  76. agentbundle/commands/adapt.py +343 -0
  77. agentbundle/commands/config.py +125 -0
  78. agentbundle/commands/diff.py +211 -0
  79. agentbundle/commands/init_state.py +279 -0
  80. agentbundle/commands/install.py +3026 -0
  81. agentbundle/commands/list_packs.py +170 -0
  82. agentbundle/commands/list_targets.py +23 -0
  83. agentbundle/commands/reconcile.py +161 -0
  84. agentbundle/commands/render.py +165 -0
  85. agentbundle/commands/scaffold.py +69 -0
  86. agentbundle/commands/uninstall.py +294 -0
  87. agentbundle/commands/upgrade.py +699 -0
  88. agentbundle/commands/validate.py +688 -0
  89. agentbundle/config.py +747 -0
  90. agentbundle/render.py +123 -0
  91. agentbundle/safety.py +633 -0
  92. agentbundle/scope.py +319 -0
  93. agentbundle/user_config.py +284 -0
  94. agentbundle/version.py +49 -0
  95. agentbundle-0.2.0.dist-info/METADATA +37 -0
  96. agentbundle-0.2.0.dist-info/RECORD +99 -0
  97. agentbundle-0.2.0.dist-info/WHEEL +5 -0
  98. agentbundle-0.2.0.dist-info/entry_points.txt +2 -0
  99. agentbundle-0.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,152 @@
1
+ {
2
+ "type": "object",
3
+ "required": ["pack"],
4
+ "properties": {
5
+ "pack": {
6
+ "type": "object",
7
+ "required": ["name", "version"],
8
+ "properties": {
9
+ "name": {"type": "string"},
10
+ "version": {"type": "string"},
11
+ "description": {"type": "string"},
12
+ "adapter-contract": {
13
+ "type": "object",
14
+ "properties": {
15
+ "version": {"type": "string"}
16
+ }
17
+ },
18
+ "recipes": {
19
+ "type": "array",
20
+ "items": {"type": "string"}
21
+ },
22
+ "dependencies": {
23
+ "type": "object",
24
+ "properties": {
25
+ "required": {
26
+ "type": "array",
27
+ "items": {
28
+ "type": "object",
29
+ "required": ["catalogue", "pack", "version"],
30
+ "properties": {
31
+ "catalogue": {"type": "string"},
32
+ "pack": {"type": "string"},
33
+ "version": {"type": "string"}
34
+ }
35
+ }
36
+ },
37
+ "recommended": {
38
+ "type": "array",
39
+ "items": {
40
+ "type": "object",
41
+ "required": ["catalogue", "pack", "version"],
42
+ "properties": {
43
+ "catalogue": {"type": "string"},
44
+ "pack": {"type": "string"},
45
+ "version": {"type": "string"}
46
+ }
47
+ }
48
+ },
49
+ "conflicts": {
50
+ "type": "array",
51
+ "items": {
52
+ "type": "object",
53
+ "required": ["catalogue", "pack", "version"],
54
+ "properties": {
55
+ "catalogue": {"type": "string"},
56
+ "pack": {"type": "string"},
57
+ "version": {"type": "string"}
58
+ }
59
+ }
60
+ }
61
+ }
62
+ },
63
+ "adaptation": {
64
+ "type": "object",
65
+ "properties": {
66
+ "infer-from": {"type": "string"},
67
+ "substitutions": {
68
+ "type": "array",
69
+ "items": {
70
+ "type": "object",
71
+ "properties": {
72
+ "marker": {"type": "string"},
73
+ "infer-from": {"type": "string"}
74
+ }
75
+ }
76
+ },
77
+ "augmentation-points": {
78
+ "type": "array",
79
+ "items": {
80
+ "type": "object",
81
+ "properties": {
82
+ "target": {"type": "string"},
83
+ "section-marker": {"type": "string"},
84
+ "describe": {"type": "string"}
85
+ }
86
+ }
87
+ }
88
+ }
89
+ },
90
+ "seeds": {
91
+ "type": "array",
92
+ "items": {
93
+ "type": "string",
94
+ "pattern": "^[^/].*"
95
+ }
96
+ }
97
+ },
98
+ "if": {
99
+ "properties": {
100
+ "adapter-contract": {
101
+ "type": "object",
102
+ "properties": {"version": {"enum": ["0.2", "0.3", "0.6"]}},
103
+ "required": ["version"]
104
+ }
105
+ },
106
+ "required": ["adapter-contract"]
107
+ },
108
+ "then": {
109
+ "required": ["install"],
110
+ "properties": {
111
+ "install": {
112
+ "type": "object",
113
+ "required": ["default-scope"],
114
+ "properties": {
115
+ "default-scope": {"enum": ["repo", "user"]},
116
+ "allowed-scopes": {
117
+ "type": "array",
118
+ "minItems": 1,
119
+ "items": {"enum": ["repo", "user"]}
120
+ },
121
+ "user-scope-hooks": {"type": "boolean"},
122
+ "allowed-adapters": {
123
+ "type": "array",
124
+ "minItems": 1,
125
+ "uniqueItems": true,
126
+ "items": {"type": "string"}
127
+ }
128
+ },
129
+ "if": {
130
+ "properties": {"default-scope": {"enum": ["user"]}},
131
+ "required": ["default-scope"]
132
+ },
133
+ "then": {
134
+ "properties": {
135
+ "allowed-scopes": {
136
+ "contains": {"enum": ["user"]}
137
+ }
138
+ }
139
+ },
140
+ "else": {
141
+ "properties": {
142
+ "allowed-scopes": {
143
+ "contains": {"enum": ["repo"]}
144
+ }
145
+ }
146
+ }
147
+ }
148
+ }
149
+ }
150
+ }
151
+ }
152
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "type": "object",
3
+ "required": ["name", "version", "description"],
4
+ "additionalProperties": false,
5
+ "properties": {
6
+ "name": {"type": "string"},
7
+ "version": {"type": "string"},
8
+ "description": {"type": "string"},
9
+ "skills": {
10
+ "type": "array",
11
+ "items": {"type": "string"}
12
+ },
13
+ "agents": {
14
+ "type": "array",
15
+ "items": {"type": "string"}
16
+ },
17
+ "hooks": {
18
+ "type": "object",
19
+ "properties": {
20
+ "SessionStart": {
21
+ "type": "array",
22
+ "items": {
23
+ "type": "object",
24
+ "required": ["command"],
25
+ "properties": {
26
+ "command": {"type": "string"}
27
+ }
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "type": "object",
3
+ "required": ["name", "version", "description"],
4
+ "additionalProperties": false,
5
+ "properties": {
6
+ "name": {"type": "string"},
7
+ "version": {"type": "string"},
8
+ "description": {"type": "string"},
9
+ "skills": {
10
+ "type": "array",
11
+ "items": {"type": "string"}
12
+ },
13
+ "agents": {
14
+ "type": "array",
15
+ "items": {"type": "string"}
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,206 @@
1
+ """Build pipeline: adapter contract, reference adapters, recipes, self-host gate.
2
+
3
+ `main` is the CLI entrypoint — `python -m agentbundle.build` and the
4
+ `tools/build/build.py` shim both call it. Sibling specs (self-hosting,
5
+ RFC-0003's CLI) import `agentbundle.build` as a library; the public
6
+ surface is `main`, `validate.validate`, and the adapter `project`
7
+ functions exposed through `adapters`.
8
+
9
+ Subcommands landed in T1a:
10
+ - `validate <path>` — load a TOML contract and check it against
11
+ adapter.schema.json. Exit 0 on valid; 1 on invalid with a one-line stderr
12
+ message.
13
+
14
+ Subcommands landing in later tasks (T6–T8):
15
+ - `build` (default) + `--recipe`, `--self`, `--dry-run`, `--check`,
16
+ `--force`, `--scaffold`, `PACK=`, `RECIPE=`.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import argparse
22
+ import json
23
+ import shutil
24
+ import sys
25
+ from pathlib import Path
26
+
27
+ from agentbundle.build.contract import load as load_contract
28
+ from agentbundle.build.validate import validate as validate_instance
29
+ from agentbundle.build.lint_packs import cmd_lint_packs
30
+ from agentbundle.build.main import cmd_build
31
+ from agentbundle.build.self_host import cmd_check, cmd_self
32
+
33
+ __all__ = ["main"]
34
+
35
+
36
+ def _cmd_validate(args: argparse.Namespace) -> int:
37
+ contract_path = Path(args.path)
38
+ if not contract_path.exists():
39
+ print(
40
+ f"validate: contract file not found at {contract_path}",
41
+ file=sys.stderr,
42
+ )
43
+ return 1
44
+
45
+ schema_path = (
46
+ Path(__file__).resolve().parent.parent.parent.parent.parent
47
+ / "docs"
48
+ / "contracts"
49
+ / "adapter.schema.json"
50
+ )
51
+ if not schema_path.exists():
52
+ print(
53
+ f"validate: adapter.schema.json not found at {schema_path}",
54
+ file=sys.stderr,
55
+ )
56
+ return 1
57
+
58
+ try:
59
+ contract = load_contract(contract_path)
60
+ except Exception as exc:
61
+ print(f"validate: failed to load {contract_path}: {exc}", file=sys.stderr)
62
+ return 1
63
+
64
+ schema = json.loads(schema_path.read_text(encoding="utf-8"))
65
+ errors = validate_instance(contract, schema)
66
+ if errors:
67
+ print(
68
+ f"validate: {contract_path} failed schema validation:",
69
+ file=sys.stderr,
70
+ )
71
+ for error in errors:
72
+ print(f" {error}", file=sys.stderr)
73
+ return 1
74
+
75
+ return 0
76
+
77
+
78
+ def _build_parser() -> argparse.ArgumentParser:
79
+ parser = argparse.ArgumentParser(
80
+ prog="agentbundle.build",
81
+ description="Build pipeline for the agent-ready-repo catalogue.",
82
+ )
83
+ subparsers = parser.add_subparsers(dest="command")
84
+
85
+ validate_parser = subparsers.add_parser(
86
+ "validate",
87
+ help="Validate a TOML file against the adapter-contract schema.",
88
+ )
89
+ validate_parser.add_argument(
90
+ "path",
91
+ help="path to adapter.toml (or any TOML file the schema accepts)",
92
+ )
93
+ validate_parser.set_defaults(func=_cmd_validate)
94
+
95
+ build_parser = subparsers.add_parser(
96
+ "build",
97
+ help="Run a recipe (or the three RFC-0001 default recipes).",
98
+ )
99
+ build_parser.add_argument(
100
+ "--recipe",
101
+ help="Recipe name (under build/recipes/) or explicit .toml path.",
102
+ )
103
+ build_parser.add_argument("--pack", help="Limit to one pack by name.")
104
+ build_parser.add_argument(
105
+ "--packs-dir",
106
+ default="packs",
107
+ help="Directory containing pack subdirectories (default: packs/).",
108
+ )
109
+ build_parser.add_argument(
110
+ "--output-dir",
111
+ default="dist",
112
+ help="Where to write build artefacts (default: dist/).",
113
+ )
114
+ build_parser.set_defaults(func=cmd_build)
115
+
116
+ self_parser = subparsers.add_parser(
117
+ "self",
118
+ help="Self-host build: render into the working tree (--dry-run for diff).",
119
+ )
120
+ self_parser.add_argument("--dry-run", action="store_true")
121
+ self_parser.add_argument("--force", action="store_true")
122
+ self_parser.add_argument("--packs-dir", default="packs")
123
+ self_parser.add_argument("--output-dir", default=".")
124
+ self_parser.add_argument(
125
+ "--no-symlink",
126
+ action="store_true",
127
+ help=(
128
+ "Write CLAUDE.md as a regular-file copy of AGENTS.md instead of "
129
+ "a symlink. Default behaviour on Windows hosts; available on any "
130
+ "OS for filesystems or workflows that disallow symlinks."
131
+ ),
132
+ )
133
+ self_parser.set_defaults(func=cmd_self)
134
+
135
+ check_parser = subparsers.add_parser(
136
+ "check",
137
+ help="Strict self-host dry-run; non-zero on any drift.",
138
+ )
139
+ check_parser.add_argument("--packs-dir", default="packs")
140
+ check_parser.add_argument("--output-dir", default=".")
141
+ check_parser.add_argument(
142
+ "--no-symlink",
143
+ action="store_true",
144
+ help=(
145
+ "As `self --no-symlink`: compare the projection against a "
146
+ "regular-file CLAUDE.md copy rather than a symlink."
147
+ ),
148
+ )
149
+ check_parser.set_defaults(func=cmd_check)
150
+
151
+ scaffold_parser = subparsers.add_parser(
152
+ "scaffold",
153
+ help="Drop a pack's seeds/ into the named output directory.",
154
+ )
155
+ scaffold_parser.add_argument("--packs-dir", default="packs")
156
+ scaffold_parser.add_argument("--pack", default="core")
157
+ scaffold_parser.add_argument("--output", required=True)
158
+ scaffold_parser.set_defaults(func=_cmd_scaffold)
159
+
160
+ lint_packs_parser = subparsers.add_parser(
161
+ "lint-packs",
162
+ help=(
163
+ "Windows-portability lint: reject packs that ship symlinks "
164
+ "or Windows-poisonous names under seeds/ or .apm/."
165
+ ),
166
+ )
167
+ lint_packs_parser.add_argument("--packs-dir", default="packs")
168
+ lint_packs_parser.set_defaults(func=cmd_lint_packs)
169
+
170
+ return parser
171
+
172
+
173
+ def _cmd_scaffold(args) -> int:
174
+ pack_seeds = Path(args.packs_dir) / args.pack / "seeds"
175
+ output = Path(args.output)
176
+ if not pack_seeds.exists():
177
+ print(f"scaffold: no seeds/ in pack {args.pack!r}", file=sys.stderr)
178
+ return 1
179
+ output.mkdir(parents=True, exist_ok=True)
180
+ for entry in pack_seeds.iterdir():
181
+ destination = output / entry.name
182
+ if entry.is_dir():
183
+ if destination.exists():
184
+ shutil.rmtree(destination)
185
+ shutil.copytree(entry, destination)
186
+ else:
187
+ shutil.copy2(entry, destination)
188
+ return 0
189
+
190
+
191
+ def main(argv: list[str] | None = None) -> int:
192
+ # Lazy import: keeps the helper resolved at the call site so a
193
+ # future split between `agentbundle.cli` and `agentbundle.build`
194
+ # (different distributions, different load orders) doesn't break
195
+ # this entry point. No circular dependency exists today and the
196
+ # incremental import cost is sub-millisecond; this is a
197
+ # call-site-locality choice, not a perf optimisation.
198
+ from agentbundle.cli import _normalise_path_separators
199
+
200
+ parser = _build_parser()
201
+ args = parser.parse_args(argv)
202
+ if not getattr(args, "func", None):
203
+ parser.print_help()
204
+ return 0
205
+ _normalise_path_separators(args)
206
+ return int(args.func(args))
@@ -0,0 +1,8 @@
1
+ """`python -m agentbundle.build` entrypoint."""
2
+
3
+ import sys
4
+
5
+ from agentbundle.build import main
6
+
7
+ if __name__ == "__main__":
8
+ sys.exit(main())