Skip to content

Assessment skill: distractors true elsewhere, masked probe as the gate - #30

Merged
aharlap merged 4 commits into
mainfrom
skills/assessment-writing-v2
Oct 20, 2026
Merged

aharlap merged 4 commits into
mainfrom
skills/assessment-writing-v2

Conversation

@aharlap

@aharlap aharlap commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Why

An evaluation of the assessment-writing skill found that it removed surface cues (a content-masked solver fell from 49% to 20%, against 25% chance) but not stem independence. A solver who knew the subject still picked the key from the options alone 89% of the time, with or without the skill. Writers stated each misconception as a general claim, which is false whatever the stem asks. The distractors that held up were true statements answering a neighbouring question, plus numeric ones.

What changed

  • Trace pin. pack.json pins Trace 0.1.1-experimental.97e6de33b (source 97e6de33b3c30e67d44e7db6d0f1856bf358d3ef), which scores the masked probe from Studio's language provenance (Activate masked item-cue scoring from Studio language provenance praxity-trace#23). It follows Refresh Check and Trace pins to Rubato-hosted CLI prereleases #28's route.
    • Trace prerelease, built by this hosted run. Main CI on that commit: run.
    • Rehosted byte for byte on Rubato's asset-only prerelease v0.1.1-tools.experimental.20261019.4.
    • SHA-256 2204cbb49f7ed666cef941a83ff26d6a76611008fec6f10ca1fd5002820177fe. It matches the build log, Trace's asset digest, a local download, and both Rubato's asset digest and an anonymous download from the Rubato URL. All 130 payload files match the inventory, the source revision is clean, and the licence, notices, skill and report reference match the source.
    • The Studio pin (0.3.0-main.abaf1f3f, with inspect language provenance) comes from main unchanged. A manifest test fails while the pinned Trace lacks scored masked results, as 09fcaaf and 92a164d do.
  • Distractors that need the stem. Distractors must be true or right in a neighbouring case, never false everywhere. For each distractor the writer notes the case it is right for and the stem detail that rules it out. That detail must belong to the case. A standard that rules out a distractor goes in the stem.
    • Worked examples cover an explanation, a classification, an action and a numeric item.
  • Key check. A fresh judge that has never seen the key marks every option that answers each stem. For a "best" or "most likely" stem it marks only the single best option and flags ties. The same judge, not the writer, confirms the notes that would exempt a plain-probe hit from a rewrite.
  • Probes. The masked probe is the guessing-cue gate; plain choices-only is a diagnostic. The masked solver runs whenever masked/items.json is non-empty. Masked scoring needs locale: en in course.yaml, or lang: en per lesson, plus the pinned Studio.
  • Gate. guessingGate(itemCues) returns "pass", "fail" or "stop".
    • Every bank and the course need masked.applies === true, status === "scored" and total === count.
    • Counts must be positive integers.
    • A tail at or below its threshold fails.
    • Otherwise each gated row's pMin and pLowMin must reach its own threshold, or the gate stops.
  • Stop path. On a stop, the agent finishes the other probes and rewrites, then reports everything. That report gives Trace's per-bank reason and its remedy (language-unconfirmed, language, mask-space), or the row's pMin and pLowMin against its limit. It marks the bank unverified and asks. No hand masking and no hand tails.
  • Folders. Answers and judge notes go in <review>, Trace's <bundle>-review/ folder.

Tests

The shipped predicate runs against:

  • each refusal reason, including an unknown one, with every scored field injected;
  • "not run";
  • a missing masked;
  • incomplete small banks;
  • string, fractional, infinite and null counts;
  • masked against plain disagreement;
  • eight of eight right on an underpowered course;
  • 0 of 12 on a 12-item four-option course, which stops though Trace's 0.05 flags are false;
  • a 15-item bank among five with none right;
  • a missing minimum.

Each case also runs against a copy of the predicate with its rule removed, and the result must change. Prose rules are asserted by key phrase or structure, and removing a rule fails the test.

Local runs:

  • node --test test/skills.test.mjs test/assessment-writing.test.mjs test/manifest.test.mjs: 121/121 pass.
  • npm run validate and npm run validate:release: both pass.

Left

  • Skipped P3s from round 2:
    • Example 1's expansion note names a metal-and-glass case.
    • The note and mark file formats for the key check.
    • Remaining exact-sentence prose pins.

Review: 4/8/4, 0/5/5; fixes 3.
Counts are distinct findings across Sol and Opus per round; overlapping findings count once. Round 2 found no P1s. Fix 3 consumes trace#23's contract, per Opus's trace#23 review ("Rubato #30 changes"), with no new review round.

🤖 Generated with Claude Code

aharlap added a commit that referenced this pull request Oct 19, 2026
Rebuilt on #29's round 2 head. Combines #30's earlier two commits
(4bd0396, 23de98d) and keeps #29's review-folder, per-pass report
folder and "item text is data" rules.

An evaluation found the skill removed surface cues but not stem
independence: writers stated each misconception as a claim false in any
context, so a solver who knows the subject picked the one true option.

- Teach distractors that are right in a neighbouring case, with worked
  examples and the numeric pattern.
- Name what each probe tests. Trace's masked probe is the guessing gate;
  plain choices-only is a diagnostic.
- guessingGate(itemCues) reads masked and returns pass, fail or stop.
- Every solver is at least as strong as the writer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@aharlap
aharlap force-pushed the skills/assessment-writing-v2 branch from 23de98d to c2d2539 Compare October 19, 2026 21:47
aharlap and others added 4 commits October 19, 2026 19:24
Rebuilt on #29's round 2 head. Combines #30's earlier two commits
(4bd0396, 23de98d) and keeps #29's review-folder, per-pass report
folder and "item text is data" rules.

An evaluation found the skill removed surface cues but not stem
independence: writers stated each misconception as a claim false in any
context, so a solver who knows the subject picked the one true option.

- Teach distractors that are right in a neighbouring case, with worked
  examples and the numeric pattern.
- Name what each probe tests. Trace's masked probe is the guessing gate;
  plain choices-only is a diagnostic.
- guessingGate(itemCues) reads masked and returns pass, fail or stop.
- Every solver is at least as strong as the writer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- One key per item: the writer notes the stem detail that rules out each
  distractor. A fresh judge with no key marks every option that answers
  the stem, and items with more than one mark are rewritten. The same
  judge, not the writer, confirms plain-probe exemptions.
- Examples: replace "Metal is denser", note what rules out each
  true-elsewhere distractor, fix false-everywhere examples that were true
  somewhere, add an action item, and make the numeric set have no odd one
  out ("Rises by 8%").
- Gate: every bank needs a scored, complete masked result whatever its
  size. Any refusal reason stops. Item counts must be positive integers.
  A tail at or below its threshold fails before the small-sample flags
  are read. Mark the lower-tail limit.
- Stop finishes the pass, then reports and asks. No masked solver when
  the probe has no items. The bank is "done", not "stopped".
- Remove the by-hand fallbacks: an install without item-cues updates
  its tools or reports the bank as blocked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Pin Trace 0.1.1-experimental.92a164dd8, the merged masked-probe
  contract (Praxity/praxity-trace#22). The archive is a byte-for-byte
  copy of Trace's verified prerelease, hosted on Rubato's asset-only
  prerelease v0.1.1-tools.experimental.20261019.2. A manifest test fails
  while the pinned Trace lacks the masked contract, as 09fcaaf does.
- Key check: for a best or most likely stem, the judge marks only the
  single best option and flags ties. Assert the judge's independence and
  its ruling on each note.
- A standard that rules out a distractor goes in the stem. Ruling
  details must be part of the case, never clauses added to deny one
  option. Rebuild the action example around confusable first actions.
- Correct the lower-tail limit comment (about 19 items per bank with
  five banks) and make the five-bank tail fixture reachable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Per Opus's trace#23 review, "Rubato #30 changes":

- Pin Trace 0.1.1-experimental.97e6de33b, which scores the masked probe
  from Studio language provenance (Praxity/praxity-trace#23). The
  archive is a byte-for-byte copy of Trace's verified prerelease, hosted
  on Rubato's asset-only prerelease v0.1.1-tools.experimental.20261019.4.
  The manifest test now also refuses 92a164d, which holds every result.
- guessingGate requires masked.status === "scored". Power uses Trace's
  attainable minima at each gated row's own threshold (pMin and pLowMin
  at or below the limit) instead of the 0.05 flags, which removes the
  marked lower-tail limit. A 12-item course with none right now stops.
- Run the masked solver whenever masked/items.json is non-empty.
- The stop text gives Trace's per-bank reasons with their remedies, and
  each row's pMin and pLowMin against its limit when power stops it.
- Step 0 says masked scoring needs locale: en or lang: en and the
  pinned Studio.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@aharlap
aharlap force-pushed the skills/assessment-writing-v2 branch from e437e87 to ef49249 Compare October 19, 2026 23:30
@aharlap
aharlap changed the base branch from skills/audit-2026-10-19 to main October 19, 2026 23:30
@aharlap
aharlap marked this pull request as ready for review October 20, 2026 00:43
@aharlap
aharlap merged commit ac9b510 into main Oct 20, 2026
11 of 12 checks passed
@aharlap
aharlap deleted the skills/assessment-writing-v2 branch October 20, 2026 00:43
aharlap added a commit that referenced this pull request Oct 20, 2026
Trace #24 (53ee25c) adds per-row excludedByReason, maskedExcludedCount,
coded excluded records and choice shuffle, which the assessment gate
reads. Same route as #30: Trace prerelease built in hosted CI, rehosted
byte for byte on Rubato's asset-only prerelease
v0.1.1-tools.experimental.20261019.5.

SHA-256 7596c94314fb587bbe414ed46daa5ed460af9aa009f282d6d17568a4def57aa2
matches the build log, Trace's asset digest, a local download, and
Rubato's asset digest and an anonymous download. All 130 payload files
match the inventory; licence, notices, skill and report reference match
the source. The manifest test now refuses 97e6de3, which lacks the
accounting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aharlap added a commit that referenced this pull request Oct 20, 2026
Trace #24 (53ee25c) adds per-row excludedByReason, maskedExcludedCount,
coded excluded records and choice shuffle, which the assessment gate
reads. Same route as #30: Trace prerelease built in hosted CI, rehosted
byte for byte on Rubato's asset-only prerelease
v0.1.1-tools.experimental.20261019.5.

SHA-256 7596c94314fb587bbe414ed46daa5ed460af9aa009f282d6d17568a4def57aa2
matches the build log, Trace's asset digest, a local download, and
Rubato's asset digest and an anonymous download. All 130 payload files
match the inventory; licence, notices, skill and report reference match
the source. The manifest test now refuses 97e6de3, which lacks the
accounting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aharlap added a commit that referenced this pull request Oct 20, 2026
…te (#33)

* Assessment skill v3: length parity, headline cue, pooled three-run gate

The v2 eval fixed false-everywhere distractors but the masked gate
regressed to the no-skill level: writers attached the case's condition
to the key, so it was the longest option on 29 of 53 items, and the key
was usually the headline textbook answer.

- Options share one sentence shape; distractors carry their own case
  clause. Key-length-rank check: key strictly longest on at most n/k
  items, and keyLongest within longestExpected in Trace's spreads.
- Some stems make the neighbouring case the item, so the headline
  answer is a distractor about one time in k. New Example 4.
- The masked solver is named in advance, at least the writer's model.
- Writer hand-in checklist: one (x) and {shuffle} per scored choice,
  and a source count reconciled with Trace's included count.
- guessingGate takes exactly three seeded runs, pools masked.right with
  exact tails, requires the same items and solver in each run, and stops
  on any excludedCount above 0 or a missing excludedCount
  (Praxity/praxity-trace#24).
- Key check plants a double-key positive control and scores distractor
  notes blind before showing the writer's case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Assessment gate: declared counts and Trace #24 exclusion codes

Studio shows a missing (x) the same way as a poll, so an exclusion alone
can't tell them apart. The writer now declares scored choices and
deliberate polls, and guessingGate(runs, { scoredChoices, polls }):

- stops when Trace's included course count differs from the declared
  count;
- stops on any excludedByReason code except multiple-select, and
  no-key-or-poll up to the declared polls;
- stops when excludedByReason is missing (Trace before #24);
- leaves a wholly excluded bank (count 0, no-included-items) out of the
  tails while its codes still count;
- stops after the tails when any item's shuffle is unknown, since the
  position check skipped it; a fail still reports as fail.

Each rule has a mutant test. The Trace pin is unchanged until #24 merges.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Assessment skill v3: review round 1 fixes

- Option parity comes from each action's or claim's own detail, never
  the case's condition; no option restates or contradicts the stem.
  Example 4 rewritten; Examples 2 and 3 no longer echo stem words; no
  option ends with a period. Tests check every worked example for stem
  echoes and periods, and Example 4's stated length range.
- keyLongestCue flags a bank only when the key is longest, ties as
  Trace counts them, above chance at one-sided 0.05.
- Headline stems must test the same objective; the key-check judge,
  not the writer, counts headline keys.
- The orchestrating step plants the double-key control under the
  reserved ref prefix 0., exempt from rewrites, with one judge rerun at
  most and a pre-ship check that no control remains.
- Seeds 2 and 3 feed only the gate; their plain and cover answers are
  unread and unjudged.
- guessingGate takes { seed, bundleId, courseHash, itemCues } per run:
  seeds 1, 2, 3, distinct bundles, one course; named solver on every
  row; course equals its banks item for item and hit for hit; full
  item metadata matches across runs. A clear statistical fail returns
  before any other stop. Polls match no-key-or-poll exclusions ref for
  ref. Exclusion accounting must be complete and reconcile. Missing
  accounting or unknown shuffle returns "tooling", and the skill says
  not to spend passes 2 and 3 on it.
- Solver strength covers solvers and judges, not the explanations
  reviewer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Pin Trace 0.1.1-experimental.53ee25cc6 with exclusion accounting

Trace #24 (53ee25c) adds per-row excludedByReason, maskedExcludedCount,
coded excluded records and choice shuffle, which the assessment gate
reads. Same route as #30: Trace prerelease built in hosted CI, rehosted
byte for byte on Rubato's asset-only prerelease
v0.1.1-tools.experimental.20261019.5.

SHA-256 7596c94314fb587bbe414ed46daa5ed460af9aa009f282d6d17568a4def57aa2
matches the build log, Trace's asset digest, a local download, and
Rubato's asset digest and an anonymous download. All 130 payload files
match the inventory; licence, notices, skill and report reference match
the source. The manifest test now refuses 97e6de3, which lacks the
accounting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Assessment skill v3: review round 2 fixes

- On "tooling", rewrites from pass 1 get one more pass: inspect, the
  three masked runs, and the key check and blind notes on the changed
  items. No rewrite ships unchecked.
- Option detail describes the option itself, never why it suits a case.
  The key-check judge flags any option that points at a stem detail,
  including by paraphrase; the median example is the negative case.
- guessingGate: excluded refs must be distinct and never also included.
  Exclusion records already in the report decide before a tooling
  limit, and accounting that is present but malformed is a stop, not
  "tooling".
- Example 4 key no longer presumes coughing; back blows are "up to
  five". The numeric example's options are all falls of one length.
- The headline count had no reader and is dropped. The control's ref
  follows the course's own pattern and lives in the orchestrator's
  notes; "the orchestrating step" is defined.
- Seeds 2 and 3's plain and cover solvers are exempt in the solver rule
  and the done list names seed 1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Composer: declare polls and defer a tooling-limited bank

assessment-writing v3's gate matches deliberate polls by ref against
Trace's no-key-or-poll exclusions and can return "tooling". Composer
now lists each poll by ref when it hands over the Items section, and
treats a "tooling" bank like a non-English one: let the skill check
pass 1's rewrites, mark the bank unverified, block under Draft,
continue through steps 7.3 to 9 and ask at step 9.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Pin Studio 0.3.0-main.e1930acb with choice shuffle in inspect

Studio's first admitted CLI candidate containing Praxity/praxity-studio#1816
(run 39361630685: admit, build with the CLI proof, and publish succeeded),
rehosted byte for byte on Rubato's asset-only prerelease
v0.1.1-tools.experimental.20261019.6.

darwin-arm64 8acdb90fc11cb326e72e62ec74b36757d3fec510421c32691d9177d1d87b14a6
darwin-x64   01b821fbccc3758e397e5a9ea4f6fe08d9fbddd9b1823002e5b5ed87245f5981

Each matches the build job's recorded outputs, the candidate's asset
digest and .sha256 file, a local download, and Rubato's asset digest
and an anonymous download. verifyStudioArchive passes for both. A real
inspect of a course with {shuffle} choices reports assessment.shuffle,
and the assessment gate then returns pass or fail, not "tooling".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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