imhcode 1.0.2 → 1.0.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.
Files changed (2) hide show
  1. package/bin/imhcode.js +41 -42
  2. package/package.json +1 -1
package/bin/imhcode.js CHANGED
@@ -1662,28 +1662,40 @@ async function generateSprintPlans(cwd, userPrompt, brainstormContent, config) {
1662
1662
  const testingModeRaw = extractAnswer(brainstormContent, 'Q31', 'A').trim().toUpperCase().charAt(0);
1663
1663
  const detectedTesting = testingModeRaw === 'B' ? 'balanced' : testingModeRaw === 'C' ? 'strict' : 'fast';
1664
1664
 
1665
- // Detect scope from brainstorm content
1666
- const b = brainstormContent.toLowerCase();
1667
- const hasFrontend = true; // Always assume frontend
1668
- const hasBackend = (() => {
1669
- // Check Q31-equivalent backend answer or keyword detection
1670
- const backendAnswer = extractAnswer(brainstormContent, 'Q16', '').trim();
1671
- if (backendAnswer && backendAnswer !== '*(edit if needed)*') return true;
1672
- return /laravel|django|fastapi|express|spring\s*boot|node\.js.*api|postgresql|mysql|redis/i.test(brainstormContent);
1673
- })();
1674
- const hasMobile = /flutter|react native|ios.*app|android.*app|expo/i.test(brainstormContent);
1675
- const needsWorktrees = /worktree.*yes|yes.*worktree/i.test(brainstormContent);
1676
- const hasPayments = /stripe|paypal|payment|yes.*payment/i.test(brainstormContent);
1677
- const hasRealtime = /websocket|real-time.*yes|yes.*real-time|socket\.io/i.test(brainstormContent);
1678
- const designStyle = (() => {
1679
- const m = brainstormContent.match(/Your Answer:\s*\*(.*?(?:glassmorphism|neumorphism|brutalism|claymorphism|minimalist|modern saas).*?)\*/i);
1680
- return m ? m[1].trim() : 'Modern SaaS';
1665
+ const ansQ8 = extractAnswer(brainstormContent, 'Q8', 'Dark Premium').trim();
1666
+ const ansQ9 = extractAnswer(brainstormContent, 'Q9', 'Modern SaaS').trim();
1667
+ const ansQ12 = extractAnswer(brainstormContent, 'Q12', 'system toggle').toLowerCase();
1668
+ const ansQ14 = extractAnswer(brainstormContent, 'Q14', 'no').toLowerCase();
1669
+ const ansQ16 = extractAnswer(brainstormContent, 'Q16', 'no').toLowerCase();
1670
+ const ansQ21 = extractAnswer(brainstormContent, 'Q21', 'no').toLowerCase();
1671
+ const ansQ22 = extractAnswer(brainstormContent, 'Q22', 'no').toLowerCase();
1672
+ const ansQ25 = extractAnswer(brainstormContent, 'Q25', 'no').toLowerCase();
1673
+
1674
+ const hasFrontend = true; // Always assume frontend
1675
+
1676
+ // Robust scope detection: only true if user answer is not "no", "none", or standard default fallback placeholder
1677
+ const hasBackend = (() => {
1678
+ if (ansQ16.includes('no') || ansQ16.includes('none') || ansQ16.includes('edit if needed') || ansQ16.trim() === '') {
1679
+ return false;
1680
+ }
1681
+ return true;
1681
1682
  })();
1682
- const colorStyle = (() => {
1683
- const m = brainstormContent.match(/Your Answer:\s*\*(.*?(?:vibrant|dark premium|minimal neutral|pastel|corporate|bold).*?)\*/i);
1684
- return m ? m[1].trim() : 'Dark Premium';
1683
+
1684
+ const hasMobile = (() => {
1685
+ if (ansQ25.includes('no') || ansQ25.includes('none') || ansQ25.includes('edit if needed') || ansQ25.trim() === '') {
1686
+ return false;
1687
+ }
1688
+ return true;
1685
1689
  })();
1686
1690
 
1691
+ const needsWorktrees = ansQ14.includes('yes') || ansQ14.includes('true');
1692
+ const hasPayments = !ansQ22.includes('no') && !ansQ22.includes('none') && !ansQ22.includes('edit if needed') && ansQ22.trim().length > 0;
1693
+ const hasRealtime = !ansQ21.includes('no') && !ansQ21.includes('none') && !ansQ21.includes('edit if needed') && ansQ21.trim().length > 0;
1694
+
1695
+ const designStyle = ansQ9.replace(/\*\(.*?\)\*/g, '').trim() || 'Modern SaaS';
1696
+ const colorStyle = ansQ8.replace(/\*\(.*?\)\*/g, '').trim() || 'Dark Premium';
1697
+ const darkmode = ansQ12.replace(/\*\(.*?\)\*/g, '').trim() || 'system toggle';
1698
+
1687
1699
  // Save testing mode to config
1688
1700
  if (config) {
1689
1701
  config.testing_mode = detectedTesting;
@@ -1691,21 +1703,7 @@ async function generateSprintPlans(cwd, userPrompt, brainstormContent, config) {
1691
1703
  try { fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8'); } catch {}
1692
1704
  }
1693
1705
 
1694
- // Fix 5: Create workspace directories lazily based on brainstorm answers
1695
- if (hasFrontend) {
1696
- const frontendDir = path.join(cwd, 'frontend');
1697
- if (!fs.existsSync(frontendDir)) {
1698
- fs.mkdirSync(frontendDir, { recursive: true });
1699
- console.log(` 📁 Created frontend/ (scope confirmed in brainstorming)`);
1700
- }
1701
- }
1702
- if (hasBackend) {
1703
- const backendDir = path.join(cwd, 'backend');
1704
- if (!fs.existsSync(backendDir)) {
1705
- fs.mkdirSync(backendDir, { recursive: true });
1706
- console.log(` 📁 Created backend/ (scope confirmed in brainstorming)`);
1707
- }
1708
- }
1706
+ // Create workspace directories lazily (only worktrees since it's a layout helper, NOT frontend/backend which must remain empty for official CLI scaffolding)
1709
1707
  if (needsWorktrees) {
1710
1708
  const wtDir = path.join(cwd, '.worktrees');
1711
1709
  if (!fs.existsSync(wtDir)) {
@@ -1716,7 +1714,7 @@ async function generateSprintPlans(cwd, userPrompt, brainstormContent, config) {
1716
1714
 
1717
1715
  // Generate PROJECT_BRIEF.md
1718
1716
  const briefContent = generateProjectBrief(userPrompt, brainstormContent, {
1719
- hasFrontend, hasBackend, hasMobile, designStyle, colorStyle, detectedTesting
1717
+ hasFrontend, hasBackend, hasMobile, designStyle, colorStyle, darkmode, detectedTesting
1720
1718
  });
1721
1719
  fs.writeFileSync(path.join(cwd, BRIEF_MD), briefContent, 'utf8');
1722
1720
  console.log(` ✅ Created PROJECT_BRIEF.md`);
@@ -1724,7 +1722,7 @@ async function generateSprintPlans(cwd, userPrompt, brainstormContent, config) {
1724
1722
  // Try LLM-powered sprint generation first (Fix 0)
1725
1723
  const llmSprintResult = await tryLLMSprintGeneration(
1726
1724
  cwd, userPrompt, brainstormContent, config,
1727
- { hasFrontend, hasBackend, hasMobile, hasPayments, hasRealtime, designStyle, colorStyle, detectedTesting, needsWorktrees }
1725
+ { hasFrontend, hasBackend, hasMobile, hasPayments, hasRealtime, designStyle, colorStyle, darkmode, detectedTesting, needsWorktrees }
1728
1726
  );
1729
1727
 
1730
1728
  let lastSprintNum;
@@ -1736,7 +1734,7 @@ async function generateSprintPlans(cwd, userPrompt, brainstormContent, config) {
1736
1734
  // Fix 5: Fallback to smart static generation
1737
1735
  lastSprintNum = await generateStaticSprintPlans(
1738
1736
  cwd,
1739
- { hasFrontend, hasBackend, hasMobile, hasPayments, hasRealtime, designStyle, colorStyle, detectedTesting },
1737
+ { hasFrontend, hasBackend, hasMobile, hasPayments, hasRealtime, designStyle, colorStyle, darkmode, detectedTesting },
1740
1738
  config
1741
1739
  );
1742
1740
  }
@@ -1750,7 +1748,7 @@ async function generateSprintPlans(cwd, userPrompt, brainstormContent, config) {
1750
1748
 
1751
1749
  // Update compact context
1752
1750
  const contextContent = buildContextContent(userPrompt, {
1753
- hasFrontend, hasBackend, hasMobile, detectedTesting, lastSprintNum, designStyle, colorStyle
1751
+ hasFrontend, hasBackend, hasMobile, detectedTesting, lastSprintNum, designStyle, colorStyle, darkmode
1754
1752
  });
1755
1753
  fs.mkdirSync(path.join(cwd, LOCAL_DIR_NAME), { recursive: true });
1756
1754
  fs.writeFileSync(path.join(cwd, CONTEXT_MD), contextContent, 'utf8');
@@ -1761,7 +1759,7 @@ async function generateSprintPlans(cwd, userPrompt, brainstormContent, config) {
1761
1759
  * Attempt LLM-generated sprint plans. Returns { sprintCount } on success, null on failure.
1762
1760
  */
1763
1761
  async function tryLLMSprintGeneration(cwd, userPrompt, brainstormContent, config, scope) {
1764
- const { hasFrontend, hasBackend, hasMobile, hasPayments, hasRealtime, designStyle, colorStyle, detectedTesting } = scope;
1762
+ const { hasFrontend, hasBackend, hasMobile, hasPayments, hasRealtime, designStyle, colorStyle, darkmode, detectedTesting } = scope;
1765
1763
 
1766
1764
  const agentList = [
1767
1765
  'planner (planning)', 'designer (frontend)', 'nextjs-executor (frontend)', 'react-executor (frontend)',
@@ -1788,7 +1786,7 @@ ${userPrompt}
1788
1786
  ${brainstormContent}
1789
1787
 
1790
1788
  ## Scope
1791
- - Frontend: ${hasFrontend ? 'YES' : 'NO'} (Design style: ${designStyle}, Colors: ${colorStyle})
1789
+ - Frontend: ${hasFrontend ? 'YES' : 'NO'} (Design style: ${designStyle}, Colors: ${colorStyle}, Dark Mode Strategy: ${darkmode})
1792
1790
  - Backend: ${hasBackend ? 'YES' : 'NO'}
1793
1791
  - Mobile: ${hasMobile ? 'YES' : 'NO'}
1794
1792
  - Payments: ${hasPayments ? 'YES' : 'NO'}
@@ -1838,7 +1836,8 @@ Return ONLY this JSON structure (no markdown, no explanation):
1838
1836
  8. Max 6 tasks per sprint for clean execution
1839
1837
  9. If design style is Glassmorphism/Neumorphism — include a designer task for design tokens in Sprint 1
1840
1838
  10. If payments needed — include payment integration task in a sprint
1841
- 11. If realtime needed — include WebSocket/SSE task in a sprint`;
1839
+ 11. If realtime needed — include WebSocket/SSE task in a sprint
1840
+ 12. Under Frontend, STRICTLY respect the Dark Mode Strategy: if strategy is "light only", do NOT generate any dark mode setups, variables, toggles or dark styles. If strategy is "always dark", design the UI strictly for dark backgrounds.`;
1842
1841
 
1843
1842
  const llmOutput = await invokePlanningLLM(llmPrompt, config, cwd);
1844
1843
  if (!llmOutput) return null;
@@ -2021,7 +2020,7 @@ ${tasks.map((t, i) => `- [ ] Task ${i+1}: ${t.task} [\`${t.agent}\`]`).join('\n'
2021
2020
  # Model: ${routedModel || 'default'} via ${routedEngine || 'default'}
2022
2021
  # Tier: ${t.tier}
2023
2022
  CWD="$(cd "$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
2024
- cd "$CWD/../../../.."
2023
+ cd "$CWD/../../.."
2025
2024
 
2026
2025
  TASK="${taskDesc.replace(/"/g, '\\"')}"
2027
2026
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "imhcode",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "IMH-Code — Imam Hussain Coding Harness Platform. A fast-first multi-agent AI coding framework with intelligent model routing. 19 generic role-based agents (planner, nextjs-executor, laravel-executor, etc.), configurable testing strategy, and 7 token-saving optimizations for rapid MVP development.",
5
5
  "main": "index.js",
6
6
  "bin": {