mirror of
https://github.com/storytold/craft-anything.git
synced 2026-11-05 20:47:45 +01:00
f64ae3bf3c
A native, pure-Rust app that shows anyone how a piece of software works, with evidence-backed answers, then helps them rebuild it. It ships a desktop app, a CLI and an MCP server, all driven by one engine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
50 lines
4.4 KiB
Markdown
50 lines
4.4 KiB
Markdown
# File formats
|
|
|
|
Every file Craft Anything saves carries a version number. Reading a file runs the same three steps:
|
|
parse it into a raw document (a JSON value or a TOML table), run the migration steps from the file's
|
|
version up to the current one, then turn the document into Rust types. The step runner is
|
|
`crates/engine/src/versioned.rs`.
|
|
|
|
| File | Owner | Current version | Older files | Newer files |
|
|
|---|---|---|---|---|
|
|
| `<project>/craft.json` | `engine::workspace` (`Manifest`) | `MANIFEST_VERSION` = 1 (`version`; missing = 0) | brought forward, saved as current | opened read-only: saving is refused |
|
|
| `config.toml` (`settings::config_dir()`) | `engine::settings` (`Settings`) | `SETTINGS_VERSION` = 2 (`version`; missing = 0; 2 moved `[engines.ghidra] enabled` to `deep_mode`) | brought forward | loaded, never saved over |
|
|
| `<name>.cany/project.toml` | `engine::project` (`ProjectMeta`) | `FORMAT_VERSION` = 1 (`format_version`, required) | brought forward | refused, with "update Craft Anything" |
|
|
| `<project>/transcript.json` | `ai::context` (the API builder's conversation) | `TRANSCRIPT_VERSION` = 1 (`{version, history}`) | read as before | not resumed; a fresh build replaces it |
|
|
| `<project>/app/mechanics.json` | `engine::mechanics` (written by the builder, read by `MechanicsCheck`) | `MECHANICS_VERSION` = 1 (`version`; missing = 1) | — | the check fails and says so |
|
|
| `<project>/checks/round-N/self-test.json` | `engine::self_test` (written by the built game's `--self-test`, read by `SelfTestCheck`) | 1 (`version`; missing = 1) | — | the check fails and says so |
|
|
| `<project>/usage.json` | `engine::workspace` (`ProjectUsage`; written only by the rebuild run) | `USAGE_VERSION` = 1 (`version`; missing = 0) | read as before, saved as current | read as far as its fields are known, never written over |
|
|
| `<project>/questions.json` | `engine::questions` (`AskedQuestion`, written by `rebuild_question_ask`) | `QUESTIONS_VERSION` = 1 (`{version, items}`) | read as before | read as far as its fields are known |
|
|
| `<project>/pinned/<n>/pin.json` | `engine::pins` (`Pin`) | `PIN_VERSION` = 1 (`version`; missing = 1) | brought forward | read as far as its fields are known |
|
|
| `<folder>/standin.json` | `engine::tools::standin_tools` (`analysis::standin::StandIn`; written only by `web_standin_build`) | `STANDIN_VERSION` = 1 (`version`, required) | brought forward | refused, with "update Craft Anything", and never written over |
|
|
| `<project>/feed.json` | `ai::rebuild::feed` (written by the run) | `FEED_VERSION` = 1 (`{version, items}`; a bare list = 0) | read as before, saved as current | never written over; the conversation is rebuilt from the project for display |
|
|
|
|
Other JSON in a project (`assets.json`, `inbox/`, `checks/`, evidence records) has no version yet;
|
|
add one the first time its shape changes.
|
|
|
|
## Newer files
|
|
|
|
A file from a newer Craft Anything is never downgraded or overwritten, because the fields we don't
|
|
know would be lost. `craft.json` and `config.toml` are still read as far as their fields are known,
|
|
so the person can see their project or keep their settings; every save returns a `ToolError` that
|
|
says to update Craft Anything. A newer `craft.json` whose fields can't be read at all is refused the
|
|
same way, and a newer `config.toml` that can't be read gives defaults without touching the file.
|
|
A newer `.cany` is refused outright: its evidence layout may have changed in ways we can't
|
|
see.
|
|
|
|
A file that can't be parsed is not "newer": `config.toml` is set aside as `config.toml.broken` and
|
|
defaults are used; an unreadable `craft.json` gives a plain-English error when opened and is left
|
|
out of the project list.
|
|
|
|
## Adding a migration step
|
|
|
|
1. Bump the version constant (`MANIFEST_VERSION`, `SETTINGS_VERSION` or `FORMAT_VERSION`).
|
|
2. Append one function to the matching steps list (`MANIFEST_STEPS`, `SETTINGS_STEPS`,
|
|
`FORMAT_STEPS`). It takes the raw document from version n to n + 1: rename, move or fill keys.
|
|
Return `Err` with a plain-English reason when it can't. A compile-time assertion fails if the
|
|
list and the constant disagree.
|
|
3. Add a test that reads a literal sample of the old file (keep the existing samples; old files
|
|
must keep loading forever).
|
|
4. For `craft.json`, `mechanics.json` and `self-test.json`, run `cargo xtask schemas` and commit `docs/schemas/`.
|
|
`cargo xtask schemas --check` (and an engine test) fail when the published schema is stale.
|