Dashboard › cli › Distillation
570e314a-6c02-4092-a5ee-a53fad15bc01["lore_tm_v1_NTICXTkpdM7CxpwPN9242Cg62guDE4b1b03ChbTsBGw"]
Date: Sep 9, 2026
src/lib/hex-id.ts: validateHexId(value, label) for 32-character hex IDs with automatic UUID-dash stripping, validateSpanId(value) for 16-character hex span IDs with dash stripping, and validateTraceId(value) as a thin wrapper in src/lib/trace-id.ts; all normalize to lowercase and throw ValidationError for invalid input."date" rather than "time" and required sort types such as SpanSortValue to be exported from the API layer and imported by commands.placeholder values such as "org/project/trace-id", not "args".CliError from src/lib/errors.ts and required using EXIT.* constants when constructing errors; numeric exit codes must never be hardcoded outside errors.ts.CliError default exit code 1; HostScopeError 13; ApiError 30; AuthError 10–12 according to 'not_authenticated' | 'expired' | 'invalid'; ConfigError 20; OutputError 60; ContextError 22; ResolutionError 23; ValidationError 21; DeviceFlowError 51; SeerError 40–42 according to 'not_enabled' | 'no_budget' | 'ai_disabled'; TimeoutError 31; UpgradeError 50; and WizardError 61–64 by workflow step.ContextError; supplied values that cannot be found use ResolutionError; malformed user input uses ValidationError.ContextError.command to be a single-line CLI usage example, required alternatives: [] when defaults are irrelevant, and required " and " in plural resource text; the constructor rejects commands containing \n.pnpm run check:errors detects multiline ContextError commands and CliError instances with ad-hoc "Try:" strings.fuzzyMatch() from src/lib/fuzzy.ts, showing at most 5 similar candidates; reference implementation is resolveDashboardId() in src/commands/dashboard/resolve.ts.catch blocks in src/: each catch must rethrow, log via log.debug() or log.warn(), or return a fallback while logging suppression via log.debug(); command files should use logger.withTag("command-name").no-silent-catch Biome plugin at lint-rules/no-silent-catch.grit, registered in biome.jsonc, flags empty, comment-only, and return-only statement or .catch() forms; grandfathered catches use inline // biome-ignore lint/plugin: <reason>, and fixing one requires removing its suppression because --error-on-warnings makes orphaned suppressions fail as suppressions/unused.looksLikeIssueShortId(), SPAN_ID_RE, HEX_ID_RE, or non-hex checks; 2. resolve to the correct type; 3. warn through log.warn(); 4. return a hint toward the correct command. Ambiguous or impossible recovery must retain the error and add entity-aware suggestions.getAuthToken(), isAuthenticated(), and setAuthToken(token, expiresIn).src/lib/*.ts utility; if an existing module covers at least 80% of the need, it must be extended rather than creating a new file. Every new src/lib/**/*.ts file must begin with module-level JSDoc describing its purpose.src/lib/formatters/time-utils.ts; hex-ID handling in src/lib/hex-id.ts; table/Markdown output in src/lib/formatters/; pagination in src/lib/db/pagination.ts and src/lib/list-command.ts; errors in src/lib/errors.ts; and search-query construction in src/lib/search-query.ts and src/lib/arg-parsing.ts.src/lib/errors.ts..js extensions for local ESM imports, external-package imports before local imports, and the type keyword for type-only imports.src/lib/list-command.ts provides buildOrgListCommand, LIST_TARGET_POSITIONAL, LIST_JSON_FLAG, LIST_CURSOR_FLAG, and buildListLimitFlag for simple lists such as team list and repo list; (2) src/lib/org-list.ts provides dispatchOrgScopedList, OrgListConfig, and handlers for auto-detect, explicit, org-all, and project-search for complex commands such as project list and issue list; (3) standalone commands such as span list and trace list wire pagination directly in func().ctx.parsed; call resolveCursor() inside the org-all override; use "Project" as the ContextError resource for handleProjectSearch; and always set orgSlugMatchBehavior to "redirect" or "error" according to whether bare-org listing is appropriate.queryEvents uses project:<slug> in the query string through buildProjectQuery(); listReplays uses the projectSlugs parameter; and listIssuesPaginated uses either the project parameter or query string depending on mode.explore datasets to implement dataset-specific sort, query, fetch, field validation, and filtering behavior centrally in resolveDatasetConfig, rather than scattering if (dataset === ...) checks through func.null semantics, and defaults.*.property.test.ts in test/lib/, *.model-based.test.ts in test/lib/db/, unit *.test.ts files under test/ mirroring src/, and E2E *.test.ts files under test/e2e/.useTestConfigDir() from test/helpers.ts; it creates a unique temporary directory in beforeEach, points SENTRY_CONFIG_DIR to it, restores rather than deletes the environment variable in afterEach, closes the database, and cleans temporary files.delete process.env.SENTRY_CONFIG_DIR, module-scope capture via const baseDir = process.env[CONFIG_DIR_ENV_VAR]!, and manual beforeEach/afterEach hooks that set or delete SENTRY_CONFIG_DIR; the environment variable must always be restored, never deleted, in afterEach.