@beastmode-develeap/beastmode 0.1.13 → 0.1.15

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.
@@ -0,0 +1,47 @@
1
+ {
2
+ "id": "design-thinking",
3
+ "name": "Design Thinking",
4
+ "description": "Human-centered approach — empathize, define, ideate, prototype, test",
5
+ "phases": [
6
+ {
7
+ "id": "empathize",
8
+ "name": "Empathize",
9
+ "agent_role": "UX Researcher",
10
+ "description": "Understand the users, their needs, pain points, and context",
11
+ "artifact": "empathy-map.md",
12
+ "prompt_template": "You are a UX Researcher conducting the Empathize phase of Design Thinking.\n\nGoal: Build deep understanding of the target users.\n- Who are the users? What do they do daily?\n- What are their pain points and frustrations?\n- What are their goals and motivations?\n- What workarounds do they use today?\n\nAsk questions one at a time. Produce an empathy map as the artifact.\n\nTopic: {idea}"
13
+ },
14
+ {
15
+ "id": "define",
16
+ "name": "Define",
17
+ "agent_role": "Product Designer",
18
+ "description": "Synthesize research into a clear problem statement",
19
+ "artifact": "problem-statement.md",
20
+ "prompt_template": "You are a Product Designer conducting the Define phase.\n\nUsing the empathy research, craft a clear problem statement:\n- Point of View (POV) statement: [User] needs [need] because [insight]\n- How Might We questions\n- Success criteria\n\nPrevious artifacts:\n{previous_artifacts}"
21
+ },
22
+ {
23
+ "id": "ideate",
24
+ "name": "Ideate",
25
+ "agent_role": "Innovation Facilitator",
26
+ "description": "Generate a wide range of creative solutions",
27
+ "artifact": "ideas.md",
28
+ "prompt_template": "You are an Innovation Facilitator conducting the Ideate phase.\n\nGenerate diverse solutions:\n- Quantity over quality — no idea is too wild\n- Build on existing ideas\n- Group and theme the ideas\n- Vote on top 3-5 to prototype\n\nProblem statement:\n{previous_artifacts}"
29
+ },
30
+ {
31
+ "id": "prototype",
32
+ "name": "Prototype",
33
+ "agent_role": "Product Designer",
34
+ "description": "Create lightweight representations of the best ideas",
35
+ "artifact": "prototype-spec.md",
36
+ "prompt_template": "You are a Product Designer in the Prototype phase.\n\nFor the selected ideas, create lightweight specs:\n- User flows and wireframe descriptions\n- Key interactions and states\n- What to test and what assumptions to validate\n\nSelected ideas:\n{previous_artifacts}"
37
+ },
38
+ {
39
+ "id": "test",
40
+ "name": "Test",
41
+ "agent_role": "UX Researcher",
42
+ "description": "Define how to validate the prototypes with real users",
43
+ "artifact": "test-plan.md",
44
+ "prompt_template": "You are a UX Researcher designing the Test phase.\n\nCreate a test plan:\n- What hypotheses to test\n- Test scenarios and tasks\n- Success/failure criteria\n- How to collect and analyze feedback\n\nPrototypes:\n{previous_artifacts}"
45
+ }
46
+ ]
47
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "id": "superpowers",
3
+ "name": "Superpowers Brainstorming",
4
+ "description": "Structured collaborative brainstorm — explore intent, propose approaches, refine design before implementation",
5
+ "phases": [],
6
+ "system_prompt_template": "You are conducting a structured brainstorming session using the Superpowers methodology.\n\nProcess:\n1. Understand the idea — ask clarifying questions one at a time\n2. Explore alternatives — propose 2-3 approaches with trade-offs\n3. Refine the design — present sections incrementally, get approval\n4. Document — summarize decisions and next steps\n\nRules:\n- One question at a time\n- Prefer multiple choice when possible\n- YAGNI ruthlessly — remove unnecessary features\n- Be ready to go back and clarify\n\nThe user's topic: {idea}"
7
+ }
@@ -5278,7 +5278,7 @@ function InceptionSetup({ methodologies, onStart, onCancel }) {
5278
5278
  return html`
5279
5279
  <div class="card" style="max-width:600px;margin:40px auto;">
5280
5280
  <div class="card-header">
5281
- <h3>New Product</h3>
5281
+ <h3>Product Inception</h3>
5282
5282
  </div>
5283
5283
  <div class="form-field">
5284
5284
  <label>Product Name</label>
@@ -5504,17 +5504,16 @@ function ChatPage({ selectedProject, inceptionMode, quickBrainstorm, resumeSessi
5504
5504
  return [...prev, { id: Date.now(), role: 'assistant', content: data.delta.text, timestamp: new Date() }];
5505
5505
  });
5506
5506
  } else if (data.type === 'tool_use') {
5507
- // Tool call — seal any in-progress assistant message, show tool card, keep thinking
5507
+ // Tool call — seal any in-progress assistant message, keep thinking.
5508
+ // Don't render tool cards in the chat — just show the thinking indicator.
5508
5509
  setMessages(prev => {
5509
5510
  if (prev.length > 0 && prev[prev.length - 1].role === 'assistant' && !prev[prev.length - 1].sealed) {
5510
5511
  return [...prev.slice(0, -1), { ...prev[prev.length - 1], sealed: true }];
5511
5512
  }
5512
5513
  return prev;
5513
5514
  });
5514
- addMessage('tool', data.name || 'tool', { input: data.input, id: data.id });
5515
5515
  setThinking(true);
5516
5516
  } else if (data.type === 'tool_result') {
5517
- addMessage('tool_result', data.output || '', { id: data.id, name: data.name });
5518
5517
  // Keep thinking — Claude will respond after processing tool results
5519
5518
  setThinking(true);
5520
5519
  } else if (data.type === 'error') {
@@ -5809,112 +5808,219 @@ function ToolResultCard({ content, extra }) {
5809
5808
  }
5810
5809
 
5811
5810
  // ================================================================
5812
- // Strategy Page
5811
+ // Strategy Start Screen — 1-liner prompt or Product inception form
5813
5812
  // ================================================================
5814
5813
 
5814
+ function StrategyStartPage({ selectedProject, sessionType }) {
5815
+ const [topic, setTopic] = useState('');
5816
+ const [approach, setApproach] = useState('auto');
5817
+ const [methodologies, setMethodologies] = useState([]);
5818
+
5819
+ useEffect(() => {
5820
+ api('GET', '/api/methodologies').then(data => setMethodologies(data.methodologies || [])).catch(() => {});
5821
+ }, []);
5822
+
5823
+ // Product type: show full inception form
5824
+ if (sessionType === 'product') {
5825
+ return html`<${InceptionSetup}
5826
+ methodologies=${methodologies}
5827
+ onStart=${(config) => {
5828
+ api('POST', '/api/strategy/' + selectedProject + '/sessions', {
5829
+ name: config.productName,
5830
+ idea: config.idea,
5831
+ methodology: config.methodology,
5832
+ interactionMode: config.interactionMode,
5833
+ sessionType: 'product',
5834
+ approach: config.methodology,
5835
+ }).then(session => {
5836
+ navigate('#/strategy-session/' + session.sessionId);
5837
+ });
5838
+ }}
5839
+ onCancel=${() => navigate('#/strategy')}
5840
+ />`;
5841
+ }
5842
+
5843
+ // Free-form: create session and go straight to chat
5844
+ if (sessionType === 'free-form') {
5845
+ useEffect(() => {
5846
+ api('POST', '/api/strategy/' + selectedProject + '/sessions', {
5847
+ name: 'Free-form session',
5848
+ idea: 'Open-ended strategic thinking',
5849
+ methodology: 'none',
5850
+ sessionType: 'free-form',
5851
+ approach: 'auto',
5852
+ }).then(session => {
5853
+ navigate('#/strategy-session/' + session.sessionId);
5854
+ });
5855
+ }, []);
5856
+ return html`<${SkeletonLoader} type="page" />`;
5857
+ }
5858
+
5859
+ // Everything else: 1-liner prompt + approach dropdown
5860
+ const typeLabel = (SESSION_TYPES.find(t => t.id === sessionType) || {}).name || sessionType;
5861
+
5862
+ const approaches = [
5863
+ { id: 'auto', name: 'Auto', desc: 'Claude picks based on topic' },
5864
+ ...(methodologies || []).map(m => ({ id: m.id, name: m.name, desc: m.description })),
5865
+ ];
5866
+
5867
+ return html`
5868
+ <div class="page-content">
5869
+ <div class="card" style="max-width:500px;margin:60px auto;">
5870
+ <div class="card-header">
5871
+ <h3>${typeLabel} Session</h3>
5872
+ </div>
5873
+ <div class="form-field">
5874
+ <label>What are you thinking about?</label>
5875
+ <textarea class="form-input form-textarea" rows="3"
5876
+ placeholder="Describe what you want to explore..."
5877
+ value=${topic} onInput=${(e) => setTopic(e.target.value)}></textarea>
5878
+ </div>
5879
+ <div class="form-field">
5880
+ <label>Approach</label>
5881
+ <select class="form-input" value=${approach} onChange=${(e) => setApproach(e.target.value)}>
5882
+ ${approaches.map(a => html`
5883
+ <option key=${a.id} value=${a.id}>${a.name}${a.desc ? ' — ' + a.desc : ''}</option>
5884
+ `)}
5885
+ </select>
5886
+ </div>
5887
+ <div style="display:flex;gap:8px;justify-content:flex-end;margin-top:16px;">
5888
+ <button class="btn" onClick=${() => navigate('#/strategy')}>Cancel</button>
5889
+ <button class="btn btn-primary" disabled=${!topic.trim()}
5890
+ onClick=${() => {
5891
+ api('POST', '/api/strategy/' + selectedProject + '/sessions', {
5892
+ name: topic.trim().substring(0, 60),
5893
+ idea: topic.trim(),
5894
+ methodology: approach === 'auto' ? 'none' : approach,
5895
+ sessionType,
5896
+ approach,
5897
+ }).then(session => {
5898
+ navigate('#/strategy-session/' + session.sessionId);
5899
+ });
5900
+ }}>
5901
+ Start
5902
+ </button>
5903
+ </div>
5904
+ </div>
5905
+ </div>
5906
+ `;
5907
+ }
5908
+
5909
+ // ================================================================
5910
+ // Strategy Page — Brain + Door
5911
+ // ================================================================
5912
+
5913
+ const SESSION_TYPES = [
5914
+ { id: 'feature', name: 'Feature', color: '#F5A623', desc: 'Brainstorm a new feature or enhancement' },
5915
+ { id: 'architecture', name: 'Architecture', color: '#4CAF50', desc: 'Evaluate design decisions & trade-offs' },
5916
+ { id: 'refactor', name: 'Refactor', color: '#2196F3', desc: 'Plan tech debt cleanup or restructuring' },
5917
+ { id: 'product', name: 'Product', color: '#9C27B0', desc: 'Full product inception (BMAD/Lean/PRD)' },
5918
+ { id: 'review', name: 'Review', color: '#FF9800', desc: 'Retrospective on recent work & runs' },
5919
+ { id: 'free-form', name: 'Free-form', color: '#888', desc: 'Open-ended strategic thinking' },
5920
+ ];
5921
+
5922
+ const FEED_TYPE_STYLES = {
5923
+ session: { letter: 'S', color: '#F5A623' },
5924
+ decision: { letter: 'D', color: '#4CAF50' },
5925
+ task: { letter: 'T', color: '#2196F3' },
5926
+ learning: { letter: 'L', color: '#FF9800' },
5927
+ run: { letter: 'R', color: '#9C27B0' },
5928
+ };
5929
+
5815
5930
  function StrategyPage({ selectedProject }) {
5816
- const [sessions, setSessions] = useState([]);
5931
+ const [feed, setFeed] = useState([]);
5932
+ const [feedTotal, setFeedTotal] = useState(0);
5933
+ const [nextCursor, setNextCursor] = useState(null);
5817
5934
  const [loading, setLoading] = useState(true);
5818
- const [index, setIndex] = useState(null);
5935
+
5936
+ const loadFeed = (cursor) => {
5937
+ const url = '/api/strategy/' + selectedProject + '/feed' + (cursor ? '?cursor=' + cursor : '');
5938
+ api('GET', url).then(data => {
5939
+ if (cursor) {
5940
+ setFeed(prev => [...prev, ...(data.items || [])]);
5941
+ } else {
5942
+ setFeed(data.items || []);
5943
+ }
5944
+ setFeedTotal(data.total || 0);
5945
+ setNextCursor(data.nextCursor || null);
5946
+ }).catch(() => {}).finally(() => setLoading(false));
5947
+ };
5819
5948
 
5820
5949
  useEffect(() => {
5821
5950
  if (!selectedProject || selectedProject === 'all') { setLoading(false); return; }
5822
- Promise.all([
5823
- api('GET', '/api/strategy/' + selectedProject + '/sessions').catch(() => ({ sessions: [] })),
5824
- api('GET', '/api/strategy/' + selectedProject + '/index').catch(() => null),
5825
- ]).then(([sessData, indexData]) => {
5826
- setSessions(sessData.sessions || []);
5827
- setIndex(indexData);
5828
- }).finally(() => setLoading(false));
5951
+ loadFeed(null);
5829
5952
  }, [selectedProject]);
5830
5953
 
5831
- if (loading) return html`<${SkeletonLoader} type="cards" />`;
5832
-
5833
5954
  if (!selectedProject || selectedProject === 'all') {
5834
5955
  return html`<div class="page-content">
5835
5956
  <div class="page-header"><h2>Strategy</h2><p>Select a project to view its strategy space</p></div>
5836
5957
  </div>`;
5837
5958
  }
5838
5959
 
5839
- const learnings = (index?.artifacts || []).filter(a => a.type === 'learning');
5960
+ if (loading) return html`<${SkeletonLoader} type="cards" />`;
5840
5961
 
5841
5962
  return html`
5842
5963
  <div class="page-content">
5843
5964
  <div class="page-header">
5844
5965
  <h2>Strategy — ${selectedProject}</h2>
5845
- <p>Plan major changes, brainstorm features, track strategic decisions</p>
5966
+ <p>Plan, brainstorm, decide, track</p>
5846
5967
  </div>
5847
5968
 
5848
- <div style="display:flex;gap:10px;margin-bottom:20px;">
5849
- <button class="btn btn-primary btn-pill" onClick=${() => navigate('#/new-session')}>
5850
- <${Icon} name="plus" size=${14} /> New Session
5851
- </button>
5852
- <button class="btn btn-pill" onClick=${() => navigate('#/quick-brainstorm')}>
5853
- <${Icon} name="chat" size=${14} /> Quick Brainstorm
5854
- </button>
5969
+ <!-- Session Launcher -->
5970
+ <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:24px;">
5971
+ ${SESSION_TYPES.map(t => html`
5972
+ <div key=${t.id} style="padding:14px;background:var(--card-bg);border:1px solid var(--border);border-radius:8px;cursor:pointer;transition:border-color 0.15s;"
5973
+ onMouseOver=${(e) => e.currentTarget.style.borderColor = t.color}
5974
+ onMouseOut=${(e) => e.currentTarget.style.borderColor = 'var(--border)'}
5975
+ onClick=${() => navigate('#/strategy-start/' + t.id)}>
5976
+ <div style="font-size:13px;font-weight:600;color:${t.color};">${t.name}</div>
5977
+ <div style="font-size:11px;color:var(--text-muted);margin-top:4px;">${t.desc}</div>
5978
+ </div>
5979
+ `)}
5855
5980
  </div>
5856
5981
 
5857
- ${learnings.length > 0 ? html`
5858
- <div class="card" style="margin-bottom:16px;">
5859
- <div class="card-header">
5860
- <h3>Active Learnings</h3>
5861
- <span class="badge badge-accent">${learnings.length}</span>
5862
- </div>
5863
- ${learnings.map(l => html`
5864
- <div class="activity-item" key=${l.path}>
5865
- <div class="activity-name" style="font-size:13px;">${l.summary}</div>
5866
- <div class="activity-meta">
5867
- <span class="activity-time">${timeAgo(l.date)}</span>
5868
- </div>
5869
- </div>
5870
- `)}
5982
+ <!-- Feed Header -->
5983
+ <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
5984
+ <div style="display:flex;align-items:center;gap:8px;">
5985
+ <span style="font-size:14px;font-weight:600;color:var(--text);">Activity</span>
5986
+ <span class="badge badge-muted">${feedTotal}</span>
5871
5987
  </div>
5872
- ` : null}
5988
+ <button class="btn btn-pill" style="font-size:12px;" onClick=${() => {
5989
+ const title = prompt('Decision title:');
5990
+ if (title) {
5991
+ api('POST', '/api/strategy/' + selectedProject + '/decisions', { title, context: '' }).then(() => loadFeed(null));
5992
+ }
5993
+ }}>Log a decision</button>
5994
+ </div>
5873
5995
 
5874
- <div class="card">
5875
- <div class="card-header">
5876
- <h3>Past Sessions</h3>
5877
- <span class="badge badge-muted">${sessions.length}</span>
5878
- </div>
5879
- ${sessions.length === 0
5880
- ? html`<${EmptyState} icon="runs" title="No strategy sessions yet"
5881
- description="Start a new session to plan features and brainstorm ideas." />`
5882
- : sessions.map(s => html`
5883
- <div class="activity-item" key=${s.sessionId} style="cursor:pointer;padding:14px 12px;"
5884
- onClick=${() => navigate('#/strategy-session/' + s.sessionId)}>
5885
- <div style="display:flex;justify-content:space-between;align-items:center;">
5886
- <div>
5887
- <div class="activity-name" style="font-size:14px;font-weight:600;">${s.name}</div>
5888
- <div style="font-size:12px;color:var(--text-muted);margin-top:2px;">
5889
- ${s.methodology.toUpperCase()} ${s.status}
5890
- ${s.phases ? ' — ' + s.phases.filter(p => p.status === 'approved').length + '/' + s.phases.length + ' phases' : ''}
5996
+ <!-- Activity Feed -->
5997
+ ${feed.length === 0
5998
+ ? html`<${EmptyState} icon="runs" title="No strategic activity yet"
5999
+ description="Start a session above to begin building your project's strategic record." />`
6000
+ : html`<div class="card" style="padding:0;">
6001
+ ${feed.map(item => {
6002
+ const style = FEED_TYPE_STYLES[item.type] || { letter: '?', color: '#666' };
6003
+ return html`
6004
+ <div key=${item.id} style="display:flex;gap:12px;padding:12px 16px;border-bottom:1px solid var(--border);cursor:${item.link ? 'pointer' : 'default'};"
6005
+ onClick=${() => item.link && navigate(item.link)}>
6006
+ <div style="width:28px;height:28px;background:${style.color};border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600;color:#000;flex-shrink:0;">
6007
+ ${style.letter}
6008
+ </div>
6009
+ <div style="flex:1;min-width:0;">
6010
+ <div style="font-size:13px;font-weight:600;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">${item.title}</div>
6011
+ ${item.subtitle ? html`<div style="font-size:11px;color:var(--text-muted);margin-top:2px;">${item.subtitle}</div>` : null}
5891
6012
  </div>
6013
+ <div style="font-size:11px;color:var(--text-muted);white-space:nowrap;flex-shrink:0;">${timeAgo(item.timestamp)}</div>
5892
6014
  </div>
5893
- <span class="activity-time">${timeAgo(s.createdAt)}</span>
6015
+ `;
6016
+ })}
6017
+ ${nextCursor ? html`
6018
+ <div style="padding:12px;text-align:center;">
6019
+ <button class="btn btn-pill" style="font-size:12px;" onClick=${() => loadFeed(nextCursor)}>Load more</button>
5894
6020
  </div>
5895
- </div>
5896
- `)}
5897
- </div>
5898
-
5899
- ${index ? html`
5900
- <div class="card" style="margin-top:16px;">
5901
- <div class="card-header"><h3>Project Intelligence</h3></div>
5902
- <div class="quick-info-row">
5903
- <div class="quick-info-item">
5904
- <div><div class="quick-info-label">Sessions</div>
5905
- <div class="quick-info-value mono">${index.stats.totalSessions}</div></div>
5906
- </div>
5907
- <div class="quick-info-item">
5908
- <div><div class="quick-info-label">Runs</div>
5909
- <div class="quick-info-value mono">${index.stats.totalRuns}</div></div>
5910
- </div>
5911
- <div class="quick-info-item">
5912
- <div><div class="quick-info-label">Learnings</div>
5913
- <div class="quick-info-value mono">${index.stats.activeLearnings}</div></div>
5914
- </div>
5915
- </div>
5916
- </div>
5917
- ` : null}
6021
+ ` : null}
6022
+ </div>`
6023
+ }
5918
6024
  </div>
5919
6025
  `;
5920
6026
  }
@@ -6167,13 +6273,16 @@ function App() {
6167
6273
  case '#/projects': page = html`<${ProjectsPage} selectedProject=${selectedProject} onProjectChange=${setSelectedProject} />`; break;
6168
6274
  case '#/extensions': page = html`<${ExtensionsPage} selectedProject=${selectedProject} />`; break;
6169
6275
  case '#/chat': page = html`<${ChatPage} selectedProject=${selectedProject} />`; break;
6170
- case '#/new-product': page = html`<${ChatPage} selectedProject=${selectedProject} inceptionMode=${true} />`; break;
6171
- case '#/new-session': page = html`<${ChatPage} selectedProject=${selectedProject} inceptionMode=${true} strategyMode=${'full'} />`; break;
6172
- case '#/quick-brainstorm': page = html`<${ChatPage} selectedProject=${selectedProject} quickBrainstorm=${true} />`; break;
6276
+ case '#/new-product': navigate('#/strategy-start/product'); page = html`<${SkeletonLoader} type="page" />`; break;
6277
+ case '#/new-session': navigate('#/strategy-start/free-form'); page = html`<${SkeletonLoader} type="page" />`; break;
6278
+ case '#/quick-brainstorm': navigate('#/strategy-start/free-form'); page = html`<${SkeletonLoader} type="page" />`; break;
6173
6279
  case '#/settings': page = html`<${SettingsPage} selectedProject=${selectedProject} />`; break;
6174
6280
  case '#/help': page = html`<${HelpPage} />`; break;
6175
6281
  default:
6176
- if (route.startsWith('#/strategy-session/')) {
6282
+ if (route.startsWith('#/strategy-start/')) {
6283
+ const sessionType = route.replace('#/strategy-start/', '');
6284
+ page = html`<${StrategyStartPage} selectedProject=${selectedProject} sessionType=${sessionType} />`;
6285
+ } else if (route.startsWith('#/strategy-session/')) {
6177
6286
  const sessionId = route.replace('#/strategy-session/', '');
6178
6287
  page = html`<${ChatPage} selectedProject=${selectedProject} resumeSession=${sessionId} />`;
6179
6288
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beastmode-develeap/beastmode",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "description": "BeastMode Dark Factory — turn intent into verified software",
5
5
  "type": "module",
6
6
  "bin": {