Lifecycle management for an already-installed module — uninstall (with confirmation, deferred if active stories still reference it), activate (undo a pending deprecation), and renegotiate (reopen a provides_rules verdict for the current project). Use /new-module for installing a new module instead.
Scanned 9/5/2026
Install to Claude Code
npx -y skills add luk-s12/legion --skill module --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Module?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/luk-s12-module)More formats (shields.io, HTML) on the badges page.
---
name: module
description: Lifecycle management for an already-installed module — uninstall (with confirmation, deferred if active stories still reference it), activate (undo a pending deprecation), and renegotiate (reopen a provides_rules verdict for the current project). Use /new-module for installing a new module instead.
---
## Mandatory project scope
Resolve or confirm the project through `.orchestrator/projects.yml` before reading project state.
The selected catalog entry is the sole configuration authority. Use only
`requirements/<project>.md`, `.orchestrator/projects/<project>/...`, `workspace/<repo_dir>` and
namespaced worktrees. A missing or empty catalog is never assumed new or old — apply exclusively
`CLAUDE.md`'s project-resolver table under "Required bootstrap for an older installation" (empty
and missing resolve differently) and never permit old singleton paths.
For a project-shared write, acquire the brief project mutex, reread current state, write and validate
a sibling candidate, rename it to the known destination, reread, then release the owned mutex.
Do not hold a mutex while interviewing, researching, testing, reviewing or waiting. Catalog and global `modules/registry.md` writes instead use the brief global metadata mutex. Never acquire or release a story claim unless this skill
is `/legion` performing a reservation.
Manage the lifecycle of a module already present in `modules/registry.md`. These three
sub-actions cover what's actually needed — not a broader command family anticipating future
operations (update, list) that aren't needed yet. See `modules/README.md` for the registry's
state machine, and its "Negotiation of `provides_rules`" section for what `renegotiate` reopens.
**Arguments**: `/module uninstall <name>`, `/module activate <name>`, or `/module renegotiate
<name> [rule_id]`.
Every `modules/registry.md` state mutation uses the global metadata mutex: acquire
`.orchestrator/runtime/catalog.lock`, reread the registry, update a sibling
`modules/registry.md.candidate-<session>`, validate all existing rows plus the intended transition,
rename exactly to `modules/registry.md`, reread/compare, then release the verified mutex. Never hold
the project mutex simultaneously. Project assignments/design/rule writes separately use the
project safe-write contract.
## `/module uninstall <name>`
1. Look up `<name>` in `modules/registry.md`. If it doesn't exist, error.
2. **If `type: gate`**, check whether any **active** story (not `finalized`/`aborted` on
`.orchestrator/projects/<project>/assignments.md`) references it in its `## Modules`, or whether it's
`default_activation: always` and there are active stories that haven't passed through its
stage yet:
- If so: mark (or confirm) state `deprecated` through the global registry safe-write contract, and
report the list of stories still referencing it, so the user can decide whether to let them
finish or remove it from their `## Modules` by hand. Also add (or update) a
`### Deprecated modules with active references` sub-section in `.orchestrator/projects/<project>/assignments.md`
(`Module | Deprecated on | Stories still referencing it`) — so this is visible from the board
itself, without cross-referencing `registry.md` against every story's `## Modules` by hand.
Drop the module's row from that sub-section once no active story references it anymore (the
next time the board is touched — no separate sweep needed). **Stop here** — do not touch
`modules/installed/<name>/`.
- If not (or the module is `type: generator`, which is never story-scoped and has no
`## Modules` references to check): continue to step 3.
3. `AskUserQuestion` to confirm — this is **irreversible**. On confirmation, acquire the global
metadata mutex and publish state `uninstalled` through the registry safe-write contract first
(never delete the row — project reputation/metrics/old reports still cite it). Only after the
destination reread succeeds, resolve `modules/installed/<name>/`, prove it is the exact expected
child of `modules/installed/` (matching name, contained real path, not a symlink/junction), and
remove that exact tree through the filesystem operation; never construct a shell glob or use
`rm -r`/`rm -rf`. Release the verified mutex afterward. If exact removal fails or is partial,
keep the durable `uninstalled` state, release the mutex and report the remaining exact path for
a confirmed cleanup retry; do not roll back to `installed`, because the clone may be incomplete.
A fresh install must refuse to overwrite that residue until the exact cleanup succeeds.
4. Running this command again on a module already `deprecated` with no remaining active
references goes straight to step 3 — same command, natural continuation, not a separate case.
## `/module activate <name>`
- Only valid if the module's current state is `deprecated` → flip it back to `installed` using the
global registry safe-write contract. Nothing else changes — stories that kept referencing it in their
`## Modules` never noticed the detour.
- **Not valid on `uninstalled`** — that registry state is not usable and cannot be reactivated,
even if a failed/partial cleanup left residue under `modules/installed/<name>/`. Never trust or
reuse such residue. Tell the user a fresh `/new-module` is needed instead (after separately
confirmed exact cleanup if residue exists).
## `/module renegotiate <name> [rule_id]`
Reopens the accept/reject question for the module's `provides_rules`, against the **current**
project (the selected slug in `.orchestrator/projects.yml`) — without waiting for the module to change
version. Useful when the user just wants to revisit a call they already made.
1. Look up `<name>` in `modules/registry.md`. **Valid only if its state is `installed` or
`deprecated`** — same criterion as `/module activate`. An `uninstalled` registry row is not a
usable module, even if a failed/partial cleanup left filesystem residue. Never read or reuse
that residue; tell the user a fresh `/new-module` is needed first (after separately confirmed
exact cleanup if necessary).
2. Resolve `modules/installed/<name>/` as the exact expected child of `modules/installed/`
(matching name, canonically contained, and not itself a symlink/junction), then read its
`module.md`. If the clone or manifest is missing, the manifest is not a regular file, or either
resolves outside that exact module root, stop and report the invalid installation; do not guess
a rules filename.
3. Parse `module.md`'s YAML frontmatter with the same manifest parsing rules used by
`/new-module`; never infer `provides_rules` from Markdown body text. The field may appear at
most once and, when present, must be a single scalar string (not a sequence, mapping or block
value). Reject a duplicate or non-scalar declaration as an invalid manifest. If the field is
not declared in the frontmatter, there is nothing to renegotiate; say so and stop.
4. Treat the declared `provides_rules` value as a module-root-relative file path. Reject it and
stop if it is empty, absolute/rooted, contains an unresolved placeholder, or resolves outside
`modules/installed/<name>/` (including through `..`, a symlink or a junction). Require the
resolved target to exist and be a regular file. These checks are repeated at renegotiation time
even though `/new-module` validated the path at install time, because installed module content
may have changed since then.
5. Read that exact validated `provides_rules` file — never a hardcoded
`modules/installed/<name>/rules.md` — and the current
`.orchestrator/projects/<project>/module-rules/<name>.md` for this project (if it doesn't exist
yet, there's nothing negotiated to reopen — point the user at running a story that references
the module instead, that's what triggers the first negotiation).
6. If `[rule_id]` was passed, reopen only that entry; otherwise reopen every `rule_id` the module
currently declares. Ask with the same single multiSelect `AskUserQuestion` used for the
original negotiation (`legion/SKILL.md`, "Module stages").
7. The result is appended as a **new row** in the resolved project's `module-rules/<name>.md` through
the project safe-write contract — the
previous row is never deleted or edited in place (same historical-record criterion as the rest
of `.orchestrator/`).
8. **No retroactivity**: this never reopens a story already `finalized` in this project — its
`designs/<Story-ID>.md` stays as it was approved. If the user wants a closed story to pick up
the new verdict, that's Phase 6 (post-closure correction) of `/legion`, not this command.
9. **Informational note on affected finalized designs** (not a reopening): if this `rule_id`'s
NEW verdict differs from the one embedded in any `finalized` story's `## Module rules applied`
section, append one line under that story's entry in `designs/<Story-ID>.md`: "Note: this
rule's verdict was renegotiated on `<date>` to `<new verdict>` for future stories — does not
apply retroactively to this story." Find affected designs by grepping `designs/*.md` for the
module name inside a `## Module rules applied` section. Purely for anyone reading that design
in isolation later — no status change, no re-review triggered.
## Rules
- Never delete a registry row, only change its state.
- Never write to or delete `modules/installed/<name>/` without the explicit confirmation and exact
containment validation in uninstall's step 3; no broad recursive shell deletion is permitted.
- `/module activate` never re-clones anything — it's a pure state flip, not an install.
- `/module renegotiate` reads `module.md` and its exact validated `provides_rules` target, but never
writes to or deletes anything in `modules/installed/<name>/` and never mutates the registry —
its only durable module-state change is a new row in the resolved project's
`module-rules/<name>.md`.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!