{"record":{"id":"4e94bbf0529bab6f","repo":"Hmbown/CodeWhale","slug":"only-codewhale-managed-skills-can-be-updated-mutation","errorCode":null,"errorMessage":"only Codewhale managed skills can be updated","messagePattern":"only Codewhale managed skills can be updated","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/skills/mutation.rs","lineNumber":867,"sourceCode":"                continue;\n            }\n            fs::copy(&path, &target)?;\n        }\n    }\n    Ok(())\n}\n\nasync fn update_skill(\n    skill_id: AuditedSkillId,\n    expected_digest: Option<String>,\n    ctx: &MutationContext<'_>,\n) -> Result<SkillMutationReceipt> {\n    let (skill, path) = find_audited_skill(ctx, &skill_id)?;\n    if !skill.root.is_writable_owned() {\n        bail!(\"refusing to update skill outside Codewhale-owned roots\");\n    }\n    if skill.source_kind != SkillSourceKind::CodeWhaleManaged {\n        bail!(\"only Codewhale managed skills can be updated\");\n    }\n    let skills_dir = validate_owned_skill_path(ctx, &skill, &path)?;\n    // Imported skills carry `import:…` provenance and must not hit the registry.\n    ensure_remote_updatable(&path)?;\n    let before = verify_expected_digest(&path, expected_digest.as_deref())?;\n    let scope = match skill.root.kind {\n        SkillRootKind::CodeWhaleProject => SkillScope::Project,\n        SkillRootKind::CodeWhaleGlobal => SkillScope::Global,\n        _ => SkillScope::Logical,\n    };\n\n    let package_name = on_disk_package_name(&skill_id)?;\n    validate_owned_skill_path(ctx, &skill, &path)?;\n    let outcome = install::update_with_registry(\n        package_name,\n        &skills_dir,\n        ctx.max_size,\n        ctx.network,","sourceCodeStart":849,"sourceCodeEnd":885,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/skills/mutation.rs#L849-L885","documentation":"`update_skill` restricts updates to skills whose audit classification is `SkillSourceKind::CodeWhaleManaged`. Imported skills (provenance `import:…`) and other kinds are excluded — imported copies must not hit the remote registry — so updating anything else is rejected.","triggerScenarios":"Calling the `Update` mutation on a skill whose `source_kind` is not `CodeWhaleManaged` — e.g. `CompatibleExternal` or an imported copy — even if it sits in a writable owned root.","commonSituations":"Attempting to update a previously imported skill (its `import:…` provenance makes it non-managed); the audit classifies a skill as external because install/trust marker files are missing or stale after a manual copy.","solutions":["Remove and re-install/re-import the skill so it becomes Codewhale-managed with proper provenance markers, then update.","Restore the missing install/trust marker files so the audit classifies the skill as `CodeWhaleManaged`.","For imported skills, update the external source and re-import instead of using the update path."],"exampleFix":"// before\nmutation.execute(Mutation::Update { skill_id: imported_skill_id, .. })?; // rejected\n// after\nmutation.execute_sync(Mutation::Remove { skill_id: imported_skill_id, .. })?;\nmutation.execute_sync(Mutation::ImportExternal { .. })?; // fresh managed install","handlingStrategy":"validation","validationCode":"let (skill, _) = find_audited_skill(ctx, &skill_id)?;\nif skill.source_kind != SkillSourceKind::CodeWhaleManaged {\n    return Err(anyhow!(\"skill is not Codewhale-managed; re-import to refresh\"));\n}","typeGuard":"fn is_managed(skill: &AuditedSkill) -> bool {\n    skill.source_kind == SkillSourceKind::CodeWhaleManaged\n}","tryCatchPattern":null,"preventionTips":["Never call Update on imported skills; re-import instead.","Keep install/trust marker files intact so provenance stays managed.","Check source_kind in the audit before any mutation."],"tags":["skills","update","validation"],"backgroundTag":"unsupported-operation","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}