Skip to content

Auto-create missing labels in file-issues - #26

Open
benthomasson wants to merge 4 commits into
mainfrom
auto-create-labels
Open

Auto-create missing labels in file-issues#26
benthomasson wants to merge 4 commits into
mainfrom
auto-create-labels

Conversation

@benthomasson

Copy link
Copy Markdown
Owner

Summary

  • file-issues now auto-creates missing labels (reasons-gate, reasons-negative, and any --label values) on the target repo before filing issues. Fixes file-issues: auto-create missing labels instead of failing #25.
  • Adds verification commands (verify, infer-sources) and a "Using the Reasons Database" guide to the CLAUDE.md template

Test plan

  • Run code-expert file-issues --dry-run — should not attempt label creation
  • Run code-expert file-issues against a repo without reasons-gate/reasons-negative labels — should create them automatically and file issues successfully
  • Run code-expert file-issues --label custom-label — should also create custom-label if missing
  • Verify code-expert init produces a CLAUDE.md with the new reasons database section

🤖 Generated with Claude Code

benthomasson and others added 2 commits July 20, 2026 13:40
Adds _ensure_labels() that checks the target repo for required labels
and creates any that are missing. Fixes #25.

Also adds verification commands and reasons database usage guide to
CLAUDE.md template.

Co-Authored-By: Claude <noreply@anthropic.com>
…plate

Co-Authored-By: Claude <noreply@anthropic.com>
@benthomasson

Copy link
Copy Markdown
Owner Author

Code Review Report

Branch: #26
Models: claude, gemini
Gate: [CONCERN] CONCERN

claude [CONCERN]

ftl_code_expert/cli.py:_ensure_labels

Verdict: CONCERN
Correctness: QUESTIONABLE
Spec Compliance: N/A
Test Coverage: UNTESTED
Integration: WIRED

Two issues:

  1. GitLab label parsing is broken. The GitHub path correctly uses --json name -q ".[].name" to get one label name per line, but the GitLab path uses bare glab label list which outputs a formatted table (columns with Name, Description, Color, etc.). Splitting on newlines will produce table headers and formatted rows, not clean label names. The required - existing set difference will never match, so every label will be "missing" and glab label create will be called unnecessarily. Creates for already-existing labels fail silently so this doesn't crash, but the dedup logic is dead code on GitLab. Fix: use glab label list --output json and parse JSON, or use a jq-style filter equivalent.

  2. gh label list pagination. Default limit is 30 labels. Repos with many labels may not return all existing labels, causing redundant create attempts. Minor since creation failures are swallowed, but adding -L 1000 would make the check reliable.

Neither issue causes data loss or crashes — label creation is idempotent (fails silently for duplicates) — so this is a CONCERN, not a BLOCK.

ftl_code_expert/cli.py:file_issues (integration point)

Verdict: PASS
Correctness: VALID
Spec Compliance: N/A
Test Coverage: UNTESTED
Integration: WIRED

The integration at lines 3527-3529 is correctly placed: after dedup and confirmation, before filing. The guard conditions (not dry_run and remaining) are appropriate. The required label set {"reasons-gate", "reasons-negative"} | set(labels) correctly covers both hardcoded labels (matching the f"reasons-{ctype}" pattern in the filing loop where ctype is "gate" or "negative") and user-supplied --label values. No issues with the wiring itself.

Self-Review

Limitations: No test files exist for cli.py (confirmed by observations), so I cannot verify whether any test infrastructure exists that should have been extended. Could not verify the exact output format of glab label list at runtime — my concern about table-formatted output is based on known glab CLI behavior but not confirmed against the specific version in use. Could not see the full _detect_platform or _find_existing_issues functions to verify they handle the same platform strings consistently.

Feature Requests

  • Include the output format of external CLI tools (gh, glab) when subprocess calls parse their stdout — a quick runtime sample or man-page excerpt would help verify parsing logic
  • Flag functions with zero test coverage automatically in the observation results, with a note about whether sibling functions have tests (to distinguish "no tests exist for this module" from "this function was skipped")

gemini [CONCERN]

ftl_code_expert/cli.py:_ensure_labels

Verdict: CONCERN
Correctness: QUESTIONABLE
Spec Compliance: N/A
Test Coverage: UNTESTED
Integration: WIRED

The GitHub implementation (gh label list --repo repo_slug --json name -q .[].name) correctly retrieves a clean list of label names. However, the GitLab implementation (glab label list --repo repo_slug) returns human-readable tables/headers containing metadata (e.g. Showing X of Y labels and colors/descriptions on each line). Thus, checking exact match via required - existing on line-by-line output will fail, causing the command to attempt to recreate existing labels on every invocation of file_issues. Also, subprocess exceptions and failure codes for label creation are swallowed silently.

ftl_code_expert/cli.py:file_issues

Verdict: PASS
Correctness: VALID
Spec Compliance: N/A
Test Coverage: UNTESTED
Integration: WIRED

The label check and creation integration is correctly positioned after verifying remaining candidates and before executing the main loop. It correctly guards label auto-creation to only execute when --dry-run is omitted and there are active issues to file, which avoids redundant CLI overhead. However, the functionality is ultimately dependent on the flawed _ensure_labels for GitLab.

Self-Review

Limitations: - Did not have a local environment with glab or gh CLI installed to execute the raw commands and verify exact output formats dynamically.

  • No automated test files were provided or exist in the workspace directory structure, making it impossible to check for regression tests or run verification suites.

Feature Requests

  • Include CLI mock fixtures or sandbox integrations for tool dependencies (e.g. gh and glab) to allow validation of subprocess commands in unit tests.
  • Show related tests or a basic testing suite outline in the workspace context to facilitate writing and reviewing test coverage.

- GitHub: add -L 1000 to gh label list to handle repos with many labels
- GitLab: use -F json output format and parse JSON instead of table output

Co-Authored-By: Claude <noreply@anthropic.com>
@benthomasson

Copy link
Copy Markdown
Owner Author

Code Review Report

Branch: #26
Models: claude, gemini
Gate: [CONCERN] CONCERN

claude [CONCERN]

ftl_code_expert/cli.py:_ensure_labels

Verdict: CONCERN
Correctness: QUESTIONABLE
Spec Compliance: N/A
Test Coverage: UNTESTED
Integration: WIRED

  1. GitHub path looks correctgh label list --json name -q ".[].name" with -L 1000 is a pragmatic approach. Silent failure on gh label create is acceptable since the subsequent _create_issue call will surface the error if the label still doesn't exist.

  2. GitLab path has a potential flag issueglab label list -F json may not be the correct flag across glab versions. The glab CLI has used --output json and -F json inconsistently. However, the existing _create_issue function also shells out to glab with similar patterns, and the try/except around JSON parsing provides a safety net (falls back to empty set, so all labels get created — a harmless over-creation).

  3. No error logging on label creation failure — Both the GitHub and GitLab branches swallow subprocess.run results for label create. A failed creation is silent. The user sees "Creating label: X" but never "Failed to create label: X". Compare with _create_issue (line 3040) which logs result.stderr on failure. This inconsistency could make debugging harder when label creation fails due to permission issues.

  4. No teststest_count: 0. This is a new function with branching logic (GitHub vs GitLab), subprocess calls, and JSON parsing — it warrants at least unit tests with mocked subprocess calls to verify both paths and error handling.

ftl_code_expert/cli.py:file_issues (label integration at line 3536-3538)

Verdict: PASS
Correctness: VALID
Spec Compliance: N/A
Test Coverage: UNTESTED
Integration: WIRED

The integration point is correctly placed — after dedup and confirmation, before filing. The guard not dry_run and remaining is correct: no point creating labels if nothing will be filed or if it's a dry run. The required_labels set correctly unions the two fixed label prefixes with user-supplied --label values. The label set {"reasons-gate", "reasons-negative"} matches the pattern used in the filing loop (line 3549: f"reasons-{ctype}" where ctype is "gate" or "negative").

Self-Review

Limitations: - Could not verify the exact glab label list flag syntax against the installed glab version — the -F json flag correctness is uncertain.

  • No test files were provided or found, so I cannot assess whether existing tests might break or whether test infrastructure exists for subprocess-mocking in this project.
  • The full _find_existing_issues and _confirm_beliefs functions were not observed — cannot verify whether the overall file_issues flow has any ordering dependencies that the new _ensure_labels call might interact with.

Feature Requests

  • When test_count: 0 is detected, include a sample of existing test files for the same module to show the project's testing patterns — this helps reviewers assess whether "untested" is an anomaly or the norm.
  • Include the output of <tool> label list --help or similar to verify CLI flag correctness when the diff shells out to external tools.

gemini [CONCERN]

ftl_code_expert/cli.py:_ensure_labels

Verdict: CONCERN
Correctness: QUESTIONABLE
Spec Compliance: N/A
Test Coverage: UNTESTED
Integration: WIRED

  1. GitLab JSON Parsing Crash Risk: If glab label list outputs a JSON dictionary instead of an array (e.g., on error or different response format such as {"message": "..."}), the loop for item in json.loads(...) will iterate over string keys. Calling item.get("name", "") on a string will raise an AttributeError (since strings do not have a .get method). This exception is not caught by the except (json.JSONDecodeError, TypeError): block and will crash the file-issues command.
  2. GitLab CLI Argument Structure (glab label create): The GitLab CLI (glab) requires specifying the label name via the -n or --name option (e.g., glab label create --name <label>). Passing the label name as a positional argument like ["glab", "label", "create", label, ...] is invalid syntax for glab and will fail or block waiting for interactive input.
  3. No Test Coverage: This newly introduced function is completely untested.

Self-Review

Limitations: - Did not have access to live GitHub/GitLab CLI credentials or binary environments to execute the exact commands and verify their behavior against different API responses.

  • No issue or PR specification was provided, so the assessment is centered entirely on general robustness, syntax compatibility, and code quality.

- Guard GitLab JSON parsing against non-array/non-dict responses
- Use --name flag for glab label create (positional args not supported)
- Log errors when label creation fails on either platform

Co-Authored-By: Claude <noreply@anthropic.com>
@benthomasson

Copy link
Copy Markdown
Owner Author

Code Review Report

Branch: #26
Models: claude, gemini
Gate: [CONCERN] CONCERN

Disagreements

The following changes have different verdicts across models:

  • ftl_code_expert/cli.py:_ensure_labels [LOW]: claude: CONCERN, gemini: PASS

claude [CONCERN]

ftl_code_expert/cli.py:_ensure_labels

Verdict: CONCERN
Correctness: VALID
Spec Compliance: N/A
Test Coverage: UNTESTED
Integration: WIRED

Logic is sound for both GitHub and GitLab paths. GitHub uses --json name -q ".[].name" which correctly produces one label per line. GitLab JSON parsing is defensive with proper type checks and exception handling. If label listing fails (returncode != 0), existing falls back to an empty set, causing all labels to be attempted for creation — if they already exist, the create command fails and the error is logged, which is acceptable best-effort behavior. Two minor observations: (1) required_labels always includes both reasons-gate and reasons-negative even when --no-negative is passed, so an unused label type may be created — harmless but slightly wasteful. (2) If _ensure_labels fails to create a label (e.g., permissions), execution continues but the downstream _create_issue call will also fail for that label since gh issue create --label X requires the label to exist. Both failures are logged, so the user gets visibility. No tests exist for this function.

ftl_code_expert/cli.py:file_issues (integration of _ensure_labels)

Verdict: PASS
Correctness: VALID
Spec Compliance: N/A
Test Coverage: UNTESTED
Integration: WIRED

The call site at line 3543-3545 is correctly placed — after dedup and LLM confirmation but before issue filing. The not dry_run and remaining guard is correct: labels shouldn't be created during dry-run (no side effects), and there's no point creating labels when there are no issues to file. The required_labels union of hardcoded labels and user-provided labels covers all labels that will be referenced by _create_issue.

Self-Review

Limitations: Could not verify glab label list accepts --repo and -F json flags — relying on consistency with existing glab usage in _create_issue. No test files were available to check whether existing test assertions still hold after these changes. Could not verify whether gh label create without --color behaves as expected across gh CLI versions.

Feature Requests

  • Include the test file(s) for the parent command (file_issues) if they exist, even when no tests directly cover the new function — callers' tests may exercise the new code path indirectly
  • Flag when a new function with subprocess calls has zero test coverage, since these are integration-sensitive and hard to verify statically

gemini [PASS]

ftl_code_expert/cli.py:_ensure_labels

Verdict: PASS
Correctness: VALID
Spec Compliance: N/A
Test Coverage: UNTESTED
Integration: WIRED

The _ensure_labels function is correctly implemented with robust checks and defensive JSON parsing for GitLab CLI (glab) output. Error scenarios (non-zero exit codes, malformed JSON, and empty list outputs) are handled gracefully to prevent command crashes. Standard output for status messages is correctly written to stderr (err=True).

ftl_code_expert/cli.py:file_issues

Verdict: PASS
Correctness: VALID
Spec Compliance: N/A
Test Coverage: UNTESTED
Integration: WIRED

Integrating _ensure_labels into file_issues right before issue creation is safe, logically placed, and guarded with not dry_run and remaining. It verifies platform and repo credentials prior to calling label check/creation commands, preventing redundant executions or unhandled crashes.

Self-Review

Limitations: - Could not list the directory structure or locate unit test files because shell command execution was restricted by security policy.

  • Test coverage is marked as UNTESTED as there is no evidence of existing test files covering file_issues or _ensure_labels in the repository metadata or changes.

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.

file-issues: auto-create missing labels instead of failing

1 participant