almost working installer updates

This commit is contained in:
Brian Madison 2025-12-07 15:38:49 -06:00
parent 38e65abd83
commit baaa984a90
9 changed files with 222 additions and 41 deletions

View File

@ -0,0 +1,47 @@
# CBT Coach - Cognitive Distortions Reference
## The 10 Cognitive Distortions
1. **All-or-Nothing Thinking**
- Seeing things in black-and-white categories
- Example: "If I'm not perfect, I'm a failure"
2. **Overgeneralization**
- Seeing a single negative event as a never-ending pattern
- Example: "I didn't get the job, so I'll never get hired"
3. **Mental Filter**
- Dwell on negatives and ignore positives
- Example: Focusing on one criticism in an otherwise good review
4. **Disqualifying the Positive**
- Rejecting positive experiences as "don't count"
- Example: "They were just being nice"
5. **Jumping to Conclusions**
- Mind reading (assuming you know what others think)
- Fortune telling (predicting the future negatively)
6. **Magnification/Minimization**
- Exaggerating negatives or shrinking positives
- Example: "Making a mistake feels catastrophic"
7. **Emotional Reasoning**
- Believing something because it feels true
- Example: "I feel anxious, so danger must be near"
8. **"Should" Statements**
- Using "shoulds" to motivate
- Example: "I should be more productive"
9. **Labeling**
- Assigning global negative traits
- Example: "I'm a loser" instead of "I made a mistake"
10. **Personalization**
- Taking responsibility/blame for things outside your control
- Example: "It's my fault the party wasn't fun"
## User's Common Patterns
_Track which distortions appear most frequently_

View File

@ -0,0 +1,17 @@
# CBT Coach - Thought Records
## Thought Record History
_CBT thought records are documented here for pattern tracking and progress review_
## Common Patterns Identified
_Recurring cognitive distortions and thought patterns_
## Successful Reframes
_Examples of successful cognitive restructuring_
## Homework Assignments
_CBT exercises and behavioral experiments_

View File

@ -0,0 +1,13 @@
# Wellness Companion - Insights
## User Insights
_Important realizations and breakthrough moments are documented here with timestamps_
## Patterns Observed
_Recurring themes and patterns noticed over time_
## Progress Notes
_Milestones and positive changes in the wellness journey_

View File

@ -0,0 +1,30 @@
# Wellness Companion - Instructions
## Safety Protocols
1. Always validate user feelings before offering guidance
2. Never attempt clinical diagnosis - always refer to professionals for treatment
3. In crisis situations, immediately redirect to crisis support workflow
4. Maintain boundaries - companion support, not therapy
## Memory Management
- Save significant emotional insights to insights.md
- Track recurring patterns in patterns.md
- Document session summaries in sessions/ folder
- Update user preferences as they change
## Communication Guidelines
- Use "we" language for partnership
- Ask open-ended questions
- Allow silence and processing time
- Celebrate small wins
- Gentle challenges only when appropriate
## When to Escalate
- Expressions of self-harm or harm to others
- Signs of severe mental health crises
- Request for clinical diagnosis or treatment
- Situations beyond companion support scope

View File

@ -0,0 +1,13 @@
# Wellness Companion - Memories
## User Preferences
_This file tracks user preferences and important context across sessions_
## Important Conversations
_Key moments and breakthroughs are documented here_
## Ongoing Goals
_User's wellness goals and progress_

View File

@ -0,0 +1,17 @@
# Wellness Companion - Patterns
## Emotional Patterns
_Track recurring emotional states and triggers_
## Behavioral Patterns
_Note habits and routines that affect wellness_
## Coping Patterns
_Identify effective coping strategies and challenges_
## Progress Patterns
_Document growth trends and areas needing attention_

View File

@ -275,10 +275,9 @@ class Detector {
hasV6Installation = true; hasV6Installation = true;
// Don't break - continue scanning to be thorough // Don't break - continue scanning to be thorough
} else { } else {
// Not V6+, check if folder name contains "bmad" (case insensitive) // Not V6+, check if this is the exact V4 folder name "bmad-method"
const nameLower = name.toLowerCase(); if (name === 'bmad-method') {
if (nameLower.includes('bmad')) { // This is the V4 default folder - flag it as legacy
// Potential V4 legacy folder
potentialV4Folders.push(fullPath); potentialV4Folders.push(fullPath);
} }
} }

View File

@ -22,11 +22,12 @@ const { getProjectRoot, getSourcePath, getModulePath } = require('../../../lib/p
* await manager.install('core-module', '/path/to/bmad'); * await manager.install('core-module', '/path/to/bmad');
*/ */
class ModuleManager { class ModuleManager {
constructor() { constructor(options = {}) {
// Path to source modules directory // Path to source modules directory
this.modulesSourcePath = getSourcePath('modules'); this.modulesSourcePath = getSourcePath('modules');
this.xmlHandler = new XmlHandler(); this.xmlHandler = new XmlHandler();
this.bmadFolderName = 'bmad'; // Default, can be overridden this.bmadFolderName = 'bmad'; // Default, can be overridden
this.scanProjectForModules = options.scanProjectForModules !== false; // Default to true for backward compatibility
} }
/** /**
@ -175,10 +176,11 @@ class ModuleManager {
/** /**
* List all available modules (excluding core which is always installed) * List all available modules (excluding core which is always installed)
* @returns {Array} List of available modules with metadata * @returns {Object} Object with modules array and customModules array
*/ */
async listAvailable() { async listAvailable() {
const modules = []; const modules = [];
const customModules = [];
// First, scan src/modules (the standard location) // First, scan src/modules (the standard location)
if (await fs.pathExists(this.modulesSourcePath)) { if (await fs.pathExists(this.modulesSourcePath)) {
@ -209,25 +211,31 @@ class ModuleManager {
} }
} }
// Then, find all other modules in the project // Then, find all other modules in the project (only if scanning is enabled)
const otherModulePaths = await this.findModulesInProject(); if (this.scanProjectForModules) {
for (const modulePath of otherModulePaths) { const otherModulePaths = await this.findModulesInProject();
const moduleName = path.basename(modulePath); for (const modulePath of otherModulePaths) {
const relativePath = path.relative(getProjectRoot(), modulePath); const moduleName = path.basename(modulePath);
const relativePath = path.relative(getProjectRoot(), modulePath);
// Skip core module - it's always installed first and not selectable // Skip core module - it's always installed first and not selectable
if (moduleName === 'core') { if (moduleName === 'core') {
continue; continue;
} }
const moduleInfo = await this.getModuleInfo(modulePath, moduleName, relativePath); const moduleInfo = await this.getModuleInfo(modulePath, moduleName, relativePath);
if (moduleInfo && !modules.some((m) => m.id === moduleInfo.id)) { if (moduleInfo && !modules.some((m) => m.id === moduleInfo.id) && !customModules.some((m) => m.id === moduleInfo.id)) {
// Avoid duplicates - skip if we already have this module ID // Avoid duplicates - skip if we already have this module ID
modules.push(moduleInfo); if (moduleInfo.isCustom) {
customModules.push(moduleInfo);
} else {
modules.push(moduleInfo);
}
}
} }
} }
return modules; return { modules, customModules };
} }
/** /**

View File

@ -52,9 +52,6 @@ class UI {
await installer.handleLegacyV4Migration(confirmedDirectory, legacyV4); await installer.handleLegacyV4Migration(confirmedDirectory, legacyV4);
} }
// Prompt for custom content location (separate from installation directory)
const customContentConfig = await this.promptCustomContentLocation();
// Check if there's an existing BMAD installation // Check if there's an existing BMAD installation
const fs = require('fs-extra'); const fs = require('fs-extra');
const path = require('node:path'); const path = require('node:path');
@ -62,6 +59,13 @@ class UI {
const bmadDir = await installer.findBmadDir(confirmedDirectory); const bmadDir = await installer.findBmadDir(confirmedDirectory);
const hasExistingInstall = await fs.pathExists(bmadDir); const hasExistingInstall = await fs.pathExists(bmadDir);
// Only ask for custom content if it's a NEW installation
let customContentConfig = { hasCustomContent: false };
if (!hasExistingInstall) {
// Prompt for custom content location (separate from installation directory)
customContentConfig = await this.promptCustomContentLocation();
}
// Track action type (only set if there's an existing installation) // Track action type (only set if there's an existing installation)
let actionType; let actionType;
@ -88,12 +92,11 @@ class UI {
// Handle quick update separately // Handle quick update separately
if (actionType === 'quick-update') { if (actionType === 'quick-update') {
// Even for quick update, ask about custom content // Quick update doesn't install custom content - just updates existing modules
const customContentConfig = await this.promptCustomContentLocation();
return { return {
actionType: 'quick-update', actionType: 'quick-update',
directory: confirmedDirectory, directory: confirmedDirectory,
customContent: customContentConfig, customContent: { hasCustomContent: false },
}; };
} }
@ -511,11 +514,11 @@ class UI {
const moduleChoices = []; const moduleChoices = [];
const isNewInstallation = installedModuleIds.size === 0; const isNewInstallation = installedModuleIds.size === 0;
// Add custom content items first if found const customContentItems = [];
if (customContentConfig && customContentConfig.hasCustomContent && customContentConfig.customPath) { const hasCustomContentItems = false;
// Add separator before custom content
moduleChoices.push(new inquirer.Separator('── Custom Content ──'));
// Add custom content items from directory
if (customContentConfig && customContentConfig.hasCustomContent && customContentConfig.customPath) {
// Get the custom content info to display proper names // Get the custom content info to display proper names
const { CustomHandler } = require('../installers/lib/custom/handler'); const { CustomHandler } = require('../installers/lib/custom/handler');
const customHandler = new CustomHandler(); const customHandler = new CustomHandler();
@ -524,29 +527,63 @@ class UI {
for (const customFile of customFiles) { for (const customFile of customFiles) {
const customInfo = await customHandler.getCustomInfo(customFile); const customInfo = await customHandler.getCustomInfo(customFile);
if (customInfo) { if (customInfo) {
moduleChoices.push({ customContentItems.push({
name: `${chalk.cyan('✓')} ${customInfo.name} ${chalk.gray(`(${customInfo.relativePath})`)}`, name: `${chalk.cyan('✓')} ${customInfo.name} ${chalk.gray(`(${customInfo.relativePath})`)}`,
value: `__CUSTOM_CONTENT__${customFile}`, // Unique value for each custom content value: `__CUSTOM_CONTENT__${customFile}`, // Unique value for each custom content
checked: true, // Default to selected since user chose to provide custom content checked: true, // Default to selected since user chose to provide custom content
path: customInfo.path, // Track path to avoid duplicates
}); });
} }
} }
// Add separator for official content
moduleChoices.push(new inquirer.Separator('── Official Content ──'));
} }
// Add official modules // Add official modules
const { ModuleManager } = require('../installers/lib/modules/manager'); const { ModuleManager } = require('../installers/lib/modules/manager');
const moduleManager = new ModuleManager(); // Only scan project for modules if user selected custom content
const availableModules = await moduleManager.listAvailable(); const moduleManager = new ModuleManager({
scanProjectForModules: customContentConfig && customContentConfig.hasCustomContent && customContentConfig.selected,
});
const { modules: availableModules, customModules: customModulesFromProject } = await moduleManager.listAvailable();
// First, add all items to appropriate sections
const allCustomModules = [];
// Add custom content items from directory
allCustomModules.push(...customContentItems);
// Add custom modules from project scan (if scanning is enabled)
for (const mod of customModulesFromProject) {
// Skip if this module is already in customContentItems (by path)
const isDuplicate = allCustomModules.some((item) => item.path && mod.path && path.resolve(item.path) === path.resolve(mod.path));
if (!isDuplicate) {
allCustomModules.push({
name: `${chalk.cyan('✓')} ${mod.name} ${chalk.gray(`(${mod.source})`)}`,
value: mod.id,
checked: isNewInstallation ? mod.defaultSelected || false : installedModuleIds.has(mod.id),
});
}
}
// Add separators and modules in correct order
if (allCustomModules.length > 0) {
// Add separator for custom content, all custom modules, and official content separator
moduleChoices.push(
new inquirer.Separator('── Custom Content ──'),
...allCustomModules,
new inquirer.Separator('── Official Content ──'),
);
}
// Add official modules (only non-custom ones)
for (const mod of availableModules) { for (const mod of availableModules) {
moduleChoices.push({ if (!mod.isCustom) {
name: mod.name, moduleChoices.push({
value: mod.id, name: mod.name,
checked: isNewInstallation ? mod.defaultSelected || false : installedModuleIds.has(mod.id), value: mod.id,
}); checked: isNewInstallation ? mod.defaultSelected || false : installedModuleIds.has(mod.id),
});
}
} }
return moduleChoices; return moduleChoices;