Skip to content

D1032 — The dev test KBs take the shape of measured real KBs, with invented content

Decision. The fleet make dev serves is eleven KBs: the 5,000-concept scale KB and the 30-concept bare KB as before (D818), and nine KBs whose shape is a table of numbers measured on a real multi-KB instance (internal/testkbs/profiles.go: Maps and journals, expanded concepts and their satellites, concept sizes, links, hubs, status mix, assets, artifacts, history) and whose content is invented around a neutral theme per profile (themes.go: seed-bank, ferry-line, …). The profile table is the only thing that enters the repository from the measured instance; the measuring script stays with the maintainer, and the real data is not needed to maintain the fleet. The output stays a pure function of the spec and the day.

Why. The formulas of D818 gave every KB the same uniform shape, so none of the Atlas bugs reported on real instances (a 490-entry journal, a concept with a hundred satellites, pages past 90 KB, a hub with 170 backlinks, thousands of commits on a few hundred concepts) reproduced on it. Numbers alone carry no privacy cost: no name, title, path, type, vocabulary or text of the measured instance is in the repository, and a test (TestProfiledKBsUseOnlyTheirOwnVocabulary) fails the build if a generated page holds a word outside the package's own tables, so a real name pasted in by mistake cannot reach a public revision (D259). What it costs: the fleet is bigger to generate, and the history of the largest profile (5,600 commits) is why it is written with git fast-import, one process per KB, instead of one git invocation per operation.

Alternatives rejected. - Keep the formula-built KBs and add outliers by hand. The extremes would be there but not the surroundings that make them bite (a big journal next to thin Maps, a status mix that is not 90 % active). - Anonymise a copy of the real KBs. Anonymising text is a filter, and a filter leaks: one forgotten name in a public repository is permanent (D259). Numbers from a script that emits nothing else cannot. - Generate from a random distribution tuned by eye. It would drift from what real instances look like; the table pins the target and a test checks each KB against it. - Keep the eight mid-size KBs (3,000 … 80 concepts). The nine profiles cover that range with real shapes; the extra KBs only cost generation time. - Spawn git per operation (D818). It does not scale to thousands of commits.

Consequences. - Every profile row is a contract: a test (profiles_test.go) generates each KB and reads it back through kb.Open, so a generator change that moves a number fails by name. Where a row cannot be met literally it is met in the closest way and recorded here: satellites are the pages inside an expanded concept and come on top of the Maps' concept counts; a profile with assets but no expanded concept (a bare asset needs an owner) gets one expanded concept without satellites. - The scale and bare KBs keep the formula path (plan()); the profiled ones have their own (planProfile); both share the file builders, the indexes, the artifacts and the local state. - Findings are planted on ferry-line only (an island, broken links, the defects of defects(), the conflicts), so the other profiles open with no finding but status_semantics, which the status mix puts there by design. - The privacy test reads every generated text file (concepts, Map contracts, text assets, paths.yaml, instructions.md) against the package's vocabulary tables plus a fixed list of English and scaffold words. It cannot catch a word pasted into the vocabulary tables themselves, which define what is allowed, and the tables of all themes are pooled, so one theme's words are allowed in another. Review changes to themes.go as a privacy matter (D259). - A new Atlas state must be planted somewhere in the fleet and checked by TestGeneratedKBShowsEveryPlantedState.