# Issue-Backed Closeout Guards Discussion Source

## Status

- Date: 2026-05-21
- Source: User discussion in the current Codex thread after live repair of
  `sympoies/nils-cli` issue 384.
- Tracking issue: [graysurf/agent-kit#273](https://github.com/graysurf/agent-kit/issues/273)
- Intended next step: Create a provider tracking issue, then implement the
  sibling plan.
- Recommended plan:
  `docs/plans/issue-backed-closeout-guards/issue-backed-closeout-guards-plan.md`
- Recommended execution state:
  `docs/plans/issue-backed-closeout-guards/issue-backed-closeout-guards-execution-state.md`

## Purpose

Prevent issue-backed execution from finishing the code path while leaving the
GitHub issue dashboard or latest `execute-from-tracking-issue:state:v1`
comment in an incomplete state.

## Confirmed Facts

- `sympoies/nils-cli` issue 384 was created as a plan-tracking issue for CLI
  destructive-operation safety.
- The issue had source and plan snapshot comments, execution-state comments,
  session comments, validation evidence, and merged PR evidence.
- PR 415 merged Sprint 1. PR 417 merged the remaining Sprint 2 and Sprint 3
  work and referenced `Closes #384`.
- GitHub closed issue 384 after PR 417 merged.
- The latest execution-state comment before repair still had
  `Status: in-progress`, `Current task: Task 2.1`, and pending Sprint 2/Sprint 3
  rows.
- The issue body dashboard before repair still showed `Status: in-progress` and
  only linked PR 415.
- A plain closeout comment recorded PR 417, merge commit
  `1b99ac07bb4bee3017b89d9817eb7f1fc82bc46f`, local validation, and remote
  validation, but it did not use the canonical
  `<!-- tracking-issue-closeout:v1 -->` marker.
- The current `tracking-issue-closeout --repair-closed` path repaired the body
  after a complete execution-state comment was manually added, but before that
  manual state repair it did not reject the stale incomplete state strongly
  enough.
- The PR close helper's required-check handling has already been tightened for
  optional skipped `coverage_badge` jobs; the remaining issue is not check
  gating, but plan-tracking lifecycle gating around PR merge and issue close.

## Decisions

1. Treat the latest issue-hosted execution-state comment as the durable
   completion gate for issue-backed execution.
2. Require a complete state ledger before any issue-backed workflow merges a PR
   that will close a plan-tracking issue or reports issue-backed closeout as
   complete.
3. Keep execution-state creation and repair owned by
   `execute-from-tracking-issue`, not by generic PR delivery or closeout
   helpers.
4. Make `tracking-issue-closeout` fail closed when the latest execution state is
   incomplete, even if PR and validation evidence exist.
5. Add a safe already-closed repair/finalization path for issues that GitHub
   auto-closed from PR merge before the closeout helper ran.
6. Keep generic GitHub PR close skills provider-focused, but let them detect
   plan-tracking issues in `closingIssuesReferences` and block or warn with an
   exact lifecycle command when the durable state gate is not met.

## Scope

- Add completion-state checks to `execute-from-tracking-issue` lifecycle helper
  and skill docs.
- Add incomplete-state closeout gates to `tracking-issue-closeout` helper,
  tests, and skill docs.
- Decide and implement an idempotent closeout marker policy for
  `--repair-closed` when an issue is already closed but lacks
  `<!-- tracking-issue-closeout:v1 -->`.
- Add plan-tracking auto-close detection to GitHub PR close/delivery workflow
  docs and, if practical, the close helper.
- Add regression tests using an issue shaped like nils-cli issue 384: merged PR
  evidence exists, but latest execution state is still `in-progress`.

## Non-Scope

- Do not change `plan-tracking-issue` issue creation or snapshot creation
  semantics.
- Do not move execution-state ownership into `tracking-issue-closeout`.
- Do not make generic PR close skills mutate plan-tracking issues directly.
- Do not weaken required-check gating or treat optional skipped checks as
  success for required jobs.
- Do not reopen already closed issues as part of repair.
- Do not change GitLab issue behavior unless a GitLab-specific lifecycle helper
  is added later.

## Requirements

- `execute-from-tracking-issue` must define a pre-merge/pre-close completion
  gate for issue-backed delivery:
  - latest state marker exists;
  - status is `complete`;
  - all task rows are `done` or explicitly `deferred`;
  - validation and PR evidence are linked;
  - issue dashboard points at the latest state/session/validation comments.
- `tracking-issue-closeout` must fail readiness when the latest state is not
  complete or contains `pending` / `in-progress` rows.
- `tracking-issue-closeout --repair-closed` must apply the same completion-state
  checks before rendering a final dashboard.
- If `--repair-closed` is allowed to append a missing
  `tracking-issue-closeout:v1` marker, it must be explicitly idempotent and
  must not duplicate an existing marker.
- GitHub PR close workflow should detect plan-tracking issues in
  `closingIssuesReferences` and avoid silently merging a PR that will close a
  tracking issue whose latest state is incomplete.
- Docs must tell agents not to rely on a plain closeout comment as the durable
  final state.

## Acceptance Criteria

- A fixture with complete PR/validation evidence but latest execution state
  `in-progress` fails closeout readiness.
- A fixture with `Status: complete` but one `pending` task row fails closeout
  readiness.
- A complete issue with merged PRs passes normal closeout readiness.
- An already closed complete issue can run the explicit repair/finalization path
  without reopening the issue.
- Generic PR close flow either blocks or emits a deterministic lifecycle warning
  when a PR would auto-close an incomplete plan-tracking issue.
- `execute-from-tracking-issue` docs describe the required state checkpoint
  before PR merge or issue close.
- `tracking-issue-closeout` docs describe incomplete-state failure and
  already-closed repair/finalization behavior.
- Focused workflow tests and repository markdown checks pass.

## Validation Plan

- `plan-tooling validate --file docs/plans/issue-backed-closeout-guards/issue-backed-closeout-guards-plan.md --format text --explain`
- `scripts/check.sh --tests -- -k "execute_from_tracking_issue or tracking_issue_closeout or close_github_pr"`
- `scripts/check.sh --markdown`
- `git diff --check`
- `scripts/check.sh --all`

## Risks And Guardrails

- PR close helpers should not become issue lifecycle owners. They should detect
  risky auto-close behavior and hand off to the issue-backed lifecycle skills.
- Closeout repair should not hide a missing execution-state update. It should
  block with a clear next action when state is incomplete.
- Auto-close keywords such as `Closes #384` can close a tracking issue before a
  normal closeout helper runs. Either avoid those keywords for issue-backed
  tracker PRs or support an explicit post-merge `--repair-closed` finalization
  path.
- Keep the issue body mutable and compact; keep source, plan, state, session,
  validation, and closeout evidence append-only in comments.

## Execution

- Execution state recommendation:
  `docs/plans/issue-backed-closeout-guards/issue-backed-closeout-guards-execution-state.md`
- Status: ready for sibling plan execution.
- Next-task source:
  `docs/plans/issue-backed-closeout-guards/issue-backed-closeout-guards-plan.md`

## Retention Intent

This source document is a plan-created coordination artifact. It can be cleaned
up after the workflow guards, tests, docs, and provider issue all reflect the
same closeout contract.

## Open Questions

- Should `tracking-issue-closeout --repair-closed` append a missing
  `tracking-issue-closeout:v1` comment when the issue is already closed, or
  should it remain body-only and require a separate explicit finalization flag?
  Default: allow a one-time explicit finalization flag, but never duplicate an
  existing marker.

## Read-First References

- `skills/workflows/issue/execute-from-tracking-issue/SKILL.md`
- `skills/workflows/issue/execute-from-tracking-issue/bin/tracking_issue_lifecycle.py`
- `skills/workflows/issue/execute-from-tracking-issue/tests/test_workflows_issue_execute_from_tracking_issue.py`
- `skills/workflows/issue/tracking-issue-closeout/SKILL.md`
- `skills/workflows/issue/tracking-issue-closeout/bin/tracking_issue_closeout.py`
- `skills/workflows/issue/tracking-issue-closeout/tests/test_workflows_issue_tracking_issue_closeout.py`
- `skills/workflows/pr/github/close-github-pr/SKILL.md`
- `skills/workflows/pr/github/close-github-pr/scripts/close-github-pr.sh`
- `skills/workflows/pr/github/close-github-pr/tests/test_workflows_pr_github_close_github_pr.py`
- `skills/workflows/pr/github/deliver-github-pr/SKILL.md`
