@@ -20,6 +20,8 @@ default:
2020 echo " just board start <id> Move story to in-progress"
2121 echo " just board done <id> [summary]"
2222 echo " Move story to done + changelog"
23+ echo " just board ice <id> Move story to icebox (blocked/deferred)"
24+ echo " just board thaw <id> Move story from icebox to backlog"
2325 echo " "
2426 echo " Epic/Milestone management:"
2527 echo " just board new epic \" name\" [description]"
@@ -184,6 +186,7 @@ status:
184186 cd " {{ board_dir}} "
185187
186188 # Count stories in each stage
189+ icebox=$(find stages/ icebox/ stories -name " *.md" ! -name " .gitkeep" 2 >/ dev/ null | wc -l | tr -d ' ' )
187190 in_progress=$(find stages/ in-progress/ stories -name " *.md" ! -name " .gitkeep" 2 >/ dev/ null | wc -l | tr -d ' ' )
188191 backlog=$(find stages/ backlog/ stories -name " *.md" ! -name " .gitkeep" 2 >/ dev/ null | wc -l | tr -d ' ' )
189192 done_count=$(find stages/ done/ stories -name " *.md" ! -name " .gitkeep" 2 >/ dev/ null | wc -l | tr -d ' ' )
@@ -194,6 +197,7 @@ status:
194197 echo " Stories by Stage:"
195198 echo " In Progress: $in_progress"
196199 echo " Backlog: $backlog"
200+ echo " Icebox: $icebox"
197201 echo " Done: $done_count"
198202 echo " "
199203
@@ -225,21 +229,30 @@ _next-id TYPE:
225229 #!/usr/bin/env bash
226230 cd " {{ board_dir}} "
227231 type=" {{ TYPE}} "
232+ type_upper=" ${type^^}"
228233 max=0
229234
230- # Search in all stages for stories with this type prefix
235+ # Search for new format: [TYPE][NNNN]-*.md
236+ for f in $(find stages -name " \[ ${type_upper}\]\[ *\] *.md" 2 >/ dev/ null); do
237+ # Extract sequence number from [TYPE][NNNN] format
238+ num=$(basename " $f" .md | grep -oE " \[ ${type_upper}\]\[ [0-9]+\] " | grep -oE " [0-9]+" )
239+ [[ -z " $num" ]] && continue
240+ num=$((10 #$num))
241+ if [[ " $num" -gt " $max" ]]; then
242+ max=$num
243+ fi
244+ done
245+
246+ # Also search old format for backwards compatibility: type-NNNN-*.md
231247 for f in $(find stages -name " ${type}-*.md" -o -name " *-${type}-*.md" 2 >/ dev/ null); do
232- # Extract sequence number after type prefix (e.g., feat-01, m37-feat-01)
233- # Pattern: TYPE-NN where NN is the sequence number we want
234248 num=$(basename " $f" .md | grep -oE " (feat|bug|chore|refactor|fix|docs)-[0-9]+" | grep -oE " [0-9]+$" )
235- # Skip if no match found
236249 [[ -z " $num" ]] && continue
237- # Strip leading zeros to avoid octal interpretation (e.g., 08 -> 8)
238250 num=$((10 #$num))
239251 if [[ " $num" -gt " $max" ]]; then
240252 max=$num
241253 fi
242254 done
255+
243256 printf " %04d" $((max + 1 ))
244257
245258# Get next milestone number
@@ -333,24 +346,16 @@ _new-story TITLE TYPE="" EPICS="" MILESTONE="":
333346 # Create slug from title
334347 slug=$(echo " $title" | tr ' [:upper:]' ' [:lower:]' | tr ' ' ' -' | tr -cd ' a-z0-9-' )
335348
336- # Build filename - include milestone prefix if provided
337- if [[ -n " $milestone" ]]; then
338- # Extract milestone number (e.g., "27" from "27-crt-design-system")
339- ms_num=$(echo " $milestone" | grep -oE ' ^[0-9]+' || echo " " )
340- if [[ -n " $ms_num" ]]; then
341- filename=" stages/backlog/stories/m${ms_num}-${type}-${id}-${slug}.md"
342- else
343- filename=" stages/backlog/stories/${type}-${id}-${slug}.md"
344- fi
345- else
346- filename=" stages/backlog/stories/${type}-${id}-${slug}.md"
347- fi
349+ # Build filename with new [TYPE][NNNN] format
350+ # Format: [TYPE][NNNN]-verb-phrase.md
351+ type_upper=" ${type^^}"
352+ filename=" stages/backlog/stories/[${type_upper}][${id}]-${slug}.md"
348353
349354 # Create the story file
350355 date=$(date + %Y-%m-%d)
351356 {
352357 echo ' ---'
353- echo " id: ${type^^ }${id}"
358+ echo " id: ${type_upper }${id}"
354359 echo " title: ${title}"
355360 echo " type: ${type}"
356361 echo " status: backlog"
@@ -558,8 +563,8 @@ _find-story PATTERN:
558563 cd " {{ board_dir}} "
559564 pattern=" {{ PATTERN}} "
560565
561- # Search in stages (backlog, in-progress, done)
562- for stage in backlog in-progress done; do
566+ # Search in stages (icebox, backlog, in-progress, done)
567+ for stage in icebox backlog in-progress done; do
563568 dir=" stages/$stage/stories"
564569 [[ -d " $dir" ]] || continue
565570
@@ -718,6 +723,116 @@ done ID SUMMARY="__PROMPT__":
718723 just board generate
719724 echo " Board updated"
720725
726+ # Move story to icebox (blocked or deferred)
727+ ice ID :
728+ #!/usr/bin/env bash
729+ set -euo pipefail
730+ cd " {{ board_dir}} "
731+
732+ path=$(just board _find-story " {{ ID}} " )
733+
734+ if [[ -z " $path" ]]; then
735+ echo " Error: Story '{{ ID}} ' not found"
736+ exit 1
737+ fi
738+
739+ # Check if already in icebox
740+ if [[ " $path" == *" icebox" * ]]; then
741+ echo " Error: Story is already in icebox"
742+ exit 1
743+ fi
744+
745+ # Check if already done
746+ if [[ " $path" == *" done" * ]]; then
747+ echo " Error: Cannot ice a completed story"
748+ exit 1
749+ fi
750+
751+ name=$(basename " $path" )
752+ dest=" stages/icebox/stories/$name"
753+
754+ # Get epics from frontmatter before moving
755+ epics=$(grep -m1 " ^epics:" " $path" 2 >/ dev/ null | sed ' s/^epics: *//' | tr -d ' []' || echo " " )
756+
757+ # Move the file
758+ mv " $path" " $dest"
759+
760+ # Update status in frontmatter
761+ sed -i ' s/^status: .*/status: icebox/' " $dest"
762+ sed -i " s/^updated: .*/updated: $(date +%Y-%m-%d)/" " $dest"
763+
764+ echo " Iced: $name"
765+
766+ # Update symlinks in epics
767+ if [[ -n " $epics" ]]; then
768+ IFS=' , ' read -ra epic_list <<< " $epics"
769+ for epic in " ${epic_list[@]}" ; do
770+ epic=$(echo " $epic" | tr -d ' ' )
771+ link=" epics/$epic/$name"
772+ if [[ -L " $link" ]]; then
773+ rm " $link"
774+ ln -sf " ../../stages/icebox/stories/$name" " $link"
775+ echo " Updated symlink in epic: $epic"
776+ fi
777+ done
778+ fi
779+
780+ # Regenerate README
781+ just board generate
782+ echo " Board updated"
783+
784+ # Move story from icebox to backlog (unblock)
785+ thaw ID :
786+ #!/usr/bin/env bash
787+ set -euo pipefail
788+ cd " {{ board_dir}} "
789+
790+ path=$(just board _find-story " {{ ID}} " )
791+
792+ if [[ -z " $path" ]]; then
793+ echo " Error: Story '{{ ID}} ' not found"
794+ exit 1
795+ fi
796+
797+ # Check if in icebox
798+ if [[ " $path" != *" icebox" * ]]; then
799+ echo " Error: Story is not in icebox (current location: $path)"
800+ exit 1
801+ fi
802+
803+ name=$(basename " $path" )
804+ dest=" stages/backlog/stories/$name"
805+
806+ # Get epics from frontmatter before moving
807+ epics=$(grep -m1 " ^epics:" " $path" 2 >/ dev/ null | sed ' s/^epics: *//' | tr -d ' []' || echo " " )
808+
809+ # Move the file
810+ mv " $path" " $dest"
811+
812+ # Update status in frontmatter
813+ sed -i ' s/^status: .*/status: backlog/' " $dest"
814+ sed -i " s/^updated: .*/updated: $(date +%Y-%m-%d)/" " $dest"
815+
816+ echo " Thawed: $name"
817+
818+ # Update symlinks in epics
819+ if [[ -n " $epics" ]]; then
820+ IFS=' , ' read -ra epic_list <<< " $epics"
821+ for epic in " ${epic_list[@]}" ; do
822+ epic=$(echo " $epic" | tr -d ' ' )
823+ link=" epics/$epic/$name"
824+ if [[ -L " $link" ]]; then
825+ rm " $link"
826+ ln -sf " ../../stages/backlog/stories/$name" " $link"
827+ echo " Updated symlink in epic: $epic"
828+ fi
829+ done
830+ fi
831+
832+ # Regenerate README
833+ just board generate
834+ echo " Board updated"
835+
721836# Start a milestone (set status to in-progress)
722837start-milestone ID :
723838 #!/usr/bin/env bash
0 commit comments