Skip to content

fix: initialize task_json in track_iteration_start#152

Open
alilxxey wants to merge 1 commit intoasklokesh:mainfrom
alilxxey:fix/task-json-unbound-variable
Open

fix: initialize task_json in track_iteration_start#152
alilxxey wants to merge 1 commit intoasklokesh:mainfrom
alilxxey:fix/task-json-unbound-variable

Conversation

@alilxxey
Copy link
Copy Markdown

@alilxxey alilxxey commented Apr 8, 2026

Under set -uo pipefail, local task_json without an initializer leaves the variable unset. When the pending queue is empty (iteration 2+ with no tasks left), next_task_context is empty, the enrichment if block is skipped, and the subsequent [[ -z "$task_json" ]] check crashes with "unbound variable", killing the run.

Initialize local task_json="" at declaration and guard reads with ${task_json:-} and ${next_task_context:-} for defense in depth. Adds BUG-RUN-003 regression assertions to tests/test-bugfix-audit.sh.

Description

Fixes a crash in track_iteration_start where local task_json was
declared without initialization. Under set -uo pipefail, when the
pending queue becomes empty (iteration 2+ after all tasks are done),
next_task_context is empty, the enrichment if block is skipped,
and the subsequent [[ -z "$task_json" ]] check crashes with
"unbound variable", killing the run and blocking further iterations.

Reproduction

On v6.75.3 with any PRD:

  1. loki start prd.md
  2. First iteration completes
  3. Council votes REJECT (or pending queue otherwise empties)
  4. Second iteration starts → crash: task_json: unbound variable

Fix

  • Initialize local task_json="" at declaration (autonomy/run.sh:3602)
  • Defensive reads: ${task_json:-} / ${next_task_context:-}
  • Explicit fallback || task_json="" if the python3 heredoc exits non-zero

Audit

Scanned run.sh for the same anti-pattern (local var without init →
conditional if assignment → unconditional read). Found 8 candidates;
all 7 use if/else with assignment in both branches (safe) and 1 uses
if ! var=$(...) which assigns inside the condition (safe). task_json
was uniquely vulnerable because it had an if without an else.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that changes existing behavior)
  • Documentation update
  • Refactor (no functional changes)
  • Test improvement

Checklist

  • Shell scripts pass syntax validation (bash -n autonomy/run.sh && bash -n autonomy/loki)
  • All existing tests pass
  • New tests added for new functionality (where applicable)
  • No emojis in code, comments, documentation, or commit messages
  • Version bumped in all required files (if this is a release -- see CLAUDE.md Release Workflow)
  • Code follows existing patterns and style conventions

CLA Acknowledgment

Related Issues

Closes #

Under `set -uo pipefail`, `local task_json` without an initializer leaves
the variable unset. When the pending queue is empty (iteration 2+ with no
tasks left), next_task_context is empty, the enrichment `if` block is
skipped, and the subsequent `[[ -z "$task_json" ]]` check crashes with
"unbound variable", killing the run.

Initialize `local task_json=""` at declaration and guard reads with
`${task_json:-}` and `${next_task_context:-}` for defense in depth. Adds
BUG-RUN-003 regression assertions to tests/test-bugfix-audit.sh.
@alilxxey alilxxey requested a review from asklokesh as a code owner April 8, 2026 20:30
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 8, 2026

All contributors have signed the CLA. Thank you.
Posted by the CLA Assistant Lite bot.

@alilxxey
Copy link
Copy Markdown
Author

alilxxey commented Apr 8, 2026

I have read the CLA Document and I hereby sign the CLA

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant