You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Enhance agentic development environment to perform Lint check before commit #423
Workflow logs at https://github.com/petry-projects/.github-private/actions/workflows/lint.yml?query=is%3Afailure
show that the Agentic dev-lead workflow saves commits without first performing the repo's required lint check.
This results in a CI failure which inefficiently triggers another dev-lead workflow to triage and fix the issue from the previous session.
This is an avoidable cost that should be optimized.
Goal: Research and identify the best approach to consistently ensure that agents are performing the appropriate repo specific validation checks to validate its work BEFORE committing changes.
Decision: We are proceeding with Option A + B (deterministic pre-commit validation gate + bounded in-session self-correction loop). Detailed implementation plan below.
Root cause
The validation responsibility is split between two layers that disagree on who enforces it:
The prompts ask the agent to lint — softly and non-deterministically.prompts/dev-lead/fix-issue.md Phase 4 says "Run any available lint/format checks" with generic examples (npm run lint, ruff, cargo clippy). The LLM can skip it, partially run it, or claim success. Worse, the examples don't match this repo — there is no npm run lint, no Makefile, no single lint entrypoint.
The actual commit is done by deterministic shell that performs zero validation. All three commit paths just git add -A && git commit && git push:
The repo's lint is repo-specific and not auto-discoverable.lint.yml runs four distinct jobs an agent would have to reverse-engineer from YAML: shellcheck on specific files, bats tests/fleet_report.bats, agent-profile frontmatter validation, and gh aw compile --no-emit + orphaned-lock detection.
The one place that could enforce a gate deterministically doesn't; the place that's told to lint can't be trusted to. Confirmed in CI history (e.g. branch dev-lead/issue-232-... produced a cascade of consecutive lint.yml failures — the "fail → re-trigger → fail again" loop).
Options considered
#
Approach
Verdict
A
Deterministic pre-push validation gate in the commit scripts, driven by a repo-declared validation command convention
✅ Selected
B
Bounded self-correction loop: run validation → on failure feed output back to the engine → re-run → re-validate (cap ~2 iters) before pushing
✅ Selected
C
Strengthen prompts to mandate lint + paste output as proof
❌ Still non-deterministic; LLM can skip/fabricate; doesn't know repo checks
D
Run the real lint.yml locally via act
❌ Heavy, slow, Docker-in-runner, brittle
E
Make lint.yml a required check + rely on existing fix-ci
❌ This is the current expensive re-trigger path the issue wants to eliminate
Why A + B: A converts the soft prompt request into a hard, machine-checked gate and is cross-repo via convention. B resolves failures in the same session instead of paying for a fresh check_run → ci-relay → repository_dispatch → dispatch run (re-checkout, engine install, intent classification, preflight, full agentic run). Together they close the loop deterministically.
A is fully engine-agnostic — the gate is pure bash running afterrun_writer_with_fallback returns; it never touches the LLM.
B works across all three engines because all commit paths funnel through one writer entry point (run_writer_with_fallback → run_writer), and per-engine flag differences (claude --permission-mode acceptEdits / gemini --approval-mode auto_edit / gh copilot --yolo) are already handled inside run_writer.
B must honor three design constraints (these are the make-or-break rules, all enforced in the plan below):
No session continuity anywhere. Every engine call is one-shot (claude --print / gemini --prompt "" <stdin / gh copilot -p). The fix loop must rebuild a full, self-contained prompt each iteration (original task + git diff + captured failure output). State lives in the working tree + re-inlined prompt, never the engine. This is uniform across engines, not a per-engine quirk.
The fallback can switch engines mid-task (run_writer_with_fallback walks claude → gemini → copilot on rate-limit, and silently skips copilot when given a classic ghp_ PAT). A fix iteration may run on a different engine than the original — safe because of test issue from agent #1.
Fail closed. If validation still fails after the iteration cap, or all engines are rate-limited (exit 2) during a fix, the gate must decline to push and post a comment — never push known-failing code (that recreates the re-trigger cost).
Implementation Plan
Three parts, in order. Part 2 doubles as the reference implementation that proves the standard before org-wide rollout.
Part 1 — Define Option A as a new org standard in petry-projects/.github
Establish the Pre-Commit Validation Gate contract that every org repo (and dev-lead) honors.
New standard doc — add standards/ci-standards.md section (or new standards/pre-commit-validation-standard.md) defining the contract:
Every repo SHOULD provide an executable scripts/validate.sh (POSIX #!/usr/bin/env bash, set -euo pipefail) that runs all repo-required checks (lint, tests, schema/format validation) and exits non-zero on any failure.
Contract: exit 0 = safe to commit; non-zero = block. Self-contained, no required args, deterministic, no network mutations, safe to run on a dirty working tree.
Single source of truth: the repo's lint/CI workflow MUST invoke scripts/validate.sh rather than duplicate commands inline, so the local gate and CI never drift.
Discovery fallback: if scripts/validate.sh is absent, dev-lead auto-detects common commands (npm run lint, ruff check ., golangci-lint run, cargo clippy, etc.) — opt-in, non-fatal, logged.
Template starter — add standards/scripts/validate.sh: a generic, commented starter that repos customize. Includes auto-detect stubs and clear "replace with your repo's checks" markers.
Reference it from standards/AGENTS.md so agents read the contract during Phase 1 scoping.
Part 2 — Implement Option B in petry-projects/.github-private (reference implementation)
New shared lib scripts/lib/validate.sh, sourced by the three commit paths (all already source engine.sh):
run_validation() — locate & execute scripts/validate.sh (or auto-detect per the standard), capture combined output to a temp file, return rc. No-op success under DEV_LEAD_DRY_RUN=true.
validate_and_fix() — the stateless retry loop honoring the three engine constraints:
run_validation; if rc=0 → return 0.
On failure, build a fresh self-contained fix prompt: original intent + git diff HEAD + captured validation output.
Re-validate. Cap at 2 iterations (bounded by ACTION_TIMEOUT_SEC=600s × 2 well within the 60-min job cap).
On persistent failure or rate-limit (exit 2) → return non-zero without pushing (fail-closed).
Wire the gate before every push:
commit_and_push in dev-lead-fix-reviews.sh (between change-detection and commit/push).
Inline commit in dev-lead-fix-issue.sh:103-107.
Inline commit in dev-lead-fix-ci.sh:257-264.
On gate failure: post a PR/issue comment ("lint still failing after N auto-fix attempts — needs human attention"), skip push, and do not emit the ci-relay re-trigger.
This repo's own scripts/validate.sh mirroring lint.yml's four jobs (shellcheck on the specified files, bats tests/fleet_report.bats, agent-profile frontmatter validation, gh aw compile --no-emit + orphan-lock detection). Refactor lint.yml to call scripts/validate.sh for the local-runnable checks (single source of truth; gh-aw-compile may stay a separate CI job if tooling-heavy).
Prompt updates — replace the soft "run any available lint" language with a directive pointing at scripts/validate.sh as the canonical gate, in fix-issue.md (Phase 4), review-changes.md, fix-ci.md, on-mention.md.
standards-sync.yml (monthly first-Monday cron + workflow_dispatch) then opens PRs adding scripts/validate.sh to non-compliant repos and reports a summary issue here.
Seed-then-tailor caveat (call out in the PR body): the synced file is a generic starter. Each repo's real checks must be filled in by its owner or a follow-up dev-lead pass. Standards-sync only guarantees the file exists and the contract is documented; it cannot infer per-repo lint commands.
Safe rollout: because Part 2 ships with the auto-detect fallback, repos without a tailored validate.sh are never broken — the gate degrades gracefully. Roll out the template, then monitor the lint.yml failure rate / fleet-monitor to confirm the re-trigger cost drops.
Sequencing & acceptance criteria
Order: Part 2 first (reference implementation + this repo's gate), Part 1 formalizes the contract it proved, Part 3 propagates.
Done when:
dev-lead never pushes a commit that fails this repo's scripts/validate.sh;
on a fixable lint error, dev-lead self-corrects in the same session (no new fix-ci dispatch);
on an unfixable error, it fails closed with a clear comment and no wasteful re-trigger;
behavior is identical across DEV_LEAD_ENGINE = claude / gemini / copilot;
the validate.sh standard is documented in petry-projects/.github and enrolled in standards-sync.
Risks / open decisions
Iteration cap vs. job budget — start at 2; tune via env (DEV_LEAD_VALIDATE_MAX_ITERS).
gh-aw compile locality — needs the gh-aw extension; may remain a CI-only check rather than part of the local gate. Decide during Part 2.
Generic-template usefulness — the seeded validate.sh is only as good as each repo's customization; rollout success depends on a tailoring follow-up, not just file presence.
Breaking the global "Done when" list into testable criteria scoped to each part. Each item is independently verifiable.
Part 1 — validate.sh standard in petry-projects/.github
standards/ci-standards.md (or new standards/pre-commit-validation-standard.md) documents the contract: scripts/validate.sh, exit-code semantics (0 = safe to commit, non-zero = block), self-contained / no-required-args / dirty-tree-safe, and the single-source-of-truth rule (CI invokes the same script).
standards/scripts/validate.sh template exists, is executable, passes shellcheck --severity=warning, begins with #!/usr/bin/env bash + set -euo pipefail, and exits 0 on a clean checkout of the template repo.
The template documents the auto-detect fallback and contains clearly marked "replace with your repo's checks" sections.
standards/AGENTS.md references the new standard so agents encounter it during Phase 1 scoping.
standards/workflows/lint.yml (org template) invokes scripts/validate.sh rather than duplicating check commands inline.
Part 2 — Option B reference implementation in .github-private
scripts/lib/validate.sh exists and passes shellcheck --severity=warning; run_validation returns 0 on a clean tree and non-zero when a check fails; both return 0 (no-op) under DEV_LEAD_DRY_RUN=true.
The gate is wired before push in all three paths — commit_and_push (dev-lead-fix-reviews.sh), inline commit in dev-lead-fix-issue.sh, inline commit in dev-lead-fix-ci.sh.
Happy path: given a fixable lint error introduced by the engine, dev-lead self-corrects and pushes a passing commit within the same session — no new fix-ci dispatch is emitted (verifiable: no repository_dispatch dev-lead-ci-failure for that SHA).
Fail-closed: when validation still fails after the iteration cap, the script does not push, posts a "needs human attention" comment, and exits non-zero. Same behavior when run_writer_with_fallback returns exit 2 (all engines rate-limited) mid-fix.
Bounded: the retry loop honors DEV_LEAD_VALIDATE_MAX_ITERS (default 2) and each iteration rebuilds a full self-contained prompt (no reliance on session memory).
Engine parity: the happy path and fail-closed behaviors are identical for DEV_LEAD_ENGINE = claude, gemini, and copilot.
scripts/validate.sh exists in this repo and reproduces lint.yml's checks; running it locally on a known-bad tree fails, and on main passes. lint.yml invokes it for the local-runnable checks (no command drift).
Prompts (fix-issue.md Phase 4, review-changes.md, fix-ci.md, on-mention.md) point at scripts/validate.sh as the canonical gate instead of the soft "run any available lint" language.
New bats tests cover: validate-command discovery, fail-closed exit, dry-run no-op, and the iteration cap.
Part 3 — Org-wide rollout via standards-sync
REQUIRED_FILES in scripts/aw-standards-sync.sh includes "scripts/validate.sh|standards/scripts/validate.sh".
A workflow_dispatch run of standards-sync.yml opens PRs adding scripts/validate.sh to every non-compliant active org repo and produces the summary issue here, with no errors in the run log.
The standards-sync PR body states the seed-then-tailor caveat (synced file is a generic starter; per-repo checks must be filled in).
No-regression guarantee: a repo that has the seeded-but-untailored validate.sh (or none at all) still has dev-lead commit successfully via the auto-detect fallback — the gate degrades gracefully, never hard-blocks an otherwise-valid change.
After rollout, the lint.yml failure rate attributable to dev-lead pushes (tracked via fleet-monitor) trends down — confirming the re-trigger cost is actually reduced.
Issue:#423 — Enhance agentic development environment to perform Lint check before commit
Scope
Add a scripts/dev-lead-lint.sh runner that executes the repo's lint checks locally, call it from dev-lead-fix-issue.sh before committing (blocking bad commits), and update the fix-issue.md prompt so the agent explicitly runs it during Phase 4 verification.
Implementation Checklist
Create scripts/dev-lead-lint.sh — runs shellcheck on all scripts/**/*.sh and validates agents/*.md frontmatter; exits non-zero on any failure
Update scripts/dev-lead-fix-issue.sh — add pre-commit lint step that calls dev-lead-lint.sh; if lint fails, post a comment on the issue and exit without committing
Update prompts/dev-lead/fix-issue.md — Phase 4 now explicitly says bash scripts/dev-lead-lint.sh so the agent knows the exact command
Tests to Write
tests/dev-lead/unit/test_dev_lead_lint.bats — new bats test file for dev-lead-lint.sh: tests shellcheck pass, shellcheck fail, agent-profile pass, agent-profile fail
Created scripts/dev-lead-lint.sh — runs shellcheck (warning level) on all scripts/**/*.sh and validates agents/*.md frontmatter; mirrors the checks in ci.yml that are fast and tool-free
Updated scripts/dev-lead-fix-issue.sh — added pre-commit lint step after the engine run; if lint fails, posts a descriptive issue comment and exits 1 without committing (prevents CI waste)
Updated prompts/dev-lead/fix-issue.md — Phase 4 now specifies bash scripts/dev-lead-lint.sh as the required lint command instead of vague "check AGENTS.md or CI config" guidance
Wrote 12 new unit tests for scripts/dev-lead-lint.sh covering shellcheck pass/fail and agent-profile validation pass/fail cases
Wrote 3 new tests for dev-lead-fix-issue.sh verifying: lint-pass proceeds to commit; lint-fail blocks commit; lint-fail posts an issue comment
Test Results
=== dev-lead unit tests: 195/197 pass (2 pre-existing failures unrelated to this issue) ===
ok 1–12 lint: passes when no shell scripts exist … exits 0 when all checks pass
ok 85 fix-issue: lint passes → proceeds to commit without error
ok 86 fix-issue: lint fails → posts issue comment and exits without committing
ok 87 fix-issue: lint fails → posts lint-failure comment on the issue
Pre-existing failures (not introduced by this change — verified against base commit):
not ok 83 fix-issue: rate-limited: all engines rate-limited → exits 2, not 1
not ok 84 fix-issue: rate-limited: posts comment on issue before exiting
Files Changed
scripts/dev-lead-lint.sh (new): local lint runner that replicates the CI shellcheck and agent-profile validation checks
scripts/dev-lead-fix-issue.sh: added pre-commit lint gate; if dev-lead-lint.sh exits non-zero, commits are blocked and an issue comment is posted
prompts/dev-lead/fix-issue.md: Phase 4 now names the exact lint command rather than pointing vaguely at CI config
tests/dev-lead/unit/test_dev_lead_lint.bats (new): 12 unit tests for the lint runner
tests/dev-lead/unit/test_fix_issue.bats: 3 new tests for the lint-before-commit behavior
Notes
Two-layer defence: the prompt tells the agent to run bash scripts/dev-lead-lint.sh during Phase 4 (agent-side); the shell script also runs it before committing (system-side) as a safety net in case the agent skips Phase 4.
On lint failure: the commit is aborted, an issue comment is posted with the exact shellcheck/profile errors, and the workflow exits 1. The dev-lead label stays on the issue — re-applying it retries the implementation. This avoids the original problem: no bad commit → no CI failure → no wasted fix-ci dev-lead run.
Scope limited to fix-issue.sh:fix-ci.sh and fix-reviews.sh modify existing code (less likely to introduce new lint failures) and were not changed. This can be revisited if lint failures from those handlers are observed.
Pre-existing test failures:test_fix_issue.bats tests 83–84 (rate-limit scenarios) were already failing on the base commit and are unrelated to this change.
Activity
don-petry commentedon Jun 4, 2026
Analysis, Options & Recommendation
Root cause
The validation responsibility is split between two layers that disagree on who enforces it:
prompts/dev-lead/fix-issue.mdPhase 4 says "Run any available lint/format checks" with generic examples (npm run lint,ruff,cargo clippy). The LLM can skip it, partially run it, or claim success. Worse, the examples don't match this repo — there is nonpm run lint, no Makefile, no single lint entrypoint.git add -A && git commit && git push:scripts/dev-lead-fix-issue.sh:103-107scripts/dev-lead-fix-reviews.sh:336-394(commit_and_push)scripts/dev-lead-fix-ci.sh:257-264lint.ymlruns four distinct jobs an agent would have to reverse-engineer from YAML:shellcheckon specific files,bats tests/fleet_report.bats, agent-profile frontmatter validation, andgh aw compile --no-emit+ orphaned-lock detection.The one place that could enforce a gate deterministically doesn't; the place that's told to lint can't be trusted to. Confirmed in CI history (e.g. branch
dev-lead/issue-232-...produced a cascade of consecutivelint.ymlfailures — the "fail → re-trigger → fail again" loop).Options considered
lint.ymllocally viaactlint.ymla required check + rely on existingfix-ciWhy A + B: A converts the soft prompt request into a hard, machine-checked gate and is cross-repo via convention. B resolves failures in the same session instead of paying for a fresh
check_run → ci-relay → repository_dispatch → dispatchrun (re-checkout, engine install, intent classification, preflight, full agentic run). Together they close the loop deterministically.Multi-engine compatibility (Claude SDK / Gemini / Copilot)
Verified against the
engine.shabstraction:run_writer_with_fallbackreturns; it never touches the LLM.run_writer_with_fallback→run_writer), and per-engine flag differences (claude --permission-mode acceptEdits/gemini --approval-mode auto_edit/gh copilot --yolo) are already handled insiderun_writer.B must honor three design constraints (these are the make-or-break rules, all enforced in the plan below):
claude --print/gemini --prompt "" <stdin/gh copilot -p). The fix loop must rebuild a full, self-contained prompt each iteration (original task +git diff+ captured failure output). State lives in the working tree + re-inlined prompt, never the engine. This is uniform across engines, not a per-engine quirk.run_writer_with_fallbackwalks claude → gemini → copilot on rate-limit, and silently skips copilot when given a classicghp_PAT). A fix iteration may run on a different engine than the original — safe because of test issue from agent #1.Implementation Plan
Three parts, in order. Part 2 doubles as the reference implementation that proves the standard before org-wide rollout.
Part 1 — Define Option A as a new org standard in
petry-projects/.githubEstablish the Pre-Commit Validation Gate contract that every org repo (and dev-lead) honors.
standards/ci-standards.mdsection (or newstandards/pre-commit-validation-standard.md) defining the contract:scripts/validate.sh(POSIX#!/usr/bin/env bash,set -euo pipefail) that runs all repo-required checks (lint, tests, schema/format validation) and exits non-zero on any failure.scripts/validate.shrather than duplicate commands inline, so the local gate and CI never drift.scripts/validate.shis absent, dev-lead auto-detects common commands (npm run lint,ruff check .,golangci-lint run,cargo clippy, etc.) — opt-in, non-fatal, logged.standards/scripts/validate.sh: a generic, commented starter that repos customize. Includes auto-detect stubs and clear "replace with your repo's checks" markers.standards/workflows/lint.yml(org template) to callscripts/validate.sh, reinforcing single-source-of-truth.standards/AGENTS.mdso agents read the contract during Phase 1 scoping.Part 2 — Implement Option B in
petry-projects/.github-private(reference implementation)scripts/lib/validate.sh, sourced by the three commit paths (all alreadysource engine.sh):run_validation()— locate & executescripts/validate.sh(or auto-detect per the standard), capture combined output to a temp file, return rc. No-op success underDEV_LEAD_DRY_RUN=true.validate_and_fix()— the stateless retry loop honoring the three engine constraints:run_validation; if rc=0 → return 0.git diff HEAD+ captured validation output.run_writer_with_fallback(tolerates mid-loop engine switch).ACTION_TIMEOUT_SEC=600s× 2 well within the 60-min job cap).commit_and_pushindev-lead-fix-reviews.sh(between change-detection and commit/push).dev-lead-fix-issue.sh:103-107.dev-lead-fix-ci.sh:257-264.scripts/validate.shmirroringlint.yml's four jobs (shellcheck on the specified files,bats tests/fleet_report.bats, agent-profile frontmatter validation,gh aw compile --no-emit+ orphan-lock detection). Refactorlint.ymlto callscripts/validate.shfor the local-runnable checks (single source of truth;gh-aw-compilemay stay a separate CI job if tooling-heavy).scripts/validate.shas the canonical gate, infix-issue.md(Phase 4),review-changes.md,fix-ci.md,on-mention.md.batscoverage: validate-command discovery, fail-closed behavior, dry-run no-op, retry-loop iteration cap.Part 3 — Apply the standard across all org repos
Leverage the existing standards-sync propagation mechanism:
scripts/aw-standards-sync.shREQUIRED_FILES:standards-sync.yml(monthly first-Monday cron +workflow_dispatch) then opens PRs addingscripts/validate.shto non-compliant repos and reports a summary issue here.validate.share never broken — the gate degrades gracefully. Roll out the template, then monitor thelint.ymlfailure rate / fleet-monitor to confirm the re-trigger cost drops.Sequencing & acceptance criteria
scripts/validate.sh;fix-cidispatch);DEV_LEAD_ENGINE= claude / gemini / copilot;validate.shstandard is documented inpetry-projects/.githuband enrolled in standards-sync.Risks / open decisions
DEV_LEAD_VALIDATE_MAX_ITERS).gh-aw compilelocality — needs thegh-awextension; may remain a CI-only check rather than part of the local gate. Decide during Part 2.validate.shis only as good as each repo's customization; rollout success depends on a tailoring follow-up, not just file presence.don-petry commentedon Jun 4, 2026
Acceptance Criteria — per implementation part
Breaking the global "Done when" list into testable criteria scoped to each part. Each item is independently verifiable.
Part 1 —
validate.shstandard inpetry-projects/.githubstandards/ci-standards.md(or newstandards/pre-commit-validation-standard.md) documents the contract:scripts/validate.sh, exit-code semantics (0= safe to commit, non-zero = block), self-contained / no-required-args / dirty-tree-safe, and the single-source-of-truth rule (CI invokes the same script).standards/scripts/validate.shtemplate exists, is executable, passesshellcheck --severity=warning, begins with#!/usr/bin/env bash+set -euo pipefail, and exits0on a clean checkout of the template repo.standards/AGENTS.mdreferences the new standard so agents encounter it during Phase 1 scoping.standards/workflows/lint.yml(org template) invokesscripts/validate.shrather than duplicating check commands inline.Part 2 — Option B reference implementation in
.github-privatescripts/lib/validate.shexists and passesshellcheck --severity=warning;run_validationreturns0on a clean tree and non-zero when a check fails; both return0(no-op) underDEV_LEAD_DRY_RUN=true.commit_and_push(dev-lead-fix-reviews.sh), inline commit indev-lead-fix-issue.sh, inline commit indev-lead-fix-ci.sh.fix-cidispatch is emitted (verifiable: norepository_dispatch dev-lead-ci-failurefor that SHA).run_writer_with_fallbackreturns exit2(all engines rate-limited) mid-fix.DEV_LEAD_VALIDATE_MAX_ITERS(default 2) and each iteration rebuilds a full self-contained prompt (no reliance on session memory).DEV_LEAD_ENGINE=claude,gemini, andcopilot.scripts/validate.shexists in this repo and reproduceslint.yml's checks; running it locally on a known-bad tree fails, and onmainpasses.lint.ymlinvokes it for the local-runnable checks (no command drift).fix-issue.mdPhase 4,review-changes.md,fix-ci.md,on-mention.md) point atscripts/validate.shas the canonical gate instead of the soft "run any available lint" language.batstests cover: validate-command discovery, fail-closed exit, dry-run no-op, and the iteration cap.Part 3 — Org-wide rollout via standards-sync
REQUIRED_FILESinscripts/aw-standards-sync.shincludes"scripts/validate.sh|standards/scripts/validate.sh".workflow_dispatchrun ofstandards-sync.ymlopens PRs addingscripts/validate.shto every non-compliant active org repo and produces the summary issue here, with no errors in the run log.validate.sh(or none at all) still has dev-lead commit successfully via the auto-detect fallback — the gate degrades gracefully, never hard-blocks an otherwise-valid change.lint.ymlfailure rate attributable to dev-lead pushes (tracked via fleet-monitor) trends down — confirming the re-trigger cost is actually reduced.don-petry commentedon Jun 4, 2026
Dev-Lead Implementation Plan
Issue: #423 — Enhance agentic development environment to perform Lint check before commit
Scope
Add a
scripts/dev-lead-lint.shrunner that executes the repo's lint checks locally, call it fromdev-lead-fix-issue.shbefore committing (blocking bad commits), and update thefix-issue.mdprompt so the agent explicitly runs it during Phase 4 verification.Implementation Checklist
scripts/dev-lead-lint.sh— runs shellcheck on allscripts/**/*.shand validatesagents/*.mdfrontmatter; exits non-zero on any failurescripts/dev-lead-fix-issue.sh— add pre-commit lint step that callsdev-lead-lint.sh; if lint fails, post a comment on the issue and exit without committingprompts/dev-lead/fix-issue.md— Phase 4 now explicitly saysbash scripts/dev-lead-lint.shso the agent knows the exact commandTests to Write
tests/dev-lead/unit/test_dev_lead_lint.bats— new bats test file fordev-lead-lint.sh: tests shellcheck pass, shellcheck fail, agent-profile pass, agent-profile failtests/dev-lead/unit/test_fix_issue.bats— add cases: lint passes → commit proceeds; lint fails → no commit, issue comment postedTest Command
bats tests/dev-lead/unit/don-petry commentedon Jun 4, 2026
Dev-Lead: Implementation Complete
Plan Execution
scripts/dev-lead-lint.sh— runs shellcheck (warning level) on allscripts/**/*.shand validatesagents/*.mdfrontmatter; mirrors the checks inci.ymlthat are fast and tool-freescripts/dev-lead-fix-issue.sh— added pre-commit lint step after the engine run; if lint fails, posts a descriptive issue comment and exits 1 without committing (prevents CI waste)prompts/dev-lead/fix-issue.md— Phase 4 now specifiesbash scripts/dev-lead-lint.shas the required lint command instead of vague "check AGENTS.md or CI config" guidancescripts/dev-lead-lint.shcovering shellcheck pass/fail and agent-profile validation pass/fail casesdev-lead-fix-issue.shverifying: lint-pass proceeds to commit; lint-fail blocks commit; lint-fail posts an issue commentTest Results
Files Changed
scripts/dev-lead-lint.sh(new): local lint runner that replicates the CI shellcheck and agent-profile validation checksscripts/dev-lead-fix-issue.sh: added pre-commit lint gate; ifdev-lead-lint.shexits non-zero, commits are blocked and an issue comment is postedprompts/dev-lead/fix-issue.md: Phase 4 now names the exact lint command rather than pointing vaguely at CI configtests/dev-lead/unit/test_dev_lead_lint.bats(new): 12 unit tests for the lint runnertests/dev-lead/unit/test_fix_issue.bats: 3 new tests for the lint-before-commit behaviorNotes
bash scripts/dev-lead-lint.shduring Phase 4 (agent-side); the shell script also runs it before committing (system-side) as a safety net in case the agent skips Phase 4.dev-leadlabel stays on the issue — re-applying it retries the implementation. This avoids the original problem: no bad commit → no CI failure → no wasted fix-ci dev-lead run.fix-issue.sh:fix-ci.shandfix-reviews.shmodify existing code (less likely to introduce new lint failures) and were not changed. This can be revisited if lint failures from those handlers are observed.test_fix_issue.batstests 83–84 (rate-limit scenarios) were already failing on the base commit and are unrelated to this change.feat: implement issue #423 — Enhance agentic development environment …
feat: implement issue #423 — Enhance agentic development environment …
feat: implement issue #423 — Enhance agentic development environment …
feat: implement issue #423 — Enhance agentic development environment …
feat: implement issue #423 — Enhance agentic development environment …
feat: implement issue #423 — Enhance agentic development environment …
feat: implement issue #423 — Enhance agentic development environment …
feat: implement issue #423 — Enhance agentic development environment …
feat: implement issue #423 — Enhance agentic development environment …