feat(spec-phase): surface zero-classification edge-probe requirements as unclassified candidates (#1110) (#1117)
Edge-probe now surfaces a zero-classification requirement (non-empty prose, no shape cue matched, no `shapes` override) as a single soft `unclassified — review manually` candidate instead of silently dropping it — the exact blind spot the probe exists to catch. Dismissible like any edge; the `shapes: []` opt-out stays silent; `TAXONOMY` (the closed 8 categories) is unchanged. Under `--auto` the candidate is left `unresolved`, never auto-`backstop` (a missing shape is not evidence an edge exists). Closes #1110
This commit is contained in:
@@ -104,8 +104,16 @@ export function applicableCategories(shapes: Shape[]): string[] {
|
||||
* taxonomy; both verification tiers require a non-empty `resolution` (an explicit AC's text
|
||||
* or a backstop note) so plan-phase has a criterion to lift.
|
||||
*/
|
||||
/**
|
||||
* Pseudo-category for a requirement whose prose matched NO shape cue (#1110). It is a soft
|
||||
* "review manually" signal, NOT a 9th taxonomy category: it stays out of `TAXONOMY` (the closed
|
||||
* eight) and only joins `EDGE_VALIDATORS.categories` so `analyzeCoverage` accepts the item.
|
||||
*/
|
||||
export const UNCLASSIFIED_CATEGORY = 'unclassified';
|
||||
const UNCLASSIFIED_PROBE = 'unclassified — review manually';
|
||||
|
||||
export const EDGE_VALIDATORS: Validators = {
|
||||
categories: TAXONOMY.map((c) => c.id),
|
||||
categories: [...TAXONOMY.map((c) => c.id), UNCLASSIFIED_CATEGORY],
|
||||
verification: ['explicit', 'backstop'],
|
||||
requiredFieldsByVerification: { explicit: ['resolution'], backstop: ['resolution'] },
|
||||
};
|
||||
@@ -162,6 +170,22 @@ export function proposeEdges(requirement: Requirement): Edge[] {
|
||||
shapes = requirement.shapes;
|
||||
} else {
|
||||
shapes = classifyShape(requirement.text);
|
||||
if (shapes.length === 0) {
|
||||
// Prose present but no shape cue matched. Do NOT silently drop it (#1110): an
|
||||
// edge-relevant requirement whose phrasing missed every cue would otherwise vanish from
|
||||
// coverage with no signal — the exact blind spot this probe exists to catch. Surface ONE
|
||||
// soft, dismissible "unclassified — review manually" candidate. The explicit `shapes: []`
|
||||
// opt-out (handled above) stays silent — that is the author's deliberate "no edge surface".
|
||||
return [{
|
||||
requirement_id: requirement.id,
|
||||
category: UNCLASSIFIED_CATEGORY,
|
||||
status: 'unresolved',
|
||||
verification: null,
|
||||
resolution: null,
|
||||
reason: null,
|
||||
probe: UNCLASSIFIED_PROBE,
|
||||
}];
|
||||
}
|
||||
}
|
||||
return applicableCategories(shapes).map((catId): Edge => {
|
||||
const cat = TAXONOMY.find((c) => c.id === catId);
|
||||
|
||||
Reference in New Issue
Block a user