Dashboard › cli › Distillation
1bd6605e-b7a9-4116-b646-ec8bc0d6bff9["lore_tm_v1_TGs_zExgy2aIHfXlCkXLrYxQBfM3Vm64KcTRVg7btdw","lore_tm_v1_rj5_HI9n3FyJGq_Qfpi1HDV47jaaIVHaVZ2LRoG8Ic8","lore_tm_v1_CNAGZYOuakxngHMdkVBWFtw_RhUei0TDda6L36-K7fw","lore_tm_v1__MDRXQF8QVlenlCf071skr8dxS8P8A-ydh41L6396yM","lore_tm_v1_Fh6vo6nNdYuRP7yrnEvDZ-28qpalemJyVVqy65U-Rb8","lore_tm_v1_Ti6IffBVLc6-HA38pUfso26CzrzwLke_fguQj_ng8M8","lore_tm_v1_B4vXHhTlL3Zlj_Y3-qymHtN1UiCFgRJ81ql5yhdESqA"]
src/risk_pr_agent/cli.py defines the risk-pr CLI (argparse.ArgumentParser(prog="risk-pr", description="Offline PR risk dataset tooling")) with 10 required subcommands: 1. backfill, 2. git-backfill, 3. features, 4. score, 5. build, 6. survey, 7. combine, 8. train, 9. apply-model, 10. score-pr.src/risk_pr_agent/cli.py defines DEFAULT_OUTCOMES = ["strong_outcome", "medium_outcome"] and three RISK_LABELS: low → name risk: low, color 0E8A16, description PR risk score: low; medium → risk: medium, FBCA04, PR risk score: medium; high → risk: high, D93F0B, PR risk score: high.backfill accepts repeatable required --repo, --out default data/raw, --since, --until, --months default 6, --max-prs, --skip-reviews, --resume, --refresh, and --sleep default 0.0; backfill_repo() writes prs.in-progress.jsonl, atomically replaces it with prs.jsonl, writes manifest.json, deduplicates PR numbers, and reports exact fetched/reused counts.git-backfill accepts repeatable required --repo and --git-repo, --git-ref default origin/master, --out default data/raw-git, --since, --until, --months default 24, and --max-prs; git_backfill_repo() uses build_git_pr_rows() and writes prs.jsonl plus a schema-version-1 manifest with data_source: "local_git".features takes required --input and --out default data/processed; build_features_file() loads raw rows, calls build_feature_rows(), and writes features.jsonl, features.csv, and manifest.json.score takes required --input, --out default data/processed, repeatable --outcome, and --include-unmerged; score_feature_file() writes scored.jsonl and, for each outcome, evaluation{suffix}.json plus evaluation{suffix}.md, evaluating merged PRs only unless --include-unmerged is set.build combines GitHub backfill, optional local-git revert enrichment, feature extraction, scoring, and evaluation. Its defaults include --out data, --months 12, --git-ref origin/master; optional --git-repo owner/name=/path enrichment records git_revert_target_prs and git_revert_commits in the processed manifest.survey accepts required --repo, date bounds, --months default 12, optional --git-repo, and --git-ref default origin/master; cmd_survey() queries total, open, and merged PR counts and computes closed_unmerged_prs = max(total - open_count - merged_count, 0), optionally adding survey_git_history() output.combine accepts repeatable required --input, --out default data/processed/combined, --dedupe, repeatable --outcome, and --include-unmerged; deduplication keys on (repo, PR number), later inputs replace earlier rows, and output is sorted descending by created_at, repo, and PR number before writing combined features, CSV, manifest, and score evaluations.train defaults are outcome medium_outcome, chronological --train-fraction 0.8, --validation-fraction 0.1, --epochs 800, --learning-rate 0.05, --l2 0.01, --maturity-days 0, balanced classes unless --no-class-balance, and feature_set=DEFAULT_FEATURE_SET. Accepted feature-set values are static_no_process, selected_static_v1, at_open, in_review_final, in_review, and legacy.train_feature_file() canonicalizes the feature-set name and writes, per outcome, model_{artifact_stem}.json, model_evaluation_{artifact_stem}.json, model_{artifact_stem}.md, and modeled_{artifact_stem}.jsonl; the evaluation artifact contains train, validation, test, and all-row evaluations.apply-model requires --input and --model, with --out default data/processed; apply_model_file() writes modeled_{stem}.jsonl and model_application_{stem}.json, preserving model metadata fields outcome_name, feature_set, and percentile_mode.score-pr accepts --repo defaulting to GITHUB_REPOSITORY, required integer --pr, repeatable required --history, required --model, optional --out, --summary-file, --skip-reviews, --label-pr, --label-prefix default risk: , --git-repo, and --git-ref default origin/master.score_pull_request() freshly fetches the target PR, marks it with data_source = "github_api", removes any historical copy of that PR, deduplicates raw rows, and raises ValueError("score-pr requires at least one historical PR row plus the current PR") when no other history remains. It optionally enriches with git reverts, builds features, applies the saved logistic model, and returns prediction data plus a Markdown summary.cmd_score_pr() optionally applies a GitHub risk label; a GitHubError is stored as github_label_error, printed as warning: failed to apply PR risk label: {exc}, and re-raised after output and summary generation.apply_pr_risk_label() chooses final_risk_label, then logistic_risk_label, then rule risk_label; unknown values raise ValueError(f"cannot apply unknown risk label {label!r}"). It upserts the selected label, removes other current labels in the configured low/medium/high risk-label set, then adds the selected label, ensuring exactly one configured risk label remains.write_github_outputs() appends these exact keys to GITHUB_OUTPUT: risk_label, final_risk_label, final_risk_policy, logistic_risk_label, rule_risk_label, logistic_probability, logistic_percentile_repo, rule_percentile_repo, and github_label.pr_risk_markdown_summary() produces # PR Risk Summary with PR link, title, final/logistic/rule labels, final policy, logistic probability, logistic/rule/churn repo percentiles, historical-row count, up to the first 8 rule signal names, and deterministic features: changed_lines, file_count, directory_count, max_file_churn_ratio, author_touched_file_ratio, max_file_prior_bad_outcomes, tests_changed, and code_changed_without_test_signal. It ends with > Experimental advisory signal only. This workflow should not block merges yet.src/risk_pr_agent/cli.py: parse_since() parses YYYY-MM-DD at UTC midnight or subtracts months * 30 days from current UTC time; parse_until() makes the supplied date inclusive by adding 1 day and subtracting 1 microsecond; created_search_query() emits either created:{since}..{until} or created:>={since}.parse_git_repo_specs() accepts explicit owner/name=path mappings; an unmapped path is allowed only when exactly one --repo is supplied, otherwise it raises ValueError("--git-repo without owner/name=path is only allowed with one --repo").getsentry/pr-risk-action as a GitHub Action that scores PRs low, medium, or high using the deterministic/logistic PR-risk MVP; consumer repositories do not need to vendor the scorer because the Action runtime is held in this repository.pull_request_target event with types [opened, synchronize, reopened, ready_for_review], permissions contents: read, pull-requests: write, and issues: write, an ubuntu-latest job gated by github.event.pull_request.draft == false, and uses: getsentry/pr-risk-action@main with inputs repo: ${{ github.repository }} and pr-number: ${{ github.event.pull_request.number }}.GITHUB_STEP_SUMMARY, writes risk-pr-result.json by default, exposes outputs including risk-label, logistic-risk-label, and rule-risk-label, and keeps exactly one of risk: low, risk: medium, or risk: high synchronized. Labels are created on demand and require caller permission issues: write because PR labels use GitHub’s Issues API.owner/repo to profiles/owner__repo by default. Each profile contains pr-history.jsonl.gz for public historical PR rows used in repo-relative calibration and model.json for selected logistic model weights; unsupported repositories may add a bundled profile or pass explicit history and model paths.pull_request_target, and the signal remains experimental/advisory rather than merge-blocking.--json never triggers the sixel probe or terminal I/O for a branded banner that would be discarded; in packages/cli/src/commands/help.ts, the full command tree is yielded to CommandOutput(introspectAllCommands()), while formatHelpHuman renders the branded banner only for human output.packages/cli/src/commands/help.ts, nonempty command paths are resolved with introspectCommand(commandPath), successful results are wrapped in new CommandOutput(result), and errors are thrown as new OutputError(result) for nonzero exit through the output system./home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/help.ts is 63 lines. helpCommand uses buildCommand(), has auth: false, declares no flags, accepts an array positional command, and documents four forms: sentry help/no args for branded overview, sentry help <command> for detailed help, sentry help --json for the full structured command tree, and sentry help --json <command> for command/group metadata./home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/formatters/output.ts defines unwrapPipe(schema), which resolves a Valibot pipe(...) to its last step with kind === "schema"; thus pipe(unknown(), transform(Number), number()) resolves to number() rather than unknown().VALIBOT_TYPE_MAP maps string→string, number→number, boolean→boolean, object→object, loose_object→object, array→array, record→object, null→null, unknown→unknown, any→any, picklist→string, enum→string, and literal→string.resolveValibotUnion() deduplicates union member type names in encounter order, joins them with " | ", and propagates optional: true if any member is optional. valibotTypeToString() unwraps optional, nullable, and nullish recursively; nullable/nullish append | null once, nullish is optional, and unknown schema types resolve to { type: "unknown", optional: false }.extractSchemaFields(schema) supports Valibot object and loose_object nodes, returning top-level field metadata {name, type, description, optional}; non-object schemas or objects without entries return []. findDescription() walks nested .wrapped schemas until getDescription() returns a value.formatSchemaForHelp(fields) returns an empty string for no fields; otherwise it emits the heading JSON fields (use --json --fields to select): and one line per field formatted as {name} ({type}{, optional}){ — description}. formatFooter(text) returns \n${plainSafeMuted(text)}\n, and writeFooter(stdout, text) writes that formatted footer./home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/formatters/output.ts, CommandReturn currently supports optional hint?: string; hints apply to the entire command invocation, are shown in human mode, suppressed in JSON mode, and are passed to renderer finalize() when available or written via writeFooter() otherwise.RenderContext contains exact fields json: boolean, optional fields?: string[], and optional clearPrefix?: string.applyJsonExclude(data, excludeKeys) leaves data unchanged when exclusions are absent or data is primitive/null; for objects it shallow-copies and deletes configured keys, and for arrays it independently shallow-copies object elements and deletes those keys while preserving primitive elements.emitJsonObject(stdout, obj) uses stdout.captureObject(obj) for zero-copy library-mode capture when available; otherwise it writes ${formatJson(obj)}\n.renderCommandOutput(stdout, data, config, renderer, ctx) sends Uint8Array directly to stdout.write(data) without text formatting, JSON pretty-printing, newline insertion, or coercion, preserving attachment downloads byte-for-byte.renderCommandOutput() first uses config.jsonTransform(data, ctx.fields) when configured and emits nothing if it returns undefined; otherwise it applies config.jsonExclude, optionally filters with filterFields() when ctx.fields is nonempty, and emits the final object. In human mode it calls renderer.render(data) and, for nonempty text, writes ${ctx.clearPrefix ?? ""}${text}\n.