terminalhire 0.23.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,9 +45,9 @@ var init_keytar = __esm({
45
45
  }
46
46
  });
47
47
 
48
- // node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node
48
+ // node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node
49
49
  var require_keytar = __commonJS({
50
- "node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node"(exports, module) {
50
+ "node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node"(exports, module) {
51
51
  "use strict";
52
52
  init_keytar();
53
53
  try {
@@ -193,7 +193,7 @@ var init_graph_data = __esm({
193
193
  { id: "anthropic", parents: ["llm"], synonyms: ["claude"] },
194
194
  { id: "rag", parents: ["llm"], synonyms: ["retrieval-augmented-generation"] },
195
195
  { id: "mlops", parents: ["ml"], related: [{ to: "devops", w: 0.4 }] },
196
- { id: "agents", parents: ["llm"], synonyms: ["agentic", "ai-agents", "multi-agent"], related: [{ to: "rag", w: 0.4 }] },
196
+ { id: "agents", parents: ["llm"], synonyms: ["agentic", "ai-agents", "multi-agent", "agent-orchestration"], related: [{ to: "rag", w: 0.4 }] },
197
197
  { id: "mcp", parents: ["agents"], synonyms: ["model-context-protocol"], related: [{ to: "llm", w: 0.45 }] },
198
198
  { id: "inference", parents: ["ml"], synonyms: ["model-inference", "llm-inference", "model-serving"], related: [{ to: "mlops", w: 0.5 }, { to: "llm", w: 0.4 }] },
199
199
  { id: "embeddings", parents: ["ml"], synonyms: ["embedding", "vector-embeddings"], related: [{ to: "rag", w: 0.55 }, { to: "llm", w: 0.45 }] },
@@ -459,6 +459,14 @@ var init_extract = __esm({
459
459
  id: "prompt-engineering",
460
460
  cue: /\bprompt[\s-]?engineer(?:ing|s)?\b|\b(llms?|gpt-?[0-9o]*|claude|gemini|llama|mistral|openai|anthropic|langchain|llama[\s-]?index|rag|retrieval[\s-]?augmented|embeddings?|fine[\s-]?tun(?:e|ed|ing)|vector[\s-]?(?:db|database|store)|agentic|ai agents?|chatbots?|generative ai|gen[\s-]?ai|genai|few[\s-]?shot|zero[\s-]?shot)\b/i
461
461
  }
462
+ // Plan-061 note: the AI-eng generic words (orchestration/evals/evaluation/guardrails/
463
+ // governance) were briefly added as raw agents/llm synonyms, but `normalize()` — the
464
+ // context-free firewall shared by the declaration path AND the GitHub bounty/
465
+ // contribution feeds — resolves synonyms with NO cue, so those words false-mined
466
+ // agents/llm from ordinary infra/SRE prose on every normalize() caller. A cue gate
467
+ // here only covers extractSkillTags(), not normalize(). Fix: they are NOT graph
468
+ // synonyms at all (see graph.data.ts) → they fall to the 3-tier SOFT/novel bucket,
469
+ // which is exactly where ambiguous, uncategorizable words belong. Nothing to gate.
462
470
  };
463
471
  ENG_INTENT = /\b(engineer|engineering|developer|dev\b|swe|sde|programmer|architect|full[\s-]?stack|front[\s-]?end|back[\s-]?end|devops|sre|software|coding|codebase|technical staff|tech(?:nical)? lead)\b/i;
464
472
  NON_ENG_TITLE = /\b(account executive|account manager|sales (?:rep|representative|development|manager|lead)|sdr|bdr|recruiter|recruiting|talent|marketing|administrative|business partner|billing coordinator|operations (?:administrator|coordinator)|customer success|project finance|controller|bookkeeper|graphic|brand)\b/i;
@@ -582,6 +590,69 @@ var init_idf_background = __esm({
582
590
  }
583
591
  });
584
592
 
593
+ // ../../packages/core/src/vocab/classify.ts
594
+ function editDistance(a, b, max) {
595
+ if (a === b) return 0;
596
+ if (Math.abs(a.length - b.length) > max) return max + 1;
597
+ const prev = new Array(b.length + 1);
598
+ const cur = new Array(b.length + 1);
599
+ for (let j = 0; j <= b.length; j++) prev[j] = j;
600
+ for (let i = 1; i <= a.length; i++) {
601
+ cur[0] = i;
602
+ let rowMin = cur[0];
603
+ for (let j = 1; j <= b.length; j++) {
604
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
605
+ cur[j] = Math.min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + cost);
606
+ if (cur[j] < rowMin) rowMin = cur[j];
607
+ }
608
+ if (rowMin > max) return max + 1;
609
+ for (let j = 0; j <= b.length; j++) prev[j] = cur[j];
610
+ }
611
+ return prev[b.length];
612
+ }
613
+ function canonicalOf(surface, graph) {
614
+ if (graph.ids.has(surface)) return surface;
615
+ return graph.synonyms.get(surface);
616
+ }
617
+ function nearBudget(len) {
618
+ if (len <= 3) return 0;
619
+ if (len <= 6) return 1;
620
+ return 2;
621
+ }
622
+ function classifyToken(raw, graph = GRAPH) {
623
+ const token = String(raw ?? "").toLowerCase().trim();
624
+ const exact = canonicalOf(token, graph);
625
+ if (exact) return { raw: token, tier: "matched", canonical: exact };
626
+ const budget = nearBudget(token.length);
627
+ if (budget > 0) {
628
+ let bestSurface;
629
+ let bestDist = budget + 1;
630
+ const consider = (surface) => {
631
+ const d = editDistance(token, surface, budget);
632
+ if (d <= budget && (d < bestDist || d === bestDist && bestSurface !== void 0 && (surface.length < bestSurface.length || surface.length === bestSurface.length && surface < bestSurface))) {
633
+ bestDist = d;
634
+ bestSurface = surface;
635
+ }
636
+ };
637
+ for (const id of graph.ids) consider(id);
638
+ for (const alias of graph.synonyms.keys()) consider(alias);
639
+ if (bestSurface !== void 0) {
640
+ const suggestion = canonicalOf(bestSurface, graph);
641
+ if (suggestion) return { raw: token, tier: "near-miss", suggestion };
642
+ }
643
+ }
644
+ return { raw: token, tier: "novel", soft: token };
645
+ }
646
+ function classifyTokens(raws, graph = GRAPH) {
647
+ return raws.map((r) => classifyToken(r, graph));
648
+ }
649
+ var init_classify = __esm({
650
+ "../../packages/core/src/vocab/classify.ts"() {
651
+ "use strict";
652
+ init_vocab();
653
+ }
654
+ });
655
+
585
656
  // ../../packages/core/src/vocab/index.ts
586
657
  function normalize(tokens) {
587
658
  const result = /* @__PURE__ */ new Set();
@@ -645,6 +716,7 @@ var init_vocab = __esm({
645
716
  init_graph_data();
646
717
  init_extract();
647
718
  init_idf_background();
719
+ init_classify();
648
720
  GRAPH = buildGraph(VOCAB_NODES);
649
721
  VOCABULARY = [...GRAPH.ids];
650
722
  SYNONYMS = Object.fromEntries(GRAPH.synonyms);
@@ -7062,6 +7134,8 @@ __export(src_exports, {
7062
7134
  buildIntroListItem: () => buildIntroListItem,
7063
7135
  buildIntroPayload: () => buildIntroPayload,
7064
7136
  buildReason: () => buildReason,
7137
+ classifyToken: () => classifyToken,
7138
+ classifyTokens: () => classifyTokens,
7065
7139
  composeIntroAcceptedEmail: () => composeIntroAcceptedEmail,
7066
7140
  composeIntroEmail: () => composeIntroEmail,
7067
7141
  computeAcceptanceCredential: () => computeAcceptanceCredential,
@@ -7165,9 +7239,9 @@ var init_keytar = __esm({
7165
7239
  }
7166
7240
  });
7167
7241
 
7168
- // node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node
7242
+ // node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node
7169
7243
  var require_keytar = __commonJS({
7170
- "node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node"(exports, module) {
7244
+ "node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node"(exports, module) {
7171
7245
  "use strict";
7172
7246
  init_keytar();
7173
7247
  try {
@@ -183,7 +183,7 @@ var init_graph_data = __esm({
183
183
  { id: "anthropic", parents: ["llm"], synonyms: ["claude"] },
184
184
  { id: "rag", parents: ["llm"], synonyms: ["retrieval-augmented-generation"] },
185
185
  { id: "mlops", parents: ["ml"], related: [{ to: "devops", w: 0.4 }] },
186
- { id: "agents", parents: ["llm"], synonyms: ["agentic", "ai-agents", "multi-agent"], related: [{ to: "rag", w: 0.4 }] },
186
+ { id: "agents", parents: ["llm"], synonyms: ["agentic", "ai-agents", "multi-agent", "agent-orchestration"], related: [{ to: "rag", w: 0.4 }] },
187
187
  { id: "mcp", parents: ["agents"], synonyms: ["model-context-protocol"], related: [{ to: "llm", w: 0.45 }] },
188
188
  { id: "inference", parents: ["ml"], synonyms: ["model-inference", "llm-inference", "model-serving"], related: [{ to: "mlops", w: 0.5 }, { to: "llm", w: 0.4 }] },
189
189
  { id: "embeddings", parents: ["ml"], synonyms: ["embedding", "vector-embeddings"], related: [{ to: "rag", w: 0.55 }, { to: "llm", w: 0.45 }] },
@@ -396,6 +396,14 @@ var init_idf_background = __esm({
396
396
  }
397
397
  });
398
398
 
399
+ // ../../packages/core/src/vocab/classify.ts
400
+ var init_classify = __esm({
401
+ "../../packages/core/src/vocab/classify.ts"() {
402
+ "use strict";
403
+ init_vocab();
404
+ }
405
+ });
406
+
399
407
  // ../../packages/core/src/vocab/index.ts
400
408
  var GRAPH, VOCABULARY, SYNONYMS;
401
409
  var init_vocab = __esm({
@@ -408,6 +416,7 @@ var init_vocab = __esm({
408
416
  init_graph_data();
409
417
  init_extract();
410
418
  init_idf_background();
419
+ init_classify();
411
420
  GRAPH = buildGraph(VOCAB_NODES);
412
421
  VOCABULARY = [...GRAPH.ids];
413
422
  SYNONYMS = Object.fromEntries(GRAPH.synonyms);
@@ -3992,9 +4001,9 @@ var init_keytar = __esm({
3992
4001
  }
3993
4002
  });
3994
4003
 
3995
- // node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node
4004
+ // node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node
3996
4005
  var require_keytar = __commonJS({
3997
- "node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node"(exports, module) {
4006
+ "node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node"(exports, module) {
3998
4007
  "use strict";
3999
4008
  init_keytar();
4000
4009
  try {
@@ -187,7 +187,7 @@ var init_graph_data = __esm({
187
187
  { id: "anthropic", parents: ["llm"], synonyms: ["claude"] },
188
188
  { id: "rag", parents: ["llm"], synonyms: ["retrieval-augmented-generation"] },
189
189
  { id: "mlops", parents: ["ml"], related: [{ to: "devops", w: 0.4 }] },
190
- { id: "agents", parents: ["llm"], synonyms: ["agentic", "ai-agents", "multi-agent"], related: [{ to: "rag", w: 0.4 }] },
190
+ { id: "agents", parents: ["llm"], synonyms: ["agentic", "ai-agents", "multi-agent", "agent-orchestration"], related: [{ to: "rag", w: 0.4 }] },
191
191
  { id: "mcp", parents: ["agents"], synonyms: ["model-context-protocol"], related: [{ to: "llm", w: 0.45 }] },
192
192
  { id: "inference", parents: ["ml"], synonyms: ["model-inference", "llm-inference", "model-serving"], related: [{ to: "mlops", w: 0.5 }, { to: "llm", w: 0.4 }] },
193
193
  { id: "embeddings", parents: ["ml"], synonyms: ["embedding", "vector-embeddings"], related: [{ to: "rag", w: 0.55 }, { to: "llm", w: 0.45 }] },
@@ -400,6 +400,14 @@ var init_idf_background = __esm({
400
400
  }
401
401
  });
402
402
 
403
+ // ../../packages/core/src/vocab/classify.ts
404
+ var init_classify = __esm({
405
+ "../../packages/core/src/vocab/classify.ts"() {
406
+ "use strict";
407
+ init_vocab();
408
+ }
409
+ });
410
+
403
411
  // ../../packages/core/src/vocab/index.ts
404
412
  function normalize(tokens) {
405
413
  const result = /* @__PURE__ */ new Set();
@@ -425,6 +433,7 @@ var init_vocab = __esm({
425
433
  init_graph_data();
426
434
  init_extract();
427
435
  init_idf_background();
436
+ init_classify();
428
437
  GRAPH = buildGraph(VOCAB_NODES);
429
438
  VOCABULARY = [...GRAPH.ids];
430
439
  SYNONYMS = Object.fromEntries(GRAPH.synonyms);
@@ -4020,9 +4029,9 @@ var init_keytar = __esm({
4020
4029
  }
4021
4030
  });
4022
4031
 
4023
- // node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node
4032
+ // node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node
4024
4033
  var require_keytar = __commonJS({
4025
- "node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node"(exports, module) {
4034
+ "node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node"(exports, module) {
4026
4035
  "use strict";
4027
4036
  init_keytar();
4028
4037
  try {
@@ -193,7 +193,7 @@ var init_graph_data = __esm({
193
193
  { id: "anthropic", parents: ["llm"], synonyms: ["claude"] },
194
194
  { id: "rag", parents: ["llm"], synonyms: ["retrieval-augmented-generation"] },
195
195
  { id: "mlops", parents: ["ml"], related: [{ to: "devops", w: 0.4 }] },
196
- { id: "agents", parents: ["llm"], synonyms: ["agentic", "ai-agents", "multi-agent"], related: [{ to: "rag", w: 0.4 }] },
196
+ { id: "agents", parents: ["llm"], synonyms: ["agentic", "ai-agents", "multi-agent", "agent-orchestration"], related: [{ to: "rag", w: 0.4 }] },
197
197
  { id: "mcp", parents: ["agents"], synonyms: ["model-context-protocol"], related: [{ to: "llm", w: 0.45 }] },
198
198
  { id: "inference", parents: ["ml"], synonyms: ["model-inference", "llm-inference", "model-serving"], related: [{ to: "mlops", w: 0.5 }, { to: "llm", w: 0.4 }] },
199
199
  { id: "embeddings", parents: ["ml"], synonyms: ["embedding", "vector-embeddings"], related: [{ to: "rag", w: 0.55 }, { to: "llm", w: 0.45 }] },
@@ -459,6 +459,14 @@ var init_extract = __esm({
459
459
  id: "prompt-engineering",
460
460
  cue: /\bprompt[\s-]?engineer(?:ing|s)?\b|\b(llms?|gpt-?[0-9o]*|claude|gemini|llama|mistral|openai|anthropic|langchain|llama[\s-]?index|rag|retrieval[\s-]?augmented|embeddings?|fine[\s-]?tun(?:e|ed|ing)|vector[\s-]?(?:db|database|store)|agentic|ai agents?|chatbots?|generative ai|gen[\s-]?ai|genai|few[\s-]?shot|zero[\s-]?shot)\b/i
461
461
  }
462
+ // Plan-061 note: the AI-eng generic words (orchestration/evals/evaluation/guardrails/
463
+ // governance) were briefly added as raw agents/llm synonyms, but `normalize()` — the
464
+ // context-free firewall shared by the declaration path AND the GitHub bounty/
465
+ // contribution feeds — resolves synonyms with NO cue, so those words false-mined
466
+ // agents/llm from ordinary infra/SRE prose on every normalize() caller. A cue gate
467
+ // here only covers extractSkillTags(), not normalize(). Fix: they are NOT graph
468
+ // synonyms at all (see graph.data.ts) → they fall to the 3-tier SOFT/novel bucket,
469
+ // which is exactly where ambiguous, uncategorizable words belong. Nothing to gate.
462
470
  };
463
471
  ENG_INTENT = /\b(engineer|engineering|developer|dev\b|swe|sde|programmer|architect|full[\s-]?stack|front[\s-]?end|back[\s-]?end|devops|sre|software|coding|codebase|technical staff|tech(?:nical)? lead)\b/i;
464
472
  NON_ENG_TITLE = /\b(account executive|account manager|sales (?:rep|representative|development|manager|lead)|sdr|bdr|recruiter|recruiting|talent|marketing|administrative|business partner|billing coordinator|operations (?:administrator|coordinator)|customer success|project finance|controller|bookkeeper|graphic|brand)\b/i;
@@ -582,6 +590,69 @@ var init_idf_background = __esm({
582
590
  }
583
591
  });
584
592
 
593
+ // ../../packages/core/src/vocab/classify.ts
594
+ function editDistance(a, b, max) {
595
+ if (a === b) return 0;
596
+ if (Math.abs(a.length - b.length) > max) return max + 1;
597
+ const prev = new Array(b.length + 1);
598
+ const cur = new Array(b.length + 1);
599
+ for (let j = 0; j <= b.length; j++) prev[j] = j;
600
+ for (let i = 1; i <= a.length; i++) {
601
+ cur[0] = i;
602
+ let rowMin = cur[0];
603
+ for (let j = 1; j <= b.length; j++) {
604
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
605
+ cur[j] = Math.min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + cost);
606
+ if (cur[j] < rowMin) rowMin = cur[j];
607
+ }
608
+ if (rowMin > max) return max + 1;
609
+ for (let j = 0; j <= b.length; j++) prev[j] = cur[j];
610
+ }
611
+ return prev[b.length];
612
+ }
613
+ function canonicalOf(surface, graph) {
614
+ if (graph.ids.has(surface)) return surface;
615
+ return graph.synonyms.get(surface);
616
+ }
617
+ function nearBudget(len) {
618
+ if (len <= 3) return 0;
619
+ if (len <= 6) return 1;
620
+ return 2;
621
+ }
622
+ function classifyToken(raw, graph = GRAPH) {
623
+ const token = String(raw ?? "").toLowerCase().trim();
624
+ const exact = canonicalOf(token, graph);
625
+ if (exact) return { raw: token, tier: "matched", canonical: exact };
626
+ const budget = nearBudget(token.length);
627
+ if (budget > 0) {
628
+ let bestSurface;
629
+ let bestDist = budget + 1;
630
+ const consider = (surface) => {
631
+ const d = editDistance(token, surface, budget);
632
+ if (d <= budget && (d < bestDist || d === bestDist && bestSurface !== void 0 && (surface.length < bestSurface.length || surface.length === bestSurface.length && surface < bestSurface))) {
633
+ bestDist = d;
634
+ bestSurface = surface;
635
+ }
636
+ };
637
+ for (const id of graph.ids) consider(id);
638
+ for (const alias of graph.synonyms.keys()) consider(alias);
639
+ if (bestSurface !== void 0) {
640
+ const suggestion = canonicalOf(bestSurface, graph);
641
+ if (suggestion) return { raw: token, tier: "near-miss", suggestion };
642
+ }
643
+ }
644
+ return { raw: token, tier: "novel", soft: token };
645
+ }
646
+ function classifyTokens(raws, graph = GRAPH) {
647
+ return raws.map((r) => classifyToken(r, graph));
648
+ }
649
+ var init_classify = __esm({
650
+ "../../packages/core/src/vocab/classify.ts"() {
651
+ "use strict";
652
+ init_vocab();
653
+ }
654
+ });
655
+
585
656
  // ../../packages/core/src/vocab/index.ts
586
657
  function normalize(tokens) {
587
658
  const result = /* @__PURE__ */ new Set();
@@ -645,6 +716,7 @@ var init_vocab = __esm({
645
716
  init_graph_data();
646
717
  init_extract();
647
718
  init_idf_background();
719
+ init_classify();
648
720
  GRAPH = buildGraph(VOCAB_NODES);
649
721
  VOCABULARY = [...GRAPH.ids];
650
722
  SYNONYMS = Object.fromEntries(GRAPH.synonyms);
@@ -7062,6 +7134,8 @@ __export(src_exports, {
7062
7134
  buildIntroListItem: () => buildIntroListItem,
7063
7135
  buildIntroPayload: () => buildIntroPayload,
7064
7136
  buildReason: () => buildReason,
7137
+ classifyToken: () => classifyToken,
7138
+ classifyTokens: () => classifyTokens,
7065
7139
  composeIntroAcceptedEmail: () => composeIntroAcceptedEmail,
7066
7140
  composeIntroEmail: () => composeIntroEmail,
7067
7141
  computeAcceptanceCredential: () => computeAcceptanceCredential,
@@ -7288,9 +7362,9 @@ var init_keytar = __esm({
7288
7362
  }
7289
7363
  });
7290
7364
 
7291
- // node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node
7365
+ // node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node
7292
7366
  var require_keytar = __commonJS({
7293
- "node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node"(exports, module) {
7367
+ "node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node"(exports, module) {
7294
7368
  "use strict";
7295
7369
  init_keytar();
7296
7370
  try {
@@ -187,7 +187,7 @@ var init_graph_data = __esm({
187
187
  { id: "anthropic", parents: ["llm"], synonyms: ["claude"] },
188
188
  { id: "rag", parents: ["llm"], synonyms: ["retrieval-augmented-generation"] },
189
189
  { id: "mlops", parents: ["ml"], related: [{ to: "devops", w: 0.4 }] },
190
- { id: "agents", parents: ["llm"], synonyms: ["agentic", "ai-agents", "multi-agent"], related: [{ to: "rag", w: 0.4 }] },
190
+ { id: "agents", parents: ["llm"], synonyms: ["agentic", "ai-agents", "multi-agent", "agent-orchestration"], related: [{ to: "rag", w: 0.4 }] },
191
191
  { id: "mcp", parents: ["agents"], synonyms: ["model-context-protocol"], related: [{ to: "llm", w: 0.45 }] },
192
192
  { id: "inference", parents: ["ml"], synonyms: ["model-inference", "llm-inference", "model-serving"], related: [{ to: "mlops", w: 0.5 }, { to: "llm", w: 0.4 }] },
193
193
  { id: "embeddings", parents: ["ml"], synonyms: ["embedding", "vector-embeddings"], related: [{ to: "rag", w: 0.55 }, { to: "llm", w: 0.45 }] },
@@ -453,6 +453,14 @@ var init_extract = __esm({
453
453
  id: "prompt-engineering",
454
454
  cue: /\bprompt[\s-]?engineer(?:ing|s)?\b|\b(llms?|gpt-?[0-9o]*|claude|gemini|llama|mistral|openai|anthropic|langchain|llama[\s-]?index|rag|retrieval[\s-]?augmented|embeddings?|fine[\s-]?tun(?:e|ed|ing)|vector[\s-]?(?:db|database|store)|agentic|ai agents?|chatbots?|generative ai|gen[\s-]?ai|genai|few[\s-]?shot|zero[\s-]?shot)\b/i
455
455
  }
456
+ // Plan-061 note: the AI-eng generic words (orchestration/evals/evaluation/guardrails/
457
+ // governance) were briefly added as raw agents/llm synonyms, but `normalize()` — the
458
+ // context-free firewall shared by the declaration path AND the GitHub bounty/
459
+ // contribution feeds — resolves synonyms with NO cue, so those words false-mined
460
+ // agents/llm from ordinary infra/SRE prose on every normalize() caller. A cue gate
461
+ // here only covers extractSkillTags(), not normalize(). Fix: they are NOT graph
462
+ // synonyms at all (see graph.data.ts) → they fall to the 3-tier SOFT/novel bucket,
463
+ // which is exactly where ambiguous, uncategorizable words belong. Nothing to gate.
456
464
  };
457
465
  ENG_INTENT = /\b(engineer|engineering|developer|dev\b|swe|sde|programmer|architect|full[\s-]?stack|front[\s-]?end|back[\s-]?end|devops|sre|software|coding|codebase|technical staff|tech(?:nical)? lead)\b/i;
458
466
  NON_ENG_TITLE = /\b(account executive|account manager|sales (?:rep|representative|development|manager|lead)|sdr|bdr|recruiter|recruiting|talent|marketing|administrative|business partner|billing coordinator|operations (?:administrator|coordinator)|customer success|project finance|controller|bookkeeper|graphic|brand)\b/i;
@@ -576,6 +584,14 @@ var init_idf_background = __esm({
576
584
  }
577
585
  });
578
586
 
587
+ // ../../packages/core/src/vocab/classify.ts
588
+ var init_classify = __esm({
589
+ "../../packages/core/src/vocab/classify.ts"() {
590
+ "use strict";
591
+ init_vocab();
592
+ }
593
+ });
594
+
579
595
  // ../../packages/core/src/vocab/index.ts
580
596
  function normalize(tokens) {
581
597
  const result = /* @__PURE__ */ new Set();
@@ -614,6 +630,7 @@ var init_vocab = __esm({
614
630
  init_graph_data();
615
631
  init_extract();
616
632
  init_idf_background();
633
+ init_classify();
617
634
  GRAPH = buildGraph(VOCAB_NODES);
618
635
  VOCABULARY = [...GRAPH.ids];
619
636
  SYNONYMS = Object.fromEntries(GRAPH.synonyms);
@@ -1343,9 +1360,9 @@ var init_keytar = __esm({
1343
1360
  }
1344
1361
  });
1345
1362
 
1346
- // node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node
1363
+ // node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node
1347
1364
  var require_keytar = __commonJS({
1348
- "node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node"(exports, module) {
1365
+ "node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node"(exports, module) {
1349
1366
  "use strict";
1350
1367
  init_keytar();
1351
1368
  try {
@@ -193,7 +193,7 @@ var init_graph_data = __esm({
193
193
  { id: "anthropic", parents: ["llm"], synonyms: ["claude"] },
194
194
  { id: "rag", parents: ["llm"], synonyms: ["retrieval-augmented-generation"] },
195
195
  { id: "mlops", parents: ["ml"], related: [{ to: "devops", w: 0.4 }] },
196
- { id: "agents", parents: ["llm"], synonyms: ["agentic", "ai-agents", "multi-agent"], related: [{ to: "rag", w: 0.4 }] },
196
+ { id: "agents", parents: ["llm"], synonyms: ["agentic", "ai-agents", "multi-agent", "agent-orchestration"], related: [{ to: "rag", w: 0.4 }] },
197
197
  { id: "mcp", parents: ["agents"], synonyms: ["model-context-protocol"], related: [{ to: "llm", w: 0.45 }] },
198
198
  { id: "inference", parents: ["ml"], synonyms: ["model-inference", "llm-inference", "model-serving"], related: [{ to: "mlops", w: 0.5 }, { to: "llm", w: 0.4 }] },
199
199
  { id: "embeddings", parents: ["ml"], synonyms: ["embedding", "vector-embeddings"], related: [{ to: "rag", w: 0.55 }, { to: "llm", w: 0.45 }] },
@@ -459,6 +459,14 @@ var init_extract = __esm({
459
459
  id: "prompt-engineering",
460
460
  cue: /\bprompt[\s-]?engineer(?:ing|s)?\b|\b(llms?|gpt-?[0-9o]*|claude|gemini|llama|mistral|openai|anthropic|langchain|llama[\s-]?index|rag|retrieval[\s-]?augmented|embeddings?|fine[\s-]?tun(?:e|ed|ing)|vector[\s-]?(?:db|database|store)|agentic|ai agents?|chatbots?|generative ai|gen[\s-]?ai|genai|few[\s-]?shot|zero[\s-]?shot)\b/i
461
461
  }
462
+ // Plan-061 note: the AI-eng generic words (orchestration/evals/evaluation/guardrails/
463
+ // governance) were briefly added as raw agents/llm synonyms, but `normalize()` — the
464
+ // context-free firewall shared by the declaration path AND the GitHub bounty/
465
+ // contribution feeds — resolves synonyms with NO cue, so those words false-mined
466
+ // agents/llm from ordinary infra/SRE prose on every normalize() caller. A cue gate
467
+ // here only covers extractSkillTags(), not normalize(). Fix: they are NOT graph
468
+ // synonyms at all (see graph.data.ts) → they fall to the 3-tier SOFT/novel bucket,
469
+ // which is exactly where ambiguous, uncategorizable words belong. Nothing to gate.
462
470
  };
463
471
  ENG_INTENT = /\b(engineer|engineering|developer|dev\b|swe|sde|programmer|architect|full[\s-]?stack|front[\s-]?end|back[\s-]?end|devops|sre|software|coding|codebase|technical staff|tech(?:nical)? lead)\b/i;
464
472
  NON_ENG_TITLE = /\b(account executive|account manager|sales (?:rep|representative|development|manager|lead)|sdr|bdr|recruiter|recruiting|talent|marketing|administrative|business partner|billing coordinator|operations (?:administrator|coordinator)|customer success|project finance|controller|bookkeeper|graphic|brand)\b/i;
@@ -582,6 +590,69 @@ var init_idf_background = __esm({
582
590
  }
583
591
  });
584
592
 
593
+ // ../../packages/core/src/vocab/classify.ts
594
+ function editDistance(a, b, max) {
595
+ if (a === b) return 0;
596
+ if (Math.abs(a.length - b.length) > max) return max + 1;
597
+ const prev = new Array(b.length + 1);
598
+ const cur = new Array(b.length + 1);
599
+ for (let j = 0; j <= b.length; j++) prev[j] = j;
600
+ for (let i = 1; i <= a.length; i++) {
601
+ cur[0] = i;
602
+ let rowMin = cur[0];
603
+ for (let j = 1; j <= b.length; j++) {
604
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
605
+ cur[j] = Math.min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + cost);
606
+ if (cur[j] < rowMin) rowMin = cur[j];
607
+ }
608
+ if (rowMin > max) return max + 1;
609
+ for (let j = 0; j <= b.length; j++) prev[j] = cur[j];
610
+ }
611
+ return prev[b.length];
612
+ }
613
+ function canonicalOf(surface, graph) {
614
+ if (graph.ids.has(surface)) return surface;
615
+ return graph.synonyms.get(surface);
616
+ }
617
+ function nearBudget(len) {
618
+ if (len <= 3) return 0;
619
+ if (len <= 6) return 1;
620
+ return 2;
621
+ }
622
+ function classifyToken(raw, graph = GRAPH) {
623
+ const token = String(raw ?? "").toLowerCase().trim();
624
+ const exact = canonicalOf(token, graph);
625
+ if (exact) return { raw: token, tier: "matched", canonical: exact };
626
+ const budget = nearBudget(token.length);
627
+ if (budget > 0) {
628
+ let bestSurface;
629
+ let bestDist = budget + 1;
630
+ const consider = (surface) => {
631
+ const d = editDistance(token, surface, budget);
632
+ if (d <= budget && (d < bestDist || d === bestDist && bestSurface !== void 0 && (surface.length < bestSurface.length || surface.length === bestSurface.length && surface < bestSurface))) {
633
+ bestDist = d;
634
+ bestSurface = surface;
635
+ }
636
+ };
637
+ for (const id of graph.ids) consider(id);
638
+ for (const alias of graph.synonyms.keys()) consider(alias);
639
+ if (bestSurface !== void 0) {
640
+ const suggestion = canonicalOf(bestSurface, graph);
641
+ if (suggestion) return { raw: token, tier: "near-miss", suggestion };
642
+ }
643
+ }
644
+ return { raw: token, tier: "novel", soft: token };
645
+ }
646
+ function classifyTokens(raws, graph = GRAPH) {
647
+ return raws.map((r) => classifyToken(r, graph));
648
+ }
649
+ var init_classify = __esm({
650
+ "../../packages/core/src/vocab/classify.ts"() {
651
+ "use strict";
652
+ init_vocab();
653
+ }
654
+ });
655
+
585
656
  // ../../packages/core/src/vocab/index.ts
586
657
  function normalize(tokens) {
587
658
  const result = /* @__PURE__ */ new Set();
@@ -645,6 +716,7 @@ var init_vocab = __esm({
645
716
  init_graph_data();
646
717
  init_extract();
647
718
  init_idf_background();
719
+ init_classify();
648
720
  GRAPH = buildGraph(VOCAB_NODES);
649
721
  VOCABULARY = [...GRAPH.ids];
650
722
  SYNONYMS = Object.fromEntries(GRAPH.synonyms);
@@ -7062,6 +7134,8 @@ __export(src_exports, {
7062
7134
  buildIntroListItem: () => buildIntroListItem,
7063
7135
  buildIntroPayload: () => buildIntroPayload,
7064
7136
  buildReason: () => buildReason,
7137
+ classifyToken: () => classifyToken,
7138
+ classifyTokens: () => classifyTokens,
7065
7139
  composeIntroAcceptedEmail: () => composeIntroAcceptedEmail,
7066
7140
  composeIntroEmail: () => composeIntroEmail,
7067
7141
  computeAcceptanceCredential: () => computeAcceptanceCredential,
@@ -7165,9 +7239,9 @@ var init_keytar = __esm({
7165
7239
  }
7166
7240
  });
7167
7241
 
7168
- // node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node
7242
+ // node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node
7169
7243
  var require_keytar = __commonJS({
7170
- "node-file:/private/tmp/claude-501/-Users-ericgang-job-placement-inline/91995792-9cff-48f4-ae9c-dee9e36fc319/scratchpad/release-v0230/node_modules/keytar/build/Release/keytar.node"(exports, module) {
7244
+ "node-file:/Users/ericgang/job-placement-inline-wt/release-v0240/node_modules/keytar/build/Release/keytar.node"(exports, module) {
7171
7245
  "use strict";
7172
7246
  init_keytar();
7173
7247
  try {