@dzhechkov/harness-core 0.3.9 → 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 CHANGED
@@ -17,6 +17,8 @@ export type { SyncUpstreamReport, UpstreamCheckResult, SourcesManifest, SourcePa
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';
@@ -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,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,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"}
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
@@ -15,6 +15,7 @@ export { checkUpstream, checkAllUpstream, discoverSourcePackages, loadSourcesMan
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,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;AAE3C,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"}
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"}
@@ -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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dzhechkov/harness-core",
3
- "version": "0.3.9",
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
- "@dzhechkov/adapter-hermes": "0.2.0",
30
28
  "@dzhechkov/adapter-claude": "0.2.0",
31
29
  "@dzhechkov/adapter-openclaude": "0.1.0",
32
30
  "@dzhechkov/adapter-opencode": "0.2.0",
33
- "@dzhechkov/core": "0.2.0"
31
+ "@dzhechkov/adapter-hermes": "0.2.0",
32
+ "@dzhechkov/core": "0.2.0",
33
+ "@dzhechkov/adapter-codex": "0.2.0"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "^25.6.0",
package/src/index.ts CHANGED
@@ -19,6 +19,8 @@ export type { SyncUpstreamReport, UpstreamCheckResult, SourcesManifest, SourcePa
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';
@@ -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
+ }