refactor(evidence): ontology-declared source roles replace named flags - #87
Merged
Merged
Conversation
GraphNodeMetadata's intentMissing/intentConflict/implementationMissing collapse into one role-agnostic missingRoles[]. validateEvidence checks presence only, blind to the role vocabulary. OntologyTypeValidator now also rejects a missingRoles entry the active ontology does not declare, the same allow-list check it runs for node and edge types. Neutralize the generic-mechanism fixtures (source, ontology, ontologies tests) to a test vocabulary. Drop the batch-plan v1 migration shim, the last intent/code literal in src; local workspace data was migrated in place. 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
Finishes decoupling the source-role taxonomy from the framework. The evidence model stops naming DDD's roles, and role references are now validated against whatever the active ontology declares. Closes the evidence half of #50 and the trust-model design of #68.
What changed
Evidence flags become one role-agnostic field.
GraphNodeMetadata.intentMissing/intentConflict/implementationMissingcollapse intomissingRoles: SourceRole[](the declared roles whose evidence is missing on this node), and the deadintentConflictflag is dropped.validateEvidence(a framework invariant) now checks presence only: a node needs asourceReferenceor a non-emptymissingRoles. It never names a role and cannot know the ontology's vocabulary. Its code is renamed toevidence.no-source-or-missing-roles.Role references are validated at the ontology layer.
OntologyTypeValidatoralready rejects a node/edgetypeoutside the active ontology's declared set. It now applies the same allow-list to a node'smissingRoles, emittingontology.unknown-source-role. The ontology is already loaded into the validation pipeline, so this is not a reverse dependency, it is the same graph-validation the types get.The last intent/code literal leaves src. The batch-plan v1-to-v2 migration shim (
intent/derivetodirect/derived) is dropped. Local~/.braidworkspace data was migrated in place, so the framework carries no legacy-format code.Fixtures. The generic-mechanism tests (
source,ontology,ontologies) move to a neutral test vocabulary (alpha/beta), proving the mechanism without naming DDD's roles.Design stance for #68 (trust / convergence without a ground-truth role)
Confirmation (acceptance 2): core does not hardcode a privileged role. Merge is blind last-write-wins (
Model.applyValidatedUpdate), drift is skill-authored and only surfaced byvalidateEvidence, andSourceRoleis an open branded string. No validator ranks one role as authoritative.The framework stays trust-neutral; trust is an ontology concern. The framework invariant checks structural presence. The ontology layer validates the role vocabulary. What a role means for trust (a ground-truth arbiter versus a non-authoritative claim) is the ontology's and its skills' policy, never the framework's.
Same-role sources conflicting on one node: split by disagreement level, not by role identity. Identity-level disagreement routes to a Clarification (human curation). Field-level disagreement is an ontology policy: an SSoT ontology makes the authoritative role win and records the rest as a
DriftIssue, while a no-SSoT ontology records the contradiction as a first-class state and does not force-merge.Recommended no-SSoT pattern. Model each claim as its own node (per-claim provenance for free), express agreement and disagreement as
corroborates/contradictsedges, derive confidence from that topology (skill or view computed), and escalate to a human selectively. This is fully expressible as a plugin today, with no framework change. Aconfidencenumber, per-field provenance, and acontradictsedge type are ontology-declared, not framework primitives, because "N agreeing sources equals true" is itself a trust policy the framework must not assume.#50 litmus outcome (honest note)
grep "'intent'|'code'|source-intent"outsideontology-dddis not literally zero, and that is expected. Every remaining hit is one of two legitimate kinds:response_type: 'code'/query('code'), andsourceId/namestring literals (proposal-preview,orphanReaper,sourceWebhooks).composeFsApp.test,batchRoutes,e2e,historyHooks,historyRoutes,showAll,cli/init. These exercisecomposeFsAppand the CLI, which intentionally bundle DDD as the coding preset, so DDD roles are the correct data there. Genuinely DDD-specific behavior lives inpackages/ontology-ddd/test.Core and schema are fully role-agnostic, so a third-party ontology declares its own roles and runs the whole loop with no edit to
@braidhq/coreor@braidhq/schema. The litmus's intent is met.Verification
pnpm typecheckgreen (15/15),pnpm lintclean.OntologyTypeValidatorrole-check tests), server 301, studio 100.~/.braidboots clean against the migrated batch-plan data.Closes #50
Closes #68
🤖 Generated with Claude Code