Vernon Wee Hong KOH ревизий этого фрагмента 2 months ago. К ревизии
8 files changed, 309 insertions, 12 deletions
README.md
| @@ -30,3 +30,17 @@ eval "$(starship init zsh)" | |||
| 30 | 30 | ``` | |
| 31 | 31 | ||
| 32 | 32 | Starship owns the prompt and loads after Oh My Zsh. The managed Starship config is installed at `~/.config/starship.toml`. A Nerd Font is required for the Powerline symbols. | |
| 33 | + | ||
| 34 | + | ## Plan-build workflow | |
| 35 | + | ||
| 36 | + | `plan_build` launches Claude Code as the implementation orchestrator, with Codex and CodeRabbit as independent reviewers. The configuration installer also installs its workflow at `~/.claude/skills/plan-build/SKILL.md`. | |
| 37 | + | ||
| 38 | + | ```zsh | |
| 39 | + | plan_build # Standard plan and build | |
| 40 | + | plan_build --prompt # Enhance the payload with Auggie first | |
| 41 | + | plan_build --writing-plan # Superpowers implementation plan, Codex review, then build | |
| 42 | + | plan_build --prompt --brainstorm # Auggie, Superpowers design and plan, Codex review, then build | |
| 43 | + | plan_build --yolo --writing-plan # Pass --yolo through to Claude Code | |
| 44 | + | ``` | |
| 45 | + | ||
| 46 | + | `--brainstorm` and `--writing-plan` are mutually exclusive. They require the enabled `superpowers@claude-plugins-official` Claude Code plugin; `plan_build` reports the install or enable command and exits before Auggie when the requirement is not met. | |
config.sh
| @@ -12,8 +12,10 @@ CONFIG_FILES=( | |||
| 12 | 12 | ".zshrc" | |
| 13 | 13 | ".config/starship.toml" | |
| 14 | 14 | ) | |
| 15 | + | PLAN_BUILD_SKILL_TARGET="$HOME/.claude/skills/plan-build/SKILL.md" | |
| 15 | 16 | ||
| 16 | 17 | echo "Starting configuration download..." | |
| 18 | + | download_failed=0 | |
| 17 | 19 | ||
| 18 | 20 | for f in "${CONFIG_FILES[@]}"; do | |
| 19 | 21 | # Remove the leading dot for the URL path | |
| @@ -21,16 +23,35 @@ for f in "${CONFIG_FILES[@]}"; do | |||
| 21 | 23 | [[ "$f" == ".config/starship.toml" ]] && remote_name="starship.toml" | |
| 22 | 24 | url="$GIST_RAW_BASE/$remote_name" | |
| 23 | 25 | target="$HOME/$f" | |
| 26 | + | tmp="${target}.tmp.$$" | |
| 24 | 27 | ||
| 25 | 28 | echo "Downloading $f..." | |
| 26 | 29 | mkdir -p "$(dirname "$target")" | |
| 27 | 30 | ||
| 28 | 31 | # Use -f to fail silently on server errors, -s for silent, -L to follow redirects | |
| 29 | - | if curl -fsSL "$url" -o "$target"; then | |
| 32 | + | if curl -fsSL "$url" -o "$tmp" && mv "$tmp" "$target"; then | |
| 30 | 33 | echo "Successfully updated $target" | |
| 31 | 34 | else | |
| 35 | + | rm -f "$tmp" | |
| 32 | 36 | echo "Error: Failed to download $f from $url" >&2 | |
| 37 | + | download_failed=1 | |
| 33 | 38 | fi | |
| 34 | 39 | done | |
| 35 | 40 | ||
| 41 | + | echo "Downloading Claude Code plan-build workflow..." | |
| 42 | + | mkdir -p "$(dirname "$PLAN_BUILD_SKILL_TARGET")" | |
| 43 | + | skill_tmp="${PLAN_BUILD_SKILL_TARGET}.tmp.$$" | |
| 44 | + | if curl -fsSL "$GIST_RAW_BASE/orchestrate-loop.md" -o "$skill_tmp" && mv "$skill_tmp" "$PLAN_BUILD_SKILL_TARGET"; then | |
| 45 | + | echo "Successfully updated $PLAN_BUILD_SKILL_TARGET" | |
| 46 | + | else | |
| 47 | + | rm -f "$skill_tmp" | |
| 48 | + | echo "Error: Failed to download the plan-build workflow" >&2 | |
| 49 | + | download_failed=1 | |
| 50 | + | fi | |
| 51 | + | ||
| 52 | + | if [ "$download_failed" -ne 0 ]; then | |
| 53 | + | echo "Configuration download completed with errors." >&2 | |
| 54 | + | exit 1 | |
| 55 | + | fi | |
| 56 | + | ||
| 36 | 57 | echo "Done! All configuration files have been replaced." | |
func
| @@ -430,17 +430,86 @@ prompt() { | |||
| 430 | 430 | # ----------------------------------------------------------------------------- | |
| 431 | 431 | # Function: plan_build (Claude Code multi-agent workflow orchestrator) | |
| 432 | 432 | # ----------------------------------------------------------------------------- | |
| 433 | + | _plan_build_superpowers_state() { | |
| 434 | + | awk ' | |
| 435 | + | BEGIN { | |
| 436 | + | RS = "}" | |
| 437 | + | state = "missing" | |
| 438 | + | printed = 0 | |
| 439 | + | } | |
| 440 | + | /"id"[[:space:]]*:[[:space:]]*"superpowers@claude-plugins-official"/ { | |
| 441 | + | state = "installed" | |
| 442 | + | if ($0 ~ /"enabled"[[:space:]]*:[[:space:]]*true/) { | |
| 443 | + | state = "enabled" | |
| 444 | + | } else if ($0 ~ /"enabled"[[:space:]]*:[[:space:]]*false/) { | |
| 445 | + | state = "disabled" | |
| 446 | + | } | |
| 447 | + | print state | |
| 448 | + | printed = 1 | |
| 449 | + | exit | |
| 450 | + | } | |
| 451 | + | END { | |
| 452 | + | if (!printed) { | |
| 453 | + | print state | |
| 454 | + | } | |
| 455 | + | } | |
| 456 | + | ' | |
| 457 | + | } | |
| 458 | + | ||
| 459 | + | _plan_build_superpowers_preflight() { | |
| 460 | + | local plugin_json | |
| 461 | + | local plugin_state | |
| 462 | + | ||
| 463 | + | case "${CLAUDE_CODE_SAFE_MODE:-}" in | |
| 464 | + | 1|true|TRUE|yes|YES|on|ON) | |
| 465 | + | echo "❌ Error: Claude Code safe mode disables Superpowers." | |
| 466 | + | echo "Unset CLAUDE_CODE_SAFE_MODE before using --brainstorm or --writing-plan." | |
| 467 | + | return 1 | |
| 468 | + | ;; | |
| 469 | + | esac | |
| 470 | + | ||
| 471 | + | if ! plugin_json="$(command claude plugin list --json 2>/dev/null)"; then | |
| 472 | + | echo "❌ Error: Unable to inspect Claude Code plugins." | |
| 473 | + | echo "Run 'claude plugin list' to diagnose the problem." | |
| 474 | + | return 1 | |
| 475 | + | fi | |
| 476 | + | ||
| 477 | + | plugin_state="$(printf '%s\n' "$plugin_json" | _plan_build_superpowers_state)" | |
| 478 | + | ||
| 479 | + | case "$plugin_state" in | |
| 480 | + | enabled) | |
| 481 | + | return 0 | |
| 482 | + | ;; | |
| 483 | + | disabled) | |
| 484 | + | echo "❌ Error: Claude Code Superpowers is installed but disabled." | |
| 485 | + | echo "Enable it with: claude plugin enable superpowers@claude-plugins-official" | |
| 486 | + | ;; | |
| 487 | + | missing) | |
| 488 | + | echo "❌ Error: Claude Code Superpowers is required for --brainstorm and --writing-plan." | |
| 489 | + | echo "Install it in Claude Code with: /plugin install superpowers@claude-plugins-official" | |
| 490 | + | ;; | |
| 491 | + | *) | |
| 492 | + | echo "❌ Error: Unable to determine Claude Code Superpowers status." | |
| 493 | + | echo "Run 'claude plugin list' to diagnose the problem." | |
| 494 | + | ;; | |
| 495 | + | esac | |
| 496 | + | ||
| 497 | + | return 1 | |
| 498 | + | } | |
| 499 | + | ||
| 433 | 500 | plan_build() { | |
| 434 | 501 | local claude_args=() | |
| 435 | 502 | local use_yolo=0 | |
| 436 | 503 | local enhance_payload=0 | |
| 504 | + | local planning_mode="standard" | |
| 505 | + | local usage="Usage: plan_build [--yolo] [--prompt] [--brainstorm | --writing-plan]" | |
| 437 | 506 | ||
| 438 | 507 | while [ $# -gt 0 ]; do | |
| 439 | 508 | case "$1" in | |
| 440 | 509 | --yolo) | |
| 441 | 510 | if [ "$use_yolo" -eq 1 ]; then | |
| 442 | 511 | echo "Error: Duplicate argument: --yolo" | |
| 443 | - | echo "Usage: plan_build [--yolo] [--prompt]" | |
| 512 | + | echo "$usage" | |
| 444 | 513 | return 1 | |
| 445 | 514 | fi | |
| 446 | 515 | use_yolo=1 | |
| @@ -449,14 +518,40 @@ plan_build() { | |||
| 449 | 518 | --prompt) | |
| 450 | 519 | if [ "$enhance_payload" -eq 1 ]; then | |
| 451 | 520 | echo "Error: Duplicate argument: --prompt" | |
| 452 | - | echo "Usage: plan_build [--yolo] [--prompt]" | |
| 521 | + | echo "$usage" | |
| 453 | 522 | return 1 | |
| 454 | 523 | fi | |
| 455 | 524 | enhance_payload=1 | |
| 456 | 525 | ;; | |
| 526 | + | --brainstorm) | |
| 527 | + | if [ "$planning_mode" = "brainstorm" ]; then | |
| 528 | + | echo "Error: Duplicate argument: --brainstorm" | |
| 529 | + | echo "$usage" | |
| 530 | + | return 1 | |
| 531 | + | fi | |
| 532 | + | if [ "$planning_mode" != "standard" ]; then | |
| 533 | + | echo "Error: --brainstorm and --writing-plan are mutually exclusive." | |
| 534 | + | echo "$usage" | |
| 535 | + | return 1 | |
| 536 | + | fi | |
| 537 | + | planning_mode="brainstorm" | |
| 538 | + | ;; | |
| 539 | + | --writing-plan) | |
| 540 | + | if [ "$planning_mode" = "writing-plan" ]; then | |
| 541 | + | echo "Error: Duplicate argument: --writing-plan" | |
| 542 | + | echo "$usage" | |
| 543 | + | return 1 | |
| 544 | + | fi | |
| 545 | + | if [ "$planning_mode" != "standard" ]; then | |
| 546 | + | echo "Error: --brainstorm and --writing-plan are mutually exclusive." | |
| 547 | + | echo "$usage" | |
| 548 | + | return 1 | |
| 549 | + | fi | |
| 550 | + | planning_mode="writing-plan" | |
| 551 | + | ;; | |
| 457 | 552 | *) | |
| 458 | 553 | echo "Error: Unknown argument: $1" | |
| 459 | - | echo "Usage: plan_build [--yolo] [--prompt]" | |
| 554 | + | echo "$usage" | |
| 460 | 555 | return 1 | |
| 461 | 556 | ;; | |
| 462 | 557 | esac | |
| @@ -464,6 +559,9 @@ plan_build() { | |||
| 464 | 559 | done | |
| 465 | 560 | ||
| 466 | 561 | require_cli claude "Claude Code CLI" || return 1 | |
| 562 | + | if [ "$planning_mode" != "standard" ]; then | |
| 563 | + | _plan_build_superpowers_preflight || return 1 | |
| 564 | + | fi | |
| 467 | 565 | require_cli codex "Codex CLI" || return 1 | |
| 468 | 566 | require_cli coderabbit "CodeRabbit CLI" || return 1 | |
| 469 | 567 | if [ "$enhance_payload" -eq 1 ]; then | |
| @@ -538,9 +636,24 @@ plan_build() { | |||
| 538 | 636 | esac | |
| 539 | 637 | fi | |
| 540 | 638 | ||
| 541 | - | echo "🚀 Launching Claude Code with your multi-agent workflow..." | |
| 639 | + | local planning_instruction | |
| 640 | + | case "$planning_mode" in | |
| 641 | + | brainstorm) | |
| 642 | + | planning_instruction="Planning mode: brainstorm. Use the superpowers:brainstorming skill, including its approval gates and transition to superpowers:writing-plans. After the implementation plan is saved, return to the plan-build workflow for Codex plan review before implementation." | |
| 643 | + | ;; | |
| 644 | + | writing-plan) | |
| 645 | + | planning_instruction="Planning mode: writing-plan. Use the superpowers:writing-plans skill with the payload as the requirements. After the implementation plan is saved, return to the plan-build workflow for Codex plan review before implementation." | |
| 646 | + | ;; | |
| 647 | + | *) | |
| 648 | + | planning_instruction="Planning mode: standard. Create the workflow's normal short implementation plan." | |
| 649 | + | ;; | |
| 650 | + | esac | |
| 651 | + | ||
| 652 | + | echo "🚀 Launching Claude Code with your multi-agent workflow ($planning_mode planning)..." | |
| 653 | + | ||
| 654 | + | claude "${claude_args[@]}" "Please read \`~/.claude/skills/plan-build/SKILL.md\` and strictly follow the 8-step multi-agent workflow to implement the following task. | |
| 542 | 655 | ||
| 543 | - | claude "${claude_args[@]}" "Please read \`~/.claude/skills/plan-build/SKILL.md\` and strictly follow the 7-step multi-agent workflow to implement the following task: | |
| 656 | + | $planning_instruction | |
| 544 | 657 | ||
| 545 | 658 | $payload" | |
| 546 | 659 | } | |
orchestrate-loop.md
| @@ -11,7 +11,7 @@ Use this workflow when `plan_build` hands Claude Code an implementation task. Th | |||
| 11 | 11 | - Do not call the task complete until validation has run or the reason it cannot run is documented. | |
| 12 | 12 | - If any agent reports a plausible correctness, security, data-loss, migration, or test risk, resolve it or explicitly document why it is not applicable. | |
| 13 | 13 | ||
| 14 | - | ## The 7-Step Workflow | |
| 14 | + | ## The 8-Step Workflow | |
| 15 | 15 | ||
| 16 | 16 | ### 1. Intake | |
| 17 | 17 | ||
| @@ -37,9 +37,40 @@ Then read the smallest useful set of files. Prefer `rg`, package manifests, test | |||
| 37 | 37 | ||
| 38 | 38 | ### 3. Plan | |
| 39 | 39 | ||
| 40 | - | Create a short implementation plan with concrete steps. Include validation commands. If the task touches behavior, data, auth, payments, destructive actions, or shared infrastructure, include a rollback or compatibility note. | |
| 40 | + | Follow the planning mode supplied by `plan_build`: | |
| 41 | 41 | ||
| 42 | - | ### 4. Implement | |
| 42 | + | - `standard`: Create a short implementation plan with concrete steps and validation commands. | |
| 43 | + | - `brainstorm`: Invoke `superpowers:brainstorming`, honor its design and written-spec approval gates, and let it transition to `superpowers:writing-plans` after approval. | |
| 44 | + | - `writing-plan`: Invoke `superpowers:writing-plans` directly, treating the payload as the requirements or specification. | |
| 45 | + | ||
| 46 | + | For either Superpowers mode, save the artifacts at the paths selected by the skills. When `writing-plans` reaches its execution handoff, return to this workflow instead of starting implementation: Codex must review the plan first. If the user rejects or cancels a required approval, stop cleanly without modifying implementation files. | |
| 47 | + | ||
| 48 | + | If the task touches behavior, data, auth, payments, destructive actions, or shared infrastructure, include a rollback or compatibility note. | |
| 49 | + | ||
| 50 | + | ### 4. Codex Plan Review | |
| 51 | + | ||
| 52 | + | Run this step only for `brainstorm` and `writing-plan` modes. Ask Codex for an independent, read-only review of the approved spec, when present, and the implementation plan before touching implementation files. Provide the original payload and artifact paths. Ask it to focus on requirement coverage, incorrect assumptions, unsafe migrations, missing edge cases, inadequate tests, and steps that are too vague to execute. | |
| 53 | + | ||
| 54 | + | Recommended prompt shape: | |
| 55 | + | ||
| 56 | + | ```text | |
| 57 | + | Review these planning artifacts before implementation. Check requirement coverage, technical correctness, repository fit, edge cases, migration or rollback risk, test coverage, and whether every step is executable. Report concrete findings only; do not modify files. | |
| 58 | + | ||
| 59 | + | Task: | |
| 60 | + | <payload> | |
| 61 | + | ||
| 62 | + | Spec: | |
| 63 | + | <spec path, if present> | |
| 64 | + | ||
| 65 | + | Implementation plan: | |
| 66 | + | <plan path> | |
| 67 | + | ``` | |
| 68 | + | ||
| 69 | + | Use a read-only, ephemeral Codex invocation. Resolve every valid finding in the artifacts and repeat the review if revisions are substantial. If an artifact is missing or empty, or Codex cannot complete the review, stop before implementation and report the failure. | |
| 70 | + | ||
| 71 | + | In `standard` mode, skip this step and continue directly to implementation. | |
| 72 | + | ||
| 73 | + | ### 5. Implement | |
| 43 | 74 | ||
| 44 | 75 | Make the change in small, reviewable edits: | |
| 45 | 76 | ||
| @@ -50,7 +81,7 @@ Make the change in small, reviewable edits: | |||
| 50 | 81 | ||
| 51 | 82 | After each meaningful edit group, re-check the diff for accidental changes. | |
| 52 | 83 | ||
| 53 | - | ### 5. Codex Review Pass | |
| 84 | + | ### 6. Codex Code Review Pass | |
| 54 | 85 | ||
| 55 | 86 | Ask Codex for an independent review of the local diff before finalizing. Provide the task, constraints, and current diff. Ask it to focus on bugs, edge cases, missing tests, regressions, and simpler project-native alternatives. | |
| 56 | 87 | ||
| @@ -68,13 +99,13 @@ Diff: | |||
| 68 | 99 | ||
| 69 | 100 | Apply fixes for valid findings, then repeat this review pass if the fixes are non-trivial. | |
| 70 | 101 | ||
| 71 | - | ### 6. CodeRabbit Review Pass | |
| 102 | + | ### 7. CodeRabbit Review Pass | |
| 72 | 103 | ||
| 73 | 104 | Run CodeRabbit on the branch or diff when available. Treat its output as advisory but investigate every concrete finding. | |
| 74 | 105 | ||
| 75 | 106 | If CodeRabbit cannot run locally, record the command attempted and the failure. Continue with manual validation rather than blocking indefinitely. | |
| 76 | 107 | ||
| 77 | - | ### 7. Validate And Close | |
| 108 | + | ### 8. Validate And Close | |
| 78 | 109 | ||
| 79 | 110 | Run the planned validation commands, such as: | |
| 80 | 111 | ||
test_plan_build.zsh(файл создан)
| @@ -0,0 +1,85 @@ | |||
| 1 | + | #!/usr/bin/env zsh | |
| 2 | + | ||
| 3 | + | set -eu | |
| 4 | + | ||
| 5 | + | repo_dir="${0:A:h}" | |
| 6 | + | source "$repo_dir/func" | |
| 7 | + | ||
| 8 | + | failures=0 | |
| 9 | + | ||
| 10 | + | assert_equal() { | |
| 11 | + | local expected="$1" | |
| 12 | + | local actual="$2" | |
| 13 | + | local label="$3" | |
| 14 | + | ||
| 15 | + | if [ "$actual" != "$expected" ]; then | |
| 16 | + | print -u2 -- "FAIL: $label (expected '$expected', got '$actual')" | |
| 17 | + | failures=$((failures + 1)) | |
| 18 | + | fi | |
| 19 | + | } | |
| 20 | + | ||
| 21 | + | assert_contains() { | |
| 22 | + | local output="$1" | |
| 23 | + | local expected="$2" | |
| 24 | + | local label="$3" | |
| 25 | + | ||
| 26 | + | if [[ "$output" != *"$expected"* ]]; then | |
| 27 | + | print -u2 -- "FAIL: $label (missing '$expected')" | |
| 28 | + | failures=$((failures + 1)) | |
| 29 | + | fi | |
| 30 | + | } | |
| 31 | + | ||
| 32 | + | plugin_state() { | |
| 33 | + | printf '%s\n' "$1" | _plan_build_superpowers_state | |
| 34 | + | } | |
| 35 | + | ||
| 36 | + | assert_equal "enabled" "$(plugin_state '[{"id":"superpowers@claude-plugins-official","enabled":true}]')" "compact enabled JSON" | |
| 37 | + | assert_equal "disabled" "$(plugin_state $'[\n {\n "enabled": false,\n "id": "superpowers@claude-plugins-official"\n }\n]')" "reordered disabled JSON" | |
| 38 | + | assert_equal "enabled" "$(plugin_state $'[\n {"enabled": false, "id": "other@market"},\n {"enabled": true, "id": "superpowers@claude-plugins-official"}\n]')" "multiple plugin JSON" | |
| 39 | + | assert_equal "missing" "$(plugin_state '[{"id":"coderabbit@claude-plugins-official","enabled":true}]')" "missing plugin JSON" | |
| 40 | + | assert_equal "installed" "$(plugin_state '[{"id":"superpowers@claude-plugins-official"}]')" "malformed plugin JSON" | |
| 41 | + | ||
| 42 | + | output="$(plan_build --brainstorm --writing-plan 2>&1)" && rc=0 || rc=$? | |
| 43 | + | assert_equal "1" "$rc" "mutually exclusive flags status" | |
| 44 | + | assert_contains "$output" "mutually exclusive" "mutually exclusive flags message" | |
| 45 | + | ||
| 46 | + | output="$(plan_build --brainstorm --brainstorm 2>&1)" && rc=0 || rc=$? | |
| 47 | + | assert_equal "1" "$rc" "duplicate brainstorm status" | |
| 48 | + | assert_contains "$output" "Duplicate argument: --brainstorm" "duplicate brainstorm message" | |
| 49 | + | ||
| 50 | + | output="$(plan_build --writing-plan --writing-plan 2>&1)" && rc=0 || rc=$? | |
| 51 | + | assert_equal "1" "$rc" "duplicate writing-plan status" | |
| 52 | + | assert_contains "$output" "Duplicate argument: --writing-plan" "duplicate writing-plan message" | |
| 53 | + | ||
| 54 | + | export CLAUDE_CODE_SAFE_MODE=1 | |
| 55 | + | output="$(_plan_build_superpowers_preflight 2>&1)" && rc=0 || rc=$? | |
| 56 | + | unset CLAUDE_CODE_SAFE_MODE | |
| 57 | + | assert_equal "1" "$rc" "safe mode status" | |
| 58 | + | assert_contains "$output" "safe mode disables Superpowers" "safe mode message" | |
| 59 | + | ||
| 60 | + | require_cli() { return 0; } | |
| 61 | + | _plan_build_superpowers_preflight() { return 0; } | |
| 62 | + | claude() { | |
| 63 | + | printf 'CLAUDE_ARGS:' | |
| 64 | + | printf ' <%s>' "$@" | |
| 65 | + | printf '\n' | |
| 66 | + | } | |
| 67 | + | ||
| 68 | + | output="$(printf 'build feature\nEOF\n' | plan_build --writing-plan --yolo 2>&1)" && rc=0 || rc=$? | |
| 69 | + | assert_equal "0" "$rc" "writing-plan launch status" | |
| 70 | + | assert_contains "$output" "Planning mode: writing-plan" "writing-plan prompt" | |
| 71 | + | assert_contains "$output" "<--yolo>" "yolo forwarding" | |
| 72 | + | ||
| 73 | + | output="$(printf 'build feature\nEOF\n' | plan_build --brainstorm 2>&1)" && rc=0 || rc=$? | |
| 74 | + | assert_equal "0" "$rc" "brainstorm launch status" | |
| 75 | + | assert_contains "$output" "Planning mode: brainstorm" "brainstorm prompt" | |
| 76 | + | ||
| 77 | + | output="$(printf 'build feature\nEOF\n' | plan_build 2>&1)" && rc=0 || rc=$? | |
| 78 | + | assert_equal "0" "$rc" "standard launch status" | |
| 79 | + | assert_contains "$output" "Planning mode: standard" "standard prompt" | |
| 80 | + | ||
| 81 | + | if [ "$failures" -ne 0 ]; then | |
| 82 | + | exit 1 | |
| 83 | + | fi | |
| 84 | + | ||
| 85 | + | print -- "PASS: plan_build tests" | |
zsh_macos.sh
| @@ -111,6 +111,17 @@ download_configs() { | |||
| 111 | 111 | fi | |
| 112 | 112 | done | |
| 113 | 113 | ||
| 114 | + | local skill_target="$HOME/.claude/skills/plan-build/SKILL.md" | |
| 115 | + | local skill_tmp="${skill_target}.tmp.$$" | |
| 116 | + | mkdir -p "$(dirname "$skill_target")" | |
| 117 | + | log "Fetching orchestrate-loop.md -> .claude/skills/plan-build/SKILL.md ..." | |
| 118 | + | if curl -fsSL "$GIST_RAW_BASE/orchestrate-loop.md" -o "$skill_tmp"; then | |
| 119 | + | mv "$skill_tmp" "$skill_target" | |
| 120 | + | else | |
| 121 | + | rm -f "$skill_tmp" | |
| 122 | + | warn "Failed to download orchestrate-loop.md" | |
| 123 | + | fi | |
| 124 | + | ||
| 114 | 125 | ok "Configs downloaded (Backup at $backup)" | |
| 115 | 126 | } | |
| 116 | 127 | ||
zsh_ubuntu.sh
| @@ -202,6 +202,17 @@ download_configs() { | |||
| 202 | 202 | fi | |
| 203 | 203 | done | |
| 204 | 204 | ||
| 205 | + | local skill_target="$HOME/.claude/skills/plan-build/SKILL.md" | |
| 206 | + | local skill_tmp="${skill_target}.tmp.$$" | |
| 207 | + | mkdir -p "$(dirname "$skill_target")" | |
| 208 | + | log "Fetching orchestrate-loop.md -> .claude/skills/plan-build/SKILL.md ..." | |
| 209 | + | if curl -fsSL "$GIST_RAW_BASE/orchestrate-loop.md" -o "$skill_tmp"; then | |
| 210 | + | mv "$skill_tmp" "$skill_target" | |
| 211 | + | else | |
| 212 | + | rm -f "$skill_tmp" | |
| 213 | + | warn "Failed to download orchestrate-loop.md" | |
| 214 | + | fi | |
| 215 | + | ||
| 205 | 216 | ok "Configs downloaded (Backup at $backup)" | |
| 206 | 217 | } | |
| 207 | 218 | ||
zsh_wsl.sh
| @@ -204,6 +204,17 @@ download_configs() { | |||
| 204 | 204 | fi | |
| 205 | 205 | done | |
| 206 | 206 | ||
| 207 | + | local skill_target="$HOME/.claude/skills/plan-build/SKILL.md" | |
| 208 | + | local skill_tmp="${skill_target}.tmp.$$" | |
| 209 | + | mkdir -p "$(dirname "$skill_target")" | |
| 210 | + | log "Fetching orchestrate-loop.md -> .claude/skills/plan-build/SKILL.md ..." | |
| 211 | + | if curl -fsSL "$GIST_RAW_BASE/orchestrate-loop.md" -o "$skill_tmp"; then | |
| 212 | + | mv "$skill_tmp" "$skill_target" | |
| 213 | + | else | |
| 214 | + | rm -f "$skill_tmp" | |
| 215 | + | warn "Failed to download orchestrate-loop.md" | |
| 216 | + | fi | |
| 217 | + | ||
| 207 | 218 | ok "Configs downloaded (Backup at $backup)" | |
| 208 | 219 | } | |
| 209 | 220 | ||
Vernon Wee Hong KOH ревизий этого фрагмента 3 months ago. К ревизии
1 file changed, 5 insertions, 5 deletions
sourcerc
| @@ -37,10 +37,10 @@ fi | |||
| 37 | 37 | # ============================================================================= | |
| 38 | 38 | # GOOGLE CLOUD SDK | |
| 39 | 39 | # ============================================================================= | |
| 40 | - | if [[ -f "$HOME/google-cloud-sdk/path.zsh.inc" ]]; then | |
| 41 | - | source "$HOME/google-cloud-sdk/path.zsh.inc" | |
| 40 | + | if [[ -f "/opt/google-cloud-sdk/path.zsh.inc" ]]; then | |
| 41 | + | source "/opt/google-cloud-sdk/path.zsh.inc" | |
| 42 | 42 | fi | |
| 43 | 43 | ||
| 44 | - | if [[ -f "$HOME/google-cloud-sdk/completion.zsh.inc" ]]; then | |
| 45 | - | source "$HOME/google-cloud-sdk/completion.zsh.inc" | |
| 46 | - | fi | |
| 44 | + | if [[ -f "/opt/google-cloud-sdk/completion.zsh.inc" ]]; then | |
| 45 | + | source "/opt/google-cloud-sdk/completion.zsh.inc" | |
| 46 | + | fi | |
Vernon Wee Hong KOH ревизий этого фрагмента 3 months ago. К ревизии
1 file changed, 27 insertions
func
| @@ -493,6 +493,7 @@ plan_build() { | |||
| 493 | 493 | ||
| 494 | 494 | if [ "$enhance_payload" -eq 1 ]; then | |
| 495 | 495 | local enhanced_file | |
| 496 | + | local review_reply | |
| 496 | 497 | enhanced_file="$(mktemp "${TMPDIR:-/tmp}/plan-build-enhanced.XXXXXX")" || return 1 | |
| 497 | 498 | ||
| 498 | 499 | echo "✨ Enhancing payload with Auggie..." | |
| @@ -509,6 +510,32 @@ plan_build() { | |||
| 509 | 510 | echo "❌ Error: Enhanced payload was empty; Claude was not launched." | |
| 510 | 511 | return 1 | |
| 511 | 512 | fi | |
| 513 | + | ||
| 514 | + | printf '\n%s\n' "━━━━━━━━━━━━━━━━ Auggie enhanced prompt ━━━━━━━━━━━━━━━━" | |
| 515 | + | printf '%s\n' "$payload" | |
| 516 | + | printf '%s\n\n' "━━━━━━━━━━━━━━━━ End enhanced prompt ━━━━━━━━━━━━━━━━━" | |
| 517 | + | ||
| 518 | + | if ! (: </dev/tty) 2>/dev/null; then | |
| 519 | + | echo "❌ Error: Cannot review the enhanced prompt without an interactive terminal; Claude was not launched." | |
| 520 | + | return 1 | |
| 521 | + | fi | |
| 522 | + | ||
| 523 | + | printf "Proceed with this enhanced prompt? (y/N) " >/dev/tty | |
| 524 | + | if ! IFS= read -r review_reply </dev/tty; then | |
| 525 | + | printf '\n' >/dev/tty | |
| 526 | + | echo "🛑 Review cancelled; Claude was not launched." | |
| 527 | + | return 1 | |
| 528 | + | fi | |
| 529 | + | ||
| 530 | + | case "$review_reply" in | |
| 531 | + | y|Y|yes|YES|Yes) | |
| 532 | + | echo "✅ Enhanced prompt approved." | |
| 533 | + | ;; | |
| 534 | + | *) | |
| 535 | + | echo "🛑 Enhanced prompt not approved; Claude was not launched." | |
| 536 | + | return 0 | |
| 537 | + | ;; | |
| 538 | + | esac | |
| 512 | 539 | fi | |
| 513 | 540 | ||
| 514 | 541 | echo "🚀 Launching Claude Code with your multi-agent workflow..." | |
Vernon Wee Hong KOH ревизий этого фрагмента 3 months ago. К ревизии
1 file changed, 3 insertions, 1 deletion
func
| @@ -544,7 +544,9 @@ aicommit() { | |||
| 544 | 544 | case "$engine" in | |
| 545 | 545 | claude) | |
| 546 | 546 | echo "🤖 Claude is analyzing staged changes..." | |
| 547 | - | cat "$HOME/.config/ai-commit-prompt.txt" <(echo -e "\n\nHere is the git diff:\n$diff") | command claude -p "Read the provided instructions and diff, then generate and execute the commit." | |
| 547 | + | cat "$HOME/.config/ai-commit-prompt.txt" <(echo -e "\n\nHere is the git diff:\n$diff") \ | |
| 548 | + | | command claude --allowedTools 'Bash(git commit *)' --permission-mode dontAsk -p \ | |
| 549 | + | "Read the provided instructions and diff, then generate and execute the commit." | |
| 548 | 550 | ;; | |
| 549 | 551 | ||
| 550 | 552 | codex) | |
Vernon Wee Hong KOH ревизий этого фрагмента 3 months ago. К ревизии
1 file changed, 16 insertions, 2 deletions
func
| @@ -522,7 +522,7 @@ $payload" | |||
| 522 | 522 | # Function: aicommit (Automated Conventional Commit Engine Wrapper) | |
| 523 | 523 | # ----------------------------------------------------------------------------- | |
| 524 | 524 | aicommit() { | |
| 525 | - | local diff engine | |
| 525 | + | local diff engine prompt | |
| 526 | 526 | ||
| 527 | 527 | # 1. Get diff safely: exclude lock files/minified files and cap at ~100k characters to prevent CLI crashes | |
| 528 | 528 | diff=$(git diff --cached -- . ":(exclude)*.lock" ":(exclude)*-lock.json" ":(exclude)*.min.js" | head -c 100000) | |
| @@ -539,6 +539,7 @@ aicommit() { | |||
| 539 | 539 | fi | |
| 540 | 540 | ||
| 541 | 541 | engine=${1:-claude} | |
| 542 | + | prompt=$(cat "$HOME/.config/ai-commit-prompt.txt") | |
| 542 | 543 | ||
| 543 | 544 | case "$engine" in | |
| 544 | 545 | claude) | |
| @@ -553,9 +554,22 @@ aicommit() { | |||
| 553 | 554 | "Read the provided instructions and diff, then generate and execute the commit." | |
| 554 | 555 | ;; | |
| 555 | 556 | ||
| 557 | + | copilot) | |
| 558 | + | echo "🤖 Copilot is analyzing staged changes..." | |
| 559 | + | copilot -p "$prompt | |
| 560 | + | ||
| 561 | + | Here is the git diff: | |
| 562 | + | $diff" -s --no-ask-user --allow-tool='shell(git:*)' | |
| 563 | + | ;; | |
| 564 | + | ||
| 565 | + | opencode) | |
| 566 | + | echo "🤖 OpenCode is analyzing staged changes..." | |
| 567 | + | cat "$HOME/.config/ai-commit-prompt.txt" <(echo -e "\n\nHere is the git diff:\n$diff") | opencode run | |
| 568 | + | ;; | |
| 569 | + | ||
| 556 | 570 | *) | |
| 557 | 571 | printf "❌ Error: Invalid engine '%s'\n" "$engine" >&2 | |
| 558 | - | printf "Usage: aicommit [claude | codex]\n" >&2 | |
| 572 | + | printf "Usage: aicommit [claude | codex | copilot | opencode]\n" >&2 | |
| 559 | 573 | return 1 | |
| 560 | 574 | ;; | |
| 561 | 575 | esac | |
Vernon Wee Hong KOH ревизий этого фрагмента 3 months ago. К ревизии
1 file changed, 8 insertions, 16 deletions
func
| @@ -522,7 +522,7 @@ $payload" | |||
| 522 | 522 | # Function: aicommit (Automated Conventional Commit Engine Wrapper) | |
| 523 | 523 | # ----------------------------------------------------------------------------- | |
| 524 | 524 | aicommit() { | |
| 525 | - | local diff engine prompt | |
| 525 | + | local diff engine | |
| 526 | 526 | ||
| 527 | 527 | # 1. Get diff safely: exclude lock files/minified files and cap at ~100k characters to prevent CLI crashes | |
| 528 | 528 | diff=$(git diff --cached -- . ":(exclude)*.lock" ":(exclude)*-lock.json" ":(exclude)*.min.js" | head -c 100000) | |
| @@ -539,31 +539,23 @@ aicommit() { | |||
| 539 | 539 | fi | |
| 540 | 540 | ||
| 541 | 541 | engine=${1:-claude} | |
| 542 | - | prompt=$(cat "$HOME/.config/ai-commit-prompt.txt") | |
| 543 | 542 | ||
| 544 | 543 | case "$engine" in | |
| 545 | 544 | claude) | |
| 546 | 545 | echo "🤖 Claude is analyzing staged changes..." | |
| 547 | 546 | cat "$HOME/.config/ai-commit-prompt.txt" <(echo -e "\n\nHere is the git diff:\n$diff") | command claude -p "Read the provided instructions and diff, then generate and execute the commit." | |
| 548 | 547 | ;; | |
| 549 | - | ||
| 550 | - | copilot) | |
| 551 | - | echo "🤖 Copilot is analyzing staged changes..." | |
| 552 | - | copilot -p "$prompt | |
| 553 | 548 | ||
| 554 | - | Here is the git diff: | |
| 555 | - | $diff" -s --no-ask-user --allow-tool='shell(git:*)' | |
| 556 | - | ;; | |
| 557 | - | ||
| 558 | - | opencode) | |
| 559 | - | echo "🤖 OpenCode is analyzing staged changes..." | |
| 560 | - | # 2. Fixed: Piping standard input to opencode bypasses OS argument length limits | |
| 561 | - | cat "$HOME/.config/ai-commit-prompt.txt" <(echo -e "\n\nHere is the git diff:\n$diff") | opencode run | |
| 549 | + | codex) | |
| 550 | + | echo "🤖 Codex is analyzing staged changes..." | |
| 551 | + | cat "$HOME/.config/ai-commit-prompt.txt" <(echo -e "\n\nHere is the git diff:\n$diff") \ | |
| 552 | + | | command codex --ask-for-approval never exec --sandbox workspace-write --ephemeral \ | |
| 553 | + | "Read the provided instructions and diff, then generate and execute the commit." | |
| 562 | 554 | ;; | |
| 563 | - | ||
| 555 | + | ||
| 564 | 556 | *) | |
| 565 | 557 | printf "❌ Error: Invalid engine '%s'\n" "$engine" >&2 | |
| 566 | - | printf "Usage: aicommit [claude | copilot | opencode]\n" >&2 | |
| 558 | + | printf "Usage: aicommit [claude | codex]\n" >&2 | |
| 567 | 559 | return 1 | |
| 568 | 560 | ;; | |
| 569 | 561 | esac | |
Vernon Wee Hong KOH ревизий этого фрагмента 3 months ago. К ревизии
1 file changed, 9 insertions, 4 deletions
func
| @@ -315,14 +315,14 @@ _enhance_prompt() { | |||
| 315 | 315 | ||
| 316 | 316 | while kill -0 "$script_pid" >/dev/null 2>&1; do | |
| 317 | 317 | if grep -aq "🤖" "$log_file" 2>/dev/null || grep -aq "Tool call:" "$log_file" 2>/dev/null; then | |
| 318 | - | kill "$script_pid" >/dev/null 2>&1 | |
| 319 | - | wait "$script_pid" >/dev/null 2>&1 | |
| 318 | + | kill "$script_pid" >/dev/null 2>&1 || true | |
| 319 | + | wait "$script_pid" >/dev/null 2>&1 || true | |
| 320 | 320 | exit 0 | |
| 321 | 321 | fi | |
| 322 | 322 | ||
| 323 | 323 | if [ "$waited" -ge "$timeout_seconds" ]; then | |
| 324 | - | kill "$script_pid" >/dev/null 2>&1 | |
| 325 | - | wait "$script_pid" >/dev/null 2>&1 | |
| 324 | + | kill "$script_pid" >/dev/null 2>&1 || true | |
| 325 | + | wait "$script_pid" >/dev/null 2>&1 || true | |
| 326 | 326 | exit 124 | |
| 327 | 327 | fi | |
| 328 | 328 | ||
| @@ -342,7 +342,12 @@ _enhance_prompt() { | |||
| 342 | 342 | fi | |
| 343 | 343 | ||
| 344 | 344 | perl -ne ' | |
| 345 | + | # Auggie redraws streamed terminal lines with carriage returns. Keep only | |
| 346 | + | # the final rendered segment so stale text cannot corrupt the prompt. | |
| 345 | 347 | s/\r$//; | |
| 348 | + | s/.*\r//; | |
| 349 | + | 1 while s/[^\x08]\x08//g; | |
| 350 | + | s/\x08//g; | |
| 346 | 351 | s/\e\][^\a]*(?:\a|\e\\)//g; | |
| 347 | 352 | s/\e\[[0-?]*[ -\/]*[@-~]//g; | |
| 348 | 353 | next if /Script started on/ || /Script done on/; | |
Vernon Wee Hong KOH ревизий этого фрагмента 3 months ago. К ревизии
1 file changed, 42 insertions, 33 deletions
func
| @@ -259,6 +259,7 @@ _enhance_prompt() { | |||
| 259 | 259 | local script_pid | |
| 260 | 260 | local waited | |
| 261 | 261 | local timeout_seconds | |
| 262 | + | local monitor_status | |
| 262 | 263 | ||
| 263 | 264 | if [ -z "$prompt" ]; then | |
| 264 | 265 | printf "Error: Prompt was empty.\n" >&2 | |
| @@ -294,50 +295,58 @@ _enhance_prompt() { | |||
| 294 | 295 | printf "Enhancing without project indexing.\n" >&2 | |
| 295 | 296 | fi | |
| 296 | 297 | ||
| 297 | - | if [ "$use_project_context" -eq 1 ]; then | |
| 298 | - | AUGGIE_PROMPT_FILE="$prompt_file" \ | |
| 299 | - | AUGGIE_WORKSPACE="$workspace" \ | |
| 300 | - | AUGGIE_CACHE_DIR="$cache_dir" \ | |
| 301 | - | AUGGIE_AUTH_FILE="$auth_file" \ | |
| 302 | - | script -q -f -O "$log_file" -c 'auggie --print --enhance-prompt --workspace-root "$AUGGIE_WORKSPACE" --augment-cache-dir "$AUGGIE_CACHE_DIR" --augment-session-json "$AUGGIE_AUTH_FILE" --allow-indexing --wait-for-indexing --dont-save-session --instruction-file "$AUGGIE_PROMPT_FILE"' </dev/null >/dev/null 2>&1 & | |
| 303 | - | else | |
| 304 | - | AUGGIE_PROMPT_FILE="$prompt_file" \ | |
| 305 | - | AUGGIE_WORKSPACE="$workspace" \ | |
| 306 | - | AUGGIE_CACHE_DIR="$cache_dir" \ | |
| 307 | - | AUGGIE_AUTH_FILE="$auth_file" \ | |
| 308 | - | script -q -f -O "$log_file" -c 'auggie --print --enhance-prompt --no-discover-workspaces --workspace-root "$AUGGIE_WORKSPACE" --augment-cache-dir "$AUGGIE_CACHE_DIR" --augment-session-json "$AUGGIE_AUTH_FILE" --dont-save-session --instruction-file "$AUGGIE_PROMPT_FILE"' </dev/null >/dev/null 2>&1 & | |
| 309 | - | fi | |
| 298 | + | ( | |
| 299 | + | if [ "$use_project_context" -eq 1 ]; then | |
| 300 | + | AUGGIE_PROMPT_FILE="$prompt_file" \ | |
| 301 | + | AUGGIE_WORKSPACE="$workspace" \ | |
| 302 | + | AUGGIE_CACHE_DIR="$cache_dir" \ | |
| 303 | + | AUGGIE_AUTH_FILE="$auth_file" \ | |
| 304 | + | script -q -f -O "$log_file" -c 'auggie --print --enhance-prompt --workspace-root "$AUGGIE_WORKSPACE" --augment-cache-dir "$AUGGIE_CACHE_DIR" --augment-session-json "$AUGGIE_AUTH_FILE" --allow-indexing --wait-for-indexing --dont-save-session --instruction-file "$AUGGIE_PROMPT_FILE"' </dev/null >/dev/null 2>&1 & | |
| 305 | + | else | |
| 306 | + | AUGGIE_PROMPT_FILE="$prompt_file" \ | |
| 307 | + | AUGGIE_WORKSPACE="$workspace" \ | |
| 308 | + | AUGGIE_CACHE_DIR="$cache_dir" \ | |
| 309 | + | AUGGIE_AUTH_FILE="$auth_file" \ | |
| 310 | + | script -q -f -O "$log_file" -c 'auggie --print --enhance-prompt --no-discover-workspaces --workspace-root "$AUGGIE_WORKSPACE" --augment-cache-dir "$AUGGIE_CACHE_DIR" --augment-session-json "$AUGGIE_AUTH_FILE" --dont-save-session --instruction-file "$AUGGIE_PROMPT_FILE"' </dev/null >/dev/null 2>&1 & | |
| 311 | + | fi | |
| 310 | 312 | ||
| 311 | - | script_pid=$! | |
| 312 | - | waited=0 | |
| 313 | + | script_pid=$! | |
| 314 | + | waited=0 | |
| 313 | 315 | ||
| 314 | - | while kill -0 "$script_pid" >/dev/null 2>&1; do | |
| 315 | - | if grep -aq "🤖" "$log_file" 2>/dev/null || grep -aq "Tool call:" "$log_file" 2>/dev/null; then | |
| 316 | - | kill "$script_pid" >/dev/null 2>&1 | |
| 317 | - | wait "$script_pid" >/dev/null 2>&1 | |
| 318 | - | break | |
| 319 | - | fi | |
| 316 | + | while kill -0 "$script_pid" >/dev/null 2>&1; do | |
| 317 | + | if grep -aq "🤖" "$log_file" 2>/dev/null || grep -aq "Tool call:" "$log_file" 2>/dev/null; then | |
| 318 | + | kill "$script_pid" >/dev/null 2>&1 | |
| 319 | + | wait "$script_pid" >/dev/null 2>&1 | |
| 320 | + | exit 0 | |
| 321 | + | fi | |
| 320 | 322 | ||
| 321 | - | if [ "$waited" -ge "$timeout_seconds" ]; then | |
| 322 | - | kill "$script_pid" >/dev/null 2>&1 | |
| 323 | - | wait "$script_pid" >/dev/null 2>&1 | |
| 324 | - | printf "Error: Timed out waiting for Auggie to enhance the prompt.\n" >&2 | |
| 325 | - | rm -rf "$run_dir" | |
| 326 | - | return 124 | |
| 327 | - | fi | |
| 323 | + | if [ "$waited" -ge "$timeout_seconds" ]; then | |
| 324 | + | kill "$script_pid" >/dev/null 2>&1 | |
| 325 | + | wait "$script_pid" >/dev/null 2>&1 | |
| 326 | + | exit 124 | |
| 327 | + | fi | |
| 328 | 328 | ||
| 329 | - | sleep 1 | |
| 330 | - | waited=$((waited + 1)) | |
| 331 | - | done | |
| 329 | + | sleep 1 | |
| 330 | + | waited=$((waited + 1)) | |
| 331 | + | done | |
| 332 | 332 | ||
| 333 | - | wait "$script_pid" >/dev/null 2>&1 || true | |
| 333 | + | wait "$script_pid" >/dev/null 2>&1 || true | |
| 334 | + | exit 0 | |
| 335 | + | ) | |
| 336 | + | monitor_status=$? | |
| 337 | + | ||
| 338 | + | if [ "$monitor_status" -eq 124 ]; then | |
| 339 | + | printf "Error: Timed out waiting for Auggie to enhance the prompt.\n" >&2 | |
| 340 | + | rm -rf "$run_dir" | |
| 341 | + | return 124 | |
| 342 | + | fi | |
| 334 | 343 | ||
| 335 | 344 | perl -ne ' | |
| 336 | 345 | s/\r$//; | |
| 337 | 346 | s/\e\][^\a]*(?:\a|\e\\)//g; | |
| 338 | 347 | s/\e\[[0-?]*[ -\/]*[@-~]//g; | |
| 339 | 348 | next if /Script started on/ || /Script done on/; | |
| 340 | - | if (/^Enhanced prompt:\s*(.*)$/) { | |
| 349 | + | if (/^(?:✨\s*)?Enhanced prompt:\s*(.*)$/) { | |
| 341 | 350 | $capturing = 1; | |
| 342 | 351 | $output .= "$1\n" if length $1; | |
| 343 | 352 | next; | |
Vernon Wee Hong KOH ревизий этого фрагмента 3 months ago. К ревизии
1 file changed, 188 insertions, 41 deletions
func
| @@ -214,40 +214,51 @@ claude() { | |||
| 214 | 214 | } | |
| 215 | 215 | ||
| 216 | 216 | # ----------------------------------------------------------------------------- | |
| 217 | - | # Function: prompt (Enhance a prompt with Auggie) | |
| 217 | + | # Internal: _prompt_confirm_indexing (Confirm project indexing via the terminal) | |
| 218 | 218 | # ----------------------------------------------------------------------------- | |
| 219 | - | prompt() { | |
| 220 | - | local prompt | |
| 221 | - | local line | |
| 219 | + | _prompt_confirm_indexing() { | |
| 220 | + | local project_root="$1" | |
| 221 | + | local reply | |
| 222 | + | ||
| 223 | + | if ! (: </dev/tty) 2>/dev/null; then | |
| 224 | + | printf "Notice: No interactive terminal available; enhancing without project indexing.\n" >&2 | |
| 225 | + | return 1 | |
| 226 | + | fi | |
| 227 | + | ||
| 228 | + | printf "Allow Auggie to index and use project context from '%s'? (y/N) " "$project_root" >/dev/tty | |
| 229 | + | if ! IFS= read -r reply </dev/tty; then | |
| 230 | + | printf "\nNotice: Unable to read confirmation; enhancing without project indexing.\n" >&2 | |
| 231 | + | return 1 | |
| 232 | + | fi | |
| 233 | + | ||
| 234 | + | case "$reply" in | |
| 235 | + | y|Y|yes|YES|Yes) | |
| 236 | + | return 0 | |
| 237 | + | ;; | |
| 238 | + | *) | |
| 239 | + | return 1 | |
| 240 | + | ;; | |
| 241 | + | esac | |
| 242 | + | } | |
| 243 | + | ||
| 244 | + | # ----------------------------------------------------------------------------- | |
| 245 | + | # Internal: _enhance_prompt (Run Auggie and write only the enhanced prompt) | |
| 246 | + | # ----------------------------------------------------------------------------- | |
| 247 | + | _enhance_prompt() { | |
| 248 | + | local prompt="$1" | |
| 249 | + | local output_file="$2" | |
| 222 | 250 | local run_dir | |
| 223 | 251 | local prompt_file | |
| 224 | 252 | local workspace | |
| 225 | 253 | local cache_dir | |
| 226 | 254 | local auth_file | |
| 227 | 255 | local log_file | |
| 256 | + | local parsed_file | |
| 257 | + | local project_root | |
| 258 | + | local use_project_context | |
| 228 | 259 | local script_pid | |
| 229 | 260 | local waited | |
| 230 | - | ||
| 231 | - | require_cli auggie "Auggie CLI" || return 1 | |
| 232 | - | require_cli script "script utility" || return 1 | |
| 233 | - | ||
| 234 | - | if [ $# -gt 0 ]; then | |
| 235 | - | prompt="$*" | |
| 236 | - | elif [ ! -t 0 ]; then | |
| 237 | - | prompt="$(cat)" | |
| 238 | - | else | |
| 239 | - | echo "Reading prompt... Type 'EOF' on a new line and press Enter when finished." | |
| 240 | - | prompt="" | |
| 241 | - | ||
| 242 | - | while IFS= read -r line; do | |
| 243 | - | [ "$line" = "EOF" ] && break | |
| 244 | - | if [ -z "$prompt" ]; then | |
| 245 | - | prompt="$line" | |
| 246 | - | else | |
| 247 | - | prompt="${prompt}"$'\n'"${line}" | |
| 248 | - | fi | |
| 249 | - | done | |
| 250 | - | fi | |
| 261 | + | local timeout_seconds | |
| 251 | 262 | ||
| 252 | 263 | if [ -z "$prompt" ]; then | |
| 253 | 264 | printf "Error: Prompt was empty.\n" >&2 | |
| @@ -265,10 +276,38 @@ prompt() { | |||
| 265 | 276 | cache_dir="$run_dir/cache" | |
| 266 | 277 | auth_file="$HOME/.augment/session.json" | |
| 267 | 278 | log_file="$run_dir/auggie.log" | |
| 279 | + | parsed_file="$run_dir/enhanced.txt" | |
| 268 | 280 | mkdir -p "$workspace" "$cache_dir" | |
| 269 | 281 | printf "%s\n" "$prompt" > "$prompt_file" | |
| 270 | 282 | ||
| 271 | - | script -q -f -O "$log_file" -c "auggie --print --enhance-prompt --no-discover-workspaces --workspace-root '$workspace' --augment-cache-dir '$cache_dir' --augment-session-json '$auth_file' --dont-save-session --instruction-file '$prompt_file'" </dev/null >/dev/null 2>&1 & | |
| 283 | + | project_root="$(git rev-parse --show-toplevel 2>/dev/null)" || project_root="$PWD" | |
| 284 | + | use_project_context=0 | |
| 285 | + | timeout_seconds=90 | |
| 286 | + | ||
| 287 | + | if _prompt_confirm_indexing "$project_root"; then | |
| 288 | + | use_project_context=1 | |
| 289 | + | timeout_seconds=300 | |
| 290 | + | workspace="$project_root" | |
| 291 | + | cache_dir="$HOME/.augment" | |
| 292 | + | printf "Indexing approved; enhancing with project context from '%s'.\n" "$project_root" >&2 | |
| 293 | + | else | |
| 294 | + | printf "Enhancing without project indexing.\n" >&2 | |
| 295 | + | fi | |
| 296 | + | ||
| 297 | + | if [ "$use_project_context" -eq 1 ]; then | |
| 298 | + | AUGGIE_PROMPT_FILE="$prompt_file" \ | |
| 299 | + | AUGGIE_WORKSPACE="$workspace" \ | |
| 300 | + | AUGGIE_CACHE_DIR="$cache_dir" \ | |
| 301 | + | AUGGIE_AUTH_FILE="$auth_file" \ | |
| 302 | + | script -q -f -O "$log_file" -c 'auggie --print --enhance-prompt --workspace-root "$AUGGIE_WORKSPACE" --augment-cache-dir "$AUGGIE_CACHE_DIR" --augment-session-json "$AUGGIE_AUTH_FILE" --allow-indexing --wait-for-indexing --dont-save-session --instruction-file "$AUGGIE_PROMPT_FILE"' </dev/null >/dev/null 2>&1 & | |
| 303 | + | else | |
| 304 | + | AUGGIE_PROMPT_FILE="$prompt_file" \ | |
| 305 | + | AUGGIE_WORKSPACE="$workspace" \ | |
| 306 | + | AUGGIE_CACHE_DIR="$cache_dir" \ | |
| 307 | + | AUGGIE_AUTH_FILE="$auth_file" \ | |
| 308 | + | script -q -f -O "$log_file" -c 'auggie --print --enhance-prompt --no-discover-workspaces --workspace-root "$AUGGIE_WORKSPACE" --augment-cache-dir "$AUGGIE_CACHE_DIR" --augment-session-json "$AUGGIE_AUTH_FILE" --dont-save-session --instruction-file "$AUGGIE_PROMPT_FILE"' </dev/null >/dev/null 2>&1 & | |
| 309 | + | fi | |
| 310 | + | ||
| 272 | 311 | script_pid=$! | |
| 273 | 312 | waited=0 | |
| 274 | 313 | ||
| @@ -279,7 +318,7 @@ prompt() { | |||
| 279 | 318 | break | |
| 280 | 319 | fi | |
| 281 | 320 | ||
| 282 | - | if [ "$waited" -ge 90 ]; then | |
| 321 | + | if [ "$waited" -ge "$timeout_seconds" ]; then | |
| 283 | 322 | kill "$script_pid" >/dev/null 2>&1 | |
| 284 | 323 | wait "$script_pid" >/dev/null 2>&1 | |
| 285 | 324 | printf "Error: Timed out waiting for Auggie to enhance the prompt.\n" >&2 | |
| @@ -291,20 +330,85 @@ prompt() { | |||
| 291 | 330 | waited=$((waited + 1)) | |
| 292 | 331 | done | |
| 293 | 332 | ||
| 333 | + | wait "$script_pid" >/dev/null 2>&1 || true | |
| 334 | + | ||
| 294 | 335 | perl -ne ' | |
| 295 | 336 | s/\r$//; | |
| 296 | - | s/\e\]0;[^\a]*\a//g; | |
| 337 | + | s/\e\][^\a]*(?:\a|\e\\)//g; | |
| 338 | + | s/\e\[[0-?]*[ -\/]*[@-~]//g; | |
| 297 | 339 | next if /Script started on/ || /Script done on/; | |
| 340 | + | if (/^Enhanced prompt:\s*(.*)$/) { | |
| 341 | + | $capturing = 1; | |
| 342 | + | $output .= "$1\n" if length $1; | |
| 343 | + | next; | |
| 344 | + | } | |
| 345 | + | next unless $capturing; | |
| 298 | 346 | exit if /^🤖/ || /Tool call:/ || /Session terminated/; | |
| 299 | - | print; | |
| 300 | - | ' "$log_file" | |
| 347 | + | $output .= $_; | |
| 348 | + | END { | |
| 349 | + | $output =~ s/^\s*\n//; | |
| 350 | + | $output =~ s/\s+\z//; | |
| 351 | + | print "$output\n" if length $output; | |
| 352 | + | } | |
| 353 | + | ' "$log_file" > "$parsed_file" | |
| 301 | 354 | ||
| 302 | - | if ! grep -aq "Enhanced prompt:" "$log_file"; then | |
| 355 | + | if [ ! -s "$parsed_file" ]; then | |
| 356 | + | printf "Error: Auggie did not return an enhanced prompt.\n" >&2 | |
| 303 | 357 | rm -rf "$run_dir" | |
| 304 | 358 | return 1 | |
| 305 | 359 | fi | |
| 306 | 360 | ||
| 361 | + | if ! command cp "$parsed_file" "$output_file"; then | |
| 362 | + | printf "Error: Unable to save the enhanced prompt.\n" >&2 | |
| 363 | + | rm -rf "$run_dir" | |
| 364 | + | return 1 | |
| 365 | + | fi | |
| 307 | 366 | rm -rf "$run_dir" | |
| 367 | + | } | |
| 368 | + | ||
| 369 | + | # ----------------------------------------------------------------------------- | |
| 370 | + | # Function: prompt (Enhance a prompt with Auggie and optional project context) | |
| 371 | + | # ----------------------------------------------------------------------------- | |
| 372 | + | prompt() { | |
| 373 | + | local prompt | |
| 374 | + | local line | |
| 375 | + | local output_file | |
| 376 | + | ||
| 377 | + | require_cli auggie "Auggie CLI" || return 1 | |
| 378 | + | require_cli script "script utility" || return 1 | |
| 379 | + | ||
| 380 | + | if [ $# -gt 0 ]; then | |
| 381 | + | prompt="$*" | |
| 382 | + | elif [ ! -t 0 ]; then | |
| 383 | + | prompt="$(cat)" | |
| 384 | + | else | |
| 385 | + | echo "Reading prompt... Type 'EOF' on a new line and press Enter when finished." | |
| 386 | + | prompt="" | |
| 387 | + | ||
| 388 | + | while IFS= read -r line; do | |
| 389 | + | [ "$line" = "EOF" ] && break | |
| 390 | + | if [ -z "$prompt" ]; then | |
| 391 | + | prompt="$line" | |
| 392 | + | else | |
| 393 | + | prompt="${prompt}"$'\n'"${line}" | |
| 394 | + | fi | |
| 395 | + | done | |
| 396 | + | fi | |
| 397 | + | ||
| 398 | + | if [ -z "$prompt" ]; then | |
| 399 | + | printf "Error: Prompt was empty.\n" >&2 | |
| 400 | + | return 1 | |
| 401 | + | fi | |
| 402 | + | ||
| 403 | + | output_file="$(mktemp "${TMPDIR:-/tmp}/auggie-enhanced-prompt.XXXXXX")" || return 1 | |
| 404 | + | if ! _enhance_prompt "$prompt" "$output_file"; then | |
| 405 | + | rm -f "$output_file" | |
| 406 | + | return 1 | |
| 407 | + | fi | |
| 408 | + | ||
| 409 | + | printf "Enhanced prompt:\n" | |
| 410 | + | command cat "$output_file" | |
| 411 | + | rm -f "$output_file" | |
| 308 | 412 | ||
| 309 | 413 | command auggie account status | |
| 310 | 414 | } | |
| @@ -314,21 +418,44 @@ prompt() { | |||
| 314 | 418 | # ----------------------------------------------------------------------------- | |
| 315 | 419 | plan_build() { | |
| 316 | 420 | local claude_args=() | |
| 317 | - | ||
| 318 | - | if [[ "${1:-}" == "--yolo" ]]; then | |
| 319 | - | claude_args=(--yolo) | |
| 421 | + | local use_yolo=0 | |
| 422 | + | local enhance_payload=0 | |
| 423 | + | ||
| 424 | + | while [ $# -gt 0 ]; do | |
| 425 | + | case "$1" in | |
| 426 | + | --yolo) | |
| 427 | + | if [ "$use_yolo" -eq 1 ]; then | |
| 428 | + | echo "Error: Duplicate argument: --yolo" | |
| 429 | + | echo "Usage: plan_build [--yolo] [--prompt]" | |
| 430 | + | return 1 | |
| 431 | + | fi | |
| 432 | + | use_yolo=1 | |
| 433 | + | claude_args=(--yolo) | |
| 434 | + | ;; | |
| 435 | + | --prompt) | |
| 436 | + | if [ "$enhance_payload" -eq 1 ]; then | |
| 437 | + | echo "Error: Duplicate argument: --prompt" | |
| 438 | + | echo "Usage: plan_build [--yolo] [--prompt]" | |
| 439 | + | return 1 | |
| 440 | + | fi | |
| 441 | + | enhance_payload=1 | |
| 442 | + | ;; | |
| 443 | + | *) | |
| 444 | + | echo "Error: Unknown argument: $1" | |
| 445 | + | echo "Usage: plan_build [--yolo] [--prompt]" | |
| 446 | + | return 1 | |
| 447 | + | ;; | |
| 448 | + | esac | |
| 320 | 449 | shift | |
| 321 | - | fi | |
| 322 | - | ||
| 323 | - | if [ $# -gt 0 ]; then | |
| 324 | - | echo "Error: Unknown argument(s): $*" | |
| 325 | - | echo "Usage: plan_build [--yolo]" | |
| 326 | - | return 1 | |
| 327 | - | fi | |
| 450 | + | done | |
| 328 | 451 | ||
| 329 | 452 | require_cli claude "Claude Code CLI" || return 1 | |
| 330 | 453 | require_cli codex "Codex CLI" || return 1 | |
| 331 | 454 | require_cli coderabbit "CodeRabbit CLI" || return 1 | |
| 455 | + | if [ "$enhance_payload" -eq 1 ]; then | |
| 456 | + | require_cli auggie "Auggie CLI" || return 1 | |
| 457 | + | require_cli script "script utility" || return 1 | |
| 458 | + | fi | |
| 332 | 459 | ||
| 333 | 460 | echo "📥 Reading payload... Type 'EOF' on a new line and press Enter when finished." | |
| 334 | 461 | ||
| @@ -350,6 +477,26 @@ plan_build() { | |||
| 350 | 477 | return 1 | |
| 351 | 478 | fi | |
| 352 | 479 | ||
| 480 | + | if [ "$enhance_payload" -eq 1 ]; then | |
| 481 | + | local enhanced_file | |
| 482 | + | enhanced_file="$(mktemp "${TMPDIR:-/tmp}/plan-build-enhanced.XXXXXX")" || return 1 | |
| 483 | + | ||
| 484 | + | echo "✨ Enhancing payload with Auggie..." | |
| 485 | + | if ! _enhance_prompt "$payload" "$enhanced_file"; then | |
| 486 | + | rm -f "$enhanced_file" | |
| 487 | + | echo "❌ Error: Prompt enhancement failed; Claude was not launched." | |
| 488 | + | return 1 | |
| 489 | + | fi | |
| 490 | + | ||
| 491 | + | payload="$(cat "$enhanced_file")" | |
| 492 | + | rm -f "$enhanced_file" | |
| 493 | + | ||
| 494 | + | if [ -z "$payload" ]; then | |
| 495 | + | echo "❌ Error: Enhanced payload was empty; Claude was not launched." | |
| 496 | + | return 1 | |
| 497 | + | fi | |
| 498 | + | fi | |
| 499 | + | ||
| 353 | 500 | echo "🚀 Launching Claude Code with your multi-agent workflow..." | |
| 354 | 501 | ||
| 355 | 502 | claude "${claude_args[@]}" "Please read \`~/.claude/skills/plan-build/SKILL.md\` and strictly follow the 7-step multi-agent workflow to implement the following task: | |
Vernon Wee Hong KOH ревизий этого фрагмента 3 months ago. К ревизии
1 file changed, 1 insertion, 1 deletion
func
| @@ -268,7 +268,7 @@ prompt() { | |||
| 268 | 268 | mkdir -p "$workspace" "$cache_dir" | |
| 269 | 269 | printf "%s\n" "$prompt" > "$prompt_file" | |
| 270 | 270 | ||
| 271 | - | script -q -f -O "$log_file" -c "auggie --print --enhance-prompt --no-discover-workspaces --workspace-root '$workspace' --augment-cache-dir '$cache_dir' --augment-session-json '$auth_file' --dont-save-session --instruction-file '$prompt_file'" >/dev/null 2>&1 & | |
| 271 | + | script -q -f -O "$log_file" -c "auggie --print --enhance-prompt --no-discover-workspaces --workspace-root '$workspace' --augment-cache-dir '$cache_dir' --augment-session-json '$auth_file' --dont-save-session --instruction-file '$prompt_file'" </dev/null >/dev/null 2>&1 & | |
| 272 | 272 | script_pid=$! | |
| 273 | 273 | waited=0 | |
| 274 | 274 | ||