mirror of
https://github.com/affaan-m/ECC.git
synced 2026-10-18 14:07:33 +02:00
fix(gateguard): do not charge the ungated arm with gate-specific holes
silence-hole and coverage-hole are claims about the gate, and an ungated arm never fires it, so classify labelled every ungated miss a coverage-hole by construction. In the 48-trial run that padded the hole counts with five rows that say nothing about the gate: coverage-hole read 7 when only 2 were the gate's. Label an ungated miss unaided-miss, which is the baseline rate and is excluded from the holes list.
This commit is contained in:
@@ -23,18 +23,28 @@ const MIN_PAIRS_FOR_A_CLAIM = 20;
|
||||
const CLASSES = Object.freeze({
|
||||
working: 'the deciding fact was obtained and the outcome is right',
|
||||
lucky: 'right outcome without ever asking: the scenario does not force the question',
|
||||
'unaided-miss': 'an ungated arm missed: the baseline rate, not a gate hole',
|
||||
'follow-through-hole': 'the deciding fact was obtained and the outcome is still wrong',
|
||||
'targeting-hole': 'the agent asked, but not for the deciding fact',
|
||||
'silence-hole': 'the gate fired and the agent still did not ask',
|
||||
'coverage-hole': 'a deciding ambiguity the gate never engaged, and the outcome is wrong'
|
||||
});
|
||||
|
||||
/** Classifies one trial from its behaviour alone. */
|
||||
/**
|
||||
* Classifies one trial from its behaviour alone.
|
||||
*
|
||||
* silence-hole and coverage-hole are statements about the gate, so they are only
|
||||
* reachable for a gated arm. An ungated arm never fires the gate, so without
|
||||
* this it would have every miss labelled coverage-hole by construction, which
|
||||
* padded the hole counts with rows that say nothing about the gate.
|
||||
*/
|
||||
function classify(row) {
|
||||
const gated = row.gated === undefined ? row.arm !== 'off' : row.gated;
|
||||
const gateFired = Number(row.gateDenials) > 0;
|
||||
if (row.disclosedDecisive) return row.passed ? 'working' : 'follow-through-hole';
|
||||
if (row.asked) return 'targeting-hole';
|
||||
if (row.passed) return 'lucky';
|
||||
if (!gated) return 'unaided-miss';
|
||||
return gateFired ? 'silence-hole' : 'coverage-hole';
|
||||
}
|
||||
|
||||
|
||||
@@ -124,6 +124,9 @@ test('classify maps each behaviour to its hole', () => {
|
||||
[{ asked: true, disclosedDecisive: false, passed: true, gateDenials: 1 }, 'targeting-hole'],
|
||||
[{ asked: false, passed: false, gateDenials: 3 }, 'silence-hole'],
|
||||
[{ asked: false, passed: false, gateDenials: 0 }, 'coverage-hole'],
|
||||
// The gate-specific holes are unreachable for an arm that has no gate, or
|
||||
// every ungated miss is a coverage-hole by construction.
|
||||
[{ arm: 'off', gated: false, asked: false, passed: false, gateDenials: 0 }, 'unaided-miss'],
|
||||
[{ asked: false, passed: true, gateDenials: 0 }, 'lucky']
|
||||
];
|
||||
for (const [fields, expected] of cases) {
|
||||
|
||||
Reference in New Issue
Block a user