feat(orchestrator): modèle de désignation d'orchestrateur + sink de diagnostic
Introduit le modèle AgentManifest { version, entries, orchestrator } et la
garde d'écriture directe may_write_directly(..., &OrchestratorDesignation) :
seul l'orchestrateur désigné peut écrire directement, les autres passent par
le rendez-vous médié. Câble la désignation à travers domain → application →
infrastructure → app-tauri (context_guard, service, lifecycle, ports).
Ajoute crates/application/src/diag.rs : sink de diagnostic best-effort, sans
dépendance, qui miroite les traces du rendez-vous inter-agents de
l'orchestrateur vers un fichier de log persistant (utile au lancement via
AppImage où stderr est jeté), avec la même discipline « zéro dépendance,
ne casse jamais le rendez-vous ».
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -292,8 +292,14 @@ mod tests {
|
||||
|
||||
let deny = str_array(&json["permissions"]["deny"]);
|
||||
// A Write capability fans out to both Edit(..) and Write(..) entries.
|
||||
assert!(deny.contains(&"Edit(.ideai/**)".to_owned()), "deny={deny:?}");
|
||||
assert!(deny.contains(&"Write(.ideai/**)".to_owned()), "deny={deny:?}");
|
||||
assert!(
|
||||
deny.contains(&"Edit(.ideai/**)".to_owned()),
|
||||
"deny={deny:?}"
|
||||
);
|
||||
assert!(
|
||||
deny.contains(&"Write(.ideai/**)".to_owned()),
|
||||
"deny={deny:?}"
|
||||
);
|
||||
|
||||
let allow = str_array(&json["permissions"]["allow"]);
|
||||
assert!(
|
||||
@ -330,7 +336,10 @@ mod tests {
|
||||
"Bash(shutdown*)",
|
||||
"Bash(reboot*)",
|
||||
] {
|
||||
assert!(deny.contains(&guard.to_owned()), "missing guardrail {guard}; deny={deny:?}");
|
||||
assert!(
|
||||
deny.contains(&guard.to_owned()),
|
||||
"missing guardrail {guard}; deny={deny:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,9 +2,11 @@
|
||||
//!
|
||||
//! Produces the **permission-relevant** part of Codex's `config.toml`
|
||||
//! (`sandbox_mode` / `approval_policy`) plus the matching launch args
|
||||
//! (`--sandbox` / `--ask-for-approval`). The posture→mode derivation is extracted
|
||||
//! verbatim from the former `codex_sandbox_mode` / `codex_approval_policy` /
|
||||
//! `apply_codex_cli_permission_args` in `lifecycle.rs`.
|
||||
//! (`--sandbox` / `--ask-for-approval`) and, for workspace-write postures, the
|
||||
//! project root as an additional writable directory (`--add-dir`). The
|
||||
//! posture→mode derivation is extracted verbatim from the former
|
||||
//! `codex_sandbox_mode` / `codex_approval_policy` / `apply_codex_cli_permission_args`
|
||||
//! in `lifecycle.rs`.
|
||||
//!
|
||||
//! Unlike Claude's seed, Codex's `config.toml` is **co-owned** (it also carries the
|
||||
//! `mcp_servers.idea` table and the `projects.*` trust entries, which are MCP/trust
|
||||
@ -44,7 +46,7 @@ impl PermissionProjector for CodexPermissionProjector {
|
||||
fn project(
|
||||
&self,
|
||||
eff: Option<&EffectivePermissions>,
|
||||
_ctx: &ProjectionContext,
|
||||
ctx: &ProjectionContext,
|
||||
) -> PermissionProjection {
|
||||
// Product invariant: nothing posed ⇒ nothing projected. Codex keeps its
|
||||
// native sandbox/approval defaults (no args, no managed keys written).
|
||||
@ -63,6 +65,17 @@ impl PermissionProjector for CodexPermissionProjector {
|
||||
toml_string(approval),
|
||||
);
|
||||
|
||||
let mut args = vec![
|
||||
"--sandbox".to_owned(),
|
||||
sandbox.to_owned(),
|
||||
"--ask-for-approval".to_owned(),
|
||||
approval.to_owned(),
|
||||
];
|
||||
if sandbox == "workspace-write" && !ctx.project_root.is_empty() {
|
||||
args.push("--add-dir".to_owned());
|
||||
args.push(ctx.project_root.to_owned());
|
||||
}
|
||||
|
||||
PermissionProjection {
|
||||
files: vec![ProjectedFile::MergeToml {
|
||||
rel_path: CONFIG_REL_PATH.to_owned(),
|
||||
@ -70,12 +83,7 @@ impl PermissionProjector for CodexPermissionProjector {
|
||||
managed_keys: MANAGED_KEYS.iter().map(|k| (*k).to_owned()).collect(),
|
||||
contents,
|
||||
}],
|
||||
args: vec![
|
||||
"--sandbox".to_owned(),
|
||||
sandbox.to_owned(),
|
||||
"--ask-for-approval".to_owned(),
|
||||
approval.to_owned(),
|
||||
],
|
||||
args,
|
||||
env: Vec::new(),
|
||||
}
|
||||
}
|
||||
@ -135,7 +143,7 @@ mod tests {
|
||||
}
|
||||
|
||||
// ---- (6) posture → sandbox_mode / approval_policy + (7) args↔contents
|
||||
// coherence + MergeToml shape -------------------------------
|
||||
// coherence + add-dir + MergeToml shape ---------------------
|
||||
|
||||
#[test]
|
||||
fn posture_maps_sandbox_and_approval_in_file_and_args() {
|
||||
@ -176,7 +184,7 @@ mod tests {
|
||||
|
||||
// -- (7) Args reflect the SAME values as the TOML, in CLI order.
|
||||
assert_eq!(
|
||||
proj.args,
|
||||
&proj.args[..4],
|
||||
vec![
|
||||
"--sandbox".to_owned(),
|
||||
sandbox.to_owned(),
|
||||
@ -185,6 +193,21 @@ mod tests {
|
||||
],
|
||||
"posture {posture:?}: args must mirror the TOML values"
|
||||
);
|
||||
if sandbox == "workspace-write" {
|
||||
assert!(
|
||||
proj.args
|
||||
.windows(2)
|
||||
.any(|w| w == ["--add-dir".to_owned(), "/proj".to_owned()]),
|
||||
"workspace-write posture must add the project root as writable: {:?}",
|
||||
proj.args
|
||||
);
|
||||
} else {
|
||||
assert!(
|
||||
!proj.args.contains(&"--add-dir".to_owned()),
|
||||
"read-only posture must not add writable dirs: {:?}",
|
||||
proj.args
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user