knowme-careerforge-skill 0.0.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/LICENSE +21 -0
- package/README.md +227 -0
- package/README.zh-CN.md +231 -0
- package/SKILL.md +179 -0
- package/agents/claude/knowme-careerforge.md +16 -0
- package/agents/codex/knowme-careerforge.yaml +15 -0
- package/agents/cursor/knowme-careerforge.mdc +12 -0
- package/agents/gemini/knowme-careerforge.json +6 -0
- package/agents/opencode/skill.yaml +11 -0
- package/agents/windsurf/knowme-careerforge.rules +10 -0
- package/bin/knowme.js +32 -0
- package/dist/cli/src/commands/init.d.ts +10 -0
- package/dist/cli/src/commands/init.js +130 -0
- package/dist/cli/src/commands/list.d.ts +5 -0
- package/dist/cli/src/commands/list.js +92 -0
- package/dist/cli/src/index.d.ts +6 -0
- package/dist/cli/src/index.js +149 -0
- package/dist/scripts/render-pdf.d.ts +11 -0
- package/dist/scripts/render-pdf.js +105 -0
- package/dist/scripts/validate-ats.d.ts +23 -0
- package/dist/scripts/validate-ats.js +169 -0
- package/dist/scripts/validate-layout.d.ts +24 -0
- package/dist/scripts/validate-layout.js +161 -0
- package/package.json +58 -0
- package/scripts/analyze-jd.py +108 -0
- package/scripts/build-gallery.py +233 -0
- package/scripts/build-knowledge.py +81 -0
- package/scripts/instantiate-resume.py +83 -0
- package/scripts/release.py +101 -0
- package/scripts/render-pdf.ts +86 -0
- package/scripts/run-all-tests.py +41 -0
- package/scripts/search-template.py +147 -0
- package/scripts/sync-version.py +57 -0
- package/scripts/validate-ats.ts +173 -0
- package/scripts/validate-layout.ts +161 -0
- package/scripts/validate-resume.py +139 -0
- package/skill.json +47 -0
- package/src/knowledge/ats-rules.json +37 -0
- package/src/knowledge/career/seniority-signals.json +24 -0
- package/src/knowledge/index.json +734 -0
- package/src/knowledge/industries/enterprise-saas.json +21 -0
- package/src/knowledge/industries/fintech.json +21 -0
- package/src/knowledge/industries/tech-ai.json +21 -0
- package/src/knowledge/layouts.json +59 -0
- package/src/knowledge/resume/action-verbs.json +20 -0
- package/src/knowledge/resume/fab-model.json +22 -0
- package/src/knowledge/roles/ai-agent-engineer.json +52 -0
- package/src/knowledge/roles/android-engineer.json +45 -0
- package/src/knowledge/roles/architect.json +48 -0
- package/src/knowledge/roles/cpp-systems.json +47 -0
- package/src/knowledge/roles/frontend.json +49 -0
- package/src/knowledge/roles/ios-engineer.json +45 -0
- package/src/knowledge/roles/java-backend.json +49 -0
- package/src/knowledge/roles/node-fullstack.json +49 -0
- package/src/knowledge/roles/product-manager.json +48 -0
- package/src/knowledge/skills/skill-matrix.json +29 -0
- package/src/knowledge/styles.json +73 -0
- package/src/knowledge/templates.json +255 -0
- package/src/references/ats.md +17 -0
- package/src/references/evidence-first.md +22 -0
- package/src/references/pdf.md +40 -0
- package/src/references/resume-writing.md +25 -0
- package/src/references/template-design.md +57 -0
- package/src/templates/classic/README.md +12 -0
- package/src/templates/classic/metadata.json +34 -0
- package/src/templates/classic/style.css +164 -0
- package/src/templates/classic/template.html +133 -0
- package/src/templates/common/resume-contract.md +69 -0
- package/src/templates/executive/README.md +12 -0
- package/src/templates/executive/metadata.json +37 -0
- package/src/templates/executive/style.css +235 -0
- package/src/templates/executive/template.html +101 -0
- package/src/templates/minimal/README.md +12 -0
- package/src/templates/minimal/metadata.json +37 -0
- package/src/templates/minimal/style.css +219 -0
- package/src/templates/minimal/template.html +114 -0
- package/src/templates/modern/README.md +12 -0
- package/src/templates/modern/metadata.json +38 -0
- package/src/templates/modern/style.css +277 -0
- package/src/templates/modern/template.html +139 -0
- package/src/workflows/analyze-job.md +16 -0
- package/src/workflows/define-goal.md +16 -0
- package/src/workflows/forge-resume.md +25 -0
- package/src/workflows/know-me.md +21 -0
- package/src/workflows/position.md +19 -0
- package/src/workflows/review.md +31 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: An agent-native skill for self-discovery, career positioning, and tailored resume engineering.
|
|
3
|
+
globs: ["workspace/*", "src/**/*"]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# KnowMe CareerForge — Claude Code Skill
|
|
7
|
+
|
|
8
|
+
Know Yourself. Define Your Direction. Forge Your Opportunity.
|
|
9
|
+
|
|
10
|
+
When activated, follow the 6-stage workflow:
|
|
11
|
+
1. **Know Me**: Extract candidate facts, classify into L1~L3 evidence.
|
|
12
|
+
2. **Define**: Establish target role, seniority, and Core Value Proposition.
|
|
13
|
+
3. **Understand**: Analyze target JD via `python3 scripts/analyze-jd.py`.
|
|
14
|
+
4. **Position**: Perform gap analysis, map evidence, design Resume Strategy.
|
|
15
|
+
5. **CareerForge**: Search template (`python3 scripts/search-template.py`), instantiate `workspace/resume.html`, calibrate CSS tokens.
|
|
16
|
+
6. **Review & Dual QA**: Run `python3 scripts/validate-resume.py`, self-heal overflow, render `workspace/resume.pdf` via `npx ts-node scripts/render-pdf.ts`.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
name: knowme-careerforge
|
|
2
|
+
description: An agent-native skill for self-discovery, career positioning, and tailored resume engineering.
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
entrypoint: SKILL.md
|
|
5
|
+
tools:
|
|
6
|
+
- name: search-template
|
|
7
|
+
command: python3 scripts/search-template.py
|
|
8
|
+
- name: analyze-jd
|
|
9
|
+
command: python3 scripts/analyze-jd.py
|
|
10
|
+
- name: instantiate-resume
|
|
11
|
+
command: python3 scripts/instantiate-resume.py
|
|
12
|
+
- name: validate-resume
|
|
13
|
+
command: python3 scripts/validate-resume.py
|
|
14
|
+
- name: render-pdf
|
|
15
|
+
command: npx ts-node scripts/render-pdf.ts
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: KnowMe CareerForge — Agent-native career positioning and resume engineering
|
|
3
|
+
globs: ["workspace/*", "src/**/*"]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# KnowMe CareerForge MDC Rules
|
|
7
|
+
|
|
8
|
+
1. Enforce Evidence-First discipline: Never hallucinate ungrounded claims (L1~L3 only).
|
|
9
|
+
2. Edit exclusively in `workspace/resume.html` intermediate working canvas.
|
|
10
|
+
3. Use `python3 scripts/search-template.py` to pick the optimal template.
|
|
11
|
+
4. Use `python3 scripts/instantiate-resume.py` to generate the self-contained canvas.
|
|
12
|
+
5. Validate using `python3 scripts/validate-resume.py` before rendering PDF.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "knowme-careerforge",
|
|
3
|
+
"description": "An agent-native skill for self-discovery, career positioning, and tailored resume engineering.",
|
|
4
|
+
"instructions": "Execute the 6-stage KnowMe CareerForge workflow: Know Me (L1~L3 evidence) -> Define -> Understand (JD signals) -> Position -> Forge (HTML canvas & tokens) -> Review (Dual QA & PDF export).",
|
|
5
|
+
"entrypoint": "SKILL.md"
|
|
6
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
name: knowme-careerforge
|
|
2
|
+
displayName: KnowMe CareerForge
|
|
3
|
+
description: An agent-native skill for self-discovery, career positioning, and tailored resume engineering.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
schema: 1.0
|
|
6
|
+
entrypoint: SKILL.md
|
|
7
|
+
tags:
|
|
8
|
+
- career
|
|
9
|
+
- resume-engineering
|
|
10
|
+
- ats-friendly
|
|
11
|
+
- html-canvas
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# KnowMe CareerForge — Windsurf Rules
|
|
2
|
+
# Trigger: Career discovery, resume tailoring, JD analysis
|
|
3
|
+
|
|
4
|
+
When user requests resume tailoring or career analysis:
|
|
5
|
+
1. Extract candidate facts and tag with Evidence Level (L1~L3).
|
|
6
|
+
2. Analyze target JD requirements using scripts/analyze-jd.py.
|
|
7
|
+
3. Recommend best template using scripts/search-template.py.
|
|
8
|
+
4. Instantiate workspace/resume.html and calibrate CSS variables.
|
|
9
|
+
5. Run scripts/validate-resume.py to check DOM fit and ATS compatibility.
|
|
10
|
+
6. Export final PDF using scripts/render-pdf.ts.
|
package/bin/knowme.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* KnowMe CareerForge CLI Executable Entrypoint
|
|
4
|
+
* Standalone zero-dependency executable for npx knowme-careerforge / npm global install.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
|
|
10
|
+
const distEntry = path.join(__dirname, '..', 'dist', 'cli', 'src', 'index.js');
|
|
11
|
+
const srcEntry = path.join(__dirname, '..', 'cli', 'src', 'index.ts');
|
|
12
|
+
|
|
13
|
+
if (fs.existsSync(distEntry)) {
|
|
14
|
+
const cli = require(distEntry);
|
|
15
|
+
if (typeof cli.main === 'function') {
|
|
16
|
+
cli.main();
|
|
17
|
+
}
|
|
18
|
+
} else if (fs.existsSync(srcEntry)) {
|
|
19
|
+
try {
|
|
20
|
+
require('ts-node/register');
|
|
21
|
+
const cli = require(srcEntry);
|
|
22
|
+
if (typeof cli.main === 'function') {
|
|
23
|
+
cli.main();
|
|
24
|
+
}
|
|
25
|
+
} catch (e) {
|
|
26
|
+
console.error('[!] Precompiled CLI not found. Please run "npm run build" first.');
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
} else {
|
|
30
|
+
console.error('[!] KnowMe CLI entrypoint not found.');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* KnowMe CareerForge CLI — Init Command
|
|
4
|
+
* 一键将 Skill 注入并配置至指定 AI Agent 平台环境。
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.runInit = runInit;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const os = __importStar(require("os"));
|
|
44
|
+
const SUPPORTED_PLATFORMS = ['claude', 'codex', 'cursor', 'windsurf', 'gemini', 'opencode'];
|
|
45
|
+
function findPackageRoot(startDir) {
|
|
46
|
+
let curr = startDir;
|
|
47
|
+
for (let i = 0; i < 6; i++) {
|
|
48
|
+
if (fs.existsSync(path.join(curr, 'src', 'templates')) && fs.existsSync(path.join(curr, 'SKILL.md'))) {
|
|
49
|
+
return curr;
|
|
50
|
+
}
|
|
51
|
+
curr = path.dirname(curr);
|
|
52
|
+
}
|
|
53
|
+
return path.resolve(startDir, '../../..');
|
|
54
|
+
}
|
|
55
|
+
function runInit(options) {
|
|
56
|
+
const rootDir = findPackageRoot(__dirname);
|
|
57
|
+
const projectDir = options.projectDir ? path.resolve(options.projectDir) : process.cwd();
|
|
58
|
+
const homeDir = os.homedir();
|
|
59
|
+
const targetPlatforms = options.all
|
|
60
|
+
? SUPPORTED_PLATFORMS
|
|
61
|
+
: options.platform
|
|
62
|
+
? [options.platform.toLowerCase()]
|
|
63
|
+
: ['cursor'];
|
|
64
|
+
console.log('==============================================================');
|
|
65
|
+
console.log(' KnowMe CareerForge CLI — Skill Initializer');
|
|
66
|
+
console.log(` Source Skill : ${rootDir}`);
|
|
67
|
+
console.log(` Target Project: ${projectDir}`);
|
|
68
|
+
console.log(` Platforms : ${targetPlatforms.join(', ')}`);
|
|
69
|
+
console.log('==============================================================');
|
|
70
|
+
for (const plat of targetPlatforms) {
|
|
71
|
+
try {
|
|
72
|
+
switch (plat) {
|
|
73
|
+
case 'claude': {
|
|
74
|
+
const claudeDir = path.join(homeDir, '.claude', 'skills', 'knowme-careerforge');
|
|
75
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
76
|
+
const skillMd = fs.readFileSync(path.join(rootDir, 'SKILL.md'), 'utf-8');
|
|
77
|
+
fs.writeFileSync(path.join(claudeDir, 'SKILL.md'), skillMd, 'utf-8');
|
|
78
|
+
console.log(`[✓] Claude Code Skill configured -> ${claudeDir}`);
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
case 'codex': {
|
|
82
|
+
const codexDir = path.join(homeDir, '.codex', 'skills', 'knowme-careerforge');
|
|
83
|
+
fs.mkdirSync(codexDir, { recursive: true });
|
|
84
|
+
const skillMd = fs.readFileSync(path.join(rootDir, 'SKILL.md'), 'utf-8');
|
|
85
|
+
fs.writeFileSync(path.join(codexDir, 'SKILL.md'), skillMd, 'utf-8');
|
|
86
|
+
console.log(`[✓] Codex Native Skill configured -> ${codexDir}`);
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
case 'cursor': {
|
|
90
|
+
const cursorRulesDir = path.join(projectDir, '.cursor', 'rules');
|
|
91
|
+
fs.mkdirSync(cursorRulesDir, { recursive: true });
|
|
92
|
+
const mdcContent = fs.readFileSync(path.join(rootDir, 'agents', 'cursor', 'knowme-careerforge.mdc'), 'utf-8');
|
|
93
|
+
fs.writeFileSync(path.join(cursorRulesDir, 'knowme-careerforge.mdc'), mdcContent, 'utf-8');
|
|
94
|
+
console.log(`[✓] Cursor MDC Rule configured -> ${path.join(cursorRulesDir, 'knowme-careerforge.mdc')}`);
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
case 'windsurf': {
|
|
98
|
+
const windsurfRulePath = path.join(projectDir, '.windsurfrules');
|
|
99
|
+
const ruleContent = fs.readFileSync(path.join(rootDir, 'agents', 'windsurf', 'knowme-careerforge.rules'), 'utf-8');
|
|
100
|
+
fs.appendFileSync(windsurfRulePath, `\n\n${ruleContent}`, 'utf-8');
|
|
101
|
+
console.log(`[✓] Windsurf Rule configured -> ${windsurfRulePath}`);
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
case 'gemini': {
|
|
105
|
+
const geminiDir = path.join(homeDir, '.gemini', 'skills');
|
|
106
|
+
fs.mkdirSync(geminiDir, { recursive: true });
|
|
107
|
+
const geminiJson = fs.readFileSync(path.join(rootDir, 'agents', 'gemini', 'knowme-careerforge.json'), 'utf-8');
|
|
108
|
+
fs.writeFileSync(path.join(geminiDir, 'knowme-careerforge.json'), geminiJson, 'utf-8');
|
|
109
|
+
console.log(`[✓] Gemini CLI Skill configured -> ${path.join(geminiDir, 'knowme-careerforge.json')}`);
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
case 'opencode': {
|
|
113
|
+
const opencodeDir = path.join(projectDir, '.opencode', 'skills', 'knowme-careerforge');
|
|
114
|
+
fs.mkdirSync(opencodeDir, { recursive: true });
|
|
115
|
+
const skillYaml = fs.readFileSync(path.join(rootDir, 'agents', 'opencode', 'skill.yaml'), 'utf-8');
|
|
116
|
+
fs.writeFileSync(path.join(opencodeDir, 'skill.yaml'), skillYaml, 'utf-8');
|
|
117
|
+
console.log(`[✓] OpenCode Skill configured -> ${opencodeDir}`);
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
default:
|
|
121
|
+
console.log(`[!] Unknown platform: ${plat}. Supported: ${SUPPORTED_PLATFORMS.join(', ')}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
126
|
+
console.error(`[✗] Failed to initialize ${plat}: ${msg}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
console.log('\n[✓] Skill setup complete. You can now use knowme-careerforge in your agent workflows!');
|
|
130
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* KnowMe CareerForge CLI — List Command
|
|
4
|
+
* 列出本地知识库中所有可用岗位技能画像、核心模板与布局样式。
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.runList = runList;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
function getRootDir() {
|
|
44
|
+
let curr = __dirname;
|
|
45
|
+
for (let i = 0; i < 6; i++) {
|
|
46
|
+
if (fs.existsSync(path.join(curr, 'src', 'templates')) && fs.existsSync(path.join(curr, 'SKILL.md'))) {
|
|
47
|
+
return curr;
|
|
48
|
+
}
|
|
49
|
+
curr = path.dirname(curr);
|
|
50
|
+
}
|
|
51
|
+
return path.resolve(__dirname, '../../..');
|
|
52
|
+
}
|
|
53
|
+
function runList() {
|
|
54
|
+
const rootDir = getRootDir();
|
|
55
|
+
const rolesDir = path.join(rootDir, 'src', 'knowledge', 'roles');
|
|
56
|
+
const templatesDir = path.join(rootDir, 'src', 'templates');
|
|
57
|
+
console.log('==============================================================');
|
|
58
|
+
console.log(' KnowMe CareerForge — Available Roles & Templates Inventory');
|
|
59
|
+
console.log(` Package Root: ${rootDir}`);
|
|
60
|
+
console.log('==============================================================');
|
|
61
|
+
// 1. 列出岗位画像
|
|
62
|
+
console.log('\n[1. Structured Role Knowledge Profiles]:');
|
|
63
|
+
if (fs.existsSync(rolesDir)) {
|
|
64
|
+
const roleFiles = fs.readdirSync(rolesDir).filter(f => f.endsWith('.json'));
|
|
65
|
+
for (const rf of roleFiles) {
|
|
66
|
+
try {
|
|
67
|
+
const data = JSON.parse(fs.readFileSync(path.join(rolesDir, rf), 'utf-8'));
|
|
68
|
+
console.log(` • [${data.id}] ${data.name} (${data.category})`);
|
|
69
|
+
console.log(` Must-have: ${(data.mustHaveSkills || []).slice(0, 4).join(', ')}`);
|
|
70
|
+
}
|
|
71
|
+
catch { }
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// 2. 列出核心模板
|
|
75
|
+
console.log('\n[2. Core HTML Resume Templates]:');
|
|
76
|
+
if (fs.existsSync(templatesDir)) {
|
|
77
|
+
const tDirs = fs.readdirSync(templatesDir).filter(d => d !== 'common');
|
|
78
|
+
for (const td of tDirs) {
|
|
79
|
+
const metaPath = path.join(templatesDir, td, 'metadata.json');
|
|
80
|
+
if (fs.existsSync(metaPath)) {
|
|
81
|
+
try {
|
|
82
|
+
const meta = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
|
|
83
|
+
console.log(` • [${meta.id}] ${meta.name} (Style: ${meta.style})`);
|
|
84
|
+
console.log(` Target: ${meta.layout?.targetPages} page(s) | ATS: ${meta.atsScoreTier} | Tone: ${meta.visualStyle?.tone}`);
|
|
85
|
+
console.log(` Tokens: ${(meta.customizableTokens || []).slice(0, 3).join(', ')}`);
|
|
86
|
+
}
|
|
87
|
+
catch { }
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
console.log('\n==============================================================');
|
|
92
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* KnowMe CareerForge CLI — Main Entry Point
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.showHelp = showHelp;
|
|
41
|
+
exports.main = main;
|
|
42
|
+
const child_process = __importStar(require("child_process"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const init_1 = require("./commands/init");
|
|
45
|
+
const list_1 = require("./commands/list");
|
|
46
|
+
function findPackageRoot(startDir) {
|
|
47
|
+
let curr = startDir;
|
|
48
|
+
for (let i = 0; i < 6; i++) {
|
|
49
|
+
if (require('fs').existsSync(path.join(curr, 'src', 'templates')) && require('fs').existsSync(path.join(curr, 'SKILL.md'))) {
|
|
50
|
+
return curr;
|
|
51
|
+
}
|
|
52
|
+
curr = path.dirname(curr);
|
|
53
|
+
}
|
|
54
|
+
return path.resolve(startDir, '../../..');
|
|
55
|
+
}
|
|
56
|
+
function showHelp() {
|
|
57
|
+
console.log(`
|
|
58
|
+
======================================================================
|
|
59
|
+
KnowMe CareerForge CLI — Know Yourself. Define Your Direction.
|
|
60
|
+
======================================================================
|
|
61
|
+
|
|
62
|
+
Usage:
|
|
63
|
+
knowme <command> [options]
|
|
64
|
+
|
|
65
|
+
Commands:
|
|
66
|
+
init Install and configure Skill for AI Agent platforms (cursor, claude, codex, windsurf, gemini, opencode)
|
|
67
|
+
list Display all available role profiles and HTML templates
|
|
68
|
+
search <role> Search and rank templates for a specific role (e.g. knowme search "AI Agent Engineer")
|
|
69
|
+
validate Validate working canvas HTML layout & ATS compliance
|
|
70
|
+
gallery Build & refresh static HTML template gallery
|
|
71
|
+
test Run full automated test suite
|
|
72
|
+
help Show this help message
|
|
73
|
+
|
|
74
|
+
Options (for init):
|
|
75
|
+
--ai, -a <platform> Target platform (claude, codex, cursor, windsurf, gemini, opencode)
|
|
76
|
+
--all Install to all supported platforms
|
|
77
|
+
--project, -p <dir> Target project directory (default: current directory)
|
|
78
|
+
|
|
79
|
+
Examples:
|
|
80
|
+
npx knowme-careerforge init --ai cursor
|
|
81
|
+
npx knowme-careerforge init --ai claude
|
|
82
|
+
npx knowme-careerforge init --all
|
|
83
|
+
npx knowme-careerforge list
|
|
84
|
+
npx knowme-careerforge search "Senior Frontend Architect"
|
|
85
|
+
npx knowme-careerforge validate
|
|
86
|
+
`);
|
|
87
|
+
}
|
|
88
|
+
function main() {
|
|
89
|
+
const args = process.argv.slice(2);
|
|
90
|
+
const command = args[0] || 'help';
|
|
91
|
+
const rootDir = findPackageRoot(__dirname);
|
|
92
|
+
switch (command) {
|
|
93
|
+
case 'init': {
|
|
94
|
+
let platform = 'cursor';
|
|
95
|
+
let all = false;
|
|
96
|
+
let projectDir = process.cwd();
|
|
97
|
+
for (let i = 1; i < args.length; i++) {
|
|
98
|
+
if (args[i] === '--ai' || args[i] === '-a') {
|
|
99
|
+
platform = args[i + 1] || 'cursor';
|
|
100
|
+
i++;
|
|
101
|
+
}
|
|
102
|
+
else if (args[i] === '--all') {
|
|
103
|
+
all = true;
|
|
104
|
+
}
|
|
105
|
+
else if (args[i] === '--project' || args[i] === '-p') {
|
|
106
|
+
projectDir = args[i + 1] || process.cwd();
|
|
107
|
+
i++;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
(0, init_1.runInit)({ platform, all, projectDir });
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
case 'list':
|
|
114
|
+
(0, list_1.runList)();
|
|
115
|
+
break;
|
|
116
|
+
case 'search': {
|
|
117
|
+
const role = args[1] || 'AI Agent Engineer';
|
|
118
|
+
const scriptPath = path.join(rootDir, 'scripts', 'search-template.py');
|
|
119
|
+
const passArgs = args.slice(1);
|
|
120
|
+
child_process.spawnSync('python3', [scriptPath, ...passArgs], { stdio: 'inherit' });
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
case 'validate': {
|
|
124
|
+
const scriptPath = path.join(rootDir, 'scripts', 'validate-resume.py');
|
|
125
|
+
const passArgs = args.slice(1);
|
|
126
|
+
child_process.spawnSync('python3', [scriptPath, ...passArgs], { stdio: 'inherit' });
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
case 'gallery': {
|
|
130
|
+
const scriptPath = path.join(rootDir, 'scripts', 'build-gallery.py');
|
|
131
|
+
child_process.spawnSync('python3', [scriptPath], { stdio: 'inherit' });
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
case 'test': {
|
|
135
|
+
const scriptPath = path.join(rootDir, 'scripts', 'run-all-tests.py');
|
|
136
|
+
child_process.spawnSync('python3', [scriptPath], { stdio: 'inherit' });
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
case 'help':
|
|
140
|
+
case '--help':
|
|
141
|
+
case '-h':
|
|
142
|
+
default:
|
|
143
|
+
showHelp();
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (require.main === module) {
|
|
148
|
+
main();
|
|
149
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
/**
|
|
3
|
+
* KnowMe CareerForge — Playwright Deterministic PDF Renderer
|
|
4
|
+
* 加载自包含 HTML 中间工作区,等待字体及样式准备就绪,输出标准像素级 A4 PDF。
|
|
5
|
+
*/
|
|
6
|
+
interface RenderOptions {
|
|
7
|
+
inputHtml: string;
|
|
8
|
+
outputPdf: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function renderResumePdf(options: RenderOptions): Promise<void>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* KnowMe CareerForge — Playwright Deterministic PDF Renderer
|
|
5
|
+
* 加载自包含 HTML 中间工作区,等待字体及样式准备就绪,输出标准像素级 A4 PDF。
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.renderResumePdf = renderResumePdf;
|
|
42
|
+
const playwright_1 = require("playwright");
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
async function renderResumePdf(options) {
|
|
46
|
+
const absoluteHtml = path.resolve(options.inputHtml);
|
|
47
|
+
const absolutePdf = path.resolve(options.outputPdf);
|
|
48
|
+
if (!fs.existsSync(absoluteHtml)) {
|
|
49
|
+
throw new Error(`Input HTML file does not exist: ${absoluteHtml}`);
|
|
50
|
+
}
|
|
51
|
+
// 确保输出目录存在
|
|
52
|
+
const outputDir = path.dirname(absolutePdf);
|
|
53
|
+
if (!fs.existsSync(outputDir)) {
|
|
54
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
55
|
+
}
|
|
56
|
+
console.log('======================================================');
|
|
57
|
+
console.log(' KnowMe CareerForge — Playwright PDF Renderer');
|
|
58
|
+
console.log(` Source Canvas : ${absoluteHtml}`);
|
|
59
|
+
console.log(` Target PDF : ${absolutePdf}`);
|
|
60
|
+
console.log('======================================================');
|
|
61
|
+
const browser = await playwright_1.chromium.launch({ headless: true });
|
|
62
|
+
const context = await browser.newContext({
|
|
63
|
+
viewport: { width: 794, height: 1123 }, // A4 at 96 DPI
|
|
64
|
+
deviceScaleFactor: 2
|
|
65
|
+
});
|
|
66
|
+
const page = await context.newPage();
|
|
67
|
+
await page.goto(`file://${absoluteHtml}`, { waitUntil: 'networkidle' });
|
|
68
|
+
// 确保所有 Web 字体准备就绪
|
|
69
|
+
await page.evaluateHandle('document.fonts.ready');
|
|
70
|
+
await page.pdf({
|
|
71
|
+
path: absolutePdf,
|
|
72
|
+
format: 'A4',
|
|
73
|
+
printBackground: true,
|
|
74
|
+
preferCSSPageSize: true,
|
|
75
|
+
margin: { top: '0px', right: '0px', bottom: '0px', left: '0px' }
|
|
76
|
+
});
|
|
77
|
+
await browser.close();
|
|
78
|
+
console.log(`[✓] Deterministic PDF Rendered Successfully -> ${absolutePdf}`);
|
|
79
|
+
}
|
|
80
|
+
async function main() {
|
|
81
|
+
const args = process.argv.slice(2);
|
|
82
|
+
let inputHtml = 'workspace/resume.html';
|
|
83
|
+
let outputPdf = 'workspace/resume.pdf';
|
|
84
|
+
for (let i = 0; i < args.length; i++) {
|
|
85
|
+
if (args[i] === '--input' || args[i] === '-i') {
|
|
86
|
+
inputHtml = args[i + 1];
|
|
87
|
+
i++;
|
|
88
|
+
}
|
|
89
|
+
else if (args[i] === '--output' || args[i] === '-o') {
|
|
90
|
+
outputPdf = args[i + 1];
|
|
91
|
+
i++;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
await renderResumePdf({ inputHtml, outputPdf });
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
99
|
+
console.error(`[✗] PDF Rendering Failed: ${errorMsg}`);
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (require.main === module) {
|
|
104
|
+
main();
|
|
105
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
/**
|
|
3
|
+
* KnowMe CareerForge — ATS Text Flow & Heading Hierarchy Inspector
|
|
4
|
+
* 验证 HTML 简历中的关键文本可提取性、标头层级规范与 ATS 机器解析友好度。
|
|
5
|
+
*/
|
|
6
|
+
interface AtsValidationResult {
|
|
7
|
+
status: 'PASS' | 'WARN' | 'FAIL';
|
|
8
|
+
candidateName: string | null;
|
|
9
|
+
detectedContacts: {
|
|
10
|
+
phone: string | null;
|
|
11
|
+
email: string | null;
|
|
12
|
+
};
|
|
13
|
+
headingsFound: Array<{
|
|
14
|
+
level: string;
|
|
15
|
+
text: string;
|
|
16
|
+
isStandard: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
totalTextLength: number;
|
|
19
|
+
warnings: string[];
|
|
20
|
+
errors: string[];
|
|
21
|
+
}
|
|
22
|
+
export declare function validateAts(htmlPath: string): Promise<AtsValidationResult>;
|
|
23
|
+
export {};
|