@dzhechkov/harness-core 0.3.9 → 0.3.11

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,10 @@ 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 { runSetup } from './setup.js';
22
+ export type { SetupOptions, SetupResult, SetupStep } from './setup.js';
23
+ export type { PretrainResult, DetectedTech } from './pretrain.js';
20
24
  export type { RecommendationReport, SkillRecommendation } from './recommend.js';
21
25
  export { discoverPackages, publishPackages } from './publish.js';
22
26
  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,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvE,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,8 @@ 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';
19
+ export { runSetup } from './setup.js';
18
20
  export { discoverPackages, publishPackages } from './publish.js';
19
21
  export { fetchAllDownloads } from './downloads.js';
20
22
  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;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAItC,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":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAyBjC,iDAAiD;AACjD,MAAM,SAAS,GAAuD;IACpE,uBAAuB;IACvB,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE;IAC9D,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE;IACnE,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE;IACjE,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE;IAC/D,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE;IACnD,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE;IACzD,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE;IAEtD,WAAW;IACX,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE;IAC9D,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE;IAC3D,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE;IAEnE,YAAY;IACZ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE;IACxD,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE;IACjE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE;IAExD,iBAAiB;IACjB,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE;IACzD,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,OAAO,EAAE;IACrE,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,IAAI,EAAE;IACrE,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC7D,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE;IACzD,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE;IACnD,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE;IACtD,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE;IACjD,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE;IAExD,UAAU;IACV,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE;IAC9D,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE;IAC1D,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE;IACtE,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE;IAChE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE;IAE1D,OAAO;IACP,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE;IAC1D,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE;IAEtD,MAAM;IACN,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE;IACrD,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE;IACrD,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE;IACtD,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE;IAE5D,cAAc;IACd,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE;IAEnD,YAAY;IACZ,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE;CAC/D,CAAC;AAEF,iDAAiD;AACjD,MAAM,kBAAkB,GAA6B;IACnD,SAAS,EAAE,CAAC,WAAW,EAAE,aAAa,EAAE,WAAW,CAAC;IACpD,UAAU,EAAE,CAAC,aAAa,EAAE,WAAW,CAAC;IACxC,UAAU,EAAE,CAAC,yBAAyB,EAAE,oBAAoB,CAAC;IAC7D,UAAU,EAAE,CAAC,iBAAiB,EAAE,oBAAoB,CAAC;IACrD,OAAO,EAAE,CAAC,gBAAgB,EAAE,YAAY,EAAE,cAAc,CAAC;IACzD,IAAI,EAAE,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IAClC,KAAK,EAAE,CAAC,WAAW,CAAC;IACpB,SAAS,EAAE,CAAC,aAAa,EAAE,oBAAoB,CAAC;IAChD,MAAM,EAAE,CAAC,eAAe,CAAC;IACzB,KAAK,EAAE,CAAC,YAAY,EAAE,gBAAgB,CAAC;IACvC,OAAO,EAAE,CAAC,gBAAgB,CAAC;IAC3B,WAAW,EAAE,CAAC,UAAU,CAAC;CAC1B,CAAC;AAEF,sCAAsC;AACtC,MAAM,eAAe,GAA2B;IAC9C,WAAW,EAAE,QAAQ,EAAE,gBAAgB,EAAE,QAAQ,EAAE,aAAa,EAAE,QAAQ;IAC1E,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ;IACjE,gBAAgB,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ;IACzE,iBAAiB,EAAE,QAAQ,EAAE,oBAAoB,EAAE,QAAQ;IAC3D,gBAAgB,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,gBAAgB,EAAE,QAAQ;IAChF,gBAAgB,EAAE,QAAQ,EAAE,oBAAoB,EAAE,QAAQ;IAC1D,eAAe,EAAE,QAAQ,EAAE,mBAAmB,EAAE,QAAQ;IACxD,yBAAyB,EAAE,QAAQ,EAAE,qBAAqB,EAAE,QAAQ;IACpE,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK;IACzE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK;CACpC,CAAC;AAEF,2DAA2D;AAC3D,SAAS,WAAW,CAAC,WAAmB;IACtC,MAAM,KAAK,GAAmB,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,wBAAwB;IACxB,IAAI,OAAO,GAAa,EAAE,CAAC;IAC3B,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,EAAE,CAAC;IAAC,CAAC;IAEtB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;QACzD,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACtC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACxB,KAAK,CAAC,IAAI,CAAC;gBACT,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;gBAC3B,UAAU,EAAE,GAAG;gBACf,MAAM,EAAE,QAAQ,CAAC,IAAI;aACtB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,sCAAsC;IACtC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QACzC,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;YACpE,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;gBAC9C,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC9E,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;oBACxB,KAAK,CAAC,IAAI,CAAC;wBACT,IAAI,EAAE,QAAQ,CAAC,IAAI;wBACnB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;wBAC3B,UAAU,EAAE,GAAG;wBACf,MAAM,EAAE,GAAG,KAAK,IAAI,QAAQ,CAAC,IAAI,EAAE;qBACpC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,kCAAkC,CAAC,CAAC;IAChD,CAAC;IAED,8BAA8B;IAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAClD,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAIpD,CAAC;YACF,MAAM,OAAO,GAAG,EAAE,GAAG,GAAG,CAAC,YAAY,EAAE,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC;YAChE,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;YAElE,MAAM,YAAY,GAA+B;gBAC/C,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC;gBAC/B,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC;gBAC9B,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC;gBAC1B,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC;gBAC7B,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC;gBAC7B,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC;gBAChC,CAAC,aAAa,EAAE,SAAS,EAAE,UAAU,CAAC;gBACtC,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;gBAC3B,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC;gBAC7B,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC;gBAC7B,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC;gBAC7B,CAAC,YAAY,EAAE,YAAY,EAAE,SAAS,CAAC;gBACvC,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC;gBAC/B,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC;aAC5B,CAAC;YAEF,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,YAAY,EAAE,CAAC;gBACjD,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC7D,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;oBACf,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,qBAAqB,GAAG,EAAE,EAAE,CAAC,CAAC;gBAC5F,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAChC,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;AAC3D,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,QAAQ,CAAC,WAAmB;IAC1C,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;IAEvC,mDAAmD;IACnD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,+BAA+B;IAC/B,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC1B,QAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAC/B,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAE1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACvD,KAAK,MAAM,CAAC,IAAI,MAAM;YAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,iBAAiB,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;IAE/C,gCAAgC;IAChC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC/C,KAAK,MAAM,KAAK,IAAI,iBAAiB,EAAE,CAAC;QACtC,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,MAAM;YAAE,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5E,CAAC;IACD,MAAM,kBAAkB,GAAG,CAAC,GAAG,YAAY,CAAC,OAAO,EAAE,CAAC;SACnD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SAC3B,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;IAEzB,sBAAsB;IACtB,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IACzD,IAAI,WAAW,GAAG,SAAS,CAAC;IAC5B,IAAI,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,WAAW,GAAG,WAAW,CAAC;SAC9E,IAAI,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC;QAAE,WAAW,GAAG,UAAU,CAAC;SACzD,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,WAAW,GAAG,SAAS,CAAC;SACnD,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,WAAW,GAAG,kBAAkB,CAAC;SAC7D,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,WAAW,GAAG,gBAAgB,CAAC;IAE/D,wCAAwC;IACxC,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAAC;IACzD,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;iBAC7E,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;YAClC,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC;YAC3B,IAAI,YAAY,GAAG,CAAC;gBAAE,QAAQ,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC;IACnC,CAAC;IAED,mBAAmB;IACnB,IAAI,WAAW,GAAG,SAAS,CAAC;IAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAClD,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAsB,CAAC;YAC5E,WAAW,GAAG,GAAG,CAAC,IAAI,IAAI,SAAS,CAAC;QACtC,CAAC;QAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC;IAED,OAAO;QACL,WAAW;QACX,KAAK;QACL,kBAAkB;QAClB,iBAAiB,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE;QACvC,WAAW;QACX,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC;QACrD,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC;QAChF,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC;QAC7C,YAAY,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC;QACvD,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;QAC9E,YAAY;KACb,CAAC;AACJ,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Full environment setup — skills + hooks + memory + pretrain.
3
+ *
4
+ * Unlike `dz init` (skills only), `dz setup` configures the complete
5
+ * self-learning environment:
6
+ * 1. Skills installation (via init)
7
+ * 2. Claude Code hooks (session-start/end for memory)
8
+ * 3. Memory database initialization (.dz/memory.db)
9
+ * 4. Pretrain (project analysis → auto-recommend)
10
+ *
11
+ * All operations are additive — never overwrites existing files.
12
+ *
13
+ * @packageDocumentation
14
+ */
15
+ /** Setup options. */
16
+ export interface SetupOptions {
17
+ readonly projectRoot: string;
18
+ readonly target: string;
19
+ readonly preset?: string | undefined;
20
+ readonly noHooks?: boolean | undefined;
21
+ readonly noMemory?: boolean | undefined;
22
+ readonly noPretrain?: boolean | undefined;
23
+ readonly force?: boolean | undefined;
24
+ }
25
+ /** Setup result. */
26
+ export interface SetupResult {
27
+ readonly steps: readonly SetupStep[];
28
+ readonly totalSteps: number;
29
+ readonly completed: number;
30
+ readonly skipped: number;
31
+ }
32
+ /** A single setup step. */
33
+ export interface SetupStep {
34
+ readonly name: string;
35
+ readonly status: 'done' | 'skipped' | 'error';
36
+ readonly detail: string;
37
+ }
38
+ /** Run full environment setup. */
39
+ export declare function runSetup(opts: SetupOptions): SetupResult;
40
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,qBAAqB;AACrB,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACtC;AAED,oBAAoB;AACpB,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,2BAA2B;AAC3B,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AA2CD,kCAAkC;AAClC,wBAAgB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,WAAW,CA0FxD"}
package/dist/setup.js ADDED
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Full environment setup — skills + hooks + memory + pretrain.
3
+ *
4
+ * Unlike `dz init` (skills only), `dz setup` configures the complete
5
+ * self-learning environment:
6
+ * 1. Skills installation (via init)
7
+ * 2. Claude Code hooks (session-start/end for memory)
8
+ * 3. Memory database initialization (.dz/memory.db)
9
+ * 4. Pretrain (project analysis → auto-recommend)
10
+ *
11
+ * All operations are additive — never overwrites existing files.
12
+ *
13
+ * @packageDocumentation
14
+ */
15
+ import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';
16
+ import { join } from 'node:path';
17
+ /** Generate Claude Code hooks configuration for self-learning. */
18
+ function generateHooksConfig(projectRoot) {
19
+ const dzDir = join(projectRoot, '.dz');
20
+ return JSON.stringify({
21
+ hooks: {
22
+ SessionStart: [{
23
+ type: 'command',
24
+ command: `node -e "const fs=require('fs');const p='${dzDir}/memory.db';const d=new Date().toISOString();fs.appendFileSync('${dzDir}/sessions.jsonl',JSON.stringify({event:'start',ts:d})+'\\n')"`,
25
+ }],
26
+ SessionEnd: [{
27
+ type: 'command',
28
+ command: `node -e "const fs=require('fs');const d=new Date().toISOString();fs.appendFileSync('${dzDir}/sessions.jsonl',JSON.stringify({event:'end',ts:d})+'\\n')"`,
29
+ }],
30
+ },
31
+ }, null, 2);
32
+ }
33
+ /** Generate .dz/config.json with learning settings. */
34
+ function generateDzConfig(target, preset) {
35
+ return JSON.stringify({
36
+ version: '1.0.0',
37
+ target,
38
+ preset: preset ?? null,
39
+ learning: {
40
+ enabled: true,
41
+ sessionTracking: true,
42
+ patternConsolidation: true,
43
+ retentionDays: 90,
44
+ },
45
+ memory: {
46
+ backend: 'jsonl',
47
+ path: '.dz/sessions.jsonl',
48
+ maxSizeMb: 10,
49
+ },
50
+ hooks: {
51
+ sessionStart: true,
52
+ sessionEnd: true,
53
+ },
54
+ }, null, 2);
55
+ }
56
+ /** Run full environment setup. */
57
+ export function runSetup(opts) {
58
+ const steps = [];
59
+ const dzDir = join(opts.projectRoot, '.dz');
60
+ // Step 1: Create .dz directory
61
+ if (!existsSync(dzDir)) {
62
+ mkdirSync(dzDir, { recursive: true });
63
+ steps.push({ name: 'Create .dz directory', status: 'done', detail: dzDir });
64
+ }
65
+ else {
66
+ steps.push({ name: 'Create .dz directory', status: 'skipped', detail: 'already exists' });
67
+ }
68
+ // Step 2: Write .dz/config.json
69
+ const configPath = join(dzDir, 'config.json');
70
+ if (!existsSync(configPath) || opts.force) {
71
+ writeFileSync(configPath, generateDzConfig(opts.target, opts.preset));
72
+ steps.push({ name: 'Write .dz/config.json', status: 'done', detail: 'learning + memory config' });
73
+ }
74
+ else {
75
+ steps.push({ name: 'Write .dz/config.json', status: 'skipped', detail: 'already exists (use --force)' });
76
+ }
77
+ // Step 3: Initialize session log
78
+ const sessionsPath = join(dzDir, 'sessions.jsonl');
79
+ if (!existsSync(sessionsPath)) {
80
+ writeFileSync(sessionsPath, '');
81
+ steps.push({ name: 'Initialize sessions.jsonl', status: 'done', detail: 'session tracking ready' });
82
+ }
83
+ else {
84
+ steps.push({ name: 'Initialize sessions.jsonl', status: 'skipped', detail: 'already exists' });
85
+ }
86
+ // Step 4: Initialize patterns store
87
+ const patternsPath = join(dzDir, 'patterns.jsonl');
88
+ if (!existsSync(patternsPath)) {
89
+ writeFileSync(patternsPath, '');
90
+ steps.push({ name: 'Initialize patterns.jsonl', status: 'done', detail: 'pattern learning ready' });
91
+ }
92
+ else {
93
+ steps.push({ name: 'Initialize patterns.jsonl', status: 'skipped', detail: 'already exists' });
94
+ }
95
+ // Step 5: Configure hooks (write to .claude/settings.json)
96
+ if (!opts.noHooks) {
97
+ const settingsDir = join(opts.projectRoot, '.claude');
98
+ const settingsPath = join(settingsDir, 'settings.json');
99
+ if (!existsSync(settingsPath) || opts.force) {
100
+ mkdirSync(settingsDir, { recursive: true });
101
+ writeFileSync(settingsPath, generateHooksConfig(opts.projectRoot));
102
+ steps.push({ name: 'Configure hooks', status: 'done', detail: 'session-start + session-end hooks' });
103
+ }
104
+ else {
105
+ // Merge hooks into existing settings
106
+ try {
107
+ const existing = JSON.parse(readFileSync(settingsPath, 'utf-8'));
108
+ if (!existing['hooks']) {
109
+ const hooks = JSON.parse(generateHooksConfig(opts.projectRoot));
110
+ existing['hooks'] = hooks.hooks;
111
+ writeFileSync(settingsPath, JSON.stringify(existing, null, 2));
112
+ steps.push({ name: 'Configure hooks', status: 'done', detail: 'merged into existing settings' });
113
+ }
114
+ else {
115
+ steps.push({ name: 'Configure hooks', status: 'skipped', detail: 'hooks already configured' });
116
+ }
117
+ }
118
+ catch {
119
+ steps.push({ name: 'Configure hooks', status: 'skipped', detail: 'could not parse existing settings' });
120
+ }
121
+ }
122
+ }
123
+ else {
124
+ steps.push({ name: 'Configure hooks', status: 'skipped', detail: '--no-hooks' });
125
+ }
126
+ // Step 6: Update .gitignore
127
+ const gitignorePath = join(opts.projectRoot, '.gitignore');
128
+ const dzIgnoreEntry = '\n# DZ Harness learning data\n.dz/sessions.jsonl\n.dz/patterns.jsonl\n';
129
+ if (existsSync(gitignorePath)) {
130
+ const content = readFileSync(gitignorePath, 'utf-8');
131
+ if (!content.includes('.dz/sessions.jsonl')) {
132
+ writeFileSync(gitignorePath, content + dzIgnoreEntry);
133
+ steps.push({ name: 'Update .gitignore', status: 'done', detail: 'added .dz/sessions.jsonl + patterns.jsonl' });
134
+ }
135
+ else {
136
+ steps.push({ name: 'Update .gitignore', status: 'skipped', detail: 'already ignoring .dz data' });
137
+ }
138
+ }
139
+ else {
140
+ writeFileSync(gitignorePath, dzIgnoreEntry);
141
+ steps.push({ name: 'Create .gitignore', status: 'done', detail: 'with .dz entries' });
142
+ }
143
+ return {
144
+ steps,
145
+ totalSteps: steps.length,
146
+ completed: steps.filter((s) => s.status === 'done').length,
147
+ skipped: steps.filter((s) => s.status === 'skipped').length,
148
+ };
149
+ }
150
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.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.11",
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,11 +25,11 @@
25
25
  ],
26
26
  "dependencies": {
27
27
  "yaml": "^2.0.0",
28
+ "@dzhechkov/adapter-claude": "0.2.0",
29
+ "@dzhechkov/adapter-opencode": "0.2.0",
28
30
  "@dzhechkov/adapter-codex": "0.2.0",
29
31
  "@dzhechkov/adapter-hermes": "0.2.0",
30
- "@dzhechkov/adapter-claude": "0.2.0",
31
32
  "@dzhechkov/adapter-openclaude": "0.1.0",
32
- "@dzhechkov/adapter-opencode": "0.2.0",
33
33
  "@dzhechkov/core": "0.2.0"
34
34
  },
35
35
  "devDependencies": {
package/src/index.ts CHANGED
@@ -19,6 +19,10 @@ 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 { runSetup } from './setup.js';
24
+ export type { SetupOptions, SetupResult, SetupStep } from './setup.js';
25
+ export type { PretrainResult, DetectedTech } from './pretrain.js';
22
26
  export type { RecommendationReport, SkillRecommendation } from './recommend.js';
23
27
  export { discoverPackages, publishPackages } from './publish.js';
24
28
  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
+ }
package/src/setup.ts ADDED
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Full environment setup — skills + hooks + memory + pretrain.
3
+ *
4
+ * Unlike `dz init` (skills only), `dz setup` configures the complete
5
+ * self-learning environment:
6
+ * 1. Skills installation (via init)
7
+ * 2. Claude Code hooks (session-start/end for memory)
8
+ * 3. Memory database initialization (.dz/memory.db)
9
+ * 4. Pretrain (project analysis → auto-recommend)
10
+ *
11
+ * All operations are additive — never overwrites existing files.
12
+ *
13
+ * @packageDocumentation
14
+ */
15
+
16
+ import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';
17
+ import { join } from 'node:path';
18
+
19
+ /** Setup options. */
20
+ export interface SetupOptions {
21
+ readonly projectRoot: string;
22
+ readonly target: string;
23
+ readonly preset?: string | undefined;
24
+ readonly noHooks?: boolean | undefined;
25
+ readonly noMemory?: boolean | undefined;
26
+ readonly noPretrain?: boolean | undefined;
27
+ readonly force?: boolean | undefined;
28
+ }
29
+
30
+ /** Setup result. */
31
+ export interface SetupResult {
32
+ readonly steps: readonly SetupStep[];
33
+ readonly totalSteps: number;
34
+ readonly completed: number;
35
+ readonly skipped: number;
36
+ }
37
+
38
+ /** A single setup step. */
39
+ export interface SetupStep {
40
+ readonly name: string;
41
+ readonly status: 'done' | 'skipped' | 'error';
42
+ readonly detail: string;
43
+ }
44
+
45
+ /** Generate Claude Code hooks configuration for self-learning. */
46
+ function generateHooksConfig(projectRoot: string): string {
47
+ const dzDir = join(projectRoot, '.dz');
48
+ return JSON.stringify({
49
+ hooks: {
50
+ SessionStart: [{
51
+ type: 'command',
52
+ command: `node -e "const fs=require('fs');const p='${dzDir}/memory.db';const d=new Date().toISOString();fs.appendFileSync('${dzDir}/sessions.jsonl',JSON.stringify({event:'start',ts:d})+'\\n')"`,
53
+ }],
54
+ SessionEnd: [{
55
+ type: 'command',
56
+ command: `node -e "const fs=require('fs');const d=new Date().toISOString();fs.appendFileSync('${dzDir}/sessions.jsonl',JSON.stringify({event:'end',ts:d})+'\\n')"`,
57
+ }],
58
+ },
59
+ }, null, 2);
60
+ }
61
+
62
+ /** Generate .dz/config.json with learning settings. */
63
+ function generateDzConfig(target: string, preset: string | undefined): string {
64
+ return JSON.stringify({
65
+ version: '1.0.0',
66
+ target,
67
+ preset: preset ?? null,
68
+ learning: {
69
+ enabled: true,
70
+ sessionTracking: true,
71
+ patternConsolidation: true,
72
+ retentionDays: 90,
73
+ },
74
+ memory: {
75
+ backend: 'jsonl',
76
+ path: '.dz/sessions.jsonl',
77
+ maxSizeMb: 10,
78
+ },
79
+ hooks: {
80
+ sessionStart: true,
81
+ sessionEnd: true,
82
+ },
83
+ }, null, 2);
84
+ }
85
+
86
+ /** Run full environment setup. */
87
+ export function runSetup(opts: SetupOptions): SetupResult {
88
+ const steps: SetupStep[] = [];
89
+ const dzDir = join(opts.projectRoot, '.dz');
90
+
91
+ // Step 1: Create .dz directory
92
+ if (!existsSync(dzDir)) {
93
+ mkdirSync(dzDir, { recursive: true });
94
+ steps.push({ name: 'Create .dz directory', status: 'done', detail: dzDir });
95
+ } else {
96
+ steps.push({ name: 'Create .dz directory', status: 'skipped', detail: 'already exists' });
97
+ }
98
+
99
+ // Step 2: Write .dz/config.json
100
+ const configPath = join(dzDir, 'config.json');
101
+ if (!existsSync(configPath) || opts.force) {
102
+ writeFileSync(configPath, generateDzConfig(opts.target, opts.preset));
103
+ steps.push({ name: 'Write .dz/config.json', status: 'done', detail: 'learning + memory config' });
104
+ } else {
105
+ steps.push({ name: 'Write .dz/config.json', status: 'skipped', detail: 'already exists (use --force)' });
106
+ }
107
+
108
+ // Step 3: Initialize session log
109
+ const sessionsPath = join(dzDir, 'sessions.jsonl');
110
+ if (!existsSync(sessionsPath)) {
111
+ writeFileSync(sessionsPath, '');
112
+ steps.push({ name: 'Initialize sessions.jsonl', status: 'done', detail: 'session tracking ready' });
113
+ } else {
114
+ steps.push({ name: 'Initialize sessions.jsonl', status: 'skipped', detail: 'already exists' });
115
+ }
116
+
117
+ // Step 4: Initialize patterns store
118
+ const patternsPath = join(dzDir, 'patterns.jsonl');
119
+ if (!existsSync(patternsPath)) {
120
+ writeFileSync(patternsPath, '');
121
+ steps.push({ name: 'Initialize patterns.jsonl', status: 'done', detail: 'pattern learning ready' });
122
+ } else {
123
+ steps.push({ name: 'Initialize patterns.jsonl', status: 'skipped', detail: 'already exists' });
124
+ }
125
+
126
+ // Step 5: Configure hooks (write to .claude/settings.json)
127
+ if (!opts.noHooks) {
128
+ const settingsDir = join(opts.projectRoot, '.claude');
129
+ const settingsPath = join(settingsDir, 'settings.json');
130
+
131
+ if (!existsSync(settingsPath) || opts.force) {
132
+ mkdirSync(settingsDir, { recursive: true });
133
+ writeFileSync(settingsPath, generateHooksConfig(opts.projectRoot));
134
+ steps.push({ name: 'Configure hooks', status: 'done', detail: 'session-start + session-end hooks' });
135
+ } else {
136
+ // Merge hooks into existing settings
137
+ try {
138
+ const existing = JSON.parse(readFileSync(settingsPath, 'utf-8')) as Record<string, unknown>;
139
+ if (!existing['hooks']) {
140
+ const hooks = JSON.parse(generateHooksConfig(opts.projectRoot));
141
+ existing['hooks'] = hooks.hooks;
142
+ writeFileSync(settingsPath, JSON.stringify(existing, null, 2));
143
+ steps.push({ name: 'Configure hooks', status: 'done', detail: 'merged into existing settings' });
144
+ } else {
145
+ steps.push({ name: 'Configure hooks', status: 'skipped', detail: 'hooks already configured' });
146
+ }
147
+ } catch {
148
+ steps.push({ name: 'Configure hooks', status: 'skipped', detail: 'could not parse existing settings' });
149
+ }
150
+ }
151
+ } else {
152
+ steps.push({ name: 'Configure hooks', status: 'skipped', detail: '--no-hooks' });
153
+ }
154
+
155
+ // Step 6: Update .gitignore
156
+ const gitignorePath = join(opts.projectRoot, '.gitignore');
157
+ const dzIgnoreEntry = '\n# DZ Harness learning data\n.dz/sessions.jsonl\n.dz/patterns.jsonl\n';
158
+ if (existsSync(gitignorePath)) {
159
+ const content = readFileSync(gitignorePath, 'utf-8');
160
+ if (!content.includes('.dz/sessions.jsonl')) {
161
+ writeFileSync(gitignorePath, content + dzIgnoreEntry);
162
+ steps.push({ name: 'Update .gitignore', status: 'done', detail: 'added .dz/sessions.jsonl + patterns.jsonl' });
163
+ } else {
164
+ steps.push({ name: 'Update .gitignore', status: 'skipped', detail: 'already ignoring .dz data' });
165
+ }
166
+ } else {
167
+ writeFileSync(gitignorePath, dzIgnoreEntry);
168
+ steps.push({ name: 'Create .gitignore', status: 'done', detail: 'with .dz entries' });
169
+ }
170
+
171
+ return {
172
+ steps,
173
+ totalSteps: steps.length,
174
+ completed: steps.filter((s) => s.status === 'done').length,
175
+ skipped: steps.filter((s) => s.status === 'skipped').length,
176
+ };
177
+ }