12 KiB
Guanghan Temporal Topology Repair Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Repair the approved audit findings so the Wiki topology is genuinely database-driven, historically accurate, deployable, navigable, readable, and covered by automated and screenshot verification.
Architecture: The Flask topology service will serve both the local demo page and same-origin JSON endpoints. PostgreSQL remains the source of truth for missions, components, connections, state, and layout; the browser will create SVG nodes and edges entirely from the snapshot response. Layout-only presentation metadata stays in layout tables, while operational facts remain in temporal topology tables.
Tech Stack: PostgreSQL 16, psycopg 3, Flask 3, vanilla JavaScript, SVG, Python unittest, Playwright.
File map
topology_api/config.py: secure environment loading and service port.topology_api/app.py: Flask app, health endpoint, and local demo-page serving.topology_api/routes/snapshot.py: JSON request validation, snapshot and mission-list endpoints.topology_api/queries/snapshot_queries.py: mission list, snapshot, component provenance, and layout queries.topology_api/migrations/005_layout_presentation.sql: layout node membership and presentation metadata.topology_api/seed/seed_ghc01_to_ghc05.py: complete mission anchors, correct temporal facts, component data.topology_api/seed/seed_layout.py: persisted node groups, concise labels, and radiator decorations.data/wiki/guanghan_topology_demo.html: same-origin API client, dynamic SVG renderer, time controls, modal, navigation.tests/test_topology_api.py: real API/database contract coverage.tests/test_guanghan_topology_demo.py: current source-level page contract.tests/test_guanghan_topology_e2e.py: browser behavior against the real Flask app and database.
Task 1: Secure and unify local serving
Files:
-
Modify:
topology_api/config.py -
Modify:
topology_api/app.py -
Create:
tests/test_topology_api.py -
Modify:
data/wiki/guanghan_topology_demo.html -
Step 1: Write failing tests
Add tests asserting:
def test_app_serves_demo_page_and_health(client):
assert client.get("/health").status_code == 200
page = client.get("/guanghan_topology_demo.html")
assert page.status_code == 200
assert "广寒基地拓扑结构" in page.get_data(as_text=True)
def test_page_uses_same_origin_api():
html = HTML_PATH.read_text(encoding="utf-8")
assert "http://localhost:5000" not in html
assert "const API_BASE = ''" in html
def test_config_has_no_default_password():
source = CONFIG_PATH.read_text(encoding="utf-8")
assert 'os.environ.get("PGPASSWORD",' not in source
- Step 2: Run tests and verify RED
Run:
python -m unittest tests.test_topology_api -v
Expected failures: no demo route, hardcoded API host, and hardcoded password.
- Step 3: Implement minimal serving and configuration
Use load_dotenv(PROJECT_ROOT / ".env"), require PGHOST, PGPORT, PGUSER, and PGPASSWORD, default only the non-secret topology database name, and default the topology service port to 8080.
Serve the existing page:
@app.get("/guanghan_topology_demo.html")
def topology_demo():
return send_from_directory(WIKI_DIR, "guanghan_topology_demo.html")
Use const API_BASE = '' so browser requests remain same-origin.
- Step 4: Run tests and verify GREEN
Run the Task 1 tests and confirm zero failures.
- Step 5: Commit
git commit -m "fix(topology): secure and unify demo serving"
Task 2: Validate API requests and expose missions
Files:
-
Modify:
topology_api/routes/snapshot.py -
Modify:
topology_api/queries/snapshot_queries.py -
Modify:
tests/test_topology_api.py -
Step 1: Write failing API tests
Cover:
def test_invalid_time_is_json_400(client):
response = client.get("/api/v1/bases/guanghan/snapshot?at=not-a-time")
assert response.status_code == 400
assert response.json["error"] == "invalid_time"
def test_time_and_mission_preserve_context(client):
response = client.get(
"/api/v1/bases/guanghan/snapshot"
"?mission=GHC-01&at=2025-01-02T08:00:00%2B08:00"
)
assert response.status_code == 200
assert response.json["query"]["requestedMission"] == "GHC-01"
assert response.json["query"]["anchorSource"] == "explicit_time"
def test_mission_list_is_database_backed(client):
response = client.get("/api/v1/bases/guanghan/missions")
assert response.status_code == 200
assert "GHC-05" in [row["code"] for row in response.json["missions"]]
- Step 2: Run tests and verify RED
Expected failures: invalid time is 500 and the mission endpoint is 404.
- Step 3: Implement validation and mission query
Parse ISO 8601 with datetime.fromisoformat(value.replace("Z", "+00:00")), require a timezone, normalize to ISO output, and return JSON 400 on failure.
Add fetch_missions(base_code) returning code, title, occurrence status, and maximum event time ordered chronologically.
- Step 4: Run tests and verify GREEN
Run python -m unittest tests.test_topology_api -v.
- Step 5: Commit
git commit -m "fix(topology): validate time and list missions"
Task 3: Correct temporal seed facts
Files:
-
Modify:
topology_api/seed/seed_ghc01_to_ghc05.py -
Modify:
tests/test_topology_api.py -
Step 1: Write failing mission-anchor and port tests
Assert all nine expected terminal instants:
EXPECTED_LAST_EVENTS = {
"BL-01": "2024-05-17T23:01:00+00:00",
"GHC-01": "2024-06-16T07:23:00+00:00",
"JC-01": "2024-06-17T08:19:00+00:00",
"BL-02": "2024-06-23T05:23:00+00:00",
"GHC-02": "2024-07-15T03:16:00+00:00",
"GHC-03": "2024-08-30T12:45:00+00:00",
"BL-03": "2024-09-23T19:20:00+00:00",
"GHC-04": "2024-11-20T13:57:00+00:00",
"GHC-05": "2025-01-22T10:52:00+00:00",
}
Also assert Binglun 1/2/3 connect to west/south/east hub ports respectively.
- Step 2: Run and verify RED
Expected: five terminal-time mismatches and two Binglun port mismatches.
- Step 3: Add terminal checkpoint events and correct ports
Add a non-topology mission_checkpoint event at each missing terminal instant. Map Binglun connections:
hub_ports = {
"binglun_1": "west",
"binglun_2": "south",
"binglun_3": "east",
}
- Step 4: Re-seed and verify GREEN
Run:
python -m topology_api.seed.seed_ghc01_to_ghc05
python -m topology_api.seed.seed_layout
python -m unittest tests.test_topology_api -v
- Step 5: Commit
git commit -m "fix(topology): correct mission anchors and rover ports"
Task 4: Persist complete diagram semantics
Files:
-
Create:
topology_api/migrations/005_layout_presentation.sql -
Modify:
topology_api/seed/seed_layout.py -
Modify:
topology_api/queries/snapshot_queries.py -
Modify:
tests/test_topology_api.py -
Step 1: Write failing layout tests
Require every layout node to expose:
{
"nodeKey": "...",
"memberKeys": ["..."],
"displayMeta": "...",
"displayHint": "...",
"decorations": {"radiator": True}
}
Assert west and east group membership and exactly four radiator nodes.
- Step 2: Run and verify RED
Expected: missing layout fields.
- Step 3: Add schema and query support
Add display_meta text, display_hint text, and decorations jsonb to diagram_nodes, plus:
CREATE TABLE topology.diagram_node_members (
diagram_node_id uuid NOT NULL REFERENCES topology.diagram_nodes(id) ON DELETE CASCADE,
component_id uuid NOT NULL REFERENCES topology.components(id),
display_order integer NOT NULL DEFAULT 0,
PRIMARY KEY (diagram_node_id, component_id)
);
Seed direct and grouped members, concise approved labels, and radiator decorations.
- Step 4: Apply migration, seed, and verify GREEN
Execute migration transactionally with psycopg, seed layout, then run API tests.
- Step 5: Commit
git commit -m "feat(topology): persist complete diagram semantics"
Task 5: Render SVG entirely from snapshot data
Files:
-
Replace rendering section:
data/wiki/guanghan_topology_demo.html -
Modify:
tests/test_guanghan_topology_demo.py -
Modify:
tests/test_guanghan_topology_e2e.py -
Step 1: Write failing renderer contracts
Assert the source no longer contains hardcoded topology nodes or fixed connection inventory, uses currentData.layout, renders connections from currentData.connections, renders radiators only from visible node decorations, and retains future expansion comments.
Add E2E assertions:
-
BL-01 has one node, zero connection lines, zero radiators;
-
GHC-01 has two nodes and zero connection lines;
-
GHC-05 has 14 visual nodes, two green pressurized lines, four radiators;
-
no visible SVG text extends outside its owning node rectangle.
-
Step 2: Run and verify RED
Expected: fixed SVG and historical visibility failures.
- Step 3: Implement dynamic renderer
Create SVG elements with document.createElementNS, map component keys to persisted layout nodes, aggregate multiple database edges that share visual endpoints and line class, calculate rectangle-edge intersections from node centers, and attach click/keyboard handlers after node creation.
Use concise persisted displayMeta/displayHint; truncate text based on node width and add a <title> for full content. Render a radiator only when the visible layout node declares decorations.radiator.
- Step 4: Run and verify GREEN
Run source and browser tests.
- Step 5: Commit
git commit -m "feat(topology): render temporal graph from database"
Task 6: Repair controls, navigation, errors, and modal semantics
Files:
-
Modify:
topology_api/queries/snapshot_queries.py -
Modify:
data/wiki/guanghan_topology_demo.html -
Modify:
tests/test_topology_api.py -
Modify:
tests/test_guanghan_topology_e2e.py -
Step 1: Write failing behavior tests
Cover:
-
mission dropdown comes from
/missions; -
mission plus explicit time sends both query parameters and retains mission subtitle;
-
invalid time shows a localized validation error without a request;
-
browser back reloads the URL-selected snapshot;
-
modal “任务节点” displays introduction mission and time;
-
modal close restores focus to the triggering node;
-
internal anchor enum values are localized;
-
database strings are inserted with
textContent, notinnerHTML. -
Step 2: Run and verify RED
Expected: each approved audit defect reproduces.
- Step 3: Implement minimal behavior
Return introducedMission and introducedAt for components. Fetch mission options from the API. Always send both non-empty parameters. Add popstate, ISO validation, localized anchor labels, stable Asia/Shanghai formatting, safe line rendering helpers, and trigger-focus restoration.
- Step 4: Run and verify GREEN
Run API, source, and E2E tests.
- Step 5: Commit
git commit -m "fix(topology): repair controls navigation and details"
Task 7: Full service and screenshot verification
Files:
-
Update only if a verified defect remains.
-
Create screenshots under
demo/topology_repair/. -
Step 1: Run the complete automated suite
python -m unittest tests.test_topology_api tests.test_guanghan_topology_demo tests.test_guanghan_topology_e2e -v
Expected: all pass with no browser console errors.
- Step 2: Restart the topology service
Stop only the verified processes listening on ports 5000 and 8080, then start:
python topology_api/app.py
with a hidden window and working directory at the repository root.
- Step 3: Test and screenshot every mission
Visit each of the nine tasks through the page control, verify node/edge/radiator counts, open representative modal details, test explicit time, invalid time, back navigation, and 390×844 layout.
- Step 4: Review diffs and requirements
Confirm no unrelated files changed, no secret remains in tracked source, all approved audit items have a test or explicit evidence, and the original GHC-05 spatial skeleton remains intact.
- Step 5: Commit verification evidence
git commit -m "test(topology): verify repaired temporal topology"