@oss-autopilot/core 3.7.0 → 3.9.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.
@@ -21,6 +21,8 @@ export { executeDailyCheck } from './daily.js';
21
21
  export { runStartup } from './startup.js';
22
22
  /** Return contribution statistics (merge rate, PR counts, repo breakdown) from local state. */
23
23
  export { runStatus } from './status.js';
24
+ /** On-demand strategy snapshot via the typed `computeStrategy` core function (#1243 step 4). */
25
+ export { runStrategy } from './strategy.js';
24
26
  /** Search GitHub for contributable issues using multi-strategy discovery. */
25
27
  export { runSearch, MAX_SEARCH_RESULTS } from './search.js';
26
28
  /** Surface feature-scoped opportunities in repos with 3+ merged PRs (scout 0.9.0). */
@@ -22,6 +22,8 @@ export { executeDailyCheck } from './daily.js';
22
22
  export { runStartup } from './startup.js';
23
23
  /** Return contribution statistics (merge rate, PR counts, repo breakdown) from local state. */
24
24
  export { runStatus } from './status.js';
25
+ /** On-demand strategy snapshot via the typed `computeStrategy` core function (#1243 step 4). */
26
+ export { runStrategy } from './strategy.js';
25
27
  /** Search GitHub for contributable issues using multi-strategy discovery. */
26
28
  export { runSearch, MAX_SEARCH_RESULTS } from './search.js';
27
29
  /** Surface feature-scoped opportunities in repos with 3+ merged PRs (scout 0.9.0). */
@@ -0,0 +1,31 @@
1
+ /**
2
+ * strategy command (#1243 step 4).
3
+ *
4
+ * Runs the typed `computeStrategy` core function against local state on
5
+ * demand. The daily auto-display already emits `strategySummary` under
6
+ * a cadence gate; this command is the *ungated* path used by the
7
+ * `contribution-strategist` agent so a user asking "how am I doing?"
8
+ * always gets an answer (or a clear "not enough data yet" message) even
9
+ * when the daily cadence has not fired.
10
+ *
11
+ * Read-only: no API calls, no state mutation.
12
+ */
13
+ import { type StrategyResult } from '../core/strategy.js';
14
+ /**
15
+ * On-demand strategy snapshot. Mirrors `StrategyOutputSchema` in
16
+ * `formatters/json.ts` structurally — that schema uses `.passthrough()`
17
+ * for forward compatibility on the JSON-validation surface, so its
18
+ * inferred type carries an extra `unknown` index signature that does
19
+ * not match `StrategyResult`. The command's TypeScript shape is the
20
+ * exact structural form below.
21
+ */
22
+ export interface StrategyCommandOutput {
23
+ strategy: StrategyResult | null;
24
+ message?: string;
25
+ }
26
+ /**
27
+ * Compute the on-demand strategy snapshot. Returns `{ strategy: null,
28
+ * message }` when state is below the merged-PR floor, and `{ strategy }`
29
+ * with the full typed result otherwise.
30
+ */
31
+ export declare function runStrategy(): Promise<StrategyCommandOutput>;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * strategy command (#1243 step 4).
3
+ *
4
+ * Runs the typed `computeStrategy` core function against local state on
5
+ * demand. The daily auto-display already emits `strategySummary` under
6
+ * a cadence gate; this command is the *ungated* path used by the
7
+ * `contribution-strategist` agent so a user asking "how am I doing?"
8
+ * always gets an answer (or a clear "not enough data yet" message) even
9
+ * when the daily cadence has not fired.
10
+ *
11
+ * Read-only: no API calls, no state mutation.
12
+ */
13
+ import { getStateManager } from '../core/index.js';
14
+ import { computeStrategy, STRATEGY_MIN_PRS } from '../core/strategy.js';
15
+ /**
16
+ * Compute the on-demand strategy snapshot. Returns `{ strategy: null,
17
+ * message }` when state is below the merged-PR floor, and `{ strategy }`
18
+ * with the full typed result otherwise.
19
+ */
20
+ export async function runStrategy() {
21
+ const stateManager = getStateManager();
22
+ const state = stateManager.getState();
23
+ const strategy = computeStrategy(state);
24
+ if (strategy === null) {
25
+ const merged = state.mergedPRs?.length ?? 0;
26
+ return {
27
+ strategy: null,
28
+ message: `Strategy snapshot needs at least ${STRATEGY_MIN_PRS} merged PRs in local state; ` +
29
+ `currently tracking ${merged}. Keep contributing and the snapshot becomes available automatically.`,
30
+ };
31
+ }
32
+ return { strategy };
33
+ }
@@ -184,6 +184,106 @@ export declare const StatusOutputSchema: z.ZodObject<{
184
184
  }, z.core.$strip>>>;
185
185
  }, z.core.$strip>;
186
186
  export type StatusOutput = z.infer<typeof StatusOutputSchema>;
187
+ export declare const StrategyResultSchema: z.ZodObject<{
188
+ profile: z.ZodObject<{
189
+ style: z.ZodEnum<{
190
+ maintainer: "maintainer";
191
+ explorer: "explorer";
192
+ specialist: "specialist";
193
+ generalist: "generalist";
194
+ }>;
195
+ totalPRs: z.ZodNumber;
196
+ mergedCount: z.ZodNumber;
197
+ mergeRate: z.ZodNumber;
198
+ primaryLanguages: z.ZodArray<z.ZodString>;
199
+ favoriteRepos: z.ZodArray<z.ZodString>;
200
+ }, z.core.$loose>;
201
+ capacity: z.ZodObject<{
202
+ openPRCount: z.ZodNumber;
203
+ dormantPRCount: z.ZodNumber;
204
+ dormantRepoCount: z.ZodNumber;
205
+ overExtended: z.ZodBoolean;
206
+ suggestedAction: z.ZodUnion<readonly [z.ZodLiteral<"open_more">, z.ZodLiteral<"follow_up_dormant">, z.ZodLiteral<"wait_on_maintainers">, z.ZodNull]>;
207
+ }, z.core.$loose>;
208
+ patterns: z.ZodObject<{
209
+ prTypeDistribution: z.ZodObject<{
210
+ docs: z.ZodNumber;
211
+ fixes: z.ZodNumber;
212
+ features: z.ZodNumber;
213
+ refactors: z.ZodNumber;
214
+ tests: z.ZodNumber;
215
+ other: z.ZodNumber;
216
+ }, z.core.$loose>;
217
+ trajectoryDirection: z.ZodEnum<{
218
+ growing: "growing";
219
+ steady: "steady";
220
+ declining: "declining";
221
+ }>;
222
+ averagePRSize: z.ZodNumber;
223
+ }, z.core.$loose>;
224
+ recommendations: z.ZodObject<{
225
+ languages: z.ZodArray<z.ZodString>;
226
+ repos: z.ZodArray<z.ZodString>;
227
+ issueTypes: z.ZodArray<z.ZodString>;
228
+ avoidPatterns: z.ZodArray<z.ZodString>;
229
+ }, z.core.$loose>;
230
+ }, z.core.$loose>;
231
+ /**
232
+ * On-demand strategy snapshot output (#1243 step 4). Wraps the same
233
+ * `StrategyResult` shape consumed by the daily auto-display, but is
234
+ * always available — the cadence gate only governs the auto-display,
235
+ * not direct CLI/MCP calls. `strategy` is null when the minimum-data
236
+ * gate fails (fewer than `STRATEGY_MIN_PRS` merged PRs); `message`
237
+ * carries the human-readable explanation in that case.
238
+ */
239
+ export declare const StrategyOutputSchema: z.ZodObject<{
240
+ strategy: z.ZodNullable<z.ZodObject<{
241
+ profile: z.ZodObject<{
242
+ style: z.ZodEnum<{
243
+ maintainer: "maintainer";
244
+ explorer: "explorer";
245
+ specialist: "specialist";
246
+ generalist: "generalist";
247
+ }>;
248
+ totalPRs: z.ZodNumber;
249
+ mergedCount: z.ZodNumber;
250
+ mergeRate: z.ZodNumber;
251
+ primaryLanguages: z.ZodArray<z.ZodString>;
252
+ favoriteRepos: z.ZodArray<z.ZodString>;
253
+ }, z.core.$loose>;
254
+ capacity: z.ZodObject<{
255
+ openPRCount: z.ZodNumber;
256
+ dormantPRCount: z.ZodNumber;
257
+ dormantRepoCount: z.ZodNumber;
258
+ overExtended: z.ZodBoolean;
259
+ suggestedAction: z.ZodUnion<readonly [z.ZodLiteral<"open_more">, z.ZodLiteral<"follow_up_dormant">, z.ZodLiteral<"wait_on_maintainers">, z.ZodNull]>;
260
+ }, z.core.$loose>;
261
+ patterns: z.ZodObject<{
262
+ prTypeDistribution: z.ZodObject<{
263
+ docs: z.ZodNumber;
264
+ fixes: z.ZodNumber;
265
+ features: z.ZodNumber;
266
+ refactors: z.ZodNumber;
267
+ tests: z.ZodNumber;
268
+ other: z.ZodNumber;
269
+ }, z.core.$loose>;
270
+ trajectoryDirection: z.ZodEnum<{
271
+ growing: "growing";
272
+ steady: "steady";
273
+ declining: "declining";
274
+ }>;
275
+ averagePRSize: z.ZodNumber;
276
+ }, z.core.$loose>;
277
+ recommendations: z.ZodObject<{
278
+ languages: z.ZodArray<z.ZodString>;
279
+ repos: z.ZodArray<z.ZodString>;
280
+ issueTypes: z.ZodArray<z.ZodString>;
281
+ avoidPatterns: z.ZodArray<z.ZodString>;
282
+ }, z.core.$loose>;
283
+ }, z.core.$loose>>;
284
+ message: z.ZodOptional<z.ZodString>;
285
+ }, z.core.$strip>;
286
+ export type StrategyCommandOutput = z.infer<typeof StrategyOutputSchema>;
187
287
  export declare const DailyOutputSchema: z.ZodObject<{
188
288
  digest: z.ZodObject<{
189
289
  generatedAt: z.ZodString;
@@ -202,7 +202,7 @@ const CompactRepoGroupSchema = z.object({
202
202
  // Mirrors {@link StrategyResult} in core/strategy.ts. Kept passthrough on the
203
203
  // inner objects so additive shape changes there don't break Zod validation
204
204
  // before the schema catches up — drift on required keys still fails.
205
- const StrategyResultSchema = z
205
+ export const StrategyResultSchema = z
206
206
  .object({
207
207
  profile: z
208
208
  .object({
@@ -258,6 +258,18 @@ const StrategyResultSchema = z
258
258
  .passthrough(),
259
259
  })
260
260
  .passthrough();
261
+ /**
262
+ * On-demand strategy snapshot output (#1243 step 4). Wraps the same
263
+ * `StrategyResult` shape consumed by the daily auto-display, but is
264
+ * always available — the cadence gate only governs the auto-display,
265
+ * not direct CLI/MCP calls. `strategy` is null when the minimum-data
266
+ * gate fails (fewer than `STRATEGY_MIN_PRS` merged PRs); `message`
267
+ * carries the human-readable explanation in that case.
268
+ */
269
+ export const StrategyOutputSchema = z.object({
270
+ strategy: StrategyResultSchema.nullable(),
271
+ message: z.string().optional(),
272
+ });
261
273
  export const DailyOutputSchema = z.object({
262
274
  digest: DailyDigestCompactSchema,
263
275
  capacity: CapacityAssessmentSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oss-autopilot/core",
3
- "version": "3.7.0",
3
+ "version": "3.9.0",
4
4
  "description": "CLI and core library for managing open source contributions",
5
5
  "type": "module",
6
6
  "bin": {
@@ -59,13 +59,13 @@
59
59
  "zod": "^4.4.3"
60
60
  },
61
61
  "devDependencies": {
62
- "@types/node": "^25.6.0",
63
- "@vitest/coverage-v8": "^4.1.5",
62
+ "@types/node": "^25.7.0",
63
+ "@vitest/coverage-v8": "^4.1.6",
64
64
  "esbuild": "^0.28.0",
65
65
  "tsx": "^4.21.0",
66
66
  "typedoc": "^0.28.19",
67
67
  "typescript": "^5.9.3",
68
- "vitest": "^4.1.5"
68
+ "vitest": "^4.1.6"
69
69
  },
70
70
  "scripts": {
71
71
  "build": "tsc",