From 6febcdc3564b37e959e1c8f3d346c4898b3a545a Mon Sep 17 00:00:00 2001 From: satyaborg Date: Wed, 29 Jul 2026 15:11:39 +1000 Subject: [PATCH 1/3] chore: simplify spec agent prompt --- devloop | 64 ++++++++++------------------------------- scripts/devloop_test.sh | 27 ++++++++++++----- 2 files changed, 35 insertions(+), 56 deletions(-) diff --git a/devloop b/devloop index 99a5e3d..a0d0609 100755 --- a/devloop +++ b/devloop @@ -5307,9 +5307,8 @@ spec_command() { skill-path) printf '%s\n' "$skill"; return ;; esac - local context today prompt spec_dir target_path target_dir + local context prompt spec_dir target_path target_dir context="$(resolve_spec_context ${context_items[@]+"${context_items[@]}"})" - today="$(date +%F)" spec_dir="$(devloop_spec_dir)" if [ -n "$output" ]; then target_path="$(absolute_path "$output")" || return 1 @@ -5323,7 +5322,7 @@ spec_command() { target_dir="$(absolute_dir_path "$spec_dir")" || return 1 fi - prompt="$(spec_prompt "$context" "$target_path" "$force" "$skill" "$today" "$target_dir")" + prompt="$(spec_prompt "$context" "$target_path" "$force" "$target_dir")" printf 'agent: %s\n' "$(agent_label "$agent")" printf 'mode: interactive spec session\n' printf 'write: %s\n' "$target_dir" @@ -5331,10 +5330,7 @@ spec_command() { } resolve_spec_context() { - if [ "$#" -eq 0 ]; then - printf '%s\n' "No source material was provided. Use the cold-start interview path in the bundled skill to discover intent before writing the spec." - return - fi + if [ "$#" -eq 0 ]; then return; fi local first=true local item file for item in "$@"; do @@ -5345,7 +5341,7 @@ resolve_spec_context() { printf 'Source file: %s\n\n' "$file" cat "$file" else - printf 'Context:\n%s\n' "$item" + printf '%s\n' "$item" fi done } @@ -5354,52 +5350,22 @@ spec_prompt() { local context="$1" local output="$2" local force="$3" - local skill="$4" - local today="$5" - local target_dir="$6" - local target_line overwrite_line + local target_dir="$4" + local target_line if [ -n "$output" ]; then - target_line="Requested spec path: $output" + target_line="Output path: $output" else - target_line="Requested spec path: choose $target_dir/$today-.md" + target_line="Output directory: $target_dir" fi + + printf '%s\n\n' 'Use the installed `devloop-spec` skill.' + printf '%s\n' "$target_line" if [ "$force" = true ]; then - overwrite_line="Overwrite policy: overwriting the requested path is allowed." - else - overwrite_line="Overwrite policy: do not overwrite an existing spec; choose a non-conflicting path instead." + printf '\n%s\n' "Overwrite allowed: true" + fi + if [ -n "$context" ]; then + printf '\nContext:\n%s\n' "$context" fi - cat < - -Do not implement the change directly in this session unless the user explicitly -asks you to leave the devloop flow. - -Bundled skill path, for fallback only: $skill - -Context: -$context -EOF } launch_spec_agent() { diff --git a/scripts/devloop_test.sh b/scripts/devloop_test.sh index 62e61d7..22c7592 100755 --- a/scripts/devloop_test.sh +++ b/scripts/devloop_test.sh @@ -2784,13 +2784,18 @@ repo_specs_real="$(cd "$repo_specs" && pwd -P)" contains "$(cat /tmp/devloop-spec-test.out)" "interactive spec session" "spec command" contains "$(cat /tmp/devloop-spec-test.out)" "write: $repo_specs_real" "spec command target" if [ -f "$repo_specs/$(date +%F)-shell-migration-spec.md" ]; then fail "spec command wrote the spec instead of launching the agent"; fi -contains "$(cat /tmp/devloop-spec-agent-prompt.txt)" "Skill: use the installed devloop-spec skill." "spec prompt skill" -contains "$(cat /tmp/devloop-spec-agent-prompt.txt)" "Keep devloop as Bash." "spec prompt" -contains "$(cat /tmp/devloop-spec-agent-prompt.txt)" "Requested spec path: choose $repo_specs_real/$(date +%F)-.md" "spec prompt configured output" -contains "$(cat /tmp/devloop-spec-agent-prompt.txt)" "has open questions that could change the work" "spec prompt interview gate" -contains "$(cat /tmp/devloop-spec-agent-prompt.txt)" "Do not turn a conversation" "spec prompt interview gate" -contains "$(cat /tmp/devloop-spec-agent-prompt.txt)" "Devloop owns the implementation" "spec prompt ownership" -contains "$(cat /tmp/devloop-spec-agent-prompt.txt)" "devloop --create-pr " "spec prompt handoff" +spec_prompt_text="$(cat /tmp/devloop-spec-agent-prompt.txt)" +expected_spec_prompt="$(printf 'Use the installed `devloop-spec` skill.\n\nOutput directory: %s\n\nContext:\nKeep devloop as Bash.' "$repo_specs_real")" +equals "$spec_prompt_text" "$expected_spec_prompt" "spec prompt" + +( + cd "$repo" + HOME="$spec_home" main spec --agent "$agent" >/tmp/devloop-spec-test.out +) +spec_prompt_text="$(cat /tmp/devloop-spec-agent-prompt.txt)" +expected_spec_prompt="$(printf 'Use the installed `devloop-spec` skill.\n\nOutput directory: %s' "$repo_specs_real")" +equals "$spec_prompt_text" "$expected_spec_prompt" "cold-start spec prompt" +not_contains "$spec_prompt_text" "Context:" "cold-start spec prompt" contains "$(absolute_path "$work/absolute-path/nested.md")" "/absolute-path/nested.md" "absolute path" existing_spec="$repo/existing.md" existing_spec_real="$(cd "$repo" && pwd -P)/existing.md" @@ -2799,6 +2804,14 @@ rm -f /tmp/devloop-spec-agent-prompt.txt if (cd "$repo" && HOME="$spec_home" main spec --agent "$agent" --output "$existing_spec" "Replace me") >/tmp/devloop-spec-existing.out 2>/tmp/devloop-spec-existing.err; then fail "spec command allowed existing output without force"; fi contains "$(cat /tmp/devloop-spec-existing.err)" "spec already exists: $existing_spec_real" "spec existing output" if [ -f /tmp/devloop-spec-agent-prompt.txt ]; then fail "spec command launched agent for existing output"; fi + +( + cd "$repo" + HOME="$spec_home" main spec --agent "$agent" --output "$existing_spec" --force "Replace me" >/tmp/devloop-spec-test.out +) +spec_prompt_text="$(cat /tmp/devloop-spec-agent-prompt.txt)" +expected_spec_prompt="$(printf 'Use the installed `devloop-spec` skill.\n\nOutput path: %s\n\nOverwrite allowed: true\n\nContext:\nReplace me' "$existing_spec_real")" +equals "$spec_prompt_text" "$expected_spec_prompt" "forced spec prompt" ok "spec launch" cat > "$fake_bin/codex" <<'AGENT' From 808e44d3f5587b4177908b9d75e1d9653dc339f9 Mon Sep 17 00:00:00 2001 From: satyaborg Date: Wed, 29 Jul 2026 15:20:47 +1000 Subject: [PATCH 2/3] fix: preserve custom agent skill fallback --- devloop | 8 +++++--- scripts/devloop_test.sh | 7 ++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/devloop b/devloop index a0d0609..deb5f47 100755 --- a/devloop +++ b/devloop @@ -5322,7 +5322,7 @@ spec_command() { target_dir="$(absolute_dir_path "$spec_dir")" || return 1 fi - prompt="$(spec_prompt "$context" "$target_path" "$force" "$target_dir")" + prompt="$(spec_prompt "$context" "$target_path" "$force" "$skill" "$target_dir")" printf 'agent: %s\n' "$(agent_label "$agent")" printf 'mode: interactive spec session\n' printf 'write: %s\n' "$target_dir" @@ -5350,7 +5350,8 @@ spec_prompt() { local context="$1" local output="$2" local force="$3" - local target_dir="$4" + local skill="$4" + local target_dir="$5" local target_line if [ -n "$output" ]; then target_line="Output path: $output" @@ -5358,7 +5359,8 @@ spec_prompt() { target_line="Output directory: $target_dir" fi - printf '%s\n\n' 'Use the installed `devloop-spec` skill.' + printf '%s\n' 'Use the installed `devloop-spec` skill.' + printf 'If unavailable, read the bundled skill at: %s\n\n' "$skill" printf '%s\n' "$target_line" if [ "$force" = true ]; then printf '\n%s\n' "Overwrite allowed: true" diff --git a/scripts/devloop_test.sh b/scripts/devloop_test.sh index 22c7592..16258f1 100755 --- a/scripts/devloop_test.sh +++ b/scripts/devloop_test.sh @@ -2785,15 +2785,16 @@ contains "$(cat /tmp/devloop-spec-test.out)" "interactive spec session" "spec co contains "$(cat /tmp/devloop-spec-test.out)" "write: $repo_specs_real" "spec command target" if [ -f "$repo_specs/$(date +%F)-shell-migration-spec.md" ]; then fail "spec command wrote the spec instead of launching the agent"; fi spec_prompt_text="$(cat /tmp/devloop-spec-agent-prompt.txt)" -expected_spec_prompt="$(printf 'Use the installed `devloop-spec` skill.\n\nOutput directory: %s\n\nContext:\nKeep devloop as Bash.' "$repo_specs_real")" +expected_spec_prompt="$(printf 'Use the installed `devloop-spec` skill.\nIf unavailable, read the bundled skill at: %s/skills/devloop-spec/SKILL.md\n\nOutput directory: %s\n\nContext:\nKeep devloop as Bash.' "$REPO_ROOT" "$repo_specs_real")" equals "$spec_prompt_text" "$expected_spec_prompt" "spec prompt" +contains "$spec_prompt_text" "$REPO_ROOT/skills/devloop-spec/SKILL.md" "spec prompt fallback skill" ( cd "$repo" HOME="$spec_home" main spec --agent "$agent" >/tmp/devloop-spec-test.out ) spec_prompt_text="$(cat /tmp/devloop-spec-agent-prompt.txt)" -expected_spec_prompt="$(printf 'Use the installed `devloop-spec` skill.\n\nOutput directory: %s' "$repo_specs_real")" +expected_spec_prompt="$(printf 'Use the installed `devloop-spec` skill.\nIf unavailable, read the bundled skill at: %s/skills/devloop-spec/SKILL.md\n\nOutput directory: %s' "$REPO_ROOT" "$repo_specs_real")" equals "$spec_prompt_text" "$expected_spec_prompt" "cold-start spec prompt" not_contains "$spec_prompt_text" "Context:" "cold-start spec prompt" contains "$(absolute_path "$work/absolute-path/nested.md")" "/absolute-path/nested.md" "absolute path" @@ -2810,7 +2811,7 @@ if [ -f /tmp/devloop-spec-agent-prompt.txt ]; then fail "spec command launched a HOME="$spec_home" main spec --agent "$agent" --output "$existing_spec" --force "Replace me" >/tmp/devloop-spec-test.out ) spec_prompt_text="$(cat /tmp/devloop-spec-agent-prompt.txt)" -expected_spec_prompt="$(printf 'Use the installed `devloop-spec` skill.\n\nOutput path: %s\n\nOverwrite allowed: true\n\nContext:\nReplace me' "$existing_spec_real")" +expected_spec_prompt="$(printf 'Use the installed `devloop-spec` skill.\nIf unavailable, read the bundled skill at: %s/skills/devloop-spec/SKILL.md\n\nOutput path: %s\n\nOverwrite allowed: true\n\nContext:\nReplace me' "$REPO_ROOT" "$existing_spec_real")" equals "$spec_prompt_text" "$expected_spec_prompt" "forced spec prompt" ok "spec launch" From 6a8bd64cd209b9d9a00df33d63a5ac5d32476fea Mon Sep 17 00:00:00 2001 From: satyaborg Date: Wed, 29 Jul 2026 15:47:22 +1000 Subject: [PATCH 3/3] fix: escape spec prompt backticks --- devloop | 2 +- scripts/devloop_test.sh | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/devloop b/devloop index deb5f47..cd57806 100755 --- a/devloop +++ b/devloop @@ -5359,7 +5359,7 @@ spec_prompt() { target_line="Output directory: $target_dir" fi - printf '%s\n' 'Use the installed `devloop-spec` skill.' + printf "Use the installed \`devloop-spec\` skill.\n" printf 'If unavailable, read the bundled skill at: %s\n\n' "$skill" printf '%s\n' "$target_line" if [ "$force" = true ]; then diff --git a/scripts/devloop_test.sh b/scripts/devloop_test.sh index 16258f1..43cdf63 100755 --- a/scripts/devloop_test.sh +++ b/scripts/devloop_test.sh @@ -2785,7 +2785,7 @@ contains "$(cat /tmp/devloop-spec-test.out)" "interactive spec session" "spec co contains "$(cat /tmp/devloop-spec-test.out)" "write: $repo_specs_real" "spec command target" if [ -f "$repo_specs/$(date +%F)-shell-migration-spec.md" ]; then fail "spec command wrote the spec instead of launching the agent"; fi spec_prompt_text="$(cat /tmp/devloop-spec-agent-prompt.txt)" -expected_spec_prompt="$(printf 'Use the installed `devloop-spec` skill.\nIf unavailable, read the bundled skill at: %s/skills/devloop-spec/SKILL.md\n\nOutput directory: %s\n\nContext:\nKeep devloop as Bash.' "$REPO_ROOT" "$repo_specs_real")" +expected_spec_prompt="$(printf "Use the installed \`devloop-spec\` skill.\nIf unavailable, read the bundled skill at: %s/skills/devloop-spec/SKILL.md\n\nOutput directory: %s\n\nContext:\nKeep devloop as Bash." "$REPO_ROOT" "$repo_specs_real")" equals "$spec_prompt_text" "$expected_spec_prompt" "spec prompt" contains "$spec_prompt_text" "$REPO_ROOT/skills/devloop-spec/SKILL.md" "spec prompt fallback skill" @@ -2794,7 +2794,7 @@ contains "$spec_prompt_text" "$REPO_ROOT/skills/devloop-spec/SKILL.md" "spec pro HOME="$spec_home" main spec --agent "$agent" >/tmp/devloop-spec-test.out ) spec_prompt_text="$(cat /tmp/devloop-spec-agent-prompt.txt)" -expected_spec_prompt="$(printf 'Use the installed `devloop-spec` skill.\nIf unavailable, read the bundled skill at: %s/skills/devloop-spec/SKILL.md\n\nOutput directory: %s' "$REPO_ROOT" "$repo_specs_real")" +expected_spec_prompt="$(printf "Use the installed \`devloop-spec\` skill.\nIf unavailable, read the bundled skill at: %s/skills/devloop-spec/SKILL.md\n\nOutput directory: %s" "$REPO_ROOT" "$repo_specs_real")" equals "$spec_prompt_text" "$expected_spec_prompt" "cold-start spec prompt" not_contains "$spec_prompt_text" "Context:" "cold-start spec prompt" contains "$(absolute_path "$work/absolute-path/nested.md")" "/absolute-path/nested.md" "absolute path" @@ -2811,7 +2811,7 @@ if [ -f /tmp/devloop-spec-agent-prompt.txt ]; then fail "spec command launched a HOME="$spec_home" main spec --agent "$agent" --output "$existing_spec" --force "Replace me" >/tmp/devloop-spec-test.out ) spec_prompt_text="$(cat /tmp/devloop-spec-agent-prompt.txt)" -expected_spec_prompt="$(printf 'Use the installed `devloop-spec` skill.\nIf unavailable, read the bundled skill at: %s/skills/devloop-spec/SKILL.md\n\nOutput path: %s\n\nOverwrite allowed: true\n\nContext:\nReplace me' "$REPO_ROOT" "$existing_spec_real")" +expected_spec_prompt="$(printf "Use the installed \`devloop-spec\` skill.\nIf unavailable, read the bundled skill at: %s/skills/devloop-spec/SKILL.md\n\nOutput path: %s\n\nOverwrite allowed: true\n\nContext:\nReplace me" "$REPO_ROOT" "$existing_spec_real")" equals "$spec_prompt_text" "$expected_spec_prompt" "forced spec prompt" ok "spec launch"