Skip to content

A regression case can expect no binding while a person's binding remains authoritative - #1334

Merged
WaylandYang merged 11 commits into
deeplethe:devfrom
virtue039:codex/ontology-negative-expectations
Oct 23, 2026
Merged

WaylandYang merged 11 commits into
deeplethe:devfrom
virtue039:codex/ontology-negative-expectations

Conversation

@virtue039

@virtue039 virtue039 commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

An Editor can record that a statement should bind to no property, using the existing regression-case request and saved alignment decisions. A negative case passes only on explicit none; bound and undecided fail, and an absent decision stays unchecked. When a person's formal binding disagrees, the case fails with conflict: human_binding and shows the actual property/direction without rewriting that binding.

Scope and contract

This implements the negative-expectation slice described in 0061 cut 2 / #1203. The 0061 status line is unchanged, and its cut 2 section is still headed “proposed”. This PR does not amend the record or add an adoption veto, case-deletion route, evaluator, model call or new job.

  • Existing positive POST requests keep their behavior; expected_binding: "none" requires both target fields absent/null. Invalid or half-specified targets are rejected, with the existing same-base, live-statement and Editor checks.
  • Migration 0118 makes both target columns nullable together under a CHECK and adds a partial unique index for negative cases. Concurrent retries return the original case and preserve its creator/origin. Explicit positive and negative expectations can coexist; saved cases observe disagreements rather than prevent decisions.
  • The workbench and statement dialog distinguish bound/none and display human-binding conflicts, with both English and Chinese strings. CLI/export integrity checks also accept an absent target without inventing a property.

The change exceeds 500 added lines because the nullable target must travel together through storage, validation, the API/TypeScript types and workbench, plus database/API/alignment regressions. Shipping those pieces independently would leave a target shape that another layer cannot represent. Adoption changes are limited to skipping automatic positive case registration for an already negatively-cased example.

Changes after the maintainer review

Addresses review 5595436225 and the landing instructions:

  • Removed the new per-example advisory locks and conflicting_case_expectation 409. A negative example no longer rolls back creation or reuse of a property.
  • Adoption skips registering that example as an automatic positive case, while still committing the proposal, its element/binding and follow-up jobs. Ordinary examples continue to get positive cases. The original negative case remains and reports failure after alignment; a reuse that writes a person's binding reports human_binding immediately in that transaction.
  • Removed the corresponding opposite-expectation error strings and adoption-refusal documentation. Confirmations of different expectations do not overwrite each other or act as a veto.
  • Restored the original positive store test's formatting; its only change against dev is wrapping the two target fields in Some. The new tests are separate.
  • Per the maintainer's landing order, this PR keeps 0118; A human phrase decision materializes ahead of queued model work #1358 moves to 0119. The merged tree has 105 migration files, matching CLI CURRENT_SCHEMA_VERSION = 105.
  • Synced the branch with dev 02611ae, including Prefer grounded subject evidence before namesake profile scores #1251 and the model-settings test update. Resolved the appended-test conflict by preserving both the complete negative-case regression and A base with no properties still queues the ontology agent once enough signatures are unbound #1336's complete empty-ontology regression. The PR adds no change to 0061's status.

Validation

Current commit: 768e85c6e3d071ad7684add9cabbc7b01ea19055. Local validation on macOS arm64, pinned pnpm 10.2.1 / Node 24.19.0:

  • cargo fmt --all --check, workspace/all-targets clippy with -D warnings, and workspace build pass.
  • Full workspace tests: 1,662 passed, 0 failed, 6 pre-existing ignored, with both DB/PDF require guards enabled against the dedicated test database.
  • Frozen pnpm install, web build, 318 web tests / 46 files, and 15 bench scorer tests pass.
  • Adoption regression covers new-property/reuse paths with both only-negative and mixed examples: HTTP success, committed proposal/jobs, no automatic positive counterpart for the negative example, ordinary positive cases retained, original actor/origin retained, and a failed negative result after the binding. Its model/embedding request counters stay at zero.
  • Store/API tests cover concurrent negative deduplication and opposite confirmations without a veto; the existing alignment test still proves ordinary rejudgement updates saved results without extra model requests and leaves human bindings authoritative.
  • The retained migration-upgrade check applied all 104 preceding migrations, seeded a populated positive case, then applied 0118: the entire saved row stayed unchanged. The SQL files are unchanged by this sync; the current guarded suite also exercises embedded SQLx migration checks.

An earlier sync hit ENOTEMPTY in two unchanged MCP fixture cleanups. The test-only follow-up is already isolated in commit fdbc189: it retries only DirectoryNotEmpty up to ten times; other and persistent IO failures still fail. The 34-test MCP suite previously passed three consecutive runs after this fix. Original CI failure logs are retained. CI 39783528607 is running at this exact head: migrations, lint, build and web pass; the full test job is still installing its PDF dependencies, with the backend summary waiting on it. The earlier sync runs 39781805298 and 39782513968 both passed all six jobs; those do not replace the current-head check. No live-model experiment is needed for this slice: it compares the existing committed ledger rather than adding an evaluator.

Refs #1103, #725, #1184, #1203.

…ins authoritative

Signed-off-by: Virtue039 <virtue039@qq.com>
Signed-off-by: Virtue039 <virtue039@qq.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.

The negative-case slice itself is clean and inside the #1103 boundary: both target columns nullable together under a CHECK, record_sql passing a negative case only on none and failing on bound or undecided, conflict: human_binding reported rather than enforced, no evaluator or model call (the request count assertion in phrase_alignment_tests says so), i18n in both files. CI is green on the head.

What blocks it is the piece the record does not ask for. Adoption now takes advisory locks on every example statement and the whole adoption rolls back with 409 if any example carries a negative case. There is no route or store function that deletes a case (api/mod.rs registers only GET and POST), so once an Editor records none for a statement, every proposal that cites it as an example can never be adopted; the only way out is invalidating the statement. The record's rule for the mirror situation, a person's binding against a negative case, is to fail the case and make the disagreement visible, not to block. Please drop the lock and the 409 (or make them their own PR, with an ADR amendment and a case-delete route) and let adoption skip a negatively-cased example the way skipped shapes already work; the case then fails after re-alignment and says why.

Also:

  • The description should state that the 0061 status line is not updated; the cut 2 section is still headed proposed, and the 409 behaviour is documented only in docs/design/ontology.md, so the contract is widened outside the record.
  • About a hundred lines of the store test diff are a rustfmt reflow of an existing test; please revert the cosmetic part.
  • migrations/0117_* is also claimed by #1332 and #1131. Whichever lands second renumbers.

Signed-off-by: Virtue039 <virtue039@qq.com>
Signed-off-by: Virtue039 <virtue039@qq.com>
Signed-off-by: Virtue039 <virtue039@qq.com>
Signed-off-by: Virtue039 <virtue039@qq.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.

Everything asked for is done: the advisory locks and the 409 veto are gone, adoption now skips a negatively-cased example (finish_adoption's NOT EXISTS on expected_property_id IS NULL) and the case reports the conflict after re-alignment, the reflow is reverted, and the description states the 0061 status line is untouched.

One thing left, the migration number: 0118 is also claimed by #1358. Whichever of the two lands first keeps 0118; the other takes the next free number (0119 is #1359's, still a draft). I will say which once the order is known. The mcp_tests.rs teardown retry is unrelated to the slice; fine to keep, but it would read better in its own commit.

@WaylandYang

Copy link
Copy Markdown
Contributor

Two mechanical things, nothing on the slice itself:

Once rebased and green I will merge.

… with dev

Signed-off-by: Virtue039 <virtue039@qq.com>
…e-expectations

Signed-off-by: Virtue039 <virtue039@qq.com>
…e-expectations

Signed-off-by: Virtue039 <virtue039@qq.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, everything requested is in. The only red check was CI infrastructure: the test job hung in apt-get update for six hours and was cancelled, which failed backend. I'll update the branch so CI runs again, and merge once it's green.

@WaylandYang
WaylandYang merged commit 4789465 into deeplethe:dev Oct 23, 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