feat: decouple intent/code from core (ontology-declared SourceRoles) - #82
Merged
Conversation
…ceRoles) Open SourceRole to an ontology-declared set so a third-party ontology runs the full loop without touching @braidhq/core or @braidhq/schema. - schema: SourceRole becomes an open branded string; BatchInputMode direct|derived; skill-input `source` provider is role-parameterized; OntologyResponse carries sourceRoles - core: SourceRoleDescriptor capability model (unitBearing drives batch + reactor); Workspace.sourcesWithRole replaces intent/codeSources - server: unitScan replaces intentScan; GET /ontologies catalog endpoint - studio: source-role UI driven by the active ontology, not hardcoded literals - ontology-ddd: declares intent|code as data Refs #50 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The server dev entry (tsx src/server.ts) crashed on boot with "WorkspaceId.openapi is not a function": startServer imports @braidhq/schema before @hono/zod-openapi loads, and zod 4's extendZodWithOpenApi is not retroactive, so branded types built first never gain .openapi(). Apply the extension inside @braidhq/schema itself, before any schema is built, so schema types are OpenAPI-ready for every consumer regardless of import order. Pre-existing break from the zod 4 migration, surfaced while running the e2e; independent of the source-role work. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Renaming BatchInputMode intent|derive to direct|derived broke existing persisted plans, workspace startup aborted with a ZodError on plan.mode. Bump BATCH_PLAN_VERSION to 2 and migrate legacy v1 plans on load (intent to direct, derive to derived), validating against the current schema afterward. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Decouples the hard-coded
intent/codesource taxonomy from core so a third-party ontology can declare its own source roles and run the full extract, propose, HITL, model, view loop without touching@braidhq/coreor@braidhq/schema. DDD becomes one ontology among several, declaringintent/codeas data.The guiding principle: the framework never branches on a role's identity, only on a capability the ontology declares for that role. The role name disappears from the framework; the capability stays.
What changed
schema
SourceRoleis now an open branded string (matching theLoaderKindprecedent) instead of a closedz.enum(['code','intent']).BatchInputModerenamedintent | deriveto role-agnosticdirect | derived.source-intentgeneralized tosourcewith arolefilter parameter.OntologyResponsecarriessourceRoles; newOntologyListResponse.core
SourceRoleDescriptorcapability model onOntologyPlugin(id,label,required,unitBearing,pathSegment) replacesrequiredSourceRoles.unitBearingis a single capability that drives both batch unit production and Reactor gating.Workspace.sourcesWithRole(role)replacesintentSources()/codeSources(); domain stays pure, the application layer resolves the ontology.BatchService.resolveMode,ReactorService.isUnitBearingSource, and the unit lister all read the declared capability, not a role literal.server
intentScanbecomes a genericunitScanfiltered by the ontology's unit-bearing roles.GET /ontologiescatalog endpoint (pre-workspace flows like the wizard);GET /ontologynow returnssourceRoles.sdk / ontology-ddd
SourceRole;defineOntologyPlugintakessourceRolesand merges an extended ontology's roles.intent(unit-bearing) andcodeas data.studio
Not in this PR
metadata.intentMissing/implementationMissingevidence flags encode a trust/corroboration model, not the source taxonomy, so they are left for design: trust / convergence model for domains with no privileged fact-SSoT #68 (trust / convergence for domains with no privileged fact source). They do not block this change: a non-software ontology's nodes carrysourceReferencesand never set them.Verification
pnpm typecheckgreen across all 15 packages.grep "'intent'|'code'|source-intent" packages/*/srchits onlypackages/ontology-ddd.@braidhq/test-utilsfixtures are role-neutral (primary/secondary); tests that exercise the real DDD ontology keepintent/codeas its declared vocabulary.examples/redoc-extending-ddd(used a non-existentdefineOntologyexport).Refs #50
🤖 Generated with Claude Code