Split public links (About, Tutorial, Extend) and auth into two groups
with 2rem gap between them and the separator. Uses inline style gap
to avoid Tailwind CSS bundle gaps.
Auth link is now session-aware: shows "Sign out" (POST form with
DELETE override) when logged in, "Sign in" (href to NewSessionAction)
when not. Implemented via currentUserOrNothing @User in the layout.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
flex-col and flex-1 were absent from the compiled prod.css (Tailwind only
bundles classes that appeared in templates at build time; these were new).
The body ended up as flex-row, placing the top nav beside the sidebar
instead of above it.
Replace Tailwind layout-structural classes with inline styles on body and
the sidebar wrapper so the column layout is independent of the CSS bundle.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move all operational links out of the top nav and into a grouped left
sidebar (192px). Top nav retains only the inter-hub logo (left) and
About / Tutorial / Extend / Sign out (right). Sidebar groups:
Core, Governance, Intelligence, Platform, Registry, API & Market.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
IHP NameSupport cannot parse trailing-underscore field names at runtime.
orderByAsc #label_ in all four registry list actions (and the API V2
equivalents) crashed the page with ParseErrorBundle. Changed to orderByAsc
#name which avoids the NameSupport conversion path entirely.
textField #label_ in the four registry form views has the same issue.
Replaced with a plain <input> element that reads entry.label_ directly.
Logout <a href={DeleteSessionAction}> sent GET but IHP requires DELETE.
IHP includes methodOverridePost middleware, so a POST form with
_method=DELETE handles this correctly.
Also corrected the seed admin-user migration hash from bcrypt to the
pwstore-fast format (sha256|17|...) that IHP actually uses.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
StaticPagesController parseRoute' used endOfInput for "/", but IHP passes
the raw path string so the parser received "/" not "". Match it explicitly
with string "/" before endOfInput, consistent with all other routes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Int16→Int in score/stars functions; uuid-based readMay→UUID.fromText;
autoRefresh do-notation fix; id→\x->x ambiguity in HubRoutingRules;
MarketplaceDashboard replaced raw SQL with IHP query builder; optional
hub selector in TypeRegistry views via CanSelect (Text, Maybe Id) instance
added to Web.View.Prelude; import consolidations to Web.View.Prelude.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fixes 46 compile errors across 18 controllers and views:
- BridgeResponse missing from explicit import lists (Widgets, RequirementCandidates,
DecisionRecords, AgentDelegations) — dot-notation HasField resolution fails without
the type in scope under DuplicateRecordFields
- unId not in IHP v1.5 — replaced all fmap (Id . unId) with fmap coerce
- respondWith not in IHP — replaced with plain redirectTo in 5 controllers
- [hubId] list param to sqlQuery — replaced with (Only hubId) tuple
- deleteWhere not in IHP — replaced with query/filterWhere/fetch/deleteRecords
- fill @'["label"] mismatch — field is label_ in generated types, not label
- PersistUUID/toUUID (persistent-style) — replaced with (Only id)
- intercalate + jsonArrayTexts ambiguity in GovernanceTemplates — hid Index import,
removed local duplicates, added Data.Text (intercalate)
- Int16 not in scope in AntifragilityDashboard — changed to Int (score :: Int)
- typeArraySection type mismatch in HubCapabilityManifests/Edit — unified to [Text]
- renderForm arity mismatch — added action param to DecisionRecords/New.renderForm
- Missing qualified Data.Aeson import in AdaptiveThresholds
- Missing ?request::Request constraint in Api/V2/WidgetPatterns.renderJsonWithStatus
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix compilation errors across 6 controllers and 29 views: import cleanup,
ResponseException pattern for API auth, type fixes, unused import removal.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- CrossHubPropagation: IHP.Prelude.head returns Maybe a; use List.head
(Data.List.head, already imported qualified) for non-empty-guarded lists
- Sessions: currentUserOrNothing is pure Maybe, not IO; use case...of instead of >>=
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Sessions: replace raw authenticate/unsetSession with IHP login/logout/verifyPassword
- Widgets/New, Widgets/Show: consolidate imports to Web.View.Prelude
- Widgets/Show: unwrap Id newtype for childrenOf comparison, Double → Scientific in renderSignalValue
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Web/Controller/Prelude.hs (was missing; 8 controllers failed to import it)
- Add .ghci-core and scripts/compile-check-core to compile Layer 1+2 in
isolation without loading Main.hs or any controller/view (Layer 3)
- Fix Application/Helper/BottleneckDetector.hs: replace coerce :: Id' -> UUID
with unpackId (IHP Id' wraps a type family; Data.Coerce cannot cross it)
- Fix devenv.nix: add pkgs.nodePackages.tailwindcss so devenv process scripts
find the tailwindcss binary (devenv v2 builds scripts with only local packages)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Convert all remaining `<- paramOrNothing / param / paramOrDefault /
currentUserOrNothing` monadic binds to `let` — these functions are pure
(ImplicitParams-based) in IHP v1.5, so `<-` is a type error in an IO
do-block.
Controllers fixed:
AgentDelegations, AiGovernancePolicies, Annotations, ApiConsumers,
CollectiveProposals, DecisionRecords, DeploymentRecords,
HubCapabilityManifests, HubRoutingRules, InstitutionalKnowledge,
OutcomeCorrelations, RequirementCandidates, TypeRegistries,
WebhookSubscriptions, Widgets,
Api/V2/{Annotations,InteractionEvents,Token}
WebhookSubscriptions: remove orphaned `Right () ->` case arm that was
left inside a bare `unless` block (structural parse error).
Also carries forward all in-progress fixes from the working tree:
helpers (AgentBridge, ApiRateLimit, BottleneckDetector,
CrossHubPropagation, FrictionScore),
views (CanSelect instances, HSX lambda extraction, formFor wrappers),
env/build (envrc GHCi perms, flake.nix Tailwind + GHC resource limits,
static/app.css additional Tailwind output).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The last action still calling callClaudeApi directly. Now routes through
resolveAgent (task_type="policy_sensitivity") + checkGovernancePolicy +
callAgent, consistent with all other Phase 11 AI invocations. Adds
agentRegistrationId, tokensIn, tokensOut to the created AgentProposal and
handles blocked_by_policy the same way as the other 4 actions.
Remove callClaudeApi and its direct HTTP imports from
Application/Helper/Controller.hs — no longer referenced anywhere.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
FR-3 (async_execute_prompt): CollectiveProposals now invokes all agents
concurrently via callAgentsBatch → single bridge subprocess with
asyncio.gather. Latency scales with slowest agent, not sum.
FR-4 (BudgetTracker): AgentDelegations passes tokenBudget to bridge;
llm-connect enforces it natively via BudgetTracker in RunConfig.
BudgetExceededError is a first-class BridgeError variant with total/
consumed/requested fields surfaced to the operator.
FR-1 (LLMServer passthrough): bridge accepts optional serverUrl field;
if present, calls POST {serverUrl}/execute instead of spawning a new
adapter. Infrastructure ready for hot-agent pre-warming (no schema
change required).
AgentBridge.hs: adds callAgentsBatch, callAgentWithBudget,
BudgetExceededError constructor, bridgeErrorMessage helper, defaultRequest,
requestToJson. All controllers updated to use bridgeErrorMessage.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AdapterCompatibilityDashboardAction added to HubsController (AutoRefresh).
Five panels: adapter summary KPIs (active/draft/deprecated), widget coverage
bar (adapter-backed vs native IHP, breakdown per spec), active contracts in use,
unassigned widgets, active adapter spec table with widget counts. Linked from
hub Show page and global nav.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ihf-annotation-launcher.js: vanilla JS, no framework dependency. Scans DOM for
data-widget-id elements, injects Annotate trigger, opens inline form, POSTs to
/widgets/:widgetId/annotations. Works in React/Vue-rendered pages via
MutationObserver. Feature-gated by IHP_ANNOTATION_LAUNCHER=true env var
(Config.hs AnnotationLauncherEnabled, FrontController layout conditional).
Docs: docs/annotation-launcher.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CRUD for WidgetAdapterSpec (index, show, new/create, edit/update — status+notes only
after creation). Widget new/edit forms expose optional adapter_spec_id select.
Widget show page renders adapter badge with link to spec. Widgets controller
fetches adapter spec for show action.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
T02: EnvelopeEmissionContractsController (index+show, read-only); widgetEnvelope
helper validates against contract v1.0 required attributes with inline warning
on missing view-context; adapterStatusBadge helper added to Application.Helper.View.
T03: InteractionReportingContractsController (index+show, read-only); API endpoint
POST /api/v1/interaction-events with bearer token auth against hub.api_key,
contract v1.0 field validation, and 201/422/401 responses.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds Phase 6 tables: envelope_emission_contracts, interaction_reporting_contracts,
widget_adapter_specs. Adds adapter_spec_id FK to widgets and api_key to hubs.
Seeds v1.0 contracts in migration. Registers Phase 6 controller types and routes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds bounded AI support to the IHF governance loop. All AI outputs are
attributed (model_ref), reviewable (AgentReviewRecord), and reversible.
No autonomous decisions; no silent requirement promotion.
- T01: Schema — agent_proposals, agent_review_records,
confidence_annotations (migration 1743379200)
- T02: AgentProposalsController (index/show/accept/reject, idempotent
review guard), global nav "Agent" link
- T03: SummarizeClusterAction — Claude API cluster summary on widget show
- T04: DraftRequirementAction — AI requirement draft; acceptance creates
RequirementCandidate (human-gated)
- T05: DetectDuplicatesAction — duplicate_flag proposal on candidate show
- T06: DetectPolicySensitivityAction — policy_flag with
ConfidenceAnnotations per concern scope
- T07: ProposeImplementationAction — impl_proposal from decision show
- T08: AgentAuditDashboardAction — autoRefresh; KPI row, unreviewed queue,
recent proposals, attribution log matrix
- T09: integration tests, SCOPE.md updated, phase5-summary.md, flake.nix
adds http-conduit/aeson/string-conversions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>