Skip to content

Consolidate target parsing into positional parsers #1564

Open

Description

@sentry-junior

parseOrgTarget and parseOrgProjectTarget (packages/cli/src/lib/completion-target.ts, added in #1557) are identity parsers. They only mark a positional's completion kind. Each command still parses and validates the raw string itself inside func, using parseOrgProjectArg, parseSlashSeparatedArg, parseIssueArg, and similar helpers from src/lib/arg-parsing.ts.

  • Commands that share a target syntax repeat the same parse call, and the positional definition and its parsing live in different places.
  • Some flows depend on the raw string reaching func today: buildListCommand rewrites the first positional to catch plural-alias subcommand typos, maybeRecoverWithHelp treats a literal help argument as --help, and some commands auto-recover from the wrong entity type. Parse failures currently surface as CliError subclasses with specific exit codes. Errors thrown from a Stricli parser go through Stricli's argument-error handling instead.

Raised by BYK in review of #1557.

via byk.

--

View Junior Session in Sentry

Activity

  1. linear-code commented on Oct 20, 2026

    @linear-code
  2. sentry-junior commented on Oct 23, 2026

    @sentry-junior
    ContributorAuthor

    Fixed by #1594 (merged 2026-10-23), which adds the target positional parser and moves trace list, replay list, feedback list, project view and project delete onto it. The PR used Refs #1564, so it didn't close this automatically. Closing per @BYK.

  3. sentry-junior commented on Oct 23, 2026

    @sentry-junior
    ContributorAuthor

    Reopening: #1594 landed the lazy parsed/resolved positional mechanism and migrated trace list, replay list, feedback list, project view and project delete, but the migration and some hardening are still open.

    Open PRs that this issue depends on

    New PRs

    Next, in priority order

    1. Harden destructive checks: right now the guard only runs when a destructive command reads .resolved. A command that reads .parsed and then mutates skips it. buildListCommand's re-wrap also drops the destructive mark (no destructive list commands exist today, so this can't trigger yet). The require-target-resolution lint rule is easy to get around.
    2. LazyPositional: memoize parse failures (a failing .parsed re-parses on every read) and avoid unhandled rejections when .resolved is read but never awaited.
    3. Migrate any remaining unblocked positionals. log list, replay view and replay download are variadic or depend on the number of arguments, so they stay in func.

    I'll link the new PRs here as I open them.

  4. sentry-junior commented on Oct 25, 2026

    @sentry-junior
    ContributorAuthor

    Status update:

    Still to do: migrate LIST_TARGET_POSITIONAL users, including agent-conversation list, once #1575 lands, and look at the issue and dashboard targets after #1572. log list, replay view and replay download keep parsing in func.

  5. sentry-junior commented on Oct 28, 2026

    @sentry-junior
    ContributorAuthor

    Status update: #1572 and #1575 have both merged, so nothing blocks this issue anymore.

    New PR

    Left over, and needs a design decision

    • issue list, dsn list and alert issues list (LIST_TARGET_POSITIONAL), project list (NAMED_LIST_TARGET_POSITIONAL), and every buildOrgListCommand list (team, repo, monitor, integration, …) go through dispatchOrgScopedList. It resolves each target mode in a different way, and some modes resolve to several projects (DSN detection, monorepos). That means orgOptionalTarget or projectBoundTarget can't stand in for these. One option is a "list target" bound positional: it parses [<org>/][<project>|<glob>] purely in the scanner, and .resolved applies the pasted URL's server and returns { parsed, filter } for dispatch. parseListTarget would need a pure variant for that, since it currently applies the URL context while it parses.
    • Issue and dashboard targets: feat(cli): Complete issues, dashboards, --query terms, and --period values #1572 only added completion (parseIssueTarget and parseDashboardTarget are still identity parsers). Most of these positionals are [<org>/[<project>/]]<id>, and what each part means depends on how many arguments were given, the same as trace view. Under the current rule they keep parsing in func.
    • log list, replay view and replay download stay out of scope, because they're variadic.
  6. sentry-junior commented on Oct 29, 2026

    @sentry-junior
    ContributorAuthor

    Update on the approved directions:

    • List targets (issue list, dsn list, alert issues list, project list, release list and the dispatch-based org lists): ref(cli): Parse list command targets in their positional #1711 adds a list-target positional. It parses with no side effects up front and applies a pasted URL's server at resolve time.
    • Arity-dependent and variadic targets: ref(cli): Parse arity-dependent arguments in the scanner #1714 adds the parser type for [<org>/[<project>/]]<id>. A small @stricli/core patch gives array positionals a combine hook that sees all the arguments at once, so these targets now fail in the scanner with exit 252. boundArguments wraps it with the same pure-parse/bound-resolve contract as boundPositional. log list, replay view and replay download are migrated.
    • Issue and dashboard IDs, trace view/logs, span list/view and log view fit the same primitive. I've left them for follow-ups so each PR stays reviewable. parseTraceTargetInput and parseDualModeInput already exist for the trace ones.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions