@evo-dev/core 0.0.1-alpha

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.
Files changed (51) hide show
  1. package/assets/agents/review/code-reviewer/examples.md +19 -0
  2. package/assets/agents/review/code-reviewer/manifest.json +10 -0
  3. package/assets/agents/review/code-reviewer/prompt.md +59 -0
  4. package/assets/agents/review/code-reviewer/verification.md +11 -0
  5. package/assets/skills/coding/engineering-discipline/SKILL.md +63 -0
  6. package/assets/skills/coding/engineering-discipline/anti-patterns.md +21 -0
  7. package/assets/skills/coding/engineering-discipline/examples.md +19 -0
  8. package/assets/skills/coding/engineering-discipline/manifest.json +10 -0
  9. package/assets/skills/coding/engineering-discipline/verification.md +11 -0
  10. package/assets/workflows/rd-bug-fix/WORKFLOW.json +45 -0
  11. package/assets/workflows/rd-code-review/WORKFLOW.json +45 -0
  12. package/assets/workflows/rd-docs-update/WORKFLOW.json +45 -0
  13. package/assets/workflows/rd-feature-implementation/WORKFLOW.json +45 -0
  14. package/assets/workflows/rd-refactor/WORKFLOW.json +45 -0
  15. package/assets/workflows/rd-release-readiness/WORKFLOW.json +49 -0
  16. package/assets/workflows/rd-security-boundary-review/WORKFLOW.json +45 -0
  17. package/assets/workflows/rd-test-generation/WORKFLOW.json +45 -0
  18. package/dist/assets/index.js +209 -0
  19. package/dist/config/index.js +601 -0
  20. package/dist/index.js +4879 -0
  21. package/dist/plugins/index.js +265 -0
  22. package/package.json +30 -0
  23. package/src/.gitkeep +0 -0
  24. package/src/agents/index.ts +561 -0
  25. package/src/assets/errors.ts +21 -0
  26. package/src/assets/index.ts +18 -0
  27. package/src/assets/manifest.ts +109 -0
  28. package/src/assets/scanner.ts +189 -0
  29. package/src/config/errors.ts +21 -0
  30. package/src/config/index.ts +26 -0
  31. package/src/config/paths.ts +43 -0
  32. package/src/config/registry.ts +84 -0
  33. package/src/config/settings.ts +212 -0
  34. package/src/config/state.ts +130 -0
  35. package/src/config/store.ts +166 -0
  36. package/src/daemon/index.ts +414 -0
  37. package/src/hooks/index.ts +1023 -0
  38. package/src/index.ts +14 -0
  39. package/src/learning/index.ts +714 -0
  40. package/src/observability/index.ts +272 -0
  41. package/src/pack/index.ts +779 -0
  42. package/src/plugins/capabilities.ts +347 -0
  43. package/src/plugins/index.ts +41 -0
  44. package/src/plugins/registry.ts +60 -0
  45. package/src/plugins/types.ts +123 -0
  46. package/src/project/index.ts +507 -0
  47. package/src/protected-zones/index.ts +137 -0
  48. package/src/sync/index.ts +7 -0
  49. package/src/sync/orchestrator.ts +298 -0
  50. package/src/task/index.ts +840 -0
  51. package/src/workflow/index.ts +137 -0
@@ -0,0 +1,298 @@
1
+ import { join } from "node:path";
2
+ import { type AssetScanResult, type ScannedAsset, scanAssets } from "../assets/index.ts";
3
+ import type { AgentManifest, SkillManifest } from "../assets/manifest.ts";
4
+ import {
5
+ type CoreConfigStore,
6
+ type EvoDevRegistry,
7
+ type EvoDevSettings,
8
+ type RegisteredAsset,
9
+ type SyncState,
10
+ createCoreConfigStore,
11
+ createDefaultRegistry,
12
+ createDefaultSyncState,
13
+ } from "../config/index.ts";
14
+ import {
15
+ type CodeAgentPlugin,
16
+ type PluginId,
17
+ type PluginRegistry,
18
+ type SyncPlan,
19
+ type SyncResult,
20
+ getEnabledPluginIds,
21
+ } from "../plugins/index.ts";
22
+
23
+ export interface SyncOrchestratorOptions {
24
+ homeDir: string;
25
+ assetsRootDir: string;
26
+ pluginRegistry: PluginRegistry;
27
+ dryRun?: boolean;
28
+ targetPlugins?: PluginId[];
29
+ includeSkills?: boolean;
30
+ includeAgents?: boolean;
31
+ now?: () => string;
32
+ }
33
+
34
+ export interface SyncRunResult {
35
+ plans: SyncPlan[];
36
+ results: SyncResult[];
37
+ registry: EvoDevRegistry;
38
+ syncState: SyncState;
39
+ }
40
+
41
+ export async function runSync(options: SyncOrchestratorOptions): Promise<SyncRunResult> {
42
+ const store = createCoreConfigStore(options.homeDir);
43
+
44
+ const settings = await store.readSettings();
45
+ const assets = await scanAssets(resolveAssetScannerPaths(options.assetsRootDir));
46
+ const plugins = getSyncTargetPlugins(settings, options.pluginRegistry, options.targetPlugins);
47
+ const plans = buildSyncPlans({
48
+ settings,
49
+ assets,
50
+ plugins,
51
+ dryRun: options.dryRun ?? false,
52
+ includeSkills: options.includeSkills,
53
+ includeAgents: options.includeAgents,
54
+ });
55
+ const results = await executeSyncPlans(plans, plugins);
56
+ const registry = updateRegistryWithSyncResults(
57
+ await readRegistryOrDefault(store),
58
+ assets,
59
+ results,
60
+ );
61
+ const syncState = updateSyncStateWithResults(
62
+ await readSyncStateOrDefault(store),
63
+ results,
64
+ options.now?.() ?? new Date().toISOString(),
65
+ );
66
+
67
+ if (!(options.dryRun ?? false) && shouldPersistSyncResults(results)) {
68
+ await store.writeRegistry(registry);
69
+ await store.writeSyncState(syncState);
70
+ }
71
+
72
+ return { plans, results, registry, syncState };
73
+ }
74
+
75
+ export interface BuildSyncPlansInput {
76
+ settings: EvoDevSettings;
77
+ assets: AssetScanResult;
78
+ plugins: CodeAgentPlugin[];
79
+ dryRun: boolean;
80
+ includeSkills?: boolean;
81
+ includeAgents?: boolean;
82
+ }
83
+
84
+ export function buildSyncPlans(input: BuildSyncPlansInput): SyncPlan[] {
85
+ const shouldIncludeSkills = input.includeSkills ?? true;
86
+ const shouldIncludeAgents = input.includeAgents ?? true;
87
+ const skills =
88
+ input.settings.assets.skills.enabled && shouldIncludeSkills ? input.assets.skills : [];
89
+ const agents =
90
+ input.settings.assets.agents.enabled && shouldIncludeAgents ? input.assets.agents : [];
91
+
92
+ return input.plugins.map((plugin) => ({
93
+ targetPlugin: plugin.id,
94
+ skills: filterAssetsForTarget(skills, plugin.id),
95
+ agents: filterAssetsForTarget(agents, plugin.id),
96
+ dryRun: input.dryRun,
97
+ }));
98
+ }
99
+
100
+ async function executeSyncPlans(
101
+ plans: SyncPlan[],
102
+ plugins: CodeAgentPlugin[],
103
+ ): Promise<SyncResult[]> {
104
+ const pluginById = new Map(plugins.map((plugin) => [plugin.id, plugin]));
105
+ const results: SyncResult[] = [];
106
+
107
+ for (const plan of plans) {
108
+ const plugin = pluginById.get(plan.targetPlugin);
109
+
110
+ if (plugin === undefined) {
111
+ throw new Error(`Cannot execute sync plan for unregistered plugin: ${plan.targetPlugin}`);
112
+ }
113
+
114
+ const [skillsResult, agentsResult] = await Promise.all([
115
+ plugin.syncSkills({
116
+ targetPlugin: plan.targetPlugin,
117
+ skills: plan.skills,
118
+ dryRun: plan.dryRun,
119
+ }),
120
+ plugin.syncAgents({
121
+ targetPlugin: plan.targetPlugin,
122
+ agents: plan.agents,
123
+ dryRun: plan.dryRun,
124
+ }),
125
+ ]);
126
+
127
+ results.push(mergeSyncResults(plan.targetPlugin, skillsResult, agentsResult));
128
+ }
129
+
130
+ return results;
131
+ }
132
+
133
+ function mergeSyncResults(
134
+ targetPlugin: string,
135
+ skillsResult: SyncResult,
136
+ agentsResult: SyncResult,
137
+ ): SyncResult {
138
+ return {
139
+ targetPlugin,
140
+ syncedSkills: unique([...skillsResult.syncedSkills, ...agentsResult.syncedSkills]),
141
+ syncedAgents: unique([...skillsResult.syncedAgents, ...agentsResult.syncedAgents]),
142
+ skipped: unique([...skillsResult.skipped, ...agentsResult.skipped]),
143
+ warnings: [...skillsResult.warnings, ...agentsResult.warnings],
144
+ errors: [...skillsResult.errors, ...agentsResult.errors],
145
+ };
146
+ }
147
+
148
+ function updateRegistryWithSyncResults(
149
+ registry: EvoDevRegistry,
150
+ assets: AssetScanResult,
151
+ results: SyncResult[],
152
+ ): EvoDevRegistry {
153
+ const next: EvoDevRegistry = {
154
+ version: 1,
155
+ skills: { ...registry.skills },
156
+ agents: { ...registry.agents },
157
+ };
158
+
159
+ for (const result of results) {
160
+ for (const key of result.syncedSkills) {
161
+ const asset = assets.skills.find((candidate) => candidate.registryKey === key);
162
+ if (asset !== undefined) {
163
+ next.skills[key] = mergeRegisteredAsset(
164
+ next.skills[key],
165
+ asset.manifest.version,
166
+ result.targetPlugin,
167
+ );
168
+ }
169
+ }
170
+
171
+ for (const key of result.syncedAgents) {
172
+ const asset = assets.agents.find((candidate) => candidate.registryKey === key);
173
+ if (asset !== undefined) {
174
+ next.agents[key] = mergeRegisteredAsset(
175
+ next.agents[key],
176
+ asset.manifest.version,
177
+ result.targetPlugin,
178
+ );
179
+ }
180
+ }
181
+ }
182
+
183
+ return next;
184
+ }
185
+
186
+ function updateSyncStateWithResults(
187
+ syncState: SyncState,
188
+ results: SyncResult[],
189
+ timestamp: string,
190
+ ): SyncState {
191
+ const next: SyncState = {
192
+ version: 1,
193
+ lastSyncAt: timestamp,
194
+ targets: { ...syncState.targets },
195
+ };
196
+
197
+ for (const result of results) {
198
+ next.targets[result.targetPlugin] = {
199
+ skills: result.syncedSkills.length,
200
+ agents: result.syncedAgents.length,
201
+ status: getSyncStatus(result),
202
+ };
203
+ }
204
+
205
+ return next;
206
+ }
207
+
208
+ function getSyncTargetPlugins(
209
+ settings: EvoDevSettings,
210
+ pluginRegistry: PluginRegistry,
211
+ targetPlugins: PluginId[] | undefined,
212
+ ): CodeAgentPlugin[] {
213
+ const enabledPluginIds = getEnabledPluginIds(settings);
214
+ const selectedPluginIds =
215
+ targetPlugins === undefined
216
+ ? enabledPluginIds
217
+ : unique(targetPlugins).filter((pluginId) => enabledPluginIds.includes(pluginId));
218
+
219
+ return selectedPluginIds.map((pluginId) => pluginRegistry.require(pluginId));
220
+ }
221
+
222
+ function shouldPersistSyncResults(results: SyncResult[]): boolean {
223
+ if (results.length === 0) return false;
224
+ if (results.every((result) => result.errors.length === 0)) return true;
225
+ return results.some((result) => result.syncedSkills.length > 0 || result.syncedAgents.length > 0);
226
+ }
227
+
228
+ function getSyncStatus(result: SyncResult): "success" | "partial" | "failed" {
229
+ if (result.errors.length === 0) {
230
+ return "success";
231
+ }
232
+
233
+ if (result.syncedSkills.length > 0 || result.syncedAgents.length > 0) {
234
+ return "partial";
235
+ }
236
+
237
+ return "failed";
238
+ }
239
+
240
+ function mergeRegisteredAsset(
241
+ existing: RegisteredAsset | undefined,
242
+ version: string,
243
+ targetPlugin: string,
244
+ ): RegisteredAsset {
245
+ return {
246
+ version,
247
+ source: existing?.source ?? "builtin",
248
+ targets: unique([...(existing?.targets ?? []), targetPlugin]),
249
+ };
250
+ }
251
+
252
+ function filterAssetsForTarget<TManifest extends SkillManifest | AgentManifest>(
253
+ assets: ScannedAsset<TManifest>[],
254
+ targetPlugin: string,
255
+ ): ScannedAsset<TManifest>[] {
256
+ return assets.filter((asset) =>
257
+ asset.manifest.targets.includes(targetPlugin as "claude" | "codex"),
258
+ );
259
+ }
260
+
261
+ function resolveAssetScannerPaths(assetsRootDir: string): { skillsDir: string; agentsDir: string } {
262
+ return {
263
+ skillsDir: join(assetsRootDir, "skills"),
264
+ agentsDir: join(assetsRootDir, "agents"),
265
+ };
266
+ }
267
+
268
+ async function readRegistryOrDefault(store: CoreConfigStore): Promise<EvoDevRegistry> {
269
+ try {
270
+ return await store.readRegistry();
271
+ } catch (error) {
272
+ if (isNotFoundError(error)) {
273
+ return createDefaultRegistry();
274
+ }
275
+
276
+ throw error;
277
+ }
278
+ }
279
+
280
+ async function readSyncStateOrDefault(store: CoreConfigStore): Promise<SyncState> {
281
+ try {
282
+ return await store.readSyncState();
283
+ } catch (error) {
284
+ if (isNotFoundError(error)) {
285
+ return createDefaultSyncState();
286
+ }
287
+
288
+ throw error;
289
+ }
290
+ }
291
+
292
+ function isNotFoundError(error: unknown): boolean {
293
+ return error instanceof Error && error.message.includes("ENOENT");
294
+ }
295
+
296
+ function unique<T>(values: T[]): T[] {
297
+ return [...new Set(values)];
298
+ }