@oss-autopilot/core 3.5.0 → 3.6.0
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/cli-registry.js +49 -0
- package/dist/cli.bundle.cjs +111 -107
- package/dist/commands/daily.d.ts +8 -0
- package/dist/commands/daily.js +21 -0
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/index.js +2 -0
- package/dist/commands/startup.js +23 -1
- package/dist/core/anti-llm-policy.d.ts +42 -13
- package/dist/core/anti-llm-policy.js +102 -13
- package/dist/core/ci-analysis.d.ts +32 -1
- package/dist/core/ci-analysis.js +92 -0
- package/dist/core/errors.d.ts +19 -0
- package/dist/core/errors.js +54 -0
- package/dist/core/pr-monitor.d.ts +1 -1
- package/dist/core/pr-monitor.js +31 -11
- package/dist/core/state-schema.d.ts +1 -0
- package/dist/core/state-schema.js +9 -0
- package/dist/core/state.d.ts +7 -0
- package/dist/core/state.js +10 -0
- package/dist/core/strategy.d.ts +21 -1
- package/dist/core/strategy.js +44 -0
- package/dist/core/types.d.ts +49 -0
- package/dist/formatters/json.d.ts +105 -0
- package/dist/formatters/json.js +74 -0
- package/package.json +1 -1
package/dist/core/pr-monitor.js
CHANGED
|
@@ -18,11 +18,11 @@ import { daysBetween } from './dates.js';
|
|
|
18
18
|
import { parseGitHubUrl, extractOwnerRepo, isOwnRepo } from './urls.js';
|
|
19
19
|
import { DEFAULT_CONCURRENCY, runWorkerPool } from './concurrency.js';
|
|
20
20
|
import { determineStatus } from './status-determination.js';
|
|
21
|
-
import { ConfigurationError, ValidationError, errorMessage, getHttpStatusCode, isRateLimitOrAuthError, } from './errors.js';
|
|
21
|
+
import { ConfigurationError, ValidationError, errorMessage, getHttpStatusCode, isInvalidUserSearchError, isRateLimitOrAuthError, } from './errors.js';
|
|
22
22
|
import { paginateAll } from './pagination.js';
|
|
23
23
|
import { debug, warn, timed } from './logger.js';
|
|
24
24
|
import { getHttpCache, cachedRequest } from './http-cache.js';
|
|
25
|
-
import { classifyFailingChecks, getCIStatus } from './ci-analysis.js';
|
|
25
|
+
import { categorizeCIStatus, classifyFailingChecks, getCIStatus } from './ci-analysis.js';
|
|
26
26
|
import { determineReviewDecision, getLatestChangesRequestedDate, checkUnrespondedComments, } from './review-analysis.js';
|
|
27
27
|
import { analyzeChecklist } from './checklist-analysis.js';
|
|
28
28
|
import { extractMaintainerActionHints } from './maintainer-analysis.js';
|
|
@@ -31,7 +31,7 @@ import { fetchUserMergedPRCounts as fetchUserMergedPRCountsImpl, fetchUserClosed
|
|
|
31
31
|
import { isPlaceholderUsername } from './placeholder-usernames.js';
|
|
32
32
|
// Re-export so existing consumers can still import from pr-monitor
|
|
33
33
|
export { computeDisplayLabel } from './display-utils.js';
|
|
34
|
-
export { classifyCICheck, classifyFailingChecks, getCIStatus } from './ci-analysis.js';
|
|
34
|
+
export { categorizeCIStatus, classifyCICheck, classifyFailingChecks, getCIStatus } from './ci-analysis.js';
|
|
35
35
|
export { isConditionalChecklistItem } from './checklist-analysis.js';
|
|
36
36
|
export { determineStatus } from './status-determination.js';
|
|
37
37
|
/**
|
|
@@ -140,16 +140,31 @@ export class PRMonitor {
|
|
|
140
140
|
}
|
|
141
141
|
debug('pr-monitor', `Fetching open PRs for @${searchUsername}...`);
|
|
142
142
|
// Search for all open PRs authored by the user with pagination
|
|
143
|
-
const allItems = [];
|
|
144
143
|
let page = 1;
|
|
145
144
|
const perPage = 100;
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
145
|
+
let firstPage;
|
|
146
|
+
try {
|
|
147
|
+
firstPage = await this.octokit.search.issuesAndPullRequests({
|
|
148
|
+
q: `is:pr is:open is:public author:${searchUsername}`,
|
|
149
|
+
sort: 'updated',
|
|
150
|
+
order: 'desc',
|
|
151
|
+
per_page: perPage,
|
|
152
|
+
page: 1,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
// Rewrite the Search API's "users do not exist" 422 into an actionable
|
|
157
|
+
// ConfigurationError naming the configured username (#1323). The raw
|
|
158
|
+
// Octokit message ("Validation Failed: ...") gives the user no signal
|
|
159
|
+
// that the cause is local config rather than a transient GitHub issue.
|
|
160
|
+
if (isInvalidUserSearchError(err)) {
|
|
161
|
+
throw new ConfigurationError(`Configured GitHub username "${searchUsername}" was not found on GitHub. ` +
|
|
162
|
+
`Run \`/setup-oss\` to reconfigure, or edit \`config.githubUsername\` in ` +
|
|
163
|
+
`\`~/.oss-autopilot/state.json\` directly.`);
|
|
164
|
+
}
|
|
165
|
+
throw err;
|
|
166
|
+
}
|
|
167
|
+
const allItems = [];
|
|
153
168
|
allItems.push(...firstPage.data.items);
|
|
154
169
|
const totalCount = firstPage.data.total_count;
|
|
155
170
|
debug(MODULE, `Found ${totalCount} open PRs`);
|
|
@@ -341,6 +356,10 @@ export class PRMonitor {
|
|
|
341
356
|
const latestChangesRequestedDate = getLatestChangesRequestedDate(reviews);
|
|
342
357
|
// Classify failing checks (delegated to ci-analysis module)
|
|
343
358
|
const classifiedChecks = classifyFailingChecks(failingCheckNames, failingCheckConclusions);
|
|
359
|
+
// Aggregate 5-state CI categorization (#1272). Computed once here so
|
|
360
|
+
// agents read pr.ciCategorization rather than re-deriving the truth
|
|
361
|
+
// table in three separate prose forms.
|
|
362
|
+
const ciCategorization = categorizeCIStatus({ ciStatus, failingCheckNames, classifiedChecks });
|
|
344
363
|
// Determine status
|
|
345
364
|
const hasActionableCIFailure = ciStatus === 'failing' && classifiedChecks.some((c) => c.category === 'actionable');
|
|
346
365
|
const { status, actionReason, waitReason, stalenessTier, actionReasons } = determineStatus({
|
|
@@ -376,6 +395,7 @@ export class PRMonitor {
|
|
|
376
395
|
ciStatus,
|
|
377
396
|
failingCheckNames,
|
|
378
397
|
classifiedChecks,
|
|
398
|
+
ciCategorization,
|
|
379
399
|
hasMergeConflict: mergeConflict,
|
|
380
400
|
reviewDecision,
|
|
381
401
|
hasUnrespondedComment,
|
|
@@ -459,6 +459,7 @@ export declare const AgentStateSchema: z.ZodObject<{
|
|
|
459
459
|
}, z.core.$strip>>;
|
|
460
460
|
lastRunAt: z.ZodDefault<z.ZodString>;
|
|
461
461
|
lastDigestAt: z.ZodOptional<z.ZodString>;
|
|
462
|
+
lastStrategyAt: z.ZodOptional<z.ZodString>;
|
|
462
463
|
lastDigest: z.ZodOptional<z.ZodObject<{
|
|
463
464
|
generatedAt: z.ZodString;
|
|
464
465
|
openPRs: z.ZodArray<z.ZodAny>;
|
|
@@ -285,6 +285,15 @@ export const AgentStateSchema = z.object({
|
|
|
285
285
|
config: AgentConfigSchema.default(() => AgentConfigSchema.parse({})),
|
|
286
286
|
lastRunAt: z.string().default(() => new Date().toISOString()),
|
|
287
287
|
lastDigestAt: z.string().optional(),
|
|
288
|
+
/**
|
|
289
|
+
* ISO timestamp of the most recent {@link computeStrategy} invocation
|
|
290
|
+
* embedded in a daily run output (#1270). The cadence gate in
|
|
291
|
+
* `daily.ts` consults this — strategy snapshots fire every 30 days OR
|
|
292
|
+
* when 5+ PRs have merged since the last snapshot, whichever comes
|
|
293
|
+
* first. Below {@link STRATEGY_MIN_PRS} merged PRs the gate stays
|
|
294
|
+
* silent regardless of cadence.
|
|
295
|
+
*/
|
|
296
|
+
lastStrategyAt: z.string().optional(),
|
|
288
297
|
lastDigest: DailyDigestSchema.optional(),
|
|
289
298
|
monthlyMergedCounts: z.record(z.string(), z.number()).optional(),
|
|
290
299
|
monthlyClosedCounts: z.record(z.string(), z.number()).optional(),
|
package/dist/core/state.d.ts
CHANGED
|
@@ -174,6 +174,13 @@ export declare class StateManager {
|
|
|
174
174
|
* @param digest - The daily digest to store
|
|
175
175
|
*/
|
|
176
176
|
setLastDigest(digest: DailyDigest): void;
|
|
177
|
+
/**
|
|
178
|
+
* Persist the timestamp of the most recent strategy snapshot embedded
|
|
179
|
+
* in a daily run output (#1270). Called from the daily pipeline after
|
|
180
|
+
* `computeStrategy()` succeeds; the cadence gate in
|
|
181
|
+
* {@link shouldComputeStrategy} reads this on the next run.
|
|
182
|
+
*/
|
|
183
|
+
setLastStrategyAt(iso: string): void;
|
|
177
184
|
/**
|
|
178
185
|
* Update monthly merged PR counts for dashboard display.
|
|
179
186
|
* @param counts - Monthly merged PR counts keyed by YYYY-MM
|
package/dist/core/state.js
CHANGED
|
@@ -416,6 +416,16 @@ export class StateManager {
|
|
|
416
416
|
this.state.lastDigestAt = digest.generatedAt;
|
|
417
417
|
this.autoSave();
|
|
418
418
|
}
|
|
419
|
+
/**
|
|
420
|
+
* Persist the timestamp of the most recent strategy snapshot embedded
|
|
421
|
+
* in a daily run output (#1270). Called from the daily pipeline after
|
|
422
|
+
* `computeStrategy()` succeeds; the cadence gate in
|
|
423
|
+
* {@link shouldComputeStrategy} reads this on the next run.
|
|
424
|
+
*/
|
|
425
|
+
setLastStrategyAt(iso) {
|
|
426
|
+
this.state.lastStrategyAt = iso;
|
|
427
|
+
this.autoSave();
|
|
428
|
+
}
|
|
419
429
|
/**
|
|
420
430
|
* Update monthly merged PR counts for dashboard display.
|
|
421
431
|
* @param counts - Monthly merged PR counts keyed by YYYY-MM
|
package/dist/core/strategy.d.ts
CHANGED
|
@@ -32,9 +32,15 @@ export interface StrategyProfile {
|
|
|
32
32
|
export interface StrategyCapacity {
|
|
33
33
|
openPRCount: number;
|
|
34
34
|
dormantPRCount: number;
|
|
35
|
+
/** Distinct repos hosting at least one dormant PR. Surfaces alongside
|
|
36
|
+
* `dormantPRCount` so consumers can render "N PRs across M repos"
|
|
37
|
+
* without re-deriving from `openPRs` themselves. */
|
|
38
|
+
dormantRepoCount: number;
|
|
35
39
|
/** True when dormant PRs span >=2 distinct repos (a signal that the
|
|
36
40
|
* contributor is awaiting reviews from multiple maintainers, not just
|
|
37
|
-
* one slow project).
|
|
41
|
+
* one slow project). Equivalent to `dormantPRCount >= 2 &&
|
|
42
|
+
* dormantRepoCount >= 2` — exposed as a separate boolean so callers
|
|
43
|
+
* with a strict yes/no presentation don't have to recompute. */
|
|
38
44
|
overExtended: boolean;
|
|
39
45
|
/** The single highest-priority next action — null when state is too
|
|
40
46
|
* thin to recommend anything. */
|
|
@@ -73,3 +79,17 @@ export declare const STRATEGY_MIN_PRS = 10;
|
|
|
73
79
|
* minimum-data gate (#1243).
|
|
74
80
|
*/
|
|
75
81
|
export declare function computeStrategy(state: AgentState): StrategyResult | null;
|
|
82
|
+
/** Cadence trigger thresholds for the auto-display in `/oss` (#1270). */
|
|
83
|
+
export declare const STRATEGY_CADENCE_DAYS = 30;
|
|
84
|
+
export declare const STRATEGY_CADENCE_MERGED_DELTA = 5;
|
|
85
|
+
/**
|
|
86
|
+
* Decide whether a strategy snapshot should be embedded in this daily run.
|
|
87
|
+
* Returns true when EITHER 30 days have elapsed since the last snapshot OR
|
|
88
|
+
* 5+ PRs have merged since then, AND the merge floor in
|
|
89
|
+
* {@link STRATEGY_MIN_PRS} is met. The caller is responsible for calling
|
|
90
|
+
* {@link computeStrategy} when this returns true and for persisting
|
|
91
|
+
* `state.lastStrategyAt` after a successful compute.
|
|
92
|
+
*
|
|
93
|
+
* `nowIso` is injected so tests can pin time without mocking `Date`.
|
|
94
|
+
*/
|
|
95
|
+
export declare function shouldComputeStrategy(state: AgentState, nowIso: string): boolean;
|
package/dist/core/strategy.js
CHANGED
|
@@ -182,6 +182,7 @@ export function computeStrategy(state) {
|
|
|
182
182
|
const capacity = {
|
|
183
183
|
openPRCount,
|
|
184
184
|
dormantPRCount,
|
|
185
|
+
dormantRepoCount: dormantRepos.size,
|
|
185
186
|
overExtended,
|
|
186
187
|
suggestedAction: recommendForOverExtension(openPRCount, dormantPRCount, overExtended),
|
|
187
188
|
};
|
|
@@ -204,6 +205,49 @@ export function computeStrategy(state) {
|
|
|
204
205
|
};
|
|
205
206
|
return { profile, capacity, patterns, recommendations };
|
|
206
207
|
}
|
|
208
|
+
/** Cadence trigger thresholds for the auto-display in `/oss` (#1270). */
|
|
209
|
+
export const STRATEGY_CADENCE_DAYS = 30;
|
|
210
|
+
export const STRATEGY_CADENCE_MERGED_DELTA = 5;
|
|
211
|
+
/**
|
|
212
|
+
* Decide whether a strategy snapshot should be embedded in this daily run.
|
|
213
|
+
* Returns true when EITHER 30 days have elapsed since the last snapshot OR
|
|
214
|
+
* 5+ PRs have merged since then, AND the merge floor in
|
|
215
|
+
* {@link STRATEGY_MIN_PRS} is met. The caller is responsible for calling
|
|
216
|
+
* {@link computeStrategy} when this returns true and for persisting
|
|
217
|
+
* `state.lastStrategyAt` after a successful compute.
|
|
218
|
+
*
|
|
219
|
+
* `nowIso` is injected so tests can pin time without mocking `Date`.
|
|
220
|
+
*/
|
|
221
|
+
export function shouldComputeStrategy(state, nowIso) {
|
|
222
|
+
const merged = state.mergedPRs ?? [];
|
|
223
|
+
if (merged.length < STRATEGY_MIN_PRS)
|
|
224
|
+
return false;
|
|
225
|
+
const lastIso = state.lastStrategyAt;
|
|
226
|
+
if (!lastIso)
|
|
227
|
+
return true;
|
|
228
|
+
// Time-based trigger: 30+ days since last snapshot.
|
|
229
|
+
const lastMs = Date.parse(lastIso);
|
|
230
|
+
const nowMs = Date.parse(nowIso);
|
|
231
|
+
if (Number.isFinite(lastMs) && Number.isFinite(nowMs)) {
|
|
232
|
+
const daysSince = (nowMs - lastMs) / (1000 * 60 * 60 * 24);
|
|
233
|
+
if (daysSince >= STRATEGY_CADENCE_DAYS)
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
// Unparseable timestamps — fail open and recompute rather than
|
|
238
|
+
// silently never re-firing. The lastStrategyAt write below will
|
|
239
|
+
// refresh to a valid ISO string.
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
// Merge-count trigger: count PRs merged after `lastStrategyAt`.
|
|
243
|
+
// `mergedAt` is required on StoredMergedPRSchema; `Date.parse` returns
|
|
244
|
+
// NaN for malformed-but-stored data and Number.isFinite excludes those.
|
|
245
|
+
const mergedSince = merged.filter((pr) => {
|
|
246
|
+
const mergedMs = Date.parse(pr.mergedAt);
|
|
247
|
+
return Number.isFinite(mergedMs) && mergedMs > lastMs;
|
|
248
|
+
}).length;
|
|
249
|
+
return mergedSince >= STRATEGY_CADENCE_MERGED_DELTA;
|
|
250
|
+
}
|
|
207
251
|
function deriveIssueTypePreferences(distribution) {
|
|
208
252
|
// Recommend the user's two strongest PR types — they have a track
|
|
209
253
|
// record there, so issues in those buckets are higher-yield.
|
package/dist/core/types.d.ts
CHANGED
|
@@ -19,6 +19,46 @@ export interface ClassifiedCheck {
|
|
|
19
19
|
category: CIFailureCategory;
|
|
20
20
|
conclusion?: string;
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Mutually exclusive overall-CI categories produced by
|
|
24
|
+
* {@link categorizeCIStatus} (#1272). The 5-row truth table that lived
|
|
25
|
+
* as prose in `agents/pr-health-checker.md` — extracted so any consumer
|
|
26
|
+
* (the agent, the dashboard, future MCP surfaces) reads one typed field
|
|
27
|
+
* instead of re-deriving the table.
|
|
28
|
+
*
|
|
29
|
+
* - `all_passing` — every reported check is green
|
|
30
|
+
* - `failing` — at least one actionable failure (real test/lint/build
|
|
31
|
+
* issue), OR ciStatus reported failing without per-check detail (the
|
|
32
|
+
* honest answer when the legacy combined-status endpoint can't tell
|
|
33
|
+
* us what failed)
|
|
34
|
+
* - `fork_limitation` — failures exist but ALL of them are
|
|
35
|
+
* `fork_limitation` / `auth_gate` (Vercel preview, internal CI) — purely
|
|
36
|
+
* informational
|
|
37
|
+
* - `blocked` — checks are pending (awaiting trigger / completion), OR
|
|
38
|
+
* non-actionable failures include `infrastructure` (cancelled /
|
|
39
|
+
* timed-out runner — re-running often resolves)
|
|
40
|
+
* - `not_running` — no checks reported
|
|
41
|
+
*/
|
|
42
|
+
export type CIStatusCategory = 'all_passing' | 'failing' | 'fork_limitation' | 'blocked' | 'not_running';
|
|
43
|
+
/**
|
|
44
|
+
* Suggested action for the {@link CIStatusCategorization}. Hint, not
|
|
45
|
+
* enforcement — the consuming agent may still escalate or skip based on
|
|
46
|
+
* other PR context.
|
|
47
|
+
*/
|
|
48
|
+
export type CIStatusAction = 'none' | 'investigate' | 'request_rerun' | 'check_workflows' | 'informational';
|
|
49
|
+
/**
|
|
50
|
+
* Aggregate CI status produced by {@link categorizeCIStatus} (#1272).
|
|
51
|
+
* Derived from `ciStatus + failingCheckNames + classifiedChecks` —
|
|
52
|
+
* exposed on {@link FetchedPR} so agents read a single field instead
|
|
53
|
+
* of re-implementing the truth table.
|
|
54
|
+
*/
|
|
55
|
+
export interface CIStatusCategorization {
|
|
56
|
+
category: CIStatusCategory;
|
|
57
|
+
/** Short human-readable summary suitable for inline display. */
|
|
58
|
+
summary: string;
|
|
59
|
+
/** Suggested next action (hint, not enforcement). */
|
|
60
|
+
action: CIStatusAction;
|
|
61
|
+
}
|
|
22
62
|
/** CI status result returned by getCIStatus(). */
|
|
23
63
|
export interface CIStatusResult {
|
|
24
64
|
status: CIStatus;
|
|
@@ -115,6 +155,15 @@ export interface FetchedPR {
|
|
|
115
155
|
failingCheckNames: string[];
|
|
116
156
|
/** Failing checks with category classification (#81). Separates actionable failures from fork limitations and auth gates. */
|
|
117
157
|
classifiedChecks: ClassifiedCheck[];
|
|
158
|
+
/**
|
|
159
|
+
* Aggregate 5-state CI categorization (#1272). Derived from `ciStatus`,
|
|
160
|
+
* `failingCheckNames`, and `classifiedChecks` via `categorizeCIStatus()`
|
|
161
|
+
* — agents read this directly instead of re-deriving the truth table.
|
|
162
|
+
* Always populated on a fresh fetch (v2 architecture has no cached
|
|
163
|
+
* `FetchedPR` to migrate); pr-monitor's `fetchPRDetails` sets it on
|
|
164
|
+
* every PR before construction.
|
|
165
|
+
*/
|
|
166
|
+
ciCategorization: CIStatusCategorization;
|
|
118
167
|
hasMergeConflict: boolean;
|
|
119
168
|
reviewDecision: ReviewDecision;
|
|
120
169
|
/** How many commits the PR branch is behind the base branch. */
|
|
@@ -97,6 +97,13 @@ export interface DailyOutput {
|
|
|
97
97
|
* on clean runs. See #1042.
|
|
98
98
|
*/
|
|
99
99
|
warnings: DailyWarning[];
|
|
100
|
+
/**
|
|
101
|
+
* Periodic contribution-strategy snapshot (#1270). Populated when the
|
|
102
|
+
* cadence trigger fires AND the user has crossed the merge floor. The
|
|
103
|
+
* `/oss` action menu renders this inline ahead of the action options;
|
|
104
|
+
* absent or null on runs where the gate stays silent.
|
|
105
|
+
*/
|
|
106
|
+
strategySummary?: import('../core/strategy.js').StrategyResult | null;
|
|
100
107
|
}
|
|
101
108
|
/**
|
|
102
109
|
* Compact version of DailyOutput for reduced JSON payload size (#763).
|
|
@@ -122,6 +129,8 @@ export interface CompactDailyOutput {
|
|
|
122
129
|
* the `--compact` payload. See #1042.
|
|
123
130
|
*/
|
|
124
131
|
warnings: DailyWarning[];
|
|
132
|
+
/** Periodic strategy snapshot, threaded through compact mode for parity. See {@link DailyOutput.strategySummary}. */
|
|
133
|
+
strategySummary?: import('../core/strategy.js').StrategyResult | null;
|
|
125
134
|
}
|
|
126
135
|
/**
|
|
127
136
|
* Strip a full DailyOutput down to the compact subset (#763).
|
|
@@ -275,6 +284,50 @@ export declare const DailyOutputSchema: z.ZodObject<{
|
|
|
275
284
|
timestamp: z.ZodOptional<z.ZodString>;
|
|
276
285
|
details: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
277
286
|
}, z.core.$strip>>;
|
|
287
|
+
strategySummary: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
288
|
+
profile: z.ZodObject<{
|
|
289
|
+
style: z.ZodEnum<{
|
|
290
|
+
maintainer: "maintainer";
|
|
291
|
+
explorer: "explorer";
|
|
292
|
+
specialist: "specialist";
|
|
293
|
+
generalist: "generalist";
|
|
294
|
+
}>;
|
|
295
|
+
totalPRs: z.ZodNumber;
|
|
296
|
+
mergedCount: z.ZodNumber;
|
|
297
|
+
mergeRate: z.ZodNumber;
|
|
298
|
+
primaryLanguages: z.ZodArray<z.ZodString>;
|
|
299
|
+
favoriteRepos: z.ZodArray<z.ZodString>;
|
|
300
|
+
}, z.core.$loose>;
|
|
301
|
+
capacity: z.ZodObject<{
|
|
302
|
+
openPRCount: z.ZodNumber;
|
|
303
|
+
dormantPRCount: z.ZodNumber;
|
|
304
|
+
dormantRepoCount: z.ZodNumber;
|
|
305
|
+
overExtended: z.ZodBoolean;
|
|
306
|
+
suggestedAction: z.ZodUnion<readonly [z.ZodLiteral<"open_more">, z.ZodLiteral<"follow_up_dormant">, z.ZodLiteral<"wait_on_maintainers">, z.ZodNull]>;
|
|
307
|
+
}, z.core.$loose>;
|
|
308
|
+
patterns: z.ZodObject<{
|
|
309
|
+
prTypeDistribution: z.ZodObject<{
|
|
310
|
+
docs: z.ZodNumber;
|
|
311
|
+
fixes: z.ZodNumber;
|
|
312
|
+
features: z.ZodNumber;
|
|
313
|
+
refactors: z.ZodNumber;
|
|
314
|
+
tests: z.ZodNumber;
|
|
315
|
+
other: z.ZodNumber;
|
|
316
|
+
}, z.core.$loose>;
|
|
317
|
+
trajectoryDirection: z.ZodEnum<{
|
|
318
|
+
growing: "growing";
|
|
319
|
+
steady: "steady";
|
|
320
|
+
declining: "declining";
|
|
321
|
+
}>;
|
|
322
|
+
averagePRSize: z.ZodNumber;
|
|
323
|
+
}, z.core.$loose>;
|
|
324
|
+
recommendations: z.ZodObject<{
|
|
325
|
+
languages: z.ZodArray<z.ZodString>;
|
|
326
|
+
repos: z.ZodArray<z.ZodString>;
|
|
327
|
+
issueTypes: z.ZodArray<z.ZodString>;
|
|
328
|
+
avoidPatterns: z.ZodArray<z.ZodString>;
|
|
329
|
+
}, z.core.$loose>;
|
|
330
|
+
}, z.core.$loose>>>;
|
|
278
331
|
}, z.core.$strip>;
|
|
279
332
|
export declare const CompactDailyOutputSchema: z.ZodObject<{
|
|
280
333
|
digest: z.ZodObject<{
|
|
@@ -371,6 +424,50 @@ export declare const CompactDailyOutputSchema: z.ZodObject<{
|
|
|
371
424
|
timestamp: z.ZodOptional<z.ZodString>;
|
|
372
425
|
details: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
373
426
|
}, z.core.$strip>>;
|
|
427
|
+
strategySummary: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
428
|
+
profile: z.ZodObject<{
|
|
429
|
+
style: z.ZodEnum<{
|
|
430
|
+
maintainer: "maintainer";
|
|
431
|
+
explorer: "explorer";
|
|
432
|
+
specialist: "specialist";
|
|
433
|
+
generalist: "generalist";
|
|
434
|
+
}>;
|
|
435
|
+
totalPRs: z.ZodNumber;
|
|
436
|
+
mergedCount: z.ZodNumber;
|
|
437
|
+
mergeRate: z.ZodNumber;
|
|
438
|
+
primaryLanguages: z.ZodArray<z.ZodString>;
|
|
439
|
+
favoriteRepos: z.ZodArray<z.ZodString>;
|
|
440
|
+
}, z.core.$loose>;
|
|
441
|
+
capacity: z.ZodObject<{
|
|
442
|
+
openPRCount: z.ZodNumber;
|
|
443
|
+
dormantPRCount: z.ZodNumber;
|
|
444
|
+
dormantRepoCount: z.ZodNumber;
|
|
445
|
+
overExtended: z.ZodBoolean;
|
|
446
|
+
suggestedAction: z.ZodUnion<readonly [z.ZodLiteral<"open_more">, z.ZodLiteral<"follow_up_dormant">, z.ZodLiteral<"wait_on_maintainers">, z.ZodNull]>;
|
|
447
|
+
}, z.core.$loose>;
|
|
448
|
+
patterns: z.ZodObject<{
|
|
449
|
+
prTypeDistribution: z.ZodObject<{
|
|
450
|
+
docs: z.ZodNumber;
|
|
451
|
+
fixes: z.ZodNumber;
|
|
452
|
+
features: z.ZodNumber;
|
|
453
|
+
refactors: z.ZodNumber;
|
|
454
|
+
tests: z.ZodNumber;
|
|
455
|
+
other: z.ZodNumber;
|
|
456
|
+
}, z.core.$loose>;
|
|
457
|
+
trajectoryDirection: z.ZodEnum<{
|
|
458
|
+
growing: "growing";
|
|
459
|
+
steady: "steady";
|
|
460
|
+
declining: "declining";
|
|
461
|
+
}>;
|
|
462
|
+
averagePRSize: z.ZodNumber;
|
|
463
|
+
}, z.core.$loose>;
|
|
464
|
+
recommendations: z.ZodObject<{
|
|
465
|
+
languages: z.ZodArray<z.ZodString>;
|
|
466
|
+
repos: z.ZodArray<z.ZodString>;
|
|
467
|
+
issueTypes: z.ZodArray<z.ZodString>;
|
|
468
|
+
avoidPatterns: z.ZodArray<z.ZodString>;
|
|
469
|
+
}, z.core.$loose>;
|
|
470
|
+
}, z.core.$loose>>>;
|
|
374
471
|
}, z.core.$strip>;
|
|
375
472
|
export declare const SearchOutputSchema: z.ZodObject<{
|
|
376
473
|
candidates: z.ZodArray<z.ZodObject<{
|
|
@@ -454,6 +551,14 @@ export declare const ListMoveTierOutputSchema: z.ZodObject<{
|
|
|
454
551
|
count: z.ZodNumber;
|
|
455
552
|
reason: z.ZodOptional<z.ZodString>;
|
|
456
553
|
}, z.core.$strip>;
|
|
554
|
+
export declare const ListMarkDoneOutputSchema: z.ZodObject<{
|
|
555
|
+
marked: z.ZodBoolean;
|
|
556
|
+
filePath: z.ZodString;
|
|
557
|
+
url: z.ZodString;
|
|
558
|
+
repoHeadingStruck: z.ZodBoolean;
|
|
559
|
+
remainingUnderRepo: z.ZodNumber;
|
|
560
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
561
|
+
}, z.core.$strip>;
|
|
457
562
|
export declare const PostOutputSchema: z.ZodObject<{
|
|
458
563
|
commentUrl: z.ZodString;
|
|
459
564
|
url: z.ZodString;
|
package/dist/formatters/json.js
CHANGED
|
@@ -30,6 +30,7 @@ export function toCompactDailyOutput(output) {
|
|
|
30
30
|
commentedIssues: output.commentedIssues,
|
|
31
31
|
failureCount: output.failures.length,
|
|
32
32
|
warnings: output.warnings,
|
|
33
|
+
strategySummary: output.strategySummary,
|
|
33
34
|
};
|
|
34
35
|
}
|
|
35
36
|
/**
|
|
@@ -198,6 +199,65 @@ const CompactRepoGroupSchema = z.object({
|
|
|
198
199
|
});
|
|
199
200
|
// DailyWarning schemas were hoisted above StatusOutputSchema (#1193) so the
|
|
200
201
|
// status output can reference them without `z.lazy()`.
|
|
202
|
+
// Mirrors {@link StrategyResult} in core/strategy.ts. Kept passthrough on the
|
|
203
|
+
// inner objects so additive shape changes there don't break Zod validation
|
|
204
|
+
// before the schema catches up — drift on required keys still fails.
|
|
205
|
+
const StrategyResultSchema = z
|
|
206
|
+
.object({
|
|
207
|
+
profile: z
|
|
208
|
+
.object({
|
|
209
|
+
style: z.enum(['maintainer', 'explorer', 'specialist', 'generalist']),
|
|
210
|
+
totalPRs: z.number().int().nonnegative(),
|
|
211
|
+
mergedCount: z.number().int().nonnegative(),
|
|
212
|
+
mergeRate: z.number(),
|
|
213
|
+
primaryLanguages: z.array(z.string()),
|
|
214
|
+
favoriteRepos: z.array(z.string()),
|
|
215
|
+
})
|
|
216
|
+
.passthrough(),
|
|
217
|
+
capacity: z
|
|
218
|
+
.object({
|
|
219
|
+
openPRCount: z.number().int().nonnegative(),
|
|
220
|
+
dormantPRCount: z.number().int().nonnegative(),
|
|
221
|
+
dormantRepoCount: z.number().int().nonnegative(),
|
|
222
|
+
overExtended: z.boolean(),
|
|
223
|
+
suggestedAction: z.union([
|
|
224
|
+
z.literal('open_more'),
|
|
225
|
+
z.literal('follow_up_dormant'),
|
|
226
|
+
z.literal('wait_on_maintainers'),
|
|
227
|
+
z.null(),
|
|
228
|
+
]),
|
|
229
|
+
})
|
|
230
|
+
.passthrough(),
|
|
231
|
+
patterns: z
|
|
232
|
+
.object({
|
|
233
|
+
// Closed set on the six required PR-type buckets — drift on any
|
|
234
|
+
// of these breaks the snapshot rendering. `.passthrough()` allows
|
|
235
|
+
// additive growth (e.g., a future 'security' bucket) without a
|
|
236
|
+
// schema bump, but a typo on `features` → `feauters` fails here.
|
|
237
|
+
prTypeDistribution: z
|
|
238
|
+
.object({
|
|
239
|
+
docs: z.number(),
|
|
240
|
+
fixes: z.number(),
|
|
241
|
+
features: z.number(),
|
|
242
|
+
refactors: z.number(),
|
|
243
|
+
tests: z.number(),
|
|
244
|
+
other: z.number(),
|
|
245
|
+
})
|
|
246
|
+
.passthrough(),
|
|
247
|
+
trajectoryDirection: z.enum(['growing', 'steady', 'declining']),
|
|
248
|
+
averagePRSize: z.number(),
|
|
249
|
+
})
|
|
250
|
+
.passthrough(),
|
|
251
|
+
recommendations: z
|
|
252
|
+
.object({
|
|
253
|
+
languages: z.array(z.string()),
|
|
254
|
+
repos: z.array(z.string()),
|
|
255
|
+
issueTypes: z.array(z.string()),
|
|
256
|
+
avoidPatterns: z.array(z.string()),
|
|
257
|
+
})
|
|
258
|
+
.passthrough(),
|
|
259
|
+
})
|
|
260
|
+
.passthrough();
|
|
201
261
|
export const DailyOutputSchema = z.object({
|
|
202
262
|
digest: DailyDigestCompactSchema,
|
|
203
263
|
capacity: CapacityAssessmentSchema,
|
|
@@ -209,6 +269,7 @@ export const DailyOutputSchema = z.object({
|
|
|
209
269
|
repoGroups: z.array(CompactRepoGroupSchema),
|
|
210
270
|
failures: z.array(PRCheckFailurePassthroughSchema),
|
|
211
271
|
warnings: z.array(DailyWarningSchema),
|
|
272
|
+
strategySummary: StrategyResultSchema.nullable().optional(),
|
|
212
273
|
});
|
|
213
274
|
export const CompactDailyOutputSchema = z.object({
|
|
214
275
|
digest: DailyDigestCompactSchema,
|
|
@@ -219,6 +280,7 @@ export const CompactDailyOutputSchema = z.object({
|
|
|
219
280
|
commentedIssues: z.array(CommentedIssuePassthroughSchema),
|
|
220
281
|
failureCount: z.number().int().nonnegative(),
|
|
221
282
|
warnings: z.array(DailyWarningSchema),
|
|
283
|
+
strategySummary: StrategyResultSchema.nullable().optional(),
|
|
222
284
|
});
|
|
223
285
|
// ── Search output schema (#1147) ─────────────────────────────────────
|
|
224
286
|
const SearchPrioritySchema = z.enum(['merged_pr', 'preferred_org', 'starred', 'normal']);
|
|
@@ -287,6 +349,18 @@ export const ListMoveTierOutputSchema = z.object({
|
|
|
287
349
|
count: z.number().int().nonnegative(),
|
|
288
350
|
reason: z.string().optional(),
|
|
289
351
|
});
|
|
352
|
+
// list-mark-done (#1299): mirrors {@link MarkDoneOutput} from the command
|
|
353
|
+
// module. Strict shape — additional keys must be added here AND in the
|
|
354
|
+
// command output, otherwise the validator's `parse()` rejects the response
|
|
355
|
+
// before it reaches consumers.
|
|
356
|
+
export const ListMarkDoneOutputSchema = z.object({
|
|
357
|
+
marked: z.boolean(),
|
|
358
|
+
filePath: z.string(),
|
|
359
|
+
url: z.string(),
|
|
360
|
+
repoHeadingStruck: z.boolean(),
|
|
361
|
+
remainingUnderRepo: z.number().int().nonnegative(),
|
|
362
|
+
reason: z.string().optional(),
|
|
363
|
+
});
|
|
290
364
|
// ── #1155: Zod coverage for remaining CLI commands ───────────────────
|
|
291
365
|
export const PostOutputSchema = z.object({
|
|
292
366
|
commentUrl: z.string(),
|