Task — engineering-spec@1

Uninstall completeness - MCP, dangling skill links, hook newline

doneTASK-IMP-126
module improvement · class product · priority p2 · created 2026-07-19 · shipped null
depends on none · blocks none

TASK-IMP-126: Uninstall completeness - MCP, dangling skill links, hook newline

Summary

uninstall.sh is not the inverse of install.sh in three places. It never removes the MCP registration files install writes, it cleans only two of the agent families' skill entries and leaves the rest pointing at the deleted machine, and its hook-strip leaves a blank line behind that accumulates on every install/uninstall cycle. Make uninstall the exact inverse of install for these three artifacts, proven by a fixture that installs, uninstalls, and asserts the tree is clean.

Problem

Three verified gaps, each a place where install writes and uninstall does not remove.

Dead MCP registrations. install.sh:694-697 writes .mcp.json (and .cursor/mcp.json when the cursor agent is selected), each pointing at .cyberos/mcp/cyberos-mcp.mjs. uninstall.sh contains zero MCP handling (grep -ci mcp = 0). After uninstall removes .cyberos/, those files survive and register an MCP server whose entry point no longer exists - a broken registration every MCP-capable agent reads.

Dangling skill links. install.sh:632-637 installs the workflow skills for the claude-code, grok, command-code, codex, and opencode families, each a symlink (or copy-fallback) into .cyberos/plugin/skills/. uninstall.sh:98-127 removes only the .agents/skills trio and the .claude/skills create-tasks pair, and :125 explicitly leaves .claude/skills/ship-tasks. The grok, command-code, codex, and opencode entries are never touched. After .cyberos/ is removed, every untouched managed link dangles.

Hook-strip newline leak. install.sh:860-861 appends the managed block to a foreign pre-commit hook via a heredoc whose first line is a blank separator, writing \n# >>> cyberos-status-hook v2 ...>>>\n...\n# <<< cyberos-status-hook <<<\n. uninstall.sh:78 strips the marked range with sed '/# >>> .../,/# <<< ...<<</d' - inclusive of both markers but not the leading blank. The separator survives, so each install/uninstall cycle on a foreign hook accumulates one blank line at the append point. The v1->v2 upgrade path (install.sh:856) shares the pattern.

Proposed Solution

Make uninstall the inverse of install for all three, keeping the whole change in uninstall.sh plus arms in the existing test_install_hygiene.sh:

Alternatives Considered

Success Metrics

Scope

In scope: uninstall.sh's MCP-file removal, the skill-cleanup coverage, the hook-strip separator, and arms in test_install_hygiene.sh.

Out of scope / Non-Goals

Dependencies

None blocking. Touches uninstall.sh (shared surface with TASK-IMP-083 hook logic and TASK-IMP-094 skill logic - both already landed; this extends their inverse coverage).

AI Authorship Disclosure

1. Description (normative)

2. Acceptance criteria

3. Edge cases