Topdata Migration (#2)

Native topdata migration summary

- Replaced the legacy 2dabuilder runtime path with the native topdata builder.
- Native build, validate, compare, and convert flows now cover the canonical topdata pipeline.
- compare-topdata is now a native self-check; legacy reference-builder runtime usage was removed.
- Parts generation follows the native asset-scan contract and uses sow-assets via project asset resolution.
- Generated feat families, class-feat injects, masterfeat/successor expansion, and dataset-derived feat generation were brought to parity and regression-covered.
- Remaining mirrored datasets were migrated into native-owned canonical data while preserving lock IDs.
- normalize-topdata bridge behavior and migration-era ownership markers were removed.
- Documentation was rewritten around the native workflow and active contracts were cleaned up.
- Final hardening pass removed stale validator assumptions and cleaned ignored/generated artifacts for PR readiness.

Reviewed-on: https://gitea.westgate.pw/ShadowsOverWestgate/sow-tools/pulls/2
Co-authored-by: vickydotbat <vickydotbat@tutamail.com>
Co-committed-by: vickydotbat <vickydotbat@tutamail.com>
This commit is contained in:
2026-04-09 07:14:01 +00:00
committed by archvillainette
parent 99f9d29d7a
commit dc93feb176
1402 changed files with 20955 additions and 3405 deletions
+35 -3
View File
@@ -36,9 +36,9 @@ type Config struct {
}
type ModuleConfig struct {
Name string `json:"name"`
ResRef string `json:"resref"`
Description string `json:"description"`
Name string `json:"name"`
ResRef string `json:"resref"`
Description string `json:"description"`
HAKOrder []string `json:"hak_order"`
}
@@ -60,6 +60,7 @@ type TopDataConfig struct {
Source string `json:"source"`
Build string `json:"build"`
ReferenceBuilder string `json:"reference_builder"`
Assets string `json:"assets"`
}
type Inventory struct {
@@ -251,6 +252,37 @@ func (p *Project) TopDataReferenceBuilderDir() string {
return filepath.Join(p.Root, ref)
}
var knownAssetRepoNames = []string{"sow-assets", "nwn-assets", "assets"}
func (p *Project) TopDataAssetsDir() string {
assets := strings.TrimSpace(p.Config.TopData.Assets)
if assets == "" {
return ""
}
if filepath.IsAbs(assets) {
return assets
}
absPath := filepath.Join(p.Root, assets)
if _, err := os.Stat(absPath); err == nil {
return absPath
}
relFromParent := filepath.Join(filepath.Dir(p.Root), assets)
if _, err := os.Stat(relFromParent); err == nil {
return relFromParent
}
absRoot := filepath.Clean(p.Root)
parentDir := filepath.Dir(absRoot)
if parentDir != absRoot {
for _, repoName := range knownAssetRepoNames {
siblingPath := filepath.Join(parentDir, repoName)
if _, err := os.Stat(siblingPath); err == nil {
return siblingPath
}
}
}
return absPath
}
func (i Inventory) Report() InventoryReport {
return InventoryReport{
SourceFiles: len(i.SourceFiles),