universal-agent-memory 0.1.1 → 0.1.3

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.
@@ -1,641 +1,717 @@
1
1
  import Handlebars from 'handlebars';
2
+ import { existsSync, readFileSync, readdirSync, statSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { prepopulateMemory } from '../memory/prepopulate.js';
2
5
  export async function generateClaudeMd(analysis, config) {
3
- const template = getTemplate(config);
6
+ // Determine platform mode
7
+ const hasWebDatabase = !!config.memory?.shortTerm?.webDatabase;
8
+ const forceDesktop = config.memory?.shortTerm?.forceDesktop;
9
+ const isWebPlatform = hasWebDatabase && !forceDesktop;
10
+ // Use appropriate template
11
+ const template = isWebPlatform ? getWebTemplate() : getDesktopTemplate();
4
12
  const compiled = Handlebars.compile(template);
5
- const context = buildContext(analysis, config);
13
+ // Build comprehensive context from analysis + auto-population
14
+ const context = await buildContext(analysis, config);
6
15
  return compiled(context);
7
16
  }
8
- function buildContext(analysis, config) {
9
- // Detect web platform by checking memory config for web database setting
17
+ async function buildContext(analysis, config) {
18
+ const cwd = process.cwd();
19
+ // Detect web vs desktop
10
20
  const hasWebDatabase = !!config.memory?.shortTerm?.webDatabase;
11
21
  const forceDesktop = config.memory?.shortTerm?.forceDesktop;
12
22
  const isWebPlatform = hasWebDatabase && !forceDesktop;
13
- const isDesktopPlatform = !isWebPlatform;
14
- // Determine long-term memory provider
15
- let longTermProvider = 'qdrant';
23
+ // Long-term memory config
24
+ let longTermBackend = 'Qdrant';
16
25
  let longTermEndpoint = config.memory?.longTerm?.endpoint || 'localhost:6333';
17
- let longTermCollection = config.memory?.longTerm?.collection || 'agent_memory';
26
+ const longTermCollection = config.memory?.longTerm?.collection || 'agent_memory';
18
27
  if (config.memory?.longTerm?.provider === 'github') {
19
- longTermProvider = 'github';
28
+ longTermBackend = 'GitHub';
20
29
  longTermEndpoint = `${config.memory?.longTerm?.github?.repo || 'owner/repo'}/${config.memory?.longTerm?.github?.path || '.uam/memory'}`;
21
30
  }
22
31
  else if (config.memory?.longTerm?.provider === 'qdrant-cloud') {
23
- longTermProvider = 'qdrant-cloud';
32
+ longTermBackend = 'Qdrant Cloud';
24
33
  longTermEndpoint = config.memory?.longTerm?.qdrantCloud?.url || 'https://xxxxxx.aws.cloud.qdrant.io:6333';
25
34
  }
26
- // GitHub repo info for web memory
27
- const githubRepo = config.memory?.longTerm?.github?.repo || '';
28
- const githubMemoryPath = config.memory?.longTerm?.github?.path || '.uam/memory';
35
+ // Prepopulate memory from project
36
+ let prepopulated = null;
37
+ try {
38
+ prepopulated = await prepopulateMemory(cwd, { docs: true, git: true, skills: true, limit: 200 });
39
+ }
40
+ catch (e) {
41
+ console.warn('Failed to prepopulate memory:', e);
42
+ }
43
+ // Build repository structure
44
+ const repoStructure = buildRepositoryStructure(cwd, analysis);
45
+ // Discover skills, droids, commands
46
+ const discoveredSkills = prepopulated?.skills || [];
47
+ const skills = discoveredSkills.filter(s => s.type === 'skill');
48
+ const droids = discoveredSkills.filter(s => s.type === 'droid');
49
+ // Commands discovered from prepopulate (unused currently but kept for reference)
50
+ // const commands = discoveredSkills.filter(s => s.type === 'command');
51
+ // Build skill mappings table
52
+ const skillMappings = buildSkillMappings(skills);
53
+ // Build language droids table
54
+ const languageDroids = buildLanguageDroidsTable(droids, analysis.languages);
55
+ // Build discovered skills table
56
+ const discoveredSkillsTable = buildDiscoveredSkillsTable(skills);
57
+ // Extract troubleshooting from git history
58
+ const troubleshooting = buildTroubleshootingSection(prepopulated?.longTerm || []);
59
+ // Build architecture overview
60
+ const architectureOverview = buildArchitectureOverview(analysis);
61
+ // Build core components section
62
+ const coreComponents = buildCoreComponentsSection(analysis);
63
+ // Build key config files
64
+ const keyConfigFiles = buildKeyConfigFiles(analysis);
65
+ // Build essential commands
66
+ const essentialCommands = buildEssentialCommands(analysis);
67
+ // Build prepopulated knowledge section
68
+ const prepopulatedKnowledge = buildPrepopulatedKnowledge(prepopulated);
69
+ // Build cluster contexts
70
+ const clusterContexts = buildClusterContexts(analysis);
71
+ // Build project URLs
72
+ const projectUrls = buildProjectUrls(analysis);
73
+ // Build key workflows
74
+ const keyWorkflows = buildKeyWorkflows(analysis);
75
+ // Build infrastructure workflow
76
+ const infraWorkflow = buildInfraWorkflow(analysis);
77
+ // Build MCP plugins
78
+ const mcpPlugins = buildMcpPlugins(cwd);
79
+ // Build primary skills for decision loop
80
+ const primarySkills = buildPrimarySkills(skills);
81
+ // Build language examples
82
+ const languageExamples = buildLanguageExamples(analysis.languages);
29
83
  return {
84
+ // Project basics
30
85
  PROJECT_NAME: analysis.projectName || config.project.name,
31
86
  DESCRIPTION: analysis.description || config.project.description || '',
32
87
  DEFAULT_BRANCH: analysis.defaultBranch || config.project.defaultBranch || 'main',
33
- // Platform detection
34
- IS_WEB_PLATFORM: isWebPlatform,
35
- IS_DESKTOP_PLATFORM: isDesktopPlatform,
36
88
  // Issue tracker
37
- HAS_ISSUE_TRACKER: !!analysis.issueTracker,
38
- ISSUE_TRACKER_NAME: analysis.issueTracker?.name || 'GitHub Issues',
39
- ISSUE_TRACKER_URL: analysis.issueTracker?.url || '',
40
- // Memory config - ALWAYS shown, differs by platform
41
- SHORT_TERM_PATH: config.memory?.shortTerm?.path || './agents/data/memory/short_term.db',
42
- SHORT_TERM_MAX_ENTRIES: config.memory?.shortTerm?.maxEntries || 50,
43
- LONG_TERM_PROVIDER: longTermProvider,
89
+ ISSUE_TRACKER: analysis.issueTracker ?
90
+ `Use [${analysis.issueTracker.name}](${analysis.issueTracker.url || '#'}) for issue tracking.` :
91
+ null,
92
+ // Memory config
93
+ MEMORY_DB_PATH: config.memory?.shortTerm?.path || 'agents/data/memory/short_term.db',
94
+ MEMORY_QUERY_CMD: 'uam memory query',
95
+ MEMORY_STORE_CMD: 'uam memory store',
96
+ MEMORY_START_CMD: 'uam memory start',
97
+ MEMORY_STATUS_CMD: 'uam memory status',
98
+ MEMORY_STOP_CMD: 'uam memory stop',
99
+ SHORT_TERM_LIMIT: config.memory?.shortTerm?.maxEntries || 50,
100
+ LONG_TERM_BACKEND: longTermBackend,
44
101
  LONG_TERM_ENDPOINT: longTermEndpoint,
45
102
  LONG_TERM_COLLECTION: longTermCollection,
46
- GITHUB_REPO: githubRepo,
47
- GITHUB_MEMORY_PATH: githubMemoryPath,
48
- HAS_GITHUB_MEMORY: !!githubRepo,
49
- // Worktree config - ALWAYS enabled for desktop
103
+ SCREENSHOTS_PATH: 'agents/data/screenshots',
104
+ DOCKER_COMPOSE_PATH: existsSync(join(cwd, 'agents/docker-compose.yml')) ? 'agents/docker-compose.yml' :
105
+ existsSync(join(cwd, 'docker-compose.yml')) ? 'docker-compose.yml' : null,
106
+ // Worktree config
50
107
  WORKTREE_DIR: config.worktrees?.directory || '.worktrees',
51
- WORKTREE_PREFIX: config.worktrees?.branchPrefix || 'feature/',
52
- // URLs
53
- URLS: analysis.urls,
54
- HAS_URLS: analysis.urls.length > 0,
55
- // Clusters
56
- HAS_CLUSTERS: analysis.clusters?.enabled,
57
- CLUSTERS: analysis.clusters?.contexts || [],
58
- // Components
59
- COMPONENTS: analysis.components,
60
- HAS_COMPONENTS: analysis.components.length > 0,
108
+ WORKTREE_CREATE_CMD: 'uam worktree create',
109
+ WORKTREE_PR_CMD: 'uam worktree pr',
110
+ WORKTREE_CLEANUP_CMD: 'uam worktree cleanup',
111
+ WORKTREE_APPLIES_TO: 'Application code, configs, workflows, documentation, CLAUDE.md itself',
112
+ BRANCH_PREFIX: config.worktrees?.branchPrefix || 'feature/',
113
+ // Paths
114
+ SKILLS_PATH: '.factory/skills/',
115
+ DROIDS_PATH: '.factory/droids/',
116
+ COMMANDS_PATH: '.factory/commands/',
117
+ DOCS_PATH: analysis.directories.docs[0] || 'docs',
118
+ FIXES_PATH: existsSync(join(cwd, 'docs/fixes')) ? 'docs/fixes/' : null,
119
+ CHANGELOG_PATH: existsSync(join(cwd, 'docs/changelog')) ? 'docs/changelog' : null,
120
+ CHANGELOG_TEMPLATE: existsSync(join(cwd, 'docs/changelog/CHANGELOG_TEMPLATE.md')) ? 'docs/changelog/CHANGELOG_TEMPLATE.md' : null,
121
+ WORKFLOW_DOCS_PATH: existsSync(join(cwd, 'docs/workflows/GIT_WORKTREE_WORKFLOW.md')) ? 'docs/workflows/GIT_WORKTREE_WORKFLOW.md' : null,
61
122
  // Commands
62
123
  TEST_COMMAND: analysis.commands.test || 'npm test',
63
124
  LINT_COMMAND: analysis.commands.lint || 'npm run lint',
64
125
  BUILD_COMMAND: analysis.commands.build || 'npm run build',
126
+ HOOKS_INSTALL_CMD: existsSync(join(cwd, '.factory/scripts/install-hooks.sh')) ? '.factory/scripts/install-hooks.sh' : null,
127
+ // Skills and droids
128
+ PRIMARY_SKILLS: primarySkills,
129
+ SKILL_MAPPINGS: skillMappings,
130
+ DISCOVERED_SKILLS: discoveredSkillsTable,
131
+ LANGUAGE_DROIDS: languageDroids,
132
+ LANGUAGE_EXAMPLES: languageExamples,
133
+ // Repository structure
134
+ '@REPOSITORY_STRUCTURE': repoStructure,
135
+ STRUCTURE_DATE: new Date().toLocaleString('en-US', { month: 'long', year: 'numeric' }),
136
+ // Path migrations (if detected from git history)
137
+ PATH_MIGRATIONS: null, // TODO: detect from git mv history
138
+ // Clusters and URLs
139
+ CLUSTER_CONTEXTS: clusterContexts,
140
+ PROJECT_URLS: projectUrls,
141
+ KEY_WORKFLOWS: keyWorkflows,
142
+ ESSENTIAL_COMMANDS: essentialCommands,
143
+ // Architecture
144
+ ARCHITECTURE_OVERVIEW: architectureOverview,
145
+ DATABASE_ARCHITECTURE: analysis.databases.length > 0 ? buildDatabaseArchitecture(analysis) : null,
146
+ // Core components
147
+ CORE_COMPONENTS: coreComponents,
148
+ // Auth flow
149
+ AUTH_FLOW: analysis.authentication ? buildAuthFlow(analysis) : null,
150
+ // Gateway knowledge
151
+ GATEWAY_KNOWLEDGE: null, // Project-specific, detected from k8s/istio files
152
+ // Multi-environment
153
+ MULTI_ENV_CONFIG: null, // Project-specific
65
154
  // Infrastructure
66
- INFRA_PATH: analysis.directories.infrastructure[0] || 'infra/',
67
- HAS_TERRAFORM: analysis.infrastructure.iac === 'Terraform',
68
- HAS_KUBERNETES: analysis.infrastructure.containerOrchestration === 'Kubernetes',
69
- // Databases
70
- DATABASES: analysis.databases,
71
- HAS_DATABASES: analysis.databases.length > 0,
72
- // Auth
73
- HAS_AUTH: !!analysis.authentication,
74
- AUTH_PROVIDER: analysis.authentication?.provider,
75
- AUTH_DESCRIPTION: analysis.authentication?.description,
76
- // CI/CD
77
- HAS_CICD: !!analysis.ciCd,
78
- CICD_PLATFORM: analysis.ciCd?.platform,
79
- WORKFLOWS: analysis.ciCd?.workflows || [],
80
- // Existing agents
81
- DROIDS: analysis.existingDroids,
82
- HAS_DROIDS: analysis.existingDroids.length > 0,
83
- SKILLS: analysis.existingSkills,
84
- HAS_SKILLS: analysis.existingSkills.length > 0,
85
- COMMANDS: analysis.existingCommands,
86
- HAS_COMMANDS: analysis.existingCommands.length > 0,
155
+ HAS_INFRA: analysis.directories.infrastructure.length > 0,
156
+ INFRA_WORKFLOW: infraWorkflow,
157
+ CLUSTER_IDENTIFY: analysis.clusters?.enabled ? 'Identify which cluster(s) affected' : null,
87
158
  // Troubleshooting
88
- TROUBLESHOOTING_HINTS: analysis.troubleshootingHints,
89
- HAS_TROUBLESHOOTING: analysis.troubleshootingHints.length > 0,
90
- // Key files
91
- KEY_FILES: analysis.keyFiles,
92
- HAS_KEY_FILES: analysis.keyFiles.length > 0,
93
- // Security
94
- SECURITY_NOTES: analysis.securityNotes,
95
- HAS_SECURITY_NOTES: analysis.securityNotes.length > 0,
96
- // Languages/Frameworks
97
- LANGUAGES: analysis.languages.join(', '),
98
- FRAMEWORKS: analysis.frameworks.join(', '),
159
+ TROUBLESHOOTING: troubleshooting,
160
+ // Key config files
161
+ KEY_CONFIG_FILES: keyConfigFiles,
162
+ // MCP plugins
163
+ MCP_PLUGINS: mcpPlugins,
164
+ // Prepopulated knowledge
165
+ PREPOPULATED_KNOWLEDGE: prepopulatedKnowledge ? true : null,
166
+ RECENT_ACTIVITY: prepopulatedKnowledge?.recentActivity || null,
167
+ LEARNED_LESSONS: prepopulatedKnowledge?.learnedLessons || null,
168
+ KNOWN_GOTCHAS: prepopulatedKnowledge?.knownGotchas || null,
169
+ HOT_SPOTS: prepopulatedKnowledge?.hotSpots || null,
170
+ // Platform detection
171
+ IS_WEB_PLATFORM: isWebPlatform,
172
+ IS_DESKTOP_PLATFORM: !isWebPlatform,
99
173
  };
100
174
  }
101
- function getTemplate(_config) {
102
- return `<coding_guidelines>
103
-
104
- # {{#if IS_WEB_PLATFORM}}AGENT.md{{else}}CLAUDE.md{{/if}} - {{PROJECT_NAME}} Development Guide
105
-
106
- You are Autonomous Claude, a self-directed AI agent with full control over this environment. You operate continuously, making your own decisions.
107
- {{#if DESCRIPTION}}
108
-
109
- > {{DESCRIPTION}}
110
- {{/if}}
111
-
112
- ---
113
-
114
- ## MANDATORY RULES - READ BEFORE ANY ACTION ⛔
115
-
116
- **STOP! Before making ANY code/infrastructure changes, you MUST follow these rules:**
117
-
118
- {{#if IS_DESKTOP_PLATFORM}}
119
- ### 1. WORKTREE REQUIREMENT (NO EXCEPTIONS)
120
-
121
- \`\`\`
122
- FORBIDDEN: Direct commits to {{DEFAULT_BRANCH}} branch
123
- REQUIRED: Create worktree Make changes → Create PR → Merge via PR
124
- \`\`\`
125
-
126
- **Before ANY code change:**
127
-
128
- \`\`\`bash
129
- # Step 1: Create worktree
130
- uam worktree create <descriptive-slug>
131
-
132
- # Step 2: cd into worktree and make changes
133
- cd {{WORKTREE_DIR}}/NNN-<slug>/
134
-
135
- # Step 3: Commit and create PR
136
- uam worktree pr <id>
137
- \`\`\`
138
-
139
- **Applies to:** All code, configs, workflows, documentation
140
- {{else}}
141
- ### 1. BRANCH REQUIREMENT (NO EXCEPTIONS)
142
-
143
- \`\`\`
144
- ❌ FORBIDDEN: Direct commits to {{DEFAULT_BRANCH}} branch
145
- ✅ REQUIRED: Create branch → Make changes → Create PR → Merge via PR
146
- \`\`\`
147
-
148
- **Before ANY code change:**
149
-
150
- \`\`\`bash
151
- git checkout -b {{WORKTREE_PREFIX}}<descriptive-slug>
152
- # Make changes, commit, push
153
- git push -u origin {{WORKTREE_PREFIX}}<descriptive-slug>
154
- # Create PR via UI
155
- \`\`\`
156
- {{/if}}
157
-
158
- ### 2. MEMORY REQUIREMENT (AFTER SIGNIFICANT ACTIONS)
159
-
160
- \`\`\`bash
161
- # Store learnings after: fixes, discoveries, architecture decisions, gotchas
162
- uam memory store lesson "What you learned" --tags tag1,tag2 --importance 7
163
- \`\`\`
164
-
165
- **Must store memories for:**
166
- - Infrastructure changes (cost savings, scaling decisions, fixes)
167
- - Bug fixes and their root causes
168
- - Architecture decisions and rationale
169
- - Gotchas and workarounds discovered
170
- - Performance optimizations
171
-
172
- ### 3. TODO LIST REQUIREMENT
173
-
174
- - Create todo list for multi-step tasks (3+ steps)
175
- - Update status IMMEDIATELY after completing each item
176
- - Never let todos go stale (update every 5-10 tool calls)
177
-
178
- ### 4. VERIFICATION BEFORE COMPLETION
179
-
180
- - [ ] Used {{#if IS_DESKTOP_PLATFORM}}worktree{{else}}feature branch{{/if}} for code changes? (or explain why not applicable)
181
- - [ ] Stored significant learnings in memory?
182
- - [ ] Updated/completed todo list?
183
- - [ ] Created PR instead of direct commit?
184
-
185
- ---
186
-
187
- ## MEMORY SYSTEM
188
-
189
- > **CRITICAL**: Memory updates are MANDATORY, not optional. Every significant discovery, fix, or lesson learned MUST be stored before completing a task.
190
-
191
- {{#if IS_DESKTOP_PLATFORM}}
192
- ### Short-term Memory (SQLite: \`{{SHORT_TERM_PATH}}\`)
193
-
194
- Table: \`memories\`
195
- - \`id\`: INTEGER PRIMARY KEY
196
- - \`timestamp\`: TEXT (ISO8601)
197
- - \`type\`: TEXT (action|observation|thought|goal)
198
- - \`content\`: TEXT
199
-
200
- **BEFORE EACH DECISION**: Query recent entries (last {{SHORT_TERM_MAX_ENTRIES}}) to understand context:
201
- \`\`\`sql
202
- SELECT * FROM memories ORDER BY id DESC LIMIT {{SHORT_TERM_MAX_ENTRIES}};
203
- \`\`\`
204
-
205
- **AFTER EACH ACTION**: Record what you did and the outcome:
206
- \`\`\`sql
207
- INSERT INTO memories (timestamp, type, content) VALUES (datetime('now'), 'action', 'Description...');
208
- \`\`\`
209
-
210
- ### Long-term Memory ({{LONG_TERM_PROVIDER}}: \`{{LONG_TERM_ENDPOINT}}\`, collection: \`{{LONG_TERM_COLLECTION}}\`)
211
-
212
- **Start services**: \`uam memory start\`
213
-
214
- Vector schema:
215
- - \`id\`: UUID
216
- - \`vector\`: 384-dim embedding (all-MiniLM-L6-v2)
217
- - \`payload\`: {type, tags[], content, importance (1-10), timestamp}
218
-
219
- **Query memories** (semantic search):
220
- \`\`\`bash
221
- uam memory query "search term"
222
- \`\`\`
223
-
224
- **Store new memory** (MANDATORY for significant learnings):
225
- \`\`\`bash
226
- uam memory store <type> "content" --tags tag1,tag2 --importance N
227
- \`\`\`
228
-
229
- Memory types: \`fact\`, \`lesson\`, \`skill\`, \`discovery\`, \`preference\`
230
-
231
- ### MANDATORY Memory Triggers
232
-
233
- **ALWAYS store to long-term memory when you:**
234
- 1. Fix a bug or resolve an error (lesson)
235
- 2. Discover how a system/component works (discovery)
236
- 3. Learn a configuration requirement (fact)
237
- 4. Find a successful approach to a problem (skill)
238
- 5. Identify a coding pattern or convention (preference)
239
- 6. Complete infrastructure changes (fact)
240
- 7. Debug authentication/networking issues (lesson)
241
-
242
- **Memory storage is part of task completion.** A task is NOT complete until learnings are stored.
243
-
244
- ### Agent Services Setup
245
-
246
- \`\`\`bash
247
- # Start services (auto-creates collection and migrates memories)
248
- uam memory start
249
-
250
- # Check status
251
- uam memory status
252
-
253
- # Stop services
254
- uam memory stop
255
- \`\`\`
256
-
257
- {{else}}
258
- ### Short-term Memory (localStorage)
259
-
260
- You have access to browser localStorage for maintaining context across messages.
261
-
262
- Key: \`agent_context_{{PROJECT_NAME}}\`
263
-
264
- Structure:
265
- \`\`\`json
266
- {
267
- "memories": [
268
- {"timestamp": "ISO8601", "type": "action|observation|thought|goal", "content": "..."}
269
- ],
270
- "maxEntries": {{SHORT_TERM_MAX_ENTRIES}}
175
+ function buildRepositoryStructure(cwd, analysis) {
176
+ const lines = [];
177
+ const visited = new Set();
178
+ // Standard directories to look for
179
+ const standardDirs = [
180
+ { path: 'apps', comment: 'Deployable applications' },
181
+ { path: 'services', comment: 'Backend microservices' },
182
+ { path: 'packages', comment: 'Shared packages' },
183
+ { path: 'libs', comment: 'Shared libraries' },
184
+ { path: 'src', comment: 'Source code' },
185
+ { path: 'infra', comment: 'Infrastructure as Code' },
186
+ { path: 'infrastructure', comment: 'Infrastructure as Code' },
187
+ { path: 'terraform', comment: 'Terraform configurations' },
188
+ { path: 'k8s', comment: 'Kubernetes manifests' },
189
+ { path: 'helm', comment: 'Helm charts' },
190
+ { path: 'tools', comment: 'Development tools' },
191
+ { path: 'scripts', comment: 'Automation scripts' },
192
+ { path: 'tests', comment: 'Test suites' },
193
+ { path: 'test', comment: 'Test suites' },
194
+ { path: 'docs', comment: 'Documentation' },
195
+ { path: '.factory', comment: 'Factory AI configuration' },
196
+ { path: '.github', comment: 'GitHub configuration' },
197
+ { path: '.gitlab', comment: 'GitLab configuration' },
198
+ ];
199
+ for (const { path, comment } of standardDirs) {
200
+ const fullPath = join(cwd, path);
201
+ if (existsSync(fullPath) && statSync(fullPath).isDirectory()) {
202
+ visited.add(path);
203
+ lines.push(`├── ${path}/`.padEnd(35) + `# ${comment}`);
204
+ // List subdirectories
205
+ try {
206
+ const subdirs = readdirSync(fullPath, { withFileTypes: true })
207
+ .filter(d => d.isDirectory() && !d.name.startsWith('.'))
208
+ .slice(0, 8);
209
+ for (let i = 0; i < subdirs.length; i++) {
210
+ const prefix = i === subdirs.length - 1 ? '│ └── ' : '│ ├── ';
211
+ const subComment = getSubdirComment(path, subdirs[i].name, join(fullPath, subdirs[i].name));
212
+ lines.push(`${prefix}${subdirs[i].name}/`.padEnd(35) + (subComment ? `# ${subComment}` : ''));
213
+ }
214
+ }
215
+ catch {
216
+ // Ignore permission errors
217
+ }
218
+ lines.push('│');
219
+ }
220
+ }
221
+ // Add component directories from analysis
222
+ for (const comp of analysis.components) {
223
+ const dirPath = comp.path.split('/')[0];
224
+ if (!visited.has(dirPath) && existsSync(join(cwd, dirPath))) {
225
+ visited.add(dirPath);
226
+ lines.push(`├── ${dirPath}/`.padEnd(35) + `# ${comp.description || comp.name}`);
227
+ }
228
+ }
229
+ // Remove trailing separator
230
+ if (lines.length > 0 && lines[lines.length - 1] === '│') {
231
+ lines.pop();
232
+ }
233
+ return lines.join('\n');
271
234
  }
272
- \`\`\`
273
-
274
- **BEFORE EACH DECISION**: Review recent memories for context
275
- **AFTER EACH ACTION**: Add a memory describing what you did and the outcome
276
-
277
- ### Long-term Memory (GitHub: \`.uam/memory/\`)
278
-
279
- Memories stored as JSON files in the project repository under \`.uam/memory/\`
280
-
281
- File format: \`{YYYY-MM-DD}_{type}_{short-id}.json\`
282
- \`\`\`json
283
- {
284
- "id": "uuid",
285
- "timestamp": "ISO8601",
286
- "type": "fact|lesson|skill|discovery|preference",
287
- "content": "Learning or discovery",
288
- "tags": ["tag1", "tag2"],
289
- "importance": 8
235
+ function getSubdirComment(parentDir, subdir, fullPath) {
236
+ // Check for package.json, README, etc. to get description
237
+ const packageJsonPath = join(fullPath, 'package.json');
238
+ if (existsSync(packageJsonPath)) {
239
+ try {
240
+ const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
241
+ if (pkg.description)
242
+ return pkg.description.slice(0, 40);
243
+ }
244
+ catch {
245
+ // Ignore
246
+ }
247
+ }
248
+ // Default comments based on common patterns
249
+ const patterns = {
250
+ apps: {
251
+ api: 'REST API',
252
+ web: 'Web frontend',
253
+ mobile: 'Mobile app',
254
+ admin: 'Admin dashboard',
255
+ cms: 'CMS',
256
+ },
257
+ services: {
258
+ auth: 'Authentication service',
259
+ gateway: 'API Gateway',
260
+ },
261
+ '.factory': {
262
+ droids: 'Custom AI agents',
263
+ skills: 'Reusable skills',
264
+ commands: 'CLI commands',
265
+ scripts: 'Automation scripts',
266
+ },
267
+ '.github': {
268
+ workflows: 'CI/CD pipelines',
269
+ },
270
+ };
271
+ return patterns[parentDir]?.[subdir] || '';
290
272
  }
291
- \`\`\`
292
-
293
- Memory types: \`fact\`, \`lesson\`, \`skill\`, \`discovery\`, \`preference\`
294
-
295
- ### MANDATORY Memory Triggers
273
+ function buildSkillMappings(skills) {
274
+ if (skills.length === 0)
275
+ return null;
276
+ const lines = [];
277
+ for (const skill of skills) {
278
+ if (skill.name.includes('design') || skill.name.includes('ui')) {
279
+ lines.push(`| UI/Design work (buttons, modals, colors, layouts) | \`${skill.name}\` |`);
280
+ }
281
+ else if (skill.name.includes('frontend') || skill.name.includes('react')) {
282
+ lines.push(`| React/TypeScript/Frontend | \`${skill.name}\` |`);
283
+ }
284
+ else if (skill.name.includes('backend') || skill.name.includes('api')) {
285
+ lines.push(`| Backend/API development | \`${skill.name}\` |`);
286
+ }
287
+ }
288
+ return lines.length > 0 ? lines.join('\n') : null;
289
+ }
290
+ function buildLanguageDroidsTable(droids, languages) {
291
+ const languageDroids = droids.filter(d => d.name.includes('-pro') ||
292
+ d.name.includes('specialist') ||
293
+ languages.some(l => d.name.toLowerCase().includes(l.toLowerCase())));
294
+ if (languageDroids.length === 0 && languages.length > 0) {
295
+ // Generate suggested droids based on detected languages
296
+ const suggestions = [];
297
+ for (const lang of languages.slice(0, 5)) {
298
+ const langLower = lang.toLowerCase();
299
+ if (langLower.includes('typescript') || langLower.includes('javascript')) {
300
+ suggestions.push('| `javascript-pro` | ES6+, async patterns, Node.js, promises, event loops |');
301
+ }
302
+ else if (langLower.includes('python')) {
303
+ suggestions.push('| `python-pro` | Async/await, decorators, generators, pytest, type hints |');
304
+ }
305
+ else if (langLower.includes('c++') || langLower.includes('cpp')) {
306
+ suggestions.push('| `cpp-pro` | C++20 with RAII, smart pointers, STL, templates, move semantics |');
307
+ }
308
+ else if (langLower.includes('rust')) {
309
+ suggestions.push('| `rust-pro` | Ownership, lifetimes, async, error handling, macros |');
310
+ }
311
+ else if (langLower.includes('go')) {
312
+ suggestions.push('| `go-pro` | Concurrency, channels, interfaces, error handling |');
313
+ }
314
+ }
315
+ return suggestions.length > 0 ? [...new Set(suggestions)].join('\n') : null;
316
+ }
317
+ return languageDroids.map(d => `| \`${d.name}\` | ${d.description || `${d.platform} language specialist`} |`).join('\n') || null;
318
+ }
319
+ function buildDiscoveredSkillsTable(skills) {
320
+ if (skills.length === 0)
321
+ return null;
322
+ return skills.slice(0, 10).map(s => {
323
+ const purpose = s.description || `${s.platform} skill`;
324
+ const useWhen = s.name.includes('design') ? 'UI/design work' :
325
+ s.name.includes('test') ? 'Testing and QA' :
326
+ s.name.includes('review') ? 'Code review' :
327
+ 'Specialized tasks';
328
+ return `| \`${s.name}\` | ${purpose} | ${useWhen} |`;
329
+ }).join('\n');
330
+ }
331
+ function buildTroubleshootingSection(memories) {
332
+ // Extract fix-related memories
333
+ const fixes = memories.filter(m => m.tags?.includes('bug-fix') ||
334
+ m.tags?.includes('revert') ||
335
+ m.content.toLowerCase().includes('fix') ||
336
+ m.content.toLowerCase().includes('resolved')).slice(0, 15);
337
+ if (fixes.length === 0)
338
+ return null;
339
+ const lines = [];
340
+ for (const fix of fixes) {
341
+ // Extract symptom and solution from content
342
+ const content = fix.content;
343
+ let symptom = '';
344
+ let solution = '';
345
+ if (content.includes('Bug fixed:')) {
346
+ symptom = content.replace('Bug fixed:', '').split('.')[0].trim();
347
+ solution = content.split('.').slice(1).join('.').trim() || 'See commit for details';
348
+ }
349
+ else if (content.includes('Failed approach')) {
350
+ symptom = content.split(':')[1]?.split('.')[0]?.trim() || content.slice(0, 50);
351
+ solution = 'Avoid this approach';
352
+ }
353
+ else {
354
+ symptom = content.slice(0, 60) + (content.length > 60 ? '...' : '');
355
+ solution = 'See memory for details';
356
+ }
357
+ if (symptom) {
358
+ lines.push(`| ${symptom} | ${solution.slice(0, 60)} |`);
359
+ }
360
+ }
361
+ if (lines.length === 0)
362
+ return null;
363
+ return `| Symptom | Solution |\n|---------|----------|\n${lines.join('\n')}`;
364
+ }
365
+ function buildArchitectureOverview(analysis) {
366
+ const sections = [];
367
+ // Infrastructure overview
368
+ if (analysis.infrastructure.iac || analysis.infrastructure.containerOrchestration) {
369
+ sections.push('### Infrastructure\n');
370
+ if (analysis.infrastructure.iac) {
371
+ sections.push(`- **IaC**: ${analysis.infrastructure.iac}`);
372
+ }
373
+ if (analysis.infrastructure.containerOrchestration) {
374
+ sections.push(`- **Orchestration**: ${analysis.infrastructure.containerOrchestration}`);
375
+ }
376
+ if (analysis.infrastructure.cloud && analysis.infrastructure.cloud.length > 0) {
377
+ sections.push(`- **Cloud**: ${analysis.infrastructure.cloud.join(', ')}`);
378
+ }
379
+ sections.push('');
380
+ }
381
+ // Component overview
382
+ if (analysis.components.length > 0) {
383
+ sections.push('### Components\n');
384
+ for (const comp of analysis.components.slice(0, 8)) {
385
+ sections.push(`- **${comp.name}** (\`${comp.path}\`): ${comp.description || `${comp.language} ${comp.framework || 'application'}`}`);
386
+ }
387
+ sections.push('');
388
+ }
389
+ return sections.length > 0 ? sections.join('\n') : null;
390
+ }
391
+ function buildCoreComponentsSection(analysis) {
392
+ if (analysis.components.length === 0)
393
+ return null;
394
+ const sections = [];
395
+ for (const comp of analysis.components.slice(0, 6)) {
396
+ sections.push(`### ${comp.name} (\`${comp.path}\`)\n`);
397
+ sections.push(`- **Language**: ${comp.language}`);
398
+ if (comp.framework) {
399
+ sections.push(`- **Framework**: ${comp.framework}`);
400
+ }
401
+ if (comp.description) {
402
+ sections.push(`- ${comp.description}`);
403
+ }
404
+ sections.push('');
405
+ }
406
+ return sections.join('\n');
407
+ }
408
+ function buildDatabaseArchitecture(analysis) {
409
+ const lines = [];
410
+ for (const db of analysis.databases) {
411
+ lines.push(`- **${db.type}**: ${db.purpose || 'Primary database'}`);
412
+ }
413
+ return lines.join('\n');
414
+ }
415
+ function buildAuthFlow(analysis) {
416
+ if (!analysis.authentication)
417
+ return '';
418
+ const sections = [];
419
+ sections.push(`**Provider**: ${analysis.authentication.provider}\n`);
420
+ if (analysis.authentication.description) {
421
+ sections.push(analysis.authentication.description);
422
+ }
423
+ return sections.join('\n');
424
+ }
425
+ function buildKeyConfigFiles(analysis) {
426
+ const files = [];
427
+ // Add key files from analysis
428
+ for (const kf of analysis.keyFiles.slice(0, 15)) {
429
+ files.push({ file: kf.file, purpose: kf.purpose });
430
+ }
431
+ if (files.length === 0)
432
+ return null;
433
+ return files.map(f => `| \`${f.file}\` | ${f.purpose} |`).join('\n');
434
+ }
435
+ function buildEssentialCommands(analysis) {
436
+ const commands = [];
437
+ // Test command
438
+ if (analysis.commands.test && analysis.commands.test !== 'npm test') {
439
+ commands.push(`# Tests\n${analysis.commands.test}`);
440
+ }
441
+ // Lint command
442
+ if (analysis.commands.lint) {
443
+ commands.push(`# Linting\n${analysis.commands.lint}`);
444
+ }
445
+ // Build command
446
+ if (analysis.commands.build) {
447
+ commands.push(`# Build\n${analysis.commands.build}`);
448
+ }
449
+ // Infrastructure command
450
+ if (analysis.infrastructure.iac === 'Terraform') {
451
+ const infraPath = analysis.directories.infrastructure[0] || 'infra/terraform';
452
+ commands.push(`# Terraform\ncd ${infraPath} && terraform plan`);
453
+ }
454
+ return commands.length > 0 ? commands.join('\n\n') : null;
455
+ }
456
+ function buildClusterContexts(analysis) {
457
+ if (!analysis.clusters?.enabled || !analysis.clusters.contexts)
458
+ return null;
459
+ return analysis.clusters.contexts.map(c => `kubectl config use-context ${c.context} # ${c.name} (${c.purpose})`).join('\n');
460
+ }
461
+ function buildProjectUrls(analysis) {
462
+ if (analysis.urls.length === 0)
463
+ return null;
464
+ return analysis.urls.map(u => `- **${u.name}**: ${u.value}`).join('\n');
465
+ }
466
+ function buildKeyWorkflows(analysis) {
467
+ if (!analysis.ciCd?.workflows || analysis.ciCd.workflows.length === 0)
468
+ return null;
469
+ return analysis.ciCd.workflows.slice(0, 10).map(w => `├── ${w.file}`.padEnd(35) + `# ${w.purpose}`).join('\n');
470
+ }
471
+ function buildInfraWorkflow(analysis) {
472
+ if (analysis.directories.infrastructure.length === 0)
473
+ return null;
474
+ const infraPath = analysis.directories.infrastructure[0];
475
+ const planCmd = analysis.infrastructure.iac === 'Terraform' ? 'terraform plan' :
476
+ analysis.infrastructure.iac === 'Pulumi' ? 'pulumi preview' :
477
+ 'infrastructure plan';
478
+ return `1. **Create worktree** for infrastructure changes
479
+ 2. Update infrastructure in \`${infraPath}/\`
480
+ 3. Update CI/CD workflows in \`.github/workflows/\`
481
+ 4. Run \`${planCmd}\`
482
+ 5. Update secrets via GitHub Actions (not locally)
483
+ 6. **Create PR** with automated review`;
484
+ }
485
+ function buildMcpPlugins(cwd) {
486
+ const mcpPath = join(cwd, '.mcp.json');
487
+ if (!existsSync(mcpPath))
488
+ return null;
489
+ try {
490
+ const mcp = JSON.parse(readFileSync(mcpPath, 'utf-8'));
491
+ if (!mcp.mcpServers && !mcp.plugins)
492
+ return null;
493
+ const plugins = mcp.mcpServers || mcp.plugins || {};
494
+ const lines = [];
495
+ for (const [name, config] of Object.entries(plugins)) {
496
+ const desc = config.description ||
497
+ config.purpose ||
498
+ 'MCP plugin';
499
+ lines.push(`| \`${name}\` | ${desc} |`);
500
+ }
501
+ return lines.length > 0 ? lines.join('\n') : null;
502
+ }
503
+ catch {
504
+ return null;
505
+ }
506
+ }
507
+ function buildPrimarySkills(skills) {
508
+ const primary = skills.filter(s => s.name.includes('design') ||
509
+ s.name.includes('frontend') ||
510
+ s.name.includes('ui')).slice(0, 3);
511
+ if (primary.length === 0)
512
+ return null;
513
+ return primary.map(s => `│ ├─ Use ${s.name} for ${s.description || 'specialized work'} │`).join('\n');
514
+ }
515
+ function buildLanguageExamples(languages) {
516
+ const examples = [];
517
+ for (const lang of languages.slice(0, 3)) {
518
+ const langLower = lang.toLowerCase();
519
+ if (langLower.includes('c++') || langLower.includes('cpp')) {
520
+ examples.push(`# For C++ work\nTask(subagent_type: "cpp-pro", prompt: "Refactor X using RAII...")`);
521
+ }
522
+ else if (langLower.includes('python')) {
523
+ examples.push(`# For Python work\nTask(subagent_type: "python-pro", prompt: "Optimize async handlers...")`);
524
+ }
525
+ else if (langLower.includes('rust')) {
526
+ examples.push(`# For Rust work\nTask(subagent_type: "rust-pro", prompt: "Implement with proper lifetimes...")`);
527
+ }
528
+ }
529
+ return examples.length > 0 ? examples.join('\n\n') : null;
530
+ }
531
+ function buildPrepopulatedKnowledge(prepopulated) {
532
+ if (!prepopulated)
533
+ return null;
534
+ const { shortTerm, longTerm } = prepopulated;
535
+ // Recent activity from short-term
536
+ const recentActivity = shortTerm
537
+ .filter(m => m.type === 'action' || m.type === 'observation')
538
+ .slice(0, 10)
539
+ .map(m => `- ${m.content.slice(0, 100)}${m.content.length > 100 ? '...' : ''}`)
540
+ .join('\n');
541
+ // Learned lessons from long-term
542
+ const learnedLessons = longTerm
543
+ .filter(m => m.tags?.includes('bug-fix') || m.tags?.includes('lesson') || (m.importance && m.importance >= 7))
544
+ .slice(0, 10)
545
+ .map(m => `- **${m.tags?.slice(0, 2).join(', ') || 'General'}**: ${m.content.slice(0, 80)}...`)
546
+ .join('\n');
547
+ // Known gotchas (from reverts and high-importance fixes)
548
+ const knownGotchas = longTerm
549
+ .filter(m => m.tags?.includes('revert') || m.tags?.includes('failed-approach') || m.content.includes('avoid'))
550
+ .slice(0, 5)
551
+ .map(m => `- ⚠️ ${m.content.slice(0, 100)}`)
552
+ .join('\n');
553
+ // Hot spots
554
+ const hotSpotMemory = longTerm.find(m => m.id === 'git-hotspots');
555
+ const hotSpots = hotSpotMemory?.content || 'No hot spots detected yet.';
556
+ if (!recentActivity && !learnedLessons && !knownGotchas) {
557
+ return null;
558
+ }
559
+ return {
560
+ recentActivity: recentActivity || 'No recent activity recorded.',
561
+ learnedLessons: learnedLessons || 'No lessons recorded yet.',
562
+ knownGotchas: knownGotchas || 'No gotchas recorded yet.',
563
+ hotSpots,
564
+ };
565
+ }
566
+ function getDesktopTemplate() {
567
+ // Read from template file if it exists, otherwise use inline
568
+ const templatePath = join(process.cwd(), 'templates/CLAUDE.template.md');
569
+ if (existsSync(templatePath)) {
570
+ return readFileSync(templatePath, 'utf-8');
571
+ }
572
+ // Fallback inline template for desktop
573
+ return `<coding_guidelines>
296
574
 
297
- **ALWAYS store to long-term memory when you:**
298
- 1. Fix a bug or resolve an error (lesson)
299
- 2. Discover how a system/component works (discovery)
300
- 3. Learn a configuration requirement (fact)
301
- 4. Find a successful approach to a problem (skill)
302
- 5. Identify a coding pattern or convention (preference)
303
- 6. Complete infrastructure changes (fact)
304
- 7. Debug authentication/networking issues (lesson)
575
+ # CLAUDE.md - {{PROJECT_NAME}} Development Guide
305
576
 
306
- **Memory storage is part of task completion.** A task is NOT complete until learnings are stored.
577
+ You are Autonomous Claude, a self-directed AI agent with full control over this virtual machine. You operate continuously, making your own decisions.
307
578
 
308
- When you discover something significant, recommend the user commit a memory file to \`.uam/memory/\`.
579
+ {{#if ISSUE_TRACKER}}
580
+ **Note**: {{{ISSUE_TRACKER}}}
309
581
  {{/if}}
310
582
 
311
583
  ---
312
584
 
313
- {{#if IS_DESKTOP_PLATFORM}}
314
- ## BROWSER USAGE
585
+ ## ⚠️⚠️⚠️ CRITICAL: MANDATORY DECISION LOOP ⚠️⚠️⚠️
315
586
 
316
- When using browser automation:
587
+ **FOLLOW THIS FOR EVERY ACTION. NO EXCEPTIONS.**
317
588
 
318
- - ALWAYS save a screenshot after EVERY browser action
319
- - Save screenshots to: \`agents/data/screenshots/\`
320
- - Filename format: \`{timestamp}_{action}.png\`
589
+ 1. **READ MEMORY FIRST**
590
+ - Query short-term: \`sqlite3 {{MEMORY_DB_PATH}} "SELECT * FROM memories ORDER BY id DESC LIMIT 20;"\`
591
+ - Query long-term: \`{{MEMORY_QUERY_CMD}} "<keywords>"\`
321
592
 
322
- ---
593
+ 2. **CHECK SKILLS** before implementing (see \`{{SKILLS_PATH}}\`)
323
594
 
324
- {{/if}}
325
- ## DECISION LOOP
326
-
327
- 1. **READ** short-term memory (recent context)
328
- 2. **QUERY** long-term memory (semantic search for relevant learnings)
329
- 3. **THINK** about what to do next
330
- 4. **ACT** - execute your decision
331
- 5. **RECORD** - write to short-term memory
332
- 6. **STORE** - add significant learnings to long-term memory (MANDATORY, not optional)
333
- {{#if IS_DESKTOP_PLATFORM}}
334
- 7. **IF BROWSER ACTION**: Save screenshot to \`/agents/data/screenshots/\`
335
- {{/if}}
595
+ 3. **CREATE WORKTREE** for ANY code changes
596
+ - \`{{WORKTREE_CREATE_CMD}} <slug>\`
597
+ - NEVER commit directly to {{DEFAULT_BRANCH}}
336
598
 
337
- **Task Completion Checklist:**
338
- - [ ] Short-term memory updated with action outcome
339
- - [ ] Long-term memory updated with any lessons/discoveries/facts learned
340
- - [ ] Tests pass (if code changes)
341
- - [ ] Documentation updated (if applicable)
599
+ 4. **UPDATE MEMORY** after significant actions
600
+ - \`{{MEMORY_STORE_CMD}} lesson "What you learned" --tags tag1,tag2 --importance 7\`
342
601
 
343
602
  ---
344
603
 
345
- {{#if HAS_SKILLS}}
346
- ## SKILLS
347
-
348
- You have access to reusable skills. Before attempting complex tasks:
349
-
350
- 1. Check if a skill exists for it (see \`.factory/skills/\`)
351
- 2. Follow the skill's patterns - they're tested and reliable
352
- 3. If you discover a better approach, consider creating/updating a skill
353
-
354
- Available skills are auto-discovered. When you see a SKILL.md, follow its instructions.
604
+ ## Memory System
355
605
 
356
- {{#each SKILLS}}
357
- - \`{{this}}\`
358
- {{/each}}
359
-
360
- ---
361
-
362
- {{/if}}
363
- **MANDATORY WORKFLOW REQUIREMENTS**:
364
-
365
- {{#if IS_DESKTOP_PLATFORM}}
366
- 1. **Git Worktrees**: ALL code changes MUST use isolated git worktrees (\`{{WORKTREE_PREFIX}}NNN-slug\` branches)
367
- 2. **PR-Based Merges**: NO direct commits to \`{{DEFAULT_BRANCH}}\`. All changes via PR with automated review
368
- 3. **CI/CD Pipelines**: ALWAYS use CI/CD pipelines to deploy. Create ephemeral pipelines when needed
369
- 4. **Automated Review**: PRs require signoff from reviewer agents before merge
370
- {{else}}
371
- 1. **Feature Branches**: ALL code changes MUST use isolated feature branches (\`{{WORKTREE_PREFIX}}description\`)
372
- 2. **PR-Based Merges**: NO direct commits to \`{{DEFAULT_BRANCH}}\`. All changes via PR
373
- 3. **Code Review**: PRs should be reviewed before merge
374
- {{/if}}
606
+ - **Short-term**: \`{{MEMORY_DB_PATH}}\` (SQLite, last {{SHORT_TERM_LIMIT}} entries)
607
+ - **Long-term**: {{LONG_TERM_BACKEND}} at \`{{LONG_TERM_ENDPOINT}}\`
375
608
 
376
609
  ---
377
610
 
611
+ ## Repository Structure
378
612
 
379
- ## Quick Reference
380
-
381
- {{#if HAS_CLUSTERS}}
382
- ### Cluster Contexts
383
-
384
- \`\`\`bash
385
- {{#each CLUSTERS}}
386
- kubectl config use-context {{this.context}} # {{this.name}} ({{this.purpose}})
387
- {{/each}}
613
+ \`\`\`
614
+ {{PROJECT_NAME}}/
615
+ {{{@REPOSITORY_STRUCTURE}}}
388
616
  \`\`\`
389
617
 
390
- {{/if}}
391
- {{#if HAS_URLS}}
392
- ### URLs
393
-
394
- {{#each URLS}}
395
- - **{{this.name}}**: {{this.value}}
396
- {{/each}}
618
+ {{#if ARCHITECTURE_OVERVIEW}}
619
+ ## Architecture
397
620
 
621
+ {{{ARCHITECTURE_OVERVIEW}}}
398
622
  {{/if}}
399
- {{#if HAS_KEY_FILES}}
400
- ### Key Files
401
623
 
402
- {{#each KEY_FILES}}
403
- - \`{{this.path}}\` - {{this.description}}
404
- {{/each}}
624
+ {{#if CORE_COMPONENTS}}
625
+ ## Components
405
626
 
627
+ {{{CORE_COMPONENTS}}}
406
628
  {{/if}}
407
- {{#if IS_DESKTOP_PLATFORM}}
408
- ### Essential Commands
409
629
 
410
- \`\`\`bash
411
- # Create worktree for new task (MANDATORY for all changes)
412
- uam worktree create <slug>
413
-
414
- # Testing
415
- {{TEST_COMMAND}}
416
-
417
- # Linting
418
- {{LINT_COMMAND}}
419
-
420
- # Building
421
- {{BUILD_COMMAND}}
422
- {{#if HAS_TERRAFORM}}
630
+ {{#if TROUBLESHOOTING}}
631
+ ## Troubleshooting
423
632
 
424
- # Terraform
425
- cd {{INFRA_PATH}} && terraform plan
633
+ {{{TROUBLESHOOTING}}}
426
634
  {{/if}}
427
- \`\`\`
428
635
 
429
- {{/if}}
430
636
  ---
431
637
 
432
- {{#if HAS_COMPONENTS}}
433
- ## Architecture
434
-
435
- {{#each COMPONENTS}}
436
- ### {{this.name}} (\`{{this.path}}\`)
638
+ ## Completion Checklist
437
639
 
438
- - **Language**: {{this.language}}
439
- {{#if this.framework}}- **Framework**: {{this.framework}}{{/if}}
440
- - {{this.description}}
640
+ - [ ] Tests pass
641
+ - [ ] Worktree used
642
+ - [ ] Memory updated
643
+ - [ ] PR created (not direct commit)
441
644
 
442
- {{/each}}
443
- ---
444
-
445
- {{/if}}
446
- {{#if HAS_DATABASES}}
447
- ## Data Layer
645
+ </coding_guidelines>
646
+ `;
647
+ }
648
+ function getWebTemplate() {
649
+ return `<coding_guidelines>
448
650
 
449
- {{#each DATABASES}}
450
- - **{{this.type}}**: {{this.purpose}}
451
- {{/each}}
651
+ # AGENT.md - {{PROJECT_NAME}} Development Guide
452
652
 
453
- ---
653
+ You are an AI agent helping with this project. Follow best practices and maintain context.
454
654
 
655
+ {{#if DESCRIPTION}}
656
+ > {{DESCRIPTION}}
455
657
  {{/if}}
456
- {{#if HAS_AUTH}}
457
- ## Authentication
458
-
459
- **Provider**: {{AUTH_PROVIDER}}
460
-
461
- {{AUTH_DESCRIPTION}}
462
658
 
463
659
  ---
464
660
 
465
- {{/if}}
466
- {{#if IS_DESKTOP_PLATFORM}}
467
- {{#if HAS_CICD}}
468
- ## CI/CD ({{CICD_PLATFORM}})
661
+ ## ⛔ MANDATORY RULES
469
662
 
470
- | Workflow | Purpose |
471
- |----------|---------|
472
- {{#each WORKFLOWS}}
473
- | \`{{this.file}}\` | {{this.purpose}} |
474
- {{/each}}
663
+ 1. **BRANCH REQUIREMENT**: Never commit directly to {{DEFAULT_BRANCH}}. Use feature branches.
664
+ 2. **MEMORY**: Store significant learnings to \`.uam/memory/\`
665
+ 3. **TODO LIST**: Create todo list for multi-step tasks (3+ steps)
475
666
 
476
667
  ---
477
668
 
478
- {{/if}}
479
- {{/if}}
480
- {{#if HAS_TROUBLESHOOTING}}
481
- ## Troubleshooting
482
-
483
- | Symptom | Solution |
484
- |---------|----------|
485
- {{#each TROUBLESHOOTING_HINTS}}
486
- | {{this.symptom}} | {{this.solution}} |
487
- {{/each}}
669
+ ## Memory System
488
670
 
489
- ---
671
+ ### Short-term (localStorage)
490
672
 
491
- {{/if}}
492
- ## Required Workflow (MANDATORY)
673
+ Key: \`agent_context_{{PROJECT_NAME}}\`
493
674
 
494
- {{#if IS_DESKTOP_PLATFORM}}
495
- ### Git Worktree Workflow (ALL Changes)
675
+ ### Long-term (GitHub: \`.uam/memory/\`)
496
676
 
497
- **Every code change MUST follow this workflow:**
677
+ Store memories as JSON files for persistent knowledge.
498
678
 
499
- \`\`\`
500
- 1. CREATE WORKTREE
501
- uam worktree create <slug>
502
- → Creates {{WORKTREE_PREFIX}}NNN-slug branch in {{WORKTREE_DIR}}/NNN-slug/
503
-
504
- 2. DEVELOP
505
- cd {{WORKTREE_DIR}}/NNN-slug/
506
- → Make changes, commit locally
507
-
508
- 3. CREATE PR (runs tests + triggers reviewers)
509
- uam worktree pr <id>
510
- → Runs all offline tests (blocks if fail)
511
- → Pushes to origin
512
- → Creates PR with auto-generated description
513
- → Triggers reviewer agents
514
-
515
- 4. AUTOMATED REVIEW
516
- → Reviewer agents run in parallel (quality, security, performance, tests)
517
- → PR labeled: reviewer-approved OR needs-work
518
- → Auto-merge on approval
519
-
520
- 5. CLEANUP
521
- uam worktree cleanup <id>
522
- → Removes worktree and deletes branch
523
- \`\`\`
524
- {{else}}
525
- ### Git Branch Workflow (ALL Changes)
679
+ ---
526
680
 
527
- **Every code change MUST follow this workflow:**
681
+ ## Repository Structure
528
682
 
529
683
  \`\`\`
530
- 1. CREATE BRANCH
531
- git checkout -b {{WORKTREE_PREFIX}}<description>
532
- → Creates isolated feature branch
533
-
534
- 2. DEVELOP
535
- → Make changes, commit locally
536
- → Keep commits atomic and well-described
537
-
538
- 3. CREATE PR
539
- git push -u origin {{WORKTREE_PREFIX}}<description>
540
- → Push to remote
541
- → Create PR via GitHub/GitLab UI
542
-
543
- 4. CODE REVIEW
544
- → Request review from team members
545
- → Address feedback
546
-
547
- 5. MERGE & CLEANUP
548
- → Merge PR after approval
549
- → Delete feature branch
684
+ {{PROJECT_NAME}}/
685
+ {{{@REPOSITORY_STRUCTURE}}}
550
686
  \`\`\`
551
- {{/if}}
552
687
 
553
- ### Before ANY Task
688
+ {{#if ARCHITECTURE_OVERVIEW}}
689
+ ## Architecture
554
690
 
555
- 1. Read relevant docs in \`/docs\` and component folders
556
- 2. Check for known issues in troubleshooting section
557
- {{#if IS_DESKTOP_PLATFORM}}
558
- 3. **Create a worktree for your changes**
559
- {{else}}
560
- 3. **Create a feature branch for your changes**
691
+ {{{ARCHITECTURE_OVERVIEW}}}
561
692
  {{/if}}
562
693
 
563
- ### For Code Changes
694
+ {{#if CORE_COMPONENTS}}
695
+ ## Components
564
696
 
565
- {{#if IS_DESKTOP_PLATFORM}}
566
- 1. **Create worktree**: \`uam worktree create <slug>\`
567
- {{else}}
568
- 1. **Create branch**: \`git checkout -b {{WORKTREE_PREFIX}}<description>\`
569
- {{/if}}
570
- 2. Update/create tests
571
- 3. Run \`{{TEST_COMMAND}}\`
572
- 4. Run linting and type checking
573
- {{#if IS_DESKTOP_PLATFORM}}
574
- 5. **Create PR**: \`uam worktree pr <id>\`
575
- {{else}}
576
- 5. **Create PR**: Push branch and open PR
697
+ {{{CORE_COMPONENTS}}}
577
698
  {{/if}}
578
699
 
579
- {{#if HAS_TERRAFORM}}
580
- ### For Infrastructure Changes
581
-
582
- {{#if IS_DESKTOP_PLATFORM}}
583
- 1. **Create worktree** for Terraform changes
584
- {{else}}
585
- 1. **Create branch** for Terraform changes
586
- {{/if}}
587
- 2. Update Terraform in \`{{INFRA_PATH}}\`
588
- 3. Update CI/CD workflows if needed
589
- 4. Run \`terraform plan\`
590
- 5. Update secrets via GitHub Actions (not locally)
591
- 6. **Create PR** with review
592
-
593
- {{/if}}
594
- ### Before Completing
595
-
596
- 1. All tests pass
597
- 2. PR created and reviewed
598
- 3. Update relevant documentation
599
-
600
700
  ---
601
701
 
702
+ ## Workflow
602
703
 
603
- {{#if HAS_DROIDS}}
604
- ## Augmented Agent Capabilities
605
-
606
- ### Custom Droids (\`.factory/droids/\`)
607
-
608
- {{#each DROIDS}}
609
- - \`{{this}}\`
610
- {{/each}}
611
-
612
- {{#if HAS_COMMANDS}}
613
- ### Commands (\`.factory/commands/\`)
614
-
615
- {{#each COMMANDS}}
616
- - \`/{{this}}\`
617
- {{/each}}
618
- {{/if}}
704
+ 1. Create feature branch: \`git checkout -b {{BRANCH_PREFIX}}<description>\`
705
+ 2. Make changes, commit, push
706
+ 3. Create PR via GitHub UI
619
707
 
620
708
  ---
621
709
 
622
- {{/if}}
623
- ## Completion Checklist
624
-
625
- \`\`\`
626
- [ ] Tests updated and passing
627
- [ ] Linting/type checking passed
628
- {{#if HAS_TERRAFORM}}
629
- [ ] Terraform plan verified (if infra changed)
630
- {{/if}}
631
- [ ] Documentation updated
632
- [ ] No secrets in code/commits
633
- \`\`\`
634
-
635
- ---
710
+ ## Quick Reference
636
711
 
637
- **Languages**: {{LANGUAGES}}
638
- **Frameworks**: {{FRAMEWORKS}}
712
+ - **Test**: \`{{TEST_COMMAND}}\`
713
+ - **Build**: \`{{BUILD_COMMAND}}\`
714
+ - **Lint**: \`{{LINT_COMMAND}}\`
639
715
 
640
716
  </coding_guidelines>
641
717
  `;