engine/extensions/struct.py: ext.struct (typed records) — in-text frontmatter parse + ON_WRITE validation (allowed-fields, content-preserving), ON_READ tags PageShape.TYPED_RECORD, ON_PROFILE raises structured-payload. Proves the framework: feature absent when off (opaque prose, honest profile), present + profile-reflected when on; works through InformationSpace edit. SCOPE updated. 6 tests, 107 total, ~97% coverage, pyflakes clean. Marks T6 + SHARD-WP-0014 done. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6.4 KiB
id, type, title, domain, repo, status, owner, topic_slug, created, updated, depends_on, state_hub_workstream_id
| id | type | title | domain | repo | status | owner | topic_slug | created | updated | depends_on | state_hub_workstream_id | ||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| SHARD-WP-0014 | workplan | wiki-engine implementation — kernel + typed-extension runtime + activation | whynot | shard-wiki | done | tegwick | whynot | 2026-06-15 | 2026-06-15 |
|
bfce1644-d93d-44c7-af2c-6b0cb50cedd4 |
SHARD-WP-0014 — Wiki-engine implementation
Goal
Implement the native headless wiki engine specified in spec/WikiEngineCoreArchitecture.md:
a small page-store kernel + a stringent typed-extension runtime, with per-shard
activation (ADR-0001: via feature-control/OpenFeature, LocalProvider default), the engine's
§A capability profile derived from active extensions (E-5), and exposure as a
canonical-mode shard (EngineShardAdapter). Target capability: stand up an engine shard,
activate a chosen extension set, and attach it to an InformationSpace — its declared
capability profile reflecting exactly what is active — proven end-to-end with one real
built-in extension.
Non-goal (this slice): the headless network API protocol; git-IS-store backing (kernel uses the existing simple store now; git backing integrates with SHARD-WP-0009/0012 later); computational extensions; the full feature-control control plane. Build the framework, prove it.
Guiding rules (from WikiEngineCoreArchitecture)
- E-1 engine is one shard, not a federation layer. E-2 small kernel. E-3 everything-else is a typed extension. E-4 per-shard activation. E-5 capability profile derived from active extensions. E-8 reuse (feature-control activation; model/provenance/coordination/adapters). E-9 extensions are typed + conformance-verified.
- Honour the §11 dependency rule:
engine/consumesmodel/,provenance/,coordination/,adapters/,policy/; it is consumed only via itsEngineShardAdapter. No orchestrator-tier (union/,projection/) import. Pure-stdlib core; OpenFeature is an optional engine extra.
Engine kernel skeleton
id: SHARD-WP-0014-T1
status: done
priority: high
state_hub_task_id: "e81ba881-7e92-4581-99ff-b12ad2bcabb3"
src/shard_wiki/engine/kernel.py: the minimal kernel — a page store + lifecycle over existing
primitives (reuse model.Page/Identity/provenance; a simple in-memory/folder-backed store
now, git-IS-store later) and a recoverable history hook into the decision log. Kernel covers the
c2-minimum (create/read/edit-as-history; [[wikilink]]+red-link resolution can be a thin kernel
helper). No extensions yet. Tests: page CRUD-as-history; kernel-only shard works.
Typed-extension runtime
id: SHARD-WP-0014-T2
status: done
priority: high
state_hub_task_id: "8ae8e58a-f081-432b-b2c5-b6435fbf3843"
src/shard_wiki/engine/extension.py: the Extension contract (id, provides, types, hooks,
depends_on, conflicts_with, config), a registry, a typed hook dispatcher (typed
inputs/outputs, declared deterministic order), a type checker, and composition that
builds the dependency closure and rejects impossible profiles (conflicts / unmet deps /
incompatible types) — the §6.5 discipline for extensions. Extensions ship a conformance check
(mirrors §6.6). Tests: register/compose; deterministic hook order; impossible profile rejected;
conformance catches a lying extension.
Per-shard activation (feature-control / OpenFeature)
id: SHARD-WP-0014-T3
status: done
priority: high
state_hub_task_id: "c4fe9df4-e6a8-4b7d-891b-59ceec6aebac"
src/shard_wiki/engine/activation.py (ADR-0001): resolve a shard's activation profile
({extension id → config}) through an OpenFeature-shaped client with a static LocalProvider
default (standalone, zero external dep); context = {tenant_id: root, shard_id, …}; OpenFeature/
feature-control is an optional provider plugged in when present (degrade gracefully, mirror the
identity ladder). Availability only — never authorization. Tests: LocalProvider activates a
subset; absent-provider falls back to defaults; context scoping works.
Capability profile derived from active extensions (E-5)
id: SHARD-WP-0014-T4
status: done
priority: high
state_hub_task_id: "15fc8db7-cd80-4675-b387-81aa9bc7d308"
src/shard_wiki/engine/profile.py: fold the active extensions' on_profile contributions into a
§A CapabilityProfile (e.g. ext.struct active ⟹ structure spectrum rises + structured-payload
verb), then validate() + conformance. Tests: activating an extension changes the derived
profile; the derived profile is valid and conformance-passes.
EngineShardAdapter (engine as a canonical-mode shard)
id: SHARD-WP-0014-T5
status: done
priority: high
state_hub_task_id: "2fbf498c-efe9-400a-8a13-7f1b521b3534"
src/shard_wiki/engine/adapter.py: EngineShardAdapter implements adapters.ShardAdapter,
backed by the kernel + active extensions, declaring the derived profile (T4). Attach an engine
shard to an InformationSpace and read/resolve/edit through it like any shard. Tests +
integration: engine shard passes assert_conformant; attach → resolve → edit works.
First built-in extension (prove the framework end-to-end)
id: SHARD-WP-0014-T6
status: done
priority: medium
state_hub_task_id: "b88d1640-9afa-4957-aec3-a7264b09494c"
Implement one real extension end-to-end — ext.views (BackLinks) or ext.struct
(typed records) — binding kernel hooks, declaring types, contributing to the derived profile,
activatable per shard. Integration test: with the extension OFF the capability is absent (honest
profile); ON it works and the profile reflects it. Update SCOPE + spec/README; pytest +
pyflakes green.
Acceptance criteria
pytestgreen, pyflakes clean; engine core pure-stdlib (OpenFeature optional, behind the LocalProvider default).- The vertical slice works: stand up an engine shard, activate a chosen extension set, attach to
an
InformationSpace; the engine's declared §A profile matches the active extensions and passes conformance. - Module boundaries honour §11 (engine consumed only via
EngineShardAdapter; no union/projection import); E-1…E-9 respected. - Activation is availability-only (no authz); standalone path has no external dependency.
- Each task committed; state-hub synced.
Suggested task order
T1 kernel → T2 extension runtime → T3 activation → T4 derived profile → T5 EngineShardAdapter → T6 first extension + integration.