mirror of
https://github.com/allexanderbergmns/xh1-research.git
synced 2026-08-26 17:47:02 +00:00
1018 lines
18 KiB
Bash
Executable File
1018 lines
18 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# ============================================================
|
|
# XH-1 Research Harness
|
|
# Pure Bash / OpenAI-compatible API
|
|
# ============================================================
|
|
|
|
ROOT="${XH1_RESEARCH_ROOT:-research}"
|
|
STATE="${ROOT}/.xh1"
|
|
CONFIG="${XH1_RESEARCH_CONFIG:-xh1-research.conf}"
|
|
|
|
mkdir -p "$STATE"/{logs,responses}
|
|
|
|
# ------------------------------------------------------------
|
|
# Defaults
|
|
# ------------------------------------------------------------
|
|
|
|
API_BASE_URL="${API_BASE_URL:-https://api.openai.com/v1}"
|
|
API_KEY_ENV="${API_KEY_ENV:-OPENAI_API_KEY}"
|
|
MODEL="${MODEL:-}"
|
|
|
|
MAX_RETRIES="${MAX_RETRIES:-3}"
|
|
DELAY_SECONDS="${DELAY_SECONDS:-5}"
|
|
MAX_ITERATIONS="${MAX_ITERATIONS:-0}"
|
|
|
|
REVIEW_ENABLED="${REVIEW_ENABLED:-true}"
|
|
AUTO_COMMIT="${AUTO_COMMIT:-false}"
|
|
|
|
# ------------------------------------------------------------
|
|
# Helpers
|
|
# ------------------------------------------------------------
|
|
|
|
die() {
|
|
echo "ERROR: $*" >&2
|
|
exit 1
|
|
}
|
|
|
|
log() {
|
|
local msg="$*"
|
|
echo "[$(date -u '+%Y-%m-%dT%H:%M:%SZ')] $msg" \
|
|
| tee -a "$STATE/logs/harness.log"
|
|
}
|
|
|
|
require() {
|
|
command -v "$1" >/dev/null 2>&1 ||
|
|
die "Required command not found: $1"
|
|
}
|
|
|
|
load_config() {
|
|
if [[ -f "$CONFIG" ]]; then
|
|
# shellcheck disable=SC1090
|
|
source "$CONFIG"
|
|
fi
|
|
}
|
|
|
|
require_dependencies() {
|
|
require bash
|
|
require curl
|
|
require jq
|
|
}
|
|
|
|
get_api_key() {
|
|
local key="${!API_KEY_ENV:-}"
|
|
|
|
[[ -n "$key" ]] ||
|
|
die "API key missing. Set ${API_KEY_ENV}."
|
|
|
|
printf '%s' "$key"
|
|
}
|
|
|
|
timestamp() {
|
|
date -u '+%Y%m%dT%H%M%SZ'
|
|
}
|
|
|
|
# ------------------------------------------------------------
|
|
# Configuration
|
|
# ------------------------------------------------------------
|
|
|
|
init_config() {
|
|
|
|
if [[ -f "$CONFIG" ]]; then
|
|
echo "Configuration already exists:"
|
|
echo " $CONFIG"
|
|
return
|
|
fi
|
|
|
|
cat > "$CONFIG" <<'EOF'
|
|
# ============================================================
|
|
# XH-1 Research Harness Configuration
|
|
# ============================================================
|
|
|
|
# OpenAI-compatible API
|
|
API_BASE_URL="https://api.openai.com/v1"
|
|
|
|
# Environment variable containing API key
|
|
API_KEY_ENV="OPENAI_API_KEY"
|
|
|
|
# Model name
|
|
MODEL=""
|
|
|
|
# Research behavior
|
|
MAX_RETRIES=3
|
|
DELAY_SECONDS=5
|
|
MAX_ITERATIONS=0
|
|
|
|
# Run reviewer after researcher
|
|
REVIEW_ENABLED=true
|
|
|
|
# Automatically create git commits
|
|
AUTO_COMMIT=false
|
|
EOF
|
|
|
|
echo "Created $CONFIG"
|
|
}
|
|
|
|
# ------------------------------------------------------------
|
|
# API
|
|
# ------------------------------------------------------------
|
|
|
|
api_call() {
|
|
|
|
local system_prompt="$1"
|
|
local user_prompt="$2"
|
|
local output="$3"
|
|
|
|
local key
|
|
key="$(get_api_key)"
|
|
|
|
[[ -n "$MODEL" ]] ||
|
|
die "MODEL is not configured."
|
|
|
|
local payload
|
|
|
|
payload="$(
|
|
jq -n \
|
|
--arg model "$MODEL" \
|
|
--arg system "$system_prompt" \
|
|
--arg user "$user_prompt" \
|
|
'{
|
|
model: $model,
|
|
messages: [
|
|
{
|
|
role: "system",
|
|
content: $system
|
|
},
|
|
{
|
|
role: "user",
|
|
content: $user
|
|
}
|
|
],
|
|
temperature: 0.2
|
|
}'
|
|
)"
|
|
|
|
local attempt=1
|
|
|
|
while (( attempt <= MAX_RETRIES )); do
|
|
|
|
if curl \
|
|
--fail \
|
|
--silent \
|
|
--show-error \
|
|
--connect-timeout 30 \
|
|
--max-time 1800 \
|
|
-H "Authorization: Bearer ${key}" \
|
|
-H "Content-Type: application/json" \
|
|
"${API_BASE_URL%/}/chat/completions" \
|
|
-d "$payload" \
|
|
> "${output}.json"
|
|
then
|
|
|
|
if jq -er \
|
|
'.choices[0].message.content' \
|
|
"${output}.json" \
|
|
> "$output"
|
|
then
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
log "API attempt $attempt failed."
|
|
|
|
sleep $((attempt * attempt))
|
|
|
|
((attempt++))
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
# ------------------------------------------------------------
|
|
# Research discovery
|
|
# ------------------------------------------------------------
|
|
|
|
is_research_file() {
|
|
|
|
[[ "$1" == *.md ]] &&
|
|
[[ "$1" != "$STATE"/* ]]
|
|
}
|
|
|
|
is_soon() {
|
|
|
|
grep -qE \
|
|
'^SOON[[:space:]]*$' \
|
|
"$1"
|
|
}
|
|
|
|
find_next_task() {
|
|
|
|
while IFS= read -r -d '' file; do
|
|
|
|
if is_research_file "$file" &&
|
|
is_soon "$file"
|
|
then
|
|
printf '%s\n' "$file"
|
|
return 0
|
|
fi
|
|
|
|
done < <(
|
|
find "$ROOT" \
|
|
-type f \
|
|
-name '*.md' \
|
|
-not -path "$STATE/*" \
|
|
-print0
|
|
)
|
|
|
|
return 1
|
|
}
|
|
|
|
# ------------------------------------------------------------
|
|
# Research context
|
|
# ------------------------------------------------------------
|
|
|
|
build_context() {
|
|
|
|
local file="$1"
|
|
|
|
local relative
|
|
relative="${file#"$ROOT"/}"
|
|
|
|
local area
|
|
area="${relative%%/*}"
|
|
|
|
cat <<EOF
|
|
PROJECT
|
|
=======
|
|
|
|
Name:
|
|
XH-1
|
|
|
|
Architecture:
|
|
Custom 128-core RISC-V CPU
|
|
|
|
Research repository:
|
|
XH-1 Research
|
|
|
|
Research document:
|
|
$file
|
|
|
|
Research area:
|
|
$area
|
|
|
|
|
|
CURRENT DOCUMENT
|
|
================
|
|
|
|
EOF
|
|
|
|
cat "$file"
|
|
|
|
cat <<EOF
|
|
|
|
|
|
RELATED DOCUMENTS
|
|
=================
|
|
|
|
EOF
|
|
|
|
find "$ROOT/$area" \
|
|
-maxdepth 1 \
|
|
-type f \
|
|
-name '*.md' \
|
|
! -path "$file" \
|
|
| sort \
|
|
| head -20 \
|
|
| while read -r related; do
|
|
|
|
echo
|
|
echo "----- $related -----"
|
|
cat "$related"
|
|
|
|
done
|
|
}
|
|
|
|
# ------------------------------------------------------------
|
|
# Research prompt
|
|
# ------------------------------------------------------------
|
|
|
|
research_system_prompt() {
|
|
|
|
cat <<'EOF'
|
|
You are a senior computer architecture researcher working on XH-1.
|
|
|
|
XH-1 is a custom 128-core RISC-V processor.
|
|
|
|
Your job is to perform rigorous technical research for exactly one assigned research topic.
|
|
|
|
You are NOT allowed to invent:
|
|
|
|
- sources
|
|
- papers
|
|
- URLs
|
|
- measurements
|
|
- benchmarks
|
|
- experiments
|
|
- hardware capabilities
|
|
- implementation details
|
|
|
|
Clearly distinguish:
|
|
|
|
FACT
|
|
ASSUMPTION
|
|
PROPOSAL
|
|
RECOMMENDATION
|
|
OPEN QUESTION
|
|
|
|
Prefer primary and authoritative sources.
|
|
|
|
For RISC-V topics, prioritize official RISC-V specifications.
|
|
|
|
For architecture topics, consider academic literature, processor manuals,
|
|
technical papers, and reputable engineering documentation.
|
|
|
|
The fact that XH-1 contains 128 cores is extremely important.
|
|
|
|
Do not provide generic CPU advice without explaining how it affects
|
|
a 128-core processor.
|
|
|
|
Research should investigate multiple alternatives where applicable.
|
|
|
|
Consider:
|
|
|
|
- performance
|
|
- latency
|
|
- bandwidth
|
|
- area
|
|
- power
|
|
- scalability
|
|
- implementation complexity
|
|
- verification complexity
|
|
- software implications
|
|
- failure modes
|
|
- future extensibility
|
|
|
|
You are researching the architecture.
|
|
|
|
Do not assume an architectural decision has already been made.
|
|
|
|
If evidence is insufficient, explicitly say:
|
|
|
|
INSUFFICIENT EVIDENCE
|
|
|
|
Do not force a recommendation when the evidence does not justify one.
|
|
EOF
|
|
}
|
|
|
|
research_user_prompt() {
|
|
|
|
local file="$1"
|
|
|
|
build_context "$file"
|
|
|
|
cat <<'EOF'
|
|
|
|
RESEARCH TASK
|
|
=============
|
|
|
|
Investigate the assigned topic thoroughly.
|
|
|
|
Produce a technically detailed Markdown research document.
|
|
|
|
Use this structure where applicable:
|
|
|
|
# Topic
|
|
|
|
## Status
|
|
|
|
## Abstract
|
|
|
|
## Research Question
|
|
|
|
## Background
|
|
|
|
## Existing Approaches
|
|
|
|
## Alternative Designs
|
|
|
|
## Comparison
|
|
|
|
## Advantages
|
|
|
|
## Disadvantages
|
|
|
|
## XH-1 Considerations
|
|
|
|
## 128-Core Scalability
|
|
|
|
## Performance Considerations
|
|
|
|
## Implementation Considerations
|
|
|
|
## Verification Considerations
|
|
|
|
## Recommendation
|
|
|
|
## Confidence
|
|
|
|
## Open Questions
|
|
|
|
## Sources
|
|
|
|
Do not include conversational commentary.
|
|
|
|
The output must be suitable for insertion into the research repository.
|
|
EOF
|
|
}
|
|
|
|
# ------------------------------------------------------------
|
|
# Reviewer
|
|
# ------------------------------------------------------------
|
|
|
|
review_system_prompt() {
|
|
|
|
cat <<'EOF'
|
|
You are the independent technical reviewer for the XH-1
|
|
128-core RISC-V processor research project.
|
|
|
|
Your job is to aggressively review another research agent's work.
|
|
|
|
Check for:
|
|
|
|
1. factual errors
|
|
2. unsupported claims
|
|
3. hallucinated sources
|
|
4. incorrect RISC-V information
|
|
5. missing alternatives
|
|
6. weak reasoning
|
|
7. contradictions
|
|
8. unexplained assumptions
|
|
9. failure to consider 128 cores
|
|
10. unrealistic implementation claims
|
|
11. unsupported performance claims
|
|
12. missing verification concerns
|
|
13. unjustified recommendations
|
|
|
|
Do not rewrite the research.
|
|
|
|
Return exactly:
|
|
|
|
VERDICT: PASS
|
|
|
|
or:
|
|
|
|
VERDICT: FAIL
|
|
|
|
Then provide:
|
|
|
|
ISSUES:
|
|
- ...
|
|
|
|
REQUIRED_FIXES:
|
|
- ...
|
|
|
|
CONFIDENCE: HIGH/MEDIUM/LOW
|
|
EOF
|
|
}
|
|
|
|
review_document() {
|
|
|
|
local document="$1"
|
|
local output="$2"
|
|
|
|
api_call \
|
|
"$(review_system_prompt)" \
|
|
"$(cat "$document")" \
|
|
"$output"
|
|
}
|
|
|
|
# ------------------------------------------------------------
|
|
# File safety
|
|
# ------------------------------------------------------------
|
|
|
|
replace_soon() {
|
|
|
|
local target="$1"
|
|
local replacement="$2"
|
|
|
|
# Make absolutely sure we are still replacing a SOON document.
|
|
|
|
if ! is_soon "$target"; then
|
|
die "Refusing to overwrite modified document: $target"
|
|
fi
|
|
|
|
local temporary
|
|
|
|
temporary="$(mktemp)"
|
|
|
|
cat "$replacement" > "$temporary"
|
|
|
|
mv "$temporary" "$target"
|
|
}
|
|
|
|
# ------------------------------------------------------------
|
|
# Git
|
|
# ------------------------------------------------------------
|
|
|
|
git_commit() {
|
|
|
|
local file="$1"
|
|
|
|
[[ "$AUTO_COMMIT" == "true" ]] ||
|
|
return 0
|
|
|
|
git rev-parse \
|
|
--is-inside-work-tree \
|
|
>/dev/null 2>&1 ||
|
|
return 0
|
|
|
|
git add "$file"
|
|
|
|
local title
|
|
|
|
title="$(
|
|
basename "$file" .md |
|
|
tr '-' ' '
|
|
)"
|
|
|
|
git commit \
|
|
-m "research: ${title}" \
|
|
|| true
|
|
}
|
|
|
|
# ------------------------------------------------------------
|
|
# Research one document
|
|
# ------------------------------------------------------------
|
|
|
|
run_one() {
|
|
|
|
local file="${1:-}"
|
|
|
|
if [[ -z "$file" ]]; then
|
|
file="$(find_next_task || true)"
|
|
fi
|
|
|
|
[[ -n "$file" ]] ||
|
|
{
|
|
echo "No incomplete research topics."
|
|
return 0
|
|
}
|
|
|
|
[[ -f "$file" ]] ||
|
|
die "Research file does not exist: $file"
|
|
|
|
log "Starting research: $file"
|
|
|
|
local id
|
|
id="$(timestamp)_$(basename "$file" .md)"
|
|
|
|
local response
|
|
response="$STATE/responses/${id}.md"
|
|
|
|
log "Running researcher."
|
|
|
|
if ! api_call \
|
|
"$(research_system_prompt)" \
|
|
"$(research_user_prompt "$file")" \
|
|
"$response"
|
|
then
|
|
|
|
log "Research agent failed."
|
|
|
|
return 1
|
|
fi
|
|
|
|
log "Research completed."
|
|
|
|
# --------------------------------------------------------
|
|
# Review
|
|
# --------------------------------------------------------
|
|
|
|
if [[ "$REVIEW_ENABLED" == "true" ]]; then
|
|
|
|
local review
|
|
review="${response}.review"
|
|
|
|
log "Running reviewer."
|
|
|
|
if ! review_document \
|
|
"$response" \
|
|
"$review"
|
|
then
|
|
|
|
log "Reviewer failed."
|
|
|
|
return 1
|
|
fi
|
|
|
|
local verdict
|
|
|
|
verdict="$(
|
|
grep -m1 '^VERDICT:' "$review" |
|
|
tr -d '\r'
|
|
)"
|
|
|
|
echo
|
|
echo "=========================================="
|
|
echo "RESEARCH REVIEW"
|
|
echo "=========================================="
|
|
cat "$review"
|
|
echo "=========================================="
|
|
echo
|
|
|
|
if [[ "$verdict" != "VERDICT: PASS" ]]; then
|
|
|
|
log "Research rejected by reviewer."
|
|
|
|
return 2
|
|
fi
|
|
|
|
log "Research passed review."
|
|
|
|
fi
|
|
|
|
# --------------------------------------------------------
|
|
# Replace SOON
|
|
# --------------------------------------------------------
|
|
|
|
replace_soon "$file" "$response"
|
|
|
|
printf '%s\t%s\t%s\n' \
|
|
"$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \
|
|
"completed" \
|
|
"$file" \
|
|
>> "$STATE/state.tsv"
|
|
|
|
git_commit "$file"
|
|
|
|
log "Completed: $file"
|
|
|
|
return 0
|
|
}
|
|
|
|
# ------------------------------------------------------------
|
|
# Loop
|
|
# ------------------------------------------------------------
|
|
|
|
run_loop() {
|
|
|
|
local iteration=0
|
|
|
|
while true; do
|
|
|
|
if (( MAX_ITERATIONS > 0 &&
|
|
iteration >= MAX_ITERATIONS )); then
|
|
|
|
log "Maximum iterations reached."
|
|
|
|
break
|
|
fi
|
|
|
|
local file
|
|
|
|
file="$(find_next_task || true)"
|
|
|
|
if [[ -z "$file" ]]; then
|
|
|
|
log "No SOON documents remain."
|
|
|
|
break
|
|
fi
|
|
|
|
echo
|
|
echo "=========================================="
|
|
echo "XH-1 RESEARCH ITERATION $((iteration + 1))"
|
|
echo "=========================================="
|
|
echo
|
|
echo "Topic:"
|
|
echo " $file"
|
|
echo
|
|
|
|
if run_one "$file"; then
|
|
|
|
log "Iteration successful."
|
|
|
|
else
|
|
|
|
log "Iteration failed."
|
|
|
|
echo
|
|
echo "Research failed."
|
|
echo "The document was NOT modified."
|
|
echo
|
|
|
|
fi
|
|
|
|
((iteration += 1))
|
|
|
|
sleep "$DELAY_SECONDS"
|
|
|
|
done
|
|
}
|
|
|
|
# ------------------------------------------------------------
|
|
# Status
|
|
# ------------------------------------------------------------
|
|
|
|
status() {
|
|
|
|
[[ -d "$ROOT" ]] ||
|
|
die "Research directory not found: $ROOT"
|
|
|
|
local total
|
|
local soon
|
|
local researched
|
|
|
|
total="$(
|
|
find "$ROOT" \
|
|
-type f \
|
|
-name '*.md' \
|
|
-not -path "$STATE/*" |
|
|
wc -l |
|
|
tr -d ' '
|
|
)"
|
|
|
|
soon="$(
|
|
grep -RIl \
|
|
'^SOON[[:space:]]*$' \
|
|
"$ROOT" \
|
|
--include='*.md' \
|
|
--exclude-dir='.xh1' \
|
|
2>/dev/null |
|
|
wc -l |
|
|
tr -d ' '
|
|
)"
|
|
|
|
researched=$((total - soon))
|
|
|
|
echo
|
|
echo "╔══════════════════════════════════════╗"
|
|
echo "║ XH-1 RESEARCH STATUS ║"
|
|
echo "╚══════════════════════════════════════╝"
|
|
echo
|
|
|
|
printf " Total documents : %s\n" "$total"
|
|
printf " Research ready : %s\n" "$researched"
|
|
printf " Remaining SOON : %s\n" "$soon"
|
|
|
|
if (( total > 0 )); then
|
|
|
|
awk \
|
|
-v done="$researched" \
|
|
-v total="$total" \
|
|
'BEGIN {
|
|
printf " Progress : %.1f%%\n",
|
|
(done / total) * 100
|
|
}'
|
|
|
|
fi
|
|
|
|
echo
|
|
|
|
echo "Next topic:"
|
|
|
|
find_next_task || echo " None"
|
|
|
|
echo
|
|
}
|
|
|
|
# ------------------------------------------------------------
|
|
# Review command
|
|
# ------------------------------------------------------------
|
|
|
|
review_command() {
|
|
|
|
local file="${1:-}"
|
|
|
|
[[ -n "$file" ]] ||
|
|
die "Usage: $0 review <file>"
|
|
|
|
[[ -f "$file" ]] ||
|
|
die "File does not exist: $file"
|
|
|
|
local output
|
|
|
|
output="$STATE/responses/manual_review_$(timestamp).txt"
|
|
|
|
review_document "$file" "$output"
|
|
|
|
cat "$output"
|
|
}
|
|
|
|
# ------------------------------------------------------------
|
|
# Initialization
|
|
# ------------------------------------------------------------
|
|
|
|
initialize() {
|
|
|
|
mkdir -p \
|
|
"$STATE/logs" \
|
|
"$STATE/responses"
|
|
|
|
touch \
|
|
"$STATE/state.tsv"
|
|
|
|
init_config
|
|
|
|
echo
|
|
echo "XH-1 research harness initialized."
|
|
echo
|
|
echo "Configuration:"
|
|
echo " $CONFIG"
|
|
echo
|
|
echo "State:"
|
|
echo " $STATE"
|
|
echo
|
|
}
|
|
|
|
# ------------------------------------------------------------
|
|
# Help
|
|
# ------------------------------------------------------------
|
|
|
|
help() {
|
|
|
|
cat <<'EOF'
|
|
|
|
XH-1 RESEARCH HARNESS
|
|
=====================
|
|
|
|
Pure Bash autonomous research system.
|
|
|
|
USAGE
|
|
|
|
./xh1-research <command>
|
|
|
|
|
|
COMMANDS
|
|
|
|
init
|
|
|
|
Initialize the harness.
|
|
|
|
status
|
|
|
|
Show research progress.
|
|
|
|
next
|
|
|
|
Show the next SOON document.
|
|
|
|
run
|
|
|
|
Research the next topic.
|
|
|
|
run <file>
|
|
|
|
Research a specific document.
|
|
|
|
run-all
|
|
|
|
Continuously research every SOON document.
|
|
|
|
loop
|
|
|
|
Alias for run-all.
|
|
|
|
resume
|
|
|
|
Resume autonomous research.
|
|
|
|
review <file>
|
|
|
|
Manually review a research document.
|
|
|
|
help
|
|
|
|
Show this help.
|
|
|
|
|
|
EXAMPLES
|
|
|
|
./xh1-research init
|
|
|
|
./xh1-research status
|
|
|
|
./xh1-research next
|
|
|
|
./xh1-research run
|
|
|
|
./xh1-research run research/04-128-core/topology.md
|
|
|
|
./xh1-research run-all
|
|
|
|
./xh1-research review research/05-memory/cache-coherency.md
|
|
|
|
|
|
ENVIRONMENT
|
|
|
|
XH1_RESEARCH_ROOT
|
|
|
|
Research directory.
|
|
|
|
Default:
|
|
research
|
|
|
|
|
|
XH1_RESEARCH_CONFIG
|
|
|
|
Configuration file.
|
|
|
|
Default:
|
|
xh1-research.conf
|
|
|
|
|
|
CONFIGURATION
|
|
|
|
API_BASE_URL
|
|
|
|
OpenAI-compatible API base.
|
|
|
|
API_KEY_ENV
|
|
|
|
Environment variable containing API key.
|
|
|
|
MODEL
|
|
|
|
Model identifier.
|
|
|
|
MAX_RETRIES
|
|
|
|
API retry count.
|
|
|
|
DELAY_SECONDS
|
|
|
|
Delay between research iterations.
|
|
|
|
MAX_ITERATIONS
|
|
|
|
Maximum autonomous iterations.
|
|
|
|
0 = unlimited.
|
|
|
|
REVIEW_ENABLED
|
|
|
|
Enable reviewer agent.
|
|
|
|
AUTO_COMMIT
|
|
|
|
Automatically commit completed research.
|
|
|
|
|
|
SAFETY
|
|
|
|
Existing research is never overwritten.
|
|
|
|
A document is only modified if it still contains
|
|
a standalone SOON marker.
|
|
|
|
Git push is never performed automatically.
|
|
|
|
|
|
EOF
|
|
}
|
|
|
|
# ------------------------------------------------------------
|
|
# Main
|
|
# ------------------------------------------------------------
|
|
|
|
load_config
|
|
require_dependencies
|
|
|
|
COMMAND="${1:-status}"
|
|
|
|
case "$COMMAND" in
|
|
|
|
init)
|
|
initialize
|
|
;;
|
|
|
|
status)
|
|
status
|
|
;;
|
|
|
|
next)
|
|
find_next_task || true
|
|
;;
|
|
|
|
run)
|
|
run_one "${2:-}"
|
|
;;
|
|
|
|
run-all|loop|resume)
|
|
run_loop
|
|
;;
|
|
|
|
review)
|
|
review_command "${2:-}"
|
|
;;
|
|
|
|
help|-h|--help)
|
|
help
|
|
;;
|
|
|
|
*)
|
|
die "Unknown command: $COMMAND. Use --help."
|
|
|
|
esac
|