Add source-first CLI with guarded writes and reviewed evidence

This commit is contained in:
2026-09-11 05:27:16 -07:00
committed by Codex
parent a34558d3be
commit bc311bc076
15 changed files with 2179 additions and 2 deletions
+67
View File
@@ -0,0 +1,67 @@
# Source-only CLI baseline — 2026-09-11
Codex-9e8r6t /root/palette_finish. Root authorized only new `crates/oa-cli`, its focused integration tests and this report. Root owns workspace membership, lockfile and public documentation. No grammar/schema/core/desktop change is part of this slice. The external source-language experiment remains a separate unratified design.
Read AGENTS, current issue1 through #143, existing local usability audit, external `release-textual-authoring-design-20260911.md`, and core source/session/file APIs. The independent reviewer supplied the loader's stabilized-warning/provisional-ID trap and verified journal/migration/no-op boundaries. Their review is `release-source-cli-review-20260911.md`.
## Proposed command contract implemented for validation
```
arcadia check ROOT [--json]
arcadia lint ROOT [--json]
arcadia stabilize ROOT [--write] [--json]
arcadia rename-alias ROOT OLD NEW [--write] [--json]
```
ROOT is the explicit entry file. No project discovery, editor, server or network is required. Check and lint are equivalent admission plus engineering-diagnostic commands. A valid model with warnings returns success. Mutation commands preview by default; `--write` explicitly saves the candidate captured and displayed/reported by that same invocation. Missing IDs in an earlier separate preview are provisional: another invocation may allocate different IDs until saved. There is no persisted apply-plan protocol in this baseline.
Exit0 means valid/success (warnings permitted),1 means invalid source or rejected semantic alias command,2 means usage,3 means disk/path/conflict/pending journal or output failure. Pending-save diagnosis is obtained from the production loader's `pending_save` code, not a copied journal-name calculation. Invalid raw source is never migrated, stabilized or renamed.
Human output places located diagnostics/status/notes on stderr and per-file unified diffs on stdout. With `--write`, the human candidate is flushed before the saver is invoked. JSON output is a single versioned envelope containing diagnostics, status, exit code, write result, exact changed before/after text, unified diffs, missing-identity count and a separate structured source-migration report. JSON after a failed save retains the proposed diff with `written:false`; a failed save can require explicit recovery and is not a blanket rollback guarantee. Diagnostic locations are half-open UTF-8 offsets into the named coordinate space; input line/column are one-based Unicode scalar coordinates. Related locations carry exact byte spans. Command/disk errors without a responsible source token explicitly have no source location.
The raw `lint_bundle` diagnostics are authoritative for source positions. Loader-only discovery/IO/path/pending errors are retained; successful-loader warnings from stabilized compilation are discarded. Unpersisted lint object IDs are omitted so they cannot be mistaken for the later candidate's freshly allocated IDs. Explicit authored object IDs remain available. Post-compilation/update errors identify their candidate coordinate space rather than claiming to point into original bytes.
## API and safety boundary
`load_project` captures original byte expectations and discoverable source, then `lint_bundle` validates raw reachable text. On success, `compile_bundle` stabilizes identities and performs supported core migrations. Alias rename resolves the existing global alias and uses `prepare_command(SetAlias)` plus `update_bundle_with_identity_map`; it does not replace text blindly. The initial migration report is retained before the updater recompiles current source. The complete raw-to-final diff shows identity insertion, supported source migration and rename together while their summary fields remain distinct. There is no canonical formatter fallback or new file writer.
`Prepared` privately owns the original DiskProject and final CompiledSourceProject. Its consuming `write` invokes `source_files::save_project`, including for an empty diff. The saver rechecks pending journal and every captured dependency before its existing no-op return, preserving conflict and journal guarantees. No CLI path calls `recover_project`. The inherited contract is recoverability with entry committed last; it is not cross-process compare-and-swap, simultaneous multi-file visibility, or a Windows power-loss durability claim. Detached files are never deleted by this wrapper. No directories/files are created by a preview.
Admission limits match desktop policy:256 files, include depth32/edges1024,64MiB aggregate UTF-8,100000 graph objects,250000 records and500000 ordered references. These are exposed in help; no performance acceptance is inferred. The per-file diff uses a linear common-prefix/suffix algorithm with one hunk and three context lines, avoiding quadratic LCS memory on large files. Far-apart changes can produce a large hunk; JSON also preserves exact full changed-file texts and newline bytes.
Dependencies are existing `oa-core`, workspace `serde` and `serde_json`; no new registry package. Root added workspace membership, then granted the serialized Cargo window. Cargo.lock gained only the local `oa-cli`0.2.0 package and those three existing dependencies. Source formatting was limited to this crate.
## Focused acceptance and executed validation
Twelve integration tests cover the complete externally authored 40-identity alarm model; preview nonmutation and one-time exact ID-only stabilization; a same-invocation captured write; CRLF/comments/omitted defaults and no-op mtime/inventory; three-file semantic alias rename with independent complete-model alias-only expectation; invalid Unicode raw diagnostics and no writes; raw missing-ID warning locality/provisional-ID suppression; external change before write and before a no-op write; pending journal at load and after preview with untouched sentinel; rejected and same-alias rename; supported source5 migration separately reported through rename; and explicit root/machine-readable usage errors. Additional cases cover invalid UTF-8, unavailable includes, unsupported/invalid old source, non-element alias rename, a changed dependency absent from the proposed diff, and exact retention of a detached invalid file. Some tests contain several linked assertions, but this is twelve test functions, not an invented larger native acceptance count.
The complete example fixture is the frozen external authoring experiment, not a new CLI-generated model. No new syntax or broad text-usability acceptance is ratified. Large-model timing, persistent review-plan application, reparent/navigation/LSP, migration to a future grammar and publication packaging remain outside this baseline.
The Windows GNU/LLVM toolchain selected by `.local/toolchain/env.ps1`, existing target and `CARGO_BUILD_JOBS=1` ran these gates:
| Gate | Result |
| --- | --- |
| `cargo test --offline -p oa-cli --all-targets -- --test-threads=1` | Initial compilation succeeded;11/12 tests passed, exit101,58.621s total. The remaining fixture used unsupported `/* block comment */` syntax. |
| `cargo test --locked --offline -p oa-cli --all-targets -- --test-threads=1` | After changing only that fixture to a supported line comment: **12/12 passed**, exit0,13.783s total /1.88s test execution. |
| `cargo clippy --locked --offline -p oa-cli --all-targets -- -D warnings` | Passed,136.447s initially (including core compilation). Independent review then corrected a note that incorrectly described changed-file output as a complete project candidate. Final strict pass:10.245s. |
| `cargo build --locked --offline -p oa-cli --bin arcadia` | Final wording-matched executable built successfully,9.734s. |
| `rustfmt --check --edition 2024` on the three crate Rust files | Passed. |
| Staged executable `--help` / `--version` | Successful; version `arcadia 0.2.0`. |
No production behavior was changed to accommodate the invalid block-comment fixture. The failed initial log remains preserved. The final note explicitly promises complete proposed **changed-file** text/diffs and disclaims a saved plan or digest of unchanged dependencies. Source-file expectations still capture every dependency, including those absent from the diff. No whole-project hash/apply protocol was added. The final wording-only change was compiled and strictly linted; the twelve semantic integration cases precede that wording change.
Immutable staging directory: `.local/source-cli-20260911/verified/`. Its `arcadia.exe` is **20312064 bytes**, SHA256 **`BAD169F8BE78DCFA74B32714569C886DD2132727080684FC2BA618D5822E3559`**. Sibling `libunwind.dll` is190976 bytes, SHA256 `F45604A12E8BCD839FD86F667C1BE1CC7C4F9DA2B3C69FF381AC708F0E1AE7D4`. `manifest.json` records source/workspace/lock/runtime/log identities; SHA256 `DD73FC2BB2190B23FFFE16D6C63D4ACDDF52338062FAC298379DDFD241D82EB8`. The matching test artifact is `.local/target-gnullvm/debug/deps/source_cli-343cec8034acf06e.exe`, SHA256 `F740CA81D0C60DEC4AA6A2BC36D3F7035844590FAB59E88F63A7F4ABE3F78AEF`.
Logs and separate exact command/exit/time JSON records remain under `.local/source-cli-20260911/`:
| Log | SHA256 |
| --- | --- |
| `tests-initial.log` | `00378D96D09A95265B09C9C7C12CB09A610E46055AC36FFD9ACEF3265965D56C` |
| `tests-final.log` | `A18B708B89FE715951201D9046C414080E0820BDC9C6DC9EDE9CF3AB84E37C04` |
| `clippy-initial.log` | `A3B5A7F051CF51B812BF5D4D0917E5CEFBD25CCCAD4033BAABD7EB36FCCFA72A` |
| `clippy-final.log` | `29C23E6372447D06EF68A5B161F323F80109024CEE3BB7AEC85F421530BD1564` |
| `build.log` | `B0968196245C5302F2576C087551E3F92071F85314E60512117BC632EED20742` |
Cargo lease was explicitly released to root/desktop owner after all gates terminated. Files remain uncommitted for root integration. The independent reviewer has the immutable executable for isolated no-compile falsifiers; that review is recorded separately and is not silently included in these author-run counts. No Linux CLI execution, native GUI or broad text-authoring release acceptance is claimed.
Independent review subsequently completed on the frozen BAD169F8 executable: **183 assertions across21 process invocations passed**, with no remaining implementation blocker. It covered all seven persistent identity families, exact header/live-reference changes with comment/quoted-alias retention and40 original UUIDs, saved/no-op source/mtime, raw CRLF/Unicode second-declaration warning offsets, explicit/provisional warning IDs and invalid non-BMP reference scalar columns. This is reviewer-owned evidence, not an addition to the author's12 tests: `harness/release-source-cli-review-20260911.md`, SHA256 `475645DB76CD193F2FC1CC1BDDAB57CCB0A724A62779A60C1E2AF0F756929344`; result `harness/experiments/source-cli-independent-20260911/result.json`, SHA256 `7F772FAB0E58C9901D9B87D7553C605C84E5DD2B234123C14EFD5B1BAF46DA9C`. The review discloses its corrected initial harness naming clash. Gitea issue1 comment176 records the handoff.