<!-- SPDX-License-Identifier: MIT -->
<!-- SPDX-FileCopyrightText: 2025-2026 Marcus Quinn -->

# t1337.1: Tier 3 Scripts Audit Report

**Date:** 2026-02-26
**Auditor:** AI worker (sonnet)
**Scope:** 5 Tier 3 infrastructure scripts + 2 shared libraries

## Executive Summary

The 5 Tier 3 scripts have **already been substantially simplified** since the t1337 brief was written. Total lines dropped from ~8,346 (brief estimate) to **2,647 lines** — a 68% reduction. The scripts are now within or near their target line counts. The remaining consolidation opportunity is **~400-600 lines** through dead code removal, duplicate function merging, and backward-compat stub cleanup.

| Script | Brief estimate | Current | Target | Status |
|--------|---------------|---------|--------|--------|
| `full-loop-helper.sh` | 1,169 | **534** | ~400 | Near target (+134) |
| `fallback-chain-helper.sh` | 1,367 | **261** | ~200 | Near target (+61) |
| `budget-tracker-helper.sh` | 1,671 | **309** | ~300 | At target (+9) |
| `issue-sync-helper.sh` | 2,398 | **903** | ~600 | Over target (+303) |
| `observability-helper.sh` | 1,741 | **640** | ~500 | Over target (+140) |
| **Total** | **8,346** | **2,647** | **~2,000** | **-647 remaining** |

**Shared libraries** (not in brief scope but relevant):

| Library | Lines | Notes |
|---------|-------|-------|
| `issue-sync-lib.sh` | 1,256 | Heavy — TODO.md parser, plan extractor, issue body composer |
| `shared-constants.sh` | 1,162 | Framework-wide constants, print helpers, sed_inplace |

## Function Map

### full-loop-helper.sh (534 lines, 25 functions)

**External API (called by other scripts):**

| Function | External callers | Purpose |
|----------|-----------------|---------|
| `cmd_start` | 5 scripts | Start a full-loop session |
| `cmd_status` | 5+ scripts | Show loop status |
| `cmd_logs` | 5 scripts | Show background logs |
| `cmd_cancel` | 1 script | Cancel active loop |
| `cmd_resume` | 1 script | Resume from saved phase |
| `get_current_branch` | 1 script | Git branch name |
| `is_headless` | 1 script | Check headless mode |

**Internal-only functions (25 total, 18 internal-only):**
`clear_state`, `cmd_complete`, `cmd_run_foreground`, `emit_deploy_phase`, `emit_postflight_phase`, `emit_pr_create_phase`, `emit_preflight_phase`, `emit_pr_review_phase`, `emit_task_phase`, `init_state_dir`, `is_aidevops_repo`, `is_loop_active`, `is_on_feature_branch`, `load_state`, `print_phase`, `save_state`, `show_help`, `main`

**Dead code:** None — all functions are called internally.

### fallback-chain-helper.sh (261 lines, 8 functions)

**External API:**

| Function | External callers | Purpose |
|----------|-----------------|---------|
| `cmd_resolve` | 1 (model-availability-helper) | Resolve tier to model |
| `resolve_chain` | 1 (model-availability-helper) | Walk model list for availability |

**Internal-only:** `cmd_table`, `get_tier_models_from_table`, `is_model_available`, `load_routing_table`

**Dead code:** None.

### budget-tracker-helper.sh (309 lines, 9 functions)

**External API:**

| Function | External callers | Purpose |
|----------|-----------------|---------|
| `cmd_record` | 3 scripts | Log a spend event |
| `cmd_status` | 5+ scripts | Summarise spend |
| ~~`get_model_pricing`~~ | — | Moved to `shared-constants.sh` (t1337.2) |

**Internal-only:** `calculate_cost`, `cmd_burn_rate`, `cmd_tail`, `init_cost_log`

**Backward-compat stubs (lines 287-299):** 13 lines handling removed commands (`check`, `recommend`, `configure`, `reset`, `tier-drift`, `prune`, `budget-check-tier`, `budget-preferred-provider`). These return gracefully but are dead weight.

### issue-sync-helper.sh (903 lines, 29 functions)

**External API:**

| Function | External callers | Purpose |
|----------|-----------------|---------|
| `cmd_push` | 2 scripts | Create GitHub issues from TODO.md |
| `cmd_pull` | 1 script | Sync refs from GitHub to TODO.md |
| `cmd_close` | 1 script | Close issues for completed tasks |
| `cmd_status` | 5+ scripts | Show sync drift |
| `detect_repo_slug` | 1 script | Extract owner/repo from git remote |
| `log_verbose` | 1 script | Conditional logging |

**Internal-only (23 functions):** All `gh_*` wrappers, `_build_title`, `_close_comment`, `_do_close`, `_find_closing_pr`, `_has_evidence`, `_mark_issue_done`, `ensure_labels_exist`, `verify_gh_cli`, `cmd_enrich`, `cmd_parse`, `cmd_reconcile`

**Dead code:** None strictly dead, but `cmd_parse` (lines 771-821, 51 lines) is a debug command unlikely to be used in production.

### observability-helper.sh (640 lines, 19 functions)

**External API:**

| Function | External callers | Purpose |
|----------|-----------------|---------|
| `check_rate_limit_risk` | 1 (model-availability-helper) | Rate limit risk assessment |
| `cmd_rate_limits` | 1 (model-availability-helper) | Rate limit dashboard |
| `cmd_record` | 3 scripts | Manually record LLM request |
| ~~`get_model_pricing`~~ | — | Moved to `shared-constants.sh` (t1337.2) |

**Internal-only (15 functions):** `_calc_costs`, `cmd_ingest`, `_count_usage_in_window`, `_get_config_val`, `get_offset`, `get_project_from_path`, `get_provider_from_model`, `_get_rate_limits_config`, `_get_rl_field`, `init_storage`, `parse_jsonl_file`, `set_offset`, `_write_metric`

**Backward-compat stubs (lines 622-630):** 9 lines handling removed commands (`summary`, `models`, `projects`, `costs`, `trend`, `sync-budget`, `prune`, `cleanup`).

### issue-sync-lib.sh (1,256 lines, 26 functions) — shared library

**Dead functions (never called externally or internally by non-archived code):**

| Function | Lines | Notes |
|----------|-------|-------|
| `find_closing_pr` | ~40 | Superseded by `_find_closing_pr` in issue-sync-helper.sh |
| `task_has_completion_evidence` | ~40 | Superseded by `_has_evidence` in issue-sync-helper.sh |

**Internal-only (called only within lib):**
`_build_pr_url`, `extract_file_summary`, `extract_plan_discoveries`, `extract_plan_extra_sections`, `_extract_plan_subsection`, `find_plan_by_task_id`, `_load_private_repo_names`, `_sanitize_for_public_repo`

## Consolidation Targets

### 1. Duplicate `get_model_pricing` (HIGH — merge into shared location)

**Problem:** Two independent implementations with different signatures:

- `budget-tracker-helper.sh:26` — returns `input|output` (2 fields)
- `observability-helper.sh:62` — returns `input|output|cache_read|cache_write` (4 fields)

The observability version is a superset. Both have the same model matching logic but observability includes cache pricing.

**Recommendation:** Extract to `shared-constants.sh` or a new `model-pricing.sh`. Use the 4-field version. Budget-tracker can ignore fields 3-4.

**Performance note (from review):** The additional `cache_read` and `cache_write` fields in the 4-field version add negligible overhead — they are static string lookups in a case statement, not computed values. The budget-tracker caller already destructures only the fields it needs (`IFS='|' read -r input_price output_price _ _ <<< "$pricing"`), so the extra fields are silently discarded. No graceful-handling changes are needed in budget-tracker. If a future caller requires only 2 fields and the lookup table grows significantly, a separate 2-field function could be justified — but at current scale this is premature optimisation.

**Savings:** ~25 lines (one copy removed + callers updated).

### 2. Backward-compat stubs (MEDIUM — remove after grace period)

| Script | Lines | Stubs |
|--------|-------|-------|
| `budget-tracker-helper.sh` | 13 | `check`, `recommend`, `configure`, `reset`, `tier-drift`, `prune`, `budget-check-tier`, `budget-preferred-provider` |
| `observability-helper.sh` | 9 | `summary`, `models`, `projects`, `costs`, `trend`, `sync-budget`, `prune`, `cleanup` |

These were added during the t1337.3/t1337.5 simplification. If no callers remain (check: `rg 'budget-tracker-helper.sh.*check\|budget-tracker-helper.sh.*recommend'`), they can be removed.

**Savings:** ~22 lines.

### 3. Dead functions in issue-sync-lib.sh (MEDIUM)

`find_closing_pr` and `task_has_completion_evidence` are dead in active code — superseded by inline versions in `issue-sync-helper.sh`. Remove them.

**Caveat (from review):** `supervisor-archived/issue-audit.sh` still calls both functions directly (not the `_`-prefixed replacements). This is archived code and not executed in production, but it confirms the functions are not universally dead. Before removing, verify: (1) `issue-audit.sh` is truly archived and will not be revived, (2) no other archived or experimental scripts source `issue-sync-lib.sh` and call these functions. Run: `rg 'find_closing_pr|task_has_completion_evidence' .agents/scripts/ --type sh` and review all hits, including `supervisor-archived/`. If the archived script is the only caller, removal is safe — but document the decision in the commit message.

**Savings:** ~80 lines from issue-sync-lib.sh.

### 4. issue-sync-helper.sh `cmd_parse` debug command (LOW)

51 lines of debug/diagnostic code. Could be removed or moved to a separate debug script. Low priority since it doesn't affect production.

**Savings:** ~51 lines.

### 5. `cmd_rate_limits` display logic in observability-helper.sh (MEDIUM)

Lines 433-574 (141 lines) are a table/JSON formatter for rate limit display. This is the largest single function. The JSON output path is useful for programmatic access, but the table formatter could be simplified or the AI could format the JSON output itself.

**Savings:** ~50-70 lines if table formatting is removed (keep JSON output).

### 6. issue-sync-helper.sh gh_* wrappers (LOW — keep for now)

11 thin `gh_*` wrapper functions (lines 92-170, ~78 lines). These add a consistent error-handling layer around `gh` CLI calls. While they could be inlined, the abstraction is clean and aids testability.

**Recommendation:** Keep. The abstraction cost is low and the consistency benefit is real.

### 7. full-loop-helper.sh emit_* phase functions (LOW — keep)

6 `emit_*` functions (lines 162-216, ~55 lines) that print phase markers for the AI to read. These are the script's core purpose — emitting structured output for AI consumption. Keep.

## Cross-Script Dependencies

```text
full-loop-helper.sh
  └── shared-constants.sh (print_*, colors, sed_inplace)

fallback-chain-helper.sh
  ├── shared-constants.sh
  └── model-availability-helper.sh (delegates availability checks)

budget-tracker-helper.sh
  └── shared-constants.sh

issue-sync-helper.sh
  ├── shared-constants.sh
  └── issue-sync-lib.sh (1,256 lines — TODO.md parser, plan extractor, body composer)

observability-helper.sh
  └── shared-constants.sh
```

## Recommended Actions for t1337.2

Priority-ordered consolidation work:

1. ~~**Merge `get_model_pricing`**~~ **DONE (t1337.2):** Consolidated into `shared-constants.sh` using the 4-field version. Both `budget-tracker-helper.sh` and `observability-helper.sh` now delegate to it. Budget-tracker discards fields 3-4 via `IFS='|' read -r input output _ _`. (~25 lines saved)

2. **Remove backward-compat stubs** from budget-tracker-helper.sh and observability-helper.sh after verifying no active callers. (~22 lines saved)

3. **Remove dead functions** from issue-sync-lib.sh: `find_closing_pr`, `task_has_completion_evidence`. (~80 lines saved)

4. **Simplify `cmd_rate_limits` table formatter** in observability-helper.sh — keep JSON output, simplify or remove ASCII table. (~50-70 lines saved)

5. **Consider removing `cmd_parse`** from issue-sync-helper.sh if not used for debugging. (~51 lines saved)

6. **Trim issue-sync-lib.sh** — the `compose_issue_body` function (lines 784-1035, ~250 lines) is the largest single function in the entire Tier 3 codebase. It builds rich GitHub issue bodies with plan sections, file summaries, and subtask lists. Review whether all sections are needed or if a simpler body template would suffice.

**Total estimated savings:** ~250-400 lines across all scripts + lib.

## Key Finding: Scripts Already Simplified

The t1337 brief estimated 8,346 lines needing reduction to ~2,000. Current state is 2,647 lines — meaning **~5,700 lines (68%) have already been removed**, likely by earlier t1337.x subtasks. The remaining gap to target is ~647 lines, achievable through the consolidation targets above.

The `issue-sync-lib.sh` (1,256 lines) was not in the original brief scope but represents the largest remaining complexity. If included, the total Tier 3 infrastructure is 3,903 lines (scripts + lib).

## Verification

```bash
# Current line counts (verified 2026-02-26)
wc -l .agents/scripts/full-loop-helper.sh        # 534
wc -l .agents/scripts/fallback-chain-helper.sh    # 261
wc -l .agents/scripts/budget-tracker-helper.sh    # 309
wc -l .agents/scripts/issue-sync-helper.sh        # 903
wc -l .agents/scripts/observability-helper.sh     # 640
wc -l .agents/scripts/issue-sync-lib.sh           # 1256

# Duplicate function check
grep -rn '^get_model_pricing()' .agents/scripts/*.sh
# Returns 2 hits: budget-tracker-helper.sh:26, observability-helper.sh:62

# Dead function check in issue-sync-lib.sh
rg 'find_closing_pr|task_has_completion_evidence' .agents/scripts/ --type sh | grep -v 'issue-sync-lib.sh' | grep -v 'archived/'
# Returns 0 hits in active code — but supervisor-archived/issue-audit.sh calls both.
# Archived callers do not affect production; removal is safe if issue-audit.sh stays archived.
```
