pikakit 2.0.0 → 3.0.0

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 (92) hide show
  1. package/README.md +8 -8
  2. package/lib/agent-cli/bin/agent.js +187 -0
  3. package/lib/agent-cli/lib/audit.js +154 -0
  4. package/lib/agent-cli/lib/audit.test.js +100 -0
  5. package/lib/agent-cli/lib/auto-learn.js +319 -0
  6. package/lib/agent-cli/lib/backup.js +138 -0
  7. package/lib/agent-cli/lib/backup.test.js +78 -0
  8. package/lib/agent-cli/lib/cognitive-lesson.js +476 -0
  9. package/lib/agent-cli/lib/completion.js +149 -0
  10. package/lib/agent-cli/lib/config.js +35 -0
  11. package/lib/agent-cli/lib/eslint-fix.js +238 -0
  12. package/lib/agent-cli/lib/evolution-signal.js +215 -0
  13. package/lib/agent-cli/lib/export.js +86 -0
  14. package/lib/agent-cli/lib/export.test.js +65 -0
  15. package/lib/agent-cli/lib/fix.js +337 -0
  16. package/lib/agent-cli/lib/fix.test.js +80 -0
  17. package/lib/agent-cli/lib/gemini-export.js +83 -0
  18. package/lib/agent-cli/lib/generate-registry.js +42 -0
  19. package/lib/agent-cli/lib/hooks/install-hooks.js +152 -0
  20. package/lib/agent-cli/lib/hooks/lint-learn.js +172 -0
  21. package/lib/agent-cli/lib/icons.js +93 -0
  22. package/lib/agent-cli/lib/ignore.js +116 -0
  23. package/lib/agent-cli/lib/ignore.test.js +58 -0
  24. package/lib/agent-cli/lib/init.js +124 -0
  25. package/lib/agent-cli/lib/knowledge-index.js +326 -0
  26. package/lib/agent-cli/lib/knowledge-metrics.js +335 -0
  27. package/lib/agent-cli/lib/knowledge-retention.js +398 -0
  28. package/lib/agent-cli/lib/knowledge-validator.js +312 -0
  29. package/lib/agent-cli/lib/learn.js +255 -0
  30. package/lib/agent-cli/lib/learn.test.js +70 -0
  31. package/lib/agent-cli/lib/proposals.js +199 -0
  32. package/lib/agent-cli/lib/proposals.test.js +56 -0
  33. package/lib/agent-cli/lib/recall.js +826 -0
  34. package/lib/agent-cli/lib/recall.test.js +107 -0
  35. package/lib/agent-cli/lib/selfevolution-bridge.js +167 -0
  36. package/lib/agent-cli/lib/settings.js +203 -0
  37. package/lib/agent-cli/lib/skill-learn.js +296 -0
  38. package/lib/agent-cli/lib/stats.js +132 -0
  39. package/lib/agent-cli/lib/stats.test.js +94 -0
  40. package/lib/agent-cli/lib/types.js +33 -0
  41. package/lib/agent-cli/lib/ui/audit-ui.js +146 -0
  42. package/lib/agent-cli/lib/ui/backup-ui.js +107 -0
  43. package/lib/agent-cli/lib/ui/clack-helpers.js +317 -0
  44. package/lib/agent-cli/lib/ui/common.js +83 -0
  45. package/lib/agent-cli/lib/ui/completion-ui.js +126 -0
  46. package/lib/agent-cli/lib/ui/custom-select.js +69 -0
  47. package/lib/agent-cli/lib/ui/dashboard-ui.js +222 -0
  48. package/lib/agent-cli/lib/ui/evolution-signals-ui.js +107 -0
  49. package/lib/agent-cli/lib/ui/export-ui.js +94 -0
  50. package/lib/agent-cli/lib/ui/fix-all-ui.js +191 -0
  51. package/lib/agent-cli/lib/ui/help-ui.js +49 -0
  52. package/lib/agent-cli/lib/ui/index.js +199 -0
  53. package/lib/agent-cli/lib/ui/init-ui.js +56 -0
  54. package/lib/agent-cli/lib/ui/knowledge-ui.js +55 -0
  55. package/lib/agent-cli/lib/ui/learn-ui.js +706 -0
  56. package/lib/agent-cli/lib/ui/lessons-ui.js +148 -0
  57. package/lib/agent-cli/lib/ui/pretty.js +145 -0
  58. package/lib/agent-cli/lib/ui/proposals-ui.js +99 -0
  59. package/lib/agent-cli/lib/ui/recall-ui.js +342 -0
  60. package/lib/agent-cli/lib/ui/routing-demo.js +79 -0
  61. package/lib/agent-cli/lib/ui/routing-ui.js +325 -0
  62. package/lib/agent-cli/lib/ui/settings-ui.js +381 -0
  63. package/lib/agent-cli/lib/ui/stats-ui.js +123 -0
  64. package/lib/agent-cli/lib/ui/watch-ui.js +236 -0
  65. package/lib/agent-cli/lib/watcher.js +181 -0
  66. package/lib/agent-cli/lib/watcher.test.js +85 -0
  67. package/lib/agent-cli/src/MIGRATION.md +418 -0
  68. package/lib/agent-cli/src/README.md +367 -0
  69. package/lib/agent-cli/src/core/evolution/evolution-signal.js +42 -0
  70. package/lib/agent-cli/src/core/evolution/index.js +17 -0
  71. package/lib/agent-cli/src/core/evolution/review-gate.js +40 -0
  72. package/lib/agent-cli/src/core/evolution/signal-detector.js +137 -0
  73. package/lib/agent-cli/src/core/evolution/signal-queue.js +79 -0
  74. package/lib/agent-cli/src/core/evolution/threshold-checker.js +79 -0
  75. package/lib/agent-cli/src/core/index.js +15 -0
  76. package/lib/agent-cli/src/core/learning/cognitive-enhancer.js +282 -0
  77. package/lib/agent-cli/src/core/learning/index.js +12 -0
  78. package/lib/agent-cli/src/core/learning/lesson-synthesizer.js +83 -0
  79. package/lib/agent-cli/src/core/scanning/index.js +14 -0
  80. package/lib/agent-cli/src/data/index.js +13 -0
  81. package/lib/agent-cli/src/data/repositories/index.js +8 -0
  82. package/lib/agent-cli/src/data/repositories/lesson-repository.js +130 -0
  83. package/lib/agent-cli/src/data/repositories/signal-repository.js +119 -0
  84. package/lib/agent-cli/src/data/storage/index.js +8 -0
  85. package/lib/agent-cli/src/data/storage/json-storage.js +64 -0
  86. package/lib/agent-cli/src/data/storage/yaml-storage.js +66 -0
  87. package/lib/agent-cli/src/infrastructure/index.js +13 -0
  88. package/lib/agent-cli/src/presentation/formatters/skill-formatter.js +232 -0
  89. package/lib/agent-cli/src/services/export-service.js +162 -0
  90. package/lib/agent-cli/src/services/index.js +13 -0
  91. package/lib/agent-cli/src/services/learning-service.js +99 -0
  92. package/package.json +5 -3
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Lint Learn - Auto-Learn from ESLint Output (CLI v3.3.0)
4
+ *
5
+ * Parses ESLint JSON output and creates lessons automatically.
6
+ *
7
+ * Usage:
8
+ * npx eslint . --format json | agent lint-learn
9
+ * npx eslint . --format json > output.json && agent lint-learn output.json
10
+ */
11
+
12
+ import fs from "fs";
13
+ import { loadKnowledge, saveKnowledge } from "../recall.js";
14
+
15
+ // ============================================================================
16
+ // ESLINT PARSER
17
+ // ============================================================================
18
+
19
+ /**
20
+ * Parse ESLint JSON output and extract rules
21
+ * @param {string} jsonContent
22
+ * @returns {Array<{ rule: string, count: number, message: string }>}
23
+ */
24
+ function parseEslintOutput(jsonContent) {
25
+ const ruleStats = {};
26
+
27
+ try {
28
+ const results = JSON.parse(jsonContent);
29
+
30
+ results.forEach(file => {
31
+ if (!file.messages) return;
32
+
33
+ file.messages.forEach(msg => {
34
+ if (!msg.ruleId) return;
35
+
36
+ if (!ruleStats[msg.ruleId]) {
37
+ ruleStats[msg.ruleId] = {
38
+ rule: msg.ruleId,
39
+ count: 0,
40
+ message: msg.message,
41
+ severity: msg.severity === 2 ? "ERROR" : "WARNING"
42
+ };
43
+ }
44
+ ruleStats[msg.ruleId].count++;
45
+ });
46
+ });
47
+ } catch (e) {
48
+ console.error("❌ Failed to parse ESLint JSON output:", e.message);
49
+ process.exit(1);
50
+ }
51
+
52
+ return Object.values(ruleStats).sort((a, b) => b.count - a.count);
53
+ }
54
+
55
+ /**
56
+ * Convert ESLint rule to regex pattern
57
+ * @param {string} rule - ESLint rule ID
58
+ * @returns {string}
59
+ */
60
+ function ruleToPattern(rule) {
61
+ // Map common ESLint rules to regex patterns
62
+ const patterns = {
63
+ "no-console": "console\\.(log|warn|error|info|debug)",
64
+ "no-debugger": "\\bdebugger\\b",
65
+ "no-var": "\\bvar\\s+",
66
+ "no-unused-vars": null, // Can't easily detect with regex
67
+ "no-undef": null,
68
+ "eqeqeq": "[^!=]==[^=]",
69
+ "no-eval": "\\beval\\s*\\(",
70
+ "no-alert": "\\balert\\s*\\("
71
+ };
72
+
73
+ return patterns[rule] || null;
74
+ }
75
+
76
+ // ============================================================================
77
+ // MAIN
78
+ // ============================================================================
79
+
80
+ async function main() {
81
+ const args = process.argv.slice(2);
82
+ let jsonContent = "";
83
+
84
+ if (args.includes("--help")) {
85
+ console.log(`
86
+ 🔧 Lint Learn - Auto-Learn from ESLint
87
+
88
+ Usage:
89
+ npx eslint . --format json | agent lint-learn
90
+ agent lint-learn eslint-output.json
91
+
92
+ Creates lessons from ESLint violations automatically.
93
+ `);
94
+ process.exit(0);
95
+ }
96
+
97
+ // Read from file or stdin
98
+ if (args[0] && !args[0].startsWith("-")) {
99
+ if (fs.existsSync(args[0])) {
100
+ jsonContent = fs.readFileSync(args[0], "utf8");
101
+ } else {
102
+ console.error(`❌ File not found: ${args[0]}`);
103
+ process.exit(1);
104
+ }
105
+ } else {
106
+ // Read from stdin
107
+ const chunks = [];
108
+ process.stdin.setEncoding("utf8");
109
+
110
+ for await (const chunk of process.stdin) {
111
+ chunks.push(chunk);
112
+ }
113
+ jsonContent = chunks.join("");
114
+ }
115
+
116
+ if (!jsonContent.trim()) {
117
+ console.log("ℹ️ No input received. Pipe ESLint JSON output or provide a file.");
118
+ process.exit(0);
119
+ }
120
+
121
+ const rules = parseEslintOutput(jsonContent);
122
+
123
+ if (rules.length === 0) {
124
+ console.log("✅ No ESLint violations found.");
125
+ process.exit(0);
126
+ }
127
+
128
+ console.log(`\n🔧 Lint Learn - Found ${rules.length} unique ESLint rule(s)\n`);
129
+
130
+ const db = loadKnowledge();
131
+ let added = 0;
132
+
133
+ rules.forEach(r => {
134
+ const pattern = ruleToPattern(r.rule);
135
+
136
+ if (!pattern) {
137
+ console.log(`⏭️ Skipped: ${r.rule} (no regex pattern available)`);
138
+ return;
139
+ }
140
+
141
+ // Check if already exists
142
+ const exists = db.lessons.some(l => l.pattern === pattern);
143
+ if (exists) {
144
+ console.log(`⏭️ Skipped: ${r.rule} (already in memory)`);
145
+ return;
146
+ }
147
+
148
+ const id = `LEARN-${String(db.lessons.length + 1).padStart(3, "0")}`;
149
+
150
+ db.lessons.push({
151
+ id,
152
+ pattern,
153
+ message: `ESLint: ${r.rule} - ${r.message}`,
154
+ severity: r.severity,
155
+ source: "eslint",
156
+ hitCount: r.count,
157
+ addedAt: new Date().toISOString()
158
+ });
159
+
160
+ added++;
161
+ console.log(`✅ Added: [${id}] ${r.rule} (${r.count} occurrences)`);
162
+ });
163
+
164
+ if (added > 0) {
165
+ saveKnowledge(db);
166
+ console.log(`\n🎓 Learned ${added} new lesson(s) from ESLint output.\n`);
167
+ } else {
168
+ console.log("\nℹ️ No new lessons to add.\n");
169
+ }
170
+ }
171
+
172
+ main();
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Windows-safe icons utility
3
+ *
4
+ * Provides ASCII fallback for emojis/Unicode when running on Windows Console
5
+ * that doesn't support UTF-8 properly.
6
+ */
7
+
8
+ // Check if we're in a Windows environment with potential encoding issues
9
+ const isWindowsConsole = process.platform === 'win32' &&
10
+ (!process.env.WT_SESSION && !process.env.TERM_PROGRAM);
11
+
12
+ // Icon mappings: [unicode, ascii fallback]
13
+ const ICONS = {
14
+ brain: ['🧠', '[*]'],
15
+ check: ['✓', '[v]'],
16
+ cross: ['✗', '[x]'],
17
+ warning: ['⚠️', '[!]'],
18
+ info: ['ℹ️', '[i]'],
19
+ arrow: ['›', '>'],
20
+ star: ['⭐', '*'],
21
+ rocket: ['🚀', '>>'],
22
+ fire: ['🔥', '!!'],
23
+ party: ['🎉', ':)'],
24
+ magnify: ['🔍', '?'],
25
+ folder: ['📁', '[]'],
26
+ file: ['📄', '-'],
27
+ gear: ['⚙️', '@'],
28
+ lock: ['🔒', '#'],
29
+ key: ['🔑', '#'],
30
+ bulb: ['💡', '!'],
31
+ clock: ['⏰', 'T'],
32
+ success: ['✅', '[OK]'],
33
+ error: ['❌', '[ERR]'],
34
+ sparkle: ['✨', '*'],
35
+ chart: ['📊', '[=]'],
36
+ note: ['📝', '-'],
37
+ book: ['📚', '[]'],
38
+ package: ['📦', '[]'],
39
+ tools: ['🛠️', '[]'],
40
+ shield: ['🛡️', 'S'],
41
+ target: ['🎯', 'o'],
42
+ refresh: ['🔄', '@'],
43
+ lightning: ['⚡', '!'],
44
+ };
45
+
46
+ /**
47
+ * Get appropriate icon for current environment
48
+ * @param {string} name - Icon name from ICONS map
49
+ * @returns {string} Unicode icon or ASCII fallback
50
+ */
51
+ export function icon(name) {
52
+ const pair = ICONS[name];
53
+ if (!pair) return '';
54
+ return isWindowsConsole ? pair[1] : pair[0];
55
+ }
56
+
57
+ /**
58
+ * Replace all emojis in text with ASCII equivalents
59
+ * @param {string} text - Text containing emojis
60
+ * @returns {string} Text with ASCII replacements on Windows
61
+ */
62
+ export function safeText(text) {
63
+ if (!isWindowsConsole) return text;
64
+
65
+ let result = text;
66
+ for (const [name, [unicode, ascii]] of Object.entries(ICONS)) {
67
+ result = result.replace(new RegExp(unicode, 'g'), ascii);
68
+ }
69
+ return result;
70
+ }
71
+
72
+ /**
73
+ * Check if Unicode output is safe
74
+ * @returns {boolean}
75
+ */
76
+ export function supportsUnicode() {
77
+ return !isWindowsConsole;
78
+ }
79
+
80
+ // Quick accessor for common icons
81
+ export const icons = {
82
+ get brain() { return icon('brain'); },
83
+ get check() { return icon('check'); },
84
+ get cross() { return icon('cross'); },
85
+ get warning() { return icon('warning'); },
86
+ get arrow() { return icon('arrow'); },
87
+ get party() { return icon('party'); },
88
+ get success() { return icon('success'); },
89
+ get error() { return icon('error'); },
90
+ get sparkle() { return icon('sparkle'); },
91
+ };
92
+
93
+ export default { icon, safeText, supportsUnicode, icons, ICONS };
@@ -0,0 +1,116 @@
1
+ /**
2
+ * @fileoverview Ignore patterns parser for PikaKit
3
+ * Supports .agentignore file with glob patterns
4
+ */
5
+
6
+ import fs from "fs";
7
+ import path from "path";
8
+ import { cwd } from "./config.js";
9
+
10
+ /** Default patterns always ignored */
11
+ const DEFAULT_IGNORES = [
12
+ "node_modules/**",
13
+ ".git/**",
14
+ "dist/**",
15
+ "build/**",
16
+ ".next/**",
17
+ "coverage/**",
18
+ "*.log"
19
+ ];
20
+
21
+ /**
22
+ * Load ignore patterns from .agentignore file
23
+ * @param {string} basePath - Base directory
24
+ * @returns {string[]} Array of patterns
25
+ */
26
+ export function loadIgnorePatterns(basePath = cwd) {
27
+ const patterns = [...DEFAULT_IGNORES];
28
+ const ignoreFile = path.join(basePath, ".agentignore");
29
+
30
+ try {
31
+ if (fs.existsSync(ignoreFile)) {
32
+ const content = fs.readFileSync(ignoreFile, "utf8");
33
+ const lines = content.split("\n");
34
+
35
+ for (const line of lines) {
36
+ const trimmed = line.trim();
37
+ // Skip empty lines and comments
38
+ if (trimmed && !trimmed.startsWith("#")) {
39
+ patterns.push(trimmed);
40
+ }
41
+ }
42
+ }
43
+ } catch (e) {
44
+ // Silently use defaults
45
+ }
46
+
47
+ return [...new Set(patterns)]; // Remove duplicates
48
+ }
49
+
50
+ /**
51
+ * Check if a file path matches any ignore pattern
52
+ * @param {string} filePath - Relative file path
53
+ * @param {string[]} patterns - Ignore patterns
54
+ * @returns {boolean}
55
+ */
56
+ export function isIgnored(filePath, patterns) {
57
+ const normalized = filePath.replace(/\\/g, "/");
58
+
59
+ for (const pattern of patterns) {
60
+ // Simple glob matching
61
+ const regex = patternToRegex(pattern);
62
+ if (regex.test(normalized)) {
63
+ return true;
64
+ }
65
+ }
66
+
67
+ return false;
68
+ }
69
+
70
+ /**
71
+ * Convert glob pattern to regex
72
+ * @param {string} pattern - Glob pattern
73
+ * @returns {RegExp}
74
+ */
75
+ function patternToRegex(pattern) {
76
+ let regex = pattern
77
+ .replace(/\./g, "\\.") // Escape dots
78
+ .replace(/\*\*/g, ".*") // ** matches everything
79
+ .replace(/\*/g, "[^/]*") // * matches segment
80
+ .replace(/\?/g, "."); // ? matches single char
81
+
82
+ // Handle directory patterns (ending with /)
83
+ if (pattern.endsWith("/")) {
84
+ regex = regex.slice(0, -1) + "(/.*)?";
85
+ }
86
+
87
+ return new RegExp(`^${regex}$|/${regex}$|^${regex}/`);
88
+ }
89
+
90
+ /**
91
+ * Filter files array by ignore patterns
92
+ * @param {string[]} files - Array of file paths
93
+ * @param {string[]} patterns - Ignore patterns
94
+ * @returns {{ included: string[], ignored: number }}
95
+ */
96
+ export function filterFiles(files, patterns) {
97
+ const included = [];
98
+ let ignored = 0;
99
+
100
+ for (const file of files) {
101
+ if (isIgnored(file, patterns)) {
102
+ ignored++;
103
+ } else {
104
+ included.push(file);
105
+ }
106
+ }
107
+
108
+ return { included, ignored };
109
+ }
110
+
111
+ export default {
112
+ loadIgnorePatterns,
113
+ isIgnored,
114
+ filterFiles,
115
+ DEFAULT_IGNORES
116
+ };
@@ -0,0 +1,58 @@
1
+ /**
2
+ * @fileoverview Tests for ignore module
3
+ */
4
+
5
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
6
+ import fs from "fs";
7
+ import path from "path";
8
+ import os from "os";
9
+
10
+ // Import directly without mocking - test actual behavior
11
+ import { loadIgnorePatterns, isIgnored } from "./ignore.js";
12
+
13
+ describe("ignore", () => {
14
+ describe("isIgnored", () => {
15
+ it("returns false when no patterns", () => {
16
+ const result = isIgnored("some/path.js", []);
17
+ expect(result).toBe(false);
18
+ });
19
+
20
+ it("matches exact pattern", () => {
21
+ const result = isIgnored("node_modules/pkg/file.js", ["node_modules"]);
22
+ expect(result).toBe(true);
23
+ });
24
+
25
+ it("matches glob pattern", () => {
26
+ const result = isIgnored("debug.log", ["*.log"]);
27
+ expect(result).toBe(true);
28
+ });
29
+
30
+ it("returns false for non-matching path", () => {
31
+ const result = isIgnored("src/app.js", ["*.log", "node_modules"]);
32
+ expect(result).toBe(false);
33
+ });
34
+
35
+ it("matches directory pattern", () => {
36
+ const result = isIgnored("dist/bundle.js", ["dist/**"]);
37
+ expect(result).toBe(true);
38
+ });
39
+
40
+ it("matches nested paths", () => {
41
+ const result = isIgnored(".git/objects/pack", [".git/**"]);
42
+ expect(result).toBe(true);
43
+ });
44
+ });
45
+
46
+ describe("loadIgnorePatterns", () => {
47
+ it("returns array of patterns", () => {
48
+ const patterns = loadIgnorePatterns();
49
+ expect(Array.isArray(patterns)).toBe(true);
50
+ });
51
+
52
+ it("includes default patterns", () => {
53
+ const patterns = loadIgnorePatterns();
54
+ // Should have at least some patterns (defaults or from file)
55
+ expect(patterns.length).toBeGreaterThan(0);
56
+ });
57
+ });
58
+ });
@@ -0,0 +1,124 @@
1
+ /**
2
+ * @fileoverview Project initialization wizard
3
+ * Sets up agent config for new projects
4
+ */
5
+
6
+ import fs from "fs";
7
+ import path from "path";
8
+ import { cwd, AGENT_DIR, KNOWLEDGE_DIR, LESSONS_PATH } from "./config.js";
9
+
10
+ /**
11
+ * Detect project type based on files
12
+ * @returns {string} Project type
13
+ */
14
+ export function detectProjectType() {
15
+ const files = fs.readdirSync(cwd);
16
+
17
+ if (files.includes("package.json")) {
18
+ const pkg = JSON.parse(fs.readFileSync(path.join(cwd, "package.json"), "utf8"));
19
+
20
+ if (pkg.dependencies?.next || pkg.devDependencies?.next) return "nextjs";
21
+ if (pkg.dependencies?.react || pkg.devDependencies?.react) return "react";
22
+ if (pkg.dependencies?.vue || pkg.devDependencies?.vue) return "vue";
23
+ if (pkg.dependencies?.express || pkg.devDependencies?.express) return "node";
24
+ return "node";
25
+ }
26
+
27
+ if (files.includes("requirements.txt") || files.includes("pyproject.toml")) return "python";
28
+ if (files.includes("Cargo.toml")) return "rust";
29
+ if (files.includes("go.mod")) return "go";
30
+ if (files.includes("pom.xml") || files.includes("build.gradle")) return "java";
31
+
32
+ return "generic";
33
+ }
34
+
35
+ /**
36
+ * Get default ignore patterns for project type
37
+ * @param {string} projectType
38
+ * @returns {string[]}
39
+ */
40
+ export function getDefaultIgnorePatterns(projectType) {
41
+ const common = [
42
+ "node_modules/**",
43
+ ".git/**",
44
+ "dist/**",
45
+ "build/**",
46
+ "coverage/**",
47
+ "*.log",
48
+ "*.lock",
49
+ ".env*"
50
+ ];
51
+
52
+ const specific = {
53
+ node: ["package-lock.json"],
54
+ nextjs: [".next/**", "out/**"],
55
+ react: ["build/**"],
56
+ vue: [".nuxt/**"],
57
+ python: ["__pycache__/**", "*.pyc", ".venv/**", "venv/**"],
58
+ rust: ["target/**"],
59
+ go: ["vendor/**"],
60
+ java: ["target/**", "*.class"],
61
+ generic: []
62
+ };
63
+
64
+ return [...common, ...(specific[projectType] || [])];
65
+ }
66
+
67
+ /**
68
+ * Initialize agent config
69
+ * @param {object} options
70
+ * @param {boolean} options.force - Overwrite existing
71
+ * @returns {{ success: boolean, message: string }}
72
+ */
73
+ export function initProject(options = {}) {
74
+ const { force = false } = options;
75
+
76
+ // Check if already initialized
77
+ if (fs.existsSync(KNOWLEDGE_DIR) && !force) {
78
+ return {
79
+ success: false,
80
+ message: "Already initialized. Use --force to reinitialize."
81
+ };
82
+ }
83
+
84
+ // Detect project type
85
+ const projectType = detectProjectType();
86
+
87
+ // Create directories
88
+ fs.mkdirSync(KNOWLEDGE_DIR, { recursive: true });
89
+
90
+ // Create lessons-learned.yaml
91
+ if (!fs.existsSync(LESSONS_PATH)) {
92
+ const initialLessons = `# PikaKit - Lessons Learned
93
+ # Project Type: ${projectType}
94
+ # Created: ${new Date().toISOString()}
95
+
96
+ lessons: []
97
+ `;
98
+ fs.writeFileSync(LESSONS_PATH, initialLessons);
99
+ }
100
+
101
+ // Create .agentignore if not exists
102
+ const agentignorePath = path.join(cwd, ".agentignore");
103
+ if (!fs.existsSync(agentignorePath)) {
104
+ const patterns = getDefaultIgnorePatterns(projectType);
105
+ fs.writeFileSync(agentignorePath, patterns.join("\n") + "\n");
106
+ }
107
+
108
+ return {
109
+ success: true,
110
+ message: `Initialized for ${projectType} project`,
111
+ projectType,
112
+ paths: {
113
+ knowledge: KNOWLEDGE_DIR,
114
+ lessons: LESSONS_PATH,
115
+ agentignore: agentignorePath
116
+ }
117
+ };
118
+ }
119
+
120
+ export default {
121
+ detectProjectType,
122
+ getDefaultIgnorePatterns,
123
+ initProject
124
+ };