merge: sync Kilo runtime branch with latest main

This commit is contained in:
Alex Alecu
2026-04-03 12:47:24 +03:00
43 changed files with 3868 additions and 407 deletions

View File

@@ -16,7 +16,7 @@ Read all files referenced by the invoking prompt's execution_context before star
## 1. Initialize
Parse `$ARGUMENTS` for `--from N` and `--only N` flags:
Parse `$ARGUMENTS` for `--from N`, `--only N`, and `--interactive` flags:
```bash
FROM_PHASE=""
@@ -29,10 +29,17 @@ if echo "$ARGUMENTS" | grep -qE '\-\-only\s+[0-9]'; then
ONLY_PHASE=$(echo "$ARGUMENTS" | grep -oE '\-\-only\s+[0-9]+\.?[0-9]*' | awk '{print $2}')
FROM_PHASE="$ONLY_PHASE"
fi
INTERACTIVE=""
if echo "$ARGUMENTS" | grep -q '\-\-interactive'; then
INTERACTIVE="true"
fi
```
When `--only` is set, also set `FROM_PHASE` to the same value so existing filter logic applies.
When `--interactive` is set, discuss runs inline with questions (not auto-answered), while plan and execute are dispatched as background agents. This keeps the main context lean — only discuss conversations accumulate — while preserving user input on all design decisions.
Bootstrap via milestone-level init:
```bash
@@ -58,6 +65,7 @@ Display startup banner:
If `ONLY_PHASE` is set, display: `Single phase mode: Phase ${ONLY_PHASE}`
Else if `FROM_PHASE` is set, display: `Starting from phase ${FROM_PHASE}`
If `INTERACTIVE` is set, display: `Mode: Interactive (discuss inline, plan+execute in background)`
</step>
@@ -230,18 +238,26 @@ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(${PADDED_PHASE
Proceed to 3b.
**If SKIP_DISCUSS is `false` (or unset):** Execute the smart_discuss step for this phase.
**If SKIP_DISCUSS is `false` (or unset):**
**IMPORTANT — Discuss must be single-pass in autonomous mode.**
The discuss step in `--auto` mode MUST NOT loop. If CONTEXT.md already exists after discuss completes, do NOT re-invoke discuss for the same phase. The `has_context` check below is authoritative — once true, discuss is done for this phase regardless of perceived "gaps" in the context file.
After smart_discuss completes, verify context was written:
**If `INTERACTIVE` is set:** Run the standard discuss-phase skill inline (asks interactive questions, waits for user answers). This preserves user input on all design decisions while keeping plan+execute out of the main context:
```
Skill(skill="gsd:discuss-phase", args="${PHASE_NUM}")
```
**If `INTERACTIVE` is NOT set:** Execute the smart_discuss step for this phase (batch table proposals, auto-optimized).
After discuss completes (either mode), verify context was written:
```bash
PHASE_STATE=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" init phase-op ${PHASE_NUM})
```
Check `has_context`. If false → go to handle_blocker: "Smart discuss for phase ${PHASE_NUM} did not produce CONTEXT.md."
Check `has_context`. If false → go to handle_blocker: "Discuss for phase ${PHASE_NUM} did not produce CONTEXT.md."
**3a.5. UI Design Contract (Frontend Phases)**
@@ -284,6 +300,20 @@ UI_SPEC_FILE=$(ls "${PHASE_DIR}"/*-UI-SPEC.md 2>/dev/null | head -1)
**3b. Plan**
**If `INTERACTIVE` is set:** Dispatch plan as a background agent to keep the main context lean. While plan runs, the workflow can immediately start discussing the next phase (see step 4).
```
Agent(
description="Plan phase ${PHASE_NUM}: ${PHASE_NAME}",
run_in_background=true,
prompt="Run plan-phase for phase ${PHASE_NUM}: Skill(skill=\"gsd:plan-phase\", args=\"${PHASE_NUM}\")"
)
```
Store the agent task_id. After discuss for the next phase completes (or if no next phase), wait for the plan agent to finish before proceeding to execute.
**If `INTERACTIVE` is NOT set (default):** Run plan inline as before.
```
Skill(skill="gsd:plan-phase", args="${PHASE_NUM}")
```
@@ -292,13 +322,29 @@ Verify plan produced output — re-run `init phase-op` and check `has_plans`. If
**3c. Execute**
**If `INTERACTIVE` is set:** Wait for the plan agent to complete (if not already), verify plans exist, then dispatch execute as a background agent:
```
Agent(
description="Execute phase ${PHASE_NUM}: ${PHASE_NAME}",
run_in_background=true,
prompt="Run execute-phase for phase ${PHASE_NUM}: Skill(skill=\"gsd:execute-phase\", args=\"${PHASE_NUM} --no-transition\")"
)
```
Store the agent task_id. The workflow can now start discussing the next phase while this phase executes in the background. Before starting post-execution routing for this phase, wait for the execute agent to complete.
**If `INTERACTIVE` is NOT set (default):** Run execute inline as before.
```
Skill(skill="gsd:execute-phase", args="${PHASE_NUM} --no-transition")
```
**3d. Post-Execution Routing**
After execute-phase returns, read the verification result:
**If `INTERACTIVE` is set:** Wait for the execute agent to complete before reading verification results.
After execute-phase returns (or the execute agent completes), read the verification result:
```bash
VERIFY_STATUS=$(grep "^status:" "${PHASE_DIR}"/*-VERIFICATION.md 2>/dev/null | head -1 | cut -d: -f2 | tr -d ' ')
@@ -733,6 +779,13 @@ Check for blockers in the Blockers/Concerns section. If blockers are found, go t
If incomplete phases remain: proceed to next phase, loop back to execute_phase.
**Interactive mode overlap:** When `INTERACTIVE` is set, the iterate step enables pipeline parallelism:
1. After discuss completes for Phase N, dispatch plan+execute as background agents
2. Immediately start discuss for Phase N+1 (the next incomplete phase) while Phase N builds
3. Before starting plan for Phase N+1, wait for Phase N's execute agent to complete and handle its post-execution routing (verification, gap closure, etc.)
This means the user is always answering discuss questions (lightweight, interactive) while the heavy work (planning, code generation) runs in the background. The main context only accumulates discuss conversations — plan and execute contexts are isolated in their agents.
If all phases complete, proceed to lifecycle step.
</step>
@@ -935,4 +988,10 @@ When any phase operation fails or a blocker is detected, present 3 options via A
- [ ] `--only N` exits cleanly after single phase completes
- [ ] `--only N` on already-complete phase exits with message
- [ ] `--only N` handle_blocker resume message uses --only flag
- [ ] `--interactive` runs discuss inline via gsd:discuss-phase (asks questions, waits for user)
- [ ] `--interactive` dispatches plan and execute as background agents (context isolation)
- [ ] `--interactive` enables pipeline parallelism: discuss Phase N+1 while Phase N builds
- [ ] `--interactive` main context only accumulates discuss conversations (lean)
- [ ] `--interactive` waits for background agents before post-execution routing
- [ ] `--interactive` compatible with `--only` and `--from` flags
</success_criteria>

View File

@@ -537,6 +537,15 @@ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
Extract `branching_strategy`, `phase_branch_template`, `milestone_branch_template`, and `commit_docs` from init JSON.
Detect base branch:
```bash
BASE_BRANCH=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get git.base_branch 2>/dev/null || echo "")
if [ -z "$BASE_BRANCH" ] || [ "$BASE_BRANCH" = "null" ]; then
BASE_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|^refs/remotes/origin/||')
BASE_BRANCH="${BASE_BRANCH:-main}"
fi
```
**If "none":** Skip to git_tag.
**For "phase" strategy:**
@@ -575,7 +584,7 @@ AskUserQuestion with options: Squash merge (Recommended), Merge with history, De
```bash
CURRENT_BRANCH=$(git branch --show-current)
git checkout main
git checkout ${BASE_BRANCH}
if [ "$BRANCHING_STRATEGY" = "phase" ]; then
for branch in $PHASE_BRANCHES; do
@@ -604,7 +613,7 @@ git checkout "$CURRENT_BRANCH"
```bash
CURRENT_BRANCH=$(git branch --show-current)
git checkout main
git checkout ${BASE_BRANCH}
if [ "$BRANCHING_STRATEGY" = "phase" ]; then
for branch in $PHASE_BRANCHES; do

View File

@@ -76,6 +76,17 @@ USE_WORKTREES=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get
When `USE_WORKTREES` is `false`, all executor agents run without `isolation="worktree"` — they execute sequentially on the main working tree instead of in parallel worktrees.
Read context window size for adaptive prompt enrichment:
```bash
CONTEXT_WINDOW=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get context_window 2>/dev/null || echo "200000")
```
When `CONTEXT_WINDOW >= 500000` (1M-class models), subagent prompts include richer context:
- Executor agents receive prior wave SUMMARY.md files and the phase CONTEXT.md/RESEARCH.md
- Verifier agents receive all PLAN.md, SUMMARY.md, CONTEXT.md files plus REQUIREMENTS.md
- This enables cross-phase awareness and history-aware verification
**If `phase_found` is false:** Error — phase directory not found.
**If `plan_count` is 0:** Error — no plans found in phase.
**If `state_exists` is false but `.planning/` exists:** Offer reconstruct or continue.
@@ -236,6 +247,7 @@ Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZAT
```
Task(
subagent_type="gsd-executor",
description="Execute plan {plan_number} of phase {phase_number}",
model="{executor_model}",
isolation="worktree",
prompt="
@@ -265,6 +277,11 @@ Execute each selected wave in sequence. Within a wave: parallel if `PARALLELIZAT
- .planning/PROJECT.md (Project context — core value, requirements, evolution rules)
- .planning/STATE.md (State)
- .planning/config.json (Config, if exists)
${CONTEXT_WINDOW >= 500000 ? `
- ${phase_dir}/*-CONTEXT.md (User decisions from discuss-phase — honors locked choices)
- ${phase_dir}/*-RESEARCH.md (Technical research — pitfalls and patterns to follow)
- ${prior_wave_summaries} (SUMMARY.md files from earlier waves in this phase — what was already built)
` : ''}
- ./CLAUDE.md (Project instructions, if exists — follow project-specific guidelines and coding conventions)
- .claude/skills/ or .agents/skills/ (Project skills, if either exists — list skills, read SKILL.md for each, follow relevant rules during implementation)
</files_to_read>
@@ -732,6 +749,7 @@ VERIFIER_SKILLS=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-ski
```
Task(
description="Verify phase {phase_number} goal achievement",
prompt="Verify phase {phase_number} goal achievement.
Phase directory: {phase_dir}
Phase goal: {goal from ROADMAP.md}
@@ -739,6 +757,18 @@ Phase requirement IDs: {phase_req_ids}
Check must_haves against actual codebase.
Cross-reference requirement IDs from PLAN frontmatter against REQUIREMENTS.md — every ID MUST be accounted for.
Create VERIFICATION.md.
<files_to_read>
Read these files before verification:
- {phase_dir}/*-PLAN.md (All plans — understand intent, check must_haves)
- {phase_dir}/*-SUMMARY.md (All summaries — cross-reference claimed vs actual)
- .planning/REQUIREMENTS.md (Requirement traceability)
${CONTEXT_WINDOW >= 500000 ? `- {phase_dir}/*-CONTEXT.md (User decisions — verify they were honored)
- {phase_dir}/*-RESEARCH.md (Known pitfalls — check for traps)
- Prior VERIFICATION.md files from earlier phases (regression check)
` : ''}
</files_to_read>
${VERIFIER_SKILLS}",
subagent_type="gsd-verifier",
model="{verifier_model}"

View File

@@ -36,7 +36,7 @@ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
AGENT_SKILLS_MAPPER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-codebase-mapper 2>/dev/null)
```
Extract from init JSON: `mapper_model`, `commit_docs`, `codebase_dir`, `existing_maps`, `has_maps`, `codebase_dir_exists`.
Extract from init JSON: `mapper_model`, `commit_docs`, `codebase_dir`, `existing_maps`, `has_maps`, `codebase_dir_exists`, `subagent_timeout`.
</step>
<step name="check_existing">
@@ -199,9 +199,11 @@ Wait for all 4 agents to complete using TaskOutput tool.
TaskOutput tool:
task_id: "{task_id from Agent result}"
block: true
timeout: 300000
timeout: {subagent_timeout from init context, default 300000}
```
> The timeout is configurable via `workflow.subagent_timeout` in `.planning/config.json` (milliseconds). Default: 300000 (5 minutes). Increase for large codebases or slower models.
Call TaskOutput for all 4 agents in parallel (single message with 4 TaskOutput calls).
Once all TaskOutput calls return, read each agent's output file to collect confirmations.

View File

@@ -27,8 +27,11 @@ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
AGENT_SKILLS_RESEARCHER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-researcher 2>/dev/null)
AGENT_SKILLS_PLANNER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-planner 2>/dev/null)
AGENT_SKILLS_CHECKER=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" agent-skills gsd-checker 2>/dev/null)
CONTEXT_WINDOW=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get context_window 2>/dev/null || echo "200000")
```
When `CONTEXT_WINDOW >= 500000`, the planner prompt includes prior phase CONTEXT.md files so cross-phase decisions are consistent (e.g., "use library X for all data fetching" from Phase 2 is visible to Phase 5's planner).
Parse JSON for: `researcher_model`, `planner_model`, `checker_model`, `research_enabled`, `plan_checker_enabled`, `nyquist_validation_enabled`, `commit_docs`, `text_mode`, `phase_found`, `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `padded_phase`, `has_research`, `has_context`, `has_reviews`, `has_plans`, `plan_count`, `planning_exists`, `roadmap_exists`, `phase_req_ids`.
**File paths (for <files_to_read> blocks):** `state_path`, `roadmap_path`, `requirements_path`, `context_path`, `research_path`, `verification_path`, `uat_path`, `reviews_path`. These are null if files don't exist.
@@ -576,6 +579,11 @@ Planner prompt:
- {uat_path} (UAT Gaps - if --gaps)
- {reviews_path} (Cross-AI Review Feedback - if --reviews)
- {UI_SPEC_PATH} (UI Design Contract — visual/interaction specs, if exists)
${CONTEXT_WINDOW >= 500000 ? `
**Cross-phase context (1M model enrichment):**
- Prior phase CONTEXT.md files (locked decisions from earlier phases — maintain consistency)
- Prior phase SUMMARY.md files (what was actually built — reuse patterns, avoid duplication)
` : ''}
</files_to_read>
${AGENT_SKILLS_PLANNER}

View File

@@ -19,6 +19,7 @@ command -v gemini >/dev/null 2>&1 && echo "gemini:available" || echo "gemini:mis
command -v claude >/dev/null 2>&1 && echo "claude:available" || echo "claude:missing"
command -v codex >/dev/null 2>&1 && echo "codex:available" || echo "codex:missing"
command -v coderabbit >/dev/null 2>&1 && echo "coderabbit:available" || echo "coderabbit:missing"
command -v opencode >/dev/null 2>&1 && echo "opencode:available" || echo "opencode:missing"
```
Parse flags from `$ARGUMENTS`:
@@ -26,6 +27,7 @@ Parse flags from `$ARGUMENTS`:
- `--claude` → include Claude
- `--codex` → include Codex
- `--coderabbit` → include CodeRabbit
- `--opencode` → include OpenCode
- `--all` → include all available
- No flags → include all available
@@ -35,6 +37,7 @@ No external AI CLIs found. Install at least one:
- gemini: https://github.com/google-gemini/gemini-cli
- codex: https://github.com/openai/codex
- claude: https://github.com/anthropics/claude-code
- opencode: https://opencode.ai (leverages GitHub Copilot subscription models)
Then run /gsd:review again.
```
@@ -141,6 +144,14 @@ Note: CodeRabbit reviews the current git diff/working tree — it does not accep
coderabbit review --prompt-only 2>/dev/null > /tmp/gsd-review-coderabbit-{phase}.md
```
**OpenCode (via GitHub Copilot):**
```bash
cat /tmp/gsd-review-prompt-{phase}.md | opencode run - 2>/dev/null > /tmp/gsd-review-opencode-{phase}.md
if [ ! -s /tmp/gsd-review-opencode-{phase}.md ]; then
echo "OpenCode review failed or returned empty output." > /tmp/gsd-review-opencode-{phase}.md
fi
```
If a CLI fails, log the error and continue with remaining CLIs.
Display progress:
@@ -160,7 +171,7 @@ Combine all review responses into `{phase_dir}/{padded_phase}-REVIEWS.md`:
```markdown
---
phase: {N}
reviewers: [gemini, claude, codex, coderabbit]
reviewers: [gemini, claude, codex, coderabbit, opencode]
reviewed_at: {ISO timestamp}
plans_reviewed: [{list of PLAN.md files}]
---
@@ -191,6 +202,12 @@ plans_reviewed: [{list of PLAN.md files}]
---
## OpenCode Review
{opencode review content}
---
## Consensus Summary
{synthesize common concerns across all reviewers}

View File

@@ -24,6 +24,15 @@ CONFIG=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" state load)
```
Extract: `branching_strategy`, `branch_name`.
Detect base branch for PRs and merges:
```bash
BASE_BRANCH=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" config-get git.base_branch 2>/dev/null || echo "")
if [ -z "$BASE_BRANCH" ] || [ "$BASE_BRANCH" = "null" ]; then
BASE_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|^refs/remotes/origin/||')
BASE_BRANCH="${BASE_BRANCH:-main}"
fi
```
</step>
<step name="preflight_checks">
@@ -46,7 +55,7 @@ Verify the work is ready to ship:
```bash
CURRENT_BRANCH=$(git branch --show-current)
```
If on `main`/`master`: warn — should be on a feature branch.
If on `${BASE_BRANCH}`: warn — should be on a feature branch.
If branching_strategy is `none`: offer to create a branch now.
4. **Remote configured?**
@@ -74,7 +83,7 @@ If push fails (e.g., no upstream): set upstream:
git push --set-upstream origin ${CURRENT_BRANCH} 2>&1
```
Report: "Pushed `{branch}` to origin ({commit_count} commits ahead of main)"
Report: "Pushed `{branch}` to origin ({commit_count} commits ahead of ${BASE_BRANCH})"
</step>
<step name="generate_pr_body">
@@ -141,7 +150,7 @@ Create the PR using the generated body:
gh pr create \
--title "Phase ${PHASE_NUMBER}: ${PHASE_NAME}" \
--body "${PR_BODY}" \
--base main
--base ${BASE_BRANCH}
```
If `--draft` flag was passed: add `--draft`.
@@ -194,7 +203,7 @@ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(${padded_phase
## ✓ Phase {X}: {Name} — Shipped
PR: #{number} ({url})
Branch: {branch} → main
Branch: {branch} → ${BASE_BRANCH}
Commits: {count}
Verification: ✓ Passed
Requirements: {N} REQ-IDs addressed