Skip to content

claims: two claims of one kind in one sentence get two uids (#125) - #210

Merged
ojungo69 merged 2 commits into
mainfrom
fix/uid-nth
Sep 28, 2026
Merged

ojungo69 merged 2 commits into
mainfrom
fix/uid-nth

Conversation

@ojungo69

@ojungo69 ojungo69 commented Sep 28, 2026 •

Copy link
Copy Markdown
Owner

Part of #125 (the Task 6 item: two claims in one sentence get two uids).

Why

A claim's uid is the hash of its kind and the sentence its first quote starts in (MUST-M18), so a recuration that rewords it derives the same uid. Two claims of one kind in one sentence therefore shared a uid. The later one's derivation became the active one, and the other claim was no longer shown. The dev arms' claim ops have such groups with quotes apart from each other: 2 in the full arm (290 claims), 5 in the whole arm (563) and 1 in the short arm (890). One of them held four proposals in one sentence, of which one was shown.

What (rewritten in round 2)

The first version numbered a sentence's claims by their order in one answer. Codex's round 1 showed why that cannot be an identity: the set of claims drafted with a claim changes between derivations. Model answers vary, the gates drop drafts, and a recuration finds one more claim. So a number moved from one claim to another. This version keys a claim by where it starts, and a claim already derived keeps its key:

  • Evidence.claim_at: Option<i64>, on a claim's first quote, and a new claim_at column of the evidence table (added to an older knowledge.db, empty, as its ops had none). claims::uid adds it when present, and the op leaves it out when it is None. So a claim alone in its sentence keeps the uid it always had, and every op written before this change keeps its uid.
  • curate::keyed, when an answer's drafts are located and before the gates. Per kind and sentence:
    • drafts whose quotes overlap are one claim drafted twice (the gates' sibling rule);
    • a claim whose quote overlaps a claim already derived in that sentence takes that claim's value, so its uid stays whatever else is drafted with it;
    • the first claim of a sentence where no derived claim holds None gets None;
    • any other claim gets its own start in the event, which does not depend on the window.
  • The lookup runs once, when the op is written, on the device that owns the records. The consumer still computes a uid from the op alone, so a rebuild or a synced device gets the same uids.
  • A recuration's retraction takes claim_at from the evidence table with the rest of the quote, so it retracts the claim it leaves out (round 1, first finding).

Limit: two windows of one recurate span are sent before the consumers run, so a claim in the second window does not see one drafted in the first. That needs a sentence longer than a window, sent again, with same-kind claims in both parts. The curation phase runs the consumers between windows.

Tests

  • two_decisions_in_one_sentence_get_two_uids_and_keep_them_on_recuration: three drafts, two of which overlap, give two uids. A recuration with both claims reworded and in the other order keeps both.
  • a_recuration_retracts_the_proposal_it_leaves_out_of_a_sentence: the second proposal is retracted, and the first stays.
  • a_claim_found_earlier_in_a_sentence_leaves_the_uid_of_the_one_there: a recuration that finds a new earlier claim leaves the old claim's uid, and with it the owner's corrections of it.
  • claims_in_two_windows_of_one_sentence_get_two_uids: a sentence split across windows.
  • an_older_evidence_table_gets_its_claim_at_column.
  • Three mutations each turn one of these red: the retraction without claim_at, the derived claims ignored, and claim_at never set.

Review stop rule (declared before the first round)

A finding is fixed here only if a plain environment reaches it (the default or documented config, agent-produced text, Linux, macOS or Windows) and it either hides a current claim or changes the uid of a claim written before this change. Everything else goes to an issue. After two rounds in a row whose findings all go to issues, this PR is merged with no further commit once check and CodeQL are green.

Added before round 2: a further finding about how a claim's identity is chosen goes to an issue, and this PR merges or closes by the rule above. The identity semantics are not changed a third time here.

🤖 Generated with Claude Code

https://claude.ai/code/session_012wbKzQZyG5Aq6poybwciHt

…hose quotes overlap stay one (#125)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012wbKzQZyG5Aq6poybwciHt
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for security reviews. Please try again later.

@coderabbitai

coderabbitai Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: c7437142-9f1b-423f-b86f-e4907fdcefb5


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-28T09:43:52.995335Z 6836a9a Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @ojungo69, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 2 hours and 37 minutes by commenting @sourcery-ai review. Upgrade to get a review now.

@sourcery-ai

sourcery-ai Bot commented Sep 28, 2026

Copy link
Copy Markdown

Reviewer's Guide

The PR adds an optional positional discriminator to claim evidence and incorporates it into UID derivation only when multiple non-overlapping claims of the same kind begin in one sentence. Curation assigns this discriminator by normalized kind, source sentence, and quote overlap before gates run, preserving legacy UIDs for existing and solitary claims while keeping identities stable across recuration.

Sequence diagram for assigning stable UIDs to same-sentence claims

sequenceDiagram
    participant Curate
    participant Number as curate::number
    participant UID as claims::uid
    participant Gates
    participant Store

    Curate->>Number: number(found)
    Number->>Number: Group by normalized kind and sentence
    Number->>Number: Merge overlapping quotes
    Number-->>Curate: Set Evidence.nth
    Curate->>Gates: check claims
    Gates->>UID: uid(kind, first evidence)
    UID-->>Gates: Hash kind, source, sentence, optional nth
    Gates->>Store: Write claim operation
Loading

Flow diagram for same-sentence claim numbering

flowchart TD
    A[Located drafts] --> B[Sort by normalized kind, source, sentence, and quote offset]
    B --> C{Same claim group?}
    C -->|Overlapping quote| D[Reuse nth]
    C -->|Non-overlapping quote| E[Increment nth]
    C -->|First or new group| F[Set nth to 0]
    D --> G[Derive UID]
    E --> G
    F --> G
    G --> H[Claims retain identity across recuration]
Loading

File-Level Changes

Change Details Files
Disambiguate same-kind claims that begin in the same sentence while preserving existing UIDs for solitary claims.
  • Add an optional serialized Evidence.nth discriminator, omitted when zero.
  • Include nonzero nth in UID hashing while retaining the legacy hash format for zero.
  • Populate the new field with backward-compatible defaults across evidence construction and reads.
src/claims.rs
src/consumer/claims.rs
src/consumer/manifest.rs
src/curate.rs
src/digest.rs
Assign stable claim numbers during curation based on quote positions and overlap.
  • Group drafts by normalized kind, source device/sequence, and sentence.
  • Sort by quote start and reuse a number for overlapping quotes; increment for non-overlapping claims.
  • Number drafts before gate evaluation so sibling handling treats overlapping drafts as one claim.
  • Apply the same numbering during recuration to preserve UIDs across reordered or reworded answers.
src/curate.rs
src/gates.rs
Add regression coverage for distinct same-sentence claims and recuration stability.
  • Verify overlapping drafts collapse to one numbered claim while separated drafts receive distinct UIDs.
  • Verify reworded claims in a different order retain both UIDs and remain active.
src/curate.rs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: db422d1815

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/curate.rs Outdated
Comment thread src/curate.rs Outdated
Comment thread src/curate.rs Outdated
…, and takes its own start when its sentence holds another claim of its kind (review on #210)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012wbKzQZyG5Aq6poybwciHt
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for security reviews. Please try again later.

@sonarqubecloud

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6836a9aade

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/curate.rs
@ojungo69

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for security reviews. Please try again later.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6836a9aade

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/claims.rs
@ojungo69
ojungo69 merged commit 9f275e7 into main Sep 28, 2026
15 of 16 checks passed
@ojungo69
ojungo69 deleted the fix/uid-nth branch September 28, 2026 09:44
ojungo69 added a commit that referenced this pull request Sep 28, 2026
…uote (#211) (#214)

Closes #211. From the Codex review of #210 (round 2), moved to an issue
under that PR's stop rule.

## What

`curate::keyed` gives a draft the `claim_at` of the claim its quote
overlaps in the same sentence. It looked at every derivation of that
kind in the sentence, active or not. A claim first quoted with its whole
sentence and later narrowed kept its old wide quote in the lookup. A
later draft anywhere in the sentence then overlapped it and took the
same uid, so one of two current claims was hidden.

The lookup now reads each uid's active derivation only (`claims` joined
to `derivations`). A draft joins a claim by the range the claim quotes
now.

## Test

`an_old_wide_quote_joins_no_claim_to_a_narrowed_one`: a claim quoted
with the whole sentence, then narrowed, then a recuration that gives the
narrow claim and one apart from it. The narrow claim keeps its uid, and
the other gets its own. Matching against every derivation turns it red.

## Review stop rule (declared before the first round)

A finding is fixed here only if a plain environment reaches it and it
hides a current claim or changes the uid of a claim written before this
change. Everything else goes to an issue. After two rounds in a row
whose findings all go to issues, or a 👍, this PR is merged with no
further commit once `check` and CodeQL are green.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_012wbKzQZyG5Aq6poybwciHt

## Summary by Sourcery

Match draft claims against active quotes so narrowed claims no longer
hide distinct claims in the same sentence.

Bug Fixes:
- Ensure drafts join only the currently active derivation of a claim,
preventing an older wider quote from incorrectly absorbing a separate
current claim.

Tests:
- Add regression coverage for preserving claim identity when a
sentence-wide quote is narrowed and a separate claim is later
recurat​ed.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
ojungo69 added a commit that referenced this pull request Sep 28, 2026
…216)

Closes #213.

Two knowledge.db migrations in `claims::schema` checked the old schema
and then changed it with no lock between the two. A worker and a command
(`oboete recurate`, `oboete search`) opening the same older knowledge.db
at once could both find the old schema; the second then failed on
"duplicate column name: claim_at", or rebuilt the queue table a second
time.

## What

- `claims::migrate(k, needed, change)`: reads `needed` first, so a
current knowledge.db takes no write lock. When a change is needed:
- outside a transaction, it takes `BEGIN IMMEDIATE`, asks `needed`
again, and changes only if it still holds;
- inside one (a consumer's step or rewind, both immediate), the lock is
already held, so it changes at once, as before.
- The `claim_at` column (#210) and the queue's key rebuild (#208) both
go through it.
- `db::ensure_column`, which the issue named, takes `&mut Connection`;
`schema` is called with the step's transaction (`&Connection`), so the
same check-again shape is written here with
`Transaction::new_unchecked`.

## Test

`two_connections_migrate_one_older_knowledge_db_at_once`: for an older
evidence table, then an older queue table, a first connection holds the
write lock (as a step does) while a second runs `schema`; the first then
migrates and commits. Both succeed, the column is there once, the queue
has its three-column key, and the rows are kept. On `main`'s `claims.rs`
it fails 3 runs in 3 with "duplicate column name: claim_at".

## Review stop rule (declared before the first round)

A finding is fixed here only if a plain environment reaches it (a
worker, a hook and the CLI commands on one home; Linux, macOS or
Windows) and it loses a row, stops a worker run, or leaves the schema
half changed. Anything else goes to an issue. After two rounds in a row
whose findings all go to issues, this PR is merged with no further
commit once `check` and CodeQL are green.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_012wbKzQZyG5Aq6poybwciHt

## Summary by Sourcery

Make knowledge.db schema migrations safe when workers and commands open
an older database concurrently.

Bug Fixes:
- Prevent concurrent knowledge.db migrations from applying schema
changes more than once or failing with duplicate-column errors.

Enhancements:
- Centralize migration checks so current databases avoid write locks
while outdated databases recheck their schema under an immediate
transaction.
- Apply lock-safe migration handling to the claim_at column and recurate
queue key migrations.

Tests:
- Add coverage for concurrent migrations of older evidence and queue
schemas, verifying successful upgrades and preservation of rows.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 5 complexity

Metric Results
Complexity 5

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

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.

1 participant