docs: CR-6 — README auf Core-Tier-Template (Badges/Topology/API/References)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
161
README.md
161
README.md
@@ -1,5 +1,162 @@
|
||||
# lib-core.api-discovery
|
||||
|
||||
Pure-Lua-Library for surface-discovery (extract `M.*` from Lua source) and README-parsing (extract documented API from markdown). Sandbox-safe — no FS, no side-effects. Used by Sporel's `--lint` CLI mode.
|
||||
Pure-Lua-Library für Surface-Discovery (extrahiert `M.*` aus Lua-Quelltext)
|
||||
und README-Parsing (extrahiert die dokumentierte API aus Markdown). Außerdem
|
||||
ein README-Struktur-Linter, der die API-Doc-Convention (ADR-0038) gegen die
|
||||
MUST-Sections eines Tiers prüft. Sandbox-safe — kein FS-Zugriff, keine
|
||||
Seiteneffekte. Verwendet vom Sporel-`--lint`-CLI-Modus.
|
||||
|
||||
Version: 0.1.0
|
||||
**Version:** 0.1.0
|
||||
**Lib-ID:** lib-core.api-discovery
|
||||
**Requires:** (none)
|
||||
**Tags:** api-discovery, lint, readme, surface, topology, tooling
|
||||
|
||||
## Topology
|
||||
|
||||
<!-- topology:start (auto-generated; do not edit) -->
|
||||
```mermaid
|
||||
graph LR
|
||||
this["lib-core.api-discovery"]
|
||||
```
|
||||
<!-- topology:end -->
|
||||
|
||||
Reine Lua-Lib ohne Dependencies und ohne `engine.*`-Aufrufe — daher kein
|
||||
`engine`-Knoten im Topology-Graphen (sandbox-safe per Design, damit der
|
||||
Linter im `--lint`-CLI-Modus ohne Engine-Kontext laufen kann).
|
||||
|
||||
## API
|
||||
|
||||
### `api-discovery.parse_lua_surface(source_string)`
|
||||
|
||||
**Syntax:** `parse_lua_surface(source_string: string) -> {public: string[], private: string[]}`
|
||||
|
||||
**Example:**
|
||||
```lua
|
||||
local ad = require("lib-core.api-discovery")
|
||||
local src = io.read_file("init.lua")
|
||||
local s = ad.parse_lua_surface(src)
|
||||
-- s.public == { "load", "create", ... }
|
||||
-- s.private == { "_normalize", ... }
|
||||
```
|
||||
|
||||
**Description:** Extrahiert die öffentliche und private Surface aus
|
||||
Lua-Quelltext. Konvention: `M.<name>` ist öffentlich, `M._<name>` privat.
|
||||
Erkennt beide Schreibweisen — explizite Zuweisung (`M.foo = function`) und
|
||||
Syntax-Sugar (`function M.foo`). Lua-Zeilenkommentare (`--` bis Zeilenende)
|
||||
werden vor dem Pattern-Matching entfernt, damit auskommentierte
|
||||
Forward-Compat-Stubs (z. B. `DEPRECATED-MVP`-Platzhalter) keine
|
||||
False-Positives erzeugen. Block-Kommentare (`--[[ ... ]]`) werden nicht
|
||||
behandelt (in Sporel-Lib-Code nicht verwendet). Dedupliziert über alle
|
||||
Namen. Liefert `{ public = [...], private = [...] }`.
|
||||
|
||||
### `api-discovery.parse_readme_api(markdown_string)`
|
||||
|
||||
**Syntax:** `parse_readme_api(markdown_string: string) -> {documented: string[]}`
|
||||
|
||||
**Example:**
|
||||
```lua
|
||||
local r = ad.parse_readme_api(readme_text)
|
||||
-- r.documented == { "bind", "unbind", ... }
|
||||
```
|
||||
|
||||
**Description:** Extrahiert die dokumentierten Funktionsnamen aus dem
|
||||
`## API`-Abschnitt eines READMEs. Sucht den Abschnitt zwischen `## API` und
|
||||
der nächsten H2-Überschrift und parst die H3-Header darin. Konvention: ein
|
||||
H3-Header öffnet mit einem Backtick, der Funktionsname folgt nach einem
|
||||
optionalen Namespace-Punkt — sowohl die namespaced-Form `ns.func(...)`
|
||||
(Capture `func`) als auch die namespace-lose Form `func(...)` werden
|
||||
erkannt. Dedupliziert; Pattern 2 matcht
|
||||
keine Namen, die Pattern 1 bereits erfasst hat. Fehlt der `## API`-Abschnitt,
|
||||
ist `documented` leer.
|
||||
|
||||
### `api-discovery.diff_surface(surface, readme)`
|
||||
|
||||
**Syntax:** `diff_surface(surface: {public: string[]}, readme: {documented: string[]}) -> {missing_docs: string[], stale_docs: string[]}`
|
||||
|
||||
**Example:**
|
||||
```lua
|
||||
local s = ad.parse_lua_surface(src)
|
||||
local r = ad.parse_readme_api(readme_text)
|
||||
local diff = ad.diff_surface(s, r)
|
||||
-- diff.missing_docs == öffentliche Funktionen ohne README-Eintrag
|
||||
-- diff.stale_docs == README-Einträge ohne öffentliche Funktion
|
||||
```
|
||||
|
||||
**Description:** Vergleicht die Code-Surface (`surface.public`) gegen die
|
||||
README-Dokumentation (`readme.documented`). `missing_docs` sind öffentliche
|
||||
Funktionen ohne dokumentierten Eintrag; `stale_docs` sind dokumentierte
|
||||
Einträge ohne korrespondierende öffentliche Funktion. Beide Listen sind
|
||||
alphabetisch sortiert.
|
||||
|
||||
### `api-discovery.grep_engine_calls(source_string)`
|
||||
|
||||
**Syntax:** `grep_engine_calls(source_string: string) -> string[]`
|
||||
|
||||
**Example:**
|
||||
```lua
|
||||
local calls = ad.grep_engine_calls(src)
|
||||
-- calls == { "engine.render.draw_rect", "engine.window.size", ... }
|
||||
```
|
||||
|
||||
**Description:** Extrahiert alle eindeutigen `engine.<namespace>.<func>`-Aufrufe
|
||||
aus Lua-Quelltext. Liefert ein dedupliziertes, alphabetisch sortiertes Array.
|
||||
Wird von `generate_topology_block` genutzt, um zu entscheiden, ob ein
|
||||
`engine.*`-Knoten in den Topology-Graphen aufgenommen wird.
|
||||
|
||||
### `api-discovery.generate_topology_block(manifest, engine_calls)`
|
||||
|
||||
**Syntax:** `generate_topology_block(manifest: {id: string, deps?: {id: string}[]}, engine_calls: string[]) -> string`
|
||||
|
||||
**Example:**
|
||||
```lua
|
||||
local manifest = { id = "lib-core.maps", deps = {} }
|
||||
local calls = ad.grep_engine_calls(src)
|
||||
local mermaid = ad.generate_topology_block(manifest, calls)
|
||||
-- mermaid == "graph LR\n this[\"lib-core.maps\"]\n engine[\"engine.*\"]\n this --> engine"
|
||||
```
|
||||
|
||||
**Description:** Generiert den Mermaid-Topology-Block aus Manifest +
|
||||
`engine_calls`. Der `this`-Knoten trägt die `manifest.id`. Für jede
|
||||
Dependency in `manifest.deps` wird ein Knoten plus `this --> dep`-Kante
|
||||
ausgegeben (die Dep-ID wird für den Mermaid-Variablennamen entschärft: `-`
|
||||
und `.` → `_`). Enthält `engine_calls` mindestens einen Eintrag, kommt ein
|
||||
`engine["engine.*"]`-Knoten mit `this --> engine`-Kante hinzu. Liefert den
|
||||
reinen Mermaid-Quelltext ohne Marker — der Aufrufer wrappt ihn in die
|
||||
`<!-- topology:start -->` / `<!-- topology:end -->`-Marker.
|
||||
|
||||
### `api-discovery.validate_readme_structure(markdown_string, tier)`
|
||||
|
||||
**Syntax:** `validate_readme_structure(markdown_string: string, tier: "core"|"engine"|"module"|"community") -> {missing_sections: string[], section_order_ok: boolean}`
|
||||
|
||||
**Example:**
|
||||
```lua
|
||||
local res = ad.validate_readme_structure(readme_text, "core")
|
||||
if #res.missing_sections > 0 or not res.section_order_ok then
|
||||
-- README verletzt die API-Doc-Convention
|
||||
end
|
||||
```
|
||||
|
||||
**Description:** Prüft die README-Struktur gegen die MUST-Sections des
|
||||
angegebenen Tiers.
|
||||
|
||||
- **`core`** verlangt: `H1`, `Badges` (ein `**Lib-ID:** lib-…`-Block),
|
||||
`Topology` (`## Topology`), `Topology-Block` (`<!-- topology:start`-Marker),
|
||||
`API` (`## API`) und `References` (`## References`).
|
||||
- **`engine`** verlangt dieselben Sections, lockert aber den Badges-Check auf
|
||||
eine beliebige fettgedruckte `**Key:**`-Zeile (die Engine ist keine Lib und
|
||||
trägt kein `Lib-ID:`, sondern `Version`/`License`).
|
||||
- **`module`** ersetzt `## API` durch `## Controls` + `## Demonstrates` und
|
||||
identifiziert über `**Module-ID:**` statt `**Lib-ID:**` (Module haben keine
|
||||
konsumierbare Public-API).
|
||||
- **`community`** erzwingt nichts (liefert ein leeres Ergebnis).
|
||||
|
||||
`section_order_ok` ist `true`, wenn `## API` vor `## References` steht
|
||||
(bzw. `## Demonstrates` vor `## References` im Module-Tier) — oder wenn
|
||||
keine der beiden Sections vorhanden ist. Liefert
|
||||
`{ missing_sections = [...], section_order_ok = bool }`.
|
||||
|
||||
## References
|
||||
|
||||
- API-Doc-Convention Spec: `meta/docs/superpowers/specs/2026-05-16-api-doc-convention-design.md`
|
||||
- ADR-0038 (API-Doc-Convention)
|
||||
- ADR-0001 (engine knows verbs, libs bring nouns)
|
||||
|
||||
Reference in New Issue
Block a user