Skip to content

Resolve time mention dependencies independently of model reply order - #1087

Merged
WaylandYang merged 2 commits into
deeplethe:devfrom
Floating-Y:fix/time-mention-dependency-order
Oct 5, 2026
Merged

WaylandYang merged 2 commits into
deeplethe:devfrom
Floating-Y:fix/time-mention-dependency-order

Conversation

@Floating-Y

Copy link
Copy Markdown
Contributor

Why

The resolver introduced in #740 could leave a valid relative time mention at grade C solely because of the model's reply order. For a chain 0 → 1 → 2 starting on 2024-01-01, reply order [0,1,2] resolved mention 2 to 2024-01-03 at grade B, while [0,2,1] left it undated at grade C. Both replies parsed completely.

The old scheduler evaluated mention dependencies once in reply order and discarded computed anchors between batches. The existing retry asks only for unanswered IDs, so it could not repair an interpretation already received with an unavailable dependency.

What changes

  • Extract a pure resolve_interpretations function used by both production and regression tests. Revisit pending interpretations while progress is made; stop when a pass makes no progress and leave the remaining interpretations at grade C.
  • Track received interpretations separately from computed dates. Collect all existing batches and the unanswered-ID retry before resolving, allowing previously received dependents to use anchors supplied later without additional model calls.
  • Preserve each interpretation's own section context, date precision, calendar arithmetic, interval shapes, grades, and writeback semantics.

This resolves dependencies among known interpretations within one document-resolution run. It does not implement the undated-event waiting mechanism proposed in #1075, expand model-visible context, or add cross-document matching. There are no migrations, public fields, dependencies, or unrelated time-feature changes. The pending-set approach requires at most O(n²) single-interpretation evaluations.

How it was checked

  • Added the deterministic regression before changing the algorithm and observed it fail against the extracted original production scheduler: [0,2,1] left mention 2 at grade C.
  • Added six tests covering all six reply permutations with full results compared by ID, an 81-mention reverse chain with non-monotonic IDs, independent chains, self-references, cycles, missing anchors, later batches and retry replies, section isolation, and dateless endings/unusable anchors.
  • Time-resolution tests: 24 passed, including five database-backed tests.
  • cargo test --locked --offline --workspace: 1437 passed, 0 failed, 6 ignored, with a dedicated temporary PostgreSQL database and UTOPIA_TEST_REQUIRE_DB=1.
  • cargo fmt --all --check and cargo clippy --locked --offline --workspace --all-targets -- -D warnings passed.
  • pnpm install --frozen-lockfile and pnpm build passed. No web files changed.

Initial database-backed mock-endpoint checks failed, and an initial workspace run was stopped after related failures, because Windows system proxy handling intercepted loopback requests. Reruns passed with process-local NO_PROXY=localhost,127.0.0.1,::1; no application code or global proxy settings were changed. The six default-ignored tests were not run: two live-service tests and four opt-in delivery/crash tests.

Before review

  • Every commit is signed off (git commit -s)
  • cargo fmt --all --check, cargo clippy --workspace --all-targets -- -D warnings and cargo test --workspace pass

Signed-off-by: Floating-Y <118035379+Floating-Y@users.noreply.github.com>

@WaylandYang WaylandYang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks @Floating-Y. The dependency order was the reply's order, which the model does not promise, and an anchor computed in one batch was thrown away before the next. Resolving all received interpretations to a fixed point, with the loop ending when a pass makes no progress, is the right structure: chains of any length resolve, and cycles, self-references and missing anchors stay at grade C as before. Keeping "received" apart from "computed" is what lets the retry ask only for what was not answered. Landing it.

@WaylandYang
WaylandYang merged commit c9abbc1 into deeplethe:dev Oct 5, 2026
6 checks passed
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