generated from coulomb/repo-seed
B1 — Web/Controller/StaticPages.hs: LandingAction, CapabilitiesAction,
TutorialAction, ExtensionGuideAction (no auth guard)
B2 — Web/View/StaticPages/Landing.hs: hero, traceability chain, capability
grid, GAAF status bar, CTAs to capabilities and management UI
B3 — Web/View/StaticPages/Capabilities.hs: 12-phase capability map, GAAF
scorecard, API v1/v2 surface table, learning loop, type registry system
B4 — Web/View/StaticPages/Tutorial.hs: 6-step developer tutorial (widgets,
events, governance, deployment, learning, federation)
Web/View/StaticPages/ExtensionGuide.hs: 6-step hub extension guide
(HubCapabilityManifest, type registry, widgets, patterns, agents)
with GAAF rules summary
B5 — Web/Routes.hs: StaticPagesController manual routes; "/" → Landing,
"/capabilities", "/tutorial", "/extension-guide"
Web/Types.hs: StaticPagesController data type
B6 — Web/FrontController.hs: import StaticPagesController; register route
(last, catches root); nav adds About/Tutorial/Extend links and
separator; logo now links to LandingAction
B7 (deployment verification) remains pending until devenv up is available.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
151 lines
8.8 KiB
Haskell
151 lines
8.8 KiB
Haskell
module Web.View.StaticPages.ExtensionGuide where
|
|
|
|
import Web.View.Prelude
|
|
|
|
data ExtensionGuideView = ExtensionGuideView
|
|
|
|
instance View ExtensionGuideView where
|
|
html ExtensionGuideView = [hsx|
|
|
<div class="max-w-4xl mx-auto py-10 px-6">
|
|
<div class="mb-8">
|
|
<a href={LandingAction} class="text-sm text-indigo-600 hover:underline">← Home</a>
|
|
<h1 class="text-3xl font-bold text-gray-900 mt-3 mb-2">Domain Hub Extension Guide</h1>
|
|
<p class="text-gray-500">
|
|
How to build and register a domain hub extension: HubCapabilityManifest,
|
|
type registry entries, hub-owned widget types, and hub-scoped controllers.
|
|
</p>
|
|
</div>
|
|
|
|
{-- Overview --}
|
|
<section class="mb-10">
|
|
<h2 class="text-xl font-semibold text-gray-800 mb-3">Overview</h2>
|
|
<p class="text-gray-600 mb-3">
|
|
inter-hub provides the governance substrate. Domain hubs (dev-hub, ops-hub, fin-hub, sec-hub)
|
|
extend it by registering their own capability manifests and type discriminators.
|
|
This keeps core tables stable while allowing domain-specific specialisation.
|
|
</p>
|
|
<div class="bg-amber-50 border border-amber-200 rounded-lg p-4 text-sm text-amber-800">
|
|
<strong>GAAF Rule 2:</strong> New hub-owned types must be declared in the hub's
|
|
<code class="bg-amber-100 px-1 rounded">HubCapabilityManifest</code> before use.
|
|
Register via the Extensions admin UI before creating any hub-owned widget types.
|
|
</div>
|
|
</section>
|
|
|
|
{-- Step 1: Create a Hub --}
|
|
<section class="mb-10">
|
|
<h2 class="text-xl font-semibold text-gray-800 mb-3">{stepBadge "1"} Create a Hub</h2>
|
|
<p class="text-gray-600 mb-3">
|
|
Navigate to <a href={HubsAction} class="text-indigo-600 hover:underline">Management UI → Hubs</a>
|
|
and create a new hub. Each hub has a <code class="bg-gray-100 px-1 rounded text-sm">slug</code>
|
|
that will prefix its owned types (e.g. <code>dev.code-review</code>).
|
|
</p>
|
|
</section>
|
|
|
|
{-- Step 2: Register a HubCapabilityManifest --}
|
|
<section class="mb-10">
|
|
<h2 class="text-xl font-semibold text-gray-800 mb-3">{stepBadge "2"} Register a HubCapabilityManifest</h2>
|
|
<p class="text-gray-600 mb-3">
|
|
A <strong>HubCapabilityManifest</strong> is the DB-side contract for a domain hub.
|
|
Go to <a href={HubCapabilityManifestsAction} class="text-indigo-600 hover:underline">Extensions</a>
|
|
and create a manifest for your hub. Set status to <code class="bg-gray-100 px-1 rounded text-sm">active</code>.
|
|
</p>
|
|
<p class="text-sm text-gray-500">
|
|
The manifest includes: <code>hubId</code>, <code>manifestVersion</code>,
|
|
<code>capabilitySchema</code> (JSON), and an optional <code>apiEndpointBase</code>.
|
|
It is the anchor point for per-consumer API keys in Phase 9.
|
|
</p>
|
|
</section>
|
|
|
|
{-- Step 3: Register type discriminators --}
|
|
<section class="mb-10">
|
|
<h2 class="text-xl font-semibold text-gray-800 mb-3">{stepBadge "3"} Register Type Discriminators</h2>
|
|
<p class="text-gray-600 mb-3">
|
|
Before creating widgets of a new type, register the type in the appropriate registry.
|
|
Go to <a href={WidgetTypeRegistryAction} class="text-indigo-600 hover:underline">Registries</a>:
|
|
</p>
|
|
<ul class="text-sm text-gray-600 space-y-1 list-disc list-inside mb-3">
|
|
<li><strong>Widget Type Registry</strong> — new widget types your hub will own</li>
|
|
<li><strong>Event Type Registry</strong> — custom interaction event types</li>
|
|
<li><strong>Annotation Category Registry</strong> — custom annotation categories</li>
|
|
<li><strong>Policy Scope Registry</strong> — custom policy sensitivity scopes</li>
|
|
</ul>
|
|
<div class="bg-gray-50 border border-gray-200 rounded-lg p-4 text-sm text-gray-600">
|
|
Set <code>owner_hub_id</code> to your hub. Once registered, your hub-scoped code
|
|
can create widgets of that type and the type will appear in the marketplace.
|
|
</div>
|
|
</section>
|
|
|
|
{-- Step 4: Create widgets --}
|
|
<section class="mb-10">
|
|
<h2 class="text-xl font-semibold text-gray-800 mb-3">{stepBadge "4"} Create Widgets</h2>
|
|
<p class="text-gray-600 mb-3">
|
|
With the type registered, create widgets via the
|
|
<a href={WidgetsAction} class="text-indigo-600 hover:underline">Widgets</a> page
|
|
or the API:
|
|
</p>
|
|
<div class="bg-gray-900 rounded-lg p-4 text-sm font-mono text-green-400">
|
|
POST /api/v2/widgets<br/>
|
|
<span class="text-gray-400">{"{"} "name": "PR Review Widget",<br/>
|
|
"widgetType": "dev.code-review",<br/>
|
|
"hubId": "...",<br/>
|
|
"viewContext": "pull-request-sidebar" {"}"}</span>
|
|
</div>
|
|
</section>
|
|
|
|
{-- Step 5: Publish a widget pattern --}
|
|
<section class="mb-10">
|
|
<h2 class="text-xl font-semibold text-gray-800 mb-3">{stepBadge "5"} Publish a Widget Pattern (optional)</h2>
|
|
<p class="text-gray-600 mb-3">
|
|
If your widget design is reusable, publish it to the
|
|
<a href={MarketplaceDashboardAction} class="text-indigo-600 hover:underline">Widget Marketplace</a>.
|
|
Other hubs can adopt it and pin to specific versions. Patterns support
|
|
semantic versioning and adoption tracking.
|
|
</p>
|
|
</section>
|
|
|
|
{-- Step 6: AI agent integration --}
|
|
<section class="mb-10">
|
|
<h2 class="text-xl font-semibold text-gray-800 mb-3">{stepBadge "6"} Connect an AI Agent (Phase 11)</h2>
|
|
<p class="text-gray-600 mb-3">
|
|
Register an <a href={AgentRegistrationsAction} class="text-indigo-600 hover:underline">AgentRegistration</a>
|
|
for your hub, then create a
|
|
<a href={ModelRoutingPoliciesAction} class="text-indigo-600 hover:underline">ModelRoutingPolicy</a>
|
|
to route task types to specific models or agents.
|
|
Agents can draft Requirements, propose governance decisions, and participate in
|
|
CollectiveProposals.
|
|
</p>
|
|
</section>
|
|
|
|
{-- GAAF rules reminder --}
|
|
<section class="mb-10">
|
|
<h2 class="text-xl font-semibold text-gray-800 mb-3">GAAF Architecture Rules (Summary)</h2>
|
|
<div class="space-y-2 text-sm">
|
|
{ruleBox "1" "Type discriminator columns must reference a registry table or carry a CHECK constraint. No bare TEXT for new type discriminators."}
|
|
{ruleBox "2" "New hub-owned types must be declared in the hub's HubCapabilityManifest before use."}
|
|
{ruleBox "3" "Core tables (widgets, interaction_events, annotations, hubs) must not have new columns without updating /contracts/core/."}
|
|
{ruleBox "4" "Append-only invariant on interaction_events and outcome_signals is permanent. Never bypass those triggers."}
|
|
</div>
|
|
</section>
|
|
|
|
<div class="flex gap-4 text-sm mt-6">
|
|
<a href={TutorialAction} class="text-indigo-600 hover:underline">← Developer Tutorial</a>
|
|
<a href={CapabilitiesAction} class="text-indigo-600 hover:underline">Full Capabilities →</a>
|
|
<a href={HubsAction} class="text-indigo-600 hover:underline">Management UI →</a>
|
|
</div>
|
|
</div>
|
|
|]
|
|
where
|
|
stepBadge n = [hsx|
|
|
<span class="inline-flex items-center justify-center w-7 h-7 rounded-full bg-indigo-600 text-white text-sm font-bold mr-2">
|
|
{n :: Text}
|
|
</span>
|
|
|]
|
|
ruleBox n desc = [hsx|
|
|
<div class="flex gap-3 bg-white border border-gray-200 rounded-lg p-3">
|
|
<div class="w-6 h-6 rounded-full bg-amber-100 text-amber-800 flex items-center justify-center text-xs font-bold flex-shrink-0">
|
|
{n :: Text}
|
|
</div>
|
|
<p class="text-gray-600">{desc :: Text}</p>
|
|
</div>
|
|
|]
|