nebari-dev / nebari-dev/nebari-frames
Inheritance resolution: merge parent and child content with child priority
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 2
- Forks
- 1
- Avg merge
- 10h 55m
- Merged PRs (30d)
- 9
Description
Motivation
Inheritance is the core promise of Frames: a team Frame extends an org Frame and refines it. The resolver in backend/internal/frames/resolver.go currently walks the extends graph, honors excludes, detects cycles, dedupes diamonds - and then merges by concatenating bodies, ancestors first and the child's body last.
Concatenation is only a proxy for merging. The resolved Frame reads as a pile of documents rather than one document: a parent's rule and a child's contradicting rule both survive, and the reader (a model) has to infer that the later one wins from ordering alone. As inheritance chains get deeper, resolved output gets longer and more self-contradictory - the opposite of what a Frame is for.
Proposal
Make resolution a real merge where the child has priority and parent content is carried forward rather than duplicated:
- Merge on structure within the body rather than treating it as an opaque blob: content under the same heading merges, with the child's version taking precedence; content only the parent has is inherited; content only the child has is added.
- Child content overrides the corresponding parent content instead of appending after it. Where a genuine conflict cannot be resolved structurally, the child wins.
- Preserve the existing guarantees:
excludesstill prunes ancestors, diamonds still contribute once, cycles still error, unreadable ancestors still fail closed. - Keep the resolved output attributable enough to debug - an author looking at a resolved Frame should be able to tell which ancestor a piece of content came from (the web app's hierarchy view and
ResolvedPrevieware the consumers here).
Open questions
- What is the merge key? Markdown headings are the obvious candidate, but that makes heading text load-bearing and needs a defined answer for un-headed prose and for a child that renames a parent's heading.
- Should a child be able to explicitly remove an inherited section, as opposed to overriding it?
excludesprunes whole ancestors, not parts.
Acceptance criteria
- Overlapping content between a child and its ancestors resolves to the child's version, not both.
- Non-overlapping ancestor content is still inherited.
- Deep chains and diamonds resolve without duplicated content.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in backend/internal/frames/resolver.go and trace how resolved content reaches the web app's hierarchy view and ResolvedPreview. Define the merge behavior for headings, unheaded prose, renamed sections, removals, attribution, and unresolved conflicts before changing resolution. Done means child content wins, unique parent content remains, deep chains and diamonds avoid duplication, and existing excludes, cycle, and unreadable-ancestor behavior is preserved.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 28/100