diff --git a/docs/superpowers/specs/2026-05-21-generated-wiki-stale-purge-design.md b/docs/superpowers/specs/2026-05-21-generated-wiki-stale-purge-design.md new file mode 100644 index 0000000..6af41db --- /dev/null +++ b/docs/superpowers/specs/2026-05-21-generated-wiki-stale-purge-design.md @@ -0,0 +1,153 @@ +# Generated Wiki Stale Purge Design + +## Goal + +Add an explicit bulk purge path for generated NodeBB wiki pages that have become +stale after generator output changes, such as topdata visibility rules hiding +previously generated pages. + +## Context + +The topdata wiki deployer already owns generated page state through +`.cache/wiki/.wiki_deploy_manifest.json`. It currently recognizes stale +generated pages that remain in the deploy manifest but no longer exist in the +current generated wiki output. Existing stale policies can either report those +pages or archive them by rewriting their managed content. + +That is not sufficient when the stale generated wiki topics should be removed +from NodeBB entirely. The Westgate Wiki plugin already treats a normal wiki topic +delete as an irreversible purge, so the deployer should use NodeBB's explicit +topic purge API when the operator asks for destructive generated-page cleanup. + +## Scope + +### In Scope + +- Add `purge` as an explicit stale policy for topdata wiki deployment. +- Plan purge candidates only from generated page entries already tracked in the + wiki deploy manifest. +- Purge the exact tracked NodeBB topic for each stale generated page. +- Report purge counts in dry-run and live deploy output. +- Remove successfully purged page entries from the deploy manifest so later + deploys do not repeatedly target removed topics. +- Allow release automation to opt into purge through the existing stale-policy + environment variable path. +- Update toolkit and module documentation for the destructive cleanup mode. + +### Out Of Scope + +- Purging manually-authored NodeBB wiki pages. +- Discovering purge candidates by namespace browsing, title, slug, or wiki + search. +- Adding a soft-delete or restore workflow for stale generated wiki pages. +- Changing the Westgate Wiki plugin delete behavior. +- Adding a separate stale cleanup command outside `deploy-wiki`. + +## Operator Interface + +The existing `deploy-wiki` stale-policy surface gains a third explicit policy: + +```bash +./deploy-wiki.sh --dry-run --stale-policy purge +./deploy-wiki.sh --stale-policy purge +``` + +Release automation may use the same policy through: + +```bash +SOW_MODULE_WIKI_DEPLOY_STALE_POLICY=purge +``` + +`purge` remains opt-in. Existing `report` and `archive` behavior remain +unchanged. + +## Purge Eligibility + +A page may be purged only when all of these are true: + +1. The page exists in `.cache/wiki/.wiki_deploy_manifest.json`. +2. The page is absent from the current generated wiki page set in the deploy + scope. +3. The deploy manifest entry has the tracked NodeBB topic id required to call + the topic purge API. + +The deployer must not search NodeBB for candidate pages when purging stale +generated output. It must not purge pages that are currently generated. It must +not purge pages that only exist as manually-authored NodeBB wiki content. + +If a stale manifest entry has no topic id, purge planning fails clearly instead +of guessing a remote target. + +## Deploy Flow + +Stale planning stays inside the existing `deploy-wiki` deploy plan: + +- `report` increments the stale count only. +- `archive` produces the existing archive post-update action. +- `purge` produces a destructive topic-purge action for the manifest entry's + tracked topic id. + +Dry runs calculate the same stale and purge counts as live runs but do not call +NodeBB and do not mutate the deploy manifest. + +Live purge execution calls NodeBB's topic purge API for each planned stale +generated page. NodeBB auth, permission, missing-topic, or transport failures +abort the deploy with the failing generated page id and remote topic context. + +## Manifest State + +Archive retains stale entries in the manifest because the archived post remains +managed remotely. + +Purge removes each successfully purged page entry from the next deploy manifest. +This records that the generated page no longer has a managed remote NodeBB topic +and prevents later deploys from attempting to purge an already removed topic. + +If a purge deployment fails partway through, only state written after the +existing deploy execution succeeds should reach the manifest. A later rerun may +retry the stale manifest entries still present, matching the deployer's current +all-or-error manifest persistence behavior. + +## Reporting And Validation + +Toolkit deploy output gains a `purged` count alongside the existing `stale` and +`archived` counts. Dry-run summaries must make the destructive plan visible +before a live purge run. + +`purge` must be accepted wherever stale policy is validated: + +- project config stale-page settings +- `deploy-wiki --stale-policy` +- module release wrapper validation for + `SOW_MODULE_WIKI_DEPLOY_STALE_POLICY` + +Unsupported stale policy values must keep failing early with clear error text. + +## Testing + +Toolkit tests should cover: + +- stale policy validation accepts `purge` +- unsupported stale policy values still fail +- dry-run purge reports stale and purged counts without calling NodeBB or + changing the manifest +- live purge calls the NodeBB topic purge endpoint for a stale tracked generated + topic +- live purge removes the manifest entry after success +- purge refuses a stale manifest entry without a tracked topic id +- current generated pages are never purge candidates +- archive/report behavior remains unchanged + +Module wrapper/docs coverage should verify: + +- release stale-policy validation accepts `purge` +- docs describe purge as destructive, generated-manifest-scoped cleanup + +## Compatibility + +Default behavior remains `report`. Existing archive cleanup remains available and +unchanged. The destructive purge path activates only when the operator selects +`purge`. + +The purge boundary is intentionally stricter than normal page adoption logic: +generated manifest state authorizes the target; NodeBB discovery never does.