@dzhechkov/harness-core 0.3.8 → 0.3.10
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/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/pretrain.d.ts +33 -0
- package/dist/pretrain.d.ts.map +1 -0
- package/dist/pretrain.js +241 -0
- package/dist/pretrain.js.map +1 -0
- package/dist/sync-upstream.d.ts +11 -0
- package/dist/sync-upstream.d.ts.map +1 -1
- package/dist/sync-upstream.js +34 -1
- package/dist/sync-upstream.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +4 -2
- package/src/pretrain.ts +281 -0
- package/src/sync-upstream.ts +42 -1
package/dist/index.d.ts
CHANGED
|
@@ -12,11 +12,13 @@ export * from './operations.js';
|
|
|
12
12
|
export * from './workflows.js';
|
|
13
13
|
export { createSkill } from './create-skill.js';
|
|
14
14
|
export type { CreateSkillOptions, CreateSkillResult } from './create-skill.js';
|
|
15
|
-
export { checkUpstream, loadSourcesManifest } from './sync-upstream.js';
|
|
16
|
-
export type { SyncUpstreamReport, UpstreamCheckResult, SourcesManifest } from './sync-upstream.js';
|
|
15
|
+
export { checkUpstream, checkAllUpstream, discoverSourcePackages, loadSourcesManifest } from './sync-upstream.js';
|
|
16
|
+
export type { SyncUpstreamReport, UpstreamCheckResult, SourcesManifest, SourcePackageInfo } from './sync-upstream.js';
|
|
17
17
|
export { benchmarkSkill, benchmarkSkills, compareSkills } from './benchmark.js';
|
|
18
18
|
export { buildRegistry, searchRegistry, filterByCategory } from './registry.js';
|
|
19
19
|
export { recommend } from './recommend.js';
|
|
20
|
+
export { pretrain } from './pretrain.js';
|
|
21
|
+
export type { PretrainResult, DetectedTech } from './pretrain.js';
|
|
20
22
|
export type { RecommendationReport, SkillRecommendation } from './recommend.js';
|
|
21
23
|
export { discoverPackages, publishPackages } from './publish.js';
|
|
22
24
|
export { fetchAllDownloads } from './downloads.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,yDAAyD;AACzD,eAAO,MAAM,oBAAoB,UAAU,CAAC;AAE5C,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,yDAAyD;AACzD,eAAO,MAAM,oBAAoB,UAAU,CAAC;AAE5C,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAClH,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACtH,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClE,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAChE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAChF,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC7D,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -11,10 +11,11 @@ export * from './targets.js';
|
|
|
11
11
|
export * from './operations.js';
|
|
12
12
|
export * from './workflows.js';
|
|
13
13
|
export { createSkill } from './create-skill.js';
|
|
14
|
-
export { checkUpstream, loadSourcesManifest } from './sync-upstream.js';
|
|
14
|
+
export { checkUpstream, checkAllUpstream, discoverSourcePackages, loadSourcesManifest } from './sync-upstream.js';
|
|
15
15
|
export { benchmarkSkill, benchmarkSkills, compareSkills } from './benchmark.js';
|
|
16
16
|
export { buildRegistry, searchRegistry, filterByCategory } from './registry.js';
|
|
17
17
|
export { recommend } from './recommend.js';
|
|
18
|
+
export { pretrain } from './pretrain.js';
|
|
18
19
|
export { discoverPackages, publishPackages } from './publish.js';
|
|
19
20
|
export { fetchAllDownloads } from './downloads.js';
|
|
20
21
|
export { discoverInstalled, checkUpgrades } from './upgrade.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,yDAAyD;AACzD,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC;AAE5C,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,yDAAyD;AACzD,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC;AAE5C,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAElH,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pretrain — bootstrap intelligence by analyzing the target project.
|
|
3
|
+
*
|
|
4
|
+
* Scans the project's file structure, package.json, and tech stack to
|
|
5
|
+
* automatically recommend the right skills and presets. Runs during
|
|
6
|
+
* `dz init --pretrain` to eliminate manual preset selection.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
/** Detected technology in the project. */
|
|
11
|
+
export interface DetectedTech {
|
|
12
|
+
readonly name: string;
|
|
13
|
+
readonly category: string;
|
|
14
|
+
readonly confidence: number;
|
|
15
|
+
readonly source: string;
|
|
16
|
+
}
|
|
17
|
+
/** Pretrain analysis result. */
|
|
18
|
+
export interface PretrainResult {
|
|
19
|
+
readonly projectName: string;
|
|
20
|
+
readonly techs: readonly DetectedTech[];
|
|
21
|
+
readonly recommendedPresets: readonly string[];
|
|
22
|
+
readonly recommendedSkills: readonly string[];
|
|
23
|
+
readonly projectType: string;
|
|
24
|
+
readonly hasTests: boolean;
|
|
25
|
+
readonly hasDocker: boolean;
|
|
26
|
+
readonly hasCI: boolean;
|
|
27
|
+
readonly hasTerraform: boolean;
|
|
28
|
+
readonly hasKubernetes: boolean;
|
|
29
|
+
readonly packageCount: number;
|
|
30
|
+
}
|
|
31
|
+
/** Run pretrain analysis on a project. */
|
|
32
|
+
export declare function pretrain(projectRoot: string): PretrainResult;
|
|
33
|
+
//# sourceMappingURL=pretrain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pretrain.d.ts","sourceRoot":"","sources":["../src/pretrain.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,0CAA0C;AAC1C,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,gCAAgC;AAChC,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;IACxC,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AA8KD,0CAA0C;AAC1C,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,CAuE5D"}
|
package/dist/pretrain.js
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pretrain — bootstrap intelligence by analyzing the target project.
|
|
3
|
+
*
|
|
4
|
+
* Scans the project's file structure, package.json, and tech stack to
|
|
5
|
+
* automatically recommend the right skills and presets. Runs during
|
|
6
|
+
* `dz init --pretrain` to eliminate manual preset selection.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
/** Tech detection rules: file/pattern → tech. */
|
|
13
|
+
const DETECTORS = [
|
|
14
|
+
// Languages/Frameworks
|
|
15
|
+
{ glob: 'package.json', tech: 'node.js', category: 'runtime' },
|
|
16
|
+
{ glob: 'tsconfig.json', tech: 'typescript', category: 'language' },
|
|
17
|
+
{ glob: 'requirements.txt', tech: 'python', category: 'runtime' },
|
|
18
|
+
{ glob: 'pyproject.toml', tech: 'python', category: 'runtime' },
|
|
19
|
+
{ glob: 'go.mod', tech: 'go', category: 'runtime' },
|
|
20
|
+
{ glob: 'Cargo.toml', tech: 'rust', category: 'runtime' },
|
|
21
|
+
{ glob: 'Gemfile', tech: 'ruby', category: 'runtime' },
|
|
22
|
+
// Frontend
|
|
23
|
+
{ glob: 'next.config', tech: 'next.js', category: 'frontend' },
|
|
24
|
+
{ glob: 'vite.config', tech: 'vite', category: 'frontend' },
|
|
25
|
+
{ glob: 'tailwind.config', tech: 'tailwind', category: 'frontend' },
|
|
26
|
+
// Databases
|
|
27
|
+
{ glob: 'prisma', tech: 'prisma', category: 'database' },
|
|
28
|
+
{ glob: 'drizzle.config', tech: 'drizzle', category: 'database' },
|
|
29
|
+
{ glob: 'knexfile', tech: 'knex', category: 'database' },
|
|
30
|
+
// Infrastructure
|
|
31
|
+
{ glob: 'Dockerfile', tech: 'docker', category: 'infra' },
|
|
32
|
+
{ glob: 'docker-compose', tech: 'docker-compose', category: 'infra' },
|
|
33
|
+
{ glob: '.github/workflows', tech: 'github-actions', category: 'ci' },
|
|
34
|
+
{ glob: '.gitlab-ci.yml', tech: 'gitlab-ci', category: 'ci' },
|
|
35
|
+
{ glob: 'terraform', tech: 'terraform', category: 'iac' },
|
|
36
|
+
{ glob: '.tf', tech: 'terraform', category: 'iac' },
|
|
37
|
+
{ glob: 'k8s', tech: 'kubernetes', category: 'infra' },
|
|
38
|
+
{ glob: 'helm', tech: 'helm', category: 'infra' },
|
|
39
|
+
{ glob: 'nginx.conf', tech: 'nginx', category: 'infra' },
|
|
40
|
+
// Testing
|
|
41
|
+
{ glob: 'vitest.config', tech: 'vitest', category: 'testing' },
|
|
42
|
+
{ glob: 'jest.config', tech: 'jest', category: 'testing' },
|
|
43
|
+
{ glob: 'playwright.config', tech: 'playwright', category: 'testing' },
|
|
44
|
+
{ glob: 'cypress.config', tech: 'cypress', category: 'testing' },
|
|
45
|
+
{ glob: '.stryker', tech: 'stryker', category: 'testing' },
|
|
46
|
+
// Data
|
|
47
|
+
{ glob: 'dbt_project.yml', tech: 'dbt', category: 'data' },
|
|
48
|
+
{ glob: 'airflow', tech: 'airflow', category: 'data' },
|
|
49
|
+
// API
|
|
50
|
+
{ glob: 'openapi', tech: 'openapi', category: 'api' },
|
|
51
|
+
{ glob: 'swagger', tech: 'swagger', category: 'api' },
|
|
52
|
+
{ glob: '.graphql', tech: 'graphql', category: 'api' },
|
|
53
|
+
{ glob: 'schema.graphql', tech: 'graphql', category: 'api' },
|
|
54
|
+
// Cache/Queue
|
|
55
|
+
{ glob: 'redis', tech: 'redis', category: 'cache' },
|
|
56
|
+
// Knowledge
|
|
57
|
+
{ glob: '.obsidian', tech: 'obsidian', category: 'knowledge' },
|
|
58
|
+
];
|
|
59
|
+
/** Map tech categories to recommended skills. */
|
|
60
|
+
const CATEGORY_TO_SKILLS = {
|
|
61
|
+
'runtime': ['debugging', 'test-writer', 'pr-review'],
|
|
62
|
+
'language': ['test-writer', 'pr-review'],
|
|
63
|
+
'frontend': ['frontend-implementation', 'playwright-testing'],
|
|
64
|
+
'database': ['database-review', 'database-migration'],
|
|
65
|
+
'infra': ['docker-compose', 'kubernetes', 'nginx-config'],
|
|
66
|
+
'ci': ['ci-fix', 'github-actions'],
|
|
67
|
+
'iac': ['terraform'],
|
|
68
|
+
'testing': ['test-writer', 'playwright-testing'],
|
|
69
|
+
'data': ['data-pipeline'],
|
|
70
|
+
'api': ['api-design', 'graphql-schema'],
|
|
71
|
+
'cache': ['redis-patterns'],
|
|
72
|
+
'knowledge': ['obsidian'],
|
|
73
|
+
};
|
|
74
|
+
/** Map detected skills to presets. */
|
|
75
|
+
const SKILL_TO_PRESET = {
|
|
76
|
+
'pr-review': 'devops', 'security-audit': 'devops', 'test-writer': 'devops',
|
|
77
|
+
'ci-fix': 'devops', 'terraform': 'devops', 'kubernetes': 'devops',
|
|
78
|
+
'docker-compose': 'devops', 'api-design': 'devops', 'debugging': 'devops',
|
|
79
|
+
'database-review': 'devops', 'database-migration': 'devops',
|
|
80
|
+
'github-actions': 'devops', 'nginx-config': 'devops', 'redis-patterns': 'devops',
|
|
81
|
+
'graphql-schema': 'devops', 'playwright-testing': 'devops',
|
|
82
|
+
'data-pipeline': 'devops', 'incident-response': 'devops',
|
|
83
|
+
'frontend-implementation': 'devops', 'monorepo-management': 'devops',
|
|
84
|
+
'brave-search': 'mcp', 'gmail': 'mcp', 'notion': 'mcp', 'obsidian': 'mcp',
|
|
85
|
+
'git-mcp': 'mcp', 'context7': 'mcp',
|
|
86
|
+
};
|
|
87
|
+
/** Scan project directory for files matching detectors. */
|
|
88
|
+
function scanProject(projectRoot) {
|
|
89
|
+
const techs = [];
|
|
90
|
+
const seen = new Set();
|
|
91
|
+
// Check top-level files
|
|
92
|
+
let entries = [];
|
|
93
|
+
try {
|
|
94
|
+
entries = readdirSync(projectRoot).map((e) => e.toLowerCase());
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return [];
|
|
98
|
+
}
|
|
99
|
+
for (const detector of DETECTORS) {
|
|
100
|
+
const globLower = detector.glob.toLowerCase();
|
|
101
|
+
const match = entries.some((e) => e.includes(globLower));
|
|
102
|
+
if (match && !seen.has(detector.tech)) {
|
|
103
|
+
seen.add(detector.tech);
|
|
104
|
+
techs.push({
|
|
105
|
+
name: detector.tech,
|
|
106
|
+
category: detector.category,
|
|
107
|
+
confidence: 0.9,
|
|
108
|
+
source: detector.glob,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Check subdirectories (1 level deep)
|
|
113
|
+
for (const entry of entries) {
|
|
114
|
+
const subPath = join(projectRoot, entry);
|
|
115
|
+
try {
|
|
116
|
+
const subEntries = readdirSync(subPath).map((e) => e.toLowerCase());
|
|
117
|
+
for (const detector of DETECTORS) {
|
|
118
|
+
const globLower = detector.glob.toLowerCase();
|
|
119
|
+
if (subEntries.some((e) => e.includes(globLower)) && !seen.has(detector.tech)) {
|
|
120
|
+
seen.add(detector.tech);
|
|
121
|
+
techs.push({
|
|
122
|
+
name: detector.tech,
|
|
123
|
+
category: detector.category,
|
|
124
|
+
confidence: 0.7,
|
|
125
|
+
source: `${entry}/${detector.glob}`,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch { /* not a directory or no access */ }
|
|
131
|
+
}
|
|
132
|
+
// Parse package.json for deps
|
|
133
|
+
const pkgPath = join(projectRoot, 'package.json');
|
|
134
|
+
if (existsSync(pkgPath)) {
|
|
135
|
+
try {
|
|
136
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
137
|
+
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
138
|
+
const depNames = Object.keys(allDeps).map((d) => d.toLowerCase());
|
|
139
|
+
const depDetectors = [
|
|
140
|
+
['next', 'next.js', 'frontend'],
|
|
141
|
+
['react', 'react', 'frontend'],
|
|
142
|
+
['vue', 'vue', 'frontend'],
|
|
143
|
+
['express', 'express', 'api'],
|
|
144
|
+
['fastify', 'fastify', 'api'],
|
|
145
|
+
['prisma', 'prisma', 'database'],
|
|
146
|
+
['drizzle-orm', 'drizzle', 'database'],
|
|
147
|
+
['redis', 'redis', 'cache'],
|
|
148
|
+
['ioredis', 'redis', 'cache'],
|
|
149
|
+
['bullmq', 'bullmq', 'queue'],
|
|
150
|
+
['graphql', 'graphql', 'api'],
|
|
151
|
+
['playwright', 'playwright', 'testing'],
|
|
152
|
+
['vitest', 'vitest', 'testing'],
|
|
153
|
+
['jest', 'jest', 'testing'],
|
|
154
|
+
];
|
|
155
|
+
for (const [dep, tech, category] of depDetectors) {
|
|
156
|
+
if (depNames.some((d) => d.includes(dep)) && !seen.has(tech)) {
|
|
157
|
+
seen.add(tech);
|
|
158
|
+
techs.push({ name: tech, category, confidence: 0.8, source: `package.json dep: ${dep}` });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch { /* invalid JSON */ }
|
|
163
|
+
}
|
|
164
|
+
return techs.sort((a, b) => b.confidence - a.confidence);
|
|
165
|
+
}
|
|
166
|
+
/** Run pretrain analysis on a project. */
|
|
167
|
+
export function pretrain(projectRoot) {
|
|
168
|
+
const techs = scanProject(projectRoot);
|
|
169
|
+
// Determine recommended skills from detected techs
|
|
170
|
+
const skillSet = new Set();
|
|
171
|
+
// Always recommend core skills
|
|
172
|
+
skillSet.add('pr-review');
|
|
173
|
+
skillSet.add('security-audit');
|
|
174
|
+
skillSet.add('debugging');
|
|
175
|
+
for (const tech of techs) {
|
|
176
|
+
const skills = CATEGORY_TO_SKILLS[tech.category] ?? [];
|
|
177
|
+
for (const s of skills)
|
|
178
|
+
skillSet.add(s);
|
|
179
|
+
}
|
|
180
|
+
const recommendedSkills = [...skillSet].sort();
|
|
181
|
+
// Determine recommended presets
|
|
182
|
+
const presetCounts = new Map();
|
|
183
|
+
for (const skill of recommendedSkills) {
|
|
184
|
+
const preset = SKILL_TO_PRESET[skill];
|
|
185
|
+
if (preset)
|
|
186
|
+
presetCounts.set(preset, (presetCounts.get(preset) ?? 0) + 1);
|
|
187
|
+
}
|
|
188
|
+
const recommendedPresets = [...presetCounts.entries()]
|
|
189
|
+
.sort((a, b) => b[1] - a[1])
|
|
190
|
+
.map(([name]) => name);
|
|
191
|
+
// Detect project type
|
|
192
|
+
const categories = new Set(techs.map((t) => t.category));
|
|
193
|
+
let projectType = 'generic';
|
|
194
|
+
if (categories.has('frontend') && categories.has('api'))
|
|
195
|
+
projectType = 'fullstack';
|
|
196
|
+
else if (categories.has('frontend'))
|
|
197
|
+
projectType = 'frontend';
|
|
198
|
+
else if (categories.has('api'))
|
|
199
|
+
projectType = 'backend';
|
|
200
|
+
else if (categories.has('data'))
|
|
201
|
+
projectType = 'data-engineering';
|
|
202
|
+
else if (categories.has('iac'))
|
|
203
|
+
projectType = 'infrastructure';
|
|
204
|
+
// Detect package count (monorepo check)
|
|
205
|
+
let packageCount = 1;
|
|
206
|
+
const pkgPath = join(projectRoot, 'pnpm-workspace.yaml');
|
|
207
|
+
if (existsSync(pkgPath)) {
|
|
208
|
+
try {
|
|
209
|
+
const dirs = readdirSync(join(projectRoot, 'packages'), { withFileTypes: true })
|
|
210
|
+
.filter((e) => e.isDirectory());
|
|
211
|
+
packageCount = dirs.length;
|
|
212
|
+
if (packageCount > 3)
|
|
213
|
+
skillSet.add('monorepo-management');
|
|
214
|
+
}
|
|
215
|
+
catch { /* no packages dir */ }
|
|
216
|
+
}
|
|
217
|
+
// Get project name
|
|
218
|
+
let projectName = 'unknown';
|
|
219
|
+
const rootPkg = join(projectRoot, 'package.json');
|
|
220
|
+
if (existsSync(rootPkg)) {
|
|
221
|
+
try {
|
|
222
|
+
const pkg = JSON.parse(readFileSync(rootPkg, 'utf-8'));
|
|
223
|
+
projectName = pkg.name ?? 'unknown';
|
|
224
|
+
}
|
|
225
|
+
catch { /* */ }
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
projectName,
|
|
229
|
+
techs,
|
|
230
|
+
recommendedPresets,
|
|
231
|
+
recommendedSkills: [...skillSet].sort(),
|
|
232
|
+
projectType,
|
|
233
|
+
hasTests: techs.some((t) => t.category === 'testing'),
|
|
234
|
+
hasDocker: techs.some((t) => t.name === 'docker' || t.name === 'docker-compose'),
|
|
235
|
+
hasCI: techs.some((t) => t.category === 'ci'),
|
|
236
|
+
hasTerraform: techs.some((t) => t.name === 'terraform'),
|
|
237
|
+
hasKubernetes: techs.some((t) => t.name === 'kubernetes' || t.name === 'helm'),
|
|
238
|
+
packageCount,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=pretrain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pretrain.js","sourceRoot":"","sources":["../src/pretrain.ts"],"names":[],"mappings":"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"}
|
package/dist/sync-upstream.d.ts
CHANGED
|
@@ -45,6 +45,17 @@ export interface SyncUpstreamReport {
|
|
|
45
45
|
}
|
|
46
46
|
/** Load sources.json from a skills package directory. */
|
|
47
47
|
export declare function loadSourcesManifest(packageDir: string): SourcesManifest | undefined;
|
|
48
|
+
/** Info about a package with external sources. */
|
|
49
|
+
export interface SourcePackageInfo {
|
|
50
|
+
readonly name: string;
|
|
51
|
+
readonly dir: string;
|
|
52
|
+
readonly origin: OriginMeta;
|
|
53
|
+
readonly skillCount: number;
|
|
54
|
+
}
|
|
55
|
+
/** Discover all packages with sources.json in the monorepo. */
|
|
56
|
+
export declare function discoverSourcePackages(monorepoRoot: string): SourcePackageInfo[];
|
|
57
|
+
/** Check all packages with sources.json against upstream. */
|
|
58
|
+
export declare function checkAllUpstream(monorepoRoot: string): Promise<SyncUpstreamReport[]>;
|
|
48
59
|
/**
|
|
49
60
|
* Check all skills in a sources.json manifest against their upstream.
|
|
50
61
|
* Compares line counts as a quick diff indicator (full diff would be too verbose).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-upstream.d.ts","sourceRoot":"","sources":["../src/sync-upstream.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,uCAAuC;AACvC,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AAED,gCAAgC;AAChC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,+BAA+B;AAC/B,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CAC9C;AAED,qDAAqD;AACrD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,GAAG,aAAa,GAAG,eAAe,CAAC;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AAED,4CAA4C;AAC5C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACjD;AAED,yDAAyD;AACzD,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAKnF;AA6BD;;;GAGG;AACH,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAiD/F"}
|
|
1
|
+
{"version":3,"file":"sync-upstream.d.ts","sourceRoot":"","sources":["../src/sync-upstream.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,uCAAuC;AACvC,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AAED,gCAAgC;AAChC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,+BAA+B;AAC/B,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CAC9C;AAED,qDAAqD;AACrD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,GAAG,aAAa,GAAG,eAAe,CAAC;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AAED,4CAA4C;AAC5C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACjD;AAED,yDAAyD;AACzD,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAKnF;AAED,kDAAkD;AAClD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,+DAA+D;AAC/D,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAmBhF;AAED,6DAA6D;AAC7D,wBAAsB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAQ1F;AA6BD;;;GAGG;AACH,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,SAAS,CAAC,CAiD/F"}
|
package/dist/sync-upstream.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* @packageDocumentation
|
|
6
6
|
*/
|
|
7
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
7
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
8
8
|
import { join } from 'node:path';
|
|
9
9
|
/** Load sources.json from a skills package directory. */
|
|
10
10
|
export function loadSourcesManifest(packageDir) {
|
|
@@ -14,6 +14,39 @@ export function loadSourcesManifest(packageDir) {
|
|
|
14
14
|
const raw = readFileSync(sourcesPath, 'utf-8');
|
|
15
15
|
return JSON.parse(raw);
|
|
16
16
|
}
|
|
17
|
+
/** Discover all packages with sources.json in the monorepo. */
|
|
18
|
+
export function discoverSourcePackages(monorepoRoot) {
|
|
19
|
+
const baseDir = join(monorepoRoot, 'packages', '@dzhechkov');
|
|
20
|
+
if (!existsSync(baseDir))
|
|
21
|
+
return [];
|
|
22
|
+
const results = [];
|
|
23
|
+
for (const entry of readdirSync(baseDir, { withFileTypes: true })) {
|
|
24
|
+
if (!entry.isDirectory())
|
|
25
|
+
continue;
|
|
26
|
+
const pkgDir = join(baseDir, entry.name);
|
|
27
|
+
const manifest = loadSourcesManifest(pkgDir);
|
|
28
|
+
if (manifest) {
|
|
29
|
+
results.push({
|
|
30
|
+
name: entry.name,
|
|
31
|
+
dir: pkgDir,
|
|
32
|
+
origin: manifest.origin,
|
|
33
|
+
skillCount: Object.keys(manifest.skills).length,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return results;
|
|
38
|
+
}
|
|
39
|
+
/** Check all packages with sources.json against upstream. */
|
|
40
|
+
export async function checkAllUpstream(monorepoRoot) {
|
|
41
|
+
const packages = discoverSourcePackages(monorepoRoot);
|
|
42
|
+
const reports = [];
|
|
43
|
+
for (const pkg of packages) {
|
|
44
|
+
const report = await checkUpstream(pkg.dir);
|
|
45
|
+
if (report)
|
|
46
|
+
reports.push(report);
|
|
47
|
+
}
|
|
48
|
+
return reports;
|
|
49
|
+
}
|
|
17
50
|
/** Build the raw GitHub URL for a skill's SKILL.md. */
|
|
18
51
|
function rawUrl(origin, skillPath) {
|
|
19
52
|
return `https://raw.githubusercontent.com/${origin.repo}/${origin.branch}/${skillPath}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-upstream.js","sourceRoot":"","sources":["../src/sync-upstream.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"sync-upstream.js","sourceRoot":"","sources":["../src/sync-upstream.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dzhechkov/harness-core",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.10",
|
|
4
4
|
"description": "Shared harness logic - skill loading, additive apply, and the init/sync/verify/doctor operations.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,12 +25,12 @@
|
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"yaml": "^2.0.0",
|
|
28
|
-
"@dzhechkov/adapter-codex": "0.2.0",
|
|
29
28
|
"@dzhechkov/adapter-claude": "0.2.0",
|
|
30
29
|
"@dzhechkov/adapter-openclaude": "0.1.0",
|
|
31
30
|
"@dzhechkov/adapter-opencode": "0.2.0",
|
|
31
|
+
"@dzhechkov/adapter-hermes": "0.2.0",
|
|
32
32
|
"@dzhechkov/core": "0.2.0",
|
|
33
|
-
"@dzhechkov/adapter-
|
|
33
|
+
"@dzhechkov/adapter-codex": "0.2.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^25.6.0",
|
package/src/index.ts
CHANGED
|
@@ -14,11 +14,13 @@ export * from './operations.js';
|
|
|
14
14
|
export * from './workflows.js';
|
|
15
15
|
export { createSkill } from './create-skill.js';
|
|
16
16
|
export type { CreateSkillOptions, CreateSkillResult } from './create-skill.js';
|
|
17
|
-
export { checkUpstream, loadSourcesManifest } from './sync-upstream.js';
|
|
18
|
-
export type { SyncUpstreamReport, UpstreamCheckResult, SourcesManifest } from './sync-upstream.js';
|
|
17
|
+
export { checkUpstream, checkAllUpstream, discoverSourcePackages, loadSourcesManifest } from './sync-upstream.js';
|
|
18
|
+
export type { SyncUpstreamReport, UpstreamCheckResult, SourcesManifest, SourcePackageInfo } from './sync-upstream.js';
|
|
19
19
|
export { benchmarkSkill, benchmarkSkills, compareSkills } from './benchmark.js';
|
|
20
20
|
export { buildRegistry, searchRegistry, filterByCategory } from './registry.js';
|
|
21
21
|
export { recommend } from './recommend.js';
|
|
22
|
+
export { pretrain } from './pretrain.js';
|
|
23
|
+
export type { PretrainResult, DetectedTech } from './pretrain.js';
|
|
22
24
|
export type { RecommendationReport, SkillRecommendation } from './recommend.js';
|
|
23
25
|
export { discoverPackages, publishPackages } from './publish.js';
|
|
24
26
|
export { fetchAllDownloads } from './downloads.js';
|
package/src/pretrain.ts
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pretrain — bootstrap intelligence by analyzing the target project.
|
|
3
|
+
*
|
|
4
|
+
* Scans the project's file structure, package.json, and tech stack to
|
|
5
|
+
* automatically recommend the right skills and presets. Runs during
|
|
6
|
+
* `dz init --pretrain` to eliminate manual preset selection.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
|
|
14
|
+
/** Detected technology in the project. */
|
|
15
|
+
export interface DetectedTech {
|
|
16
|
+
readonly name: string;
|
|
17
|
+
readonly category: string;
|
|
18
|
+
readonly confidence: number;
|
|
19
|
+
readonly source: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Pretrain analysis result. */
|
|
23
|
+
export interface PretrainResult {
|
|
24
|
+
readonly projectName: string;
|
|
25
|
+
readonly techs: readonly DetectedTech[];
|
|
26
|
+
readonly recommendedPresets: readonly string[];
|
|
27
|
+
readonly recommendedSkills: readonly string[];
|
|
28
|
+
readonly projectType: string;
|
|
29
|
+
readonly hasTests: boolean;
|
|
30
|
+
readonly hasDocker: boolean;
|
|
31
|
+
readonly hasCI: boolean;
|
|
32
|
+
readonly hasTerraform: boolean;
|
|
33
|
+
readonly hasKubernetes: boolean;
|
|
34
|
+
readonly packageCount: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Tech detection rules: file/pattern → tech. */
|
|
38
|
+
const DETECTORS: { glob: string; tech: string; category: string }[] = [
|
|
39
|
+
// Languages/Frameworks
|
|
40
|
+
{ glob: 'package.json', tech: 'node.js', category: 'runtime' },
|
|
41
|
+
{ glob: 'tsconfig.json', tech: 'typescript', category: 'language' },
|
|
42
|
+
{ glob: 'requirements.txt', tech: 'python', category: 'runtime' },
|
|
43
|
+
{ glob: 'pyproject.toml', tech: 'python', category: 'runtime' },
|
|
44
|
+
{ glob: 'go.mod', tech: 'go', category: 'runtime' },
|
|
45
|
+
{ glob: 'Cargo.toml', tech: 'rust', category: 'runtime' },
|
|
46
|
+
{ glob: 'Gemfile', tech: 'ruby', category: 'runtime' },
|
|
47
|
+
|
|
48
|
+
// Frontend
|
|
49
|
+
{ glob: 'next.config', tech: 'next.js', category: 'frontend' },
|
|
50
|
+
{ glob: 'vite.config', tech: 'vite', category: 'frontend' },
|
|
51
|
+
{ glob: 'tailwind.config', tech: 'tailwind', category: 'frontend' },
|
|
52
|
+
|
|
53
|
+
// Databases
|
|
54
|
+
{ glob: 'prisma', tech: 'prisma', category: 'database' },
|
|
55
|
+
{ glob: 'drizzle.config', tech: 'drizzle', category: 'database' },
|
|
56
|
+
{ glob: 'knexfile', tech: 'knex', category: 'database' },
|
|
57
|
+
|
|
58
|
+
// Infrastructure
|
|
59
|
+
{ glob: 'Dockerfile', tech: 'docker', category: 'infra' },
|
|
60
|
+
{ glob: 'docker-compose', tech: 'docker-compose', category: 'infra' },
|
|
61
|
+
{ glob: '.github/workflows', tech: 'github-actions', category: 'ci' },
|
|
62
|
+
{ glob: '.gitlab-ci.yml', tech: 'gitlab-ci', category: 'ci' },
|
|
63
|
+
{ glob: 'terraform', tech: 'terraform', category: 'iac' },
|
|
64
|
+
{ glob: '.tf', tech: 'terraform', category: 'iac' },
|
|
65
|
+
{ glob: 'k8s', tech: 'kubernetes', category: 'infra' },
|
|
66
|
+
{ glob: 'helm', tech: 'helm', category: 'infra' },
|
|
67
|
+
{ glob: 'nginx.conf', tech: 'nginx', category: 'infra' },
|
|
68
|
+
|
|
69
|
+
// Testing
|
|
70
|
+
{ glob: 'vitest.config', tech: 'vitest', category: 'testing' },
|
|
71
|
+
{ glob: 'jest.config', tech: 'jest', category: 'testing' },
|
|
72
|
+
{ glob: 'playwright.config', tech: 'playwright', category: 'testing' },
|
|
73
|
+
{ glob: 'cypress.config', tech: 'cypress', category: 'testing' },
|
|
74
|
+
{ glob: '.stryker', tech: 'stryker', category: 'testing' },
|
|
75
|
+
|
|
76
|
+
// Data
|
|
77
|
+
{ glob: 'dbt_project.yml', tech: 'dbt', category: 'data' },
|
|
78
|
+
{ glob: 'airflow', tech: 'airflow', category: 'data' },
|
|
79
|
+
|
|
80
|
+
// API
|
|
81
|
+
{ glob: 'openapi', tech: 'openapi', category: 'api' },
|
|
82
|
+
{ glob: 'swagger', tech: 'swagger', category: 'api' },
|
|
83
|
+
{ glob: '.graphql', tech: 'graphql', category: 'api' },
|
|
84
|
+
{ glob: 'schema.graphql', tech: 'graphql', category: 'api' },
|
|
85
|
+
|
|
86
|
+
// Cache/Queue
|
|
87
|
+
{ glob: 'redis', tech: 'redis', category: 'cache' },
|
|
88
|
+
|
|
89
|
+
// Knowledge
|
|
90
|
+
{ glob: '.obsidian', tech: 'obsidian', category: 'knowledge' },
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
/** Map tech categories to recommended skills. */
|
|
94
|
+
const CATEGORY_TO_SKILLS: Record<string, string[]> = {
|
|
95
|
+
'runtime': ['debugging', 'test-writer', 'pr-review'],
|
|
96
|
+
'language': ['test-writer', 'pr-review'],
|
|
97
|
+
'frontend': ['frontend-implementation', 'playwright-testing'],
|
|
98
|
+
'database': ['database-review', 'database-migration'],
|
|
99
|
+
'infra': ['docker-compose', 'kubernetes', 'nginx-config'],
|
|
100
|
+
'ci': ['ci-fix', 'github-actions'],
|
|
101
|
+
'iac': ['terraform'],
|
|
102
|
+
'testing': ['test-writer', 'playwright-testing'],
|
|
103
|
+
'data': ['data-pipeline'],
|
|
104
|
+
'api': ['api-design', 'graphql-schema'],
|
|
105
|
+
'cache': ['redis-patterns'],
|
|
106
|
+
'knowledge': ['obsidian'],
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/** Map detected skills to presets. */
|
|
110
|
+
const SKILL_TO_PRESET: Record<string, string> = {
|
|
111
|
+
'pr-review': 'devops', 'security-audit': 'devops', 'test-writer': 'devops',
|
|
112
|
+
'ci-fix': 'devops', 'terraform': 'devops', 'kubernetes': 'devops',
|
|
113
|
+
'docker-compose': 'devops', 'api-design': 'devops', 'debugging': 'devops',
|
|
114
|
+
'database-review': 'devops', 'database-migration': 'devops',
|
|
115
|
+
'github-actions': 'devops', 'nginx-config': 'devops', 'redis-patterns': 'devops',
|
|
116
|
+
'graphql-schema': 'devops', 'playwright-testing': 'devops',
|
|
117
|
+
'data-pipeline': 'devops', 'incident-response': 'devops',
|
|
118
|
+
'frontend-implementation': 'devops', 'monorepo-management': 'devops',
|
|
119
|
+
'brave-search': 'mcp', 'gmail': 'mcp', 'notion': 'mcp', 'obsidian': 'mcp',
|
|
120
|
+
'git-mcp': 'mcp', 'context7': 'mcp',
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/** Scan project directory for files matching detectors. */
|
|
124
|
+
function scanProject(projectRoot: string): DetectedTech[] {
|
|
125
|
+
const techs: DetectedTech[] = [];
|
|
126
|
+
const seen = new Set<string>();
|
|
127
|
+
|
|
128
|
+
// Check top-level files
|
|
129
|
+
let entries: string[] = [];
|
|
130
|
+
try {
|
|
131
|
+
entries = readdirSync(projectRoot).map((e) => e.toLowerCase());
|
|
132
|
+
} catch { return []; }
|
|
133
|
+
|
|
134
|
+
for (const detector of DETECTORS) {
|
|
135
|
+
const globLower = detector.glob.toLowerCase();
|
|
136
|
+
const match = entries.some((e) => e.includes(globLower));
|
|
137
|
+
if (match && !seen.has(detector.tech)) {
|
|
138
|
+
seen.add(detector.tech);
|
|
139
|
+
techs.push({
|
|
140
|
+
name: detector.tech,
|
|
141
|
+
category: detector.category,
|
|
142
|
+
confidence: 0.9,
|
|
143
|
+
source: detector.glob,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Check subdirectories (1 level deep)
|
|
149
|
+
for (const entry of entries) {
|
|
150
|
+
const subPath = join(projectRoot, entry);
|
|
151
|
+
try {
|
|
152
|
+
const subEntries = readdirSync(subPath).map((e) => e.toLowerCase());
|
|
153
|
+
for (const detector of DETECTORS) {
|
|
154
|
+
const globLower = detector.glob.toLowerCase();
|
|
155
|
+
if (subEntries.some((e) => e.includes(globLower)) && !seen.has(detector.tech)) {
|
|
156
|
+
seen.add(detector.tech);
|
|
157
|
+
techs.push({
|
|
158
|
+
name: detector.tech,
|
|
159
|
+
category: detector.category,
|
|
160
|
+
confidence: 0.7,
|
|
161
|
+
source: `${entry}/${detector.glob}`,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
} catch { /* not a directory or no access */ }
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Parse package.json for deps
|
|
169
|
+
const pkgPath = join(projectRoot, 'package.json');
|
|
170
|
+
if (existsSync(pkgPath)) {
|
|
171
|
+
try {
|
|
172
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as {
|
|
173
|
+
name?: string;
|
|
174
|
+
dependencies?: Record<string, string>;
|
|
175
|
+
devDependencies?: Record<string, string>;
|
|
176
|
+
};
|
|
177
|
+
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
178
|
+
const depNames = Object.keys(allDeps).map((d) => d.toLowerCase());
|
|
179
|
+
|
|
180
|
+
const depDetectors: [string, string, string][] = [
|
|
181
|
+
['next', 'next.js', 'frontend'],
|
|
182
|
+
['react', 'react', 'frontend'],
|
|
183
|
+
['vue', 'vue', 'frontend'],
|
|
184
|
+
['express', 'express', 'api'],
|
|
185
|
+
['fastify', 'fastify', 'api'],
|
|
186
|
+
['prisma', 'prisma', 'database'],
|
|
187
|
+
['drizzle-orm', 'drizzle', 'database'],
|
|
188
|
+
['redis', 'redis', 'cache'],
|
|
189
|
+
['ioredis', 'redis', 'cache'],
|
|
190
|
+
['bullmq', 'bullmq', 'queue'],
|
|
191
|
+
['graphql', 'graphql', 'api'],
|
|
192
|
+
['playwright', 'playwright', 'testing'],
|
|
193
|
+
['vitest', 'vitest', 'testing'],
|
|
194
|
+
['jest', 'jest', 'testing'],
|
|
195
|
+
];
|
|
196
|
+
|
|
197
|
+
for (const [dep, tech, category] of depDetectors) {
|
|
198
|
+
if (depNames.some((d) => d.includes(dep)) && !seen.has(tech)) {
|
|
199
|
+
seen.add(tech);
|
|
200
|
+
techs.push({ name: tech, category, confidence: 0.8, source: `package.json dep: ${dep}` });
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
} catch { /* invalid JSON */ }
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return techs.sort((a, b) => b.confidence - a.confidence);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/** Run pretrain analysis on a project. */
|
|
210
|
+
export function pretrain(projectRoot: string): PretrainResult {
|
|
211
|
+
const techs = scanProject(projectRoot);
|
|
212
|
+
|
|
213
|
+
// Determine recommended skills from detected techs
|
|
214
|
+
const skillSet = new Set<string>();
|
|
215
|
+
// Always recommend core skills
|
|
216
|
+
skillSet.add('pr-review');
|
|
217
|
+
skillSet.add('security-audit');
|
|
218
|
+
skillSet.add('debugging');
|
|
219
|
+
|
|
220
|
+
for (const tech of techs) {
|
|
221
|
+
const skills = CATEGORY_TO_SKILLS[tech.category] ?? [];
|
|
222
|
+
for (const s of skills) skillSet.add(s);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const recommendedSkills = [...skillSet].sort();
|
|
226
|
+
|
|
227
|
+
// Determine recommended presets
|
|
228
|
+
const presetCounts = new Map<string, number>();
|
|
229
|
+
for (const skill of recommendedSkills) {
|
|
230
|
+
const preset = SKILL_TO_PRESET[skill];
|
|
231
|
+
if (preset) presetCounts.set(preset, (presetCounts.get(preset) ?? 0) + 1);
|
|
232
|
+
}
|
|
233
|
+
const recommendedPresets = [...presetCounts.entries()]
|
|
234
|
+
.sort((a, b) => b[1] - a[1])
|
|
235
|
+
.map(([name]) => name);
|
|
236
|
+
|
|
237
|
+
// Detect project type
|
|
238
|
+
const categories = new Set(techs.map((t) => t.category));
|
|
239
|
+
let projectType = 'generic';
|
|
240
|
+
if (categories.has('frontend') && categories.has('api')) projectType = 'fullstack';
|
|
241
|
+
else if (categories.has('frontend')) projectType = 'frontend';
|
|
242
|
+
else if (categories.has('api')) projectType = 'backend';
|
|
243
|
+
else if (categories.has('data')) projectType = 'data-engineering';
|
|
244
|
+
else if (categories.has('iac')) projectType = 'infrastructure';
|
|
245
|
+
|
|
246
|
+
// Detect package count (monorepo check)
|
|
247
|
+
let packageCount = 1;
|
|
248
|
+
const pkgPath = join(projectRoot, 'pnpm-workspace.yaml');
|
|
249
|
+
if (existsSync(pkgPath)) {
|
|
250
|
+
try {
|
|
251
|
+
const dirs = readdirSync(join(projectRoot, 'packages'), { withFileTypes: true })
|
|
252
|
+
.filter((e) => e.isDirectory());
|
|
253
|
+
packageCount = dirs.length;
|
|
254
|
+
if (packageCount > 3) skillSet.add('monorepo-management');
|
|
255
|
+
} catch { /* no packages dir */ }
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Get project name
|
|
259
|
+
let projectName = 'unknown';
|
|
260
|
+
const rootPkg = join(projectRoot, 'package.json');
|
|
261
|
+
if (existsSync(rootPkg)) {
|
|
262
|
+
try {
|
|
263
|
+
const pkg = JSON.parse(readFileSync(rootPkg, 'utf-8')) as { name?: string };
|
|
264
|
+
projectName = pkg.name ?? 'unknown';
|
|
265
|
+
} catch { /* */ }
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return {
|
|
269
|
+
projectName,
|
|
270
|
+
techs,
|
|
271
|
+
recommendedPresets,
|
|
272
|
+
recommendedSkills: [...skillSet].sort(),
|
|
273
|
+
projectType,
|
|
274
|
+
hasTests: techs.some((t) => t.category === 'testing'),
|
|
275
|
+
hasDocker: techs.some((t) => t.name === 'docker' || t.name === 'docker-compose'),
|
|
276
|
+
hasCI: techs.some((t) => t.category === 'ci'),
|
|
277
|
+
hasTerraform: techs.some((t) => t.name === 'terraform'),
|
|
278
|
+
hasKubernetes: techs.some((t) => t.name === 'kubernetes' || t.name === 'helm'),
|
|
279
|
+
packageCount,
|
|
280
|
+
};
|
|
281
|
+
}
|
package/src/sync-upstream.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* @packageDocumentation
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
8
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
9
9
|
import { join } from 'node:path';
|
|
10
10
|
|
|
11
11
|
/** A single skill's source mapping. */
|
|
@@ -60,6 +60,47 @@ export function loadSourcesManifest(packageDir: string): SourcesManifest | undef
|
|
|
60
60
|
return JSON.parse(raw) as SourcesManifest;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
/** Info about a package with external sources. */
|
|
64
|
+
export interface SourcePackageInfo {
|
|
65
|
+
readonly name: string;
|
|
66
|
+
readonly dir: string;
|
|
67
|
+
readonly origin: OriginMeta;
|
|
68
|
+
readonly skillCount: number;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Discover all packages with sources.json in the monorepo. */
|
|
72
|
+
export function discoverSourcePackages(monorepoRoot: string): SourcePackageInfo[] {
|
|
73
|
+
const baseDir = join(monorepoRoot, 'packages', '@dzhechkov');
|
|
74
|
+
if (!existsSync(baseDir)) return [];
|
|
75
|
+
|
|
76
|
+
const results: SourcePackageInfo[] = [];
|
|
77
|
+
for (const entry of readdirSync(baseDir, { withFileTypes: true })) {
|
|
78
|
+
if (!entry.isDirectory()) continue;
|
|
79
|
+
const pkgDir = join(baseDir, entry.name);
|
|
80
|
+
const manifest = loadSourcesManifest(pkgDir);
|
|
81
|
+
if (manifest) {
|
|
82
|
+
results.push({
|
|
83
|
+
name: entry.name,
|
|
84
|
+
dir: pkgDir,
|
|
85
|
+
origin: manifest.origin,
|
|
86
|
+
skillCount: Object.keys(manifest.skills).length,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return results;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Check all packages with sources.json against upstream. */
|
|
94
|
+
export async function checkAllUpstream(monorepoRoot: string): Promise<SyncUpstreamReport[]> {
|
|
95
|
+
const packages = discoverSourcePackages(monorepoRoot);
|
|
96
|
+
const reports: SyncUpstreamReport[] = [];
|
|
97
|
+
for (const pkg of packages) {
|
|
98
|
+
const report = await checkUpstream(pkg.dir);
|
|
99
|
+
if (report) reports.push(report);
|
|
100
|
+
}
|
|
101
|
+
return reports;
|
|
102
|
+
}
|
|
103
|
+
|
|
63
104
|
/** Build the raw GitHub URL for a skill's SKILL.md. */
|
|
64
105
|
function rawUrl(origin: OriginMeta, skillPath: string): string {
|
|
65
106
|
return `https://raw.githubusercontent.com/${origin.repo}/${origin.branch}/${skillPath}`;
|