@dendelion/paper-camp 0.8.0 → 0.10.0

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 (75) hide show
  1. package/dist/app/assets/index-BnXxehKU.js +2 -0
  2. package/dist/app/assets/index-BnXxehKU.js.map +1 -0
  3. package/dist/app/assets/index-C2kYil0S.js +3 -0
  4. package/dist/app/assets/index-C2kYil0S.js.map +1 -0
  5. package/dist/app/assets/index-CRRHTP77.js +2 -0
  6. package/dist/app/assets/index-CRRHTP77.js.map +1 -0
  7. package/dist/app/assets/index-DrNAzLuW.js +2 -0
  8. package/dist/app/assets/index-DrNAzLuW.js.map +1 -0
  9. package/dist/app/assets/main-BJGNGUiz.css +1 -0
  10. package/dist/app/assets/main-CyxblUnu.js +233 -0
  11. package/dist/app/assets/main-CyxblUnu.js.map +1 -0
  12. package/dist/app/assets/sidebar-section-Ch50IaLb.js +2 -0
  13. package/dist/app/assets/sidebar-section-Ch50IaLb.js.map +1 -0
  14. package/dist/app/index.html +2 -2
  15. package/dist/chunks/{serializer.BfH7zTwv.js → roadmap.C0AQ6pUX.js} +1437 -1387
  16. package/dist/chunks/roadmap.C0AQ6pUX.js.map +1 -0
  17. package/dist/cli/index.js +6720 -6420
  18. package/dist/cli/index.js.map +1 -1
  19. package/dist/core/env.d.ts +0 -5
  20. package/dist/core/env.d.ts.map +1 -1
  21. package/dist/core/git-pr/branch.d.ts +2 -6
  22. package/dist/core/git-pr/branch.d.ts.map +1 -1
  23. package/dist/core/git-pr/pr-lookup.d.ts +3 -44
  24. package/dist/core/git-pr/pr-lookup.d.ts.map +1 -1
  25. package/dist/core/git-pr/pr.d.ts +5 -85
  26. package/dist/core/git-pr/pr.d.ts.map +1 -1
  27. package/dist/core/git-pr/scopes.d.ts +0 -6
  28. package/dist/core/git-pr/scopes.d.ts.map +1 -1
  29. package/dist/core/index.d.ts +1 -0
  30. package/dist/core/index.d.ts.map +1 -1
  31. package/dist/core/index.js +71 -66
  32. package/dist/core/parse/frontmatter-schemas.d.ts +0 -8
  33. package/dist/core/parse/frontmatter-schemas.d.ts.map +1 -1
  34. package/dist/core/parse/parser.d.ts +3 -31
  35. package/dist/core/parse/parser.d.ts.map +1 -1
  36. package/dist/core/parse/schemas.d.ts +2 -0
  37. package/dist/core/parse/schemas.d.ts.map +1 -1
  38. package/dist/core/readers.d.ts +2 -28
  39. package/dist/core/readers.d.ts.map +1 -1
  40. package/dist/core/roadmap.d.ts +4 -0
  41. package/dist/core/roadmap.d.ts.map +1 -0
  42. package/dist/core/roadmap.test.d.ts +2 -0
  43. package/dist/core/roadmap.test.d.ts.map +1 -0
  44. package/dist/core/run-order.d.ts +23 -0
  45. package/dist/core/run-order.d.ts.map +1 -0
  46. package/dist/core/run-order.test.d.ts +2 -0
  47. package/dist/core/run-order.test.d.ts.map +1 -0
  48. package/dist/core/scaffold/scaffold.d.ts +0 -6
  49. package/dist/core/scaffold/scaffold.d.ts.map +1 -1
  50. package/dist/core/scaffold/templates.d.ts +0 -6
  51. package/dist/core/scaffold/templates.d.ts.map +1 -1
  52. package/dist/core/sections.d.ts +18 -0
  53. package/dist/core/sections.d.ts.map +1 -0
  54. package/dist/core/serialize/content-hash.d.ts +0 -6
  55. package/dist/core/serialize/content-hash.d.ts.map +1 -1
  56. package/dist/core/serialize/serializer.d.ts +3 -60
  57. package/dist/core/serialize/serializer.d.ts.map +1 -1
  58. package/dist/core/serialize/serializer.test.d.ts +2 -0
  59. package/dist/core/serialize/serializer.test.d.ts.map +1 -0
  60. package/dist/core/status/status.d.ts +4 -19
  61. package/dist/core/status/status.d.ts.map +1 -1
  62. package/dist/types/index.d.ts +56 -29
  63. package/dist/types/index.d.ts.map +1 -1
  64. package/dist/types/index.js.map +1 -1
  65. package/package.json +2 -2
  66. package/dist/app/assets/index-CF8jC3IN.js +0 -2
  67. package/dist/app/assets/index-CF8jC3IN.js.map +0 -1
  68. package/dist/app/assets/index-DGXi8vpJ.js +0 -2
  69. package/dist/app/assets/index-DGXi8vpJ.js.map +0 -1
  70. package/dist/app/assets/main-D66GnCKz.css +0 -1
  71. package/dist/app/assets/main-DJDNx4Xs.js +0 -218
  72. package/dist/app/assets/main-DJDNx4Xs.js.map +0 -1
  73. package/dist/app/assets/sidebar-section-C2j12TzE.js +0 -2
  74. package/dist/app/assets/sidebar-section-C2j12TzE.js.map +0 -1
  75. package/dist/chunks/serializer.BfH7zTwv.js.map +0 -1
@@ -0,0 +1,2 @@
1
+ import{u as a,a as m,j as e,s as d,Z as j,f as p,d as v,c as S,l as x,b as f,M as b,e as D,h as T,P as C,r as w,X as k,o as L}from"./main-CyxblUnu.js";import{S as $}from"./sidebar-section-Ch50IaLb.js";const g=(s,l)=>s.toLowerCase().includes(l.toLowerCase()),Q=(s,l,c=120)=>{const r=s.toLowerCase().indexOf(l.toLowerCase());if(r===-1)return s.slice(0,c);const n=Math.max(0,r-40),i=Math.min(s.length,r+l.length+40);let h=s.slice(n,i);return n>0&&(h=`…${h}`),i<s.length&&(h=`${h}…`),h},z=({query:s})=>{const l=a(o=>o.repoDocs),c=a(o=>o.setActiveDocTitle),r=a(o=>o.setDocSearchQuery),n=m(),i=[];for(const o of l)(g(o.name,s)||g(o.content,s))&&i.push({title:o.name,snippet:Q(o.content,s)});const h=o=>{n({to:"/docs/$section",params:{section:"repo-docs"}}),c(o),r("")};return i.length===0?e.jsxs("p",{style:{opacity:.5},children:['No results found for "',s,'".']}):e.jsxs("div",{children:[e.jsxs("p",{className:"text-sm",style:{opacity:.5,marginBottom:d[3]},children:[i.length," result",i.length===1?"":"s",' for "',s,'"']}),e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:d[1]},children:i.map(o=>e.jsx(j,{variant:"ghost",size:"small",fullWidth:!0,onClick:()=>h(o.title),style:{justifyContent:"flex-start",padding:`${d[2]} ${d[3]}`},children:e.jsxs("span",{style:{textAlign:"left"},children:[e.jsx("span",{style:{fontFamily:p.serif,fontWeight:600,fontSize:"0.95rem",display:"block",marginBottom:"0.2rem"},children:o.title}),e.jsx("span",{className:"text-sm",style:{opacity:.6},children:o.snippet})]})},o.title))})]})},A=()=>{const s=a(n=>n.repoDocs),l=a(n=>n.activeDocTitle),c=s.find(n=>n.name===l);if(!c)return null;const r=c.name.endsWith(".md");return e.jsxs("div",{children:[e.jsx("h2",{style:{...v,margin:`0 0 ${d[4]}`},children:c.name}),r?e.jsx("div",{style:{fontFamily:p.body,fontSize:f.base,lineHeight:x.relaxed,color:S.textProse},children:e.jsx(b,{children:c.content})}):e.jsx("pre",{style:{fontFamily:p.mono,fontSize:f.xs,background:"rgba(0,0,0,0.04)",borderRadius:6,padding:d[4],overflowX:"auto",lineHeight:x.normal,whiteSpace:"pre-wrap"},children:c.content})]})},F=()=>{const s=a(i=>i.docSearchQuery),l=a(i=>i.activeDocTitle),c=m(),r=D(),n=()=>c({to:"/docs"});return s.trim()?e.jsx("div",{children:e.jsx(z,{query:s})}):r==="repo-docs"&&l?e.jsxs("div",{children:[e.jsx("div",{style:{marginBottom:d[4]},children:e.jsx(T,{items:[{id:"docs",label:"Docs",onClick:n},{id:"repo-doc",label:l}]})}),e.jsx(A,{})]}):e.jsxs("div",{children:[e.jsx(C,{children:"Docs"}),e.jsx("p",{style:{opacity:.5},children:"Select a section from the sidebar."})]})},R=s=>s.charAt(0).toUpperCase()+s.slice(1).toLowerCase(),u=({children:s})=>e.jsx("span",{className:"text-sm",style:{display:"block",padding:`${d[1]} ${d[3]}`,opacity:.35,fontStyle:"italic"},children:s}),M=()=>{const s=a(t=>t.repoDocs),l=a(t=>t.repoDocsLoading),c=a(t=>t.loadRepoDocs),r=a(t=>t.activeDocTitle),n=a(t=>t.setActiveDocTitle),i=a(t=>t.docSearchQuery),h=a(t=>t.setDocSearchQuery),o=D(),y=m();return w.useEffect(()=>{c()},[c]),e.jsxs(e.Fragment,{children:[e.jsx("div",{style:{marginBottom:d[4]},children:e.jsx(k,{size:"small","aria-label":"Search docs",placeholder:"Search docs…",value:i,onChange:t=>h(t.target.value)})}),e.jsx($,{label:"Repo Docs",children:l&&s.length===0?e.jsx(u,{children:"Loading…"}):s.length>0?s.map(t=>e.jsx(L,{size:"small",active:o==="repo-docs"&&r===t.name,onClick:()=>{y({to:"/docs/$section",params:{section:"repo-docs"}}),n(t.name)},children:R(t.name)},t.name)):e.jsx(u,{children:"No repo docs found"})})]})};export{F as DocsPage,M as DocsSidebar};
2
+ //# sourceMappingURL=index-BnXxehKU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-BnXxehKU.js","sources":["../../../src/app/features/docs/components/docs-search.tsx","../../../src/app/features/docs/components/repo-doc-detail.tsx","../../../src/app/features/docs/docs-page.tsx","../../../src/app/features/docs/components/docs-sidebar.tsx"],"sourcesContent":["import { useAppStore } from '@/app/stores/app-store';\nimport { fontFamily, space } from '@/app/styles/tokens';\nimport { Button } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\n\ninterface SearchMatch {\n title: string;\n snippet: string;\n}\n\ninterface DocsSearchProps {\n query: string;\n}\n\nconst searchIn = (text: string, query: string): boolean =>\n text.toLowerCase().includes(query.toLowerCase());\n\nconst snippet = (text: string, query: string, maxLen = 120): string => {\n const idx = text.toLowerCase().indexOf(query.toLowerCase());\n if (idx === -1) return text.slice(0, maxLen);\n const start = Math.max(0, idx - 40);\n const end = Math.min(text.length, idx + query.length + 40);\n let s = text.slice(start, end);\n if (start > 0) s = `…${s}`;\n if (end < text.length) s = `${s}…`;\n return s;\n};\n\nexport const DocsSearch = ({ query }: DocsSearchProps) => {\n const repoDocs = useAppStore((s) => s.repoDocs);\n const setActiveDocTitle = useAppStore((s) => s.setActiveDocTitle);\n const setDocSearchQuery = useAppStore((s) => s.setDocSearchQuery);\n const navigate = useNavigate();\n\n const results: SearchMatch[] = [];\n\n for (const f of repoDocs) {\n if (searchIn(f.name, query) || searchIn(f.content, query)) {\n results.push({\n title: f.name,\n snippet: snippet(f.content, query),\n });\n }\n }\n\n const handleSelect = (title: string) => {\n navigate({ to: '/docs/$section', params: { section: 'repo-docs' } });\n setActiveDocTitle(title);\n setDocSearchQuery('');\n };\n\n if (results.length === 0) {\n return <p style={{ opacity: 0.5 }}>No results found for \"{query}\".</p>;\n }\n\n return (\n <div>\n <p className=\"text-sm\" style={{ opacity: 0.5, marginBottom: space[3] }}>\n {results.length} result{results.length === 1 ? '' : 's'} for \"{query}\"\n </p>\n <div style={{ display: 'flex', flexDirection: 'column', gap: space[1] }}>\n {results.map((m) => (\n <Button\n key={m.title}\n variant=\"ghost\"\n size=\"small\"\n fullWidth\n onClick={() => handleSelect(m.title)}\n style={{ justifyContent: 'flex-start', padding: `${space[2]} ${space[3]}` }}\n >\n <span style={{ textAlign: 'left' }}>\n <span\n style={{\n fontFamily: fontFamily.serif,\n fontWeight: 600,\n fontSize: '0.95rem',\n display: 'block',\n marginBottom: '0.2rem',\n }}\n >\n {m.title}\n </span>\n <span className=\"text-sm\" style={{ opacity: 0.6 }}>\n {m.snippet}\n </span>\n </span>\n </Button>\n ))}\n </div>\n </div>\n );\n};\n","import { detailHeadingStyle } from '@/app/components/detail-heading-style';\nimport { Markdown } from '@/app/components/markdown';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { color, fontFamily, fontSize, lineHeight, space } from '@/app/styles/tokens';\n\nexport const RepoDocDetail = () => {\n const repoDocs = useAppStore((s) => s.repoDocs);\n const activeDocTitle = useAppStore((s) => s.activeDocTitle);\n\n const file = repoDocs.find((f) => f.name === activeDocTitle);\n if (!file) return null;\n\n const isMarkdown = file.name.endsWith('.md');\n\n return (\n <div>\n <h2 style={{ ...detailHeadingStyle, margin: `0 0 ${space[4]}` }}>{file.name}</h2>\n\n {isMarkdown ? (\n <div\n style={{\n fontFamily: fontFamily.body,\n fontSize: fontSize.base,\n lineHeight: lineHeight.relaxed,\n color: color.textProse,\n }}\n >\n <Markdown>{file.content}</Markdown>\n </div>\n ) : (\n <pre\n style={{\n fontFamily: fontFamily.mono,\n fontSize: fontSize.xs,\n background: 'rgba(0,0,0,0.04)',\n borderRadius: 6,\n padding: space[4],\n overflowX: 'auto',\n lineHeight: lineHeight.normal,\n whiteSpace: 'pre-wrap',\n }}\n >\n {file.content}\n </pre>\n )}\n </div>\n );\n};\n","import { PageTitle } from '@/app/components/page-title';\nimport { useResolvedDocSection } from '@/app/hooks';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { space } from '@/app/styles/tokens';\nimport { Breadcrumb } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\nimport { DocsSearch } from './components/docs-search';\nimport { RepoDocDetail } from './components/repo-doc-detail';\n\nexport const DocsPage = () => {\n const docSearchQuery = useAppStore((s) => s.docSearchQuery);\n const activeDocTitle = useAppStore((s) => s.activeDocTitle);\n const navigate = useNavigate();\n const activeDocSection = useResolvedDocSection();\n\n const handleBackToDocs = () => navigate({ to: '/docs' });\n\n if (docSearchQuery.trim()) {\n return (\n <div>\n <DocsSearch query={docSearchQuery} />\n </div>\n );\n }\n\n if (activeDocSection === 'repo-docs' && activeDocTitle) {\n return (\n <div>\n <div style={{ marginBottom: space[4] }}>\n <Breadcrumb\n items={[\n { id: 'docs', label: 'Docs', onClick: handleBackToDocs },\n { id: 'repo-doc', label: activeDocTitle },\n ]}\n />\n </div>\n <RepoDocDetail />\n </div>\n );\n }\n\n return (\n <div>\n <PageTitle>Docs</PageTitle>\n <p style={{ opacity: 0.5 }}>Select a section from the sidebar.</p>\n </div>\n );\n};\n","import { useResolvedDocSection } from '@/app/hooks';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { space } from '@/app/styles/tokens';\nimport { Input, ListItem } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\nimport { useEffect } from 'react';\nimport { SidebarSection } from '../../plans/components/sidebar-section';\n\nconst simplecaseLabel = (name: string) =>\n name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();\n\nconst EmptyState = ({ children }: { children: React.ReactNode }) => (\n <span\n className=\"text-sm\"\n style={{\n display: 'block',\n padding: `${space[1]} ${space[3]}`,\n opacity: 0.35,\n fontStyle: 'italic',\n }}\n >\n {children}\n </span>\n);\n\nexport const DocsSidebar = () => {\n const repoDocs = useAppStore((s) => s.repoDocs);\n const repoDocsLoading = useAppStore((s) => s.repoDocsLoading);\n const loadRepoDocs = useAppStore((s) => s.loadRepoDocs);\n const activeDocTitle = useAppStore((s) => s.activeDocTitle);\n const setActiveDocTitle = useAppStore((s) => s.setActiveDocTitle);\n const docSearchQuery = useAppStore((s) => s.docSearchQuery);\n const setDocSearchQuery = useAppStore((s) => s.setDocSearchQuery);\n const activeDocSection = useResolvedDocSection();\n const navigate = useNavigate();\n\n useEffect(() => {\n loadRepoDocs();\n }, [loadRepoDocs]);\n\n return (\n <>\n <div style={{ marginBottom: space[4] }}>\n <Input\n size=\"small\"\n aria-label=\"Search docs\"\n placeholder=\"Search docs…\"\n value={docSearchQuery}\n onChange={(e) => setDocSearchQuery(e.target.value)}\n />\n </div>\n\n <SidebarSection label=\"Repo Docs\">\n {repoDocsLoading && repoDocs.length === 0 ? (\n <EmptyState>Loading…</EmptyState>\n ) : repoDocs.length > 0 ? (\n repoDocs.map((f) => (\n <ListItem\n key={f.name}\n size=\"small\"\n active={activeDocSection === 'repo-docs' && activeDocTitle === f.name}\n onClick={() => {\n navigate({ to: '/docs/$section', params: { section: 'repo-docs' } });\n setActiveDocTitle(f.name);\n }}\n >\n {simplecaseLabel(f.name)}\n </ListItem>\n ))\n ) : (\n <EmptyState>No repo docs found</EmptyState>\n )}\n </SidebarSection>\n </>\n );\n};\n"],"names":["searchIn","text","query","snippet","maxLen","idx","start","end","s","DocsSearch","repoDocs","useAppStore","setActiveDocTitle","setDocSearchQuery","navigate","useNavigate","results","f","handleSelect","title","jsxs","space","m","jsx","Button","fontFamily","RepoDocDetail","activeDocTitle","file","isMarkdown","detailHeadingStyle","fontSize","lineHeight","color","Markdown","DocsPage","docSearchQuery","activeDocSection","useResolvedDocSection","handleBackToDocs","Breadcrumb","PageTitle","simplecaseLabel","name","EmptyState","children","DocsSidebar","repoDocsLoading","loadRepoDocs","useEffect","Fragment","Input","e","SidebarSection","ListItem"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import{u as m,C as w,r,j as e,P as v,s as f,p as x,b as g,A as S,f as j,O as L,c as y,E as D}from"./main-CyxblUnu.js";const N={phase:"Phase run",audit:"Audit","batch-reconcile":"Batch reconcile","run-all":"Run all phases",draft:"Draft",extend:"Extend",suggest:"Suggest ideas","commit-suggest":"Commit suggest","overlap-check":"Overlap check",sync:"Sync",reconcile:"Reconcile","fix-review":"Fix review"},p=s=>String(s).padStart(2,"0"),A=s=>{const t=new Date(s);return`${t.getFullYear()}-${p(t.getMonth()+1)}-${p(t.getDate())}`},T=s=>new Date(s).toLocaleDateString(void 0,{weekday:"long",year:"numeric",month:"long",day:"numeric"}),k=s=>{const t=new Date(s);return`${p(t.getHours())}:${p(t.getMinutes())}:${p(t.getSeconds())}`},c={fontSize:g.sm,fontWeight:600,opacity:.6,whiteSpace:"nowrap",overflow:"hidden"},E=({id:s})=>{const[t,o]=r.useState(null);return r.useEffect(()=>{o(null),D(s).then(l=>o(l.lines)).catch(()=>o([]))},[s]),t===null?e.jsx("p",{style:{opacity:.5,margin:0},children:"Loading…"}):t.length===0?e.jsx("p",{style:{opacity:.5,margin:0},children:"No output recorded."}):e.jsx("pre",{style:{fontFamily:j.mono,fontSize:g.xs,margin:0,maxHeight:320,overflowY:"auto",whiteSpace:"pre-wrap"},children:t.join(`
2
+ `)})},b=({size:s=14})=>e.jsx("svg",{width:s,height:s,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:e.jsx("polyline",{points:"9 18 15 12 9 6"})}),R=({entry:s,highlighted:t})=>{const[o,l]=r.useState(t);r.useEffect(()=>{t&&l(!0)},[t]);const d=()=>l(i=>!i);return e.jsxs("div",{className:t?"task-row-highlighted":void 0,style:{display:"flex",flexDirection:"column",gap:f[1],borderRadius:10},children:[e.jsx("div",{role:"button",tabIndex:0,onClick:d,onKeyDown:i=>{(i.key==="Enter"||i.key===" ")&&(i.preventDefault(),d())},style:{cursor:"pointer",borderRadius:10},children:e.jsx(x,{size:"small",texture:"canvas",className:"plan-row-card",children:e.jsxs("div",{className:"task-rows-grid",children:[e.jsx("span",{className:"task-rows-chevron","aria-expanded":o,style:{display:"inline-flex",alignItems:"center",opacity:.5},children:e.jsx(b,{})}),e.jsx("span",{style:{fontWeight:600,whiteSpace:"nowrap",overflow:"hidden"},children:N[s.taskKind]}),e.jsx("span",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",opacity:.7},children:s.planTitle}),e.jsx("span",{className:"text-sm",style:{opacity:.5,whiteSpace:"nowrap"},children:S[s.agentId]}),e.jsxs("span",{className:"task-rows-cell-time",style:{fontFamily:j.mono,fontSize:g.xs,opacity:.55,whiteSpace:"nowrap"},children:[k(s.startedAt),"–",k(s.endedAt)]}),e.jsx("div",{style:{display:"flex",alignItems:"center"},children:e.jsx(L,{size:"small",fillColor:s.outcome==="done"?"rgba(143, 185, 150, 0.25)":"rgba(201, 139, 139, 0.25)",textColor:s.outcome==="done"?y.accentGreenDark:y.accentRoseDark,children:s.outcome})})]})})}),o&&e.jsx(x,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsx(E,{id:s.id})})]})},C=()=>{const s=m(a=>a.taskLog),t=m(a=>a.taskLogLoading),o=m(a=>a.loadTaskLog),{taskId:l}=w({from:"/tasks"}),d=r.useRef(null);r.useEffect(()=>{o()},[o]),r.useEffect(()=>{var n;if(!l)return;const a=(n=d.current)==null?void 0:n.querySelector(".task-row-highlighted");a==null||a.scrollIntoView({behavior:"smooth",block:"center"})},[l]);const i=[...s].sort((a,n)=>n.endedAt.localeCompare(a.endedAt)),u=[];for(const a of i){const n=A(a.endedAt),h=u.at(-1);(h==null?void 0:h.key)===n?h.entries.push(a):u.push({key:n,entries:[a]})}return e.jsxs("div",{ref:d,children:[e.jsx(v,{children:"Tasks"}),t&&e.jsx("p",{style:{opacity:.5},children:"Loading…"}),!t&&i.length===0&&e.jsx("p",{style:{opacity:.5},children:"No tasks have run yet."}),!t&&i.length>0&&e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:f[1]},children:[e.jsx(x,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsxs("div",{className:"task-rows-grid",children:[e.jsx("span",{}),e.jsx("span",{style:c,children:"Task"}),e.jsx("span",{style:c,children:"Plan"}),e.jsx("span",{style:c,children:"Agent"}),e.jsx("span",{className:"task-rows-cell-time",style:c,children:"Time"}),e.jsx("span",{style:c,children:"Outcome"})]})}),u.map(a=>e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:f[1]},children:[e.jsx(x,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsx("span",{style:{...c,opacity:.75},children:T(a.entries[0].endedAt)})}),a.entries.map(n=>e.jsx(R,{entry:n,highlighted:n.id===l},n.id))]},a.key))]})]})};export{C as TasksPage};
3
+ //# sourceMappingURL=index-C2kYil0S.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-C2kYil0S.js","sources":["../../../src/app/features/tasks/tasks-page.tsx"],"sourcesContent":["import { PageTitle } from '@/app/components/page-title';\nimport { fetchTaskLogLines } from '@/app/services/content/docs-api';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { color, fontFamily, fontSize, space } from '@/app/styles/tokens';\nimport { AGENT_LABELS, type TaskKind, type TaskLogEntry } from '@/types/index';\nimport { Card, Stamp } from '@dendelion/paper-ui';\nimport { useSearch } from '@tanstack/react-router';\nimport { useEffect, useRef, useState } from 'react';\n\nconst TASK_KIND_LABELS: Record<TaskKind, string> = {\n phase: 'Phase run',\n audit: 'Audit',\n 'batch-reconcile': 'Batch reconcile',\n 'run-all': 'Run all phases',\n draft: 'Draft',\n extend: 'Extend',\n suggest: 'Suggest ideas',\n 'commit-suggest': 'Commit suggest',\n 'overlap-check': 'Overlap check',\n sync: 'Sync',\n reconcile: 'Reconcile',\n 'fix-review': 'Fix review',\n};\n\nconst pad = (n: number) => String(n).padStart(2, '0');\n\nconst dayKey = (iso: string) => {\n const d = new Date(iso);\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;\n};\n\nconst formatDayHeader = (iso: string) =>\n new Date(iso).toLocaleDateString(undefined, {\n weekday: 'long',\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n\nconst formatTime = (iso: string) => {\n const d = new Date(iso);\n return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;\n};\n\nconst headerLabelStyle: React.CSSProperties = {\n fontSize: fontSize.sm,\n fontWeight: 600,\n opacity: 0.6,\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n};\n\nconst TaskLogLines = ({ id }: { id: string }) => {\n const [lines, setLines] = useState<string[] | null>(null);\n\n useEffect(() => {\n setLines(null);\n fetchTaskLogLines(id)\n .then((data) => setLines(data.lines))\n .catch(() => setLines([]));\n }, [id]);\n\n if (lines === null) return <p style={{ opacity: 0.5, margin: 0 }}>Loading…</p>;\n if (lines.length === 0) return <p style={{ opacity: 0.5, margin: 0 }}>No output recorded.</p>;\n return (\n <pre\n style={{\n fontFamily: fontFamily.mono,\n fontSize: fontSize.xs,\n margin: 0,\n maxHeight: 320,\n overflowY: 'auto',\n whiteSpace: 'pre-wrap',\n }}\n >\n {lines.join('\\n')}\n </pre>\n );\n};\n\nconst ChevronRightIcon = ({ size = 14 }: { size?: number }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n);\n\nconst TaskRow = ({ entry, highlighted }: { entry: TaskLogEntry; highlighted: boolean }) => {\n const [expanded, setExpanded] = useState(highlighted);\n useEffect(() => {\n if (highlighted) setExpanded(true);\n }, [highlighted]);\n const toggle = () => setExpanded((v) => !v);\n\n return (\n <div\n className={highlighted ? 'task-row-highlighted' : undefined}\n style={{ display: 'flex', flexDirection: 'column', gap: space[1], borderRadius: 10 }}\n >\n {/* biome-ignore lint/a11y/useSemanticElements: the clickable row wraps a Card whose block layout a native <button> would break; keyboard toggling is wired on the div. */}\n <div\n role=\"button\"\n tabIndex={0}\n onClick={toggle}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n toggle();\n }\n }}\n style={{ cursor: 'pointer', borderRadius: 10 }}\n >\n <Card size=\"small\" texture=\"canvas\" className=\"plan-row-card\">\n <div className=\"task-rows-grid\">\n <span\n className=\"task-rows-chevron\"\n aria-expanded={expanded}\n style={{ display: 'inline-flex', alignItems: 'center', opacity: 0.5 }}\n >\n <ChevronRightIcon />\n </span>\n <span style={{ fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden' }}>\n {TASK_KIND_LABELS[entry.taskKind]}\n </span>\n <span\n style={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n opacity: 0.7,\n }}\n >\n {entry.planTitle}\n </span>\n <span className=\"text-sm\" style={{ opacity: 0.5, whiteSpace: 'nowrap' }}>\n {AGENT_LABELS[entry.agentId]}\n </span>\n <span\n className=\"task-rows-cell-time\"\n style={{\n fontFamily: fontFamily.mono,\n fontSize: fontSize.xs,\n opacity: 0.55,\n whiteSpace: 'nowrap',\n }}\n >\n {formatTime(entry.startedAt)}–{formatTime(entry.endedAt)}\n </span>\n <div style={{ display: 'flex', alignItems: 'center' }}>\n <Stamp\n size=\"small\"\n fillColor={\n entry.outcome === 'done'\n ? 'rgba(143, 185, 150, 0.25)'\n : 'rgba(201, 139, 139, 0.25)'\n }\n textColor={entry.outcome === 'done' ? color.accentGreenDark : color.accentRoseDark}\n >\n {entry.outcome}\n </Stamp>\n </div>\n </div>\n </Card>\n </div>\n {expanded && (\n <Card size=\"small\" texture=\"kraft\" className=\"plan-row-card\">\n <TaskLogLines id={entry.id} />\n </Card>\n )}\n </div>\n );\n};\n\nexport const TasksPage = () => {\n const taskLog = useAppStore((s) => s.taskLog);\n const taskLogLoading = useAppStore((s) => s.taskLogLoading);\n const loadTaskLog = useAppStore((s) => s.loadTaskLog);\n const { taskId } = useSearch({ from: '/tasks' });\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n loadTaskLog();\n }, [loadTaskLog]);\n\n useEffect(() => {\n if (!taskId) return;\n const row = containerRef.current?.querySelector('.task-row-highlighted');\n row?.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }, [taskId]);\n\n const sorted = [...taskLog].sort((a, b) => b.endedAt.localeCompare(a.endedAt));\n\n const groups: { key: string; entries: TaskLogEntry[] }[] = [];\n for (const entry of sorted) {\n const key = dayKey(entry.endedAt);\n const group = groups.at(-1);\n if (group?.key === key) group.entries.push(entry);\n else groups.push({ key, entries: [entry] });\n }\n\n return (\n <div ref={containerRef}>\n <PageTitle>Tasks</PageTitle>\n {taskLogLoading && <p style={{ opacity: 0.5 }}>Loading…</p>}\n {!taskLogLoading && sorted.length === 0 && (\n <p style={{ opacity: 0.5 }}>No tasks have run yet.</p>\n )}\n {!taskLogLoading && sorted.length > 0 && (\n <div style={{ display: 'flex', flexDirection: 'column', gap: space[1] }}>\n <Card size=\"small\" texture=\"kraft\" className=\"plan-row-card\">\n <div className=\"task-rows-grid\">\n <span />\n <span style={headerLabelStyle}>Task</span>\n <span style={headerLabelStyle}>Plan</span>\n <span style={headerLabelStyle}>Agent</span>\n <span className=\"task-rows-cell-time\" style={headerLabelStyle}>\n Time\n </span>\n <span style={headerLabelStyle}>Outcome</span>\n </div>\n </Card>\n {groups.map((group) => (\n <div\n key={group.key}\n style={{ display: 'flex', flexDirection: 'column', gap: space[1] }}\n >\n <Card size=\"small\" texture=\"kraft\" className=\"plan-row-card\">\n <span style={{ ...headerLabelStyle, opacity: 0.75 }}>\n {formatDayHeader(group.entries[0].endedAt)}\n </span>\n </Card>\n {group.entries.map((entry) => (\n <TaskRow key={entry.id} entry={entry} highlighted={entry.id === taskId} />\n ))}\n </div>\n ))}\n </div>\n )}\n </div>\n );\n};\n"],"names":["TASK_KIND_LABELS","pad","n","dayKey","iso","d","formatDayHeader","formatTime","headerLabelStyle","fontSize","TaskLogLines","id","lines","setLines","useState","useEffect","fetchTaskLogLines","data","jsx","fontFamily","ChevronRightIcon","size","TaskRow","entry","highlighted","expanded","setExpanded","toggle","v","jsxs","space","e","Card","AGENT_LABELS","Stamp","color","TasksPage","taskLog","useAppStore","s","taskLogLoading","loadTaskLog","taskId","useSearch","containerRef","useRef","row","_a","sorted","b","groups","key","group","PageTitle"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{u as m,t as I,r as h,g as D,j as e,J as L,s,Y as F,b as j,c as T,Z as v,F as B,G as H,a as _,H as C,P,f as R,M,p as w}from"./main-CyxblUnu.js";const g="__no-subject__",W=({horizonTitle:t,item:n,candidateName:l,onClose:o,onPromoted:d})=>{const x=m(r=>r.promoteRoadmapItem),a=m(r=>r.launchIdeaExtend),{subjects:f}=I(),[c,p]=h.useState(g),[i,u]=h.useState(!1),[y,b]=h.useState(null),{toast:z}=D();h.useEffect(()=>{n&&(p(l?n.name:g),u(!1),b(null))},[n,l]);const E=async()=>{if(!(!n||!t)){u(!0),b(null);try{const r=await x(t,n,c===g?void 0:c,l??void 0),k=m.getState().ideaEntries.find(S=>S.id===r);if(k)try{await a(r,B(k,t))}catch(S){z({title:"Idea created, but the refine agent failed to launch",description:H(S.message),variant:"error"})}d(),o()}catch(r){b(r.message)}finally{u(!1)}}};return e.jsx(L,{open:n!==null,onClose:o,title:l??(n==null?void 0:n.name)??"",size:"small",children:e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:s[4]},children:[!l&&e.jsx("p",{style:{margin:0,opacity:.8},children:n==null?void 0:n.description}),e.jsx("div",{children:e.jsx(F,{size:"small",value:c,onChange:p,disabled:i,options:[{value:g,label:"No subject"},...f.map(r=>({value:r,label:r}))]})}),y&&e.jsx("p",{style:{margin:0,color:T.accentRoseDark,fontSize:j.sm},children:y}),e.jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:s[2]},children:[e.jsx(v,{type:"button",variant:"ghost",onClick:o,disabled:i,children:"Cancel"}),e.jsx(v,{type:"button",variant:"primary",onClick:E,disabled:i,children:i?"Promoting…":"Promote to idea"})]})]})})},$=t=>{if(t.length===0)return null;const n=t.filter(d=>d.status==="done").length,l=t.filter(d=>d.status!=="done"&&d.status!=="dropped").length,o=[];return l>0&&o.push(`${l} in queue`),n>0&&o.push(`${n} shipped`),o.length>0?o.join(", "):null},A={fontFamily:R.handwritten,fontSize:j.md,fontWeight:600,opacity:.7,lineHeight:1,padding:`${s[2]} ${s[1]} 0`},J=({size:t=14})=>e.jsx("svg",{width:t,height:t,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:e.jsx("polyline",{points:"9 18 15 12 9 6"})}),q=({name:t,onPromote:n})=>e.jsx(w,{size:"small",texture:"kraft",className:"plan-row-card",children:e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:s[3]},children:[e.jsx("span",{style:{flex:1},children:t}),e.jsx(v,{type:"button",variant:"ghost",size:"small",onClick:n,children:"Promote to idea"})]})}),G=({item:t,graduated:n,onPromote:l,onPromoteCandidate:o,onViewGraduated:d})=>{const[x,a]=h.useState(!1),f=t.candidates.length>0,c=$(n);return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:s[1]},children:[e.jsx(w,{size:"small",texture:"canvas",className:"plan-row-card",children:e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:s[3]},children:[f&&e.jsx("button",{type:"button","aria-expanded":x,"aria-label":x?"Hide candidates":"Show candidates",onClick:()=>a(p=>!p),style:{display:"inline-flex",alignItems:"center",background:"none",border:"none",cursor:"pointer",opacity:.5,padding:0,transform:x?"rotate(90deg)":void 0},children:e.jsx(J,{})}),e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:s[1],flex:1},children:[e.jsx("span",{style:{fontWeight:600},children:t.name}),e.jsx("span",{style:{fontSize:j.sm,opacity:.7},children:t.description}),c&&e.jsx("button",{type:"button",onClick:d,style:{alignSelf:"flex-start",background:"none",border:"none",padding:0,cursor:"pointer",fontSize:j["2xs"],opacity:.65,textDecoration:"underline"},children:c})]}),e.jsx(v,{type:"button",variant:"ghost",size:"small",onClick:l,children:"Promote to idea"})]})}),f&&x&&e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:s[1],paddingLeft:s[6]},children:t.candidates.map(p=>e.jsx(q,{name:p,onPromote:()=>o(p)},p))})]})},O=()=>{const[t,n]=h.useState(null),[l,o]=h.useState(!0),[d,x]=h.useState(!1),[a,f]=h.useState(null),c=m(i=>i.plans),p=_();return h.useEffect(()=>{C().then(n).catch(()=>x(!0)).finally(()=>o(!1))},[]),l?e.jsxs("div",{children:[e.jsx(P,{children:"Roadmap"}),e.jsx("p",{style:{opacity:.5},children:"Loading…"})]}):d?e.jsxs("div",{children:[e.jsx(P,{children:"Roadmap"}),e.jsx("p",{style:{opacity:.5},children:"Couldn't load the roadmap — the server may need a restart to pick up new routes."})]}):!t||t.horizons.length===0?e.jsxs("div",{children:[e.jsx(P,{children:"Roadmap"}),e.jsx("p",{style:{opacity:.5},children:"No `ROADMAP.md` found at the project root."})]}):e.jsxs("div",{children:[e.jsxs("div",{style:{marginBottom:s[6],paddingBottom:s[4],borderBottom:"1px solid rgba(0, 0, 0, 0.08)"},children:[e.jsx("span",{style:{fontFamily:R.handwritten,fontSize:j.xs,fontWeight:600,opacity:.55},children:"The goal"}),e.jsx("div",{style:{fontFamily:R.serif,fontSize:j.lg,lineHeight:1.4,marginTop:s[2]},children:e.jsx(M,{children:t.goal})})]}),e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:s[6]},children:t.horizons.map(i=>e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:s[1]},children:[e.jsx("div",{style:A,children:i.title}),i.items.map(u=>e.jsx(G,{item:u,graduated:(c==null?void 0:c.entries.filter(y=>y.subject===u.name))??[],onPromote:()=>f({horizonTitle:i.title,item:u}),onPromoteCandidate:y=>f({horizonTitle:i.title,item:u,candidateName:y}),onViewGraduated:()=>p({to:"/",search:{subject:u.name}})},u.name))]},i.title))}),e.jsx(W,{horizonTitle:(a==null?void 0:a.horizonTitle)??null,item:(a==null?void 0:a.item)??null,candidateName:a==null?void 0:a.candidateName,onClose:()=>f(null),onPromoted:()=>C().then(n)})]})};export{O as RoadmapPage};
2
+ //# sourceMappingURL=index-CRRHTP77.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-CRRHTP77.js","sources":["../../../src/app/features/roadmap/promote-roadmap-item-modal.tsx","../../../src/app/features/roadmap/roadmap-page.tsx"],"sourcesContent":["import { buildRoadmapPromotePrompt } from '@/app/features/plans/prompts';\nimport { useProjectSubjects } from '@/app/hooks/use-project-subjects';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { color, fontSize, space } from '@/app/styles/tokens';\nimport { oneLineErrorSummary } from '@/app/utils/error-summary';\nimport type { RoadmapItem } from '@/types/index';\nimport { Button, Modal, Select, useToast } from '@dendelion/paper-ui';\nimport { useEffect, useState } from 'react';\n\nconst NO_SUBJECT = '__no-subject__';\n\ninterface PromoteRoadmapItemModalProps {\n horizonTitle: string | null;\n item: RoadmapItem | null;\n candidateName?: string | null;\n onClose: () => void;\n onPromoted: () => void;\n}\n\nexport const PromoteRoadmapItemModal = ({\n horizonTitle,\n item,\n candidateName,\n onClose,\n onPromoted,\n}: PromoteRoadmapItemModalProps) => {\n const promoteRoadmapItem = useAppStore((s) => s.promoteRoadmapItem);\n const launchIdeaExtend = useAppStore((s) => s.launchIdeaExtend);\n const { subjects } = useProjectSubjects();\n const [subject, setSubject] = useState(NO_SUBJECT);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const { toast } = useToast();\n\n useEffect(() => {\n if (item) {\n // A candidate defaults to its parent item's name — the \"big bet becomes a\n // Subject\" rule — but the picker still lets the user override it.\n setSubject(candidateName ? item.name : NO_SUBJECT);\n setLoading(false);\n setError(null);\n }\n }, [item, candidateName]);\n\n const handlePromote = async () => {\n if (!item || !horizonTitle) return;\n setLoading(true);\n setError(null);\n try {\n const id = await promoteRoadmapItem(\n horizonTitle,\n item,\n subject === NO_SUBJECT ? undefined : subject,\n candidateName ?? undefined,\n );\n const idea = useAppStore.getState().ideaEntries.find((e) => e.id === id);\n if (idea) {\n try {\n await launchIdeaExtend(id, buildRoadmapPromotePrompt(idea, horizonTitle));\n } catch (err) {\n // The idea was created either way — a failed refine launch just means\n // no background research ran, not that the promotion itself failed.\n toast({\n title: 'Idea created, but the refine agent failed to launch',\n description: oneLineErrorSummary((err as Error).message),\n variant: 'error',\n });\n }\n }\n onPromoted();\n onClose();\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <Modal\n open={item !== null}\n onClose={onClose}\n title={candidateName ?? item?.name ?? ''}\n size=\"small\"\n >\n <div style={{ display: 'flex', flexDirection: 'column', gap: space[4] }}>\n {!candidateName && <p style={{ margin: 0, opacity: 0.8 }}>{item?.description}</p>}\n <div>\n <Select\n size=\"small\"\n value={subject}\n onChange={setSubject}\n disabled={loading}\n options={[\n { value: NO_SUBJECT, label: 'No subject' },\n ...subjects.map((s) => ({ value: s, label: s })),\n ]}\n />\n </div>\n {error && (\n <p style={{ margin: 0, color: color.accentRoseDark, fontSize: fontSize.sm }}>{error}</p>\n )}\n <div style={{ display: 'flex', justifyContent: 'flex-end', gap: space[2] }}>\n <Button type=\"button\" variant=\"ghost\" onClick={onClose} disabled={loading}>\n Cancel\n </Button>\n <Button type=\"button\" variant=\"primary\" onClick={handlePromote} disabled={loading}>\n {loading ? 'Promoting…' : 'Promote to idea'}\n </Button>\n </div>\n </div>\n </Modal>\n );\n};\n","import { Markdown } from '@/app/components/markdown';\nimport { PageTitle } from '@/app/components/page-title';\nimport { fetchRoadmap } from '@/app/services/content/docs-api';\nimport { useAppStore } from '@/app/stores/app-store';\nimport { fontFamily, fontSize, space } from '@/app/styles/tokens';\nimport type { PlanEntry, Roadmap, RoadmapItem } from '@/types/index';\nimport { Button, Card } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\nimport { useEffect, useState } from 'react';\nimport { PromoteRoadmapItemModal } from './promote-roadmap-item-modal';\n\nconst graduationLabel = (graduated: PlanEntry[]): string | null => {\n if (graduated.length === 0) return null;\n const shipped = graduated.filter((p) => p.status === 'done').length;\n const queued = graduated.filter((p) => p.status !== 'done' && p.status !== 'dropped').length;\n const parts: string[] = [];\n if (queued > 0) parts.push(`${queued} in queue`);\n if (shipped > 0) parts.push(`${shipped} shipped`);\n return parts.length > 0 ? parts.join(', ') : null;\n};\n\nconst horizonHeaderStyle: React.CSSProperties = {\n fontFamily: fontFamily.handwritten,\n fontSize: fontSize.md,\n fontWeight: 600,\n opacity: 0.7,\n lineHeight: 1,\n padding: `${space[2]} ${space[1]} 0`,\n};\n\nconst ChevronRightIcon = ({ size = 14 }: { size?: number }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n);\n\nconst CandidateRow = ({\n name,\n onPromote,\n}: {\n name: string;\n onPromote: () => void;\n}) => (\n <Card size=\"small\" texture=\"kraft\" className=\"plan-row-card\">\n <div style={{ display: 'flex', alignItems: 'center', gap: space[3] }}>\n <span style={{ flex: 1 }}>{name}</span>\n <Button type=\"button\" variant=\"ghost\" size=\"small\" onClick={onPromote}>\n Promote to idea\n </Button>\n </div>\n </Card>\n);\n\nconst RoadmapItemRow = ({\n item,\n graduated,\n onPromote,\n onPromoteCandidate,\n onViewGraduated,\n}: {\n item: RoadmapItem;\n graduated: PlanEntry[];\n onPromote: () => void;\n onPromoteCandidate: (candidateName: string) => void;\n onViewGraduated: () => void;\n}) => {\n const [expanded, setExpanded] = useState(false);\n const hasCandidates = item.candidates.length > 0;\n const label = graduationLabel(graduated);\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: space[1] }}>\n <Card size=\"small\" texture=\"canvas\" className=\"plan-row-card\">\n <div style={{ display: 'flex', alignItems: 'center', gap: space[3] }}>\n {hasCandidates && (\n // Raw <button>: icon-only toggle, paper-ui Button doesn't offer this compact chrome.\n <button\n type=\"button\"\n aria-expanded={expanded}\n aria-label={expanded ? 'Hide candidates' : 'Show candidates'}\n onClick={() => setExpanded((v) => !v)}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n opacity: 0.5,\n padding: 0,\n transform: expanded ? 'rotate(90deg)' : undefined,\n }}\n >\n <ChevronRightIcon />\n </button>\n )}\n <div style={{ display: 'flex', flexDirection: 'column', gap: space[1], flex: 1 }}>\n <span style={{ fontWeight: 600 }}>{item.name}</span>\n <span style={{ fontSize: fontSize.sm, opacity: 0.7 }}>{item.description}</span>\n {label && (\n <button\n type=\"button\"\n onClick={onViewGraduated}\n style={{\n alignSelf: 'flex-start',\n background: 'none',\n border: 'none',\n padding: 0,\n cursor: 'pointer',\n fontSize: fontSize['2xs'],\n opacity: 0.65,\n textDecoration: 'underline',\n }}\n >\n {label}\n </button>\n )}\n </div>\n <Button type=\"button\" variant=\"ghost\" size=\"small\" onClick={onPromote}>\n Promote to idea\n </Button>\n </div>\n </Card>\n {hasCandidates && expanded && (\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: space[1],\n paddingLeft: space[6],\n }}\n >\n {item.candidates.map((candidateName) => (\n <CandidateRow\n key={candidateName}\n name={candidateName}\n onPromote={() => onPromoteCandidate(candidateName)}\n />\n ))}\n </div>\n )}\n </div>\n );\n};\n\nexport const RoadmapPage = () => {\n const [roadmap, setRoadmap] = useState<Roadmap | null>(null);\n const [loading, setLoading] = useState(true);\n const [loadFailed, setLoadFailed] = useState(false);\n const [promoting, setPromoting] = useState<{\n horizonTitle: string;\n item: RoadmapItem;\n candidateName?: string;\n } | null>(null);\n const plans = useAppStore((s) => s.plans);\n const navigate = useNavigate();\n\n useEffect(() => {\n fetchRoadmap()\n .then(setRoadmap)\n .catch(() => setLoadFailed(true))\n .finally(() => setLoading(false));\n }, []);\n\n if (loading) {\n return (\n <div>\n <PageTitle>Roadmap</PageTitle>\n <p style={{ opacity: 0.5 }}>Loading…</p>\n </div>\n );\n }\n\n if (loadFailed) {\n return (\n <div>\n <PageTitle>Roadmap</PageTitle>\n <p style={{ opacity: 0.5 }}>\n Couldn't load the roadmap — the server may need a restart to pick up new routes.\n </p>\n </div>\n );\n }\n\n if (!roadmap || roadmap.horizons.length === 0) {\n return (\n <div>\n <PageTitle>Roadmap</PageTitle>\n <p style={{ opacity: 0.5 }}>No `ROADMAP.md` found at the project root.</p>\n </div>\n );\n }\n\n return (\n <div>\n <div\n style={{\n marginBottom: space[6],\n paddingBottom: space[4],\n borderBottom: '1px solid rgba(0, 0, 0, 0.08)',\n }}\n >\n <span\n style={{\n fontFamily: fontFamily.handwritten,\n fontSize: fontSize.xs,\n fontWeight: 600,\n opacity: 0.55,\n }}\n >\n The goal\n </span>\n <div\n style={{\n fontFamily: fontFamily.serif,\n fontSize: fontSize.lg,\n lineHeight: 1.4,\n marginTop: space[2],\n }}\n >\n <Markdown>{roadmap.goal}</Markdown>\n </div>\n </div>\n <div style={{ display: 'flex', flexDirection: 'column', gap: space[6] }}>\n {roadmap.horizons.map((horizon) => (\n <div\n key={horizon.title}\n style={{ display: 'flex', flexDirection: 'column', gap: space[1] }}\n >\n <div style={horizonHeaderStyle}>{horizon.title}</div>\n {horizon.items.map((item) => (\n <RoadmapItemRow\n key={item.name}\n item={item}\n graduated={plans?.entries.filter((p) => p.subject === item.name) ?? []}\n onPromote={() => setPromoting({ horizonTitle: horizon.title, item })}\n onPromoteCandidate={(candidateName) =>\n setPromoting({ horizonTitle: horizon.title, item, candidateName })\n }\n onViewGraduated={() => navigate({ to: '/', search: { subject: item.name } })}\n />\n ))}\n </div>\n ))}\n </div>\n <PromoteRoadmapItemModal\n horizonTitle={promoting?.horizonTitle ?? null}\n item={promoting?.item ?? null}\n candidateName={promoting?.candidateName}\n onClose={() => setPromoting(null)}\n onPromoted={() => fetchRoadmap().then(setRoadmap)}\n />\n </div>\n );\n};\n"],"names":["NO_SUBJECT","PromoteRoadmapItemModal","horizonTitle","item","candidateName","onClose","onPromoted","promoteRoadmapItem","useAppStore","s","launchIdeaExtend","subjects","useProjectSubjects","subject","setSubject","useState","loading","setLoading","error","setError","toast","useToast","useEffect","handlePromote","id","idea","e","buildRoadmapPromotePrompt","err","oneLineErrorSummary","jsx","Modal","jsxs","space","Select","color","fontSize","Button","graduationLabel","graduated","shipped","p","queued","parts","horizonHeaderStyle","fontFamily","ChevronRightIcon","size","CandidateRow","name","onPromote","Card","RoadmapItemRow","onPromoteCandidate","onViewGraduated","expanded","setExpanded","hasCandidates","label","v","RoadmapPage","roadmap","setRoadmap","loadFailed","setLoadFailed","promoting","setPromoting","plans","navigate","useNavigate","fetchRoadmap","PageTitle","Markdown","horizon"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{r as u,g as E,i as G,k as W,j as e,s as n,m as _,p as M,Z as L,O as Y,b as S,n as b,q as C,A as N,t as J,X as T,K as Q,v as ee,w as K,P as te,x as se,c as ae,D as I,y as ie,z as B,Y as P,B as ne,a as le,o as U}from"./main-CyxblUnu.js";import{S as $}from"./sidebar-section-Ch50IaLb.js";function oe(t){if(t==="git")return{label:"Git",unlocks:"Commits, phase logging, branch creation",fix:o=>o.startsWith("Not inside")?"git init":'git config user.name "Your Name" && git config user.email you@example.com'};if(t==="gh")return{label:"GitHub CLI",unlocks:"PR badges, review flow, fix-review",fix:o=>o.includes("not found")?"Install: https://cli.github.com":o.includes("no origin remote")?"git remote add origin <url>":o.includes("not reachable")?"gh repo view":"gh auth login"};const s=t.slice(6);return{label:`${N[s]} CLI`,unlocks:`Launching ${N[s]} for phase runs, drafts, and reviews`,fix:()=>`Install the ${N[s]} CLI and add it to PATH`}}const re={ok:{fill:"rgba(143, 185, 150, 0.25)",text:"#5E8A66",label:"Ready"},warn:{fill:"rgba(212, 163, 115, 0.25)",text:"#A67B4F",label:"Needs attention"},missing:{fill:"rgba(201, 139, 139, 0.25)",text:"#6E3A3A",label:"Missing"}},de=({result:t,isLast:s,onRecheck:o,rechecking:p})=>{const h=oe(t.id),r=re[t.status],m=t.status!=="ok"?h.fix(t.detail):null;return e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{paddingBottom:n[3],paddingTop:n[3]},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:n[3]},children:[e.jsx("span",{style:{flex:1,fontWeight:500},children:h.label}),e.jsx(Y,{size:"small",fillColor:r.fill,textColor:r.text,children:r.label}),e.jsx(L,{size:"small",variant:"secondary",onClick:()=>o(t.id),disabled:p,children:p?"Checking…":"Recheck"})]}),e.jsxs("p",{style:{opacity:.65,fontSize:S.sm,margin:`${n[1]} 0 0`},children:["Unlocks: ",h.unlocks]}),e.jsx("p",{style:{opacity:.5,fontSize:S.sm,margin:`${n[1]} 0 0`},children:t.detail}),m&&e.jsx("code",{style:{display:"block",marginTop:n[2],padding:n[2],background:"rgba(0,0,0,0.06)",borderRadius:4,fontSize:S.sm},children:m})]}),!s&&e.jsx(b,{})]})},ce=()=>{const[t,s]=u.useState(null),[o,p]=u.useState(!1),[h,r]=u.useState(null),[m,x]=u.useState(!1),{toast:d}=E(),j=u.useCallback(a=>{if(a===null){p(!0);return}p(!1),s(a)},[]);u.useEffect(()=>{G().then(j),W().then(a=>x((a==null?void 0:a.setupDismissed)??!1))},[j]);const c=async a=>{r(a),j(await G()),r(null)},v=async()=>{const a=!m,{ok:g}=await C({setupDismissed:a});g?(x(a),d({title:"Saved",variant:"success"})):d({title:"Failed to save",variant:"error"})},w=(t==null?void 0:t.every(a=>a.status==="ok"))??!0;return e.jsxs("div",{children:[e.jsx("div",{style:{marginBottom:n[6]},children:e.jsx("h2",{style:{margin:0},children:"Setup"})}),t===null&&!o&&e.jsx("p",{children:"Loading…"}),o&&e.jsx("div",{style:{marginBottom:n[4]},children:e.jsx(_,{variant:"warning",children:"Failed to load capabilities. Try refreshing."})}),t&&e.jsxs(e.Fragment,{children:[!w&&e.jsx("div",{style:{marginBottom:n[4]},children:e.jsx(_,{variant:"warning",children:"Some capabilities are incomplete — features that depend on them stay disabled until fixed. Run the fix command in your terminal, then recheck."})}),e.jsx(M,{size:"small",children:t.map((a,g)=>e.jsx(de,{result:a,isLast:g===t.length-1,onRecheck:c,rechecking:h===a.id},a.id))}),e.jsx("div",{style:{marginTop:n[4]},children:e.jsx(L,{variant:"secondary",size:"small",onClick:v,children:m?"Show Setup on open again":"Don't show Setup on open"})})]})]})},ue=({name:t,isLast:s,onRename:o,onRemove:p})=>{const[h,r]=u.useState(t),{toast:m}=E(),x=async()=>{const d=h.trim();if(!d||d===t){r(t);return}await o(t,d)||(r(t),m({title:"Failed to rename",variant:"error"}))};return e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:n[3],paddingBottom:n[2],paddingTop:n[2]},children:[e.jsx(T,{size:"small",value:h,onChange:d=>r(d.target.value),onBlur:x,style:{flex:1}}),e.jsx(ee,{icon:e.jsx("span",{children:"×"}),variant:"ghost",size:"small",label:`Remove ${t}`,onClick:()=>p(t)})]}),!s&&e.jsx(b,{})]})},pe=()=>{const{subjects:t,loading:s,addSubject:o,renameSubject:p,removeSubject:h}=J(),[r,m]=u.useState(""),{toast:x}=E(),d=async()=>{const c=r.trim();if(!c)return;await o(c)?m(""):x({title:"Failed to add subject",variant:"error"})},j=async c=>{await h(c)||x({title:"Failed to remove subject",variant:"error"})};return e.jsxs("div",{children:[e.jsxs("div",{style:{marginBottom:n[6]},children:[e.jsx("h2",{style:{margin:0},children:"Subjects"}),e.jsx("p",{style:{opacity:.5,marginTop:n[1]},children:'Group ideas by subject. Removing one falls its ideas back to "No subject" — file contents are untouched.'})]}),s&&e.jsx("p",{children:"Loading…"}),!s&&e.jsxs(M,{size:"small",children:[t.length===0&&e.jsx("p",{style:{opacity:.45,margin:0,paddingBottom:n[2]},children:"No subjects yet."}),t.map((c,v)=>e.jsx(ue,{name:c,isLast:v===t.length-1,onRename:p,onRemove:j},c)),t.length>0&&e.jsx(b,{}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:n[3],paddingTop:n[3]},children:[e.jsx(T,{size:"small",placeholder:"New subject",value:r,onChange:c=>m(c.target.value),onKeyDown:c=>{c.key==="Enter"&&d()},style:{flex:1}}),e.jsxs(L,{variant:"secondary",size:"small",onClick:d,disabled:!r.trim(),children:[e.jsx(Q,{size:14})," Add"]})]})]})]})},H=["phase","planDraft","ideaExtend","commitSuggest"],he={phase:"Phase run",planDraft:"Plan draft",ideaExtend:"Idea extend",commitSuggest:"Commit suggest"},Z=110,X=140,O=160,q=110,me=()=>e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:n[3],paddingBottom:n[1]},children:[e.jsx("span",{style:{width:Z,flexShrink:0,fontSize:S.sm,opacity:.45},children:"Task"}),e.jsx("span",{style:{width:X,flexShrink:0,fontSize:S.sm,opacity:.45},children:"Agent"}),e.jsx("span",{style:{width:O,flexShrink:0,fontSize:S.sm,opacity:.45},children:"Model"}),e.jsx("span",{style:{width:q,flexShrink:0,fontSize:S.sm,opacity:.45},children:"Effort"})]}),ge=({taskKey:t,agentConfig:s,isLast:o,onSave:p})=>{const h=B[s.agent]??B["claude-code"],r=h.model,m=h.effort,[x,d]=u.useState(s.model??"");u.useEffect(()=>{d(s.model??"")},[s.model]);const j=a=>{var z;const g=a,k=B[g],A={agent:g};s.model&&(k.model===null||(z=k.model)!=null&&z.includes(s.model))&&(A.model=s.model),s.effort&&Array.isArray(k.effort)&&(A.effort=s.effort),p(t,A)},c=a=>{p(t,{...s,model:a||void 0})},v=()=>{p(t,{...s,model:x||void 0})},w=a=>{p(t,{...s,effort:a||void 0})};return e.jsxs(e.Fragment,{children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:n[3],paddingBottom:n[2],paddingTop:n[2]},children:[e.jsx("span",{style:{width:Z,flexShrink:0,fontSize:S.sm,opacity:.65},children:he[t]}),e.jsx(P,{size:"small",width:X,value:s.agent,onChange:j,options:ne.map(a=>({value:a,label:N[a]}))}),Array.isArray(r)?e.jsx(P,{size:"small",width:O,value:s.model??"",onChange:c,options:[{value:"",label:"Default"},...r.map(a=>({value:a,label:a}))]}):r===null?e.jsx(T,{size:"small",style:{width:O},value:x,placeholder:"Default model",onChange:a=>d(a.target.value),onBlur:v}):null,e.jsx("div",{style:{visibility:Array.isArray(m)?"visible":"hidden"},children:e.jsx(P,{size:"small",width:q,value:s.effort??"",onChange:w,options:[{value:"",label:"Default"},...(Array.isArray(m)?m:[]).map(a=>({value:a,label:a}))]})})]}),!o&&e.jsx(b,{})]})},xe=()=>{const t=u.useRef(null),[s,o]=u.useState(void 0),{iconDataUri:p,loading:h}=se(),[r,m]=u.useState(null),x=r??p,[d,j]=u.useState(!1),[c,v]=u.useState(""),[w,a]=u.useState(""),{toast:g}=E();u.useEffect(()=>{W().then(i=>{o(i),(i==null?void 0:i.port)!==void 0&&v(String(i.port)),(i==null?void 0:i.projectName)!==void 0&&a(i.projectName)})},[]);const k=async(i,y)=>{const l=s==null?void 0:s.defaultAgents,f={phase:(l==null?void 0:l.phase)??I.phase,planDraft:(l==null?void 0:l.planDraft)??I.planDraft,ideaExtend:(l==null?void 0:l.ideaExtend)??I.ideaExtend,commitSuggest:(l==null?void 0:l.commitSuggest)??I.commitSuggest,[i]:y},{ok:D,error:F}=await C({defaultAgents:f});D?(o(R=>R&&{...R,defaultAgents:f}),g({title:"Saved",variant:"success"})):g({title:"Failed to save",description:F,variant:"error"})},A=async()=>{const i=Number(c);if(!s||!Number.isInteger(i)||i<=0||i===s.port)return;const{ok:y,error:l}=await C({port:i});y?(o(f=>f&&{...f,port:i}),g({title:"Saved",variant:"success"})):g({title:"Failed to save",description:l,variant:"error"})},z=async()=>{const i=w.trim();if(!s||!i||i===s.projectName)return;const{ok:y,error:l}=await C({projectName:i});y?(o(f=>f&&{...f,projectName:i}),a(i),g({title:"Saved",variant:"success"})):g({title:"Failed to save",description:l,variant:"error"})},V=async i=>{var f;const y=(f=i.target.files)==null?void 0:f[0];if(!y)return;j(!0);const l=new FileReader;l.onloadend=async()=>{const D=l.result,F=await ie(D);j(!1),F?(m(D),g({title:"Saved",variant:"success"})):g({title:"Failed to save",variant:"error"})},l.readAsDataURL(y)};return e.jsxs("div",{children:[e.jsx("div",{style:{marginBottom:n[6]},children:e.jsx("h2",{style:{margin:0},children:"Project Info"})}),s===void 0&&e.jsx("p",{children:"Loading…"}),s===null&&e.jsxs(_,{variant:"warning",children:["No papercamp/config.json found — run ",e.jsx("code",{children:"paper-camp init"})," in this directory first."]}),s&&e.jsxs(M,{size:"small",children:[e.jsxs("div",{style:{display:"flex",alignItems:"flex-end",gap:n[3],paddingBottom:n[3]},children:[e.jsx(T,{value:w,onChange:i=>a(i.target.value),onBlur:z,label:"Project Name"}),e.jsxs(Y,{size:"small",fillColor:"rgba(143, 185, 150, 0.25)",textColor:ae.accentGreenDark,children:["v",s.version]})]}),e.jsx(b,{}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:n[3],paddingBottom:n[3],paddingTop:n[3]},children:[x&&e.jsx("img",{src:x,alt:"Project icon",style:{width:40,height:40,objectFit:"contain",flexShrink:0,borderRadius:4}}),e.jsxs("div",{children:[e.jsx("input",{ref:t,type:"file",accept:".svg,.png,.jpg,.jpeg,.gif,.webp",onChange:V,style:{display:"none"}}),e.jsx(L,{variant:"secondary",size:"small",onClick:()=>{var i;return(i=t.current)==null?void 0:i.click()},disabled:d,children:d?"Uploading…":"Choose File"}),h&&e.jsx("p",{className:"text-sm",style:{opacity:.5,margin:`${n[1]} 0 0`},children:"Loading…"}),!h&&!x&&!d&&e.jsx("p",{className:"text-sm",style:{opacity:.45,margin:`${n[1]} 0 0`},children:"No icon set."})]})]}),e.jsx(b,{}),e.jsx("div",{style:{display:"flex",alignItems:"flex-end",gap:n[3],paddingBottom:n[3],paddingTop:n[3]},children:e.jsx(T,{type:"number",value:c,onChange:i=>v(i.target.value),onBlur:A,label:"Port",helperText:"Default for `paper-camp dev`. Does not affect the running server."})}),e.jsx(b,{}),e.jsx(me,{}),H.map((i,y)=>{var l;return e.jsx(ge,{taskKey:i,agentConfig:((l=s.defaultAgents)==null?void 0:l[i])??I[i],isLast:y===H.length-1,onSave:k},i)})]}),e.jsxs("p",{style:{opacity:.45,fontSize:S.sm,marginTop:n[4]},children:[e.jsx("strong",{children:"Initialized:"})," ",s?new Date(s.initializedAt).toLocaleString():"—"]})]})},ve=()=>{const t=K();return e.jsxs("div",{children:[e.jsx(te,{children:"Settings"}),t==="subjects"?e.jsx(pe,{}):t==="setup"?e.jsx(ce,{}):e.jsx(xe,{})]})},ye=()=>{const t=K(),s=le();return e.jsxs(e.Fragment,{children:[e.jsxs($,{label:"General",children:[e.jsx(U,{size:"small",active:t===null,onClick:()=>s({to:"/settings"}),children:"Project Info"}),e.jsx(U,{size:"small",active:t==="setup",onClick:()=>s({to:"/settings/$section",params:{section:"setup"}}),children:"Setup"})]}),e.jsx($,{label:"Ideas",children:e.jsx(U,{size:"small",active:t==="subjects",onClick:()=>s({to:"/settings/$section",params:{section:"subjects"}}),children:"Subjects"})})]})};export{ve as SettingsPage,ye as SettingsSidebar};
2
+ //# sourceMappingURL=index-DrNAzLuW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-DrNAzLuW.js","sources":["../../../src/app/features/settings/components/setup-section.tsx","../../../src/app/features/settings/components/subjects-section.tsx","../../../src/app/features/settings/settings-page.tsx","../../../src/app/features/settings/components/settings-sidebar.tsx"],"sourcesContent":["import { fetchCapabilities, fetchConfig, saveConfig } from '@/app/services/system';\nimport { fontSize, space } from '@/app/styles/tokens';\nimport {\n AGENT_LABELS,\n type AgentId,\n type CapabilityResult,\n type CapabilityStatus,\n} from '@/types/index';\nimport { Alert, Button, Card, Divider, Stamp, useToast } from '@dendelion/paper-ui';\nimport { useCallback, useEffect, useState } from 'react';\n\ninterface CapabilityMeta {\n label: string;\n unlocks: string;\n fix: (detail: string) => string;\n}\n\nfunction capabilityMeta(id: string): CapabilityMeta {\n if (id === 'git') {\n return {\n label: 'Git',\n unlocks: 'Commits, phase logging, branch creation',\n fix: (detail) =>\n detail.startsWith('Not inside')\n ? 'git init'\n : 'git config user.name \"Your Name\" && git config user.email you@example.com',\n };\n }\n if (id === 'gh') {\n return {\n label: 'GitHub CLI',\n unlocks: 'PR badges, review flow, fix-review',\n fix: (detail) => {\n if (detail.includes('not found')) return 'Install: https://cli.github.com';\n if (detail.includes('no origin remote')) return 'git remote add origin <url>';\n if (detail.includes('not reachable')) return 'gh repo view';\n return 'gh auth login';\n },\n };\n }\n const agentId = id.slice('agent:'.length) as AgentId;\n return {\n label: `${AGENT_LABELS[agentId]} CLI`,\n unlocks: `Launching ${AGENT_LABELS[agentId]} for phase runs, drafts, and reviews`,\n fix: () => `Install the ${AGENT_LABELS[agentId]} CLI and add it to PATH`,\n };\n}\n\nconst STATUS_STAMP: Record<CapabilityStatus, { fill: string; text: string; label: string }> = {\n ok: { fill: 'rgba(143, 185, 150, 0.25)', text: '#5E8A66', label: 'Ready' },\n warn: { fill: 'rgba(212, 163, 115, 0.25)', text: '#A67B4F', label: 'Needs attention' },\n missing: { fill: 'rgba(201, 139, 139, 0.25)', text: '#6E3A3A', label: 'Missing' },\n};\n\nconst CapabilityRow = ({\n result,\n isLast,\n onRecheck,\n rechecking,\n}: {\n result: CapabilityResult;\n isLast: boolean;\n onRecheck: (id: string) => void;\n rechecking: boolean;\n}) => {\n const meta = capabilityMeta(result.id);\n const stamp = STATUS_STAMP[result.status];\n const fix = result.status !== 'ok' ? meta.fix(result.detail) : null;\n return (\n <>\n <div style={{ paddingBottom: space[3], paddingTop: space[3] }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: space[3] }}>\n <span style={{ flex: 1, fontWeight: 500 }}>{meta.label}</span>\n <Stamp size=\"small\" fillColor={stamp.fill} textColor={stamp.text}>\n {stamp.label}\n </Stamp>\n <Button\n size=\"small\"\n variant=\"secondary\"\n onClick={() => onRecheck(result.id)}\n disabled={rechecking}\n >\n {rechecking ? 'Checking…' : 'Recheck'}\n </Button>\n </div>\n <p style={{ opacity: 0.65, fontSize: fontSize.sm, margin: `${space[1]} 0 0` }}>\n Unlocks: {meta.unlocks}\n </p>\n <p style={{ opacity: 0.5, fontSize: fontSize.sm, margin: `${space[1]} 0 0` }}>\n {result.detail}\n </p>\n {fix && (\n <code\n style={{\n display: 'block',\n marginTop: space[2],\n padding: space[2],\n background: 'rgba(0,0,0,0.06)',\n borderRadius: 4,\n fontSize: fontSize.sm,\n }}\n >\n {fix}\n </code>\n )}\n </div>\n {!isLast && <Divider />}\n </>\n );\n};\n\nexport const SetupSection = () => {\n const [capabilities, setCapabilities] = useState<CapabilityResult[] | null>(null);\n const [loadFailed, setLoadFailed] = useState(false);\n const [reloadingId, setReloadingId] = useState<string | null>(null);\n const [setupDismissed, setSetupDismissed] = useState(false);\n const { toast } = useToast();\n\n const applyCapabilities = useCallback((result: CapabilityResult[] | null) => {\n if (result === null) {\n setLoadFailed(true);\n return;\n }\n setLoadFailed(false);\n setCapabilities(result);\n }, []);\n\n useEffect(() => {\n fetchCapabilities().then(applyCapabilities);\n fetchConfig().then((c) => setSetupDismissed(c?.setupDismissed ?? false));\n }, [applyCapabilities]);\n\n const handleRecheck = async (id: string) => {\n setReloadingId(id);\n applyCapabilities(await fetchCapabilities());\n setReloadingId(null);\n };\n\n const handleDismissToggle = async () => {\n const next = !setupDismissed;\n const { ok } = await saveConfig({ setupDismissed: next });\n if (ok) {\n setSetupDismissed(next);\n toast({ title: 'Saved', variant: 'success' });\n } else {\n toast({ title: 'Failed to save', variant: 'error' });\n }\n };\n\n const allOk = capabilities?.every((c) => c.status === 'ok') ?? true;\n\n return (\n <div>\n <div style={{ marginBottom: space[6] }}>\n <h2 style={{ margin: 0 }}>Setup</h2>\n </div>\n {capabilities === null && !loadFailed && <p>Loading…</p>}\n {loadFailed && (\n <div style={{ marginBottom: space[4] }}>\n <Alert variant=\"warning\">Failed to load capabilities. Try refreshing.</Alert>\n </div>\n )}\n {capabilities && (\n <>\n {!allOk && (\n <div style={{ marginBottom: space[4] }}>\n <Alert variant=\"warning\">\n Some capabilities are incomplete — features that depend on them stay disabled until\n fixed. Run the fix command in your terminal, then recheck.\n </Alert>\n </div>\n )}\n <Card size=\"small\">\n {capabilities.map((c, idx) => (\n <CapabilityRow\n key={c.id}\n result={c}\n isLast={idx === capabilities.length - 1}\n onRecheck={handleRecheck}\n rechecking={reloadingId === c.id}\n />\n ))}\n </Card>\n <div style={{ marginTop: space[4] }}>\n <Button variant=\"secondary\" size=\"small\" onClick={handleDismissToggle}>\n {setupDismissed ? 'Show Setup on open again' : \"Don't show Setup on open\"}\n </Button>\n </div>\n </>\n )}\n </div>\n );\n};\n","import { useProjectSubjects } from '@/app/hooks';\nimport { space } from '@/app/styles/tokens';\nimport { Button, Card, Divider, IconButton, Input, PlusIcon, useToast } from '@dendelion/paper-ui';\nimport { useState } from 'react';\n\nconst SubjectRow = ({\n name,\n isLast,\n onRename,\n onRemove,\n}: {\n name: string;\n isLast: boolean;\n onRename: (from: string, to: string) => Promise<boolean>;\n onRemove: (name: string) => Promise<void>;\n}) => {\n const [value, setValue] = useState(name);\n const { toast } = useToast();\n\n const handleBlur = async () => {\n const trimmed = value.trim();\n if (!trimmed || trimmed === name) {\n setValue(name);\n return;\n }\n const ok = await onRename(name, trimmed);\n if (!ok) {\n setValue(name);\n toast({ title: 'Failed to rename', variant: 'error' });\n }\n };\n\n return (\n <>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: space[3],\n paddingBottom: space[2],\n paddingTop: space[2],\n }}\n >\n <Input\n size=\"small\"\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onBlur={handleBlur}\n style={{ flex: 1 }}\n />\n <IconButton\n icon={<span>×</span>}\n variant=\"ghost\"\n size=\"small\"\n label={`Remove ${name}`}\n onClick={() => onRemove(name)}\n />\n </div>\n {!isLast && <Divider />}\n </>\n );\n};\n\nexport const SubjectsSection = () => {\n const { subjects, loading, addSubject, renameSubject, removeSubject } = useProjectSubjects();\n const [newSubject, setNewSubject] = useState('');\n const { toast } = useToast();\n\n const handleAdd = async () => {\n const trimmed = newSubject.trim();\n if (!trimmed) return;\n const ok = await addSubject(trimmed);\n if (ok) setNewSubject('');\n else toast({ title: 'Failed to add subject', variant: 'error' });\n };\n\n const handleRemove = async (name: string) => {\n const ok = await removeSubject(name);\n if (!ok) toast({ title: 'Failed to remove subject', variant: 'error' });\n };\n\n return (\n <div>\n <div style={{ marginBottom: space[6] }}>\n <h2 style={{ margin: 0 }}>Subjects</h2>\n <p style={{ opacity: 0.5, marginTop: space[1] }}>\n Group ideas by subject. Removing one falls its ideas back to \"No subject\" — file contents\n are untouched.\n </p>\n </div>\n {loading && <p>Loading…</p>}\n {!loading && (\n <Card size=\"small\">\n {subjects.length === 0 && (\n <p style={{ opacity: 0.45, margin: 0, paddingBottom: space[2] }}>No subjects yet.</p>\n )}\n {subjects.map((name, idx) => (\n <SubjectRow\n key={name}\n name={name}\n isLast={idx === subjects.length - 1}\n onRename={renameSubject}\n onRemove={handleRemove}\n />\n ))}\n {subjects.length > 0 && <Divider />}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: space[3],\n paddingTop: space[3],\n }}\n >\n <Input\n size=\"small\"\n placeholder=\"New subject\"\n value={newSubject}\n onChange={(e) => setNewSubject(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') handleAdd();\n }}\n style={{ flex: 1 }}\n />\n <Button\n variant=\"secondary\"\n size=\"small\"\n onClick={handleAdd}\n disabled={!newSubject.trim()}\n >\n <PlusIcon size={14} /> Add\n </Button>\n </div>\n </Card>\n )}\n </div>\n );\n};\n","import { PageTitle } from '@/app/components/page-title';\nimport { useActiveSettingsSection, useProjectIdentity } from '@/app/hooks';\nimport { fetchConfig, saveConfig, uploadIcon } from '@/app/services/system';\nimport { color, fontFamily, fontSize, space } from '@/app/styles/tokens';\nimport {\n AGENT_IDS,\n AGENT_LABELS,\n AGENT_OPTIONS,\n type AgentConfig,\n type AgentId,\n DEFAULT_AGENTS,\n type DefaultAgentsMap,\n type PaperCampConfig,\n} from '@/types/index';\nimport { Alert, Button, Card, Divider, Input, Select, Stamp, useToast } from '@dendelion/paper-ui';\nimport { useEffect, useRef, useState } from 'react';\nimport { SetupSection } from './components/setup-section';\nimport { SubjectsSection } from './components/subjects-section';\n\nconst TASK_TYPE_KEYS = ['phase', 'planDraft', 'ideaExtend', 'commitSuggest'] as const;\ntype TaskTypeKey = (typeof TASK_TYPE_KEYS)[number];\n\nconst TASK_TYPE_LABELS: Record<TaskTypeKey, string> = {\n phase: 'Phase run',\n planDraft: 'Plan draft',\n ideaExtend: 'Idea extend',\n commitSuggest: 'Commit suggest',\n};\n\ninterface AgentTaskRowProps {\n taskKey: TaskTypeKey;\n agentConfig: AgentConfig;\n isLast: boolean;\n onSave: (key: TaskTypeKey, config: AgentConfig) => Promise<void>;\n}\n\nconst TASK_COLUMN_WIDTH = 110;\nconst AGENT_COLUMN_WIDTH = 140;\nconst MODEL_COLUMN_WIDTH = 160;\nconst EFFORT_COLUMN_WIDTH = 110;\n\nconst AgentTaskRowHeader = () => (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: space[3],\n paddingBottom: space[1],\n }}\n >\n <span style={{ width: TASK_COLUMN_WIDTH, flexShrink: 0, fontSize: fontSize.sm, opacity: 0.45 }}>\n Task\n </span>\n <span\n style={{ width: AGENT_COLUMN_WIDTH, flexShrink: 0, fontSize: fontSize.sm, opacity: 0.45 }}\n >\n Agent\n </span>\n <span\n style={{ width: MODEL_COLUMN_WIDTH, flexShrink: 0, fontSize: fontSize.sm, opacity: 0.45 }}\n >\n Model\n </span>\n <span\n style={{ width: EFFORT_COLUMN_WIDTH, flexShrink: 0, fontSize: fontSize.sm, opacity: 0.45 }}\n >\n Effort\n </span>\n </div>\n);\n\nconst AgentTaskRow = ({ taskKey, agentConfig, isLast, onSave }: AgentTaskRowProps) => {\n // Fall back if the config carries an unknown agent id — never white-screen the page.\n const opts = AGENT_OPTIONS[agentConfig.agent] ?? AGENT_OPTIONS['claude-code'];\n const modelOpts = opts.model;\n const effortOpts = opts.effort;\n const [localModel, setLocalModel] = useState(agentConfig.model ?? '');\n\n useEffect(() => {\n setLocalModel(agentConfig.model ?? '');\n }, [agentConfig.model]);\n\n const handleAgentChange = (v: string) => {\n const newId = v as AgentId;\n const newOpts = AGENT_OPTIONS[newId];\n const newConfig: AgentConfig = { agent: newId };\n // Only carry the model over if the new agent accepts it — otherwise a claude\n // model like 'opus' would leak into opencode and fail at launch.\n if (\n agentConfig.model &&\n (newOpts.model === null || newOpts.model?.includes(agentConfig.model))\n ) {\n newConfig.model = agentConfig.model;\n }\n if (agentConfig.effort && Array.isArray(newOpts.effort)) newConfig.effort = agentConfig.effort;\n onSave(taskKey, newConfig);\n };\n\n const handleModelSelectChange = (v: string) => {\n onSave(taskKey, { ...agentConfig, model: v || undefined });\n };\n\n const handleModelInputBlur = () => {\n onSave(taskKey, { ...agentConfig, model: localModel || undefined });\n };\n\n const handleEffortChange = (v: string) => {\n onSave(taskKey, { ...agentConfig, effort: v || undefined });\n };\n\n return (\n <>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: space[3],\n paddingBottom: space[2],\n paddingTop: space[2],\n }}\n >\n <span\n style={{ width: TASK_COLUMN_WIDTH, flexShrink: 0, fontSize: fontSize.sm, opacity: 0.65 }}\n >\n {TASK_TYPE_LABELS[taskKey]}\n </span>\n <Select\n size=\"small\"\n width={AGENT_COLUMN_WIDTH}\n value={agentConfig.agent}\n onChange={handleAgentChange}\n options={AGENT_IDS.map((id) => ({ value: id, label: AGENT_LABELS[id] }))}\n />\n {Array.isArray(modelOpts) ? (\n <Select\n size=\"small\"\n width={MODEL_COLUMN_WIDTH}\n value={agentConfig.model ?? ''}\n onChange={handleModelSelectChange}\n options={[\n { value: '', label: 'Default' },\n ...modelOpts.map((m) => ({ value: m, label: m })),\n ]}\n />\n ) : modelOpts === null ? (\n <Input\n size=\"small\"\n style={{ width: MODEL_COLUMN_WIDTH }}\n value={localModel}\n placeholder=\"Default model\"\n onChange={(e) => setLocalModel(e.target.value)}\n onBlur={handleModelInputBlur}\n />\n ) : null}\n {/* Reserve the effort slot even when the agent has no effort options, so\n switching agents doesn't change the control count and shift the row. */}\n <div style={{ visibility: Array.isArray(effortOpts) ? 'visible' : 'hidden' }}>\n <Select\n size=\"small\"\n width={EFFORT_COLUMN_WIDTH}\n value={agentConfig.effort ?? ''}\n onChange={handleEffortChange}\n options={[\n { value: '', label: 'Default' },\n ...(Array.isArray(effortOpts) ? effortOpts : []).map((e) => ({ value: e, label: e })),\n ]}\n />\n </div>\n </div>\n {!isLast && <Divider />}\n </>\n );\n};\n\nconst GeneralSection = () => {\n const fileRef = useRef<HTMLInputElement>(null);\n const [config, setConfig] = useState<PaperCampConfig | null | undefined>(undefined);\n const { iconDataUri: fetchedIconDataUri, loading: identityLoading } = useProjectIdentity();\n const [uploadedIconDataUri, setUploadedIconDataUri] = useState<string | null>(null);\n const iconDataUri = uploadedIconDataUri ?? fetchedIconDataUri;\n const [uploading, setUploading] = useState(false);\n const [portInput, setPortInput] = useState('');\n const [nameInput, setNameInput] = useState('');\n const { toast } = useToast();\n\n useEffect(() => {\n fetchConfig().then((c) => {\n setConfig(c);\n if (c?.port !== undefined) setPortInput(String(c.port));\n if (c?.projectName !== undefined) setNameInput(c.projectName);\n });\n }, []);\n\n const handleSaveAgentConfig = async (key: TaskTypeKey, newEntry: AgentConfig) => {\n const current = config?.defaultAgents;\n const updated: DefaultAgentsMap = {\n phase: current?.phase ?? DEFAULT_AGENTS.phase,\n planDraft: current?.planDraft ?? DEFAULT_AGENTS.planDraft,\n ideaExtend: current?.ideaExtend ?? DEFAULT_AGENTS.ideaExtend,\n commitSuggest: current?.commitSuggest ?? DEFAULT_AGENTS.commitSuggest,\n [key]: newEntry,\n };\n const { ok, error } = await saveConfig({ defaultAgents: updated });\n if (ok) {\n setConfig((prev) => (prev ? { ...prev, defaultAgents: updated } : prev));\n toast({ title: 'Saved', variant: 'success' });\n } else {\n toast({ title: 'Failed to save', description: error, variant: 'error' });\n }\n };\n\n const handleSavePort = async () => {\n const port = Number(portInput);\n if (!config || !Number.isInteger(port) || port <= 0 || port === config.port) return;\n const { ok, error } = await saveConfig({ port });\n if (ok) {\n setConfig((prev) => (prev ? { ...prev, port } : prev));\n toast({ title: 'Saved', variant: 'success' });\n } else {\n toast({ title: 'Failed to save', description: error, variant: 'error' });\n }\n };\n\n const handleSaveName = async () => {\n const projectName = nameInput.trim();\n if (!config || !projectName || projectName === config.projectName) return;\n const { ok, error } = await saveConfig({ projectName });\n if (ok) {\n setConfig((prev) => (prev ? { ...prev, projectName } : prev));\n setNameInput(projectName);\n toast({ title: 'Saved', variant: 'success' });\n } else {\n toast({ title: 'Failed to save', description: error, variant: 'error' });\n }\n };\n\n const handleFile = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n setUploading(true);\n const reader = new FileReader();\n reader.onloadend = async () => {\n const dataUri = reader.result as string;\n const ok = await uploadIcon(dataUri);\n setUploading(false);\n if (ok) {\n setUploadedIconDataUri(dataUri);\n toast({ title: 'Saved', variant: 'success' });\n } else {\n toast({ title: 'Failed to save', variant: 'error' });\n }\n };\n reader.readAsDataURL(file);\n };\n\n return (\n <div>\n <div style={{ marginBottom: space[6] }}>\n <h2 style={{ margin: 0 }}>Project Info</h2>\n </div>\n {config === undefined && <p>Loading…</p>}\n {config === null && (\n <Alert variant=\"warning\">\n No papercamp/config.json found — run <code>paper-camp init</code> in this directory first.\n </Alert>\n )}\n {config && (\n <Card size=\"small\">\n <div\n style={{\n display: 'flex',\n alignItems: 'flex-end',\n gap: space[3],\n paddingBottom: space[3],\n }}\n >\n <Input\n value={nameInput}\n onChange={(e) => setNameInput(e.target.value)}\n onBlur={handleSaveName}\n label=\"Project Name\"\n />\n <Stamp\n size=\"small\"\n fillColor=\"rgba(143, 185, 150, 0.25)\"\n textColor={color.accentGreenDark}\n >\n v{config.version}\n </Stamp>\n </div>\n <Divider />\n\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: space[3],\n paddingBottom: space[3],\n paddingTop: space[3],\n }}\n >\n {iconDataUri && (\n <img\n src={iconDataUri}\n alt=\"Project icon\"\n style={{\n width: 40,\n height: 40,\n objectFit: 'contain',\n flexShrink: 0,\n borderRadius: 4,\n }}\n />\n )}\n <div>\n {/* paper-ui has no file-input component, so this raw input is intentional */}\n <input\n ref={fileRef}\n type=\"file\"\n accept=\".svg,.png,.jpg,.jpeg,.gif,.webp\"\n onChange={handleFile}\n style={{ display: 'none' }}\n />\n <Button\n variant=\"secondary\"\n size=\"small\"\n onClick={() => fileRef.current?.click()}\n disabled={uploading}\n >\n {uploading ? 'Uploading…' : 'Choose File'}\n </Button>\n {identityLoading && (\n <p className=\"text-sm\" style={{ opacity: 0.5, margin: `${space[1]} 0 0` }}>\n Loading…\n </p>\n )}\n {!identityLoading && !iconDataUri && !uploading && (\n <p className=\"text-sm\" style={{ opacity: 0.45, margin: `${space[1]} 0 0` }}>\n No icon set.\n </p>\n )}\n </div>\n </div>\n <Divider />\n\n <div\n style={{\n display: 'flex',\n alignItems: 'flex-end',\n gap: space[3],\n paddingBottom: space[3],\n paddingTop: space[3],\n }}\n >\n <Input\n type=\"number\"\n value={portInput}\n onChange={(e) => setPortInput(e.target.value)}\n onBlur={handleSavePort}\n label=\"Port\"\n helperText=\"Default for `paper-camp dev`. Does not affect the running server.\"\n />\n </div>\n <Divider />\n\n <AgentTaskRowHeader />\n {TASK_TYPE_KEYS.map((key, idx) => (\n <AgentTaskRow\n key={key}\n taskKey={key}\n agentConfig={config.defaultAgents?.[key] ?? DEFAULT_AGENTS[key]}\n isLast={idx === TASK_TYPE_KEYS.length - 1}\n onSave={handleSaveAgentConfig}\n />\n ))}\n </Card>\n )}\n\n <p style={{ opacity: 0.45, fontSize: fontSize.sm, marginTop: space[4] }}>\n <strong>Initialized:</strong>{' '}\n {config ? new Date(config.initializedAt).toLocaleString() : '—'}\n </p>\n </div>\n );\n};\n\nexport const SettingsPage = () => {\n const section = useActiveSettingsSection();\n return (\n <div>\n <PageTitle>Settings</PageTitle>\n {section === 'subjects' ? (\n <SubjectsSection />\n ) : section === 'setup' ? (\n <SetupSection />\n ) : (\n <GeneralSection />\n )}\n </div>\n );\n};\n","import { useActiveSettingsSection } from '@/app/hooks';\nimport { ListItem } from '@dendelion/paper-ui';\nimport { useNavigate } from '@tanstack/react-router';\nimport { SidebarSection } from '../../plans/components/sidebar-section';\n\nexport const SettingsSidebar = () => {\n const section = useActiveSettingsSection();\n const navigate = useNavigate();\n\n return (\n <>\n <SidebarSection label=\"General\">\n <ListItem\n size=\"small\"\n active={section === null}\n onClick={() => navigate({ to: '/settings' })}\n >\n Project Info\n </ListItem>\n <ListItem\n size=\"small\"\n active={section === 'setup'}\n onClick={() => navigate({ to: '/settings/$section', params: { section: 'setup' } })}\n >\n Setup\n </ListItem>\n </SidebarSection>\n <SidebarSection label=\"Ideas\">\n <ListItem\n size=\"small\"\n active={section === 'subjects'}\n onClick={() => navigate({ to: '/settings/$section', params: { section: 'subjects' } })}\n >\n Subjects\n </ListItem>\n </SidebarSection>\n </>\n );\n};\n"],"names":["capabilityMeta","id","detail","agentId","AGENT_LABELS","STATUS_STAMP","CapabilityRow","result","isLast","onRecheck","rechecking","meta","stamp","fix","jsxs","Fragment","space","jsx","Stamp","Button","fontSize","Divider","SetupSection","capabilities","setCapabilities","useState","loadFailed","setLoadFailed","reloadingId","setReloadingId","setupDismissed","setSetupDismissed","toast","useToast","applyCapabilities","useCallback","useEffect","fetchCapabilities","fetchConfig","c","handleRecheck","handleDismissToggle","next","ok","saveConfig","allOk","Alert","Card","idx","SubjectRow","name","onRename","onRemove","value","setValue","handleBlur","trimmed","Input","e","IconButton","SubjectsSection","subjects","loading","addSubject","renameSubject","removeSubject","useProjectSubjects","newSubject","setNewSubject","handleAdd","handleRemove","PlusIcon","TASK_TYPE_KEYS","TASK_TYPE_LABELS","TASK_COLUMN_WIDTH","AGENT_COLUMN_WIDTH","MODEL_COLUMN_WIDTH","EFFORT_COLUMN_WIDTH","AgentTaskRowHeader","AgentTaskRow","taskKey","agentConfig","onSave","opts","AGENT_OPTIONS","modelOpts","effortOpts","localModel","setLocalModel","handleAgentChange","v","newId","newOpts","newConfig","_a","handleModelSelectChange","handleModelInputBlur","handleEffortChange","Select","AGENT_IDS","m","GeneralSection","fileRef","useRef","config","setConfig","fetchedIconDataUri","identityLoading","useProjectIdentity","uploadedIconDataUri","setUploadedIconDataUri","iconDataUri","uploading","setUploading","portInput","setPortInput","nameInput","setNameInput","handleSaveAgentConfig","key","newEntry","current","updated","DEFAULT_AGENTS","error","prev","handleSavePort","port","handleSaveName","projectName","handleFile","file","reader","dataUri","uploadIcon","color","SettingsPage","section","useActiveSettingsSection","PageTitle","SettingsSidebar","navigate","useNavigate","SidebarSection","ListItem"],"mappings":"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"}