lifeloop/host_assets.rs
1//! Host integration asset rendering and merge behavior.
2//!
3//! Lifeloop owns the file shape, merge safety, and status reporting for
4//! lifecycle integration assets installed into harness host directories
5//! (`.claude/`, `.codex/`, `.hermes/`, `.openclaw/`). The `host apply`
6//! and `host inspect` compatibility commands route here.
7//!
8//! # Boundary (issue #4)
9//!
10//! This module owns:
11//! * rendering source/applied asset content as in-memory data,
12//! * additive-merge logic that preserves user-owned entries,
13//! * asset status reporting (`Present`/`Missing`/`Drifted`/`InvalidMode`/
14//! `NotApplicable`),
15//! * supported-mode rules for each adapter.
16//!
17//! This module does **not** own:
18//! * the hook protocol command strings themselves (those are issue #3 —
19//! the strings appear here only as opaque compatibility labels that the
20//! merge logic must recognize so it can scrub stale entries);
21//! * the full adapter manifest registry (issue #6);
22//! * lifecycle routing (issue #7);
23//! * telemetry parsing (issue #5);
24//! * filesystem IO. Callers handle reads, writes, mode bits, and atomic
25//! replace. This module is pure: it operates on `serde_json::Value`,
26//! strings, and byte slices.
27//!
28//! # CCD compatibility
29//!
30//! The command-prefix constants and legacy recognizer patterns
31//! (`CCD_COMPAT_*`) are CCD compatibility labels — Lifeloop's first
32//! client wires its own binary into harness hooks via these prefixes.
33//! They are *not* core Lifeloop semantics: a future non-CCD client
34//! gets its own profile in the same shape. Keeping them in one place
35//! makes the compat surface auditable.
36//!
37//! # Lifecycle integration profiles (issue #26)
38//!
39//! [`LifecycleProfile`] generalizes the CCD-shaped command-prefix /
40//! managed-event surface into a per-client-profile struct. The free
41//! functions exported from this module keep their CCD-compat default
42//! behavior (they delegate to [`CCD_COMPAT_PROFILE`]); paired
43//! `*_with_profile` variants accept any profile so a non-CCD client
44//! (e.g. [`LIFELOOP_DIRECT_PROFILE`], the post-slimdown shape where
45//! the harness invokes the `lifeloop` CLI directly without CCD as
46//! broker) can render and merge its own lifecycle hook assets without
47//! editing core merge logic. This is the bridge contemplated by
48//! `docs/release-gates.md` for the CCD slimdown
49//! (dusk-network/ccd#723) — the slimdown lands by switching active
50//! installs from `CCD_COMPAT_PROFILE` to a non-CCD profile, not by
51//! rewriting the renderer.
52
53mod merge;
54mod model;
55mod profiles;
56mod render;
57mod status;
58
59pub use merge::{
60 codex_hooks_contain_managed_lifecycle, codex_hooks_contain_managed_lifecycle_with_profile,
61 codex_hooks_feature_is_enabled, merge_claude_settings, merge_claude_settings_text,
62 merge_claude_settings_text_with_profile, merge_claude_settings_with_profile,
63 merge_codex_config_text, merge_codex_hooks, merge_codex_hooks_text,
64 merge_codex_hooks_text_with_profile, merge_codex_hooks_with_profile,
65};
66pub use model::*;
67pub use profiles::*;
68pub use render::{
69 render_applied_assets, render_applied_assets_with_profile, render_required_source_assets,
70 render_source_assets, render_source_assets_with_profile,
71};
72pub use status::{
73 aggregate_status, asset_status, byte_equal_asset_status, claude_settings_status,
74 claude_settings_status_with_profile, codex_config_status, codex_hooks_status,
75 codex_hooks_status_with_profile,
76};