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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//! The [`Operations`] trait — the shared internal operation layer an
//! Arcature application implements for binary-subcommand dispatch
//! (AP2.1-10).
//!
//! The application implements [`Operations`] once; [`super::dispatch`] reads
//! the subcommand from argv and calls the corresponding method. This is the
//! "one internal operation layer" the six subcommands share: instead of six
//! separate binaries or six hand-written `main` branches, the app has one
//! trait impl and one `main` that calls `arcature::cli::run(operations)`.
//!
//! # Design
//!
//! Each method is `async` and returns [`crate::Result`] (the engine's typed
//! result). The dispatch drives them on the certified Tokio runtime
//! (`macros` feature). An operation that needs no subsystem (e.g. `about`)
//! returns `Ok(())` after printing; one that serves (`serve`) runs until a
//! termination signal. The application owns the bodies — the engine does not
//! invent business behavior (AGENTS.md §7, ADR-0006 §7: "Auto-discover
//! wiring, never invent business behavior").
//!
//! `about` is the one operation the engine can help with: it prints the
//! framework version. The app's `about` includes its own name and version
//! alongside [`crate::FRAMEWORK_VERSION`]; the engine re-exports that
//! constant so the app does not hardcode the Arcature version.
/// The shared internal operation layer an Arcature application implements.
///
/// One impl per application; [`super::dispatch`] calls the method matching
/// the parsed subcommand. Each method receives the trailing argv (the
/// arguments after the subcommand selector) so an operation like `migrate`
/// can forward `up`/`down`/`--steps N` to the app's migrator.
///
/// The trait is `Send + Sync + 'static` so the dispatch can own it across
/// the async runtime; `async-trait` is not used (the engine avoids the
/// `async-trait` supply-chain surface on the hot path) — the methods return
/// `Pin<Box<dyn Future>>` directly, which is the same desugaring without the
/// macro.