Skip to content

v1.3: separate case outcome from coverage verdict, split policy actions out of the verdict vocabulary, fix payload digest to §2.3 - #8

Merged
LGD-Eval merged 2 commits into
mainfrom
v1.3-outcome-vocabulary
Oct 25, 2026
Merged

LGD-Eval merged 2 commits into
mainfrom
v1.3-outcome-vocabulary

Conversation

@LGD-Eval

Copy link
Copy Markdown
Owner

v1.3 — case outcome, one vocabulary, corrected digest

Responds to the review in FG-TIDA/use-cases#27 (2026-10-23).

What this PR is not

It is not a change of position. B1/B2 were already split on 2026-10-16 following the
themes#42 review; that split is not being
re-argued here. This PR fixes three places where the repository failed to say what it
already meant, and one place where it contradicted its own published standard.

Three defects, three fixes

1. verdict was being read as the case outcome

verdict counts how many of the six evaluation domains reach grade V/S. A case set that
exercises two domains is therefore Insufficient evidence — including Case A, a valid,
current, in-registration credential whose authorization verdict is verified. Anyone
reading verdict as "the conclusion" gets a false negative on the one positive case.

v1.3 adds outcome.verification (verified / unresolved / rejected) as the field to
read, keeps verdict with its original meaning, and carries a scopes object inside
every conclusion stating what each summary field does and does not answer.

2. Policy actions were inside the verdict vocabulary

quarantined used to be a fourth authorization verdict, but it describes what an
operator does with an unsettled field — not what was verified. Verdicts are now three
(verified / unresolved / rejected), and policy actions live in their own field,
policy_action, reusing the four operator meanings this repository already publishes in
EVALUATION-STANDARD.md §2.2:

Operator action Typical trigger
allow verified
defer unresolved
deny rejected
exclude field semantics unsettled — not a verdict

reject is deliberately unavailable as an action name, so that the action and the
verdict cannot be confused in a single glance. reason_code becomes required and
machine-readable.

3. The digest did not match §2.3

§2.3 has specified sort_keys=True with compact separators since v0.1. The v1.2
implementation used default separators and insertion order. Recomputed under §2.3, the
four v1.2 conclusions hash to ab56339d…, be1677e8…, ff4ff95a…, 6c37e632… — none
of them the published values. A third party following the standard could not reproduce
any digest we published. The implementation now matches the text.

New digests

Case Outcome reason_code policy_action Digest
A. Valid registered credential verified none allow fa8b1420cca29307
B1. Unverifiable issuer scope unresolved authorization_unresolved defer a353ad64f911030a
B2. Confirmed out-of-scope issuer rejected authorization_rejected deny d709c4ec85ef5d6e
C. Status source unavailable unresolved status_unavailable defer 982c390107058485

Verification

  • Selftest: 35 invariants (was 15), including B1/B2 outcome separation, reason_code
    consistency with the verdict, rejection of quarantined as a verdict, digest equality
    against an independently computed §2.3 value, and key-order independence of the digest.
  • Clean-copy reproduction: delete the four conclusions, re-run the grader on the four
    inputs, compare — 4/4 MATCH, and the selftest passes in that copy.
  • 19 files: 15 modified, 4 added (a rendered .md per case alongside each JSON), none
    removed.

Review notes

  • demo/evidence-grading-demo.html was stale (three cases, "12 invariants", pre-split
    digests). It is regenerated from the four conclusions, and its "external verification"
    wording is replaced with what actually happened — a reproduction run from a fresh
    download, made by the maintainers. Claiming third-party verification for our own run
    would be precisely the overstatement this project exists to catch.
  • assets/three_cases_outcome_flow.svg keeps its file name so existing links from
    threads do not break; the page and the caption state that it shows four cases.
  • Nothing here changes the evidence grades or the per-domain findings of any case. Only
    the summary fields, the vocabulary and the digest computation changed.

…ns out of the verdict vocabulary; fix payload digest to §2.3

Three defects found while reviewing the case set for FG-TIDA/use-cases#27 against the
2026-10-23 review comment. None of them is a change of position; all three are the same
position applied consistently.

1) `verdict` is six-domain evidence coverage, not a case outcome.
   Case A — a valid, current, in-registration credential — reports
   "Insufficient evidence(证据不足)" because only 2 of the 6 domains are exercised.
   A program that reads `verdict` as the conclusion gets a false negative on the
   positive case. v1.3 adds `outcome.verification` (verified / unresolved / rejected)
   as the field to read, keeps `verdict` with its original meaning, and states both
   scopes inside every conclusion in a machine-readable `scopes` object. The field was
   not wrong; it was being asked the wrong question.

2) The verdict vocabulary mixed policy actions with verification states.
   `quarantined` was a fourth verdict, but it describes what an operator does with an
   unsettled field, not what was verified. It is now `policy_action: exclude`, and
   `policy_action` reuses the four operator meanings already published in
   EVALUATION-STANDARD.md §2.2 (allow / defer / deny / exclude) instead of introducing
   a fifth word set. `reason_code` becomes a required machine-readable field
   (none / authorization_unresolved / authorization_rejected / status_unavailable).

3) The payload digest did not match the convention in EVALUATION-STANDARD.md §2.3.
   The v1.2 implementation computed the digest with default JSON separators and
   insertion order; §2.3 specifies sort_keys=True with compact separators. Any third
   party following §2.3 could not reproduce a published digest. This was verified
   against the v1.2 files before changing anything: recomputed under §2.3 they hash to
   ab56339d…, be1677e8…, ff4ff95a…, 6c37e632…, none of which matches the published
   values. The implementation now matches the text.

All four digests change (schema lgd-eval/conclusion/v1.3):

    Case A   fa8b1420cca29307
    Case B1  a353ad64f911030a
    Case B2  d709c4ec85ef5d6e
    Case C   982c390107058485

Selftest: 35 invariants (was 15). New invariants cover B1/B2 outcome separation,
reason_code consistency with the verdict, rejection of `quarantined` as a verdict,
digest equality with an independently computed §2.3 value, and key-order independence.

Reproduction: from a clean copy of this tree with the conclusions deleted, re-running
the grader on the four inputs reproduces all four published digests (4/4 MATCH), and
the selftest passes in that copy.

Also in scope: demo/evidence-grading-demo.html was stale (three cases, "12 invariants",
and the pre-split digests) and is regenerated from the four conclusions; the
"external verification" wording is replaced with what actually happened (a reproduction
run from a fresh download, made by the maintainers), since claiming third-party
verification for our own run would be the exact overstatement this project exists to
avoid.

No files removed. The `three_cases_outcome_flow.svg` asset keeps its file name so that
links from existing threads do not break; the caption and the page state that it shows
four cases.
@github-actions

Copy link
Copy Markdown

🤖 LGD-Eval PR Review Bot

Blocking issues/阻断: 0 — Warnings/提示: 2

  • 🟡 Changed files (19): EVALUATION-STANDARD.md, WORKED_EXAMPLES_L0-L13.md, demo/evidence-grading-demo.html, tools/demo/demo-conclusion.json, tools/demo/demo-conclusion.md, tools/evidence-grader.py, worked-examples/cases/README.md, worked-examples/cases/caseA_valid_registered_credential_conclusion.json, worked-examples/cases/caseA_valid_registered_credential_conclusion.md, worked-examples/cases/caseA_valid_registered_credential_input.json, worked-examples/cases/caseB1_unverifiable_issuer_scope_conclusion.json, worked-examples/cases/caseB1_unverifiable_issuer_scope_conclusion.md, worked-examples/cases/caseB1_unverifiable_issuer_scope_input.json, worked-examples/cases/caseB2_confirmed_out_of_scope_issuer_conclusion.json, worked-examples/cases/caseB2_confirmed_out_of_scope_issuer_conclusion.md, worked-examples/cases/caseB2_confirmed_out_of_scope_issuer_input.json, worked-examples/cases/caseC_unavailable_status_source_conclusion.json, worked-examples/cases/caseC_unavailable_status_source_conclusion.md, worked-examples/cases/caseC_unavailable_status_source_input.json
  • 🟡 README worked-examples/cases/README.md has no LGD-Eval cross-repo links (anchor discipline/内锚)

审核机器人结论:乱码/编码类错误必须修复;提示类仅供人类评审参考。签发权始终在人。
Bot verdict: mojibake/encoding failures must be fixed; warnings are for human reviewers. Sign-off always stays with humans (签发权在人)。

The digest quoted in three places was computed over the local CRLF copy:
34,795 bytes + 647 lines = 35,442, which is the size that was hashed.
No historical version of tools/evidence-grader.py has that digest.
Replaced with the SHA-256 of the bytes GitHub actually serves, and stated
the measurement basis inline so the mistake cannot recur silently.
@github-actions

Copy link
Copy Markdown

🤖 LGD-Eval PR Review Bot

Blocking issues/阻断: 0 — Warnings/提示: 2

  • 🟡 Changed files (19): EVALUATION-STANDARD.md, WORKED_EXAMPLES_L0-L13.md, demo/evidence-grading-demo.html, tools/demo/demo-conclusion.json, tools/demo/demo-conclusion.md, tools/evidence-grader.py, worked-examples/cases/README.md, worked-examples/cases/caseA_valid_registered_credential_conclusion.json, worked-examples/cases/caseA_valid_registered_credential_conclusion.md, worked-examples/cases/caseA_valid_registered_credential_input.json, worked-examples/cases/caseB1_unverifiable_issuer_scope_conclusion.json, worked-examples/cases/caseB1_unverifiable_issuer_scope_conclusion.md, worked-examples/cases/caseB1_unverifiable_issuer_scope_input.json, worked-examples/cases/caseB2_confirmed_out_of_scope_issuer_conclusion.json, worked-examples/cases/caseB2_confirmed_out_of_scope_issuer_conclusion.md, worked-examples/cases/caseB2_confirmed_out_of_scope_issuer_input.json, worked-examples/cases/caseC_unavailable_status_source_conclusion.json, worked-examples/cases/caseC_unavailable_status_source_conclusion.md, worked-examples/cases/caseC_unavailable_status_source_input.json
  • 🟡 README worked-examples/cases/README.md has no LGD-Eval cross-repo links (anchor discipline/内锚)

审核机器人结论:乱码/编码类错误必须修复;提示类仅供人类评审参考。签发权始终在人。
Bot verdict: mojibake/encoding failures must be fixed; warnings are for human reviewers. Sign-off always stays with humans (签发权在人)。

@LGD-Eval
LGD-Eval merged commit 1e8c173 into main Oct 25, 2026
5 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.

1 participant