Skip to content

feat(domain): family knowledge records — schema, invariants, Convex adapter, synthetic fixtures - #16

Merged
obvious-autobuild[bot] merged 1 commit into
masterfrom
feat/family-knowledge-schema
Sep 17, 2026
Merged

obvious-autobuild[bot] merged 1 commit into
masterfrom
feat/family-knowledge-schema

Conversation

@obvious-autobuild

Copy link
Copy Markdown
Contributor

Acceptance criteria

  • packages/domain/src/knowledge.ts defines a closed four-kind family-knowledge taxonomy (settling, routine, quote, preference) with source attribution, confidence, visibility, and validity windows — no medical kind, no invented conclusions
  • assertKnowledgeInvariants enforces: kind-specific data placement (quote text/speaker on quotes only, ordered non-empty steps on routines only), normalized kebab-case topics, superseded⇒validUntil / current⇒no validUntil / never-inverted windows, no self-supersession, confidence 1 reserved for caregiver-confirmed (model-recorded items can never reach it), mutually exclusive source attribution (entry vs conversation vs manual), manual items carry no source span
  • Convex knowledge table registered via the tested convexFields adapter, with household, child/topic, and supersession indexes
  • JSON Schema (draft 2020-12) tool contract derived with exactly the four kinds
  • Six synthetic fixture sets (settling corpus, routines, quotes, changing preferences with supersession chains, conflicting reports, invalid cases split by rejection layer) pass decode + invariants + round-trip + expectation checks
  • pnpm turbo run typecheck test build green; bun test ./security still green

What this is

The family-knowledge layer as a record type separate from logged events: durable, source-attributed statements about the household that don't happen at a single time the way events do. Settling preferences, routines, verbatim child quotes, and changing preferences; append-only supersession with validity windows; and deliberate conflict tolerance — multiple current items may share a topic and disagree, because conflicting caregiver reports are a family reality, not a data error.

Deliberately scoped out (per the schema proposal): medical conclusions, automatic conflict winners, and audience data on the item itself — visibility is draft|published, and audience resolution stays with household/relationship grants.

Relation to the Remember & Retrieve contract proposal (art_DUzlnxI9 v0.1)

Implements the shared core (separate record type, attribution, draft|published, append-only supersession) and extends it with topic slugs, kinds, confidence, and validity windows. Two flagged deltas for contract-fold reconciliation: this schema uses a forward supersedes edge (mirroring Event lineage) while the proposal uses a supersededById back-pointer; and it preserves sourceQuote alongside quoteText (verbatim words vs surrounding source wording).

Verification evidence

  • Tested head SHA: 673772c (branch feat/family-knowledge-schema, based on 32d1f00)
  • Focused suite: 17 pass / 127 assertions (bun test packages/domain/test/knowledge.test.ts)
  • Workspace: pnpm turbo run typecheck test — 9/9 tasks green on the working tree containing this commit
  • Security suite: bun test ./security — 17 pass / 0 fail at this SHA
  • CI on the pushed head SHA is the merge gate (note: branch predates the latest master commits; squash-merge will reconcile, or rebase on request before merge)

Review notes

…dapter, synthetic fixtures

Implements the family-knowledge layer as a record type separate from logged
events: source-attributed statements (statedBy/recordedBy/provenanceKind),
kind-specific data (quote verbatim text + speaker, routine ordered steps),
append-only supersession with validity windows, and conflict tolerance
(multiple current items may share a topic and disagree — no automatic winner).

- KnowledgeSchema (Effect v4, closed four-kind taxonomy: settling, routine,
  quote, preference — no medical kind; no invented conclusions)
- assertKnowledgeInvariants: kind-specific data placement, normalized kebab
  topics, supersession windows, self-supersession, confidence/provenance
  consistency (1 = caregiver-confirmed; the model may never claim it), and
  mutually exclusive source attribution
- knowledge table registered in the Convex schema via convexFields adapter
  (household/child/topic + supersession indexes)
- six synthetic acceptance fixtures: nominal settling/routine/quote corpora,
  supersession chains, conflicting reports, and ten negative cases split by
  rejection layer (decode vs invariants)

Relation to the Remember & Retrieve proposal (art_DUzlnxI9, v0.1): implements
the shared core — separate record type, attribution, draft|published, append-
only supersession — and extends it with topic slugs, kinds, confidence, and
validity windows; the supersedes forward edge (matching Event lineage) vs
their supersededById back-pointer is flagged for the v0.4 fold owner.
@obvious-autobuild

Copy link
Copy Markdown
Contributor Author

Independent review — verdict: fail (merge-blocked, rebase required) — code itself verified sound

Reviewed per the repo review→repair→merge workflow (acceptance criteria → full diff → independent verification at exact HEAD → checks). PR-owning thread keeps merge ownership; this review does not merge.

Tested SHAs: PR head 673772c (all local gates) · base/merge target now 652ace5 (master = v0.3 fold 00581f5 + PR #17) · scratch test-merge commit 4e42965 (branch review/test-merge-16, worktree /home/user/work/review-pr16 on the shared sandbox — kept as rebase reference).

Acceptance criteria check (stated in body — all six verified against code + tests)

  1. Closed four-kind taxonomy — ✅ KnowledgeKind = settling|routine|quote|preference; no medical kind (negative case "medical kind invented by extraction" rejected at decode layer).
  2. assertKnowledgeInvariants — ✅ kind-specific placement (quote: quoteText+spokenBy required, steps forbidden; routine: non-empty ordered steps required), kebab-case topic pattern, superseded⇒validUntil / current⇒never validUntil / windows never invert, self-supersession rejected on documents, confidence 1 reserved for caregiver-confirmed (model recorder can never reach it), mutually exclusive source attribution (entry/conversation/manual), manual items carry no source span.
  3. Convex knowledge table via tested adapter — ✅ tableFrom(KnowledgeFields) with by_household, by_child_topic, by_supersedes indexes; no hand-written field validators.
  4. JSON Schema draft 2020-12, exactly four kinds — ✅ test-asserted (dialect === "draft-2020-12").
  5. Six synthetic fixture sets — ✅ decode + invariants + round-trip + expectation loops over all six; invalid set split by rejectAt: "decode" | "invariants".
  6. Gates — ✅ re-run by reviewer, uncached: pnpm turbo run typecheck test build --force 9/9 (0 cached), bun test ./security 17/0, focused knowledge.test.ts 17 tests / 127 assertions — all at 673772c.

The four special checks

  • Stale-base / v0.3 drift — no semantic drift. knowledge.ts is additive and uses canonical idioms (convexId, satisfies Schema.Struct.Fields, reuses EntryVisibility for draft|published; no envelope/lineage duplication — correct, since knowledge records are at-rest records, not operation outputs). Empirically: reviewer test-merge of 673772c with current master 652ace5 typechecks and tests green (10/10 turbo tasks, 0 cached) after ONE trivial conflict resolution.
  • Event.authorId stays OPEN — ✅ zero authorId mentions in the diff; Event untouched; knowledge attribution is its own statedBy/recordedBy/provenanceKind. This PR does not settle that contract question. (The forward-supersedes and sourceQuote deltas are already dispositioned as fold positions — noted, not blocking.)
  • TS2769 — ✅ resolved at 673772c, verified directly (clean typecheck as-authored and post-merge). Earlier claims either way were stale.
  • Scope confinement — ✅ 10 files, all family-knowledge scope (domain module + barrel + tests + fixtures + the declared Convex table registration). No thin-path/catchup/evaluation contamination.

Blocking findings (2, same root cause)

  1. mergeable: CONFLICTING / mergeStateStatus: DIRTY — conflict with current master in packages/domain/src/index.ts (the PR's knowledge export block vs the v0.3 fold's lineage/contextEnvelope/operations barrel additions — same region, both-additions collision).
  2. CI has zero checks on this PR (rollup empty; repo Actions confirmed working — 16 runs, e.g. PR feat(domain): fold contract v0.3 — context envelope, operation outputs, lineage #14 rollup SUCCESS). Root cause: the pull_request workflow cannot build the merge ref while the PR conflicts. The body's expectation that "squash-merge will reconcile" no longer holds — GitHub cannot build a conflicting merge ref for squash either.

Required repair (owner, per rule 5 — repairs invalidate prior evidence)

Rebase feat/family-knowledge-schema onto origin/master (652ace5), resolving index.ts by keeping both export blocks (union — see scratch commit 4e42965 in /home/user/work/review-pr16 for the exact resolution). Then the owner re-runs the local gate table against the new HEAD, pushes, and CI runs green on the pushed head SHA. Re-review of the rebase delta expected to be trivial (barrel union only); after that this is a pass-with-notes PR. The six acceptance-criteria checkboxes in the body can be ticked by the owner once re-verified at the new HEAD.

— Independent reviewer thread (todo_CvG5gruV), verification only; no merge performed.

@obvious-autobuild
obvious-autobuild Bot force-pushed the feat/family-knowledge-schema branch from 673772c to 4a55019 Compare September 17, 2026 18:38
@obvious-autobuild

Copy link
Copy Markdown
Contributor Author

Independent review — re-review after rebase: verdict pass-with-notes (updated from fail; prior round at 673772c invalidated per rule 5)

Reviewer re-verification against the exact new head 4a55019 (rebased onto master 652ace5 — v0.3 fold 00581f5 + PR #17).

Rebase delta (rule 5 re-inspection)

Full git range-diff 32d1f00..673772c 652ace5..4a55019: the only content hunk changed by the rebase is packages/domain/src/index.ts — the knowledge export block repositioned after the v0.3 operations block, both sides kept as separate statements (the pre-agreed union). The backend/convex/convex/schema.ts hunk is context-only; every other file in the patch is byte-identical. Scope remains exactly the 10 family-knowledge files (1185 insertions) — no thin-path/catchup contamination introduced.

Local gates at 4a55019 (reviewer-run, uncached)

  • pnpm turbo run typecheck test build --force — 12/12 successful, 0 cached
  • bun test ./security — 17 pass / 0 fail
  • Focused packages/domain/test/knowledge.test.ts — 17 tests / 127 assertions / 0 fail

Matches the PR-owning thread's reported gate run exactly.

CI on the pushed head SHA

  • Check "Typecheck, test, build": SUCCESS — run 35260106834, pull_request event, head SHA 4a55019. Since the branch now sits directly on master 652ace5, the merge-ref head equals the pushed head SHA — both are 4a55019. PR state: mergeStateStatus: CLEAN, mergeable: MERGEABLE.

Review receipt

PR:               https://github.com/OCPdev25/obv-hackaton/pull/16
Tested head SHA:  4a55019 (post-rebase re-review; round 1 at 673772c invalidated by the rebase)
Review result:    pass-with-notes — independent reviewer thread (todo_CvG5gruV), 2026-09-17
Checks:           "Typecheck, test, build" SUCCESS on 4a55019 (run 35260106834; merge-ref head = pushed head)
Merge commit:     n/a — merge ownership stays with the PR-owning thread (own-owner precedent); reviewer does not merge
Post-merge smoke: n/a here — owner's evidence receipt to follow the merge
Unlocked tasks:   family-knowledge lane: merge per workflow (squash) when ready; contract-fold bookkeeping may treat family-knowledge as verified at 4a55019

Notes (non-blocking)

  1. The six acceptance-criteria checkboxes in the body remain unticked — all six verified by this review (round 1 code-read + test evidence, carried over: barrel was the only change). Owner may tick them at this SHA.
  2. The two flagged design deltas (forward supersedes edge, sourceQuote retained alongside quoteText) are unchanged and already dispositioned as fold positions in the Remember & Retrieve synthesis — no action.
  3. Event.authorId: re-confirmed untouched — zero authorId mentions; attribution modeled solely on the knowledge-record schema (statedBy/recordedBy/provenanceKind). The contract question stays open with its owner.

— Independent reviewer thread (todo_CvG5gruV); verification only, no merge performed.

@obvious-autobuild

Copy link
Copy Markdown
Contributor Author

Replying to the independent review receipt — all points addressed on branch feat/family-knowledge-schema:

  • Rebase done: head is now 4a55019 on top of 652ace5, pushed with --force-with-lease. The sole conflict was packages/domain/src/index.ts — resolved as the union (knowledge barrel kept as a separate export statement after the v0.3 fold's lineage/contextEnvelope/operations exports), matching the union resolution proven in your scratch merge.
  • Uncached local gates at the new head: pnpm turbo run typecheck test build --force — 12/12 tasks successful, 0 cached; bun test ./security — 17 pass / 0 fail; focused knowledge.test.ts — 17 pass / 127 assertions.
  • CI: registered and passing on the pushed head 4a55019 (Typecheck, test, build — run 35260106834).
  • Prior evidence at 673772c is superseded per repo rule 5; the evidence artifact (art_HGXGouCP) now carries the post-rebase table.

Prior results per your special checks carry over by construction (no diff beyond the barrel union): Event.authorId remains untouched, scope stays confined to the ten family-knowledge files, and the module remains additive against the v0.3 fold. Awaiting your delta re-verification at 4a55019; merge ownership holds with this thread per the sweep owner's dispatch.

@obvious-autobuild
obvious-autobuild Bot merged commit 0c65862 into master Sep 17, 2026
1 check passed
@obvious-autobuild

Copy link
Copy Markdown
Contributor Author

Replying to this comment

Delta verdict: pass-with-notes at 4a55019 — full re-review receipt in my re-review comment. Independently re-verified: full range-diff shows the barrel union as the only content delta (schema.ts hunk context-only, other 9 files byte-identical); uncached gates at the exact head — turbo 12/12 (0 cached), security 17/0, focused suite 17 tests / 127 assertions; CI run 35260106834 SUCCESS on the pushed head (merge-ref head = 4a55019); PR CLEAN/MERGEABLE. Event.authorId untouched; all six acceptance criteria verified. Merge ownership is yours per own-owner precedent — proceed per workflow (squash) and file the post-merge evidence receipt.

@obvious-autobuild

Copy link
Copy Markdown
Contributor Author

Evidence receipt — PR #16

PR:               https://github.com/OCPdev25/obv-hackaton/pull/16
Tested head SHA:  4a55019 (rebased onto 652ace5; prior head 673772c invalidated per rule 5)
Review result:    pass-with-notes — independent reviewer (todo_CvG5gruV / receipt art_EsLPwk3O,
                  comments 5719428176 + 5719456830), 2026-09-17. Round-1 fail at 673772c was the
                  dirty merge ref (zero CI checks), not code; delta re-verified at 4a55019
                  (range-diff: index.ts barrel union only, 9 files byte-identical).
Checks:           all green — CI "Typecheck, test, build" SUCCESS, run 35260106834 on 4a55019.
                  Reviewer-run uncached gates at 4a55019: turbo --force 12/12 (0 cached),
                  security 17/0, focused knowledge suite 17 tests / 127 assertions.
Merge commit:     0c65862 (squash on master; tree byte-identical to 4a55019)
Post-merge smoke: on 0c65862 — turbo typecheck/test/build 12/12 (cache hits valid: tree identical
                  to 4a55019, verified via empty diff), bun test ./security 17 pass / 0 fail,
                  focused knowledge.test.ts 17 pass / 127 assertions (fresh runs).
Unlocked tasks:   family-knowledge lane slot 23 (implementation + Convex table landed; functions
                  follow); contract v0.4 fold inputs — forward `supersedes` edge adopted over
                  supersededById back-pointer, sourceQuote as additive provenance, four-kind
                  taxonomy explicit adopt/reject; Event.authorId remains OPEN for the contract
                  owner.

obvious-autobuild Bot added a commit that referenced this pull request Sep 17, 2026
…ess cases (#31)

Write path (create + atomic append-only supersede) and bounded read path
(listCurrent/listHistory) over the knowledge table, composed from the PR #16
canonical contract in packages/domain — no domain changes. Supersession
enforces the fixture-grounded window rule (validUntil = successor's validFrom),
rejects forks, cross-household/cross-child targets, and invalid windows.

Authorization mirrors the security-suite reference policy: fail-closed
(household, child) tenancy checks on every function; publication dimension
(drafts recorder-only) enforced DB-side and re-checked post-decode; kind is
never an authorization input (KN-8 pins it). Stored rows decode through the
document contract before driving any decision.

Evidence (N1 standard — no local Convex runtime harness): strict typechecking
against the generated API, 17 validator-level tests over the pure logic with
the PR #16 fixtures as ground truth, 12 new executable access cases (29 total
in the security suite).

Co-authored-by: Obvious <obvious@obvious.ai>
Co-authored-by: Gilbert Polanco <gilbertpolanco42@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants