diff --git a/docs/BACKLOG.md b/docs/BACKLOG.md index e3e4983bc..5bb1eeae0 100644 --- a/docs/BACKLOG.md +++ b/docs/BACKLOG.md @@ -268,6 +268,16 @@ are closed (status: closed in frontmatter)._ - [ ] **[B-0472](backlog/P1/B-0472-mirror-beacon-two-axis-classification-matrix-2026-05-14.md)** Mirror/Beacon two-axis classification matrix — classify all repos on Axis 2 - [ ] **[B-0473](backlog/P1/B-0473-mirror-beacon-promotion-gate-protocol-2026-05-14.md)** Mirror→Beacon promotion gate protocol — concrete criteria for repo-level graduation - [ ] **[B-0474](backlog/P1/B-0474-mirror-beacon-axis-adr-2026-05-14.md)** Mirror/Beacon axis ADR — two-axis design decision (extends 2026-04-22 ADR) +- [ ] **[B-0475](backlog/P1/B-0475-axis3-prior-art-substrate-consistency-audit-2026-05-14.md)** Axis-3 prior-art audit — verify three-axis substrate composes without conflict +- [ ] **[B-0476](backlog/P1/B-0476-github-ruleset-divergence-audit-2026-05-14.md)** GitHub ruleset divergence audit — survey rulesets across repos; identify smell signals +- [ ] **[B-0477](backlog/P1/B-0477-axis3-code-english-classification-matrix-2026-05-14.md)** Axis-3 Code/English classification matrix — per-repo two-tier classification with engineering-docs exception +- [ ] **[B-0478](backlog/P1/B-0478-formal-verification-repo-split-evaluation-2026-05-14.md)** Formal-verification sub-axis evaluation — per-property-class split vs co-locate decision +- [ ] **[B-0479](backlog/P1/B-0479-axis3-adr-code-english-formal-verification-design-2026-05-14.md)** Axis-3 ADR — Code/English + formal-verification three-axis design decision +- [ ] **[B-0480](backlog/P1/B-0480-dbpedia-library-choice-adr-prior-art-audit-2026-05-14.md)** DBpedia B-0428.1 — library-choice ADR (dotNetRDF vs RDFSharp) + prior-art audit +- [ ] **[B-0481](backlog/P1/B-0481-dbpedia-fsharp-project-scaffold-nuget-connectivity-2026-05-14.md)** DBpedia B-0428.2 — F# project scaffold + NuGet add + connectivity smoke test +- [ ] **[B-0482](backlog/P1/B-0482-dbpedia-sparql-fsharp-ce-computation-expression-2026-05-14.md)** DBpedia B-0428.3 — SPARQL F# computation expression (query authoring CE) +- [ ] **[B-0483](backlog/P1/B-0483-dbpedia-hkt-mdm-entity-bindings-dv2-hub-satellite-2026-05-14.md)** DBpedia B-0428.4 — HKT-MDM entity bindings + DV2.0 hub-satellite types +- [ ] **[B-0484](backlog/P1/B-0484-dbpedia-end-to-end-demo-project-2026-05-14.md)** DBpedia B-0428.5 — end-to-end demo project + integration test ## P2 — research-grade diff --git a/docs/backlog/P1/B-0428-dbpedia-direct-dotnetrdf-fsharp-ce-hkt-mdm-canonical-demo-aaron-2026-05-13.md b/docs/backlog/P1/B-0428-dbpedia-direct-dotnetrdf-fsharp-ce-hkt-mdm-canonical-demo-aaron-2026-05-13.md index 6cdb9fce9..d04881265 100644 --- a/docs/backlog/P1/B-0428-dbpedia-direct-dotnetrdf-fsharp-ce-hkt-mdm-canonical-demo-aaron-2026-05-13.md +++ b/docs/backlog/P1/B-0428-dbpedia-direct-dotnetrdf-fsharp-ce-hkt-mdm-canonical-demo-aaron-2026-05-13.md @@ -1,12 +1,18 @@ --- id: B-0428 priority: P1 -status: open +status: decomposed title: "DBpedia via direct dotNetRDF + F# CE — HKT-MDM canonical demo (Path B, do now)" type: feature origin: Aaron 2026-05-13 (autonomous-loop substrate cascade) created: 2026-05-13 -last_updated: 2026-05-13 +last_updated: 2026-05-14 +children: + - B-0480 + - B-0481 + - B-0482 + - B-0483 + - B-0484 composes_with: - B-0043 - memory/feedback_aaron_dbpedia_is_free_master_data_human_curated_fsharp_type_provider_archived_resurrect_for_hkt_mdm_canonical_demo_fork_fsharp_compiler_for_ai_safety_real_hkt_over_clifford_2026_05_13.md @@ -170,6 +176,21 @@ HKT over Clifford), open a separate backlog row for: - Composes with this row's direct-API substrate (transition path documented in this row's ADR) +## Decomposition (Otto, 2026-05-14) + +This row was too broad to implement atomically. Decomposed into 5 dependency-ordered +child rows: + +| Row | Title | Type | Depends on | +|-----|-------|------|------------| +| [B-0480](B-0480-dbpedia-library-choice-adr-prior-art-audit-2026-05-14.md) | Library-choice ADR + prior-art audit | research (gate) | — | +| [B-0481](B-0481-dbpedia-fsharp-project-scaffold-nuget-connectivity-2026-05-14.md) | F# project scaffold + NuGet + connectivity smoke | feature | B-0480 | +| [B-0482](B-0482-dbpedia-sparql-fsharp-ce-computation-expression-2026-05-14.md) | SPARQL F# computation expression | feature | B-0481 | +| [B-0483](B-0483-dbpedia-hkt-mdm-entity-bindings-dv2-hub-satellite-2026-05-14.md) | HKT-MDM entity bindings + DV2.0 hub-satellite | feature | B-0482 | +| [B-0484](B-0484-dbpedia-end-to-end-demo-project-2026-05-14.md) | End-to-end demo project (closes B-0428) | feature | B-0483 | + +**Work on B-0480 first.** All subsequent rows depend on the library-choice ADR. + ## Composes with - B-0043 (universal-company-government-information-substrate) diff --git a/docs/backlog/P1/B-0480-dbpedia-library-choice-adr-prior-art-audit-2026-05-14.md b/docs/backlog/P1/B-0480-dbpedia-library-choice-adr-prior-art-audit-2026-05-14.md new file mode 100644 index 000000000..90b37bfe1 --- /dev/null +++ b/docs/backlog/P1/B-0480-dbpedia-library-choice-adr-prior-art-audit-2026-05-14.md @@ -0,0 +1,96 @@ +--- +id: B-0480 +priority: P1 +status: open +title: "DBpedia B-0428.1 — library-choice ADR (dotNetRDF vs RDFSharp) + prior-art audit" +type: research +origin: B-0428 decomposition (Otto, 2026-05-14) +created: 2026-05-14 +last_updated: 2026-05-14 +parent: B-0428 +depends_on: [] +composes_with: + - B-0428 + - B-0481 + - B-0482 + - B-0483 + - B-0484 + - docs/backlog/P3/B-0043-universal-company-government-information-substrate.md + - memory/feedback_aaron_dbpedia_is_free_master_data_human_curated_fsharp_type_provider_archived_resurrect_for_hkt_mdm_canonical_demo_fork_fsharp_compiler_for_ai_safety_real_hkt_over_clifford_2026_05_13.md +--- + +# B-0480 — DBpedia library-choice ADR + prior-art audit + +**Gate row for B-0481..B-0484.** No code is written until this row closes. + +## Purpose + +1. Survey all prior-art in the codebase relevant to B-0428 (F# CE patterns, + existing SPARQL/RDF substrate, B-0043 scope). +2. Choose between **dotNetRDF 3.x** and **RDFSharp 3.x** via an ADR. +3. Document the Path-A (type-provider) transition plan in the same ADR so + future work knows the intended upgrade path. + +## Pre-start checklist + +Per `.claude/rules/backlog-item-start-gate.md`: + +- [ ] Survey existing F# CE patterns in `src/Core/Dsl.fs` (CircuitBuilder model) +- [ ] Check `Directory.Packages.props` for any existing RDF/SPARQL packages +- [ ] Read B-0043 to confirm demo scope alignment +- [ ] Walk `composes_with:` chain (B-0428, B-0043, PR #2913, PR #2915) +- [ ] Otto-364: WebSearch current NuGet download counts + GitHub star counts for + both libraries before asserting recency + +## Prior-art surfaces to audit + +| Surface | Path | What to verify | +|---------|------|----------------| +| F# CE model | `src/Core/Dsl.fs` | CircuitBuilder pattern — applies to SparqlBuilder | +| Package manifest | `Directory.Packages.props` | Confirm no RDF packages already present | +| B-0043 parent | `docs/backlog/P3/B-0043-*.md` | Scope of universal-business-templates | +| PR #2913 | GitHub | HKT-MDM universality — confirm `M<'T>` substrate shape | +| DV2.0 rule | `.claude/rules/dv2-data-split-discipline-activated.md` | Hub-satellite partition applies | +| Aaron's DBpedia memory | `memory/feedback_aaron_dbpedia_is_free_master_data_*.md` | Confirm Path A vs Path B ordering | + +## Evaluation criteria for library choice + +| Criterion | dotNetRDF 3.x | RDFSharp 3.x | +|-----------|---------------|--------------| +| Last NuGet publish | Verify via search | Verify via search | +| CI offline capability | Needs recording or mocking | Needs recording or mocking | +| SPARQL 1.1 query support | Yes | Yes | +| RDF-Star support | Yes (claimed) | Partial | +| API surface size | Large | Small/focused | +| F# ergonomics | Verify | Verify | + +**Use Otto-364 WebSearch to verify current NuGet activity before asserting.** + +## ADR output + +Path: `docs/DECISIONS/2026-05-14-dbpedia-library-choice-dotnetrdf-vs-rdfsharp.md` + +Must include: + +1. Decision: which library, version pinned +2. Rationale (table above filled in with current data) +3. CI strategy: how SPARQL queries are tested in CI (live endpoint / recorded + fixture / mock; offline-first preferred per `dotnet test` isolation requirement) +4. Path-A transition plan: when F# compiler fork lands, how to migrate from + direct-API CE (B-0482) to a proper type provider +5. Where in the solution the new project lives: `src/DBpedia/` under `Zeta.sln` + +## Definition of done + +- [ ] ADR written and merged at canonical path above +- [ ] CI strategy decision recorded in ADR +- [ ] Path-A transition plan recorded in ADR +- [ ] `composes_with:` pointers backfilled on B-0428 and B-0043 +- [ ] B-0481 can begin immediately after this merges (no remaining blockers) +- [ ] B-0480 status set to `closed` + +## Why P1 / gate + +All four implementation rows (B-0481..B-0484) depend on the library +choice. Executing the ADR first prevents throwaway implementation work +if the library choice flips mid-stream. diff --git a/docs/backlog/P1/B-0481-dbpedia-fsharp-project-scaffold-nuget-connectivity-2026-05-14.md b/docs/backlog/P1/B-0481-dbpedia-fsharp-project-scaffold-nuget-connectivity-2026-05-14.md new file mode 100644 index 000000000..5df3b4e23 --- /dev/null +++ b/docs/backlog/P1/B-0481-dbpedia-fsharp-project-scaffold-nuget-connectivity-2026-05-14.md @@ -0,0 +1,125 @@ +--- +id: B-0481 +priority: P1 +status: open +title: "DBpedia B-0428.2 — F# project scaffold + NuGet add + connectivity smoke test" +type: feature +origin: B-0428 decomposition (Otto, 2026-05-14) +created: 2026-05-14 +last_updated: 2026-05-14 +parent: B-0428 +depends_on: + - B-0480 +composes_with: + - B-0428 + - B-0480 + - B-0482 + - B-0483 + - B-0484 +--- + +# B-0481 — F# project scaffold + NuGet add + connectivity smoke test + +**Depends on B-0480 (library choice ADR must be closed first).** + +## Purpose + +Create the `src/DBpedia/` F# project, wire it into `Zeta.sln`, add the chosen +NuGet package (from B-0480's ADR), and prove the SPARQL endpoint is reachable +with a minimal query. Everything in B-0482..B-0484 builds on this foundation. + +## Pre-start checklist + +Per `.claude/rules/backlog-item-start-gate.md`: + +- [ ] Confirm B-0480 is `closed` and ADR is merged +- [ ] Read ADR to confirm library name + version + CI strategy +- [ ] Check existing project structure in `Zeta.sln` +- [ ] Confirm `Directory.Packages.props` does not already have the package + +## Work items + +### 1. New F# project + +``` +src/DBpedia/ + DBpedia.fsproj ← references the library from B-0480 ADR + Client.fs ← minimal SPARQL client wrapper +tests/DBpedia.Tests/ + DBpedia.Tests.fsproj + ConnectivityTests.fs ← smoke test(s) +``` + +`DBpedia.fsproj` must: + +- Target `net10.0` (matches existing projects) +- Reference chosen library (pinned version from ADR) +- Include in `Zeta.sln` + +### 2. Package manifest + +Add to `Directory.Packages.props`: + +```xml + +``` + +### 3. Minimal `Client.fs` + +A thin type over the library's SPARQL query client: + +```fsharp +module Zeta.DBpedia.Client + +// Opaque endpoint handle — keeps library leakage off the public surface +type Endpoint = private Endpoint of + +let dbpedia : Endpoint = ... +let query (endpoint: Endpoint) (sparql: string) : Result<..., DbspError> = ... +``` + +Error surface: `Result<_, DbspError>` per the repo-wide result-over-exception rule. + +### 4. CI strategy (per ADR) + +Implement whichever CI strategy the ADR chose: + +- **Recorded fixture** (preferred): capture one real DBpedia response; replay + in CI without network access +- **Live endpoint** (fallback): mark test `[]` + so the test is skipped by default; remove `Skip=` only when running locally against DBpedia + +The smoke test must: + +- Execute the query below (or recorded equivalent): + ```sparql + PREFIX rdfs: + SELECT ?label WHERE { rdfs:label ?label . FILTER (LANG(?label) = 'en') } + ``` +- Assert at least one `rdfs:label` result +- Pass under `dotnet test Zeta.sln -c Release` + +## Build gate check + +```bash +dotnet build -c Release # 0 warnings 0 errors +dotnet test Zeta.sln -c Release +``` + +Both must pass before PR opens. + +## Definition of done + +- [ ] `src/DBpedia/DBpedia.fsproj` added to `Zeta.sln` +- [ ] `tests/DBpedia.Tests/DBpedia.Tests.fsproj` added to `Zeta.sln` +- [ ] Chosen NuGet package in `Directory.Packages.props` +- [ ] Connectivity smoke test passes (live or recorded per ADR) +- [ ] `dotnet build -c Release` — 0 warnings 0 errors +- [ ] `dotnet test Zeta.sln -c Release` — all tests green +- [ ] B-0482 can begin immediately after this merges +- [ ] B-0481 status set to `closed` + +## Why P1 + +Foundation row: B-0482, B-0483, and B-0484 all add code on top of this project. +Establishing a green build with the library wired in de-risks all three. diff --git a/docs/backlog/P1/B-0482-dbpedia-sparql-fsharp-ce-computation-expression-2026-05-14.md b/docs/backlog/P1/B-0482-dbpedia-sparql-fsharp-ce-computation-expression-2026-05-14.md new file mode 100644 index 000000000..454019526 --- /dev/null +++ b/docs/backlog/P1/B-0482-dbpedia-sparql-fsharp-ce-computation-expression-2026-05-14.md @@ -0,0 +1,151 @@ +--- +id: B-0482 +priority: P1 +status: open +title: "DBpedia B-0428.3 — SPARQL F# computation expression (query authoring CE)" +type: feature +origin: B-0428 decomposition (Otto, 2026-05-14) +created: 2026-05-14 +last_updated: 2026-05-14 +parent: B-0428 +depends_on: + - B-0481 +composes_with: + - B-0428 + - B-0481 + - B-0483 + - B-0484 + - src/Core/Dsl.fs + - .claude/rules/fsharp-anchor-dotnet-build-sanity-check.md +--- + +# B-0482 — SPARQL F# computation expression + +**Depends on B-0481 (project + NuGet must be in place).** + +## Purpose + +Implement a `sparql { }` F# computation expression that lets callers author +SPARQL SELECT queries in a typed, composable way — without raw string +manipulation. This is the core CE row; all HKT-MDM bindings (B-0483) and the +demo (B-0484) consume this layer. + +## F# anchor + +The `CircuitBuilder` in `src/Core/Dsl.fs` is the reference implementation. +Key properties to mirror: + +- CE type is a delegate/reader over the endpoint context (analogous to + `CircuitM<'T> = delegate of Circuit -> 'T`) +- All builder methods are `inline` with `[]` where applicable +- Public surface returns `Result<_, DbspError>` — no exceptions on hot paths + +## Implementation outline + +### `Sparql.fs` — query model types + +```fsharp +module Zeta.DBpedia.Sparql + +type Prefix = { Alias: string; Uri: string } + +type SelectVar = string + +type WhereClause = + | IsA of subject: string * rdfType: string + | HasProp of subject: string * prop: string * var: string + | Filter of expr: string + +type SparqlQuery = { + Prefixes : Prefix list + Variables : SelectVar list + Where : WhereClause list +} +``` + +### `SparqlBuilder.fs` — CE builder + +```fsharp +module Zeta.DBpedia.SparqlBuilder + +open Zeta.DBpedia.Sparql + +// Accumulator threaded through the CE +type QueryState = { Prefixes: Prefix list; Vars: SelectVar list; Where: WhereClause list } + +type SparqlM<'T> = QueryState -> QueryState * 'T + +[] +type SparqlBuilder() = + member _.Yield(()) = fun s -> s, () + member _.Return(x) = fun s -> s, x + // prefix, select, where, filter operations + member _.prefix alias uri : SparqlM = ... + member _.select vars : SparqlM = ... + member _.where clause : SparqlM = ... + +let sparql = SparqlBuilder() +``` + +### `QueryRenderer.fs` — SparqlQuery → string + +Renders a `SparqlQuery` to a SPARQL 1.1 SELECT string. Pure function; no I/O. +This is the primary unit-testable surface. + +### Integration with `Client.fs` (from B-0481) + +```fsharp +let run (endpoint: Endpoint) (query: SparqlQuery) : Result = + query |> QueryRenderer.render |> Client.query endpoint +``` + +## Tests (`tests/DBpedia.Tests/SparqlCeTests.fs`) + +All tests are **pure** (no network): render a query and assert the SPARQL +string. Example: + +```fsharp +[] +let ``sparql CE produces correct PREFIX and SELECT`` () = + let q = sparql { + prefix "dbo" "http://dbpedia.org/ontology/" + select ["?name"] + where (IsA ("?person", "dbo:Person")) + } + let s = QueryRenderer.render q + test <@ s.Contains "PREFIX dbo:" @> + test <@ s.Contains "SELECT ?name" @> +``` + +At minimum: + +- PREFIX rendering test +- SELECT variable test +- WHERE clause (IsA, HasProp, Filter) tests +- Round-trip: render → parse → render produces identical string (if library + provides a parser; else skip) + +## Build gate + +```bash +dotnet build -c Release # 0 warnings 0 errors +dotnet test Zeta.sln -c Release +``` + +## Definition of done + +- [ ] `Sparql.fs` (query model) in `src/DBpedia/` +- [ ] `SparqlBuilder.fs` (CE builder) in `src/DBpedia/` +- [ ] `QueryRenderer.fs` (pure renderer) in `src/DBpedia/` +- [ ] `SparqlCeTests.fs` in `tests/DBpedia.Tests/` with ≥ 4 tests +- [ ] All tests pure (no network required) +- [ ] `dotnet build -c Release` — 0 warnings 0 errors +- [ ] `dotnet test Zeta.sln -c Release` — all tests green +- [ ] B-0483 can begin immediately after this merges +- [ ] B-0482 status set to `closed` + +## F# anchor check + +`dotnet build` IS the sanity check that the CE types compose correctly. +Per `.claude/rules/fsharp-anchor-dotnet-build-sanity-check.md`: build +passing = type-level claims validated. diff --git a/docs/backlog/P1/B-0483-dbpedia-hkt-mdm-entity-bindings-dv2-hub-satellite-2026-05-14.md b/docs/backlog/P1/B-0483-dbpedia-hkt-mdm-entity-bindings-dv2-hub-satellite-2026-05-14.md new file mode 100644 index 000000000..0780b0ca8 --- /dev/null +++ b/docs/backlog/P1/B-0483-dbpedia-hkt-mdm-entity-bindings-dv2-hub-satellite-2026-05-14.md @@ -0,0 +1,152 @@ +--- +id: B-0483 +priority: P1 +status: open +title: "DBpedia B-0428.4 — HKT-MDM entity bindings + DV2.0 hub-satellite types" +type: feature +origin: B-0428 decomposition (Otto, 2026-05-14) +created: 2026-05-14 +last_updated: 2026-05-14 +parent: B-0428 +depends_on: + - B-0482 +composes_with: + - B-0428 + - B-0482 + - B-0484 + - B-0043 + - .claude/rules/dv2-data-split-discipline-activated.md + - memory/feedback_aaron_ontology_hkt_applies_directly_to_master_data_every_company_has_one_human_lineage_2026_05_13.md + - memory/feedback_aaron_clifford_hkt_ontology_vocabulary_axis_basis_rudders_rotors_steering_cartographer_navigator_edge_mapper_world_model_civsim_edge_runner_5_control_structures_or_4_plus_meta_2026_05_13.md +--- + +# B-0483 — HKT-MDM entity bindings + DV2.0 hub-satellite types + +**Depends on B-0482 (SPARQL CE must exist).** + +## Purpose + +Bind DBpedia SPARQL results to the factory's HKT `M<'T>` substrate (PR #2913) +and apply the DV2.0 hub-satellite partition to the resulting types. This row +is the MDM (Master Data Management) layer — it turns raw SPARQL rows into +typed, DV2.0-structured F# entities. + +## DV2.0 partition design + +Per `.claude/rules/dv2-data-split-discipline-activated.md`, separate by +change rate: + +| DV2.0 type | DBpedia shape | Change rate | +|------------|---------------|-------------| +| **Hub** | Wikipedia article URI (stable business key) | Rare — stable across edits | +| **Satellite** | Named attributes (label, birth date, occupation, etc.) | Frequent — wiki edits | +| **Link** | Relationships between entities (e.g. Person → Organization) | Medium | + +## F# types to implement + +### `src/DBpedia/Entities.fs` + +```fsharp +module Zeta.DBpedia.Entities + +open System + +// ── Hubs (stable business keys) ────────────────────────────────────────── +[] +type PersonHub = PersonHub of uri: string +[] +type OrganizationHub = OrganizationHub of uri: string +[] +type EventHub = EventHub of uri: string + +// ── Satellites (versioned attributes) ──────────────────────────────────── +type PersonSatellite = { + Hub : PersonHub + Name : string + BirthDate : DateOnly option + Occupation : string option + AsOf : DateTimeOffset // revision timestamp (DV2.0 effective date) +} + +type OrganizationSatellite = { + Hub : OrganizationHub + Name : string + Founded : DateOnly option + Industry : string option + AsOf : DateTimeOffset +} + +type EventSatellite = { + Hub : EventHub + Label : string + Date : DateOnly option + Location : string option + AsOf : DateTimeOffset +} + +// ── HKT binding (factory M<'T> parametric over entity type) ────────────── +// M<'T> follows PR #2913 pattern — parametric wrapper that composes with +// the DV2.0 satellite, making each entity type a named "slot" in the MDM. +type M<'T> = { Entity: 'T } + +module Person = + let ofSparqlRow (hub: PersonHub) (row: SparqlRow) : Result = ... + +module Organization = + let ofSparqlRow (hub: OrganizationHub) (row: SparqlRow) : Result = ... + +module Event = + let ofSparqlRow (hub: EventHub) (row: SparqlRow) : Result = ... +``` + +`SparqlRow` is the result row type returned by `Client.query` (defined in B-0481). + +## Tests (`tests/DBpedia.Tests/EntityBindingTests.fs`) + +All tests are pure (use fixture rows, not network). For each entity type: + +- Happy-path binding from a valid SPARQL row +- Missing optional field → `None` (not an error) +- Missing required field → `Error DbspError` +- Hub URI round-trip: `PersonHub "http://dbpedia.org/resource/Alan_Turing"` renders + correctly in the SPARQL CE (compose with B-0482 query) + +At minimum 6 tests (2 per entity type). + +## FsCheck property + +```fsharp +[] +let ``Hub URI is preserved through satellite round-trip`` + (uri: NonEmptyString) = + let hub = PersonHub uri.Get + let row = ... // synthetic fixture + match Person.ofSparqlRow hub row with + | Ok sat -> sat.Hub = hub + | Error _ -> true // error case doesn't violate invariant +``` + +## Build gate + +```bash +dotnet build -c Release # 0 warnings 0 errors +dotnet test Zeta.sln -c Release +``` + +## Definition of done + +- [ ] `Entities.fs` in `src/DBpedia/` with hub + satellite types for 3 entities +- [ ] `ofSparqlRow` bindings for Person, Organization, Event +- [ ] `M<'T>` wrapper type present +- [ ] `EntityBindingTests.fs` with ≥ 6 tests + ≥ 1 FsCheck property +- [ ] All tests pure +- [ ] `dotnet build -c Release` — 0 warnings 0 errors +- [ ] `dotnet test Zeta.sln -c Release` — all tests green +- [ ] B-0483 status set to `closed` +- [ ] B-0484 can begin immediately after this merges + +## Why P1 + +Without the MDM binding layer the demo (B-0484) is just a raw SPARQL query +result dump, not an HKT-MDM canonical demonstration. This row is what makes +B-0428 a "canonical demo" rather than a connectivity spike. diff --git a/docs/backlog/P1/B-0484-dbpedia-end-to-end-demo-project-2026-05-14.md b/docs/backlog/P1/B-0484-dbpedia-end-to-end-demo-project-2026-05-14.md new file mode 100644 index 000000000..d11e1a0a0 --- /dev/null +++ b/docs/backlog/P1/B-0484-dbpedia-end-to-end-demo-project-2026-05-14.md @@ -0,0 +1,142 @@ +--- +id: B-0484 +priority: P1 +status: open +title: "DBpedia B-0428.5 — end-to-end demo project + integration test" +type: feature +origin: B-0428 decomposition (Otto, 2026-05-14) +created: 2026-05-14 +last_updated: 2026-05-14 +parent: B-0428 +depends_on: + - B-0483 +composes_with: + - B-0428 + - B-0483 + - B-0043 + - docs/backlog/P3/B-0043-universal-company-government-information-substrate.md + - memory/feedback_aaron_dbpedia_is_free_master_data_human_curated_fsharp_type_provider_archived_resurrect_for_hkt_mdm_canonical_demo_fork_fsharp_compiler_for_ai_safety_real_hkt_over_clifford_2026_05_13.md +--- + +# B-0484 — DBpedia end-to-end demo project + +**Depends on B-0483 (HKT-MDM bindings must exist). Closes B-0428.** + +## Purpose + +Wire together the full stack built in B-0481..B-0483 into an end-to-end +demo that: + +1. Constructs a SPARQL query using the `sparql { }` CE +2. Executes against DBpedia (live or recorded per ADR strategy) +3. Binds results to HKT-MDM entities (hub + satellite) +4. Demonstrates the DV2.0 hub-satellite separation visibly + +This is the "definition of done" deliverable for B-0428 and the canonical +demo that composes with B-0043 (universal-business-templates). + +## Demo shape + +A console app or xUnit integration test — whichever the ADR CI strategy +implies is more appropriate. + +### Preferred: xUnit integration test (recorded fixture) + +```fsharp +// tests/DBpedia.Tests/DemoIntegrationTests.fs +[] +module DemoIntegrationTests + +[] +let ``DBpedia master-data demo — persons with birthDate`` () = + let query = + sparql { + prefix "dbo" "http://dbpedia.org/ontology/" + prefix "rdfs" "http://www.w3.org/2000/01/rdf-schema#" + select ["?person"; "?name"; "?birth"] + where (IsA ("?person", "dbo:Person")) + where (HasProp ("?person", "rdfs:label", "?name")) + where (HasProp ("?person", "dbo:birthDate", "?birth")) + where (Filter "LANG(?name) = 'en'") + } + let result = query |> DBpedia.run Client.dbpedia + match result with + | Ok entities -> + entities |> List.iter (fun sat -> + printfn "Hub: %A Name: %s Born: %A" sat.Hub sat.Name sat.BirthDate) + Assert.True(List.length entities > 0) + | Error e -> + Assert.True(false, $"Query failed: {e}") +``` + +### Required output visible in CI / test output + +``` +Hub: PersonHub "http://dbpedia.org/resource/Alan_Turing" + Name: "Alan Turing" Born: Some 1912-06-23 + (DV2.0 satellite — attributes; Hub = stable Wikipedia URI) +``` + +The comment in the output (or in the test's assertion message) must explicitly +name the DV2.0 hub-satellite split so it reads as a canonical demo. + +### ADR appendix update + +Add a section to the ADR from B-0480: + +```markdown +## Path-A transition plan + +After the F#-compiler-fork-for-AI-safety ships real HKT over Clifford: + +1. Generate a type provider on `FSharp.TypeProviders.SDK` targeting DBpedia's + SPARQL endpoint. +2. Replace `SparqlBuilder.fs` CE with compile-time `dbpedia.Person` / + `dbpedia.Organization` type provider projections. +3. The `Entities.fs` hub-satellite types stay unchanged — the DV2.0 partition + is library-agnostic. +4. Migration guide: swap `open Zeta.DBpedia.SparqlBuilder` → `open DBpedia.TP`. +``` + +## Composes-with B-0043 check + +Read `docs/backlog/P3/B-0043-*.md` and verify: + +- The demo query (persons / organizations) overlaps with B-0043's + "universal company + government information substrate" scope +- Add a pointer from B-0043 to B-0484 in `composes_with:` on both rows +- Write one sentence in the demo comment: _"DBpedia master data — canonical + demonstration for B-0043 universal-business-templates"_ + +## Build gate + +```bash +dotnet build -c Release # 0 warnings 0 errors +dotnet test Zeta.sln -c Release +``` + +CI runs `dotnet test Zeta.sln -c Release` with no category filter — every +test (including `[]` tests) runs by default. +The recorded fixture path is therefore required for CI safety: it replays a +captured response without network access. The live-endpoint fallback requires +an explicit workflow change (add `--filter "Category!=Integration"` to both +`gate.yml` and `low-memory.yml`) before it may be used. + +## Definition of done + +- [ ] End-to-end demo test in `tests/DBpedia.Tests/DemoIntegrationTests.fs` +- [ ] Demo test passes with recorded fixture or live endpoint per ADR +- [ ] Output visibly labels hub and satellite with DV2.0 language +- [ ] ADR from B-0480 updated with Path-A transition plan section +- [ ] B-0043 `composes_with:` backfilled with B-0484 pointer +- [ ] `dotnet build -c Release` — 0 warnings 0 errors +- [ ] `dotnet test Zeta.sln -c Release` — all tests green +- [ ] B-0428 status updated to `closed` with PR link +- [ ] B-0484 status set to `closed` + +## Why P1 / closes B-0428 + +B-0484 is the only row that produces the externally-visible demo Aaron +named ("DBpedia HKT-MDM canonical demo"). Without it the four implementation +rows don't constitute a "canonical demo" — they're plumbing. This row +stitches them together and closes the parent row.