docs(prd-0011): drop the migration command requirement
claude-bottle has a single primary user today; an automated JSON → MD migration tool is overkill. Hand-rewriting one file is the migration cost. The resolver still dies with a pointer at the README's manifest section if a stale claude-bottle.json is found alongside no .claude-bottle/ directory, so the breaking change isn't silent. Drops: SC #6 (migration tool), the "Migration command" In Scope sub-bullet, the migrate_manifest.py / cli wiring entries from Existing code touched, the tests/integration/test_migrate_manifest.py entry from Tests, the destructive-vs-additive open question. Renumbers the remaining success criteria 6, 7 (formerly 7, 8). Backward-compat section rewritten around hand-rewrite.
This commit is contained in:
@@ -87,21 +87,13 @@ Each test runs against a temporary `$HOME` and a temporary `$CWD`:
|
||||
parser test. Frontmatter parsing is hand-rolled against the
|
||||
declared YAML subset.
|
||||
|
||||
6. **Migration tool converts existing JSON to per-file MD.**
|
||||
`./cli.py migrate-manifest` reads `$HOME/claude-bottle.json`
|
||||
(and `$CWD/claude-bottle.json` if present), writes a tree of
|
||||
per-file MD docs to the new locations, then prints what was
|
||||
moved. Idempotent: rerunning is a no-op when the new layout
|
||||
already exists. Does not delete the old JSON files
|
||||
automatically (user-driven cleanup).
|
||||
|
||||
7. **Existing tests pass against the new layout.** Tests today
|
||||
6. **Existing tests pass against the new layout.** Tests today
|
||||
build manifests via JSON literals against `Manifest.from_json_obj`.
|
||||
That entry point keeps working for tests (used to construct
|
||||
manifests programmatically); production resolution flows
|
||||
through the new directory-globbing loader.
|
||||
|
||||
8. **Agent files double as Claude Code subagent files.** The
|
||||
7. **Agent files double as Claude Code subagent files.** The
|
||||
`name`, `description`, `model`, `color`, and `memory` fields
|
||||
from Claude Code's existing subagent spec are accepted in
|
||||
our frontmatter alongside our own fields. Copying an agent
|
||||
@@ -119,11 +111,11 @@ Each test runs against a temporary `$HOME` and a temporary `$CWD`:
|
||||
pointer at the spec. We are not building a YAML library.
|
||||
|
||||
- **Compatibility with the old JSON layout at runtime.** The
|
||||
resolver no longer reads `claude-bottle.json` files. The
|
||||
migration tool is the bridge; after migration the JSON file
|
||||
is stale (and the user removes it). This is a breaking
|
||||
change for v1 users; the migration cost is one command + a
|
||||
manual delete.
|
||||
resolver no longer reads `claude-bottle.json` files. This is
|
||||
a breaking change; existing users hand-rewrite their JSON
|
||||
into the new per-file layout (claude-bottle has a single
|
||||
primary user today, so the migration is one person rewriting
|
||||
one file). Documented as part of the README rewrite.
|
||||
|
||||
- **`$HOME/.claude/agents/` integration on the input side.** We
|
||||
don't read agent files out of Claude Code's directory. Our
|
||||
@@ -208,25 +200,6 @@ Each test runs against a temporary `$HOME` and a temporary `$CWD`:
|
||||
5. Warn if `$CWD/.claude-bottle/bottles/` exists with files.
|
||||
6. Return Manifest dataclass — same shape as today.
|
||||
|
||||
- **Migration command.** `./cli.py migrate-manifest`:
|
||||
- Reads `$HOME/claude-bottle.json` and (if present)
|
||||
`$CWD/claude-bottle.json`.
|
||||
- Creates `$HOME/.claude-bottle/{bottles,agents}/` dirs.
|
||||
- For each `bottles[<name>]`, writes
|
||||
`$HOME/.claude-bottle/bottles/<name>.md` with frontmatter
|
||||
rendered from the bottle dict, body empty (or a one-line
|
||||
"Migrated from claude-bottle.json on <date>" stub).
|
||||
- For each home `agents[<name>]`, writes
|
||||
`$HOME/.claude-bottle/agents/<name>.md` with frontmatter
|
||||
(bottle, skills, etc.) and body = `prompt`.
|
||||
- For each cwd `agents[<name>]` (if cwd JSON existed),
|
||||
writes `$CWD/.claude-bottle/agents/<name>.md`.
|
||||
- Refuses to overwrite existing MD files; if a target
|
||||
already exists, prints what would have been written and
|
||||
bails on that file (continues with the others).
|
||||
- Prints a summary at the end: N bottles written, M agents
|
||||
written, what was skipped.
|
||||
|
||||
- **Docs.** README's manifest section rewrites against the new
|
||||
layout. `claude-bottle.example.json` becomes
|
||||
`examples/bottles/dev.md` + `examples/agents/implementer.md`.
|
||||
@@ -238,9 +211,7 @@ Each test runs against a temporary `$HOME` and a temporary `$CWD`:
|
||||
- `tests/unit/test_yaml_subset_parser.py` — the parser
|
||||
itself, including all the rejection cases listed above.
|
||||
- `tests/unit/test_manifest_md_load.py` — directory-globbing
|
||||
+ assembly, the 8 success criteria.
|
||||
- `tests/integration/test_migrate_manifest.py` — round-trip
|
||||
JSON → MD; idempotency.
|
||||
+ assembly, the seven success criteria.
|
||||
- Existing integration tests keep working (the only public
|
||||
entry points they hit are `Manifest.resolve` and
|
||||
`Manifest.from_json_obj`).
|
||||
@@ -248,7 +219,9 @@ Each test runs against a temporary `$HOME` and a temporary `$CWD`:
|
||||
### Out of scope
|
||||
|
||||
- Watching the directory for changes mid-session.
|
||||
- A migration tool for moving back (MD → JSON).
|
||||
- An automated migration command. Existing JSON users
|
||||
hand-rewrite into the new layout. The README rewrite
|
||||
documents the new shape; that's the migration surface.
|
||||
- Validating that frontmatter `name:` matches the filename.
|
||||
Soft check via a warn log if mismatched, but not enforced.
|
||||
- A bottle/agent dependency graph beyond the existing `bottle:`
|
||||
@@ -378,9 +351,6 @@ def parse_frontmatter(text: str) -> tuple[dict[str, object], str]:
|
||||
a programmatic entry point (used by tests). New
|
||||
`Manifest.from_md_dirs(home_dir, cwd_dir)` for the loader.
|
||||
- **`claude_bottle/yaml_subset.py`** — new. The parser.
|
||||
- **`claude_bottle/cli/migrate_manifest.py`** — new. The
|
||||
migration command.
|
||||
- **`claude_bottle/cli/__init__.py`** — wire the new subcommand.
|
||||
- **`README.md`** — manifest section rewritten against the new
|
||||
layout.
|
||||
- **`claude-bottle.example.json`** — removed; replaced by an
|
||||
@@ -396,14 +366,15 @@ etc. all stay the same shape. Only the loader changes.
|
||||
|
||||
### Backward compatibility
|
||||
|
||||
This is a breaking change for v1 users. Mitigations:
|
||||
This is a breaking change for v1 users. claude-bottle has a
|
||||
single primary user today, so migration is one person rewriting
|
||||
one file — no automated migration command is in scope.
|
||||
|
||||
- `./cli.py migrate-manifest` does the heavy lifting in one
|
||||
command.
|
||||
- If `claude-bottle.json` exists in `$HOME` or `$CWD` *and* the
|
||||
new directories don't exist, the resolver dies with a clear
|
||||
pointer at the migration command — not silently merging
|
||||
formats, not silently dropping the JSON content.
|
||||
If `claude-bottle.json` exists in `$HOME` or `$CWD` *and* the
|
||||
new `.claude-bottle/` directory does not exist, the resolver
|
||||
dies with a clear pointer at the README's manifest section —
|
||||
not silently merging formats, not silently dropping the JSON
|
||||
content.
|
||||
|
||||
## Open questions
|
||||
|
||||
@@ -427,11 +398,6 @@ This is a breaking change for v1 users. Mitigations:
|
||||
pattern will be "every bottle allows api.anthropic.com and
|
||||
github.com"; do we want a way to share the list? Default no
|
||||
for v1; revisit if it bites.
|
||||
- **Migration tool destructive vs additive.** Default
|
||||
additive (writes new files, leaves old JSON in place). If
|
||||
users find the half-migrated state confusing, switch to
|
||||
printing a "delete claude-bottle.json now" reminder at the
|
||||
end of the migration.
|
||||
|
||||
## References
|
||||
|
||||
|
||||
Reference in New Issue
Block a user