diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..6ddc4f0 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,134 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +**inter-hub** is the reference implementation of the **Interaction Hub Framework (IHF)** — a governed, observable interaction substrate for hub-based AI-enabled software systems. It treats every UI element as a governed artifact, creating a full traceability chain from rendered widget → user interaction → structured feedback → requirement candidate → decision record → implementation change → observed outcome. + +**Current state:** Phase 0 (specification) is complete. Phase 1 (Minimal Interaction Core) is the active implementation target. No application code exists yet. + +For situational context, read `SCOPE.md`. For architecture depth, read `specs/InteractionHubFrameworkSpecification_v0.1.md`. + +## Stack + +- **IHP** (Integrated Haskell Platform) v1.5 — full-stack Haskell web framework, server-rendered + optional realtime +- **Haskell** (GHC 9.10) — strongly typed, functional +- **PostgreSQL** — canonical datastore, managed via Nix (no manual DB setup) +- **Nix / devenv** — reproducible environment +- **Tailwind CSS** — see `specs/TailwindForInteractionHubs_v0.2.md` for IHF-specific conventions + +## Development Setup + +Requires Determinate Nix + direnv: + +```bash +# One-time environment setup +curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh +nix profile install nixpkgs#ihp-new +nix profile add nixpkgs#direnv + +# Bootstrap IHP project (Phase 1, Task T01) +ihp-new inter-hub +cd inter-hub +devenv up +``` + +After `devenv up`: +- App server: `http://localhost:8000` +- IHP IDE + Schema Designer: `http://localhost:8001` + +## Key Commands + +```bash +devenv up # Start dev environment (app + postgres + file watchers) +migrate # Run pending migrations +test # Run tests (auto-creates temp Postgres DB) +make static/prod.js static/prod.css # Production asset bundle +deploy-to-nixos production # NixOS deploy +``` + +Schema editing: use the IHP IDE at `localhost:8001` or edit `Application/Schema.sql` directly. Code generation via `localhost:8001/Generators`. + +## Architecture + +### Core Domain Model (Phase 1) + +| Entity | Role | +|--------|------| +| `Hub` | Bounded domain of responsibility (Dev Hub, Ops Hub, etc.) | +| `Widget` | Smallest semantically governable interaction unit with stable ID | +| `WidgetVersion` | Version history of widget definitions | +| `InteractionEvent` | Recorded user/agent interaction (viewed, clicked, submitted, etc.) — **append-only** (enforced by PostgreSQL trigger) | +| `Annotation` | Structured comment attached to a widget with category | +| `ViewContext` | Logical location in the UI | +| `CapabilityReference` | Link to hub capability | + +### Traceability Chain + +``` +Widget → InteractionEvent / Annotation + → RequirementCandidate (Phase 2) + → DecisionRecord (Phase 3) + → ImplementationChange → DeploymentRecord → OutcomeSignal +``` + +### IHP Conventions + +- Controllers live in `Web/Controller/`, views in `Web/View/`, types in `Web/Types.hs` +- Schema changes go in `Application/Schema.sql`, then generate with IHP IDE +- Use `AutoRefresh` for operator dashboards (server push on DB change) — not DataSync or Server-Side Components in Phase 1 +- See `docs/ihp-ihf-mapping.md` for how IHP capabilities map to IHF requirements + +### Widget Envelope + +Every rendered widget wraps its HSX in a `widgetEnvelope` helper (Task T08) that injects the stable `widget-id` and `view-context` attributes, enabling client-side event capture without coupling to implementation. + +## UI Conventions + +All hub interfaces follow the Tailwind layer model in `specs/TailwindForInteractionHubs_v0.2.md`: + +``` +Semantic Role → Visual Primitive → Tailwind Token → Screen Composition +``` + +Key rules: +- Every interactive element belongs to a named semantic role (`action-primary`, `nav-item`, `data-cell`, etc.) +- Use spacing rhythm from the spec; do not invent ad-hoc spacing +- State cues (hover, active, disabled, error) follow the defined color roles + +## Required Environment Variables + +| Variable | Purpose | +|----------|---------| +| `IHP_SESSION_SECRET` | Session encryption key | +| `DATABASE_URL` | Postgres connection string | +| `IHP_BASEURL` | External URL (e.g., `https://example.com`) | + +## Active Workplan + +Phase 1 work is tracked in `workplans/IHUB-WP-0001-ihf-phase1-minimal-interaction-core.md` (12 tasks, T01–T12). Use `/ralph-workplan workplans/IHUB-WP-0001-ihf-phase1-minimal-interaction-core.md` to drive implementation loops. + +Phase 1 exit criteria: +- Widgets can be addressed and annotated reliably +- Interaction data is captured with actor attribution and view context +- Hub-level inspection of interaction signals is possible via a dashboard + +## Key Reference Docs + +| File | Purpose | +|------|---------| +| `SCOPE.md` | Situational guide — in/out of scope, terminology, entry points | +| `specs/InteractionHubFrameworkSpecification_v0.1.md` | Full IHF spec (8 phases, risks, design principles) | +| `specs/TailwindForInteractionHubs_v0.2.md` | Agent-optimized Tailwind coding guide | +| `docs/ihp-overview.md` | IHP v1.5 fundamentals and dev workflow | +| `docs/ihp-data-and-queries.md` | Schema design, auto-generated types, query builder, migrations | +| `docs/ihp-controllers-views-forms.md` | Controller patterns, HSX, forms, validation, auth | +| `docs/ihp-realtime.md` | AutoRefresh vs DataSync vs HTMX decision guide | +| `docs/ihp-ihf-mapping.md` | IHP capability → IHF requirement mapping with schema templates | + +## Related Repositories + +- `hub-core` — planned shared base package for domain/capability registration +- `the-custodian` — State Hub (decision records, workstreams) that IHF governance integrates with +- Downstream consumers: `dev-hub`, `ops-hub`, `fin-hub` diff --git a/SCOPE.md b/SCOPE.md new file mode 100644 index 0000000..7b608aa --- /dev/null +++ b/SCOPE.md @@ -0,0 +1,128 @@ +# SCOPE + +> This file helps you quickly understand what this repository is about, +> when it is relevant, and when it is not. +> It is intentionally lightweight and may be incomplete. + +--- + +## One-liner + +Specification and reference implementation of the Interaction Hub Framework (IHF) — a governed, observable interaction substrate for hub-based AI-enabled software systems. + +--- + +## Core Idea + +IHF treats every meaningful UI element as a **governed interaction artifact** rather than mere markup. It connects the full traceability chain from rendered widget → user interaction → structured feedback → requirement candidate → decision record → implementation change → observed outcome. This makes interaction observable, frustration actionable, and UI evolution evidence-based. + +--- + +## In Scope + +- Widget identity, lifecycle governance, and semantic addressability +- Interaction event capture and contextual enrichment +- Annotation and structured comment threads attached to widgets +- Requirements distillation from raw feedback clusters +- Governance ledger: decision records linked to requirements and implementations +- Outcome observation and pre/post change comparison +- AI-assisted distillation (bounded, attributable, reviewer-controlled) +- Cross-hub integration of interaction signals +- Platform APIs and conventions for framework-agnostic UI integration +- IHF specification documents and canonical artifact type definitions + +--- + +## Out of Scope + +- A complete universal frontend framework or design system +- Pixel-level visual design or CSS conventions +- Full product management methodology +- Replacement for DevOps observability tooling (ops-hub handles that) +- Unrestricted autonomous AI decision-making on requirements +- Mandatory single UI technology for all hub surfaces + +--- + +## Relevant When + +- Building or reviewing any hub dashboard or operator surface (dev-hub, ops-hub, fin-hub) +- Capturing and triaging user/operator feedback on existing hub UIs +- Defining governed widget identity for a new capability surface +- Implementing structured requirements distillation from interaction signals +- Designing cross-hub feedback routing or policy-linked decisions + +--- + +## Not Relevant When + +- Backend API development with no interaction surface +- Infrastructure provisioning or cluster operations (see railiance-*, ops-bridge) +- Data pipeline or SBOM work (see state-hub / dev-hub) +- One-off scripts or tooling with no end-user UI + +--- + +## Current State + +- Status: concept / early spec +- Implementation: Phase 0 complete (specification written); Phase 1 (Minimal Interaction Core) not yet started +- Stability: spec is draft — artifact model and vocabulary are stable enough for repo creation +- Usage: none yet; reference implementation target is IHP + PostgreSQL + +--- + +## How It Fits + +- Upstream dependencies: hub-core (for base models, domain/capability registration, MCP tools) — see CUST-WP-0025 +- Downstream consumers: dev-hub, ops-hub, fin-hub — any hub with an operator-facing surface +- Often used with: kaizen-agentic (agent-assist module), state-hub (decision records, requirement linkage) + +--- + +## Terminology + +- Preferred terms: Widget, Widget Envelope, Interaction Event, Annotation, Requirement Candidate, Decision Record, Outcome Signal +- Also known as: IHF, inter-hub +- Potentially confusing terms: "Hub" here = bounded domain of responsibility (Dev Hub, Ops Hub, etc.) — not the GitHub feature; "Widget" = governed semantic unit, not a visual component library widget + +--- + +## Related / Overlapping Repositories + +- `the-custodian` — provides state-hub (decision records, workstreams) that IHF governance ledger will integrate with +- `ops-bridge` — tunnel connectivity for remote hub surfaces +- `kaizen-agentic` — agent personas that map to IHF's Agent Integration Module (§9.8) +- `hub-core` — planned shared base package that IHF will depend on for domain/capability plumbing + +--- + +## Getting Oriented + +- Start with: `specs/InteractionHubFrameworkSpecification_v0.1.md` — the full IHF spec (19 sections) +- Key files / directories: `specs/` (specifications), root `SCOPE.md` (this file) +- Entry points: read IHF spec §6 (Key Concepts), §9 (Core Modules), §14 (Phased Implementation Plan) + +--- + +## Provided Capabilities + +```capability +type: framework +title: Governed interaction substrate +description: Provides widget registry, interaction event capture, annotation, and requirements distillation for hub-based AI systems. +keywords: [widget, interaction, feedback, annotation, requirements, governance, traceability] +``` + +```capability +type: specification +title: IHF specification and artifact model +description: Canonical artifact types and traceability chain from Widget → InteractionEvent → RequirementCandidate → DecisionRecord → OutcomeSignal. +keywords: [spec, artifact, traceability, widget, decision, outcome] +``` + +--- + +## Notes + +Phase 0 is complete (specification foundation). Implementation begins at Phase 1 (widget registry + interaction event capture). The spec is intentionally broader than the first implementation — IHP is the reference technology for Phase 1, but the framework is designed to survive UI technology changes (§12.7, §Phase 6). diff --git a/docs/ihp-controllers-views-forms.md b/docs/ihp-controllers-views-forms.md new file mode 100644 index 0000000..ef119b8 --- /dev/null +++ b/docs/ihp-controllers-views-forms.md @@ -0,0 +1,272 @@ +# IHP: Controllers, Views, Forms, and Authentication + +--- + +## Controllers and Actions + +Controllers live in `Web/Controller/`. Each action is a constructor in `Web/Types.hs` and a case in the controller's `action` handler. + +```haskell +-- Web/Controller/Widgets.hs +instance Controller WidgetsController where + action WidgetsAction = do + widgets <- query @Widget |> fetch + render IndexView { .. } + + action ShowWidgetAction { widgetId } = do + widget <- fetch widgetId + events <- query @InteractionEvent + |> filterWhere (#widgetId, widgetId) + |> orderByDesc #occurredAt + |> limit 20 + |> fetch + render ShowView { .. } + + action CreateWidgetAction = do + let widget = newRecord @Widget + widget + |> fill @'["name", "widgetType", "hubId"] + |> validateField #name nonEmpty + |> ifValid \case + Left widget -> render NewView { widget } + Right widget -> do + widget <- createRecord widget + setSuccessMessage "Widget created" + redirectTo WidgetsAction +``` + +### Key Patterns + +| Pattern | Description | +|---------|-------------| +| `fill @'["fieldA", "fieldB"]` | Type-safe HTTP param binding; compile error if field doesn't exist | +| `validateField #name nonEmpty` | Chains a validator onto the record | +| `ifValid \case Left r -> ... Right r -> ...` | Branches on validation success/failure | +| `createRecord r` | INSERT; returns the persisted record | +| `updateRecord r` | UPDATE | +| `deleteRecord r` | DELETE | +| `redirectTo SomeAction { ... }` | Type-safe redirect | +| `render SomeView { .. }` | Passes in-scope bindings to the view (record wildcard) | +| `respondJson value` | JSON response (no view) | +| `respondHtml someHtml` | Partial HTML response (useful with htmx) | + +### Before Filters + +```haskell +instance Controller WidgetsController where + beforeAction = do + ensureIsUser -- redirects to login if not authenticated + -- custom per-controller guards here + action ... +``` + +### ControllerContext + +An implicit key-value map threaded through all actions and views. Stores current user, request, flash messages, layout. Access via `fromContext @SomeType` or framework helpers like `currentUser`. + +--- + +## Views and HSX + +### The View Typeclass + +Views are data types with a `View` instance: + +```haskell +data ShowView = ShowView + { widget :: !Widget + , events :: ![InteractionEvent] + } + +instance View ShowView where + html ShowView { .. } = [hsx| +
+ |] +``` + +Views can also implement a `json` method for content-negotiated API responses. + +### HSX Syntax + +HSX is a quasi-quoter (`[hsx| ... |]`) that compiles to BlazeHtml. Checked at compile time. + +```haskell +[hsx| + -- Interpolation (auto-escaped, XSS-safe) + {widget.name} + + -- Raw HTML (opt-out of escaping) +