Spaces:
Sleeping
Sleeping
feat(compare): bootstrap Galaxy corpus with GROUP_it_core (100)
Browse filesDefault Visualize payload is IT core first, then existing GROUP_1/GROUP_2 demos so REF sits in the galactic core; keep 2 Groups preset unchanged.
Co-authored-by: Cursor <cursoragent@cursor.com>
- src/ui/ComparePanel.js +9 -1
- src/ui/itCoreCorpus.js +39 -0
- tests/CompareBootstrap.test.js +53 -10
src/ui/ComparePanel.js
CHANGED
|
@@ -2,6 +2,7 @@ import { reorderCompareItems, sortCompareItemsByCosine } from './compareCosine.j
|
|
| 2 |
import { parseCompareInput } from './parseCompareGroups.js';
|
| 3 |
import { saeControlsMarkup, wireSaeControls } from './SaeControls.js';
|
| 4 |
import { FIELD_INFO, infoTipMarkup } from './fieldInfo.js';
|
|
|
|
| 5 |
|
| 6 |
/**
|
| 7 |
* Typical auto-manual lexicon in English (parts, fluids, systems).
|
|
@@ -53,6 +54,10 @@ export const AUTO_MANUAL_UNIQUE_EN = [...new Set(AUTO_MANUAL_VOCAB_EN)];
|
|
| 53 |
export const COMPARE_GROUPS_DEMO_TEXT = `GROUP_1 = "car, vehicle, automobile, truck, van, engine, piston, cylinder, crankshaft, camshaft, turbo, exhaust, muffler, radiator, transmission, gearbox, clutch, differential, driveshaft, steering, suspension, chassis, brake, brakes, rotor, wheel, wheels, tire, tires, rim, axle, bearing, pedal, accelerator, throttle, injector, manifold, intake, coolant, antifreeze, oil, filter, battery, alternator, starter, coil, fuse, relay, sensor, wiring, shock, spring, hood, trunk, windshield, headlight, bumper, fender, seatbelt, airbag, dashboard, speedometer, fuel, gasoline, diesel"
|
| 54 |
GROUP_2 = "sophia, isabella, victoria, florence, beatrice, eleanor, charlotte, gloria, clara, penelope, serenity, compassion, tenderness, nostalgia, melancholy, empathy, affection, gratitude, forgiveness, solitude, devotion, harmony, poetry, symphony, melody, lullaby, romance, intimacy, solace, grace, bliss, euphoria, sweetness, delight, softness, warmth, kindness, hope, peace, innocence, purity, elegance, beauty, passion, desire, yearning, whisper, caress, embrace, soul, spirit, intuition, wisdom, reverie, fantasy, butterfly, blossom, rose, orchid, petal, jasmine, violet, peony, dahlia, magnolia"`;
|
| 55 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
/**
|
| 57 |
* COMPARE presets — arrays become comma-joined; strings are written as-is (group demos).
|
| 58 |
*/
|
|
@@ -62,11 +67,13 @@ export const COMPARE_AUTO_PRESETS = {
|
|
| 62 |
sample20: AUTO_MANUAL_UNIQUE_EN.slice(0, 20),
|
| 63 |
sample50: AUTO_MANUAL_UNIQUE_EN.slice(0, 50),
|
| 64 |
groupsDemo: COMPARE_GROUPS_DEMO_TEXT,
|
|
|
|
| 65 |
};
|
| 66 |
|
| 67 |
/**
|
| 68 |
* Single source for COMPARE first-paint: textarea default + auto Visualize payload.
|
| 69 |
* Must stay grouped so GROUP_* floating badges appear without a second submit.
|
|
|
|
| 70 |
* @returns {{
|
| 71 |
* mode: 'flat'|'grouped',
|
| 72 |
* tokens: string[],
|
|
@@ -76,7 +83,7 @@ export const COMPARE_AUTO_PRESETS = {
|
|
| 76 |
* }}
|
| 77 |
*/
|
| 78 |
export function getCompareBootstrap() {
|
| 79 |
-
const textareaValue =
|
| 80 |
const parsed = parseCompareInput(textareaValue);
|
| 81 |
return { ...parsed, textareaValue };
|
| 82 |
}
|
|
@@ -134,6 +141,7 @@ export class ComparePanel {
|
|
| 134 |
<button type="button" class="btn-preset" data-preset="sample20">20 Tokens</button>
|
| 135 |
<button type="button" class="btn-preset" data-preset="sample50">50 Tokens</button>
|
| 136 |
<button type="button" class="btn-preset" data-preset="groupsDemo">2 Groups</button>
|
|
|
|
| 137 |
</div>
|
| 138 |
|
| 139 |
${saeControlsMarkup('cmp')}
|
|
|
|
| 2 |
import { parseCompareInput } from './parseCompareGroups.js';
|
| 3 |
import { saeControlsMarkup, wireSaeControls } from './SaeControls.js';
|
| 4 |
import { FIELD_INFO, infoTipMarkup } from './fieldInfo.js';
|
| 5 |
+
import { formatItCoreGroupLine } from './itCoreCorpus.js';
|
| 6 |
|
| 7 |
/**
|
| 8 |
* Typical auto-manual lexicon in English (parts, fluids, systems).
|
|
|
|
| 54 |
export const COMPARE_GROUPS_DEMO_TEXT = `GROUP_1 = "car, vehicle, automobile, truck, van, engine, piston, cylinder, crankshaft, camshaft, turbo, exhaust, muffler, radiator, transmission, gearbox, clutch, differential, driveshaft, steering, suspension, chassis, brake, brakes, rotor, wheel, wheels, tire, tires, rim, axle, bearing, pedal, accelerator, throttle, injector, manifold, intake, coolant, antifreeze, oil, filter, battery, alternator, starter, coil, fuse, relay, sensor, wiring, shock, spring, hood, trunk, windshield, headlight, bumper, fender, seatbelt, airbag, dashboard, speedometer, fuel, gasoline, diesel"
|
| 55 |
GROUP_2 = "sophia, isabella, victoria, florence, beatrice, eleanor, charlotte, gloria, clara, penelope, serenity, compassion, tenderness, nostalgia, melancholy, empathy, affection, gratitude, forgiveness, solitude, devotion, harmony, poetry, symphony, melody, lullaby, romance, intimacy, solace, grace, bliss, euphoria, sweetness, delight, softness, warmth, kindness, hope, peace, innocence, purity, elegance, beauty, passion, desire, yearning, whisper, caress, embrace, soul, spirit, intuition, wisdom, reverie, fantasy, butterfly, blossom, rose, orchid, petal, jasmine, violet, peony, dahlia, magnolia"`;
|
| 56 |
|
| 57 |
+
/** Bootstrap / Galaxy default: IT core (100) first, then existing GROUP_1 + GROUP_2 demos. */
|
| 58 |
+
export const COMPARE_GALAXY_BOOTSTRAP_TEXT = `${formatItCoreGroupLine()}
|
| 59 |
+
${COMPARE_GROUPS_DEMO_TEXT}`;
|
| 60 |
+
|
| 61 |
/**
|
| 62 |
* COMPARE presets — arrays become comma-joined; strings are written as-is (group demos).
|
| 63 |
*/
|
|
|
|
| 67 |
sample20: AUTO_MANUAL_UNIQUE_EN.slice(0, 20),
|
| 68 |
sample50: AUTO_MANUAL_UNIQUE_EN.slice(0, 50),
|
| 69 |
groupsDemo: COMPARE_GROUPS_DEMO_TEXT,
|
| 70 |
+
galaxyDemo: COMPARE_GALAXY_BOOTSTRAP_TEXT,
|
| 71 |
};
|
| 72 |
|
| 73 |
/**
|
| 74 |
* Single source for COMPARE first-paint: textarea default + auto Visualize payload.
|
| 75 |
* Must stay grouped so GROUP_* floating badges appear without a second submit.
|
| 76 |
+
* Order: GROUP_it_core → GROUP_1 → GROUP_2 (REF inside the IT core).
|
| 77 |
* @returns {{
|
| 78 |
* mode: 'flat'|'grouped',
|
| 79 |
* tokens: string[],
|
|
|
|
| 83 |
* }}
|
| 84 |
*/
|
| 85 |
export function getCompareBootstrap() {
|
| 86 |
+
const textareaValue = COMPARE_GALAXY_BOOTSTRAP_TEXT;
|
| 87 |
const parsed = parseCompareInput(textareaValue);
|
| 88 |
return { ...parsed, textareaValue };
|
| 89 |
}
|
|
|
|
| 141 |
<button type="button" class="btn-preset" data-preset="sample20">20 Tokens</button>
|
| 142 |
<button type="button" class="btn-preset" data-preset="sample50">50 Tokens</button>
|
| 143 |
<button type="button" class="btn-preset" data-preset="groupsDemo">2 Groups</button>
|
| 144 |
+
<button type="button" class="btn-preset" data-preset="galaxyDemo">3 Groups</button>
|
| 145 |
</div>
|
| 146 |
|
| 147 |
${saeControlsMarkup('cmp')}
|
src/ui/itCoreCorpus.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* Canonical GROUP_it_core corpus for Galaxy VIEW (exactly 100 unique EN IT tokens).
|
| 3 |
+
* Do not silently grow — tests assert length + uniqueness.
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
/** @type {readonly string[]} */
|
| 7 |
+
export const IT_CORE_TOKENS = Object.freeze([
|
| 8 |
+
'server', 'client', 'api', 'endpoint', 'database', 'sql', 'nosql', 'cache', 'redis', 'kafka',
|
| 9 |
+
'queue', 'microservice', 'container', 'docker', 'kubernetes', 'devops', 'cicd', 'pipeline',
|
| 10 |
+
'repository', 'git', 'commit', 'branch', 'merge', 'frontend', 'backend', 'javascript',
|
| 11 |
+
'typescript', 'python', 'rust', 'golang', 'java', 'react', 'vue', 'angular', 'nodejs',
|
| 12 |
+
'fastapi', 'django', 'flask', 'graphql', 'rest', 'json', 'protobuf', 'grpc', 'websocket',
|
| 13 |
+
'http', 'https', 'oauth', 'jwt', 'auth', 'latency', 'throughput', 'loadbalancer', 'nginx',
|
| 14 |
+
'cdn', 'dns', 'ssl', 'tls', 'certificate', 'firewall', 'vpn', 'cloud', 'aws', 'gcp', 'azure',
|
| 15 |
+
'lambda', 'serverless', 'terraform', 'ansible', 'monitoring', 'logging', 'metrics',
|
| 16 |
+
'tracing', 'prometheus', 'grafana', 'opentelemetry', 'unittest', 'integration', 'e2e',
|
| 17 |
+
'agile', 'scrum', 'sprint', 'backlog', 'kanban', 'architecture', 'modularity', 'refactor',
|
| 18 |
+
'debugging', 'profiling', 'optimization', 'concurrency', 'async', 'thread', 'process',
|
| 19 |
+
'memory', 'cpu', 'gpu', 'storage', 'network', 'protocol', 'encryption',
|
| 20 |
+
]);
|
| 21 |
+
|
| 22 |
+
export const IT_CORE_GROUP_ID = 'GROUP_it_core';
|
| 23 |
+
|
| 24 |
+
/**
|
| 25 |
+
* Textarea line for the IT galactic core group.
|
| 26 |
+
* @returns {string}
|
| 27 |
+
*/
|
| 28 |
+
export function formatItCoreGroupLine() {
|
| 29 |
+
return `${IT_CORE_GROUP_ID} = "${IT_CORE_TOKENS.join(', ')}"`;
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
/**
|
| 33 |
+
* @returns {{ length: number, unique: boolean, tokens: readonly string[] }}
|
| 34 |
+
*/
|
| 35 |
+
export function assertItCoreCorpus() {
|
| 36 |
+
const length = IT_CORE_TOKENS.length;
|
| 37 |
+
const unique = new Set(IT_CORE_TOKENS).size === length;
|
| 38 |
+
return { length, unique, tokens: IT_CORE_TOKENS };
|
| 39 |
+
}
|
tests/CompareBootstrap.test.js
CHANGED
|
@@ -2,28 +2,67 @@ import { describe, it, expect } from 'vitest';
|
|
| 2 |
import * as THREE from 'three';
|
| 3 |
import {
|
| 4 |
COMPARE_AUTO_PRESETS,
|
|
|
|
|
|
|
| 5 |
getCompareBootstrap,
|
| 6 |
} from '../src/ui/ComparePanel.js';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
import {
|
| 8 |
attachCompareGroupMeta,
|
| 9 |
mergeCompareOverlayLabels,
|
|
|
|
| 10 |
} from '../src/ui/parseCompareGroups.js';
|
| 11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
/**
|
| 13 |
-
*
|
| 14 |
-
* flat `default` (136 tokens, no groupId) → overlay showed token names forever.
|
| 15 |
*/
|
| 16 |
describe('COMPARE bootstrap ↔ GROUP overlay contract', () => {
|
| 17 |
-
it('bootstrap is
|
| 18 |
const boot = getCompareBootstrap();
|
| 19 |
expect(boot.mode).toBe('grouped');
|
| 20 |
-
expect(boot.
|
| 21 |
-
expect(boot.
|
| 22 |
-
expect(boot.
|
| 23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
});
|
| 25 |
|
| 26 |
-
it('bootstrap + attach meta → overlay shows
|
| 27 |
const boot = getCompareBootstrap();
|
| 28 |
const data = {
|
| 29 |
count: boot.tokens.length,
|
|
@@ -44,8 +83,12 @@ describe('COMPARE bootstrap ↔ GROUP overlay contract', () => {
|
|
| 44 |
groupLabel: item.groupLabel,
|
| 45 |
}));
|
| 46 |
const overlay = mergeCompareOverlayLabels(labels);
|
| 47 |
-
expect(overlay).toHaveLength(
|
| 48 |
-
expect(overlay.map((l) => l.text)).toEqual([
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
expect(overlay.every((l) => l.type === 'group')).toBe(true);
|
| 50 |
});
|
| 51 |
|
|
|
|
| 2 |
import * as THREE from 'three';
|
| 3 |
import {
|
| 4 |
COMPARE_AUTO_PRESETS,
|
| 5 |
+
COMPARE_GALAXY_BOOTSTRAP_TEXT,
|
| 6 |
+
COMPARE_GROUPS_DEMO_TEXT,
|
| 7 |
getCompareBootstrap,
|
| 8 |
} from '../src/ui/ComparePanel.js';
|
| 9 |
+
import {
|
| 10 |
+
assertItCoreCorpus,
|
| 11 |
+
IT_CORE_GROUP_ID,
|
| 12 |
+
IT_CORE_TOKENS,
|
| 13 |
+
} from '../src/ui/itCoreCorpus.js';
|
| 14 |
import {
|
| 15 |
attachCompareGroupMeta,
|
| 16 |
mergeCompareOverlayLabels,
|
| 17 |
+
parseCompareInput,
|
| 18 |
} from '../src/ui/parseCompareGroups.js';
|
| 19 |
|
| 20 |
+
describe('IT core corpus fixture', () => {
|
| 21 |
+
it('has exactly 100 unique tokens', () => {
|
| 22 |
+
const { length, unique } = assertItCoreCorpus();
|
| 23 |
+
expect(length).toBe(100);
|
| 24 |
+
expect(unique).toBe(true);
|
| 25 |
+
expect(IT_CORE_TOKENS[0]).toBe('server');
|
| 26 |
+
expect(IT_CORE_TOKENS[99]).toBe('encryption');
|
| 27 |
+
});
|
| 28 |
+
});
|
| 29 |
+
|
| 30 |
/**
|
| 31 |
+
* Bootstrap = GROUP_it_core (100) + GROUP_1 + GROUP_2; REF inside IT core.
|
|
|
|
| 32 |
*/
|
| 33 |
describe('COMPARE bootstrap ↔ GROUP overlay contract', () => {
|
| 34 |
+
it('bootstrap is 3 groups with it_core first', () => {
|
| 35 |
const boot = getCompareBootstrap();
|
| 36 |
expect(boot.mode).toBe('grouped');
|
| 37 |
+
expect(boot.textareaValue).toBe(COMPARE_GALAXY_BOOTSTRAP_TEXT);
|
| 38 |
+
expect(boot.textareaValue).toBe(COMPARE_AUTO_PRESETS.galaxyDemo);
|
| 39 |
+
expect(boot.groups.map((g) => g.id)).toEqual([
|
| 40 |
+
IT_CORE_GROUP_ID,
|
| 41 |
+
'GROUP_1',
|
| 42 |
+
'GROUP_2',
|
| 43 |
+
]);
|
| 44 |
+
expect(boot.groups[0].tokens).toHaveLength(100);
|
| 45 |
+
expect(boot.tokenMeta[0].groupId).toBe(IT_CORE_GROUP_ID);
|
| 46 |
+
expect(boot.tokens[0]).toBe('server');
|
| 47 |
+
|
| 48 |
+
const g1Start = 100;
|
| 49 |
+
const g2Start = 100 + boot.groups[1].tokens.length;
|
| 50 |
+
expect(boot.tokenMeta[g1Start].groupId).toBe('GROUP_1');
|
| 51 |
+
expect(boot.tokenMeta[g2Start].groupId).toBe('GROUP_2');
|
| 52 |
+
expect(boot.tokens.length).toBe(
|
| 53 |
+
100 + boot.groups[1].tokens.length + boot.groups[2].tokens.length,
|
| 54 |
+
);
|
| 55 |
+
expect(boot.tokens.length).toBe(230);
|
| 56 |
+
});
|
| 57 |
+
|
| 58 |
+
it('2 Groups preset remains GROUP_1 + GROUP_2 only (130)', () => {
|
| 59 |
+
const parsed = parseCompareInput(COMPARE_GROUPS_DEMO_TEXT);
|
| 60 |
+
expect(parsed.tokens).toHaveLength(130);
|
| 61 |
+
expect(parsed.groups.map((g) => g.id)).toEqual(['GROUP_1', 'GROUP_2']);
|
| 62 |
+
expect(COMPARE_AUTO_PRESETS.groupsDemo).toBe(COMPARE_GROUPS_DEMO_TEXT);
|
| 63 |
});
|
| 64 |
|
| 65 |
+
it('bootstrap + attach meta → overlay shows it_core / GROUP_1 / GROUP_2', () => {
|
| 66 |
const boot = getCompareBootstrap();
|
| 67 |
const data = {
|
| 68 |
count: boot.tokens.length,
|
|
|
|
| 83 |
groupLabel: item.groupLabel,
|
| 84 |
}));
|
| 85 |
const overlay = mergeCompareOverlayLabels(labels);
|
| 86 |
+
expect(overlay).toHaveLength(3);
|
| 87 |
+
expect(overlay.map((l) => l.text)).toEqual([
|
| 88 |
+
IT_CORE_GROUP_ID,
|
| 89 |
+
'GROUP_1',
|
| 90 |
+
'GROUP_2',
|
| 91 |
+
]);
|
| 92 |
expect(overlay.every((l) => l.type === 'group')).toBe(true);
|
| 93 |
});
|
| 94 |
|