Initial plan-tools: plan-refine and plan-status
Semi-automated plan refinement pipeline using Oracle for ChatGPT browser automation. Includes frontmatter-based tracking and a dashboard scanner for plan status across projects. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
103
lib/frontmatter.sh
Normal file
103
lib/frontmatter.sh
Normal file
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env bash
|
||||
# frontmatter.sh — Read/write YAML frontmatter in plan files
|
||||
|
||||
# Read a value from YAML frontmatter
|
||||
# Usage: get_frontmatter <file> <key> [default]
|
||||
get_frontmatter() {
|
||||
local file="$1"
|
||||
local key="$2"
|
||||
local default="${3:-}"
|
||||
|
||||
if ! head -1 "$file" | grep -q '^---$'; then
|
||||
echo "$default"
|
||||
return
|
||||
fi
|
||||
|
||||
local value
|
||||
value=$(awk '/^---$/{n++; next} n==1{print}' "$file" \
|
||||
| grep "^${key}:" \
|
||||
| head -1 \
|
||||
| sed "s/^${key}: *//; s/^ *//; s/ *$//; s/^[\"']//; s/[\"']$//")
|
||||
echo "${value:-$default}"
|
||||
}
|
||||
|
||||
# Set a value in YAML frontmatter (adds frontmatter if missing)
|
||||
# Usage: set_frontmatter <file> <key> <value>
|
||||
set_frontmatter() {
|
||||
local file="$1"
|
||||
local key="$2"
|
||||
local value="$3"
|
||||
|
||||
# If file has no frontmatter, add it
|
||||
if ! head -1 "$file" | grep -q '^---$'; then
|
||||
local tmp
|
||||
tmp=$(mktemp)
|
||||
{
|
||||
echo "---"
|
||||
echo "${key}: ${value}"
|
||||
echo "---"
|
||||
cat "$file"
|
||||
} > "$tmp"
|
||||
mv "$tmp" "$file"
|
||||
return
|
||||
fi
|
||||
|
||||
if grep -q "^${key}:" "$file"; then
|
||||
# Replace existing key (using | as delimiter to avoid path issues)
|
||||
sed -i '' "s|^${key}:.*|${key}: ${value}|" "$file"
|
||||
else
|
||||
# Insert before closing --- (second occurrence)
|
||||
awk -v key="$key" -v val="$value" '
|
||||
BEGIN { count=0; inserted=0 }
|
||||
/^---$/ { count++ }
|
||||
count == 2 && !inserted { print key ": " val; inserted=1 }
|
||||
{ print }
|
||||
' "$file" > "${file}.tmp" && mv "${file}.tmp" "$file"
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if a file has plan frontmatter
|
||||
# Usage: is_plan_file <file>
|
||||
is_plan_file() {
|
||||
local file="$1"
|
||||
[[ -f "$file" ]] && head -20 "$file" | grep -q "^plan: true"
|
||||
}
|
||||
|
||||
# Initialize frontmatter on a plan file that doesn't have it
|
||||
# Usage: init_frontmatter <file> [title]
|
||||
init_frontmatter() {
|
||||
local file="$1"
|
||||
local title="${2:-$(basename "$file" .md)}"
|
||||
local today
|
||||
today=$(date +%Y-%m-%d)
|
||||
|
||||
if head -1 "$file" | grep -q '^---$'; then
|
||||
# Has frontmatter, just ensure plan fields exist
|
||||
set_frontmatter "$file" "plan" "true"
|
||||
[[ -z "$(get_frontmatter "$file" "status")" ]] && set_frontmatter "$file" "status" "drafting"
|
||||
[[ -z "$(get_frontmatter "$file" "iteration")" ]] && set_frontmatter "$file" "iteration" "0"
|
||||
[[ -z "$(get_frontmatter "$file" "target_iterations")" ]] && set_frontmatter "$file" "target_iterations" "8"
|
||||
[[ -z "$(get_frontmatter "$file" "created")" ]] && set_frontmatter "$file" "created" "$today"
|
||||
set_frontmatter "$file" "updated" "$today"
|
||||
else
|
||||
# No frontmatter, add full block
|
||||
local tmp
|
||||
tmp=$(mktemp)
|
||||
{
|
||||
echo "---"
|
||||
echo "plan: true"
|
||||
echo "title: \"${title}\""
|
||||
echo "status: drafting"
|
||||
echo "iteration: 0"
|
||||
echo "target_iterations: 8"
|
||||
echo "beads_revision: 0"
|
||||
echo "related_plans: []"
|
||||
echo "created: ${today}"
|
||||
echo "updated: ${today}"
|
||||
echo "---"
|
||||
echo ""
|
||||
cat "$file"
|
||||
} > "$tmp"
|
||||
mv "$tmp" "$file"
|
||||
fi
|
||||
}
|
||||
Reference in New Issue
Block a user