-
Notifications
You must be signed in to change notification settings - Fork 393
Claude/spec driven plan system wx oxs #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4dd4b9f
41ba044
b5cc4f6
a2d0b70
d54fb41
1097e2c
5e34829
6dbc11b
ee099ed
c2153a9
496c57e
cbfb1ba
27f2cf2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| { | ||
| "name": "plannotator", | ||
| "owner": { | ||
| "name": "backnotprop" | ||
| "name": "bradennapier" | ||
| }, | ||
| "plugins": [ | ||
| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,10 @@ | ||
| { | ||
| "name": "plannotator", | ||
| "description": "Interactive Plan Review: Mark up and refine your plans using a UI, easily share for team collaboration, automatically integrates with plan mode hooks.", | ||
| "version": "0.2.1", | ||
| "version": "0.3.0", | ||
| "author": { | ||
| "name": "backnotprop" | ||
| "name": "bradennapier" | ||
| }, | ||
| "repository": "https://github.com/backnotprop/plannotator", | ||
| "keywords": ["planning", "review", "hooks", "ExitPlanMode", "collaboration"] | ||
| "repository": "https://github.com/bradennapier/plannotator", | ||
| "keywords": ["planning", "review", "hooks", "ExitPlanMode", "collaboration", "spec-driven"] | ||
| } |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -13,6 +13,7 @@ import { Settings } from '@plannotator/ui/components/Settings'; | |||||||||||||||||||||||||||||||||
| import { useSharing } from '@plannotator/ui/hooks/useSharing'; | ||||||||||||||||||||||||||||||||||
| import { storage } from '@plannotator/ui/utils/storage'; | ||||||||||||||||||||||||||||||||||
| import { UpdateBanner } from '@plannotator/ui/components/UpdateBanner'; | ||||||||||||||||||||||||||||||||||
| import { InstructionsPrompt, generateDefaultInstructions } from '@plannotator/ui/components/InstructionsPrompt'; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| const PLAN_CONTENT = `# Implementation Plan: Real-time Collaboration | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
|
|
@@ -229,8 +230,20 @@ const App: React.FC = () => { | |||||||||||||||||||||||||||||||||
| const [isLoading, setIsLoading] = useState(true); | ||||||||||||||||||||||||||||||||||
| const [isSubmitting, setIsSubmitting] = useState(false); | ||||||||||||||||||||||||||||||||||
| const [submitted, setSubmitted] = useState<'approved' | 'denied' | null>(null); | ||||||||||||||||||||||||||||||||||
| const [instructions, setInstructions] = useState(() => { | ||||||||||||||||||||||||||||||||||
| // Restore instructions from cookies to persist across plan revisions | ||||||||||||||||||||||||||||||||||
| return storage.getItem('plannotator-instructions') || ''; | ||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||
| const [isInstructionsExpanded, setIsInstructionsExpanded] = useState(true); | ||||||||||||||||||||||||||||||||||
| const viewerRef = useRef<ViewerHandle>(null); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| // Persist instructions to cookies when they change | ||||||||||||||||||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||||||||||||||||||
| if (instructions.trim()) { | ||||||||||||||||||||||||||||||||||
| storage.setItem('plannotator-instructions', instructions); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| }, [instructions]); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| // URL-based sharing | ||||||||||||||||||||||||||||||||||
| const { | ||||||||||||||||||||||||||||||||||
| isSharedSession, | ||||||||||||||||||||||||||||||||||
|
|
@@ -239,6 +252,7 @@ const App: React.FC = () => { | |||||||||||||||||||||||||||||||||
| shareUrlSize, | ||||||||||||||||||||||||||||||||||
| pendingSharedAnnotations, | ||||||||||||||||||||||||||||||||||
| clearPendingSharedAnnotations, | ||||||||||||||||||||||||||||||||||
| loadedInstructions, | ||||||||||||||||||||||||||||||||||
| } = useSharing( | ||||||||||||||||||||||||||||||||||
| markdown, | ||||||||||||||||||||||||||||||||||
| annotations, | ||||||||||||||||||||||||||||||||||
|
|
@@ -247,9 +261,17 @@ const App: React.FC = () => { | |||||||||||||||||||||||||||||||||
| () => { | ||||||||||||||||||||||||||||||||||
| // When loaded from share, mark as loaded | ||||||||||||||||||||||||||||||||||
| setIsLoading(false); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||
| instructions | ||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| // Apply loaded instructions from shared URL | ||||||||||||||||||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||||||||||||||||||
| if (loadedInstructions && !instructions.trim()) { | ||||||||||||||||||||||||||||||||||
| setInstructions(loadedInstructions); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| }, [loadedInstructions, instructions]); | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+268
to
+273
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| // Apply shared annotations to DOM after they're loaded | ||||||||||||||||||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||||||||||||||||||
| if (pendingSharedAnnotations && pendingSharedAnnotations.length > 0) { | ||||||||||||||||||||||||||||||||||
|
|
@@ -295,11 +317,22 @@ const App: React.FC = () => { | |||||||||||||||||||||||||||||||||
| setBlocks(parseMarkdownToBlocks(markdown)); | ||||||||||||||||||||||||||||||||||
| }, [markdown]); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| // Generate default instructions when plan is loaded in API mode | ||||||||||||||||||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||||||||||||||||||
| if (isApiMode && markdown && !instructions.trim()) { | ||||||||||||||||||||||||||||||||||
| setInstructions(generateDefaultInstructions(markdown)); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| }, [isApiMode, markdown, instructions]); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
|
Comment on lines
+322
to
+326
|
||||||||||||||||||||||||||||||||||
| if (isApiMode && markdown && !instructions.trim()) { | |
| setInstructions(generateDefaultInstructions(markdown)); | |
| } | |
| }, [isApiMode, markdown, instructions]); | |
| if (!isApiMode || !markdown) { | |
| return; | |
| } | |
| setInstructions((prev) => { | |
| // If the user or other logic has already provided instructions, keep them. | |
| if (prev.trim()) { | |
| return prev; | |
| } | |
| return generateDefaultInstructions(markdown); | |
| }); | |
| }, [isApiMode, markdown]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The instructions are only persisted to storage when they have content (instructions.trim() is truthy), but there's no mechanism to remove them from storage when the user clears the instructions field. This means once instructions are set, they can never be fully cleared from storage even if the user deletes all text. Consider also calling storage.removeItem('plannotator-instructions') when instructions.trim() is empty.