dependfix 0.2.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,255 +1,6 @@
1
- import { AlertSourceKind, AppError, FixAction, NormalizedSecurityAlert, RunResult, SeverityThreshold } from "@dependfix/core";
2
- import { Octokit } from "@octokit/rest";
1
+ import { CliConfigOverrides, RuntimeConfig, RuntimeMode, resolveRuntimeConfig } from "@dependfix/engine";
3
2
  export * from "@dependfix/core";
4
- //#region src/config/index.d.ts
5
- declare const RUNTIME_MODES: readonly ["report-only", "fix", "fix-and-pr", "cleanup-branches"];
6
- declare const SEVERITY_THRESHOLDS: readonly ["critical", "high", "medium", "all"];
7
- declare const ALERT_SOURCES: readonly AlertSourceKind[];
8
- /**
9
- * 环境变量统一前缀(v0.2 起替代旧项目名遗留的 `AUTO_FIX_GITHUB_SECURITY_`)。
10
- * 所有环境变量读取必须经由 {@link readEnv},禁止散落硬编码,防止改名漏网。
11
- */
12
- declare const ENV_PREFIX = "DEPENDFIX_";
13
- /**
14
- * 从统一前缀读取环境变量。
15
- * @param env 进程环境
16
- * @param name 变量名(不含前缀),如 `'MODE'` → `DEPENDFIX_MODE`
17
- */
18
- declare function readEnv(env: NodeJS.ProcessEnv, name: string): string | undefined;
19
- type RuntimeMode = typeof RUNTIME_MODES[number];
20
- interface RuntimeConfig {
21
- mode: RuntimeMode;
22
- severityThreshold: SeverityThreshold;
23
- repositories: string[];
24
- /**
25
- * owner / org 列表(`--owner` / `DEPENDFIX_OWNER`)。
26
- * 提供时按 owner 自动发现仓库:与显式 `repositories` 合并去重
27
- * (显式优先,发现仅补充未出现项)。适用于 report-only / fix / fix-and-pr。
28
- */
29
- owner?: string[];
30
- /**
31
- * 发现结果的 topic 白名单(`--repo-topics` / `DEPENDFIX_REPO_TOPICS`,AND 语义)。
32
- * 仓库必须包含全部指定 topics 才保留。仅影响发现结果,不影响显式列表。
33
- */
34
- repoTopics?: string[];
35
- /**
36
- * 仓库白名单 glob(`--repo-include`,如 `owner/*`、`owner/pkg-*`)。
37
- * 仅作用于发现结果;显式 repositories 列表不受 include 影响(显式优先)。
38
- */
39
- repoInclude?: string[];
40
- /**
41
- * 仓库黑名单 glob(`--repo-exclude`)。
42
- * 显式列表与发现结果均受 exclude 约束;与 include 冲突时 exclude 胜出。
43
- */
44
- repoExclude?: string[];
45
- /**
46
- * 发现结果 topic 黑名单(`--repo-topics-exclude`):
47
- * 排除含任一指定 topic 的仓库。仅作用于发现结果(显式列表无 topics 元数据)。
48
- */
49
- repoTopicsExclude?: string[];
50
- dryRun: boolean;
51
- createPullRequest: boolean;
52
- /** 修复完成后是否在本地当前分支直接提交(不推送、不创建 PR) */
53
- commit: boolean;
54
- /** fix-and-pr 模式下结束后是否列出已合并的 dependfix 分支到报告(不自动删除) */
55
- cleanupBranches: boolean;
56
- /** fix-and-pr 模式下结束后是否自动删除已合并/已关闭的 dependfix 分支(非交互) */
57
- cleanupBranchesAuto: boolean;
58
- githubToken: string;
59
- /**
60
- * 告警数据源。默认 `github-dependabot`(GitHub Dependabot alerts API);
61
- * `pnpm-audit` 为本地无 token 回退(`pnpm audit --json`),repository 解析
62
- * 优先显式 --repo → git remote → `local` 兜底。详见 docs/design/pnpm-audit-fallback.md。
63
- */
64
- alertSource: AlertSourceKind;
65
- /**
66
- * 是否同时拉取 Code Scanning alerts(与 Dependabot 并行源,非回退)。
67
- * 默认关闭(行为与现状一致);开启后 GitHub 源下 Dependabot + Code Scanning
68
- * 并行拉取、互不覆盖。Code Scanning 告警默认不可自动修复(按规则启用)。
69
- * 需要 token 具备 `security-events: read` 权限(GITHUB_TOKEN 默认具备)。
70
- */
71
- codeScanningEnabled: boolean;
72
- /**
73
- * 跨线告警(推荐版本跨大版本)显式授权自动升级(`--allow-major-upgrade`)。
74
- *
75
- * 仅 CLI 参数入口,**刻意不提供 env 通道**(action 结构性禁用:
76
- * action.yml 未暴露 input 且无 `DEPENDFIX_ALLOW_MAJOR_UPGRADE` 可绕过)。
77
- *
78
- * 开启后仅对「根 package.json 直接依赖(workspace 成员独占声明维持人工)
79
- * + lockfile 单版本」的跨线告警自动升级,升级后复核脆弱实例消除、
80
- * 强制完整验证(install + lint + build),失败自动回滚;
81
- * 间接依赖 / 多版本共存跨线告警维持人工处理(skipped + warn)。
82
- */
83
- allowMajorUpgrade: boolean;
84
- /**
85
- * Dependabot alerts 专用 token(可选)。
86
- * 提供时仅用于拉取 Dependabot alerts(GITHUB_TOKEN 无法读取该 API,
87
- * 建议使用最小权限 fine-grained PAT,仅 `Dependabot alerts: read`);
88
- * 缺省时回退使用 githubToken(本地完整 PAT 场景)。
89
- * 背景详见 docs/plan/todo.md「已知缺口 G2」。
90
- */
91
- alertsToken?: string;
92
- maxAlertsPerRepository: number;
93
- /**
94
- * 多仓库并发窗口。默认 1(保守,行为与现状一致);
95
- * >1 时调度器输出警告(GitHub API 限流风险)。
96
- */
97
- maxConcurrency: number;
98
- /**
99
- * GitHub API 限流重试次数。默认 3;
100
- * 对 429 / primary rate limit / secondary rate limit 指数退避重试,0 关闭。
101
- */
102
- maxRetries: number;
103
- /**
104
- * 限流退避单次等待上限毫秒。默认 30000(30s);
105
- * Retry-After / x-ratelimit-reset / 指数退避均受此上限约束。
106
- */
107
- maxBackoffMs: number;
108
- /**
109
- * 用户显式分组(最高优先级,覆盖自动分组)。
110
- * 键为组名,值为组内包列表。缺省时使用自动分组
111
- * (dependabot.yml groups → @types 归并 → scope/前缀启发式)。
112
- * 详见 docs/design/dependency-grouping.md。
113
- */
114
- upgradeGroups?: Record<string, string[]>;
115
- /**
116
- * lockfile 修复用的 pnpm 版本(工具链固定)。
117
- * 提供时 PIN_TOOLCHAIN 策略执行 `corepack pnpm@<version> install --lockfile-only`;
118
- * 缺省从 package.json 的 `packageManager` 字段解析;都不可用时回退裸 pnpm 命令
119
- * (由策略链 REGENERATE/REINSTALL 兜底)。
120
- */
121
- toolchainPnpmVersion?: string;
122
- /**
123
- * AI 研判配置(`--ai` 系列参数 / `DEPENDFIX_AI_*` env)。
124
- * 默认关闭(opt-in);开启后依赖升级验证失败或 major 升级时触发
125
- * breaking change 研判(触发范围由 `trigger` 控制)。
126
- * `apiKey` 为凭据:仅运行时持有,**不进入 RunReportConfig 序列化**。
127
- */
128
- ai?: AiOptions;
129
- }
130
- /**
131
- * AI 研判触发范围。
132
- * - `failure`:仅升级验证失败时触发
133
- * - `major`:仅 major 升级时触发
134
- * - `both`(默认):验证失败 或 major 升级均触发
135
- */
136
- type AiTriggerKind = 'failure' | 'major' | 'both';
137
- interface AiOptions {
138
- /** AI 研判总开关(默认 false,opt-in;dry-run 下不触发) */
139
- enabled: boolean;
140
- /** 提供商:openai-compatible(默认,DeepSeek 等指定 baseUrl)/ anthropic */
141
- provider: 'openai-compatible' | 'anthropic';
142
- /** 模型名(默认 `deepseek-v4-flash`,2026-08-07 决策,models.dev 确认) */
143
- model: string;
144
- /**
145
- * OpenAI 兼容端点基地址。
146
- * 默认 `https://api.deepseek.com`(与默认模型 deepseek-v4-flash 配套;
147
- * DeepSeek 官方 OpenAI 兼容端点,models.dev 确认)。
148
- * 使用 OpenAI 官方模型时显式指定 `--ai-base-url https://api.openai.com/v1`
149
- * 并配合对应 --ai-model。
150
- */
151
- baseUrl: string;
152
- /**
153
- * Anthropic 兼容端点(仅 provider=anthropic 生效;
154
- * 默认 `https://api.anthropic.com/v1/messages`;自托管/网关可显式指定)。
155
- */
156
- apiUrl?: string;
157
- /** AI API Key(凭据:仅运行时,不进报告/日志) */
158
- apiKey?: string;
159
- /** 触发范围(默认 both) */
160
- trigger: AiTriggerKind;
161
- }
162
- interface CliConfigOverrides {
163
- mode?: RuntimeMode;
164
- severityThreshold?: SeverityThreshold;
165
- repositories?: string[];
166
- reposFilePath?: string;
167
- /** owner / org 列表(自动发现仓库,与显式列表合并去重) */
168
- owner?: string[];
169
- /** 发现结果 topic 白名单(AND 语义) */
170
- repoTopics?: string[];
171
- /** 仓库白名单 glob(仅作用于发现结果) */
172
- repoInclude?: string[];
173
- /** 仓库黑名单 glob(显式列表与发现结果均受约束) */
174
- repoExclude?: string[];
175
- /** 发现结果 topic 黑名单(排除含任一指定 topic 的仓库) */
176
- repoTopicsExclude?: string[];
177
- dryRun?: boolean;
178
- createPullRequest?: boolean;
179
- /** 修复完成后是否在本地当前分支直接提交 */
180
- commit?: boolean;
181
- /** fix-and-pr 模式下结束后是否列出已合并的 dependfix 分支到报告 */
182
- cleanupBranches?: boolean;
183
- /** fix-and-pr 模式下结束后是否自动删除已合并/已关闭的 dependfix 分支(非交互) */
184
- cleanupBranchesAuto?: boolean;
185
- githubToken?: string;
186
- /** 告警数据源(`github-dependabot` / `pnpm-audit`) */
187
- alertSource?: AlertSourceKind;
188
- /** 是否同时拉取 Code Scanning alerts(默认 false) */
189
- codeScanningEnabled?: boolean;
190
- /**
191
- * 跨线告警显式授权自动升级(仅 CLI `--allow-major-upgrade` 入口,
192
- * 无 env 通道;Action 不支持)。详见 RuntimeConfig.allowMajorUpgrade。
193
- */
194
- allowMajorUpgrade?: boolean;
195
- /** Dependabot alerts 专用 token(可选,最小权限;缺省回退 githubToken) */
196
- alertsToken?: string;
197
- maxAlertsPerRepository?: number;
198
- /** 多仓库并发窗口(1-16,默认 1 保守) */
199
- maxConcurrency?: number;
200
- /** GitHub API 限流重试次数(0-10,默认 3) */
201
- maxRetries?: number;
202
- /** 限流退避单次等待上限毫秒(100-120000,默认 30000) */
203
- maxBackoffMs?: number;
204
- /** 用户显式分组(覆盖自动分组),格式 `name1:pkg1,pkg2;name2:pkg3` */
205
- upgradeGroups?: Record<string, string[]>;
206
- /** lockfile 修复用的 pnpm 版本(工具链固定;缺省从 packageManager 解析) */
207
- toolchainPnpmVersion?: string;
208
- /** AI 研判总开关(`--ai`) */
209
- aiEnabled?: boolean;
210
- /** AI 提供商(`--ai-provider`:openai-compatible / anthropic) */
211
- aiProvider?: 'openai-compatible' | 'anthropic';
212
- /** AI 模型(`--ai-model`,默认 deepseek-v4-flash) */
213
- aiModel?: string;
214
- /** AI 端点(`--ai-base-url`,OpenAI 兼容) */
215
- aiBaseUrl?: string;
216
- /** AI Anthropic 兼容端点(`--ai-api-url`,仅 provider=anthropic 生效) */
217
- aiApiUrl?: string;
218
- /** AI API Key(`--ai-api-key`;优先 DEPENDFIX_AI_API_KEY env) */
219
- aiApiKey?: string;
220
- /** AI 触发范围(`--ai-trigger`:failure / major / both) */
221
- aiTrigger?: AiTriggerKind;
222
- /** 是否输出详细日志 */
223
- verbose?: boolean;
224
- /** 自定义验证命令(覆盖默认的 `pnpm install --frozen-lockfile` / `pnpm lint` / `pnpm build`) */
225
- commands?: string[];
226
- /**
227
- * 历史查询(仅 CLI `--history`):读取归档索引列出仓库历史运行摘要,
228
- * 不进入运行配置(resolveRuntimeConfig 不消费),由 CLI 层直接处理。
229
- */
230
- history?: string;
231
- }
232
- interface ResolveRuntimeConfigOptions {
233
- env?: NodeJS.ProcessEnv;
234
- cliOverrides?: CliConfigOverrides;
235
- /** 工作目录,用于从 git remote 推断仓库名(默认 `process.cwd()`) */
236
- workDir?: string;
237
- }
238
- declare const DEFAULT_RUNTIME_CONFIG: Omit<RuntimeConfig, 'githubToken' | 'repositories' | 'dryRun' | 'createPullRequest' | 'commit' | 'cleanupBranches' | 'cleanupBranchesAuto'>;
239
- declare function readEnvConfig(env?: NodeJS.ProcessEnv): CliConfigOverrides;
240
- declare function resolveRuntimeConfig(options?: ResolveRuntimeConfigOptions): RuntimeConfig;
241
- /**
242
- * 从 git remote origin 推断 owner/repo。
243
- *
244
- * 支持格式:
245
- * - `https://github.com/owner/repo.git`
246
- * - `git@github.com:owner/repo.git`
247
- * - `ssh://git@github.com/owner/repo.git`
248
- *
249
- * @returns `owner/repo` 或 `null`(非 GitHub / 无 origin)
250
- */
251
- declare function inferRepoFromGitRemote(workDir: string): string | null;
252
- //#endregion
3
+ export * from "@dependfix/engine";
253
4
  //#region src/cli/index.d.ts
254
5
  interface CliInvocation {
255
6
  mode?: RuntimeMode;
@@ -583,842 +334,6 @@ declare const dependfixCommand: import("citty").CommandDef<{
583
334
  }>;
584
335
  declare function runDependfixMain(rawArgs?: string[]): Promise<void>;
585
336
  //#endregion
586
- //#region src/app/index.d.ts
587
- interface DependfixAppOptions {
588
- /** 已解析的运行时配置 */
589
- config: RuntimeConfig;
590
- /** 工作目录(默认 `process.cwd()`) */
591
- workDir?: string;
592
- /** 报告输出目录(默认 `./dependfix-reports`;测试可指向临时目录) */
593
- reportOutputDir?: string;
594
- /** 是否输出详细日志 */
595
- verbose?: boolean;
596
- /** 自定义验证命令(覆盖默认命令链) */
597
- commands?: string[];
598
- }
599
- interface DependfixRunResult {
600
- /** 结构化运行结果(用于报告生成) */
601
- result: RunResult;
602
- /** 进程退出码:0=全部成功, 1=部分失败, 2=全部失败 */
603
- exitCode: number;
604
- }
605
- declare class DependfixApp {
606
- private readonly config;
607
- private readonly workDir;
608
- private readonly reportOutputDir;
609
- private readonly logger;
610
- private readonly verbose;
611
- private readonly customCommands?;
612
- private readonly runId;
613
- private readonly allAlerts;
614
- private readonly allActions;
615
- private readonly allErrors;
616
- private readonly repoResults;
617
- private readonly summary;
618
- /** run 级 AI 用量聚合(--ai 实际调用时填充;报告 aiUsage 段数据源) */
619
- private aiUsageAggregate;
620
- private startedAt;
621
- private finishedAt;
622
- /** 运行前工作区是否已有未提交改动(验证门禁回滚保护:避免销毁用户本地工作) */
623
- private preExistingDirty;
624
- constructor(options: DependfixAppOptions);
625
- /** 供辅助方法使用的状态切片。 */
626
- private get ctx();
627
- /** 执行完整的编排流程,返回结构化结果和退出码。 */
628
- run(): Promise<DependfixRunResult>;
629
- private executeMode;
630
- private executeReportMode;
631
- private processRepoForReport;
632
- private executeFixMode;
633
- private processRepoForFix;
634
- /**
635
- * 修复 → 计算内容指纹 → 查重 →(同指纹跳过 / 异指纹关旧开新)。
636
- *
637
- * 去重语义:
638
- * - 同告警集 → 同修复结果 → 同指纹 → 跳过,不重复提交相同 PR
639
- * - 内容变化 → 先创建新 PR(body 注明 Supersedes),成功后关闭旧 PR;
640
- * 新 PR 创建失败时保留旧 PR,避免出现"无 PR 窗口"
641
- */
642
- private executeFixAndPrMode;
643
- /**
644
- * 清理已合并(或已关闭)的 dependfix 分支。
645
- *
646
- * - 分类:已合并(安全清理)/ 已关闭未合并(supersede 孤儿)/ open(跳过)
647
- * - 删除前必须交互式确认(y/N);非 TTY 环境(CI)默认拒绝
648
- * - 只删 `dependfix/` 前缀分支,绝不触碰 open PR 对应分支
649
- * - dry-run 模式仅列清单并打印 "would delete",不执行删除
650
- */
651
- private executeCleanupBranchesMode;
652
- /**
653
- * 多仓库并发执行管线。
654
- *
655
- * - 并发窗口 = config.maxConcurrency(默认 1 保守串行,行为与现状一致)
656
- * - `>1` 时输出警告(并行 GitHub API 调用可能触发限流)
657
- * - 失败隔离由 task 内部 try-catch 承担(每仓库独立 repoResults 记录),
658
- * scheduler 提供 onError 兜底,单仓库异常不中断整体
659
- * - 空清单:记录 EMPTY_REPO_LIST 错误(非 0 退出),避免静默空跑(同构缺陷)
660
- */
661
- private runRepoPipeline;
662
- /**
663
- * 解析本次运行要处理的仓库清单(owner 自动发现 + 显式列表合并)。
664
- *
665
- * - 配置了 `--owner` 且 client 可用:自动发现 → 与显式 `repositories` 合并去重
666
- * (显式优先:显式列表保持原顺序在前,发现结果按仓库名排序仅补充未出现项)
667
- * - 发现失败(token 权限、网络等全局性问题):记录 DISCOVERY_FAILED 错误,
668
- * 回退处理显式列表(显式优先语义,不静默丢弃显式仓库)
669
- * - 未配置 `--owner`:沿用现有 resolveAlertRepositories 语义
670
- */
671
- private resolveRepositories;
672
- /**
673
- * 告警数据源统一入口:
674
- * - `github-dependabot`:Octokit 拉取 Dependabot alerts(alertsToken 优先);
675
- * `codeScanningEnabled` 时**并行**拉取 Code Scanning alerts(互不覆盖、互不回退)
676
- * - `pnpm-audit`:本地 `pnpm audit --json` 回退(无 token;repository 已由 resolveAlertRepositories 解析)
677
- *
678
- * per-source 错误隔离:并行源任一失败 → 记录该源 FETCH_FAILED 错误
679
- * (退出码保持非 0)并保留成功源数据继续处理;**全部源失败**才抛错
680
- * (调用方 catch 记录仓库失败,保持 hint 语义)。
681
- */
682
- private fetchAlerts;
683
- /** 记录单个告警源的拉取失败(不中断另一源的处理)。 */
684
- private recordAlertSourceError;
685
- /** pnpm-audit 模式不创建 GitHub client(无 token);github-dependabot 模式返回主 token client。 */
686
- private githubClientOrNull;
687
- private createClient;
688
- /**
689
- * 拉取 Dependabot alerts 使用的 client(双 token 设计):
690
- * 优先使用 `alertsToken`(最小权限:仅 Dependabot alerts: read),
691
- * 缺省回退主 token(本地完整 PAT 场景)。
692
- * 背景详见 docs/plan/todo.md「已知缺口 G2」。
693
- */
694
- private createAlertsClient;
695
- /**
696
- * 获取仓库的默认分支。
697
- * pnpm-audit 模式 client 为 null → 返回 ''(报告显示 local)。
698
- * 失败时返回 `'unknown'`(不阻塞主流程)。
699
- */
700
- private fetchDefaultBranch;
701
- }
702
- //#endregion
703
- //#region src/fixers/dependency/index.d.ts
704
- interface UpgradeDependencyParams {
705
- /** 包名(如 `'lodash'`, `'@babel/traverse'`) */
706
- packageName: string;
707
- /** 目标精确版本(如 `'4.17.21'`) */
708
- targetVersion: string;
709
- /** 工作目录(workspace 根,包含 `package.json` 和 `pnpm-lock.yaml`) */
710
- workDir: string;
711
- /**
712
- * 可选:目标 manifest 所在成员目录(相对 workDir,如 `'packages/web'`)。
713
- * 缺省 = 根 `package.json`(现状行为)。
714
- * 指定时:修改成员 manifest 的依赖声明,`pnpm install` 仍在根 `workDir`
715
- * 执行(workspace 解析语义),失败回滚成员 manifest + `pnpm-lock.yaml`。
716
- */
717
- manifestDir?: string;
718
- }
719
- interface DependencyFixResult {
720
- packageName: string;
721
- /** 升级前版本声明(保留原始 range 格式,如 `^4.17.20`) */
722
- fromVersion: string;
723
- /** 升级后版本声明(保留原始前缀,如 `^4.17.21`) */
724
- toVersion: string;
725
- /** 是否为 major 版本升级 */
726
- isMajor: boolean;
727
- /** 升级是否成功 */
728
- success: boolean;
729
- /** 失败原因(仅 `success=false` 时有值) */
730
- error?: string;
731
- /** 成功但存在需要用户注意的附加信息(如 overrides 写入位置可能被 pnpm 忽略) */
732
- warning?: string;
733
- }
734
- interface PackageJson {
735
- name?: string;
736
- dependencies?: Record<string, string>;
737
- devDependencies?: Record<string, string>;
738
- optionalDependencies?: Record<string, string>;
739
- peerDependencies?: Record<string, string>;
740
- pnpm?: {
741
- overrides?: Record<string, string>;
742
- [key: string]: unknown;
743
- };
744
- [key: string]: unknown;
745
- }
746
- interface DependencyInfo {
747
- group: 'dependencies' | 'devDependencies' | 'optionalDependencies';
748
- version: string;
749
- }
750
- /**
751
- * 升级单个依赖到指定版本。
752
- *
753
- * - 在目标 manifest(根 `package.json`,或 `params.manifestDir` 指定的成员 manifest)
754
- * 中修改目标包的版本声明(保留原始前缀)
755
- * - 执行 `pnpm install --no-frozen-lockfile` 更新 lockfile(始终在根 `workDir` 执行,
756
- * workspace 解析语义——成员声明变更会触发全 workspace 重新解析)
757
- * - 失败时自动回滚目标 manifest 和 `pnpm-lock.yaml`
758
- * - 声明为包管理器协议(`workspace:` / `catalog:` / `link:` 等)时明确失败,
759
- * 不做不可逆的声明改写
760
- * - 不执行验证(由验证执行器负责)
761
- *
762
- * @param params - 包名、目标版本、工作目录、可选成员目录
763
- * @returns 修复结果
764
- */
765
- declare function upgradeDependency(params: UpgradeDependencyParams): Promise<DependencyFixResult>;
766
- /**
767
- * 通过 pnpm `overrides` 升级间接(transitive)依赖。
768
- *
769
- * 间接依赖不在 `package.json` 的 `dependencies` / `devDependencies` 中列出,
770
- * 因此无法通过常规 `upgradeDependency` 处理。本函数根据项目类型选择覆盖写入位置:
771
- *
772
- * - **有 `pnpm-workspace.yaml`**(monorepo / workspace)→ 写入其中的 `overrides` 字段(pnpm v10+ 推荐)
773
- * - **无 `pnpm-workspace.yaml`**(单包项目)→ 写入 `package.json` 的 `pnpm.overrides`
774
- *
775
- * 失败时自动回滚被修改的文件和 `pnpm-lock.yaml`。不执行验证(由验证执行器负责)。
776
- *
777
- * @param params - 包名、目标版本、工作目录
778
- * @returns 修复结果
779
- */
780
- declare function overrideTransitiveDependency(params: UpgradeDependencyParams): Promise<DependencyFixResult>;
781
- /**
782
- * 通过 pnpm `overrides` **批量**写入版本化覆盖并执行 install(多版本共存场景)。
783
- *
784
- * 场景:lockfile 中同一包共存多个版本实例(如 vite@5.4.14 与 vite@8.2.0),
785
- * 单一 `pkg: version` 全局覆盖会波及所有实例(可能误降级根声明),
786
- * 因此按版本实例分别写 `pkg@version: ^target`(pnpm 版本化 override 惯例,
787
- * 参考用户提供的 path-to-regexp / picomatch 多版本分别覆盖示例)。
788
- *
789
- * 写入位置与 `overrideTransitiveDependency` 一致:
790
- * - 存在 `pnpm-workspace.yaml` → 写入其中 `overrides`
791
- * - 否则 → 写入 `package.json` 的 `pnpm.overrides`
792
- *
793
- * 失败时自动回滚被修改的文件和 `pnpm-lock.yaml`。不执行验证(由上层负责)。
794
- *
795
- * @param params - 包名、版本化 overrides 映射(`pkg@version` → `^target`)、工作目录
796
- * @returns 修复结果(fromVersion 为空字符串,表示多实例无单一来源版本)
797
- */
798
- declare function applyVersionedOverrides(params: {
799
- packageName: string;
800
- versionedOverrides: Record<string, string>;
801
- workDir: string;
802
- }): Promise<DependencyFixResult>;
803
- /**
804
- * 从版本声明中提取前缀(^ / ~ / 空)。
805
- *
806
- * @example
807
- * extractPrefix('^4.17.20') // '^'
808
- * extractPrefix('~4.17.0') // '~'
809
- * extractPrefix('4.17.20') // ''
810
- * extractPrefix('*') // '^' (默认)
811
- */
812
- declare function extractPrefix(version: string): string;
813
- /**
814
- * 检测版本声明是否包含包管理器协议前缀
815
- * (`workspace:` / `catalog:` / `link:` / `file:` / `npm:` / `github:` /
816
- * `gitlab:` / `bitbucket:` / `gist:` / `git:` / `git+ssh:` / `git+https:` /
817
- * `git+http:` / `git+file:` / `https:` / `ssh:` 等)。
818
- *
819
- * 这类声明不是 semver range,`extractPrefix` 会将其误归为 `^` 导致声明被
820
- * 不可逆改写(如 `catalog:` → `^x.y.z`、`git+ssh:` 来源从 fork/私有源静默
821
- * 切回 registry),升级前必须拒绝。
822
- *
823
- * @example
824
- * isNonSemverDeclaration('^4.17.20') // false
825
- * isNonSemverDeclaration('workspace:*') // true
826
- * isNonSemverDeclaration('catalog:') // true
827
- * isNonSemverDeclaration('link:../pkg') // true
828
- * isNonSemverDeclaration('git+ssh://...') // true
829
- * isNonSemverDeclaration('gitlab:...') // true
830
- * isNonSemverDeclaration('https://...tgz') // true
831
- */
832
- declare function isNonSemverDeclaration(version: string): boolean;
833
- /**
834
- * 从版本声明中提取主版本号(major)。
835
- * 去除前缀后匹配第一个 semver 段。
836
- *
837
- * @example
838
- * parseMajorVersion('^4.17.20') // 4
839
- * parseMajorVersion('~2.0.0') // 2
840
- * parseMajorVersion('1.2.3') // 1
841
- * parseMajorVersion('*') // -1
842
- */
843
- declare function parseMajorVersion(version: string): number;
844
- /**
845
- * 比较两个语义化版本(`x.y.z`,可选 pre-release 后缀)。
846
- *
847
- * - `a > b` 返回正数,`a < b` 返回负数,相等返回 0
848
- * - 非 semver 字符串按 0 处理(保守:不参与大小比较)
849
- * - 仅比较主/次/补丁段,pre-release 后缀忽略(如 `1.0.0-beta` 视为 `1.0.0`)
850
- *
851
- * @example
852
- * compareSemver('4.18.0', '4.17.21') // 1
853
- * compareSemver('5.4.20', '6.4.3') // -1
854
- * compareSemver('1.2.3', '1.2.3') // 0
855
- */
856
- declare function compareSemver(a: string, b: string): number;
857
- /**
858
- * 在 `package.json` 的 `dependencies` / `devDependencies` / `optionalDependencies` 中按顺序查找包。
859
- */
860
- declare function findDependencyVersion(pkg: PackageJson, packageName: string): DependencyInfo | null;
861
- /**
862
- * 确保 `package.json` 中存在 `pnpm.overrides` 对象,若不存在则创建。
863
- * 返回 `overrides` 对象的引用,调用方可直接写入。
864
- */
865
- declare function ensurePnpmOverrides(pkg: PackageJson): Record<string, string>;
866
- /**
867
- * 从 `pnpm-lock.yaml` 中读取指定包的**所有**锁定版本实例。
868
- *
869
- * 支持两种 lockfile 键格式:
870
- * 1. v9 早期格式(lockfileVersion 9.0 起):`/package-name/version:`
871
- * 2. pnpm v10+/v11 snapshot 格式:`package-name@version:` 或
872
- * `package-name@version(peer@x)(peer2@y):`(peer 后缀条目)
873
- *
874
- * 同一包在 lockfile 中可能共存多个版本(如 vite@5.4.14 与 vite@8.2.0),
875
- * 多版本共存是「版本化 overrides(pkg@version: ^target)」修复策略的前提。
876
- *
877
- * @returns 去重后的版本列表(如 `['5.4.14', '8.2.0']`),未找到返回 `[]`
878
- */
879
- declare function readLockfileVersions(lockfilePath: string, packageName: string): string[];
880
- /**
881
- * 从 `pnpm-lock.yaml` 中读取指定包的当前锁定版本。
882
- *
883
- * 多版本并存时(如同一包同时被根与子目录 manifest 引用),取**最高版本**
884
- * (保守:不降级保护依赖此语义,如根 vite@8.2.0 与 docs vite@5.4.14 并存)。
885
- *
886
- * @returns 锁定版本字符串(如 `'5.0.0'`),未找到返回 `null`
887
- */
888
- declare function readLockfileVersion(lockfilePath: string, packageName: string): string | null;
889
- /**
890
- * 探测当前 pnpm 大版本(pnpm v10+ 对无 `pnpm-workspace.yaml` 的项目
891
- * 可能不读取 `package.json#pnpm.overrides`,写入会"假成功")。
892
- * 探测失败(pnpm 不可用 / 输出异常)返回 null,调用方降级为不告警。
893
- */
894
- declare function detectPnpmMajor(workDir: string): number | null;
895
- /**
896
- * 跨线修复判定(2026-08-06 复盘 PR #28)。
897
- *
898
- * lockfile 告警的推荐版本 major 不在 lockfile 实例 majors 中 → 本仓库没有该
899
- * 大版本线的实例,且当前线(如 5.x)没有该告警的修复版本(如 GHSA-fx2h
900
- * 影响 `<= 6.4.2`、first_patched 6.4.3)——只能**跨大版本升级**才能修复。
901
- *
902
- * 保持不跨大版本自动升级:此类告警不进入修复链路(不标 fixed/converged),
903
- * 由上层计入 skipped 并提示用户手动检查/升级/批准。
904
- *
905
- * lockfile 中无该包实例(versions 为空)时返回 false——"无实例"场景由
906
- * partitionSubmanifestAlerts 的常规跳过逻辑处理,避免重复计数。
907
- */
908
- declare function isCrossMajorFixRequired(lockfilePath: string, alert: NormalizedSecurityAlert): boolean;
909
- //#endregion
910
- //#region src/fixers/pnpm/index.d.ts
911
- type LockfileFailureCategory = 'LOCKFILE_NOT_FOUND' | 'MANIFEST_MISMATCH' | 'LOCKFILE_VERSION_MISMATCH' | 'CORRUPTED_LOCKFILE' | 'CREDENTIAL_ERROR' | 'RESOLVE_ERROR' | 'UNKNOWN';
912
- type RepairStrategy = 'REGENERATE' | 'FIX_ENTRIES' | 'PIN_TOOLCHAIN' | 'REINSTALL' | 'SKIP';
913
- interface RepairLockfileParams {
914
- /** 工作目录(必须包含 package.json 和 pnpm-lock.yaml) */
915
- workDir: string;
916
- /** 可选:期望的 pnpm 版本(优先于 packageManager 字段) */
917
- toolchain?: {
918
- pnpmVersion?: string;
919
- };
920
- }
921
- interface LockfileDiff {
922
- /** lockfile 行数变化(正=增加) */
923
- linesChanged: number;
924
- /** packages 条数变化(正=增加) */
925
- packagesChanged: number;
926
- /** 简要文字摘要 */
927
- summary: string;
928
- }
929
- interface RepairAttempt {
930
- strategy: RepairStrategy;
931
- command: string;
932
- success: boolean;
933
- error?: string;
934
- durationMs: number;
935
- }
936
- interface LockfileRepairResult {
937
- success: boolean;
938
- failureCategory?: LockfileFailureCategory;
939
- failureDetail?: string;
940
- strategy?: RepairStrategy;
941
- diff?: LockfileDiff | null;
942
- attemptHistory: RepairAttempt[];
943
- /** 修复后 lockfile 的 lockfileVersion(提取自 pnpm-lock.yaml) */
944
- lockfileVersion?: string;
945
- /** 修复前后 lockfileVersion 是否变化(格式漂移检测,wisdom: pnpm v11 overrides 迁移教训) */
946
- lockfileVersionChanged?: boolean;
947
- }
948
- interface ClassificationResult {
949
- ok: boolean;
950
- category?: LockfileFailureCategory;
951
- stderr?: string;
952
- }
953
- /**
954
- * 执行 `pnpm i --frozen-lockfile` 并解析失败分类。
955
- * 成功时返回 { ok: true }。
956
- */
957
- declare function classifyLockfileFailure(workDir: string): ClassificationResult;
958
- /** 从 lockfile 内容提取 `lockfileVersion` 字段值(如 `9.0`);缺失返回 null。 */
959
- declare function extractLockfileVersion(content: string): string | null;
960
- /**
961
- * 比较修复前后 lockfile,返回行数与包数量变化摘要。
962
- */
963
- declare function computeLockfileDiff(beforePath: string, afterPath: string): LockfileDiff;
964
- /** 校验 pnpm 版本格式是否合法(非法返回 false,调用方回退裸命令/报错)。 */
965
- declare function isValidPnpmVersion(version: string | undefined | null): version is string;
966
- /**
967
- * 从 package.json 的 `packageManager` 字段解析 pnpm 版本。
968
- * 优先级: toolchain.pnpmVersion > packageManager > null
969
- * 非法 toolchain 版本 → 回退 packageManager;两者都非法/缺失 → null(裸命令兜底)。
970
- */
971
- declare function resolvePnpmVersion(workDir: string, toolchain?: {
972
- pnpmVersion?: string;
973
- }): string | null;
974
- /**
975
- * 检测并修复 pnpm frozen-lockfile 漂移。
976
- *
977
- * 流程:
978
- * 1. 先跑 `pnpm i --frozen-lockfile` 诊断
979
- * 2. 若已合规 → 直接返回 success
980
- * 3. 若为 CREDENTIAL_ERROR → SKIP
981
- * 4. 按分类选取策略链,逐级尝试修复:
982
- * - 每个策略执行后立即用 `pnpm i --frozen-lockfile` 验证
983
- * - 验证通过 → 记录 diff、返回 success
984
- * - 验证失败 → 继续下一个策略
985
- * 5. 所有策略失败 → 回滚 lockfile、返回失败结果
986
- */
987
- declare function repairLockfile(params: RepairLockfileParams): LockfileRepairResult;
988
- //#endregion
989
- //#region src/github/client.d.ts
990
- interface RetryPolicyOptions {
991
- /** 最大重试次数(默认 3;0 = 不重试) */
992
- maxRetries?: number;
993
- /** 指数退避基数毫秒(默认 1000;测试时可调小) */
994
- baseDelayMs?: number;
995
- /**
996
- * 指数退避单次等待上限毫秒(默认 30000),防止长时间空转。
997
- * Retry-After / x-ratelimit-reset 指定的等待同样受此上限约束。
998
- */
999
- maxBackoffMs?: number;
1000
- }
1001
- interface OctokitClientOptions {
1002
- /** GitHub Personal Access Token */
1003
- token: string;
1004
- /**
1005
- * API 基地址。
1006
- * 默认 `https://api.github.com`。
1007
- * 测试时指向 nock 拦截的同一地址。
1008
- */
1009
- baseUrl?: string;
1010
- /**
1011
- * API 限流 / 次要限流(secondary rate limit)指数退避重试策略。
1012
- * 默认 maxRetries=3。对 429、primary rate limit(403 + x-ratelimit-remaining: 0)、
1013
- * secondary rate limit(403/429 带 secondary/abuse/retry 特征)自动退避重试;
1014
- * 权限类 403 不重试。
1015
- */
1016
- retry?: RetryPolicyOptions;
1017
- }
1018
- /**
1019
- * 创建已认证的 Octokit 实例。
1020
- *
1021
- * 调用方直接使用 `octokit.rest.*` 访问所有已类型化的 GitHub REST API。
1022
- * 分页使用 `octokit.paginate()` 自动合并多页结果。
1023
- *
1024
- * 配置 `retry` 时通过 `hook.wrap('request')` 统一包装所有请求
1025
- * (含 paginate 内部请求),对限流响应做指数退避重试。
1026
- *
1027
- * @example
1028
- * ```typescript
1029
- * const octokit = createGitHubClient({ token: 'ghp_xxxx' })
1030
- *
1031
- * // 仓库信息
1032
- * const { data: repo } = await octokit.rest.repos.get({ owner: 'foo', repo: 'bar' })
1033
- *
1034
- * // Dependabot 告警(自动分页)
1035
- * const alerts = await octokit.paginate(
1036
- * octokit.rest.dependabot.listAlertsForRepo,
1037
- * { owner: 'foo', repo: 'bar', state: 'open', per_page: 100 },
1038
- * )
1039
- * ```
1040
- */
1041
- declare function createGitHubClient(options: OctokitClientOptions): Octokit;
1042
- /**
1043
- * 计算限流重试等待时间(纯函数,可单测)。
1044
- *
1045
- * 可重试(返回等待毫秒):
1046
- * - 429(Too Many Requests / secondary rate limit)
1047
- * - 403 + `x-ratelimit-remaining: 0`(primary rate limit)
1048
- * - 403/429 + message 含 secondary rate limit / abuse / retry 特征
1049
- *
1050
- * 等待策略(Retry-After 优先):
1051
- * 1. `retry-after` 头(秒)→ 等待其秒数(受 maxBackoffMs 上限约束)
1052
- * 2. `x-ratelimit-reset`(unix 秒)→ 等待到 reset + 1s 缓冲
1053
- * 3. 否则 → 指数退避 `baseDelayMs * 2^attempt`
1054
- * 所有等待均受 maxBackoffMs 上限约束(默认 30s)。
1055
- *
1056
- * 不重试(返回 null):
1057
- * - 非 RequestError(网络错误等由上层 AppError 语义处理)
1058
- * - 权限类 403(无限流特征)
1059
- * - 其他状态码
1060
- */
1061
- declare function computeRetryDelayMs(error: unknown, attempt: number, baseDelayMs?: number, maxBackoffMs?: number): number | null;
1062
- //#endregion
1063
- //#region src/github/dependabot-fetcher.d.ts
1064
- interface FetchDependabotAlertsParams {
1065
- /** 仓库所属组织或用户 */
1066
- owner: string;
1067
- /** 仓库名称 */
1068
- repo: string;
1069
- /**
1070
- * 告警状态过滤。
1071
- * 只拉 `open`(默认)。
1072
- */
1073
- state?: 'open' | 'fixed' | 'dismissed' | 'auto_dismissed';
1074
- /** 每页数量,默认 100(GitHub API 最大值) */
1075
- perPage?: number;
1076
- }
1077
- /**
1078
- * 拉取指定仓库的 Dependabot 告警并映射为标准化模型。
1079
- *
1080
- * - 自动分页(`octokit.paginate()`),返回所有匹配的告警
1081
- * - 仅处理 `state=open` 的告警(可通过 `params.state` 覆盖)
1082
- * - 异常通过 `mapGitHubError` 转为 `AppError`
1083
- * - 空仓库返回 `[]`,不抛异常
1084
- *
1085
- * @param client - 已认证的 Octokit 实例(来自 `createGitHubClient`)
1086
- * @param params - 仓库标识与过滤参数
1087
- * @returns 标准化告警列表
1088
- *
1089
- * @example
1090
- * ```typescript
1091
- * const octokit = createGitHubClient({ token: 'ghp_xxxx' })
1092
- * const alerts = await fetchDependabotAlerts(octokit, { owner: 'foo', repo: 'bar' })
1093
- * ```
1094
- */
1095
- declare function fetchDependabotAlerts(client: Octokit, params: FetchDependabotAlertsParams): Promise<NormalizedSecurityAlert[]>;
1096
- //#endregion
1097
- //#region src/github/errors.d.ts
1098
- /**
1099
- * 将 Octokit 请求错误映射为 `AppError`。
1100
- *
1101
- * @param error - 原始错误(`RequestError` 或网络异常)
1102
- * @param context - 调用上下文描述(如 `'fetch repo info for foo/bar'`),会附加到错误消息中
1103
- */
1104
- declare function mapGitHubError(error: unknown, context: string): AppError;
1105
- //#endregion
1106
- //#region src/github/pr-creator.d.ts
1107
- interface CreatePullRequestParams {
1108
- /** 已认证的 Octokit 实例 */
1109
- octokit: Octokit;
1110
- /** 仓库 owner */
1111
- owner: string;
1112
- /** 仓库名 */
1113
- repo: string;
1114
- /** 修复分支名 */
1115
- headBranch: string;
1116
- /** 目标分支(默认 master/main,从 API 获取) */
1117
- baseBranch: string;
1118
- /** PR 标题 */
1119
- title: string;
1120
- /** PR 内容(Markdown) */
1121
- body: string;
1122
- }
1123
- interface PullRequestResult {
1124
- /** PR 编号 */
1125
- number: number;
1126
- /** PR HTML URL */
1127
- htmlUrl: string;
1128
- }
1129
- interface FixBranchResult {
1130
- /** 分支名 */
1131
- branchName: string;
1132
- /** 是否为新创建 */
1133
- created: boolean;
1134
- }
1135
- /** dependfix 自动修复 PR 的公开信息(用于查重/取代判定) */
1136
- interface DependfixOpenPR {
1137
- /** PR 编号 */
1138
- number: number;
1139
- /** PR HTML URL */
1140
- htmlUrl: string;
1141
- /** PR head 分支名 */
1142
- headRef: string;
1143
- }
1144
- /**
1145
- * 计算修复内容指纹(sha256 前 8 位)。
1146
- *
1147
- * 指纹基于**结构化修复结果**而非 git diff:
1148
- * - 成功升级集:`pkg@toVersion@manifest`(排序拼接;manifest 区分根升级与
1149
- * 成员升级——成员级修复后,同包根/成员升级是不同修复内容,
1150
- * 若指纹不含 manifest 维度,根升级 PR 会错误 skip 后续成员升级)
1151
- * - 修复失败集:失败包名@manifest(排序拼接)
1152
- * - lockfile 修复状态(成功/失败)
1153
- *
1154
- * 同告警集 → 同修复结果 → 同指纹 → 幂等跳过;
1155
- * 内容变化(升级集/失败集/锁文件修复变化)→ 指纹变化 → 关旧开新。
1156
- * 不用 diff hash 是因为 pnpm 版本等非确定性因素会使锁文件内容漂移,
1157
- * 导致"告警没变但指纹变"。
1158
- */
1159
- declare function computeFixFingerprint(actions: FixAction[]): string;
1160
- /**
1161
- * 从分支名提取内容指纹(`dependfix/auto-fix-{fp8}` → `{fp8}`)。
1162
- * 指纹格式为 8 位 hex;分支名不含 `-` 后的内容、前缀不匹配或格式不合法时返回 null
1163
- * (如旧版 runId 分支,会被 supersede)。
1164
- */
1165
- declare function extractFingerprintFromBranch(branchName: string): string | null;
1166
- /** fix-and-pr 去重决策结果 */
1167
- interface FixAndPrPlan {
1168
- /** skip = 已有同内容 PR,不重复提交;create = 需要新建 PR */
1169
- action: 'skip' | 'create';
1170
- /** action=skip 时命中的同内容 PR */
1171
- sameContentPR?: DependfixOpenPR;
1172
- /** 内容不同、需要关闭(supersede)的旧 PR 列表 */
1173
- supersedePRs: DependfixOpenPR[];
1174
- }
1175
- /**
1176
- * 计算 fix-and-pr 去重决策:
1177
- * - 存在同指纹 open PR → skip(仅需关闭其余异指纹 PR)
1178
- * - 否则 → create(关闭全部旧 PR,先建新后关旧由调用方保证)
1179
- */
1180
- declare function computeFixAndPrPlan(existingPRs: DependfixOpenPR[], fingerprint: string): FixAndPrPlan;
1181
- /**
1182
- * 在工作目录创建修复分支。
1183
- *
1184
- * - 分支名由调用方传入(分支名为 `dependfix/auto-fix-{内容指纹}`,不再依赖 runId)
1185
- * - 如果分支已存在(如重跑),切换到该分支
1186
- *
1187
- * @returns 分支名和是否为新创建
1188
- */
1189
- declare function createFixBranch(branchName: string, workDir: string): FixBranchResult;
1190
- /**
1191
- * 暂存所有变更并提交。
1192
- * 自动设置 git user.name / user.email(如未设置)。
1193
- * 使用 `execFileSync` 参数数组形式(不经 shell),保证多行 commit message
1194
- * 与 UTF-8 字符(如 →)在 Windows/Linux 双平台传递一致。
1195
- */
1196
- declare function stageAndCommit(message: string, workDir: string): void;
1197
- /**
1198
- * 推送分支到远程 origin。
1199
- */
1200
- declare function pushBranch(branchName: string, workDir: string): void;
1201
- /**
1202
- * 查找目标仓库中所有 open 状态的 dependfix 自动修复 PR。
1203
- *
1204
- * GitHub 的 `pulls.list` 的 `head` 参数不支持通配符,因此拉取 open PR 列表后
1205
- * 按 head 分支前缀 `dependfix/auto-fix-` 过滤。假设 PR 数量不多(单页 100 足够),
1206
- * 未来 PR 数量增大时可引入 label 索引(backlog 已登记演进项)。
1207
- */
1208
- declare function findDependfixOpenPR(octokit: Octokit, owner: string, repo: string): Promise<DependfixOpenPR[]>;
1209
- /**
1210
- * 关闭 Pull Request(用于 supersede 旧 PR)。
1211
- */
1212
- declare function closePullRequest(octokit: Octokit, owner: string, repo: string, pullNumber: number): Promise<void>;
1213
- /**
1214
- * 通过 GitHub API 创建 Pull Request。
1215
- */
1216
- declare function createPullRequest(params: CreatePullRequestParams): Promise<PullRequestResult>;
1217
- /** 分支清理状态(用于 cleanup-branches 清单分类) */
1218
- interface DependfixBranchStatus {
1219
- /** 分支名 */
1220
- branch: string;
1221
- /** 关联 PR 编号(无 PR 记录时为 null) */
1222
- prNumber: number | null;
1223
- /** PR 是否已合并 */
1224
- merged: boolean;
1225
- /** PR 是否已关闭(含合并) */
1226
- closed: boolean;
1227
- }
1228
- /**
1229
- * 列出远端所有 `dependfix/` 前缀分支(git.listMatchingRefs 精确前缀匹配)。
1230
- */
1231
- declare function listDependfixBranches(octokit: Octokit, owner: string, repo: string): Promise<string[]>;
1232
- /**
1233
- * 查询分支对应的最近 PR 状态(pulls.list head 精确匹配,按最近更新取 1 条)。
1234
- */
1235
- declare function getBranchPrStatus(octokit: Octokit, owner: string, repo: string, branch: string): Promise<DependfixBranchStatus>;
1236
- /**
1237
- * 删除远端分支(git ref delete)。失败(分支保护、不存在)由调用方捕获处理。
1238
- */
1239
- declare function deleteRemoteBranch(octokit: Octokit, owner: string, repo: string, branch: string): Promise<void>;
1240
- /**
1241
- * 判定交互确认回答是否为"是"(y/yes,大小写不敏感;空输入默认拒绝)。
1242
- */
1243
- declare function isConfirmAnswer(answer: string): boolean;
1244
- /**
1245
- * 从 RunResult 生成 PR body(Markdown)。
1246
- *
1247
- * 升级/失败列表按 (仓库, 包名) 聚合:同一包多次出现合并为一行
1248
- * (from 取最早起点、to 取最新终点),避免一个包出现多次。
1249
- *
1250
- * body 超出 GitHub 64KB 上限时从**尾部**逐行截断(保留头部摘要与升级明细,
1251
- * 明细表在尾部被截断),并附加截断说明——避免大仓库 PR 创建 422。
1252
- *
1253
- * @param supersededNumbers 被本 PR 取代并已关闭的旧 PR 编号列表(用于 Supersedes 声明)
1254
- */
1255
- declare function generatePRBody(result: RunResult, supersededNumbers?: number[]): string;
1256
- //#endregion
1257
- //#region src/github/repo-policy.d.ts
1258
- /** 单条 glob 模式长度上限(加固:防止超长模式引入匹配开销;受信配置 + 短输入) */
1259
- declare const MAX_GLOB_PATTERN_LENGTH = 200;
1260
- /**
1261
- * 将仓库 glob 模式转正则(`owner/*`、`owner/pkg-*`)。
1262
- *
1263
- * 支持通配:
1264
- * - `*` → 任意非 `/` 字符序列(不跨仓库分隔符)
1265
- * - `?` → 单个非 `/` 字符
1266
- * - 其余字符按字面量(正则元字符转义)
1267
- *
1268
- * 匹配对象为完整 `owner/repo` 字符串(大小写敏感,与 GitHub full_name 一致)。
1269
- * 模式仅限受信配置输入(CLI/env),长度超过 {@link MAX_GLOB_PATTERN_LENGTH} 时拒绝。
1270
- * 多通配符模式存在理论 O(n^k) 回溯面(`[^/]*` 单层字符类、输入 ≤ ~140 字符,风险低);
1271
- * 正则引擎演进时需专项 ReDoS 审计。
1272
- */
1273
- declare function repoGlobToRegExp(pattern: string): RegExp;
1274
- /** glob 模式匹配 `owner/repo`(完整匹配)。 */
1275
- declare function matchesRepoGlob(pattern: string, fullName: string): boolean;
1276
- interface RepoPolicy {
1277
- /** 白名单 glob(仅作用于发现结果;显式列表不受影响) */
1278
- include?: string[];
1279
- /** 黑名单 glob(显式列表 + 发现结果均受约束;与 include 冲突时胜出) */
1280
- exclude?: string[];
1281
- /** topic 黑名单(仅作用于发现结果:排除含任一指定 topic 的仓库) */
1282
- topicsExclude?: string[];
1283
- }
1284
- /** 是否命中任一 exclude 模式(黑名单)。 */
1285
- declare function matchesRepoExclude(policy: RepoPolicy, fullName: string): boolean;
1286
- /** 是否通过 include 白名单(include 为空 = 不限制;非空 = 必须命中任一模式)。 */
1287
- declare function matchesRepoInclude(policy: RepoPolicy, fullName: string): boolean;
1288
- /** topic 黑名单:仓库 topics 含任一指定 topic 即排除(大小写归一化后比较)。 */
1289
- declare function matchesTopicsExclude(policy: RepoPolicy, topics: string[]): boolean;
1290
- /**
1291
- * 过滤显式仓库列表:仅受 exclude 约束(白名单 include 不适用于显式列表,
1292
- * 设计要点:显式优先,用户显式指定的仓库不应被 include 静默剔除)。
1293
- */
1294
- declare function filterExplicitRepositories(policy: RepoPolicy, repositories: string[]): string[];
1295
- //#endregion
1296
- //#region src/github/repo-selector.d.ts
1297
- /**
1298
- * 从文件读取仓库列表(每行一个 `owner/repo`)。
1299
- * 空行和 `#` 开头的注释行会被跳过。
1300
- */
1301
- declare function readReposFile(filePath: string): string[];
1302
- /**
1303
- * 合并 CLI 传入仓库列表与文件中的仓库列表,去重并校验。
1304
- */
1305
- declare function resolveRepoList(cliRepos: string[], reposFilePath?: string): string[];
1306
- //#endregion
1307
- //#region src/github/repository-discovery.d.ts
1308
- interface RepositoryDiscoveryOptions {
1309
- /** 已认证的 Octokit 实例 */
1310
- client: Octokit;
1311
- /** owner / org 列表(分别拉取后合并) */
1312
- owners: string[];
1313
- /**
1314
- * topic 白名单(AND 语义):仓库必须包含**全部**指定 topics 才保留。
1315
- * 为空时不按 topic 过滤。
1316
- */
1317
- topics?: string[];
1318
- /**
1319
- * 名单策略(include / exclude / topicsExclude):
1320
- * 在基础过滤与 topic 过滤之后、dependabot.yml 探测**之前**应用——
1321
- * 被策略排除的仓库不触达 contents API(探测请求数量受控)。
1322
- * include 与 exclude 冲突时 exclude 胜出。
1323
- */
1324
- policy?: RepoPolicy;
1325
- /**
1326
- * 是否探测 `.github/dependabot.yml` 存在性(默认 true)。
1327
- * 仅对候选仓库触达 contents API;404 视为不支持(false),不剔除仓库。
1328
- */
1329
- probeDependabot?: boolean;
1330
- /** dependabot.yml 探测并发上限(默认 5,避免一次性打爆 API) */
1331
- probeConcurrency?: number;
1332
- }
1333
- interface DiscoveredRepository {
1334
- /** `owner/repo` 格式 */
1335
- fullName: string;
1336
- defaultBranch: string;
1337
- topics: string[];
1338
- /** 默认分支存在 `.github/dependabot.yml`(contents API 探测,404=false) */
1339
- hasDependabotConfig: boolean;
1340
- }
1341
- /**
1342
- * 按 owner / org 自动发现仓库,产出稳定处理清单。
1343
- *
1344
- * 过滤链(按顺序):
1345
- * 1. 基础过滤:archived / disabled / fork 剔除,默认分支缺失剔除
1346
- * 2. topic 过滤(`--repo-topics`,AND 语义)
1347
- * 3. 名单策略过滤(include / exclude / topicsExclude,探测前应用)
1348
- * 4. dependabot.yml 探测(仅候选仓库触达 contents API;404 视为不支持,不剔除)
1349
- *
1350
- * 结果按 `fullName` 字典序排序,保证同输入多次运行结果一致
1351
- * (runId / 指纹稳定性前提)。
1352
- *
1353
- * @throws AppError(mapGitHubError 转换;token 权限、网络等全局性问题 fail-fast)
1354
- */
1355
- declare function discoverRepositories(options: RepositoryDiscoveryOptions): Promise<DiscoveredRepository[]>;
1356
- /**
1357
- * 合并显式仓库列表与发现结果:
1358
- * - 显式优先:显式列表保持原顺序且在前
1359
- * - 发现结果仅补充未出现的项(去重;大小写不敏感——GitHub full_name 恒小写,
1360
- * 显式 `Owner/Repo` 与发现 `owner/repo` 视为同一仓库)
1361
- */
1362
- declare function mergeRepositories(explicit: string[], discovered: string[]): string[];
1363
- //#endregion
1364
- //#region src/runners/verification-runner.d.ts
1365
- /**
1366
- * 单条命令的执行结果
1367
- */
1368
- interface CommandResult {
1369
- /** 执行的命令文本 */
1370
- command: string;
1371
- /** 退出码(0 = 成功) */
1372
- exitCode: number;
1373
- /** 执行耗时(毫秒) */
1374
- durationMs: number;
1375
- /** stdout 摘要(截断到 200 行,已脱敏) */
1376
- stdout: string;
1377
- /** stderr 摘要(截断到 200 行,已脱敏) */
1378
- stderr: string;
1379
- }
1380
- /**
1381
- * 验证执行参数
1382
- */
1383
- interface VerificationParams {
1384
- /** 工作目录 */
1385
- workDir: string;
1386
- /**
1387
- * 要执行的命令序列。
1388
- * 默认: `pnpm install --frozen-lockfile` → `pnpm lint` → `pnpm build`
1389
- */
1390
- commands?: string[];
1391
- }
1392
- /**
1393
- * 验证执行结果
1394
- */
1395
- interface VerificationResult {
1396
- /** 所有命令是否全部成功 */
1397
- success: boolean;
1398
- /** 每条命令的详细结果 */
1399
- commandResults: CommandResult[];
1400
- /** 失败的命令(仅 success=false 时填充) */
1401
- failedCommand?: string;
1402
- /** 失败详情(仅 success=false 时填充) */
1403
- failure?: string;
1404
- }
1405
- /**
1406
- * 按顺序在工作目录执行命令序列,任一命令失败则停止。
1407
- *
1408
- * @example
1409
- * ```ts
1410
- * const result = await runVerification({ workDir: '/repo' })
1411
- * if (!result.success) {
1412
- * console.error(result.failure)
1413
- * }
1414
- * ```
1415
- */
1416
- declare function runVerification(params: VerificationParams): Promise<VerificationResult>;
1417
- /**
1418
- * 对外暴露以支持单独测试
1419
- */
1420
- declare function sanitizeOutput(output: string): string;
1421
- //#endregion
1422
337
  //#region src/app/pipeline.d.ts
1423
338
  interface PipelineLogger {
1424
339
  info(msg: string): void;
@@ -1459,5 +374,5 @@ declare function createPipeline(deps?: PipelineDeps): Pipeline;
1459
374
  */
1460
375
  declare function main(args?: string[]): CliRunResult;
1461
376
  //#endregion
1462
- export { ALERT_SOURCES, AiOptions, AiTriggerKind, type AlertSourceKind, CliConfigOverrides, CliInvocation, CliRunResult, CommandResult, CreatePullRequestParams, DEFAULT_RUNTIME_CONFIG, DependencyFixResult, DependfixApp, DependfixAppOptions, DependfixBranchStatus, DependfixOpenPR, DependfixRunResult, DiscoveredRepository, ENV_PREFIX, FetchDependabotAlertsParams, FixAndPrPlan, FixBranchResult, LockfileDiff, LockfileFailureCategory, LockfileRepairResult, MAX_GLOB_PATTERN_LENGTH, OctokitClientOptions, type Pipeline, type PipelineDeps, type PipelineLogger, type PipelineParseResult, PullRequestResult, RUNTIME_MODES, RepairAttempt, RepairLockfileParams, RepairStrategy, RepoPolicy, RepositoryDiscoveryOptions, ResolveRuntimeConfigOptions, RetryPolicyOptions, RuntimeConfig, RuntimeMode, SEVERITY_THRESHOLDS, type SeverityThreshold, UpgradeDependencyParams, VerificationParams, VerificationResult, applyVersionedOverrides, argsDef, classifyLockfileFailure, closePullRequest, compareSemver, computeFixAndPrPlan, computeFixFingerprint, computeLockfileDiff, computeRetryDelayMs, createFixBranch, createGitHubClient, createPipeline, createPullRequest, deleteRemoteBranch, dependfixCommand, detectPnpmMajor, discoverRepositories, ensurePnpmOverrides, extractFingerprintFromBranch, extractLockfileVersion, extractPrefix, fetchDependabotAlerts, filterExplicitRepositories, findDependencyVersion, findDependfixOpenPR, generatePRBody, getBranchPrStatus, inferRepoFromGitRemote, isConfirmAnswer, isCrossMajorFixRequired, isNonSemverDeclaration, isValidPnpmVersion, listDependfixBranches, main, mapGitHubError, matchesRepoExclude, matchesRepoGlob, matchesRepoInclude, matchesTopicsExclude, mergeRepositories, overrideTransitiveDependency, parseCliArgs, parseMajorVersion, pushBranch, readEnv, readEnvConfig, readLockfileVersion, readLockfileVersions, readReposFile, repairLockfile, repoGlobToRegExp, resolvePnpmVersion, resolveRepoList, resolveRuntimeConfig, runCli, runDependfixMain, runVerification, sanitizeOutput, stageAndCommit, upgradeDependency };
377
+ export { CliInvocation, CliRunResult, type Pipeline, type PipelineDeps, type PipelineLogger, type PipelineParseResult, argsDef, createPipeline, dependfixCommand, main, parseCliArgs, runCli, runDependfixMain };
1463
378
  //# sourceMappingURL=index.d.mts.map