feat(TASK-039): wire hooks into bundle installs and reconcile builtin hook dirs
Bundles: RemoteLayout.hooks + scan/is_empty/plan routing into hooks_dir, a functional --filter hooks arm replacing the inert interim arm, TopCategory::Hooks provenance rows, and per-file 'bundle defines hook script' summary lines (visibility only, no approval prompt). Reconciliation: new builtin_manifest module — a hidden per-directory .builtin-manifest records the files the builtin installer actually owns (written this run, previously owned, or pending failed deletions); deletion is strictly manifest-minus-embed so user-created files in the same directory are never touched. Wired into install_builtin_agents for agents/<name>/hooks/ and a greenfield minimal Role::install_builtin_role_hooks for roles/hooks/. Hardening: bundles are barred from shipping any path component that aliases .builtin-manifest (Unicode case fold + trailing dot/space, directories included); manifest entries reuse the bundle store's is_safe_component rules; malformed manifests fail safe toward keeping files; role-side reconcile failures degrade to a warning like the agent side.
This commit is contained in:
7 files changed
+893
-8
No files matched your search
@@ -965,6 +965,12 @@ network:
|
||||
let hook_mixin = roles.join("hooks").join("notify.sbx-mixin.yaml");
|
||||
fs::write(&role_mixin, "kind: mixin\n").unwrap();
|
||||
fs::write(&hook_mixin, "kind: mixin\n").unwrap();
|
||||
// The builtin installer's hidden manifest lives in the same dir but
|
||||
// is not a mixin and must never be picked up by the flat scan.
|
||||
let manifest = roles
|
||||
.join("hooks")
|
||||
.join(crate::config::builtin_manifest::BUILTIN_MANIFEST_FILE);
|
||||
fs::write(&manifest, "notify.sh\n").unwrap();
|
||||
|
||||
let config_env = get_env_name("config_dir");
|
||||
let roles_env = get_env_name("roles_dir");
|
||||
@@ -998,6 +1004,10 @@ network:
|
||||
found.contains(&hook_mixin),
|
||||
"missing role hook mixin: {found:?}"
|
||||
);
|
||||
assert!(
|
||||
!found.contains(&manifest),
|
||||
"builtin manifest must not be scanned as a mixin: {found:?}"
|
||||
);
|
||||
|
||||
let _ = fs::remove_dir_all(&root);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user