chore: bump version to 0.1411

This commit is contained in:
arkon
2026-01-28 04:17:14 +01:00
parent 38c36502ec
commit 0a928144da
5 changed files with 272 additions and 30 deletions
+15 -20
View File
@@ -16,7 +16,7 @@ When user says "COM":
1. Increment version in BOTH `package.json` AND `CLAUDE.md`
2. Run: `git add -A && git commit -m "chore: bump version to X.XXXX" && git push && npm run build && systemctl --user restart claudeman-web`
**Version**: 0.1410 (must match `package.json`)
**Version**: 0.1411 (must match `package.json`)
## Project Overview
@@ -167,25 +167,20 @@ The app must stay fast with 20 sessions and 50 agent windows:
| **Test utilities** | `test/respawn-test-utils.ts` |
| **Keyboard shortcuts** | README.md or App Settings in web UI |
## Active Ralph Loop Task
## MCP Server Integration
**Current Task**: Create an improvement plan to make this app(Claudeman) significantly better, but focus on performance, memory leaks, that it runs really fluid and fast and all the functions are working properly also in edge cases.
The `claudeman-mcp` binary provides Model Context Protocol integration for Claude Desktop:
**Case Folder**: `/home/arkon/claudeman-cases/claudeman`
```json
// Add to ~/.claude/claude_desktop_config.json
{
"mcpServers": {
"claudeman-spawn": {
"command": "node",
"args": ["/path/to/claudeman/dist/mcp-server.js"]
}
}
}
```
### Key Files
- **Plan Summary**: `/home/arkon/claudeman-cases/claudeman/ralph-wizard/summary.md` - Human-readable plan overview
- **Todo Items**: `/home/arkon/claudeman-cases/claudeman/ralph-wizard/final-result.json` - Contains `items` array with all todo tasks
- **Research**: `/home/arkon/claudeman-cases/claudeman/ralph-wizard/research/result.json` - External resources and codebase patterns
### How to Work on This Task
1. Read the plan summary to understand the overall approach
2. Check `final-result.json` for the todo items array - each item has `id`, `title`, `description`, `priority`
3. Work through items in priority order (critical → high → medium → low)
4. Use `<promise>COMPLETION_PHRASE</promise>` when the entire task is complete
### Research Insights
Check `/home/arkon/claudeman-cases/claudeman/ralph-wizard/research/result.json` for:
- External GitHub repos and documentation links to reference
- Existing codebase patterns to follow
- Technical recommendations from the research phase
This enables Claude Desktop to spawn and manage agents via MCP tools.
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "claudeman",
"version": "0.1410",
"version": "0.1411",
"description": "The missing control plane for Claude Code - run 20 autonomous agents with real-time monitoring and session persistence",
"type": "module",
"main": "dist/index.js",
+163 -9
View File
@@ -2663,9 +2663,11 @@ class ClaudemanApp {
document.getElementById('ralphTaskDescription').value = '';
document.getElementById('ralphCompletionPhrase').value = 'COMPLETE';
this.selectIterationPreset(10);
// Reset auto-start checkbox (off by default)
// Reset auto-start checkboxes (off by default) - there are two, one in step 2 and one in step 3
const autoStartEl = document.getElementById('ralphAutoStart');
const autoStartStep2El = document.getElementById('ralphAutoStartStep2');
if (autoStartEl) autoStartEl.checked = false;
if (autoStartStep2El) autoStartStep2El.checked = false;
// Populate case selector
this.populateRalphCaseSelector();
@@ -2767,6 +2769,137 @@ class ClaudemanApp {
}
}
// Check for existing ralph-wizard research files
async checkExistingWizardFiles() {
const caseName = this.ralphWizardConfig.caseName;
if (!caseName) return;
try {
const res = await fetch(`/api/cases/${encodeURIComponent(caseName)}/ralph-wizard/files`);
const data = await res.json();
if (data.success && data.data?.files?.length > 0) {
this.ralphWizardConfig.existingWizardFiles = data.data.files;
this.updateExistingWizardFilesUI();
} else {
this.ralphWizardConfig.existingWizardFiles = null;
this.updateExistingWizardFilesUI();
}
} catch (err) {
console.error('Failed to check for existing wizard files:', err);
this.ralphWizardConfig.existingWizardFiles = null;
}
}
// Update UI to show existing wizard files option
updateExistingWizardFilesUI() {
const files = this.ralphWizardConfig.existingWizardFiles;
let section = document.getElementById('existingWizardFilesSection');
if (!files || files.length === 0) {
section?.remove();
return;
}
// Count agents with results
const agentsWithResults = files.filter(f => f.resultFile).length;
if (!section) {
// Create the section if it doesn't exist - insert before loading state
const loadingState = document.getElementById('planGenerationLoading');
section = document.createElement('div');
section.id = 'existingWizardFilesSection';
section.className = 'existing-wizard-files-section';
loadingState?.parentNode?.insertBefore(section, loadingState);
}
section.innerHTML = `
<div class="existing-wizard-card">
<div class="existing-wizard-header">
<span class="existing-wizard-icon">📁</span>
<span class="existing-wizard-title">Previous Research Found</span>
</div>
<p class="existing-wizard-desc">
Found ${agentsWithResults} agent result${agentsWithResults !== 1 ? 's' : ''} from a previous plan generation.
</p>
<div class="existing-wizard-agents">
${files.filter(f => f.resultFile).map(f => `
<span class="existing-wizard-agent">${this.getAgentTypeLabel(f.agentType)}</span>
`).join('')}
</div>
<div class="existing-wizard-actions">
<button class="btn-toolbar btn-sm btn-primary" onclick="app.reuseExistingWizardFiles()">
Use Existing Research
</button>
<button class="btn-toolbar btn-sm" onclick="app.regenerateAllWizardFiles()">
Regenerate All
</button>
</div>
</div>
`;
}
getAgentTypeLabel(agentType) {
const labels = {
research: 'Research',
requirements: 'Requirements',
architecture: 'Architecture',
testing: 'Testing',
risks: 'Risks',
verification: 'Verification',
execution: 'Execution',
'final-review': 'Review',
};
return labels[agentType] || agentType;
}
async reuseExistingWizardFiles() {
// Load the final result if it exists
const caseName = this.ralphWizardConfig.caseName;
try {
const res = await fetch(`/api/cases/${encodeURIComponent(caseName)}/ralph-wizard/file/${encodeURIComponent('final-result.json')}`);
const data = await res.json();
if (data.success && data.data?.parsed?.items) {
// Use the existing plan items
this.ralphWizardConfig.generatedPlan = data.data.parsed.items.map((item, idx) => ({
content: item.content || item.title || `Task ${idx + 1}`,
priority: item.priority || 'P1',
enabled: true,
id: item.id || `reused-${Date.now()}-${idx}`,
source: item.source,
rationale: item.rationale,
tddPhase: item.tddPhase,
}));
this.ralphWizardConfig.planGenerated = true;
this.ralphWizardConfig.reusingExistingFiles = true;
this.ralphWizardConfig.planCost = 0;
// Hide the existing files section
document.getElementById('existingWizardFilesSection')?.remove();
// Show the plan editor
this.renderPlanEditor();
this.updateDetailLevelButtons();
} else {
// No final result, just skip to generate with existing research
this.ralphWizardConfig.reusingExistingFiles = true;
this.generatePlan();
}
} catch (err) {
console.error('Failed to load existing results:', err);
// Fall back to regenerating
this.generatePlan();
}
}
regenerateAllWizardFiles() {
// Clear the reuse flag and hide the section
this.ralphWizardConfig.reusingExistingFiles = false;
document.getElementById('existingWizardFilesSection')?.remove();
this.generatePlan();
}
// Called when case selector changes
onRalphCaseChange() {
const caseName = document.getElementById('ralphCaseSelect')?.value;
@@ -2774,6 +2907,7 @@ class ClaudemanApp {
this.ralphWizardConfig.caseName = caseName;
this.ralphWizardConfig.existingPlan = null;
this.ralphWizardConfig.useExistingPlan = false;
this.ralphWizardConfig.existingWizardFiles = null;
this.checkExistingFixPlan();
}
}
@@ -2852,6 +2986,19 @@ class ClaudemanApp {
this.updateDetailLevelButtons();
}
// Sync auto-start checkboxes between step 2 and step 3
syncAutoStartCheckbox(sourceEl) {
const step2El = document.getElementById('ralphAutoStartStep2');
const step3El = document.getElementById('ralphAutoStart');
const isChecked = sourceEl.checked;
if (step2El) step2El.checked = isChecked;
if (step3El) step3El.checked = isChecked;
// Update config
this.ralphWizardConfig.autoStart = isChecked;
}
// Stop any ongoing plan generation (abort fetch, clear timers, hide spinner)
stopPlanGeneration() {
// Abort ongoing fetch
@@ -2903,13 +3050,17 @@ class ClaudemanApp {
this.ralphWizardStep = 2;
this.updateRalphWizardUI();
// If there's an existing plan, show the option to use it
// Otherwise auto-start plan generation
if (this.ralphWizardConfig.existingPlan) {
this.updateExistingPlanUI();
} else {
this.generatePlan();
}
// Check for existing wizard files first, then existing plan
this.checkExistingWizardFiles().then(() => {
// If there's an existing plan (@fix_plan.md), show the option to use it
if (this.ralphWizardConfig.existingPlan) {
this.updateExistingPlanUI();
} else if (!this.ralphWizardConfig.existingWizardFiles?.length) {
// No existing files, auto-start plan generation
this.generatePlan();
}
// If existingWizardFiles exists, the UI will show and wait for user choice
});
} else if (this.ralphWizardStep === 2) {
// Must have generated or skipped plan
if (!this.ralphWizardConfig.planGenerated && !this.ralphWizardConfig.skipPlanGeneration) {
@@ -4732,7 +4883,10 @@ class ClaudemanApp {
// Read advanced options (respawn disabled by default for Ralph Loops)
config.enableRespawn = document.getElementById('ralphEnableRespawn')?.checked ?? false;
config.autoStart = document.getElementById('ralphAutoStart')?.checked ?? false;
// Check either auto-start checkbox (step 2 or step 3)
config.autoStart = document.getElementById('ralphAutoStart')?.checked ||
document.getElementById('ralphAutoStartStep2')?.checked ||
this.ralphWizardConfig.autoStart || false;
// Close wizard
this.closeRalphWizard();
+7
View File
@@ -1030,6 +1030,13 @@
<button class="btn-toolbar btn-sm plan-cancel-btn" onclick="app.cancelPlanGeneration()">Stop</button>
<button class="btn-toolbar btn-sm" onclick="app.regeneratePlan()">Regenerate</button>
</div>
<!-- Auto-start toggle visible during generation -->
<div class="plan-autostart-toggle">
<label class="plan-autostart-label">
<input type="checkbox" id="ralphAutoStartStep2" onchange="app.syncAutoStartCheckbox(this)">
<span class="plan-autostart-text">Auto-launch when plan completes</span>
</label>
</div>
</div>
<!-- Stopped/Error state -->
+86
View File
@@ -5925,6 +5925,92 @@ kbd {
justify-content: center;
}
.plan-autostart-toggle {
margin-top: 1.25rem;
padding-top: 1rem;
border-top: 1px solid var(--border);
}
.plan-autostart-label {
display: flex;
align-items: center;
gap: 0.5rem;
cursor: pointer;
justify-content: center;
}
.plan-autostart-label input[type="checkbox"] {
width: 18px;
height: 18px;
accent-color: var(--accent);
cursor: pointer;
}
.plan-autostart-text {
font-size: 0.85rem;
color: var(--text);
}
.plan-autostart-label:hover .plan-autostart-text {
color: var(--accent);
}
/* Existing wizard files section */
.existing-wizard-files-section {
padding: 1rem;
}
.existing-wizard-card {
background: var(--bg-dark);
border: 1px solid var(--accent);
border-radius: 8px;
padding: 1rem;
}
.existing-wizard-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.5rem;
}
.existing-wizard-icon {
font-size: 1.2rem;
}
.existing-wizard-title {
font-weight: 600;
color: var(--text);
}
.existing-wizard-desc {
font-size: 0.85rem;
color: var(--text-dim);
margin: 0 0 0.75rem 0;
}
.existing-wizard-agents {
display: flex;
flex-wrap: wrap;
gap: 0.35rem;
margin-bottom: 1rem;
}
.existing-wizard-agent {
background: rgba(96, 165, 250, 0.2);
color: var(--accent);
padding: 0.2rem 0.5rem;
border-radius: 4px;
font-size: 0.75rem;
font-weight: 500;
}
.existing-wizard-actions {
display: flex;
gap: 0.5rem;
justify-content: center;
}
.plan-cancel-btn {
color: var(--red);
}