@oss-autopilot/core 3.12.0 → 3.13.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 +11 -11
- package/dist/cli.bundle.cjs +51 -51
- package/dist/commands/list-mark-done.d.ts +9 -1
- package/dist/commands/list-mark-done.js +14 -1
- package/dist/commands/search.d.ts +8 -0
- package/dist/commands/search.js +10 -0
- package/dist/formatters/json.d.ts +10 -1
- package/dist/formatters/json.js +7 -1
- package/package.json +1 -1
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* list-mark-done command (#1299).
|
|
3
3
|
*
|
|
4
|
+
* A URL that is not in the list at all is an error (#1406) — marking done
|
|
5
|
+
* requires an existing entry; only the already-marked re-run is a quiet no-op.
|
|
6
|
+
*
|
|
4
7
|
* Mark an issue line in a curated list as done by wrapping it in
|
|
5
8
|
* `~~strikethrough~~` and appending a `**Done** — PR [#N](url) ...` sub-bullet.
|
|
6
9
|
* If every issue under the same `### repo/name` heading is now struck through,
|
|
@@ -19,7 +22,8 @@ export interface MarkDoneOptions {
|
|
|
19
22
|
listPath: string;
|
|
20
23
|
}
|
|
21
24
|
export interface MarkDoneOutput {
|
|
22
|
-
/** True if the line was found and updated. False
|
|
25
|
+
/** True if the line was found and updated. False only when already marked
|
|
26
|
+
* done — a URL missing from the list entirely throws instead (#1406). */
|
|
23
27
|
marked: boolean;
|
|
24
28
|
/** Fully-resolved file path that was inspected. */
|
|
25
29
|
filePath: string;
|
|
@@ -32,6 +36,8 @@ export interface MarkDoneOutput {
|
|
|
32
36
|
/** Human-readable explanation when `marked` is false. */
|
|
33
37
|
reason?: string;
|
|
34
38
|
}
|
|
39
|
+
/** Discriminates the two `marked: false` outcomes of {@link markIssueAsDone}. */
|
|
40
|
+
export type MarkDoneNoOpReason = 'not-found' | 'already-marked';
|
|
35
41
|
/** Pure transform — exposed for unit testing. */
|
|
36
42
|
export declare function markIssueAsDone(content: string, opts: {
|
|
37
43
|
issueUrl: string;
|
|
@@ -43,6 +49,8 @@ export declare function markIssueAsDone(content: string, opts: {
|
|
|
43
49
|
repoHeadingStruck: boolean;
|
|
44
50
|
remainingUnderRepo: number;
|
|
45
51
|
reason?: string;
|
|
52
|
+
/** Set only when `marked` is false — why nothing changed. */
|
|
53
|
+
reasonCode?: MarkDoneNoOpReason;
|
|
46
54
|
};
|
|
47
55
|
/** Read → transform → write atomically (tmp + rename) so a crash mid-write can't corrupt the file. */
|
|
48
56
|
export declare function runMarkIssueListItemDone(options: MarkDoneOptions): Promise<MarkDoneOutput>;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* list-mark-done command (#1299).
|
|
3
3
|
*
|
|
4
|
+
* A URL that is not in the list at all is an error (#1406) — marking done
|
|
5
|
+
* requires an existing entry; only the already-marked re-run is a quiet no-op.
|
|
6
|
+
*
|
|
4
7
|
* Mark an issue line in a curated list as done by wrapping it in
|
|
5
8
|
* `~~strikethrough~~` and appending a `**Done** — PR [#N](url) ...` sub-bullet.
|
|
6
9
|
* If every issue under the same `### repo/name` heading is now struck through,
|
|
@@ -13,7 +16,7 @@
|
|
|
13
16
|
*/
|
|
14
17
|
import * as fs from 'node:fs';
|
|
15
18
|
import * as path from 'node:path';
|
|
16
|
-
import { errorMessage } from '../core/errors.js';
|
|
19
|
+
import { errorMessage, ValidationError } from '../core/errors.js';
|
|
17
20
|
const STRIKE = '~~';
|
|
18
21
|
const DONE_PREFIX = ' - **Done**';
|
|
19
22
|
const ISSUE_LINE_RE = /^[*+-]\s/;
|
|
@@ -113,6 +116,7 @@ export function markIssueAsDone(content, opts) {
|
|
|
113
116
|
repoHeadingStruck: false,
|
|
114
117
|
remainingUnderRepo: 0,
|
|
115
118
|
reason: 'issue URL not found in the list',
|
|
119
|
+
reasonCode: 'not-found',
|
|
116
120
|
};
|
|
117
121
|
}
|
|
118
122
|
const issueLine = lines[block.start];
|
|
@@ -126,6 +130,7 @@ export function markIssueAsDone(content, opts) {
|
|
|
126
130
|
repoHeadingStruck: false,
|
|
127
131
|
remainingUnderRepo: section ? countOpenIssues(lines, section) : 0,
|
|
128
132
|
reason: 'already marked done',
|
|
133
|
+
reasonCode: 'already-marked',
|
|
129
134
|
};
|
|
130
135
|
}
|
|
131
136
|
// 1. Strike the issue line.
|
|
@@ -186,6 +191,14 @@ export async function runMarkIssueListItemDone(options) {
|
|
|
186
191
|
prUrl: options.prUrl,
|
|
187
192
|
prStatus: options.prStatus,
|
|
188
193
|
});
|
|
194
|
+
// #1406: a missing entry is a caller error, not a quiet success — the
|
|
195
|
+
// consumer branch in workflows/draft-first-workflow.md already documents
|
|
196
|
+
// this contract (STOP on success:false mentioning "Issue URL not found").
|
|
197
|
+
// Idempotent re-runs (already marked done) still resolve normally.
|
|
198
|
+
if (result.reasonCode === 'not-found') {
|
|
199
|
+
throw new ValidationError(`Issue URL not found in the list: ${options.issueUrl} (${filePath}). ` +
|
|
200
|
+
'Check the URL and --list-path; the entry must exist before it can be marked done.');
|
|
201
|
+
}
|
|
189
202
|
if (result.marked) {
|
|
190
203
|
const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
191
204
|
try {
|
|
@@ -10,6 +10,14 @@ export { type SearchOutput } from '../formatters/json.js';
|
|
|
10
10
|
* lands in one place instead of three (#1002).
|
|
11
11
|
*/
|
|
12
12
|
export declare const MAX_SEARCH_RESULTS = 100;
|
|
13
|
+
/**
|
|
14
|
+
* Fraction of search slots reserved for candidates that matched neither
|
|
15
|
+
* strategy-preferred languages nor repos (#1244). Counterweight against
|
|
16
|
+
* echo-chamber bias: without it, strategy-boosted searches return more of
|
|
17
|
+
* what already merged, which merges more of the same, and the profile
|
|
18
|
+
* narrows over time. Scout clamps to [0, 1]; 0.2 is the issue's proposal.
|
|
19
|
+
*/
|
|
20
|
+
export declare const SEARCH_DIVERSITY_RATIO = 0.2;
|
|
13
21
|
interface SearchOptions {
|
|
14
22
|
maxResults: number;
|
|
15
23
|
}
|
package/dist/commands/search.js
CHANGED
|
@@ -14,6 +14,14 @@ const MODULE = 'search';
|
|
|
14
14
|
* lands in one place instead of three (#1002).
|
|
15
15
|
*/
|
|
16
16
|
export const MAX_SEARCH_RESULTS = 100;
|
|
17
|
+
/**
|
|
18
|
+
* Fraction of search slots reserved for candidates that matched neither
|
|
19
|
+
* strategy-preferred languages nor repos (#1244). Counterweight against
|
|
20
|
+
* echo-chamber bias: without it, strategy-boosted searches return more of
|
|
21
|
+
* what already merged, which merges more of the same, and the profile
|
|
22
|
+
* narrows over time. Scout clamps to [0, 1]; 0.2 is the issue's proposal.
|
|
23
|
+
*/
|
|
24
|
+
export const SEARCH_DIVERSITY_RATIO = 0.2;
|
|
17
25
|
/**
|
|
18
26
|
* Search GitHub for contributable issues using multi-phase discovery.
|
|
19
27
|
*
|
|
@@ -63,6 +71,7 @@ export async function runSearch(options) {
|
|
|
63
71
|
maxResults: options.maxResults,
|
|
64
72
|
preferLanguages,
|
|
65
73
|
preferRepos,
|
|
74
|
+
diversityRatio: SEARCH_DIVERSITY_RATIO,
|
|
66
75
|
});
|
|
67
76
|
// #1354: never surface issues the user already has an open PR for. Uses
|
|
68
77
|
// scout's structured linked-PR metadata when present; candidates without it
|
|
@@ -128,6 +137,7 @@ export async function runSearch(options) {
|
|
|
128
137
|
...(linkedPR ? { linkedPR } : {}),
|
|
129
138
|
...(typeof c.boostScore === 'number' ? { boostScore: c.boostScore } : {}),
|
|
130
139
|
...(c.boostReasons && c.boostReasons.length > 0 ? { boostReasons: c.boostReasons } : {}),
|
|
140
|
+
...(c.diversitySlot === true ? { diversitySlot: true } : {}),
|
|
131
141
|
};
|
|
132
142
|
}),
|
|
133
143
|
excludedRepos: result.excludedRepos,
|
|
@@ -648,6 +648,7 @@ export declare const SearchOutputSchema: z.ZodObject<{
|
|
|
648
648
|
}, z.core.$strip>>;
|
|
649
649
|
boostScore: z.ZodOptional<z.ZodNumber>;
|
|
650
650
|
boostReasons: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
651
|
+
diversitySlot: z.ZodOptional<z.ZodBoolean>;
|
|
651
652
|
}, z.core.$strip>>;
|
|
652
653
|
excludedRepos: z.ZodArray<z.ZodString>;
|
|
653
654
|
aiPolicyBlocklist: z.ZodArray<z.ZodString>;
|
|
@@ -707,6 +708,7 @@ export declare const FeaturesOutputSchema: z.ZodObject<{
|
|
|
707
708
|
}, z.core.$strip>>;
|
|
708
709
|
boostScore: z.ZodOptional<z.ZodNumber>;
|
|
709
710
|
boostReasons: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
711
|
+
diversitySlot: z.ZodOptional<z.ZodBoolean>;
|
|
710
712
|
horizon: z.ZodEnum<{
|
|
711
713
|
"quick-win": "quick-win";
|
|
712
714
|
"bigger-bet": "bigger-bet";
|
|
@@ -764,6 +766,7 @@ export declare const FeaturesOutputSchema: z.ZodObject<{
|
|
|
764
766
|
}, z.core.$strip>>;
|
|
765
767
|
boostScore: z.ZodOptional<z.ZodNumber>;
|
|
766
768
|
boostReasons: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
769
|
+
diversitySlot: z.ZodOptional<z.ZodBoolean>;
|
|
767
770
|
horizon: z.ZodEnum<{
|
|
768
771
|
"quick-win": "quick-win";
|
|
769
772
|
"bigger-bet": "bigger-bet";
|
|
@@ -816,7 +819,7 @@ export declare const ListMarkDoneOutputSchema: z.ZodObject<{
|
|
|
816
819
|
url: z.ZodString;
|
|
817
820
|
repoHeadingStruck: z.ZodBoolean;
|
|
818
821
|
remainingUnderRepo: z.ZodNumber;
|
|
819
|
-
reason: z.ZodOptional<z.
|
|
822
|
+
reason: z.ZodOptional<z.ZodLiteral<"already marked done">>;
|
|
820
823
|
}, z.core.$strip>;
|
|
821
824
|
export declare const VerifyIssueOutputSchema: z.ZodObject<{
|
|
822
825
|
url: z.ZodString;
|
|
@@ -1216,6 +1219,12 @@ export interface SearchCandidate {
|
|
|
1216
1219
|
* opportunities (open PR + no updates for 30+ days, scout 0.9.0 #97).
|
|
1217
1220
|
*/
|
|
1218
1221
|
linkedPR?: CandidateLinkedPR;
|
|
1222
|
+
/** Strategy-bias sort boost from scout (#1244); absent when unboosted. */
|
|
1223
|
+
boostScore?: number;
|
|
1224
|
+
/** Human-readable boost explanations, e.g. "repo affinity: vercel/next.js". */
|
|
1225
|
+
boostReasons?: string[];
|
|
1226
|
+
/** True when this candidate filled a diversity slot (#1244). */
|
|
1227
|
+
diversitySlot?: boolean;
|
|
1219
1228
|
}
|
|
1220
1229
|
export interface SearchOutput {
|
|
1221
1230
|
candidates: SearchCandidate[];
|
package/dist/formatters/json.js
CHANGED
|
@@ -353,6 +353,9 @@ const SearchCandidateSchema = z.object({
|
|
|
353
353
|
*/
|
|
354
354
|
boostScore: z.number().optional(),
|
|
355
355
|
boostReasons: z.array(z.string()).optional(),
|
|
356
|
+
/** True when this candidate filled a diversity slot (#1244) — surfaced so
|
|
357
|
+
* the user can see the counterweight working, not just its absence. */
|
|
358
|
+
diversitySlot: z.boolean().optional(),
|
|
356
359
|
});
|
|
357
360
|
export const SearchOutputSchema = z.object({
|
|
358
361
|
candidates: z.array(SearchCandidateSchema),
|
|
@@ -421,7 +424,10 @@ export const ListMarkDoneOutputSchema = z.object({
|
|
|
421
424
|
url: z.string(),
|
|
422
425
|
repoHeadingStruck: z.boolean(),
|
|
423
426
|
remainingUnderRepo: z.number().int().nonnegative(),
|
|
424
|
-
|
|
427
|
+
// #1406: not-found now throws before the success envelope, so the only
|
|
428
|
+
// reachable no-op reason is the idempotent one. Pinned so a new quiet
|
|
429
|
+
// no-op path trips the #1105 runtime validator instead of shipping silently.
|
|
430
|
+
reason: z.literal('already marked done').optional(),
|
|
425
431
|
});
|
|
426
432
|
// verify-issue (#1353, #1354): mirrors {@link IssueVerification} from
|
|
427
433
|
// core/issue-verification.ts. Strict shape — additional keys must be added
|