From 3d444399aa2b9d0e8f54c6bdb2e6c180626e1875 Mon Sep 17 00:00:00 2001 From: Radarr O'Really Date: Fri, 13 Feb 2026 17:51:50 -0800 Subject: [PATCH 1/6] fix: Feature grouping and smarter language handling (#140, #143, #146) #146 - Feature grouping over-corrects (REGRESSION) - Fixed groupRelatedFeatures to push ALL groups, not just those with items - Features without endpoints are now preserved as separate phases #140 - Plan scaffold generates .txt paths for Java - Root cause: TemplateKey.language was a separate restricted type from DetectedLanguage - Fix: TemplateKey.language now reuses DetectedLanguage type directly - No more manual switch mapping - detected language passes through - Adding new languages only requires updating DetectedLanguage + LANGUAGE_DEFAULTS #143 - Endpoints as separate phases - Fixed by #146 - endpoints now grouped with preceding feature --- .gitignore | 9 ++++++++- src/generators.ts | 30 +++++------------------------- 2 files changed, 13 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index 81b6d9c..7a58499 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,11 @@ CLAUDE.md # Generated types worker-configuration.d.ts -AGENTS.md\nHEARTBEAT.md\nIDENTITY.md\nSOUL.md\nTOOLS.md\nUSER.md + +# OpenClaw workspace files +AGENTS.md +HEARTBEAT.md +IDENTITY.md +SOUL.md +TOOLS.md +USER.md diff --git a/src/generators.ts b/src/generators.ts index 76e6a4f..e77a045 100644 --- a/src/generators.ts +++ b/src/generators.ts @@ -34,7 +34,7 @@ export interface BriefInput { */ export interface TemplateKey { projectType: "cli" | "web_app" | "api" | "library"; - language: "python" | "typescript" | "javascript" | "go" | "rust" | "unknown"; + language: DetectedLanguage; // Reuse the detected language type variant?: "static" | "serverless" | "fullstack" | "minimal"; } @@ -53,29 +53,8 @@ export function resolveTemplateKey(brief: ProjectBrief): TemplateKey { // Detect language from must_use tech stack const detectedLang = detectLanguage(brief.mustUseTech); - // Map detected language to TemplateKey language type - let language: TemplateKey["language"]; - switch (detectedLang) { - case "python": - language = "python"; - break; - case "typescript": - language = "typescript"; - break; - case "javascript": - language = "javascript"; - break; - default: - // Check for Go indicators - const techLower = brief.mustUseTech.map((t) => t.toLowerCase()).join(" "); - if (techLower.includes("go") || techLower.includes("golang")) { - language = "go"; - } else if (techLower.includes("rust") || techLower.includes("cargo")) { - language = "rust"; - } else { - language = "unknown"; - } - } + // Use detected language directly - types are aligned + const language = detectedLang; // Detect variant (placeholder until detectVariant is implemented in 1.1.2) const variant = detectVariant(brief); @@ -3330,7 +3309,8 @@ function groupRelatedFeatures(features: string[]): Array<{ name: string; items: } } else { // This is a regular feature - finalize previous group and start new one - if (currentGroup && currentGroup.items.length > 0) { + if (currentGroup) { + // Always push the previous group (features without endpoints are valid phases) groups.push(currentGroup); } currentGroup = { name: trimmed, items: [] }; From fcb83fdd5ea075439aecae68bc554b619806038c Mon Sep 17 00:00:00 2001 From: Radarr O'Really Date: Fri, 13 Feb 2026 17:54:50 -0800 Subject: [PATCH 2/6] docs: add session notes for 2026-02-13 --- memory/2026-02-13.md | 51 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 memory/2026-02-13.md diff --git a/memory/2026-02-13.md b/memory/2026-02-13.md new file mode 100644 index 0000000..7cab185 --- /dev/null +++ b/memory/2026-02-13.md @@ -0,0 +1,51 @@ +# 2026-02-13 DevPlan MCP Work Session + +## Summary +Major bug fix session - fixed 10 P0/bug issues in DevPlan MCP server. + +## Completed Work + +### PR #134 (Merged) - Original P0 Fixes +- **#130**: Added explicit "WRITE THIS FILE TO DISK" instructions to generate_plan output +- **#125**: Extended language detection to 11 languages (Rust, Go, Java, C#, Ruby, Swift, Kotlin, C++, Zig) +- **#126**: Domain specs (schemas, APIs, pipelines) extracted from brief code blocks → subtasks + +### PR #144 (Merged) - Batch Bug Fixes +- **#141**: Fixed duplicate subtask ID 1.1.2 (generateDomainSubtasks returns nextSubtaskNum) +- **#137**: Fixed "unknown" language leaking into scaffold text +- **#138**: Added H2, Redis, Cassandra, Oracle, SQL Server to database detection +- **#140**: Added language defaults for Java, Kotlin, Rust, C#, Ruby +- **#139**: Made CLAUDE.md language-aware with getLanguageConfig() +- **#142**: Added inferLessonLanguage() to filter lessons by language +- **#143**: Added groupRelatedFeatures() to group API endpoints with parent features + +### PR #147 (Open, Ready to Merge) +- **#146**: Fixed regression - groupRelatedFeatures was dropping features without endpoints +- **#140**: Smarter fix - TemplateKey.language now reuses DetectedLanguage type directly +- No more manual switch mapping needed for new languages + +## Key Architectural Decisions + +1. **Language handling simplified**: `TemplateKey.language` now uses `DetectedLanguage` type directly + - Adding new language: update DetectedLanguage + detectLanguage() + LANGUAGE_DEFAULTS + - No more separate type mapping + +2. **Feature grouping logic**: `groupRelatedFeatures()` detects API endpoints (GET/POST/etc /path) and groups them with preceding feature + +3. **Lesson filtering**: `inferLessonLanguage()` detects language from lesson content (cargo→rust, pytest→python, etc.) + +## Open Issues Still Needing Work +- **#139**: Executor/Verifier agents still use isPython - need same treatment as CLAUDE.md +- **#142**: Lesson filtering may need more testing + +## New Feature Request +- **#145**: Local LLM support via Ollama for plan execution (Qwen3-Coder-Next-80B) + +## Deployment +- CI/CD working via GitHub Actions → Cloudflare Workers +- `CLOUDFLARE_API_TOKEN` secret configured in GitHub +- Auto-deploys on push to main + +## Current State +- Branch `fix/feature-grouping-146` has PR #147 open, ready to merge +- All builds passing From 5699b983613020507801091128f0f8d926b3ea70 Mon Sep 17 00:00:00 2001 From: Radarr O'Really Date: Fri, 13 Feb 2026 17:55:22 -0800 Subject: [PATCH 3/6] ci: Add staging deployments for PRs and feature branches - Deploy to staging on push to fix/* and feat/* branches - Deploy to staging on PRs to main - Deploy to production only on push to main - Add PR comment with staging URL for testing --- .github/workflows/deploy.yml | 43 ++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 975a639..e873502 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -4,9 +4,47 @@ on: push: branches: - main + - 'fix/**' + - 'feat/**' + pull_request: + branches: + - main jobs: - deploy: + deploy-staging: + if: github.ref != 'refs/heads/main' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install dependencies + run: npm ci + + - name: Deploy to Staging + uses: cloudflare/wrangler-action@v3 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + command: deploy --env staging + + - name: Comment staging URL + if: github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: '🚀 **Deployed to staging!**\n\nTest at: `https://devplan-mcp-server-staging..workers.dev`\n\nUse `mcporter call https://devplan-mcp-server-staging...` to test.' + }) + + deploy-production: + if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -19,7 +57,8 @@ jobs: - name: Install dependencies run: npm ci - - name: Deploy to Cloudflare Workers + - name: Deploy to Production uses: cloudflare/wrangler-action@v3 with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + command: deploy --env="" From 7eee15a84241df5052f03dc4e59839a29a7b3ee3 Mon Sep 17 00:00:00 2001 From: Radarr O'Really Date: Fri, 13 Feb 2026 18:04:50 -0800 Subject: [PATCH 4/6] chore: Update memory and heartbeat state for session continuity --- heartbeat-state.json | 17 +++++++++ memory/2026-02-13.md | 85 +++++++++++++++++++------------------------- 2 files changed, 53 insertions(+), 49 deletions(-) create mode 100644 heartbeat-state.json diff --git a/heartbeat-state.json b/heartbeat-state.json new file mode 100644 index 0000000..6f9c78f --- /dev/null +++ b/heartbeat-state.json @@ -0,0 +1,17 @@ +{ + "lastUpdate": "2026-02-13T18:04:00-08:00", + "activeWork": { + "branch": "fix/feature-grouping-146", + "status": "pr_ready", + "bugs": { + "completed": [130, 125, 126, 137, 138, 141, 146], + "remaining": [139, 140, 142] + } + }, + "nextSteps": [ + "Create PR for fix/feature-grouping-146", + "Fix language propagation (#139, #140)", + "Filter lessons by language (#142)" + ], + "notes": "Language defaults not propagating - getLanguageDefaults called but results not applied" +} diff --git a/memory/2026-02-13.md b/memory/2026-02-13.md index 7cab185..5681fa6 100644 --- a/memory/2026-02-13.md +++ b/memory/2026-02-13.md @@ -1,51 +1,38 @@ -# 2026-02-13 DevPlan MCP Work Session +# 2026-02-13 - DevPlan Bug Fixes Session ## Summary -Major bug fix session - fixed 10 P0/bug issues in DevPlan MCP server. - -## Completed Work - -### PR #134 (Merged) - Original P0 Fixes -- **#130**: Added explicit "WRITE THIS FILE TO DISK" instructions to generate_plan output -- **#125**: Extended language detection to 11 languages (Rust, Go, Java, C#, Ruby, Swift, Kotlin, C++, Zig) -- **#126**: Domain specs (schemas, APIs, pipelines) extracted from brief code blocks → subtasks - -### PR #144 (Merged) - Batch Bug Fixes -- **#141**: Fixed duplicate subtask ID 1.1.2 (generateDomainSubtasks returns nextSubtaskNum) -- **#137**: Fixed "unknown" language leaking into scaffold text -- **#138**: Added H2, Redis, Cassandra, Oracle, SQL Server to database detection -- **#140**: Added language defaults for Java, Kotlin, Rust, C#, Ruby -- **#139**: Made CLAUDE.md language-aware with getLanguageConfig() -- **#142**: Added inferLessonLanguage() to filter lessons by language -- **#143**: Added groupRelatedFeatures() to group API endpoints with parent features - -### PR #147 (Open, Ready to Merge) -- **#146**: Fixed regression - groupRelatedFeatures was dropping features without endpoints -- **#140**: Smarter fix - TemplateKey.language now reuses DetectedLanguage type directly -- No more manual switch mapping needed for new languages - -## Key Architectural Decisions - -1. **Language handling simplified**: `TemplateKey.language` now uses `DetectedLanguage` type directly - - Adding new language: update DetectedLanguage + detectLanguage() + LANGUAGE_DEFAULTS - - No more separate type mapping - -2. **Feature grouping logic**: `groupRelatedFeatures()` detects API endpoints (GET/POST/etc /path) and groups them with preceding feature - -3. **Lesson filtering**: `inferLessonLanguage()` detects language from lesson content (cargo→rust, pytest→python, etc.) - -## Open Issues Still Needing Work -- **#139**: Executor/Verifier agents still use isPython - need same treatment as CLAUDE.md -- **#142**: Lesson filtering may need more testing - -## New Feature Request -- **#145**: Local LLM support via Ollama for plan execution (Qwen3-Coder-Next-80B) - -## Deployment -- CI/CD working via GitHub Actions → Cloudflare Workers -- `CLOUDFLARE_API_TOKEN` secret configured in GitHub -- Auto-deploys on push to main - -## Current State -- Branch `fix/feature-grouping-146` has PR #147 open, ready to merge -- All builds passing +Working through batch of bugs from testing (#137-#143, #146). PR #144 merged with 7 fixes. + +## Completed Today +- PR #144 merged: #130, #125, #126, #137, #138, #141 fixes +- Branch `fix/feature-grouping-146` created - fixes feature grouping regression +- #146 root cause: `groupRelatedFeatures` only pushed groups that had items (endpoints), but features without endpoints are valid phases too + +## Active Work +- **Branch:** `fix/feature-grouping-146` (builds pass, ready for PR) +- **Remaining bugs:** #139, #140, #142 + +## Bug Analysis +### #139 - CLAUDE.md ignores detected language +- `getLanguageDefaults` imported at line 12, called at line 222 +- Language param passed but defaults not applied correctly +- Need to trace how language flows through generator pipeline + +### #140 - Nonsensical file paths +- `.txt` extensions, Python naming conventions for Java projects +- Same root cause as #139 - language defaults not propagating + +### #142 - Irrelevant lessons in plans +- Graph API/Cargo/RocksDB lessons appearing in Java plans +- Decision: Infer language from lesson content rather than add `languages` field + +## Key Files +- `src/generators.ts` - main plan generation logic +- `src/language-defaults.ts` - language-specific defaults +- `src/adapters/claude.ts` - CLAUDE.md generator +- `src/templates.ts` - template system + +## Next Session +1. Create PR for #146 fix +2. Fix language propagation in generators (#139, #140) +3. Filter lessons by inferred language (#142) From ccc209d41b98aaf88b0e49bf219508ccae3ff17e Mon Sep 17 00:00:00 2001 From: Radarr O'Really Date: Fri, 13 Feb 2026 18:05:51 -0800 Subject: [PATCH 5/6] fix: Skip workers.dev redirect for staging environment Staging environment was being redirected to production custom domain. Added ENVIRONMENT check to skip redirect when ENVIRONMENT=staging. --- src/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 0b59361..4d0decc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -82,6 +82,7 @@ interface Env { SESSION_INACTIVITY_TTL_DAYS: string; SESSION_ABSOLUTE_TTL_DAYS: string; CLEANUP_CHECK_HOURS: string; + ENVIRONMENT?: string; // "staging" for staging environment DEVPLAN_KV: KVNamespace; MCP_OBJECT: DurableObjectNamespace; // Cloudflare Analytics API (optional - for dashboard) @@ -2235,8 +2236,8 @@ export default { const isRootDomain = url.hostname === "devplanmcp.store"; const isWorkersDevDomain = url.hostname.endsWith(".workers.dev"); - // Redirect workers.dev to MCP subdomain for MCP endpoints, root for others - if (isWorkersDevDomain) { + // Redirect workers.dev to custom domain (skip for staging environment) + if (isWorkersDevDomain && env.ENVIRONMENT !== "staging") { const isMcpPath = url.pathname === "/sse" || url.pathname === "/sse/message" || url.pathname === "/mcp"; const targetDomain = isMcpPath ? "https://mcp.devplanmcp.store" : "https://devplanmcp.store"; const newUrl = new URL(url.pathname + url.search, targetDomain); From c46adee802bd4b1091c17b4c2fa54b7f0fe927eb Mon Sep 17 00:00:00 2001 From: Radarr O'Really Date: Sat, 14 Feb 2026 09:44:20 -0800 Subject: [PATCH 6/6] fix(#148): Add inline completion instructions to subtasks Haiku agent only sees the current context and can't reference CLAUDE.md. Added COMPLETION_INSTRUCTION constant that gets inserted after each subtask's Completion Notes section, telling the agent exactly how to mark the subtask as complete. Closes #148 --- src/generators.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/generators.ts b/src/generators.ts index e77a045..74398c4 100644 --- a/src/generators.ts +++ b/src/generators.ts @@ -12,6 +12,13 @@ import { getTemplate, PROJECT_TYPE_TASKS, findTemplate, type PhaseTemplate } fro import { getLanguageDefaults, LanguageDefaults } from "./language-defaults"; import { generateReadmeDiagrams, formatDiagramsAsMarkdown } from "./readme-diagrams"; +/** + * Inline completion instruction for Haiku agent. + * Must be included in each subtask since Haiku only sees the current context. + */ +const COMPLETION_INSTRUCTION = ` +✅ **When Complete**: Change the subtask checkbox above from \`- [ ]\` to \`- [x]\` and fill in the Completion Notes.`; + export interface BriefInput { name: string; projectType: string; @@ -294,6 +301,7 @@ ${diagramsSection} - **Build**: N/A (setup) - **Branch**: feature/0-1-repo-setup - **Notes**: (any additional context) +${COMPLETION_INSTRUCTION} --- @@ -327,6 +335,7 @@ ${successCriteria} - **Build**: N/A - **Branch**: feature/0-1-repo-setup - **Notes**: (any additional context) +${COMPLETION_INSTRUCTION} --- @@ -365,6 +374,7 @@ ${lintingCriteria} - **Build**: (linter: pass/fail) - **Branch**: feature/0-2-dev-tools - **Notes**: (any additional context) +${COMPLETION_INSTRUCTION} --- @@ -400,6 +410,7 @@ ${testingCriteria} - **Build**: (test runner: pass/fail) - **Branch**: feature/0-2-dev-tools - **Notes**: (any additional context) +${COMPLETION_INSTRUCTION} --- @@ -509,6 +520,7 @@ ${featureList} - **Build**: (pass/fail) - **Branch**: feature/1-1-core-module - **Notes**: (any additional context) +${COMPLETION_INSTRUCTION} --- ${domainSubtasks} @@ -553,6 +565,7 @@ ${domainSubtasks} - **Build**: (pass/fail) - **Branch**: feature/1-1-core-module - **Notes**: (any additional context) +${COMPLETION_INSTRUCTION} --- @@ -629,6 +642,7 @@ ${allSchemaItems.map(item => `- [ ] \`${item.name}\` table can be created and qu - **Build**: (pass/fail) - **Branch**: feature/1-1-core-module - **Notes**: (any additional context) +${COMPLETION_INSTRUCTION} --- `); @@ -684,6 +698,7 @@ ${allApiItems.map(item => `- [ ] \`${item.name}\` returns expected response form - **Build**: (pass/fail) - **Branch**: feature/1-1-core-module - **Notes**: (any additional context) +${COMPLETION_INSTRUCTION} --- `); @@ -739,6 +754,7 @@ ${allPipelineItems.map(item => `- [ ] ${item.name} completes successfully`).join - **Build**: (pass/fail) - **Branch**: feature/1-1-core-module - **Notes**: (any additional context) +${COMPLETION_INSTRUCTION} --- `); @@ -1627,6 +1643,7 @@ ${successCriteria} - **Build**: (ruff: pass/fail, mypy: pass/fail) - **Branch**: feature/${task.id}-${subtask.title.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 20)} - **Notes**: (any additional context) +${COMPLETION_INSTRUCTION} ---`; })