Skip to content

Run the fact-list updater in the pipeline (HINBOX_PROFILE_UPDATE_APPROACH=facts), with timelines and saved fact rows - #69

Merged
strickvl merged 8 commits into
mainfrom
claude/project-thread-orjf3o
Nov 4, 2026
Merged

strickvl merged 8 commits into
mainfrom
claude/project-thread-orjf3o

Conversation

@strickvl

@strickvl strickvl commented Nov 4, 2026 •

Copy link
Copy Markdown
Owner

Requested by Alex · project thread

What changes

This follows #64, which added the fact-list updater as an eval-only prototype.

  • Pipeline: update_profile(approach="facts") and HINBOX_PROFILE_UPDATE_APPROACH=facts make just process use src/engine/fact_list.py. The default stays edit.

  • Saved rows: each profile saves its fact rows as a JSON string under profile["fact_rows_json"]. A row records:

    • each source's kind and quote, including for facts the model placed itself (one sentence can state several facts, and then those rows share it);
    • which articles only repeated it;
    • which row a conflict disputes.

    load_rows() reloads the rows on the next update. It drops a saved row whose sentence is no longer in the text, and builds rows from the text for any cited sentence that no saved row covers.

  • Timelines: the compare step gets an update verdict for a later state of the same thing, such as a move to another camp, a decision after "still deciding", or a rescheduled trial date. It is written next to the old state, not as "Another report differs".

  • Fewer false conflicts: a conflict must also pass same_subject(), which means the two sentences share at least 40% of their word stems, ignoring numbers.

  • Details no longer dropped: a claim judged same that has a year, month or number the row lacks ("a 78-minute secret session") is written as a new fact instead of being dropped.

  • Removed checks:

    • 5795add tried a looser conversion of same and update verdicts into conflicts. On test it brought back 6 false disputes per run and still caught 0 of 4 planted disputes, so it is reverted.
    • The earlier update-to-conflict check (different dates plus 60% shared stems) never fired on dev or test. Review showed it could turn a rescheduled trial date into a false dispute, so it is removed too.

Results

All runs use local Qwen through llama-server. Every run had 0 errors.

Eval, on the cc1158f code. That version still had the update-to-conflict check, but the check never fired, so the scores apply to this PR. Scores are cases passed:

dev (81) test (79)
Luna, facts 79 75
Luna, edit 75 74
Qwen-32k, facts 77 73
Qwen-32k, edit 69 67

Real just process run on the same 60 articles, edit against facts, counted by scripts/audit_entities.py. This run used 989d194, before the last fixes.

edit facts
Repeated sentences 320 23
"Sources disagree" sentences 312 4
Longest profile 55k chars 27k
profile.update seconds 10,256 9,212
Rows with a linked but uncited article 13 121

I sampled 11 of the 121 rows with linked but uncited articles:

  • In 8, the article adds nothing new: it's a passing mention or a repeat.
  • In 2, a small detail was lost. The same_with_detail change fixes that.
  • 1 is unclear.

Known gap

Planted disputes on test are 0 of 4 for both models. The models call a different year for a past event "the same" or "an update". Fixing that inside the updater brought back false disputes, so it needs a separate check after the update, with its own eval.

Testing

uv run pytest -q tests -m "not asyncio": 590 passed after merging main. ruff is clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_017KuZSfznoSE6bnm9t8KWMf

…ates, add `HINBOX_PROFILE_UPDATE_APPROACH=facts`

The compare step gets an `update` verdict for a later state of the same
thing, written next to the old state; a `conflict` must also share most of
its words with the row (`same_subject()`). Rows are saved as
`profile["fact_rows_json"]` and reloaded by `load_rows()`, so source kinds
and repeat counts survive. `update_profile(approach="facts")` runs it in the
pipeline.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017KuZSfznoSE6bnm9t8KWMf
…nflicts; loosen the `update` check

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017KuZSfznoSE6bnm9t8KWMf
On dev/test it brought back false "Another report differs" sentences
(6 per test run) and still caught 0 of 4 planted disputes.

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

chatgpt-codex-connector Bot commented Nov 4, 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-11-04T05:26:27.093832Z b52b25d New commits
ℹ️ 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.

@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: 24d42adc5f

ℹ️ 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/engine/fact_list.py Resolved
Comment thread src/engine/fact_list.py Resolved
…act_list`

The update-to-conflict check never fired on the evals and could turn a
rescheduled trial date into a false dispute, so it is removed. Facts the
model placed now keep their sentence on their row, so their quote and
source kind are saved in `fact_rows_json`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017KuZSfznoSE6bnm9t8KWMf
…-orjf3o

# Conflicts:
#	src/engine/profiles.py

@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: 52868be9cb

ℹ️ 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/engine/fact_list.py Resolved
…t_list`

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017KuZSfznoSE6bnm9t8KWMf
@strickvl
strickvl merged commit 8aa34bc into main Nov 4, 2026
2 checks passed
@strickvl
strickvl deleted the claude/project-thread-orjf3o branch November 4, 2026 05:26
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