fix(m3): AI-assist scope + confidence gate + grouped wood categories
- inference: _taxonomy_lists hands the model the synced species leaves + wood leaves + case-insensitive attribute terms (was furniture roots / empty) - inference: CALL1_SEED pins exact flat schema + *_confidence keys, drops grade - inference: _gate maps field->confidence key correctly (was species_id_confidence), reads nested shape as safety net, omits grade (METADATA-40) - review.svelte: figure gets AI assist, grade dropped from AI (owner judgment) - MultiSelect: grouped mode (parents non-selectable headers, selectable leaves) - METADATA-40 updated: grade not suggested by Call 1
This commit is contained in:
@@ -30,7 +30,7 @@
|
||||
|
||||
// --- Derived taxonomy option lists (resolve by slug, never hardcoded ids) ---
|
||||
let speciesOpts: Opt[] = [];
|
||||
let woodCatOpts: Opt[] = [];
|
||||
let woodCatGroups: import('./MultiSelect.svelte').Group[] = [];
|
||||
let edgeOpts: Opt[] = [];
|
||||
let figureOpts: Opt[] = [];
|
||||
let gradeOpts: Opt[] = [];
|
||||
@@ -57,7 +57,17 @@
|
||||
return (attr?.terms ?? []).map((t) => ({ id: t.id, name: t.name, ai: false }));
|
||||
};
|
||||
speciesOpts = childrenOf(speciesGrouper).map((c) => ({ id: c.id, name: c.name, ai: false }));
|
||||
woodCatOpts = childrenOf(wcatGrouper).map((c) => ({ id: c.id, name: c.name, ai: false }));
|
||||
// Wood categories: parent/child grouped (METADATA-10 — parents group only, never
|
||||
// assigned). Each direct child of `wcat` that has its own children becomes a parent
|
||||
// group with those children as leaves; a child with no children is a leaf under the
|
||||
// (implicit) top group. This keeps the full tree visible with non-selectable parents.
|
||||
woodCatGroups = (childrenOf(wcatGrouper)).map((parent) => {
|
||||
const kids = cats.filter((c) => c.parent_id === parent.id);
|
||||
const leaves: Opt[] = kids.length
|
||||
? kids.map((c) => ({ id: c.id, name: c.name, ai: false }))
|
||||
: [{ id: parent.id, name: parent.name, ai: false }];
|
||||
return { parent: { id: parent.id, name: parent.name }, leaves };
|
||||
});
|
||||
edgeOpts = termsOf('edge type');
|
||||
figureOpts = termsOf('figure');
|
||||
gradeOpts = termsOf('grade');
|
||||
@@ -216,7 +226,7 @@
|
||||
}
|
||||
if (s.edge_type_term_id) edgeTypeId = s.edge_type_term_id;
|
||||
if (s.figure_term_ids) { figureIds = [...s.figure_term_ids]; recs.push(...s.figure_term_ids); }
|
||||
if (s.grade_term_id) gradeId = s.grade_term_id;
|
||||
// Grade is not AI-suggested (METADATA-40) — owner judgment. Do not auto-fill.
|
||||
aiRecommendations = recs;
|
||||
aiNote = recs.length ? `AI suggested ${recs.length} field${recs.length === 1 ? '' : 's'} — review & edit below.` : 'No confident AI suggestions.';
|
||||
await commitReview();
|
||||
@@ -330,7 +340,7 @@
|
||||
<!-- Wood categories (multi, searchable list, AI-assist) -->
|
||||
<MultiSelect
|
||||
label="Wood categories"
|
||||
options={woodCatOpts}
|
||||
groups={woodCatGroups}
|
||||
selected={woodCatIds}
|
||||
placeholder="Choose wood categories"
|
||||
testid="wood-cat"
|
||||
@@ -349,18 +359,21 @@
|
||||
</div>
|
||||
|
||||
<!-- Figure (multi, searchable list, AI-assist) -->
|
||||
<MultiSelect
|
||||
label="Figure"
|
||||
options={figureOpts}
|
||||
selected={figureIds}
|
||||
placeholder="Choose figure"
|
||||
testid="figure"
|
||||
onToggle={(id) => (figureIds = toggleMulti(figureIds, id))}
|
||||
/>
|
||||
|
||||
<!-- Grade / Thickness / Moisture (single, AI-assist) -->
|
||||
<div class="field">
|
||||
<label class="lbl" for="grade">Grade <span class="ai">AI assist</span></label>
|
||||
<label class="lbl">Figure <span class="ai">AI assist</span></label>
|
||||
<MultiSelect
|
||||
label="Figure"
|
||||
options={figureOpts}
|
||||
selected={figureIds}
|
||||
placeholder="Choose figure"
|
||||
testid="figure"
|
||||
onToggle={(id) => (figureIds = toggleMulti(figureIds, id))}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Grade (single, owner judgment — NOT AI-assisted per METADATA-40) -->
|
||||
<div class="field">
|
||||
<label class="lbl" for="grade">Grade</label>
|
||||
<select id="grade" class="sel" data-testid="grade" bind:value={gradeId} on:change={commitReview}>
|
||||
<option value="">— select —</option>
|
||||
{#each gradeOpts as o (o.id)}<option value={o.id}>{o.name}</option>{/each}
|
||||
|
||||
Reference in New Issue
Block a user