hbauzan Cursor commited on
Commit
5b669f6
·
1 Parent(s): 25ea490

feat(compare): bootstrap Galaxy corpus with GROUP_it_core (100)

Browse files

Default 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 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 = COMPARE_GROUPS_DEMO_TEXT;
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
- * Regression: textarea default was groupsDemo but COMPARE entry auto-loaded
14
- * flat `default` (136 tokens, no groupId) → overlay showed token names forever.
15
  */
16
  describe('COMPARE bootstrap ↔ GROUP overlay contract', () => {
17
- it('bootstrap is grouped and matches groupsDemo token count', () => {
18
  const boot = getCompareBootstrap();
19
  expect(boot.mode).toBe('grouped');
20
- expect(boot.tokens.length).toBe(130);
21
- expect(boot.tokenMeta[0].groupId).toBe('GROUP_1');
22
- expect(boot.tokenMeta[65].groupId).toBe('GROUP_2');
23
- expect(boot.textareaValue).toBe(COMPARE_AUTO_PRESETS.groupsDemo);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  });
25
 
26
- it('bootstrap + attach meta → overlay shows only GROUP_1 / GROUP_2', () => {
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(2);
48
- expect(overlay.map((l) => l.text)).toEqual(['GROUP_1', 'GROUP_2']);
 
 
 
 
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