1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//! Shell out to the app's `arcature-metadata` binary and deserialize the
//! canonical UAG JSON.
//!
//! Mirrors the `contracts::execute` pattern: run
//! `cargo run --quiet --package <backend_package> --bin arcature-metadata`,
//! capture stdout, deserialize as the canonical [`Uag`]. This is
//! side-effect-free from the CLI's perspective — the app binary itself must
//! not boot infrastructure (PROGRAM.md §"Side-effect-free inspection"). The
//! deserialization target is the single schema type `arcature-build` owns,
//! so the CLI reads the full UAG (modules, routes, services, pages, and the
//! typed action/query/query-string field shapes) instead of a
//! hand-maintained subset that silently dropped fields (ADR-0006 §2).
//!
//! The freshness mechanism is unchanged: the CLI always regenerates the
//! manifest by running the live app's `arcature-metadata` binary, so it
//! reflects the application as currently compiled (never a stale cached
//! artifact). Only the deserialization target type changed.
use crate;
use crateProjectConfig;
use Uag;
/// Load the canonical UAG by shelling out to the app's `arcature-metadata`
/// binary. The binary emits the full UAG JSON — modules, routes, services,
/// pages, and the typed action/query/query-string field shapes — never booted
/// infrastructure. Deserializing into [`Uag`] (the single schema type
/// `arcature-build` owns) means the CLI surfaces the full graph and can never
/// silently drop fields the way a hand-maintained mirror could.
///
/// The error is a typed [`String`] only because it flows into the existing
/// [`crate::error::CommandError::Metadata`] variant; serde's deserialization
/// error already carries line/column context, which the formatted message
/// preserves verbatim.
pub