|
| 1 | +# Architecture Graph Audit — E-2: Real Stage 1+2 Data Acquisition/Labeling Run |
| 2 | + |
| 3 | +- Before commit: `15e021a1291dba63d8eebf1ef27d128f1656b073` |
| 4 | +- After commit: `44dce258678ee496b580d95f4d70085e0f09b7f8` |
| 5 | +- Before: 3303 nodes, 7100 edges |
| 6 | +- After: 3354 nodes, 7185 edges |
| 7 | +- Node delta: +60 / -9 |
| 8 | +- Edge delta: +97 / -12 |
| 9 | + |
| 10 | +## Architecture Split |
| 11 | +_Scoping summary only — the detailed sections below (centrality, degree, boundary report, etc.) remain whole-graph, since those measures are not meaningful computed on a subgraph alone._ |
| 12 | + |
| 13 | +## Engine Architecture |
| 14 | +- Before: 1584 nodes; After: 1584 nodes |
| 15 | +- Node delta: +0 / -0 |
| 16 | + |
| 17 | +## Trainer Architecture |
| 18 | +- Before: 432 nodes; After: 478 nodes |
| 19 | +- Node delta: +55 / -9 |
| 20 | + |
| 21 | +## Top 10 nodes by betweenness centrality change |
| 22 | +- `Board` (engine_core_src_main_java_coeusyk_game_chess_core_models_board_board): 0.0035 -> 0.0034 (-0.0001) |
| 23 | +- `MovesGenerator` (engine_core_src_main_java_coeusyk_game_chess_core_movegen_movesgenerator_movesgenerator): 0.0009 -> 0.0009 (-0.0000) |
| 24 | +- `TunerPosition` (engine_tuner_src_main_java_coeusyk_game_chess_tuner_tunerposition_tunerposition): 0.0008 -> 0.0008 (-0.0000) |
| 25 | +- `NNUE_PRD.md` (docs_nnue_prd): 0.0000 -> 0.0000 (-0.0000) |
| 26 | +- `LabelledPosition` (engine_tuner_src_main_java_coeusyk_game_chess_tuner_labelledposition_labelledposition): 0.0006 -> 0.0006 (-0.0000) |
| 27 | +- `.iterativeDeepening()` (engine_core_src_main_java_coeusyk_game_chess_core_search_searcher_searcher_iterativedeepening): 0.0006 -> 0.0006 (-0.0000) |
| 28 | +- `.searchRoot()` (engine_core_src_main_java_coeusyk_game_chess_core_search_searcher_searcher_searchroot): 0.0005 -> 0.0005 (-0.0000) |
| 29 | +- `Task 14.7 WDL Self-Play Pilot` (changelog_task_14_7_wdl_selfplay_pilot): 0.0000 -> 0.0000 (-0.0000) |
| 30 | +- `.searchDepth()` (engine_core_src_main_java_coeusyk_game_chess_core_search_searcher_searcher_searchdepth): 0.0005 -> 0.0005 (-0.0000) |
| 31 | +- `.from()` (engine_tuner_src_main_java_coeusyk_game_chess_tuner_tunerposition_tunerposition_from): 0.0004 -> 0.0004 (-0.0000) |
| 32 | + |
| 33 | +## Top 10 nodes by degree change |
| 34 | +- `NNUE_PRD.md` (docs_nnue_prd): 5 -> 2 (-3) |
| 35 | +- `ADR-006-self-written-pytorch-trainer.md` (docs_adr_adr_006_self_written_pytorch_trainer): 2 -> 1 (-1) |
| 36 | +- `ADR-010-trainer-repository-location.md` (docs_adr_adr_010_trainer_repository_location): 2 -> 1 (-1) |
| 37 | +- `ADR-007-staged-training-data.md` (docs_adr_adr_007_staged_training_data): 2 -> 1 (-1) |
| 38 | + |
| 39 | +## Newly introduced architectural bridge-node candidates |
| 40 | +_New nodes ranked by betweenness centrality in the after-graph (>0). Heuristic, not a graphify-defined threshold._ |
| 41 | +- `acquire()` (trainer_scripts_acquire_stage1_lichess_acquire): betweenness centrality 0.0000 |
| 42 | +- `_iter_records()` (trainer_scripts_acquire_stage1_lichess_iter_records): betweenness centrality 0.0000 |
| 43 | +- `acquire_stage1_lichess.py` (trainer_scripts_acquire_stage1_lichess): betweenness centrality 0.0000 |
| 44 | +- `_to_record()` (trainer_scripts_acquire_stage1_lichess_to_record): betweenness centrality 0.0000 |
| 45 | +- `test_acquire_stage1_lichess.py` (trainer_tests_scripts_test_acquire_stage1_lichess): betweenness centrality 0.0000 |
| 46 | +- `stream_records()` (trainer_scripts_acquire_stage1_lichess_stream_records): betweenness centrality 0.0000 |
| 47 | +- `validate_dataset_manifest()` (trainer_trainer_dataset_manifest_schema_validate_dataset_manifest): betweenness centrality 0.0000 |
| 48 | +- `_open_source_stream()` (trainer_scripts_acquire_stage1_lichess_open_source_stream): betweenness centrality 0.0000 |
| 49 | +- `_write_fixture()` (trainer_tests_scripts_test_acquire_stage1_lichess_write_fixture): betweenness centrality 0.0000 |
| 50 | +- ``stockfish-label-e2-real.json` — provenance of each value` (trainer_configs_stockfish_label_e2_real_stockfish_label_e2_real_json_provenance_of_each_value): betweenness centrality 0.0000 |
| 51 | + |
| 52 | +## Newly introduced dependency cycles |
| 53 | +_Detected via strongly-connected-components (existence check, not full cycle enumeration)._ |
| 54 | +- None |
| 55 | + |
| 56 | +## Cross-module dependency changes |
| 57 | +- None |
| 58 | + |
| 59 | +## Community changes |
| 60 | +_Community IDs are not stable across separate graphify runs — flagged via cohort-overlap (Jaccard < 0.5) among nodes present in both snapshots, not raw ID equality._ |
| 61 | +- **490 of 3294 common nodes (15%) flagged — this volume is typical Louvain re-clustering instability under any graph perturbation, not evidence of real coupling change. Read this section by checking whether the specific files this PR touched appear below, not by the raw count.** |
| 62 | +- `MoveOrderer.java` (engine_core_src_main_java_coeusyk_game_chess_core_search_moveorderer): cohort overlap 0.01 |
| 63 | +- `.getZobristHash()` (engine_core_src_main_java_coeusyk_game_chess_core_models_board_board_getzobristhash): cohort overlap 0.01 |
| 64 | +- `.bruteForceNegamax()` (engine_core_src_test_java_coeusyk_game_chess_core_search_searchertest_searchertest_bruteforcenegamax): cohort overlap 0.01 |
| 65 | +- `Piece.java` (engine_core_src_main_java_coeusyk_game_chess_core_models_piece): cohort overlap 0.01 |
| 66 | +- `.evaluateTerminal()` (engine_core_src_main_java_coeusyk_game_chess_core_search_searcher_searcher_evaluateterminal): cohort overlap 0.01 |
| 67 | +- `.enableTTStats()` (engine_core_src_main_java_coeusyk_game_chess_core_search_searcher_searcher_enablettstats): cohort overlap 0.01 |
| 68 | +- `ClassicalEvaluator.java` (engine_core_src_main_java_coeusyk_game_chess_core_eval_classicalevaluator): cohort overlap 0.01 |
| 69 | +- `.explainEval()` (engine_core_src_main_java_coeusyk_game_chess_core_eval_evaluator_evaluator_explaineval): cohort overlap 0.01 |
| 70 | +- `.singularityGuardRequiresDepthAndQualifiedTtEntry()` (engine_core_src_test_java_coeusyk_game_chess_core_search_searchertest_searchertest_singularityguardrequiresdepthandqualifiedttentry): cohort overlap 0.01 |
| 71 | +- `Evaluator.java` (engine_core_src_main_java_coeusyk_game_chess_core_eval_evaluator): cohort overlap 0.01 |
| 72 | +- `KingSafety.java` (engine_core_src_main_java_coeusyk_game_chess_core_eval_kingsafety): cohort overlap 0.01 |
| 73 | +- `.setEvaluatorStrategy()` (engine_core_src_main_java_coeusyk_game_chess_core_search_searcher_searcher_setevaluatorstrategy): cohort overlap 0.01 |
| 74 | +- `ClassicalEvaluator` (engine_core_src_main_java_coeusyk_game_chess_core_eval_classicalevaluator_classicalevaluator): cohort overlap 0.01 |
| 75 | +- `StaticExchangeEvaluator.java` (engine_core_src_main_java_coeusyk_game_chess_core_search_staticexchangeevaluator): cohort overlap 0.02 |
| 76 | +- `.contemptScore()` (engine_core_src_main_java_coeusyk_game_chess_core_search_searcher_searcher_contemptscore): cohort overlap 0.02 |
| 77 | +- ... and 475 more |
| 78 | + |
| 79 | +## New God Nodes (top 15 by degree) |
| 80 | +- None |
| 81 | + |
| 82 | +## Architectural cohesion |
| 83 | +- maintained (modularity 0.7850 -> 0.7869, delta +0.0019) |
| 84 | + |
| 85 | +## Architectural Boundary Report |
| 86 | +_`production` = src/main/*.java outside `DEBUG_ONLY_MAIN_CLASSES`; `debug` = NnueOracle.java (ADR-002). Test files are excluded — test-to-production coupling is normal and not a boundary risk. Edges are reported at whichever node granularity graphify attaches them to (class/method), grouped by owning file._ |
| 87 | + |
| 88 | +### production -> debug dependencies |
| 89 | +- No change |
| 90 | + |
| 91 | +### debug -> production dependencies |
| 92 | +- No change |
| 93 | + |
| 94 | +### cross-module dependency changes |
| 95 | +_See "Cross-module dependency changes" above._ |
| 96 | + |
| 97 | +### EvaluatorStrategy coupling changes |
| 98 | +- No change |
| 99 | + |
| 100 | +### Searcher coupling changes |
| 101 | +- No change |
| 102 | + |
| 103 | +### NnueEvaluator coupling changes |
| 104 | +- No change |
| 105 | + |
| 106 | +### FeatureExtractor coupling changes |
| 107 | +- No change |
| 108 | + |
| 109 | +### NnueNetwork coupling changes |
| 110 | +- No change |
| 111 | + |
| 112 | +### Frozen boundary verdict |
| 113 | +- UNCHANGED — no unapproved production -> debug edges introduced. |
| 114 | + |
| 115 | +## Narrative |
| 116 | + |
| 117 | +E-2's real content shows up exactly where expected and nowhere else. The graph's |
| 118 | +independent confirmation of this issue's Non-Scope: **Engine Architecture is |
| 119 | +unchanged (1584 -> 1584, +0/-0)** — zero Java files were touched, matching "no |
| 120 | +changes to `TextDatasetProvider`'s or `stockfish_label.py`'s own logic" and no |
| 121 | +Stage 3/self-play work. All real movement is in **Trainer Architecture (432 -> 478, |
| 122 | ++55/-9, net +46)**. |
| 123 | + |
| 124 | +The "newly introduced architectural bridge-node candidates" are precisely this |
| 125 | +issue's new deliverables and nothing else: `acquire()`, `_iter_records()`, |
| 126 | +`_to_record()`, `_open_source_stream()`, `stream_records()` (all |
| 127 | +`acquire_stage1_lichess.py`, the new Stage 1 acquisition driver), |
| 128 | +`validate_dataset_manifest()` (the new dataset-manifest validator), plus their |
| 129 | +test-scope counterparts (`test_acquire_stage1_lichess.py`, `_write_fixture()`) and |
| 130 | +the new `stockfish-label-e2-real.json` provenance doc node. No unexplained |
| 131 | +additions — every new bridge-node candidate maps directly to a file this commit |
| 132 | +actually added. |
| 133 | + |
| 134 | +**Degree-change table (`NNUE_PRD.md`, `ADR-006`/`ADR-007`/`ADR-010`, all -1 to -3): |
| 135 | +a known, expected side effect of the post-commit hook's own documented scope, not |
| 136 | +a real architectural regression.** Verified directly (not inferred from the table |
| 137 | +alone): before this commit, `docs_nnue_prd` carried 3 `references` edges to those |
| 138 | +three ADRs, extracted by an earlier *semantic* (LLM) pass. The installed |
| 139 | +post-commit hook rebuilds "code files only, no LLM needed" (its own header |
| 140 | +comment) — when it detected `NNUE_PRD.md` had changed, it correctly pruned that |
| 141 | +file's stale node data but has no LLM pass available to regenerate the semantic |
| 142 | +`references` edges, leaving the after-graph with only the 2 structurally-derivable |
| 143 | +edges (the inbound reference from the changelog, and the file's own `contains` |
| 144 | +edge to its title node). The PRD's actual prose still cites all three ADRs |
| 145 | +unchanged (`git diff` for this commit touches exactly one line, the Open Question 1 |
| 146 | +resolution) — this is the graph's semantic layer for one file going stale, not a |
| 147 | +change in the document's real content or any real decoupling from those ADRs. A |
| 148 | +future full or `--update` run with semantic extraction enabled (as this session did |
| 149 | +manually, mid-review, before the shrink-guard correctly refused to merge a |
| 150 | +scope-mismatched incremental result — see this issue's completion report) would |
| 151 | +restore these edges; the code-only hook alone cannot and was never expected to. |
| 152 | + |
| 153 | +No newly introduced dependency cycles, no cross-module dependency changes, no new |
| 154 | +God nodes. The Architectural Boundary Report is unanimous "No change" across every |
| 155 | +tracked row, including all `FROZEN_BOUNDARY_CLASSES`, and the frozen boundary |
| 156 | +verdict is **UNCHANGED** — this is the graph's independent confirmation of |
| 157 | +Invariant 8 (engine/trainer isolation) holding through this issue, on top of |
| 158 | +Invariant 1 (`DatasetProvider` isolation) and Invariant 6 (provenance chain) already |
| 159 | +verified directly (not just via the graph) elsewhere in this issue's completion |
| 160 | +report: `acquire_stage1_lichess.py` produces a manifest via |
| 161 | +`validate_dataset_manifest()`, never imports another `DatasetProvider`, and no edge |
| 162 | +from any of its new nodes to `TextDatasetProvider`/`StockfishLabeledProvider` |
| 163 | +appears anywhere in the after-graph. |
| 164 | + |
| 165 | +Modularity moved by a small, positive amount (0.7850 -> 0.7869, delta +0.0019) — |
| 166 | +within the same noise band every prior Phase D/E audit has established, and if |
| 167 | +anything slightly *more* cohesive, not less. The community-churn section (490 of |
| 168 | +3294 common nodes, 15%, flagged) was checked against this PR's actual file list |
| 169 | +before being dismissed as noise — the listed churned nodes (`MoveOrderer.java`, |
| 170 | +`Piece.java`, `KingSafety.java`, `StaticExchangeEvaluator.java`, etc.) are |
| 171 | +pre-existing, unrelated engine-core classes, matching every prior audit's pattern |
| 172 | +of Louvain re-clustering instability rather than real coupling change. |
| 173 | + |
| 174 | +Overall: an additive-only commit whose graph footprint is exactly its stated |
| 175 | +scope — nine new Python/doc nodes in Trainer Architecture, zero Engine Architecture |
| 176 | +change, zero boundary changes, zero cycles, zero cross-module drift, and one |
| 177 | +identified (not hidden) side effect of the code-only post-commit hook's own scope |
| 178 | +on a single pre-existing doc node, fully explained above rather than left as an |
| 179 | +unremarked anomaly in the degree-change table. |
| 180 | + |
0 commit comments