{"record":{"id":"fa4cc8aae7238dfd","repo":"Hmbown/CodeWhale","slug":"audited-skill-root-identity-changed-refusing-muta","errorCode":null,"errorMessage":"audited skill root identity changed; refusing mutation","messagePattern":"audited skill root identity changed; refusing mutation","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/skills/mutation.rs","lineNumber":333,"sourceCode":"    let canonical_child = fs::canonicalize(child)\n        .with_context(|| format!(\"failed to resolve owned skill path {}\", child.display()))?;\n    if canonical_child.parent() != Some(canonical_root.as_path()) {\n        bail!(\n            \"owned skill path {} escapes direct root {}\",\n            child.display(),\n            skills_dir.display()\n        );\n    }\n    Ok(true)\n}\n\nfn validate_owned_skill_path(\n    ctx: &MutationContext<'_>,\n    skill: &AuditedSkill,\n    path: &Path,\n) -> Result<PathBuf> {\n    if skill.id.root_id != skill.root.id {\n        bail!(\"audited skill root identity changed; refusing mutation\");\n    }\n    let skills_dir = validate_owned_root_descriptor(ctx, &skill.root)?;\n    let package_name = on_disk_package_name(&skill.id)?;\n    let expected = skills_dir.join(package_name);\n    if path != expected {\n        bail!(\n            \"audited skill path {} does not match owned package {}\",\n            path.display(),\n            expected.display()\n        );\n    }\n    validate_owned_child(&skills_dir, path, true)?;\n    Ok(skills_dir)\n}\n\n/// Resolve the on-disk CodeWhale-owned skills directory for a target scope.\npub fn resolve_owned_target(\n    workspace: &Path,","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/skills/mutation.rs#L315-L351","documentation":"validate_owned_skill_path compares the root_id recorded on the audited skill with the root_id of its associated root descriptor; they differ. This means the audit snapshot became inconsistent between scan and mutation (root rescanned/re-indexed, ids regenerated) so the skill-to-root binding can no longer be trusted; a fresh audit is required. The stale audit data is the input at fault.","triggerScenarios":"Thrown at crates/tui/src/skills/mutation.rs:333 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Re-run the skills audit/scan and retry the mutation with fresh ids","Avoid holding skill references across scans or root re-indexing"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}