feat(ai): patch Architect prompt with full Spec Kit PRD template rules
This commit is contained in:
@@ -109,91 +109,92 @@ export default function PlanPageV2() {
|
||||
// The business case / 1-page summary
|
||||
// ──────────────────────────────────────────────────
|
||||
function ObjectiveView({ plan, projectId, onChange }: { plan: Plan, projectId: string, onChange: (p: Plan) => void }) {
|
||||
const [editing, setEditing] = useState(!plan.vision);
|
||||
const [draft, setDraft] = useState(plan.vision ?? "");
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [generating, setGenerating] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (plan.vision !== draft) {
|
||||
setDraft(plan.vision ?? "");
|
||||
}
|
||||
}, [plan.vision]);
|
||||
|
||||
const save = async () => {
|
||||
const save = async (text: string) => {
|
||||
setSaving(true);
|
||||
try {
|
||||
const r = await fetch(`/api/projects/${projectId}/plan`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ kind: "vision", text: draft }),
|
||||
body: JSON.stringify({ kind: "vision", text }),
|
||||
});
|
||||
const d = await r.json();
|
||||
if (d.plan) onChange(d.plan);
|
||||
setEditing(false);
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleGenerate = async () => {
|
||||
if (!draft.trim()) {
|
||||
alert("Please write an objective first before generating the PRD.");
|
||||
return;
|
||||
}
|
||||
if (!confirm("This will overwrite the PRD and Execution Plan based on this objective. Continue?")) return;
|
||||
|
||||
setGenerating(true);
|
||||
try {
|
||||
await fetch(`/api/projects/${projectId}/plan`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ kind: "vision", text: draft }),
|
||||
});
|
||||
|
||||
const r = await fetch(`/api/projects/${projectId}/plan/generate`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ objective: draft }),
|
||||
});
|
||||
const d = await r.json();
|
||||
if (d.plan) onChange(d.plan);
|
||||
alert("Blueprint generated successfully! Check the PRD and Delegate tabs.");
|
||||
} finally {
|
||||
setGenerating(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="panel-container">
|
||||
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }}>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
<div style={{ display: "flex", gap: 12 }}>
|
||||
<div style={{ display: "flex", justifyContent: "flex-end", marginBottom: 16 }}>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 12 }}>
|
||||
{saving && <span style={{ fontSize: "0.75rem", color: INK.faint }}>Saving...</span>}
|
||||
<button
|
||||
onClick={async () => {
|
||||
if (!confirm("This will overwrite the PRD and Execution Plan based on the current objective. Continue?")) return;
|
||||
setSaving(true);
|
||||
try {
|
||||
const r = await fetch(`/api/projects/${projectId}/plan/generate`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ objective: draft }),
|
||||
});
|
||||
const d = await r.json();
|
||||
if (d.plan) onChange(d.plan);
|
||||
} finally {
|
||||
setSaving(false);
|
||||
setEditing(false);
|
||||
}
|
||||
}}
|
||||
disabled={saving || !draft.trim()}
|
||||
onClick={handleGenerate}
|
||||
disabled={generating || !draft.trim()}
|
||||
className="btn-primary"
|
||||
style={{ fontWeight: 600, fontSize: "0.85rem", padding: "6px 16px", borderRadius: 6 }}
|
||||
style={{ padding: "8px 16px", borderRadius: 8, fontWeight: 600 }}
|
||||
>
|
||||
{saving ? <><Loader2 size={12} className="animate-spin" /> Generating...</> : "Generate Complete PRD"}
|
||||
{generating ? (
|
||||
<><Loader2 size={14} className="animate-spin" /> Generating Blueprint...</>
|
||||
) : (
|
||||
"Generate Complete PRD"
|
||||
)}
|
||||
</button>
|
||||
{!editing && (
|
||||
<button onClick={() => setEditing(true)} className="btn-ghost">
|
||||
<Pencil size={12} /> Edit
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{editing ? (
|
||||
<div style={{ border: `1px solid ${INK.border}`, borderRadius: 8, overflow: "hidden" }}>
|
||||
<textarea
|
||||
value={draft}
|
||||
onChange={(e) => setDraft(e.target.value)}
|
||||
style={{
|
||||
width: "100%", minHeight: 400, padding: 20, fontSize: "0.95rem", lineHeight: 1.6,
|
||||
border: "none", outline: "none", resize: "vertical", fontFamily: "var(--font-sans)",
|
||||
}}
|
||||
placeholder="Describe the business objective..."
|
||||
/>
|
||||
<div style={{ display: "flex", justifyContent: "flex-end", gap: 8, padding: "12px 20px", background: INK.bgHover, borderTop: `1px solid ${INK.border}` }}>
|
||||
<button onClick={() => setEditing(false)} className="btn-ghost">Cancel</button>
|
||||
<button onClick={save} disabled={saving} className="btn-primary">
|
||||
{saving ? "Saving..." : "Save Objective"}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="markdown-prose" style={{ background: "#fff", border: `1px solid ${INK.border}`, padding: 32, borderRadius: 8, minHeight: 200 }}>
|
||||
{plan.vision ? (
|
||||
<ReactMarkdown>{plan.vision}</ReactMarkdown>
|
||||
) : (
|
||||
<div style={{ color: INK.faint, fontStyle: "italic" }}>No objective defined yet. Switch to Architect mode and brainstorm with the AI.</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div style={{ border: `1px solid ${INK.border}`, borderRadius: 8, overflow: "hidden", background: "#fff", boxShadow: "0 1px 3px rgba(0,0,0,0.02)" }}>
|
||||
<textarea
|
||||
value={draft}
|
||||
onChange={(e) => setDraft(e.target.value)}
|
||||
onBlur={() => save(draft)}
|
||||
style={{
|
||||
width: "100%", minHeight: 400, padding: 24, fontSize: "0.95rem", lineHeight: 1.6,
|
||||
border: "none", outline: "none", resize: "vertical", fontFamily: "var(--font-sans)",
|
||||
color: INK.main
|
||||
}}
|
||||
placeholder="Describe the business objective..."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user