`reach wiki stats` and `reach wiki gttr-hook` replace tooling/db/wiki_sync.py and populate_gttr_hook.py. Both are output-identical to the originals: `stats` byte-for-byte, and all 301 extracted GTTR hooks line-for-line. wiki_sync.py moved whole, but generate_wiki() and import_from_wiki() are NOT verbs. Before porting, the old `--generate` was run against a clean tree to get a parity baseline. It changed all 301 system pages, +940 / -10,761, and was reverted at once. It deletes the Celestial Bodies / Stations blocks (owned by the Rust atlas sync, which it does not know about), deletes the Industries / Exports / Imports rows (nothing writes those any more), and rewrites star types where systems.db and the pages disagree. D-262, CLAUDE.md and the wiki skill all described it as the routine, prose-preserving render. CLAUDE.md and the skill now say not to run it; D-262 needs amending — T-1292. Provenance moves to tooling/archive/, with a README naming what each script did and why it is not run: - pql-migrate/ (the T-1271 ruling) - wiki-bootstrap/: assign-astro-ids + its catalog, migrate-s-to-gj, patch-core-sector (hardcodes a dead path), fill-missing-globes, generate-stubs and find-stubs (finds 0 stubs — Phase 1 is done), backfill_cultural_corridor (a raw systems.db patch script, outside D-262), and process-wiki-system-changes, whose last step is the destructive render Also: - stats() printed "run import first" and exited 0 when a table was missing; it now fails with a remedy. generate_wiki() counted created pages after writing them, so `created` was always 0. - tooling/godot-cold-parse and godot-parse-sweep were never retired after T-1283, and the pr-process skill still told agents to run them. Removed; the skill and parse_sweep.gd now name the reach verbs. - systems.db re-stamped: schema comments changed, and the stamp records the schema file's SHA for tamper detection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
90 lines
3.8 KiB
GDScript
90 lines
3.8 KiB
GDScript
extends SceneTree
|
|
|
|
## Parse-sweep: open EVERY project .gd so the engine reports the broken ones.
|
|
##
|
|
## Why this exists. `reach godot cold-parse` only ever sees scripts on the
|
|
## STARTUP path — autoloads and the main scene chain. That is the correct
|
|
## scope for the job it was built for (Sprint 36's `Could not find base class
|
|
## "MetaScreen"`, an autoload-vs-class_name registration ORDER bug), but it is
|
|
## far narrower than its name suggests, and most of the codebase is invisible
|
|
## to it. Verified 2026-07-27 by deliberately breaking a non-startup UI script
|
|
## and a test file in turn: cold-parse reported `clean`, exit 0, for both.
|
|
##
|
|
## That gap cost real time. A parse error in `test_step_canvas_annotation_layer.gd`
|
|
## went unnoticed for hours because it passed cold-parse AND because gdUnit4
|
|
## reports the suites that DID load as a clean pass (fixed separately by
|
|
## `tests/run-godot`'s harness guards). Two gates, one blind spot: neither
|
|
## verified that a file it never opened was openable.
|
|
##
|
|
## **This script deliberately makes no verdict of its own.** It opens every
|
|
## script and lets Godot's own front-end print the diagnosis; the wrapper
|
|
## (`reach godot parse-sweep`) greps for that. Two rejected alternatives,
|
|
## both found the hard way while building this:
|
|
##
|
|
## - `ResourceLoader.load(path, "GDScript", CACHE_MODE_IGNORE)` **segfaults
|
|
## the engine** (signal 11, Godot 4.6) on a script that fails to parse —
|
|
## i.e. it dies on exactly the input this tool exists to find.
|
|
## - `GDScript.new()` + `source_code` + `reload()` returns a clean error code,
|
|
## but detaches the script from its `resource_path`, so `class_name`,
|
|
## `preload()` and relative `extends` stop resolving: it reported 150 of
|
|
## 226 healthy scripts as broken.
|
|
##
|
|
## Plain `ResourceLoader.load()` neither crashes nor lies — but it returns a
|
|
## NON-null object for a broken script, so the return value cannot be trusted
|
|
## either. The engine's stderr is the only honest signal, which is why the
|
|
## verdict lives in the wrapper.
|
|
##
|
|
## Run via `reach godot parse-sweep` (never directly — this half cannot fail).
|
|
|
|
## Vendor and generated trees are not ours to verify. `addons/` is gdUnit4,
|
|
## whose own test corpus deliberately contains broken fixtures — sweeping it
|
|
## would report failures that are the vendor's intended state.
|
|
const SKIP_PREFIXES: PackedStringArray = ["res://addons/", "res://.godot/"]
|
|
|
|
var _checked: int = 0
|
|
var _unreadable_dirs: int = 0
|
|
|
|
|
|
func _initialize() -> void:
|
|
var scripts: PackedStringArray = []
|
|
_collect("res://", scripts)
|
|
scripts.sort() # deterministic ordering, so output diffs cleanly run to run
|
|
|
|
for path in scripts:
|
|
_checked += 1
|
|
# Return value deliberately discarded — see the header. Touching the
|
|
# file is the whole job; the engine prints the diagnosis.
|
|
ResourceLoader.load(path)
|
|
|
|
# stdout only. A non-zero verdict is the wrapper's to make, from stderr.
|
|
print("parse-sweep: opened %d scripts (%d unreadable dirs)" % [_checked, _unreadable_dirs])
|
|
quit(0)
|
|
|
|
|
|
## Recursive walk of the VIRTUAL filesystem. DirAccess rather than a shell
|
|
## `find`, because `res://` is what the engine can actually open — a source-tree
|
|
## walk would include files the engine ignores and miss the distinction.
|
|
func _collect(dir_path: String, out: PackedStringArray) -> void:
|
|
for prefix in SKIP_PREFIXES:
|
|
if dir_path.begins_with(prefix):
|
|
return
|
|
|
|
var dir := DirAccess.open(dir_path)
|
|
if dir == null:
|
|
_unreadable_dirs += 1
|
|
return
|
|
|
|
dir.list_dir_begin()
|
|
var name := dir.get_next()
|
|
while name != "":
|
|
if name.begins_with("."):
|
|
name = dir.get_next()
|
|
continue
|
|
var full := dir_path.path_join(name) if dir_path != "res://" else "res://" + name
|
|
if dir.current_is_dir():
|
|
_collect(full, out)
|
|
elif name.ends_with(".gd"):
|
|
out.append(full)
|
|
name = dir.get_next()
|
|
dir.list_dir_end()
|