@dzhechkov/harness-core 0.3.10 → 0.3.12

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
@@ -18,6 +18,8 @@ export { benchmarkSkill, benchmarkSkills, compareSkills } from './benchmark.js';
18
18
  export { buildRegistry, searchRegistry, filterByCategory } from './registry.js';
19
19
  export { recommend } from './recommend.js';
20
20
  export { pretrain } from './pretrain.js';
21
+ export { runSetup } from './setup.js';
22
+ export type { SetupOptions, SetupResult, SetupStep } from './setup.js';
21
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';
@@ -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,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"}
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
@@ -16,6 +16,7 @@ export { benchmarkSkill, benchmarkSkills, compareSkills } from './benchmark.js';
16
16
  export { buildRegistry, searchRegistry, filterByCategory } from './registry.js';
17
17
  export { recommend } from './recommend.js';
18
18
  export { pretrain } from './pretrain.js';
19
+ export { runSetup } from './setup.js';
19
20
  export { discoverPackages, publishPackages } from './publish.js';
20
21
  export { fetchAllDownloads } from './downloads.js';
21
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;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"}
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,43 @@
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
+ /** Memory backend type. */
16
+ export type MemoryBackend = 'jsonl' | 'agentdb';
17
+ /** Setup options. */
18
+ export interface SetupOptions {
19
+ readonly projectRoot: string;
20
+ readonly target: string;
21
+ readonly preset?: string | undefined;
22
+ readonly memory?: MemoryBackend | undefined;
23
+ readonly noHooks?: boolean | undefined;
24
+ readonly noMemory?: boolean | undefined;
25
+ readonly noPretrain?: boolean | undefined;
26
+ readonly force?: boolean | undefined;
27
+ }
28
+ /** Setup result. */
29
+ export interface SetupResult {
30
+ readonly steps: readonly SetupStep[];
31
+ readonly totalSteps: number;
32
+ readonly completed: number;
33
+ readonly skipped: number;
34
+ }
35
+ /** A single setup step. */
36
+ export interface SetupStep {
37
+ readonly name: string;
38
+ readonly status: 'done' | 'skipped' | 'error';
39
+ readonly detail: string;
40
+ }
41
+ /** Run full environment setup. */
42
+ export declare function runSetup(opts: SetupOptions): SetupResult;
43
+ //# 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,2BAA2B;AAC3B,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,SAAS,CAAC;AAEhD,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,MAAM,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAC5C,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;AA6ED,kCAAkC;AAClC,wBAAgB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,WAAW,CAwJxD"}
package/dist/setup.js ADDED
@@ -0,0 +1,249 @@
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, backend) {
19
+ const dzDir = join(projectRoot, '.dz');
20
+ if (backend === 'agentdb') {
21
+ // agentdb backend: hooks use agentdb CLI to store patterns
22
+ const rvfPath = join(dzDir, 'memory.rvf');
23
+ return JSON.stringify({
24
+ hooks: {
25
+ SessionStart: [{
26
+ type: 'command',
27
+ command: `node -e "const fs=require('fs');const d=new Date().toISOString();try{require('child_process').execSync('npx agentdb add \\'${rvfPath}\\' \\'session-start: '+d+'\\'',{stdio:'pipe'})}catch{fs.appendFileSync('${dzDir}/sessions.jsonl',JSON.stringify({event:'start',ts:d,backend:'agentdb'})+'\\n')}"`,
28
+ }],
29
+ SessionEnd: [{
30
+ type: 'command',
31
+ command: `node -e "const fs=require('fs');const d=new Date().toISOString();try{require('child_process').execSync('npx agentdb add \\'${rvfPath}\\' \\'session-end: '+d+'\\'',{stdio:'pipe'})}catch{fs.appendFileSync('${dzDir}/sessions.jsonl',JSON.stringify({event:'end',ts:d,backend:'agentdb'})+'\\n')}"`,
32
+ }],
33
+ },
34
+ }, null, 2);
35
+ }
36
+ // JSONL backend (default)
37
+ return JSON.stringify({
38
+ hooks: {
39
+ SessionStart: [{
40
+ type: 'command',
41
+ command: `node -e "const fs=require('fs');const d=new Date().toISOString();fs.appendFileSync('${dzDir}/sessions.jsonl',JSON.stringify({event:'start',ts:d})+'\\n')"`,
42
+ }],
43
+ SessionEnd: [{
44
+ type: 'command',
45
+ command: `node -e "const fs=require('fs');const d=new Date().toISOString();fs.appendFileSync('${dzDir}/sessions.jsonl',JSON.stringify({event:'end',ts:d})+'\\n')"`,
46
+ }],
47
+ },
48
+ }, null, 2);
49
+ }
50
+ /** Generate .dz/config.json with learning settings. */
51
+ function generateDzConfig(target, preset, backend) {
52
+ return JSON.stringify({
53
+ version: '1.0.0',
54
+ target,
55
+ preset: preset ?? null,
56
+ learning: {
57
+ enabled: true,
58
+ sessionTracking: true,
59
+ patternConsolidation: true,
60
+ retentionDays: 90,
61
+ },
62
+ memory: {
63
+ backend,
64
+ path: backend === 'agentdb' ? '.dz/memory.rvf' : '.dz/sessions.jsonl',
65
+ maxSizeMb: backend === 'agentdb' ? 100 : 10,
66
+ agentdb: backend === 'agentdb' ? {
67
+ learning: true,
68
+ vectorDim: 384,
69
+ mcpServer: 'agentdb',
70
+ } : undefined,
71
+ },
72
+ hooks: {
73
+ sessionStart: true,
74
+ sessionEnd: true,
75
+ },
76
+ }, null, 2);
77
+ }
78
+ /** Check if agentdb is available. */
79
+ function isAgentdbAvailable() {
80
+ try {
81
+ require('child_process').execSync('npx agentdb --version', { stdio: 'pipe', timeout: 10000 });
82
+ return true;
83
+ }
84
+ catch {
85
+ return false;
86
+ }
87
+ }
88
+ /** Run full environment setup. */
89
+ export function runSetup(opts) {
90
+ const steps = [];
91
+ const dzDir = join(opts.projectRoot, '.dz');
92
+ const backend = opts.memory ?? 'jsonl';
93
+ // Step 0: Check agentdb availability if requested
94
+ if (backend === 'agentdb') {
95
+ const available = isAgentdbAvailable();
96
+ if (available) {
97
+ steps.push({ name: 'AgentDB check', status: 'done', detail: 'agentdb available' });
98
+ }
99
+ else {
100
+ steps.push({ name: 'AgentDB check', status: 'error', detail: 'not found — install: npm i -g agentdb' });
101
+ // Fall through — will still create config, hooks will fallback to JSONL
102
+ }
103
+ }
104
+ // Step 1: Create .dz directory
105
+ if (!existsSync(dzDir)) {
106
+ mkdirSync(dzDir, { recursive: true });
107
+ steps.push({ name: 'Create .dz directory', status: 'done', detail: dzDir });
108
+ }
109
+ else {
110
+ steps.push({ name: 'Create .dz directory', status: 'skipped', detail: 'already exists' });
111
+ }
112
+ // Step 2: Write .dz/config.json
113
+ const configPath = join(dzDir, 'config.json');
114
+ if (!existsSync(configPath) || opts.force) {
115
+ writeFileSync(configPath, generateDzConfig(opts.target, opts.preset, backend));
116
+ steps.push({ name: 'Write .dz/config.json', status: 'done', detail: `${backend} backend` });
117
+ }
118
+ else {
119
+ steps.push({ name: 'Write .dz/config.json', status: 'skipped', detail: 'already exists (use --force)' });
120
+ }
121
+ // Step 3: Initialize session log
122
+ const sessionsPath = join(dzDir, 'sessions.jsonl');
123
+ if (!existsSync(sessionsPath)) {
124
+ writeFileSync(sessionsPath, '');
125
+ steps.push({ name: 'Initialize sessions.jsonl', status: 'done', detail: 'session tracking ready' });
126
+ }
127
+ else {
128
+ steps.push({ name: 'Initialize sessions.jsonl', status: 'skipped', detail: 'already exists' });
129
+ }
130
+ // Step 4: Initialize memory store
131
+ if (backend === 'agentdb') {
132
+ // Initialize .rvf via agentdb CLI
133
+ const rvfPath = join(dzDir, 'memory.rvf');
134
+ if (!existsSync(rvfPath)) {
135
+ try {
136
+ const { execSync } = require('child_process');
137
+ execSync(`npx agentdb init "${rvfPath}"`, { stdio: 'pipe', timeout: 30000 });
138
+ steps.push({ name: 'Initialize memory.rvf', status: 'done', detail: 'agentdb vector memory' });
139
+ }
140
+ catch {
141
+ // Fallback: create empty file, agentdb will init on first use
142
+ writeFileSync(rvfPath, '');
143
+ steps.push({ name: 'Initialize memory.rvf', status: 'done', detail: 'placeholder (agentdb will init on first use)' });
144
+ }
145
+ }
146
+ else {
147
+ steps.push({ name: 'Initialize memory.rvf', status: 'skipped', detail: 'already exists' });
148
+ }
149
+ // Also create JSONL fallback
150
+ const sessionsPath = join(dzDir, 'sessions.jsonl');
151
+ if (!existsSync(sessionsPath))
152
+ writeFileSync(sessionsPath, '');
153
+ }
154
+ else {
155
+ // JSONL backend
156
+ const sessionsPath = join(dzDir, 'sessions.jsonl');
157
+ if (!existsSync(sessionsPath)) {
158
+ writeFileSync(sessionsPath, '');
159
+ steps.push({ name: 'Initialize sessions.jsonl', status: 'done', detail: 'session tracking ready' });
160
+ }
161
+ else {
162
+ steps.push({ name: 'Initialize sessions.jsonl', status: 'skipped', detail: 'already exists' });
163
+ }
164
+ const patternsPath = join(dzDir, 'patterns.jsonl');
165
+ if (!existsSync(patternsPath)) {
166
+ writeFileSync(patternsPath, '');
167
+ steps.push({ name: 'Initialize patterns.jsonl', status: 'done', detail: 'pattern learning ready' });
168
+ }
169
+ else {
170
+ steps.push({ name: 'Initialize patterns.jsonl', status: 'skipped', detail: 'already exists' });
171
+ }
172
+ }
173
+ // Step 5: Configure hooks (write to .claude/settings.json)
174
+ if (!opts.noHooks) {
175
+ const settingsDir = join(opts.projectRoot, '.claude');
176
+ const settingsPath = join(settingsDir, 'settings.json');
177
+ if (!existsSync(settingsPath) || opts.force) {
178
+ mkdirSync(settingsDir, { recursive: true });
179
+ writeFileSync(settingsPath, generateHooksConfig(opts.projectRoot, backend));
180
+ steps.push({ name: 'Configure hooks', status: 'done', detail: `${backend} session hooks` });
181
+ }
182
+ else {
183
+ try {
184
+ const existing = JSON.parse(readFileSync(settingsPath, 'utf-8'));
185
+ if (!existing['hooks']) {
186
+ const hooks = JSON.parse(generateHooksConfig(opts.projectRoot, backend));
187
+ existing['hooks'] = hooks.hooks;
188
+ writeFileSync(settingsPath, JSON.stringify(existing, null, 2));
189
+ steps.push({ name: 'Configure hooks', status: 'done', detail: `merged ${backend} hooks` });
190
+ }
191
+ else {
192
+ steps.push({ name: 'Configure hooks', status: 'skipped', detail: 'hooks already configured' });
193
+ }
194
+ }
195
+ catch {
196
+ steps.push({ name: 'Configure hooks', status: 'skipped', detail: 'could not parse existing settings' });
197
+ }
198
+ }
199
+ }
200
+ else {
201
+ steps.push({ name: 'Configure hooks', status: 'skipped', detail: '--no-hooks' });
202
+ }
203
+ // Step 5.5: Register agentdb MCP server (if agentdb backend)
204
+ if (backend === 'agentdb') {
205
+ const mcpConfigPath = join(opts.projectRoot, '.claude', 'mcp.json');
206
+ if (!existsSync(mcpConfigPath) || opts.force) {
207
+ const mcpConfig = {
208
+ mcpServers: {
209
+ agentdb: {
210
+ command: 'npx',
211
+ args: ['agentdb@latest', 'mcp', 'start'],
212
+ },
213
+ },
214
+ };
215
+ mkdirSync(join(opts.projectRoot, '.claude'), { recursive: true });
216
+ writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
217
+ steps.push({ name: 'Register agentdb MCP', status: 'done', detail: '41 tools available' });
218
+ }
219
+ else {
220
+ steps.push({ name: 'Register agentdb MCP', status: 'skipped', detail: 'mcp.json already exists' });
221
+ }
222
+ }
223
+ // Step 6: Update .gitignore
224
+ const gitignorePath = join(opts.projectRoot, '.gitignore');
225
+ const dzIgnoreEntry = backend === 'agentdb'
226
+ ? '\n# DZ Harness learning data\n.dz/memory.rvf\n.dz/sessions.jsonl\n'
227
+ : '\n# DZ Harness learning data\n.dz/sessions.jsonl\n.dz/patterns.jsonl\n';
228
+ if (existsSync(gitignorePath)) {
229
+ const content = readFileSync(gitignorePath, 'utf-8');
230
+ if (!content.includes('.dz/sessions.jsonl')) {
231
+ writeFileSync(gitignorePath, content + dzIgnoreEntry);
232
+ steps.push({ name: 'Update .gitignore', status: 'done', detail: 'added .dz/sessions.jsonl + patterns.jsonl' });
233
+ }
234
+ else {
235
+ steps.push({ name: 'Update .gitignore', status: 'skipped', detail: 'already ignoring .dz data' });
236
+ }
237
+ }
238
+ else {
239
+ writeFileSync(gitignorePath, dzIgnoreEntry);
240
+ steps.push({ name: 'Create .gitignore', status: 'done', detail: 'with .dz entries' });
241
+ }
242
+ return {
243
+ steps,
244
+ totalSteps: steps.length,
245
+ completed: steps.filter((s) => s.status === 'done').length,
246
+ skipped: steps.filter((s) => s.status === 'skipped').length,
247
+ };
248
+ }
249
+ //# 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.10",
3
+ "version": "0.3.12",
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",
@@ -28,9 +28,9 @@
28
28
  "@dzhechkov/adapter-claude": "0.2.0",
29
29
  "@dzhechkov/adapter-openclaude": "0.1.0",
30
30
  "@dzhechkov/adapter-opencode": "0.2.0",
31
- "@dzhechkov/adapter-hermes": "0.2.0",
32
31
  "@dzhechkov/core": "0.2.0",
33
- "@dzhechkov/adapter-codex": "0.2.0"
32
+ "@dzhechkov/adapter-codex": "0.2.0",
33
+ "@dzhechkov/adapter-hermes": "0.2.0"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "^25.6.0",
package/src/index.ts CHANGED
@@ -20,6 +20,8 @@ export { benchmarkSkill, benchmarkSkills, compareSkills } from './benchmark.js';
20
20
  export { buildRegistry, searchRegistry, filterByCategory } from './registry.js';
21
21
  export { recommend } from './recommend.js';
22
22
  export { pretrain } from './pretrain.js';
23
+ export { runSetup } from './setup.js';
24
+ export type { SetupOptions, SetupResult, SetupStep } from './setup.js';
23
25
  export type { PretrainResult, DetectedTech } from './pretrain.js';
24
26
  export type { RecommendationReport, SkillRecommendation } from './recommend.js';
25
27
  export { discoverPackages, publishPackages } from './publish.js';
package/src/setup.ts ADDED
@@ -0,0 +1,277 @@
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
+ /** Memory backend type. */
20
+ export type MemoryBackend = 'jsonl' | 'agentdb';
21
+
22
+ /** Setup options. */
23
+ export interface SetupOptions {
24
+ readonly projectRoot: string;
25
+ readonly target: string;
26
+ readonly preset?: string | undefined;
27
+ readonly memory?: MemoryBackend | undefined;
28
+ readonly noHooks?: boolean | undefined;
29
+ readonly noMemory?: boolean | undefined;
30
+ readonly noPretrain?: boolean | undefined;
31
+ readonly force?: boolean | undefined;
32
+ }
33
+
34
+ /** Setup result. */
35
+ export interface SetupResult {
36
+ readonly steps: readonly SetupStep[];
37
+ readonly totalSteps: number;
38
+ readonly completed: number;
39
+ readonly skipped: number;
40
+ }
41
+
42
+ /** A single setup step. */
43
+ export interface SetupStep {
44
+ readonly name: string;
45
+ readonly status: 'done' | 'skipped' | 'error';
46
+ readonly detail: string;
47
+ }
48
+
49
+ /** Generate Claude Code hooks configuration for self-learning. */
50
+ function generateHooksConfig(projectRoot: string, backend: MemoryBackend): string {
51
+ const dzDir = join(projectRoot, '.dz');
52
+
53
+ if (backend === 'agentdb') {
54
+ // agentdb backend: hooks use agentdb CLI to store patterns
55
+ const rvfPath = join(dzDir, 'memory.rvf');
56
+ return JSON.stringify({
57
+ hooks: {
58
+ SessionStart: [{
59
+ type: 'command',
60
+ command: `node -e "const fs=require('fs');const d=new Date().toISOString();try{require('child_process').execSync('npx agentdb add \\'${rvfPath}\\' \\'session-start: '+d+'\\'',{stdio:'pipe'})}catch{fs.appendFileSync('${dzDir}/sessions.jsonl',JSON.stringify({event:'start',ts:d,backend:'agentdb'})+'\\n')}"`,
61
+ }],
62
+ SessionEnd: [{
63
+ type: 'command',
64
+ command: `node -e "const fs=require('fs');const d=new Date().toISOString();try{require('child_process').execSync('npx agentdb add \\'${rvfPath}\\' \\'session-end: '+d+'\\'',{stdio:'pipe'})}catch{fs.appendFileSync('${dzDir}/sessions.jsonl',JSON.stringify({event:'end',ts:d,backend:'agentdb'})+'\\n')}"`,
65
+ }],
66
+ },
67
+ }, null, 2);
68
+ }
69
+
70
+ // JSONL backend (default)
71
+ return JSON.stringify({
72
+ hooks: {
73
+ SessionStart: [{
74
+ type: 'command',
75
+ command: `node -e "const fs=require('fs');const d=new Date().toISOString();fs.appendFileSync('${dzDir}/sessions.jsonl',JSON.stringify({event:'start',ts:d})+'\\n')"`,
76
+ }],
77
+ SessionEnd: [{
78
+ type: 'command',
79
+ command: `node -e "const fs=require('fs');const d=new Date().toISOString();fs.appendFileSync('${dzDir}/sessions.jsonl',JSON.stringify({event:'end',ts:d})+'\\n')"`,
80
+ }],
81
+ },
82
+ }, null, 2);
83
+ }
84
+
85
+ /** Generate .dz/config.json with learning settings. */
86
+ function generateDzConfig(target: string, preset: string | undefined, backend: MemoryBackend): string {
87
+ return JSON.stringify({
88
+ version: '1.0.0',
89
+ target,
90
+ preset: preset ?? null,
91
+ learning: {
92
+ enabled: true,
93
+ sessionTracking: true,
94
+ patternConsolidation: true,
95
+ retentionDays: 90,
96
+ },
97
+ memory: {
98
+ backend,
99
+ path: backend === 'agentdb' ? '.dz/memory.rvf' : '.dz/sessions.jsonl',
100
+ maxSizeMb: backend === 'agentdb' ? 100 : 10,
101
+ agentdb: backend === 'agentdb' ? {
102
+ learning: true,
103
+ vectorDim: 384,
104
+ mcpServer: 'agentdb',
105
+ } : undefined,
106
+ },
107
+ hooks: {
108
+ sessionStart: true,
109
+ sessionEnd: true,
110
+ },
111
+ }, null, 2);
112
+ }
113
+
114
+ /** Check if agentdb is available. */
115
+ function isAgentdbAvailable(): boolean {
116
+ try {
117
+ require('child_process').execSync('npx agentdb --version', { stdio: 'pipe', timeout: 10000 });
118
+ return true;
119
+ } catch {
120
+ return false;
121
+ }
122
+ }
123
+
124
+ /** Run full environment setup. */
125
+ export function runSetup(opts: SetupOptions): SetupResult {
126
+ const steps: SetupStep[] = [];
127
+ const dzDir = join(opts.projectRoot, '.dz');
128
+ const backend: MemoryBackend = opts.memory ?? 'jsonl';
129
+
130
+ // Step 0: Check agentdb availability if requested
131
+ if (backend === 'agentdb') {
132
+ const available = isAgentdbAvailable();
133
+ if (available) {
134
+ steps.push({ name: 'AgentDB check', status: 'done', detail: 'agentdb available' });
135
+ } else {
136
+ steps.push({ name: 'AgentDB check', status: 'error', detail: 'not found — install: npm i -g agentdb' });
137
+ // Fall through — will still create config, hooks will fallback to JSONL
138
+ }
139
+ }
140
+
141
+ // Step 1: Create .dz directory
142
+ if (!existsSync(dzDir)) {
143
+ mkdirSync(dzDir, { recursive: true });
144
+ steps.push({ name: 'Create .dz directory', status: 'done', detail: dzDir });
145
+ } else {
146
+ steps.push({ name: 'Create .dz directory', status: 'skipped', detail: 'already exists' });
147
+ }
148
+
149
+ // Step 2: Write .dz/config.json
150
+ const configPath = join(dzDir, 'config.json');
151
+ if (!existsSync(configPath) || opts.force) {
152
+ writeFileSync(configPath, generateDzConfig(opts.target, opts.preset, backend));
153
+ steps.push({ name: 'Write .dz/config.json', status: 'done', detail: `${backend} backend` });
154
+ } else {
155
+ steps.push({ name: 'Write .dz/config.json', status: 'skipped', detail: 'already exists (use --force)' });
156
+ }
157
+
158
+ // Step 3: Initialize session log
159
+ const sessionsPath = join(dzDir, 'sessions.jsonl');
160
+ if (!existsSync(sessionsPath)) {
161
+ writeFileSync(sessionsPath, '');
162
+ steps.push({ name: 'Initialize sessions.jsonl', status: 'done', detail: 'session tracking ready' });
163
+ } else {
164
+ steps.push({ name: 'Initialize sessions.jsonl', status: 'skipped', detail: 'already exists' });
165
+ }
166
+
167
+ // Step 4: Initialize memory store
168
+ if (backend === 'agentdb') {
169
+ // Initialize .rvf via agentdb CLI
170
+ const rvfPath = join(dzDir, 'memory.rvf');
171
+ if (!existsSync(rvfPath)) {
172
+ try {
173
+ const { execSync } = require('child_process') as typeof import('child_process');
174
+ execSync(`npx agentdb init "${rvfPath}"`, { stdio: 'pipe', timeout: 30000 });
175
+ steps.push({ name: 'Initialize memory.rvf', status: 'done', detail: 'agentdb vector memory' });
176
+ } catch {
177
+ // Fallback: create empty file, agentdb will init on first use
178
+ writeFileSync(rvfPath, '');
179
+ steps.push({ name: 'Initialize memory.rvf', status: 'done', detail: 'placeholder (agentdb will init on first use)' });
180
+ }
181
+ } else {
182
+ steps.push({ name: 'Initialize memory.rvf', status: 'skipped', detail: 'already exists' });
183
+ }
184
+ // Also create JSONL fallback
185
+ const sessionsPath = join(dzDir, 'sessions.jsonl');
186
+ if (!existsSync(sessionsPath)) writeFileSync(sessionsPath, '');
187
+ } else {
188
+ // JSONL backend
189
+ const sessionsPath = join(dzDir, 'sessions.jsonl');
190
+ if (!existsSync(sessionsPath)) {
191
+ writeFileSync(sessionsPath, '');
192
+ steps.push({ name: 'Initialize sessions.jsonl', status: 'done', detail: 'session tracking ready' });
193
+ } else {
194
+ steps.push({ name: 'Initialize sessions.jsonl', status: 'skipped', detail: 'already exists' });
195
+ }
196
+ const patternsPath = join(dzDir, 'patterns.jsonl');
197
+ if (!existsSync(patternsPath)) {
198
+ writeFileSync(patternsPath, '');
199
+ steps.push({ name: 'Initialize patterns.jsonl', status: 'done', detail: 'pattern learning ready' });
200
+ } else {
201
+ steps.push({ name: 'Initialize patterns.jsonl', status: 'skipped', detail: 'already exists' });
202
+ }
203
+ }
204
+
205
+ // Step 5: Configure hooks (write to .claude/settings.json)
206
+ if (!opts.noHooks) {
207
+ const settingsDir = join(opts.projectRoot, '.claude');
208
+ const settingsPath = join(settingsDir, 'settings.json');
209
+
210
+ if (!existsSync(settingsPath) || opts.force) {
211
+ mkdirSync(settingsDir, { recursive: true });
212
+ writeFileSync(settingsPath, generateHooksConfig(opts.projectRoot, backend));
213
+ steps.push({ name: 'Configure hooks', status: 'done', detail: `${backend} session hooks` });
214
+ } else {
215
+ try {
216
+ const existing = JSON.parse(readFileSync(settingsPath, 'utf-8')) as Record<string, unknown>;
217
+ if (!existing['hooks']) {
218
+ const hooks = JSON.parse(generateHooksConfig(opts.projectRoot, backend));
219
+ existing['hooks'] = hooks.hooks;
220
+ writeFileSync(settingsPath, JSON.stringify(existing, null, 2));
221
+ steps.push({ name: 'Configure hooks', status: 'done', detail: `merged ${backend} hooks` });
222
+ } else {
223
+ steps.push({ name: 'Configure hooks', status: 'skipped', detail: 'hooks already configured' });
224
+ }
225
+ } catch {
226
+ steps.push({ name: 'Configure hooks', status: 'skipped', detail: 'could not parse existing settings' });
227
+ }
228
+ }
229
+ } else {
230
+ steps.push({ name: 'Configure hooks', status: 'skipped', detail: '--no-hooks' });
231
+ }
232
+
233
+ // Step 5.5: Register agentdb MCP server (if agentdb backend)
234
+ if (backend === 'agentdb') {
235
+ const mcpConfigPath = join(opts.projectRoot, '.claude', 'mcp.json');
236
+ if (!existsSync(mcpConfigPath) || opts.force) {
237
+ const mcpConfig = {
238
+ mcpServers: {
239
+ agentdb: {
240
+ command: 'npx',
241
+ args: ['agentdb@latest', 'mcp', 'start'],
242
+ },
243
+ },
244
+ };
245
+ mkdirSync(join(opts.projectRoot, '.claude'), { recursive: true });
246
+ writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
247
+ steps.push({ name: 'Register agentdb MCP', status: 'done', detail: '41 tools available' });
248
+ } else {
249
+ steps.push({ name: 'Register agentdb MCP', status: 'skipped', detail: 'mcp.json already exists' });
250
+ }
251
+ }
252
+
253
+ // Step 6: Update .gitignore
254
+ const gitignorePath = join(opts.projectRoot, '.gitignore');
255
+ const dzIgnoreEntry = backend === 'agentdb'
256
+ ? '\n# DZ Harness learning data\n.dz/memory.rvf\n.dz/sessions.jsonl\n'
257
+ : '\n# DZ Harness learning data\n.dz/sessions.jsonl\n.dz/patterns.jsonl\n';
258
+ if (existsSync(gitignorePath)) {
259
+ const content = readFileSync(gitignorePath, 'utf-8');
260
+ if (!content.includes('.dz/sessions.jsonl')) {
261
+ writeFileSync(gitignorePath, content + dzIgnoreEntry);
262
+ steps.push({ name: 'Update .gitignore', status: 'done', detail: 'added .dz/sessions.jsonl + patterns.jsonl' });
263
+ } else {
264
+ steps.push({ name: 'Update .gitignore', status: 'skipped', detail: 'already ignoring .dz data' });
265
+ }
266
+ } else {
267
+ writeFileSync(gitignorePath, dzIgnoreEntry);
268
+ steps.push({ name: 'Create .gitignore', status: 'done', detail: 'with .dz entries' });
269
+ }
270
+
271
+ return {
272
+ steps,
273
+ totalSteps: steps.length,
274
+ completed: steps.filter((s) => s.status === 'done').length,
275
+ skipped: steps.filter((s) => s.status === 'skipped').length,
276
+ };
277
+ }