terminalhire 0.23.0 → 0.24.1
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.
- package/dist/bin/claim-push-bg.js +2 -2
- package/dist/bin/jpi-bounties.js +77 -3
- package/dist/bin/jpi-chat-read.js +12 -3
- package/dist/bin/jpi-chat.js +12 -3
- package/dist/bin/jpi-claim.js +77 -3
- package/dist/bin/jpi-contribute.js +20 -3
- package/dist/bin/jpi-devs.js +77 -3
- package/dist/bin/jpi-dispatch.js +288 -28
- package/dist/bin/jpi-hub.js +231 -16
- package/dist/bin/jpi-inbox.js +12 -3
- package/dist/bin/jpi-init.js +75 -1
- package/dist/bin/jpi-intro.js +12 -3
- package/dist/bin/jpi-jobs.js +77 -3
- package/dist/bin/jpi-learn.js +12 -3
- package/dist/bin/jpi-login.js +77 -3
- package/dist/bin/jpi-profile.js +12 -3
- package/dist/bin/jpi-project.js +121 -7
- package/dist/bin/jpi-refresh.js +77 -3
- package/dist/bin/jpi-save.js +12 -3
- package/dist/bin/jpi-spinner.js +1 -1
- package/dist/bin/jpi-sync.js +12 -3
- package/dist/bin/jpi-trajectory.js +23 -9
- package/dist/bin/spinner.js +1 -1
- package/dist/bin/tui-core.js +10 -3
- package/dist/src/chat-client.js +3 -3
- package/dist/src/chat-keystore.js +3 -3
- package/dist/src/github-auth.js +2 -2
- package/dist/src/intro.js +12 -3
- package/dist/src/profile.js +3 -3
- package/dist/src/signal.js +1 -1
- package/dist/src/trajectory.js +23 -9
- package/package.json +1 -1
|
@@ -45,9 +45,9 @@ var init_keytar = __esm({
|
|
|
45
45
|
}
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
// node-file:/
|
|
48
|
+
// node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
|
|
49
49
|
var require_keytar = __commonJS({
|
|
50
|
-
"node-file:/
|
|
50
|
+
"node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
51
51
|
"use strict";
|
|
52
52
|
init_keytar();
|
|
53
53
|
try {
|
package/dist/bin/jpi-bounties.js
CHANGED
|
@@ -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:/
|
|
7242
|
+
// node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
|
|
7169
7243
|
var require_keytar = __commonJS({
|
|
7170
|
-
"node-file:/
|
|
7244
|
+
"node-file:/Users/ericgang/job-placement-inline/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:/
|
|
4004
|
+
// node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
|
|
3996
4005
|
var require_keytar = __commonJS({
|
|
3997
|
-
"node-file:/
|
|
4006
|
+
"node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
3998
4007
|
"use strict";
|
|
3999
4008
|
init_keytar();
|
|
4000
4009
|
try {
|
package/dist/bin/jpi-chat.js
CHANGED
|
@@ -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:/
|
|
4032
|
+
// node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
|
|
4024
4033
|
var require_keytar = __commonJS({
|
|
4025
|
-
"node-file:/
|
|
4034
|
+
"node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
4026
4035
|
"use strict";
|
|
4027
4036
|
init_keytar();
|
|
4028
4037
|
try {
|
package/dist/bin/jpi-claim.js
CHANGED
|
@@ -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:/
|
|
7365
|
+
// node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
|
|
7292
7366
|
var require_keytar = __commonJS({
|
|
7293
|
-
"node-file:/
|
|
7367
|
+
"node-file:/Users/ericgang/job-placement-inline/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:/
|
|
1363
|
+
// node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
|
|
1347
1364
|
var require_keytar = __commonJS({
|
|
1348
|
-
"node-file:/
|
|
1365
|
+
"node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
1349
1366
|
"use strict";
|
|
1350
1367
|
init_keytar();
|
|
1351
1368
|
try {
|
package/dist/bin/jpi-devs.js
CHANGED
|
@@ -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:/
|
|
7242
|
+
// node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node
|
|
7169
7243
|
var require_keytar = __commonJS({
|
|
7170
|
-
"node-file:/
|
|
7244
|
+
"node-file:/Users/ericgang/job-placement-inline/node_modules/keytar/build/Release/keytar.node"(exports, module) {
|
|
7171
7245
|
"use strict";
|
|
7172
7246
|
init_keytar();
|
|
7173
7247
|
try {
|