Phase 5: scaffold Crucible (sow-tools) — dispatcher + builder shims, container, PR-first CI, fail-closed (D11, D19).
This commit is contained in:
@@ -1,153 +0,0 @@
|
||||
# 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.
|
||||
@@ -1,105 +0,0 @@
|
||||
# Class Progression Feat Availability Design
|
||||
|
||||
## Goal
|
||||
|
||||
Class progression wiki providers should let module-owned wiki configuration
|
||||
distinguish automatically granted class feats from level-gated selectable feats
|
||||
while also exposing bonus feat gains declared by class `bfeat` tables in the
|
||||
progression table.
|
||||
|
||||
## Ownership
|
||||
|
||||
The authored wiki page layout and progression projection policy stay in
|
||||
`sow-module/topdata/wiki/`. The toolkit owns generic progression row data
|
||||
assembly from configured class feat and bonus-feat sources. The change should
|
||||
stay inside those boundaries:
|
||||
|
||||
- module wiki YAML decides which class feat rows project into progression
|
||||
fields;
|
||||
- module page templates decide how progression row fields are rendered;
|
||||
- toolkit progression row assembly groups configured projections by level
|
||||
without hardcoding the module's class feat list semantics or note wording.
|
||||
|
||||
## Behavior
|
||||
|
||||
Class feat rows with positive `GrantedOnLevel` values are not all equivalent.
|
||||
This module uses rows in class feat tables with `List` value `3` as
|
||||
automatically granted feats and positive-level selectable rows as feats that
|
||||
become available at the declared level. That distinction is repository policy
|
||||
and must be declared in wiki YAML rather than hidden in toolkit code.
|
||||
|
||||
The `ClassProgression` data provider should support configured class feat
|
||||
projection fields. This module can declare a shape such as:
|
||||
|
||||
```yaml
|
||||
providers:
|
||||
ClassProgression:
|
||||
source: class_progression
|
||||
levels: 1-12
|
||||
class_feats:
|
||||
fields:
|
||||
GrantedFeats:
|
||||
when: "{{GrantedOnLevel > 0 && List == 3}}"
|
||||
AvailableFeats:
|
||||
when: "{{GrantedOnLevel > 0 && List != 3}}"
|
||||
```
|
||||
|
||||
For each progression row, the toolkit should:
|
||||
|
||||
- continue exposing the per-level bonus feat count from the class `bfeat` table
|
||||
as `BonusFeat`;
|
||||
- expose each configured class feat field as a deterministic list of resolved
|
||||
wiki feat links for class feat rows whose configured expression matches the
|
||||
progression level;
|
||||
- leave non-matching class feat rows out of that configured field.
|
||||
|
||||
The default `class_progression` provider behavior should preserve the current
|
||||
`GrantedFeats` projection when no custom field configuration is declared.
|
||||
|
||||
## Rendering
|
||||
|
||||
The class progression template can render `BonusFeat` inline in its existing
|
||||
Feats cell rather than adding another progression column. It should emit the
|
||||
separator only when `GrantedFeats` already rendered content so bonus-only rows
|
||||
do not start with a comma.
|
||||
|
||||
The existing Notes column should render `AvailableFeats` in the module template
|
||||
with module-owned wording such as `<feat link> becomes available.`. The lower
|
||||
class feat table remains useful for listing class feat membership and list
|
||||
metadata; its level label should not be interpreted as an automatic grant for
|
||||
selectable rows.
|
||||
|
||||
## Data Flow
|
||||
|
||||
The toolkit resolves the class `FeatsTable` while building progression rows.
|
||||
Each configured class feat field evaluates its `when` expression against class
|
||||
feat rows, groups matched rows by positive `GrantedOnLevel`, resolves feat
|
||||
references to wiki link text, and writes the grouped list onto the progression
|
||||
row under the configured field name. Output order follows source table row
|
||||
order so repeated builds are deterministic.
|
||||
|
||||
The class `BonusFeatsTable` lookup continues to populate `BonusFeat` from the
|
||||
row whose id matches the progression level.
|
||||
|
||||
## Errors And Compatibility
|
||||
|
||||
The change should preserve current behavior for missing class feat tables,
|
||||
missing bonus feat tables, unresolved feat references, and classes without
|
||||
custom class feat projections. Invalid projection configuration should fail
|
||||
early with the provider file path and field name. Existing module templates
|
||||
that only read `GrantedFeats`, `BonusFeat`, and `Notes` continue to use the same
|
||||
progression row fields.
|
||||
|
||||
## Tests
|
||||
|
||||
Toolkit coverage should verify:
|
||||
|
||||
- default progression behavior still exposes `GrantedFeats`;
|
||||
- configured class feat fields filter by expression and group by level;
|
||||
- configured output order follows source table row order;
|
||||
- invalid configured class feat fields fail clearly;
|
||||
- bonus feat counts remain available to the progression template.
|
||||
|
||||
Module validation should rebuild the generated wiki output with the local
|
||||
toolkit binary after the toolkit change and inspect a class that has both
|
||||
granted feats and level-gated selectable feats, such as fighter.
|
||||
Reference in New Issue
Block a user