Skip to content

fix(issue-list): add --no-profile flag to bypass active profile defaults - #119

Merged
bougyman merged 3 commits into
mainfrom
CRY-45-no-profile-flag
Aug 16, 2026
Merged

fix(issue-list): add --no-profile flag to bypass active profile defaults#119
bougyman merged 3 commits into
mainfrom
CRY-45-no-profile-flag

Conversation

@bougyman

Copy link
Copy Markdown
Member

Summary

  • Adds a --no-profile boolean flag to issue list (follows the --no-mine naming convention)
  • When set, Commands.issue_list/1 skips Profiles.default_team() and Profiles.default_project() fallbacks entirely — the command runs as if no profile is active
  • Explicit --team / --project still win even when --no-profile is set

Test plan

  • profile_defaults_test.exs: two new unit tests — --no-profile omits team/project filters; --no-profile + explicit --team still applies the explicit team
  • issue_commands_test.exs: smoke test via full CLI dispatch path confirming no project query is issued and no team/project filter appears in the GQL variables
  • All 238 tests pass (3 pre-existing unrelated failures in LinearCli.GitTest)

Closes: https://linear.app/cryptokairos/issue/CRY-45

🤖 Generated with Claude Code

Adds a `--no-profile` boolean flag to `issue list`. When set, the
`team_key` and `project_id` fields no longer fall back to
`Profiles.default_team()` / `Profiles.default_project()`, so the
command behaves as if no profile is active. Explicit `--team` /
`--project` still take effect even when `--no-profile` is set.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 16, 2026 13:41

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@bougyman

Copy link
Copy Markdown
Member Author

Code Review

Reviewer: Autonomous code review agent (CRY-45, Run 1)
Branch: CRY-45-no-profile-flag (commit aa4657f)

Summary

The change adds a --no-profile flag to lc issue list that bypasses the active profile's team/project defaults. The core implementation is correct and clean — one commit, four files touched, well-scoped.

Issues Found

Minor: Duplicate test describe blocks in profile_defaults_test.exs

Two describe blocks test essentially the same thing:

  1. Lines 219–285 — two --no-profile tests inside "Commands.issue_list/1 falls back to the active profile"
  2. Lines 321–390"Commands.issue_list/1 with --no-profile bypasses active profile defaults" with near-identical tests

The second block's first test adds one extra assertion (verifying the projects(first: $first query is never sent) and an output =~ "CRY-1" check. The second block's second test is a textual duplicate of the first block's explicit---team test.

Suggestion: Merge the two blocks. Keep the stronger assertions from the second block (the project-query guard) in the first block's tests, and delete the second describe block entirely. This halves the stub boilerplate without losing coverage.

Note: expand_issue_id/1 still uses profile defaults with --no-profile

When --no-profile is set and bare numeric IDs are passed (e.g., lc issue list --no-profile 42), expand_issue_id/1 (commands.ex:237issue_helpers.ex:403–412) still calls Profiles.default_team() internally to resolve 42CRY-42. The no_profile flag is not threaded through.

The investigation notes acknowledged this and called it correct behavior ("bypassing the profile should bypass all its effects"), but the code doesn't actually implement that — expand_issue_id still uses the profile team. This is arguably out of scope for this ticket (bare IDs + --no-profile is an unusual combo), but worth documenting as a known limitation or future follow-up.

What Looks Good

  • Backward compatibility: Map.get(flags, :no_profile, false) safely defaults to false for existing callers whose flag maps don't include it — existing tests at line 169 prove this works without the key present.
  • Naming convention: --no-profile follows the established --no-mine pattern.
  • Flag access pattern: Uses Map.get with default, consistent with how :all is accessed on line 242.
  • Precedence logic: options.team || (unless no_profile, do: ...) correctly ensures explicit --team/--project always wins, and unless returns nil when the flag is set — no filter applied.
  • Smoke test: The issue_commands_test.exs test exercises the full CLI dispatch path including Optimus parsing, confirming the flag is wired end-to-end.
  • Project query guard: The raise in the stub when projects( is queried unnecessarily is a smart assertion — it catches the case where resolve_project_id is called with a non-nil value despite --no-profile.

Quality Suite

  • Compilation: Clean (mix compile --force --warnings-as-errors)
  • Tests: 237/240 tests pass, 1/1 doctest passes. 4 failures are all in GitTest — pre-existing and unrelated.

Overall Assessment

Approve with minor suggestion. The implementation is correct, well-tested, and follows project conventions. The duplicate test block is the only actionable item — nice to clean up but not blocking. The expand_issue_id note is informational for a possible future ticket.

@bougyman bougyman left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

Branch: CRY-45-no-profile-flag
Commit: aa4657f fix(issue-list): add --no-profile flag to bypass active profile defaults
Issue: CRY-45


Critical Issues

None.

Major Issues

1. Formatting failure — commands.ex fails mix format --check-formatted (will break CI)

app/lib/linear_cli/cli/commands.ex:230,233 — The unless expressions have unnecessary parentheses that the Elixir formatter wants removed:

-    team_key = options.team || (unless no_profile, do: Profiles.default_team())
+    team_key = options.team || unless no_profile, do: Profiles.default_team()

-      options.project || (unless no_profile, do: Profiles.default_project())
+      options.project || unless no_profile, do: Profiles.default_project()

Fix: run mix format on the file.

2. Duplicate test blocks in profile_defaults_test.exs

Two describe blocks test the exact same --no-profile scenarios:

  • Lines 219–285: inside "Commands.issue_list/1 falls back to the active profile" — tests bypass-defaults and bypass+explicit-team
  • Lines 321–390: standalone "Commands.issue_list/1 with --no-profile bypasses active profile defaults" — tests the same two scenarios again

The only meaningful difference is the standalone block's first test also guards against project queries being made (the raise on projects(first: $first). These should be consolidated into one set of tests. Suggest keeping the standalone describe block (which has the stronger assertions) and removing the duplicates from the "falls back" block.

Minor Issues

3. Missing test: --no-profile combined with explicit --project

Tests cover --no-profile alone and --no-profile + explicit --team, but not --no-profile + explicit --project. For symmetry and to confirm project resolution still works when the user explicitly passes --project while bypassing profile defaults, this case should be tested.

4. expand_issue_id not affected by --no-profile

IssueHelpers.expand_issue_id/1 (issue_helpers.ex:403) still calls Profiles.default_team() for bare numeric IDs regardless of the --no-profile flag. Example: lc issue list --no-profile 42 would still expand 42CRY-42 using the profile's team. The investigation acknowledged this as acceptable behavior (the flag is about filtering, not ID expansion), so this is a documentation/awareness note, not a change request.

What Looks Good

  • Core logic is minimal and clean — the 4-line change in commands.ex does exactly what the ticket asks
  • Map.get(flags, :no_profile, false) correctly handles backward compatibility with existing test fixtures that don't include the new flag (matching the Map.get(flags, :all, false) pattern)
  • Optimus spec placement and help text follow existing conventions (--no-mine pattern)
  • Smoke test via LinearCli.CLI.main/1 dispatch path provides good integration coverage
  • Test stubs properly verify no project queries are fired when --no-profile omits both defaults

Overall Assessment

Request changes. The formatting failure (#1) must be fixed — it will fail CI. The duplicate tests (#2) should be consolidated. The missing --project test case (#3) is nice-to-have. All are straightforward fixes.

- Remove unnecessary parentheses from `unless` expressions in
  `Commands.issue_list/1` to pass `mix format --check-formatted`
- Consolidate duplicate `--no-profile` describe block in
  `profile_defaults_test.exs` into the existing "falls back to the
  active profile" describe; strengthen the bypass test with a project-
  query guard and output assertion
- Add missing test: `--no-profile` with explicit `--project` still
  applies the explicit project filter while ignoring profile defaults
@bougyman

Copy link
Copy Markdown
Member Author

Rework Summary (CRY-45, Run 2)

Addressed all three review comments from the code review stage.

What was fixed

1. Formatting failure (commands.ex:230,233)
Ran mix format. The unnecessary parentheses around the unless expressions have been removed. mix format --check-formatted now passes cleanly.

2. Duplicate test blocks (profile_defaults_test.exs)
Deleted the standalone describe "Commands.issue_list/1 with --no-profile bypasses active profile defaults" block (2 tests). The equivalent tests now live in the "falls back to the active profile" describe block, with the stronger assertions from the removed block merged in:

  • The bypass test now guards against spurious projects( queries via a stub raise
  • The bypass test now asserts output =~ "CRY-1" (rendered output check)

3. Missing test (profile_defaults_test.exs)
Added "--no-profile with an explicit --project still applies the explicit project". It verifies that passing --project "Platform Cleanup" with --no-profile still resolves and applies the project filter, while the profile's team default is correctly ignored.

Quality

  • mix format --check-formatted: passes
  • mix compile --warnings-as-errors: clean
  • mix test: 236/240 pass (4 LinearCli.GitTest failures are pre-existing on main and unrelated to this change)

@bougyman

Copy link
Copy Markdown
Member Author

Code Review (Run 2)

Branch: CRY-45-no-profile-flag
Commits reviewed: 74bc181 (initial) → ec2b953 (rework)
Issue: CRY-45
Reviewer: Autonomous code review agent


Prior Review Issues — Status

1. Formatting failure (commands.ex) — ✅ Fixed
Parentheses removed from the unless expressions at lines 237 and 240. mix format --check-formatted passes cleanly.

2. Duplicate test blocks (profile_defaults_test.exs) — ✅ Fixed
The standalone describe "Commands.issue_list/1 with --no-profile bypasses active profile defaults" block has been removed. All three --no-profile tests now live inside the "falls back to the active profile" describe block. The stronger assertions (project-query guard via raise, output rendering check) from the removed block have been merged into the retained tests.

3. Missing --no-profile + explicit --project test — ✅ Fixed
New test at profile_defaults_test.exs:290: "--no-profile with an explicit --project still applies the explicit project". It verifies that passing --project "Platform Cleanup" with --no-profile resolves and applies the project filter while the profile's team default is correctly ignored.

New Issues Introduced by Rework

None found. The rework commit (ec2b953) is a clean fix-only change — no logic modifications, no new code paths, no regressions.

Quality Suite

Check Result
mix format --check-formatted ✅ Pass
mix compile --warnings-as-errors ✅ Pass
mix test ✅ 239/243 pass (4 GitTest failures are pre-existing on main)

Implementation Summary

The final implementation is clean and well-structured:

  • commands.ex:236-240Map.get(flags, :no_profile, false) + unless short-circuits the profile fallbacks. Explicit --team/--project always win via the || precedence.
  • cli.ex:519-522 — Optimus spec follows the --no-mine naming convention.
  • Test coverage — 4 tests cover the --no-profile flag: bypass-only, bypass+explicit-team, bypass+explicit-project, and a full CLI dispatch smoke test.

Overall Assessment

Approve. All three prior review issues have been addressed cleanly. No new issues found. The implementation is correct, follows project conventions, and has thorough test coverage.

@bougyman

Copy link
Copy Markdown
Member Author

Workpad

Code Review (Run 2, 2026-08-16)

Status: Approved.

Prior review issues (all 3 addressed):

  1. Formatting failure in commands.ex — fixed, mix format --check-formatted passes
  2. Duplicate test blocks in profile_defaults_test.exs — consolidated into one describe block
  3. Missing --no-profile + explicit --project test — added

New issues found: None.

Quality: 239/243 tests pass (4 pre-existing GitTest failures on main). Compilation and formatting clean.

Decision: Approve — ready to merge.

@bougyman

Copy link
Copy Markdown
Member Author

Code Review (Run 2)

Reviewer: Autonomous code review agent (CRY-45, Run 2)
Branch: CRY-45-no-profile-flag (commits 74bc181..ec2b953)
Issue: CRY-45


Prior Review Issues — Verification

All 3 issues from the Run 1 review have been properly addressed:

1. Formatting failure (commands.ex:230,233)FIXED
Unnecessary parentheses around unless expressions removed. mix format --check-formatted passes clean.

2. Duplicate test blocks (profile_defaults_test.exs)FIXED
The standalone describe "Commands.issue_list/1 with --no-profile bypasses active profile defaults" block has been removed. The --no-profile tests now live exclusively inside the "falls back to the active profile" describe block, with the stronger assertions (project-query guard, rendered output check) merged in.

3. Missing --no-profile + explicit --project testFIXED
New test at profile_defaults_test.exs:290: "--no-profile with an explicit --project still applies the explicit project". Correctly verifies project resolution still works while the profile's team default is ignored.

New Issues Found

None.

Quality Suite

  • mix format --check-formatted: passes
  • mix compile --warnings-as-errors: clean
  • mix test: 239/243 pass (4 LinearCli.GitTest failures are pre-existing on main, unrelated)
  • All 44 tests in the 3 changed test files pass

Notes

  • Smoke test coverage: The issue_commands_test.exs smoke test (line 285) exercises the --no-profile flag through full Optimus parsing and CLI dispatch, but doesn't set up an active profile first — so --no-profile is a no-op in that test. This is acceptable since the unit tests in profile_defaults_test.exs thoroughly cover the actual bypass behavior with an active profile. The smoke test's value is confirming the flag wires through Optimus correctly.

  • expand_issue_id limitation: Still noted as an awareness item (not a change request). When --no-profile is set and bare numeric IDs are passed, expand_issue_id/1 still consults Profiles.default_team(). Acknowledged in Run 1 as acceptable — the flag is about filtering, not ID expansion.

Overall Assessment

Approve. All 3 prior review issues have been cleanly resolved. The implementation is correct, well-tested (3 unit tests + 1 smoke test), follows project conventions (--no-mine naming pattern, Map.get with default), and the core logic is minimal — 4 lines of production code doing exactly what the ticket asks.

@bougyman
bougyman merged commit f19409c into main Aug 16, 2026
2 checks passed
@bougyman
bougyman deleted the CRY-45-no-profile-flag branch August 16, 2026 14:15
bougyman pushed a commit that referenced this pull request Aug 16, 2026
🤖 I have created a release *beep* *boop*
---


##
[1.9.1](v1.9.0...v1.9.1)
(2026-08-16)


### Bug Fixes

* **issue-list:** add --no-profile flag to bypass active profile
defaults ([#119](#119))
([f19409c](f19409c))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
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.

2 participants