chore: rename packages/ to crates/

Move all 29 workspace members from packages/<name>/ to crates/<name>/.
Updates: workspace Cargo.toml (members + path deps), justfile, root
CLAUDE.md, scripts/build/CARGO_INSTALL.md, docs/architecture/crates.md
(renamed from packages.md), structural references in docs/architecture
and docs/configuration, per-crate CLAUDE.md self-references. Historical
plans, reports, and building/ docs are left untouched.

No behavior change; just check-all stays green and fermata tests pass.
This commit is contained in:
2026-04-30 21:58:57 +02:00
commit 97001e1544
26 changed files with 1678 additions and 0 deletions
+112
View File
@@ -0,0 +1,112 @@
//! Smoke-test contract from `docs/workpad/brainstorm/fermata.md` Appendix A.4.
use dirigent_fermata::core::{Decision, Op, Policy};
use std::fs;
use tempfile::TempDir;
fn fixture() -> TempDir {
let tmp = TempDir::new().unwrap();
let root = tmp.path();
fs::write(root.join(".botignore"), ".env\n.env.*\nconf/cert/**\nconf/mitmproxy/**\n").unwrap();
fs::write(
root.join("botignore.toml"),
r#"
[read]
patterns = [
"conf/localtestsettings.yaml",
"conf/localsettings.yaml",
"conf/default-secrets.yaml",
".claude/self-reflections/**",
]
[write]
patterns = [
"conf/localtestsettings.yaml",
"conf/localsettings.yaml",
"conf/default-secrets.yaml",
]
[bash]
deny = ["localtestsettings.yaml", "localsettings.yaml", "default-secrets.yaml", ".env"]
ask = ["rm *", "mv *"]
allow_prefixes = ["make test"]
"#,
)
.unwrap();
fs::create_dir_all(root.join("conf")).unwrap();
fs::create_dir_all(root.join("datatap")).unwrap();
fs::create_dir_all(root.join(".claude/self-reflections")).unwrap();
for f in [".env", "conf/localsettings.yaml", "datatap/foo.py", ".claude/self-reflections/x.md"] {
fs::write(root.join(f), "").unwrap();
}
tmp
}
#[test]
fn read_dot_env_denied() {
let t = fixture();
let p = Policy::load(t.path()).unwrap();
assert!(matches!(p.check(Op::Read, &t.path().join(".env")).unwrap(), Decision::Deny(_)));
}
#[test]
fn bash_cat_dot_env_denied() {
let t = fixture();
let p = Policy::load(t.path()).unwrap();
assert!(matches!(p.check_command("cat ./.env").unwrap(), Decision::Deny(_)));
}
#[test]
fn bash_rm_localsettings_denied() {
let t = fixture();
let p = Policy::load(t.path()).unwrap();
assert!(matches!(
p.check_command("rm ./conf/localsettings.yaml").unwrap(),
Decision::Deny(_)
));
}
#[test]
fn write_localsettings_denied() {
let t = fixture();
let p = Policy::load(t.path()).unwrap();
assert!(matches!(
p.check(Op::Write, &t.path().join("conf/localsettings.yaml")).unwrap(),
Decision::Deny(_)
));
}
#[test]
fn edit_datatap_foo_py_allowed() {
let t = fixture();
let p = Policy::load(t.path()).unwrap();
assert_eq!(
p.check(Op::Write, &t.path().join("datatap/foo.py")).unwrap(),
Decision::Allow
);
}
#[test]
fn bash_make_test_allowed() {
let t = fixture();
let p = Policy::load(t.path()).unwrap();
assert_eq!(p.check_command("make test").unwrap(), Decision::Allow);
}
#[test]
fn bash_rm_somefile_asks() {
let t = fixture();
let p = Policy::load(t.path()).unwrap();
assert!(matches!(p.check_command("rm somefile").unwrap(), Decision::Ask(_)));
}
#[test]
fn read_self_reflections_asks() {
// Note: A.4 has self-reflections under "ask" — current toml schema uses `[read].patterns`
// for hard reads. This documents the gap; once toml has a `[read].ask`, switch to Ask.
let t = fixture();
let p = Policy::load(t.path()).unwrap();
let d = p.check(Op::Read, &t.path().join(".claude/self-reflections/x.md")).unwrap();
assert!(matches!(d, Decision::Deny(_)));
}