Conversation
9c34597 to
850c318
Compare
850c318 to
01efb62
Compare
01efb62 to
daed48f
Compare
daed48f to
eeed0b7
Compare
eeed0b7 to
661845b
Compare
661845b to
87a6a54
Compare
87a6a54 to
aa19efa
Compare
aa19efa to
47dbc6f
Compare
e127de0 to
4e9d478
Compare
01304dc to
ec4416b
Compare
|
Findings from CODEX: Findings
|
ec4416b to
af3ff70
Compare
|
All three addressed.
|
|
@jimador - looks like rebase is required, thx |
|
Yes, and it is in ff8e343. Pruning on read only helps a run somebody reads, so On the rebase: the branch is on current main, GitHub reports it clean. What it is showing is the stacked base, since #101 sits on #99, which sits on #98 and so on down to #91. It merges after those, and the stack tool moves each remaining branch onto main as the one below it lands. |
ff8e343 to
e506941
Compare
e506941 to
8fa72d8
Compare
Signed-off-by: James Dunnam <7660553+jimador@users.noreply.github.com>
Canonical persistence is now the only path: projection and grounding wire against what save returned whether or not a run is set, closing the split where the no-run path kept pre-save minted ids, and a run's only effect is the lineage write. That write runs last, so a STRICT failure leaves claims persisted, edges wired, projection and grounding complete, and no PRODUCED_BY_RUN — the operation reports failure and nothing claims a run produced the result. STRICT is the default where a run is set; LENIENT records the failure and continues, and both end states are tabled in the design doc. Duplicate links cannot form: the in-memory store guards on the pair and the Drivine store merges the edge, which Neo4j serialises on its endpoints. The run and link stores join the autoconfiguration under the graph condition, overridable and inert until a caller sets a run. Signed-off-by: James Dunnam <7660553+jimador@users.noreply.github.com>
The revision capability, run model, failure vocabulary, request object and protected-content specification entries now carry the EXPERIMENTAL marker and name their opt-in triggers. Signed-off-by: James Dunnam <7660553+jimador@users.noreply.github.com>
Registering the Drivine run store, the link store and the run schema under the graph condition alone wrote three constraints and five indexes into every graph-backed host on its next snapshot, for a feature nothing there calls. The three beans now sit behind embabel.dice.extraction.runs.enabled, default false, and the changelog says exactly what enabling writes to the database. Signed-off-by: James Dunnam <7660553+jimador@users.noreply.github.com>
recordRunLineage used to run last in persistAndProject, after structural wiring, projection and grounding had all completed. A projector or wirer that threw left the saved claims with no PRODUCED_BY_RUN edge, even though PersistablePropositions.persistCanonicalPropositions was split out specifically so a failing edge write could not strand a stored claim without a record of the run that produced it. Move recordRunLineage to right after persistCanonicalPropositions returns, before wireStructuralRelationships. A stored claim is now attributed the moment it exists. A STRICT lineage failure now leaves the claim saved and unattributed with the later passes never run; it used to leave a fully wired extraction missing only the audit edge. Rewrite the KDoc on persistAndProject and recordRunLineage to describe the new ordering and end state, invert RunLineageWiringTest's structural-wiring test to assert the claim is attributed before the failing pass runs, add the matching case for a throwing projector, and update the two lineage-failure end-state tests for the new declared state. Update docs/design/extraction-runs.md and the CHANGELOG entry for PR #101 to match. Signed-off-by: James Dunnam <7660553+jimador@users.noreply.github.com>
extractPropositions caught every exception from an event-published extraction and logged it at warn, so a LineageNotRecordedException under STRICT was lost on the async path while the same inputs on a direct call failed. It is now logged at error with the run key and rethrown, and the queue drain keeps going past a failing event and raises the first failure once the queue it can see is empty, so one wiring mistake costs no other event its turn. The policy KDoc, the design note and the changelog say what a host sees on each path. Signed-off-by: James Dunnam <7660553+jimador@users.noreply.github.com>
The in-memory link store is never told when a proposition is deleted, so a run kept naming ids that no longer resolved and the map only grew. Both reads now drop an id the proposition store no longer holds at all, and drop a run left with no links. A read from the wrong tenant still fails closed and touches nothing. Signed-off-by: James Dunnam <7660553+jimador@users.noreply.github.com>
Pruning on read only helps a run somebody reads. The in-memory link store now takes maxRuns, defaulting to 10,000 like the reference run store, and past it evicts the links of the runs linked earliest once the run store says they have ended. A run still running keeps its links, and a breach with nothing to evict logs once. Signed-off-by: James Dunnam <7660553+jimador@users.noreply.github.com>
8fa72d8 to
dbcb3ac
Compare
Slice 9 of the extraction-integrity train (#67), stacked on #99. A stored claim can now be traced to the run that produced it.
PropositionStore.saveAllReturningCanonicalandPersistablePropositions.persistReturningCanonicalare additive default-bodied calls returningPropositionPersistenceResult— the canonical proposition for each input, the input-id to stored-id mapping, and a distinct-by-canonical-id view; the result type rejects length mismatches, one input landing on two ids, per-position tenant mismatches, and one canonical id answered under two contexts.PropositionRunLinkStore(in-memory and Drivine, behind a 14-case cross-backend contract suite) writes aMERGE-idempotent(:Proposition)-[:PRODUCED_BY_RUN]->(:ExtractionRun)edge, tenant-guarded on both endpoints, with all-or-nothing batch writes proven inside the TOCTOU window. The headline invariant on Neo4j: two identical-content runs leave one proposition, one source grounding, and two run links. Lineage is recorded immediately after the claims are saved, before any fallible pass, so a throwing projector or grounding service leaves saved claims attributed and still propagates.Changed in this review round:
persistAndProjectused to take the repository's canonical propositions only when a run was present and the pre-save minted ones otherwise, which let an audit setting decide whether the graph was written correctly. It now wires projection, grounding and structural relationships against whatsavereturned on every call; a run's only effect is the lineage write. A mutation restoring the old no-run wiring fails three tests, projection-targets-a-pre-save-id among them.PRODUCED_BY_RUNedges cannot occur (MERGEon the pair, proven by the linking-twice case).ExtractionRun.invocationsnormalize to plan order at construction (the Extraction runs: the Drivine store #99 follow-up); stored fingerprints are unaffected.Breaking changes: none. Every existing public signature, descriptor and default-body behavior is byte-identical, pinned by a binary-compatibility test asserting the
@JvmOverloadssynthetic constructor descriptors (arities 9–16) survived. One behavioral change, sanctioned and on an unreleased experimental surface: the no-run extraction path now also persists, projects and grounds against canonical ids — the audit-metadata-never-changes-product-behavior rule, applied.Opt-in and status: EXPERIMENTAL, marked
@ApiStatus.Experimentalin code. The Drivine stores and the run schema DDL sit behindembabel.dice.extraction.runs.enabled(default false) alongside the graph backend condition; a host that never sets it gets no run beans and no constraints or indexes written, and the CHANGELOG names exactly what turning it on writes. Run attribution happens whenExtractionRequest.currentRunis set and aPropositionRunLinkStoreis bound; with neither, behavior is the canonical path alone. Honest limit, in shipped docs: lineage is best-effort for application-level failures only — a statement failing at the server inside a wrapping host transaction terminates that transaction beneath Spring, demonstrated by a fault-injection test; the structural fix (committing claims before recording lineage) belongs to the coordinator slice and the docs name it.The lineage shape. The root ref is denormalized onto every run, so a whole-lineage lookup is one indexed read, with no chain walk:
flowchart LR R[run A, pass 0, root = self] --> B[run B, pass 1, parent = A] B --> C[run C, pass 2, parent = B] B -. "root = A" .-> R C -. "root = A" .-> R PA[proposition] -->|PRODUCED_BY_RUN| C PB[proposition] -->|PRODUCED_BY_RUN| CChain walks stay bounded and cycle-safe, because the denormalized root is a read optimization and never the integrity check.
Landing
DiceStorageAutoConfiguration.ktconflicts too and is resolved by hand from the union worktree's committed adaptation, which also carries the runs gate on both schema beans.ExtractionRunSchemajoins the metamodel stack'sDiceStorageSchemaderived-ownership contract (object declaration,overrideonspecs(), bookkeeping relationship types, catalog and test beans).DiceStorageSchemaRegistrationTestfails until it is applied — that is the guard working.undoSingleCollapsestays as a deprecated overload (Source-revision provenance: authoritative collector fold and undo #92). Downstream callers move toCollapseUndoCommandwhen convenient.