@reneturcios/greenlight 0.9.1 → 0.9.3
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/README.md +31 -1
- package/dist/automate.d.ts +20 -0
- package/dist/automate.js +75 -7
- package/dist/automate.js.map +1 -1
- package/dist/babysit.d.ts +1 -1
- package/dist/babysit.js +2 -2
- package/dist/babysit.js.map +1 -1
- package/dist/ci-triage.d.ts +1 -1
- package/dist/ci-triage.js +6 -0
- package/dist/ci-triage.js.map +1 -1
- package/dist/claim-health.d.ts +1 -1
- package/dist/claim-health.js +12 -0
- package/dist/claim-health.js.map +1 -1
- package/dist/claims.js +73 -20
- package/dist/claims.js.map +1 -1
- package/dist/cli.js +85 -33
- package/dist/cli.js.map +1 -1
- package/dist/friction.d.ts +12 -4
- package/dist/friction.js +45 -14
- package/dist/friction.js.map +1 -1
- package/dist/gates.d.ts +16 -0
- package/dist/gates.js +169 -4
- package/dist/gates.js.map +1 -1
- package/dist/github.d.ts +42 -1
- package/dist/github.js +163 -15
- package/dist/github.js.map +1 -1
- package/dist/help.js +4 -3
- package/dist/help.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/llm-claims.d.ts +13 -2
- package/dist/llm-claims.js +54 -17
- package/dist/llm-claims.js.map +1 -1
- package/dist/posting-ledger.d.ts +70 -0
- package/dist/posting-ledger.js +170 -0
- package/dist/posting-ledger.js.map +1 -0
- package/dist/protocol-fetch.d.ts +3 -1
- package/dist/protocol-fetch.js +10 -1
- package/dist/protocol-fetch.js.map +1 -1
- package/dist/protocol.d.ts +14 -1
- package/dist/protocol.js +34 -3
- package/dist/protocol.js.map +1 -1
- package/dist/types.d.ts +33 -0
- package/package.json +1 -1
- package/server.json +2 -2
package/dist/claim-health.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claim-health.js","sourceRoot":"","sources":["../src/claim-health.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"claim-health.js","sourceRoot":"","sources":["../src/claim-health.ts"],"names":[],"mappings":"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"}
|
package/dist/claims.js
CHANGED
|
@@ -1,22 +1,39 @@
|
|
|
1
1
|
// Strong: explicit claim of work or a concrete "I am doing it" statement.
|
|
2
2
|
const STRONG_PATTERNS = [
|
|
3
|
-
|
|
3
|
+
// "I'd like to work on this issue" — formbricks/formbricks#9504
|
|
4
|
+
// (2026-10-17): the contracted form missed the old "i would like".
|
|
5
|
+
// The trailing guard keeps "take this opportunity to ..." out, the
|
|
6
|
+
// same idiom the like-to-take pattern below protects.
|
|
7
|
+
{ name: "explicit-claim", regex: /\bi(['’]d| would) like to (work on|take|handle) (this|it)\b(?! (opportunity|moment|time) to)/i, strength: "strong" },
|
|
4
8
|
{ name: "please-assign", regex: /please assign (this|it|me)/i, strength: "strong" },
|
|
5
9
|
{ name: "assign-to-me", regex: /\bassign (it |this )?to me\b/i, strength: "strong" },
|
|
6
10
|
{ name: "assign-request", regex: /\bassign me\b/i, strength: "strong" },
|
|
7
|
-
|
|
8
|
-
|
|
11
|
+
// "If that's okay, I'll work on it and open a PR." — the same
|
|
12
|
+
// formbricks thread: "it" is as much a claim as "this". The lookahead
|
|
13
|
+
// keeps "take it into account / offline / under / as" from matching.
|
|
14
|
+
{ name: "will-take", regex: /\bi (will|shall) (take|work on|handle) (this|it)\b(?!\s+(?:into|offline|under|as|for granted)\b)/i, strength: "strong" },
|
|
15
|
+
// "It's yours @08abhinav, thanks!" — batrapulkit/squidbrake#79
|
|
16
|
+
// (2026-10-17): a maintainer handing the issue to a contributor is an
|
|
17
|
+
// assignment, the strongest taken-signal there is.
|
|
18
|
+
{ name: "its-yours", regex: /\bit(?:['’]s| is)(?: all)? yours\b/i, strength: "strong" },
|
|
19
|
+
// "I've packaged a clean, production-verified fix for this" —
|
|
20
|
+
// dubinc/dub#4659 (2026-10-17), and "I also prepared and tested a fix
|
|
21
|
+
// for this issue" — formbricks#9504's second claimant. A concrete
|
|
22
|
+
// fix-in-hand claim. The not/n't guard keeps "I have not prepared a
|
|
23
|
+
// fix" from matching.
|
|
24
|
+
{ name: "fix-packaged", regex: /\bi(?:['’]ve| have| also| just)?\s+(?!(?:not|n['’]t)\s)(?:packaged|prepared|completed|finished)\s+(?:(?:a|the|my|this)\s+)?(?:[\w.,-]+\s+){0,6}fix\b/i, strength: "strong" },
|
|
25
|
+
{ name: "working-on", regex: /i(['’]| a)m (currently |now )?working on this/i, strength: "strong" },
|
|
9
26
|
{ name: "taking-it", regex: /\btak(e|ing) this (on|up)\b/i, strength: "strong" },
|
|
10
|
-
{ name: "pr-opened", regex: /i('ve| have) opened (a |the )?pr\b/i, strength: "strong" },
|
|
27
|
+
{ name: "pr-opened", regex: /i(['’]ve| have) opened (a |the )?pr\b/i, strength: "strong" },
|
|
11
28
|
{ name: "fix-ready", regex: /\bfix (is )?ready\b/i, strength: "strong" },
|
|
12
29
|
{ name: "fix-in-progress", regex: /\bfix is in progress\b/i, strength: "strong" },
|
|
13
30
|
{ name: "pr-incoming", regex: /\bpr (is |will be |to be )?(incoming|coming|ready|prepared)\b/i, strength: "strong" },
|
|
14
|
-
{ name: "started-work", regex: /\bi('ve| have) started (working )?on this/i, strength: "strong" },
|
|
15
|
-
{ name: "want-to-work", regex: /i('d| would) like to (take|pick) (this|it) (on|up)/i, strength: "strong" },
|
|
31
|
+
{ name: "started-work", regex: /\bi(['’]ve| have) started (working )?on this/i, strength: "strong" },
|
|
32
|
+
{ name: "want-to-work", regex: /i(['’]d| would) like to (take|pick) (this|it) (on|up)/i, strength: "strong" },
|
|
16
33
|
// "Hi, I'd like to take this. Plan: ..." — the fastmcp #5743 claim (2026-10-14) that scan
|
|
17
34
|
// missed because want-to-work above demands a trailing "on"/"up". The negative lookahead
|
|
18
35
|
// keeps "I'd like to take this opportunity to thank ..." from counting as a claim.
|
|
19
|
-
{ name: "like-to-take", regex: /\bi('d| would) like to take (this|it)\b(?! (opportunity|moment|time) to)/i, strength: "strong" },
|
|
36
|
+
{ name: "like-to-take", regex: /\bi(['’]d| would) like to take (this|it)\b(?! (opportunity|moment|time) to)/i, strength: "strong" },
|
|
20
37
|
// "/attempt #1234" (or "/claim #1234") — bot-style commands some contributors post to
|
|
21
38
|
// announce they are taking the issue. tscircuit/tscircuit#5563 (2026-10-15) carried five
|
|
22
39
|
// of these from one contributor before anyone linked the actual fix PRs; without this
|
|
@@ -36,13 +53,38 @@ const STRONG_PATTERNS = [
|
|
|
36
53
|
// with a grain of salt".
|
|
37
54
|
{
|
|
38
55
|
name: "bare-take",
|
|
39
|
-
regex: /\b(?:i(?:'ll| will) take|let me take|i take|taking) (?:this|it)(?: one)?\b(?!\s+(?:[a-z][\w-]*\s+){0,2}(?:into|off(?:line)?|opportunity|opportunities|moment|time|with|under|as)\b)/i,
|
|
56
|
+
regex: /\b(?:i(?:['’]ll| will) take|let me take|i take|taking) (?:this|it)(?: one)?\b(?!\s+(?:[a-z][\w-]*\s+){0,2}(?:into|off(?:line)?|opportunity|opportunities|moment|time|with|under|as)\b)/i,
|
|
40
57
|
strength: "soft",
|
|
41
58
|
},
|
|
42
59
|
];
|
|
43
60
|
// Soft: interest or an offer, not a claim. Used only to soften confidence, not to mark TAKEN.
|
|
44
61
|
const SOFT_PATTERNS = [
|
|
45
|
-
|
|
62
|
+
// "I'd be happy to implement the proposed fix" — formbricks#9504
|
|
63
|
+
// (2026-10-17): the happy-to family missed the implementation verbs.
|
|
64
|
+
{ name: "soft-offer", regex: /\bhappy to (fix|work|help|take|implement|submit|contribute|open|review)\b/i, strength: "soft" },
|
|
65
|
+
// Bare "Working on this." — ollama/ollama#19078 (2026-10-17): the
|
|
66
|
+
// whole comment was three words. The morning eval caught it through
|
|
67
|
+
// the AI layer; with the layer down, the patterns missed it. Soft,
|
|
68
|
+
// not strong: no plan, no assignment ask. The guard rejects negations
|
|
69
|
+
// ("I'm not working on this"), non-actors ("Nobody is working on
|
|
70
|
+
// this"), and questions addressed at someone else ("Are you working
|
|
71
|
+
// on this?"). The strong working-on pattern above owns "I'm working
|
|
72
|
+
// on this" and runs first, so this never downgrades it.
|
|
73
|
+
{
|
|
74
|
+
name: "bare-working-on",
|
|
75
|
+
regex: /\bworking on (?:this|it|a fix|the fix)\b/i,
|
|
76
|
+
strength: "soft",
|
|
77
|
+
guard: (body, match) => {
|
|
78
|
+
const clause = (body.slice(0, match.index).split(/[.!?\n]/).pop() ?? "").toLowerCase();
|
|
79
|
+
if (/\b(not|n't|never|nobody|no one|none)\b/.test(clause))
|
|
80
|
+
return false;
|
|
81
|
+
if (/\bi(?:['’]m| am)\b/.test(clause))
|
|
82
|
+
return false;
|
|
83
|
+
if (/\b(you|u)\b/.test(clause))
|
|
84
|
+
return false;
|
|
85
|
+
return true;
|
|
86
|
+
},
|
|
87
|
+
},
|
|
46
88
|
{ name: "can-take", regex: /i can take this/i, strength: "soft" },
|
|
47
89
|
{ name: "interested", regex: /\binterested in (working on|taking|this)\b/i, strength: "soft" },
|
|
48
90
|
{ name: "looking-into", regex: /\blooking into this\b/i, strength: "soft" },
|
|
@@ -61,7 +103,7 @@ const SOFT_PATTERNS = [
|
|
|
61
103
|
// of place.
|
|
62
104
|
{
|
|
63
105
|
name: "pick-up-offer",
|
|
64
|
-
regex: /\b(?:i can|i(?:'ll| will)|let me|(?:can|could) i) pick (?:this|it) up\b(?!\s+(?:from|at|in|on|off|out)\b)/i,
|
|
106
|
+
regex: /\b(?:i can|i(?:['’]ll| will)|let me|(?:can|could) i) pick (?:this|it) up\b(?!\s+(?:from|at|in|on|off|out)\b)/i,
|
|
65
107
|
strength: "soft",
|
|
66
108
|
},
|
|
67
109
|
// "Can i still work on this, is this open." — the same firecrawl thread:
|
|
@@ -78,7 +120,7 @@ const PARTIAL_PATTERNS = [
|
|
|
78
120
|
{ name: "partial-taking", regex: /taking (the|this|on)\b.{0,40}?\b(ask|part|half|piece|fallback|remaining)\b/i, strength: "strong" },
|
|
79
121
|
{ name: "partial-claiming", regex: /claiming (the|this)\b.{0,30}?\b(part|half|ask)\b/i, strength: "strong" },
|
|
80
122
|
{ name: "partial-working-on", regex: /working on (the|this)\b.{0,30}?\b(part|half|piece)\b/i, strength: "strong" },
|
|
81
|
-
{ name: "partial-will-take", regex: /i('ll| will) take (the|this)\b.{0,30}?\b(part|half|ask|fallback)\b/i, strength: "strong" },
|
|
123
|
+
{ name: "partial-will-take", regex: /i(['’]ll| will) take (the|this)\b.{0,30}?\b(part|half|ask|fallback)\b/i, strength: "strong" },
|
|
82
124
|
];
|
|
83
125
|
const ALL_PATTERNS = [...PARTIAL_PATTERNS, ...STRONG_PATTERNS, ...SOFT_PATTERNS];
|
|
84
126
|
// Authors that are not humans claiming work.
|
|
@@ -113,19 +155,30 @@ export function detectClaims(issueAuthor, comments, now = new Date()) {
|
|
|
113
155
|
let scopeWord;
|
|
114
156
|
for (const pattern of ALL_PATTERNS) {
|
|
115
157
|
const m = pattern.regex.exec(comment.body);
|
|
116
|
-
if (m)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
158
|
+
if (!m)
|
|
159
|
+
continue;
|
|
160
|
+
// v0.9.2: a guard can reject a regex match the pattern alone
|
|
161
|
+
// cannot judge (negation, the actor). Rejected matches fall
|
|
162
|
+
// through to the next pattern, not out of detection.
|
|
163
|
+
if (pattern.guard && !pattern.guard(comment.body, m))
|
|
164
|
+
continue;
|
|
165
|
+
matched = pattern;
|
|
166
|
+
if (pattern.name.startsWith("partial-")) {
|
|
167
|
+
// Partial patterns carry the scope word in the second capture group.
|
|
168
|
+
scopeWord = (m[2] ?? "").toLowerCase() || undefined;
|
|
123
169
|
}
|
|
170
|
+
break; // partial and strong patterns come first, so first match wins
|
|
124
171
|
}
|
|
125
172
|
if (!matched)
|
|
126
173
|
continue;
|
|
127
|
-
// Skip the issue author unless they announce real work in progress
|
|
128
|
-
|
|
174
|
+
// Skip the issue author unless they announce real work in progress,
|
|
175
|
+
// or assign the issue to someone else (v0.9.2: "It's yours @x" is an
|
|
176
|
+
// assignment, not a self-claim — batrapulkit/squidbrake#79).
|
|
177
|
+
if (author === issueAuthor &&
|
|
178
|
+
matched.name !== "fix-ready" &&
|
|
179
|
+
matched.name !== "fix-in-progress" &&
|
|
180
|
+
matched.name !== "pr-opened" &&
|
|
181
|
+
matched.name !== "its-yours") {
|
|
129
182
|
continue;
|
|
130
183
|
}
|
|
131
184
|
const existing = byAuthor.get(author);
|
package/dist/claims.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claims.js","sourceRoot":"","sources":["../src/claims.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"claims.js","sourceRoot":"","sources":["../src/claims.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -22,13 +22,16 @@
|
|
|
22
22
|
* The claim/prep/pr commands default to a DRY RUN: nothing is posted or
|
|
23
23
|
* created without --yes, and writes require GITHUB_TOKEN (or GH_TOKEN).
|
|
24
24
|
*/
|
|
25
|
-
import { parseIssueUrl, buildIssueSnapshot, scanCandidates,
|
|
25
|
+
import { parseIssueUrl, buildIssueSnapshot, scanCandidates, RateLimitError, fetchComments, } from "./github.js";
|
|
26
|
+
import { CLAIM_MARKER } from "./protocol.js";
|
|
27
|
+
import { llmEnabled, llmModelId } from "./llm-claims.js";
|
|
28
|
+
import { checkPacing, pacingConfigFromEnv, pacingSummary, readLedger, } from "./posting-ledger.js";
|
|
26
29
|
import { scoreIssue } from "./verdict.js";
|
|
27
|
-
import {
|
|
30
|
+
import { parseGatefileJson } from "./gates.js";
|
|
28
31
|
import { existsSync, readFileSync } from "node:fs";
|
|
29
|
-
import {
|
|
32
|
+
import { fetchFrictionSummary } from "./friction.js";
|
|
30
33
|
import { createRestClient, claimIssue, prepIssue, openPr, AutomationRefusal, } from "./automate.js";
|
|
31
|
-
import {
|
|
34
|
+
import { describeMergeVelocity } from "./merge-velocity.js";
|
|
32
35
|
import { triagePr } from "./ci-triage.js";
|
|
33
36
|
import { triageReview } from "./review-triage.js";
|
|
34
37
|
import { guardPr, readGuardConfig } from "./guard.js";
|
|
@@ -91,6 +94,14 @@ function printVerdict(snapshot, result, asJson) {
|
|
|
91
94
|
if (llmClaims.length > 0) {
|
|
92
95
|
console.log(` ai claim signals: ${llmClaims.map((f) => `@${f.author} (${f.confidence.toFixed(2)}): "${f.quote}"`).join("; ")}`);
|
|
93
96
|
}
|
|
97
|
+
// v0.9.2: the AI claim layer always says whether it ran, so a dead
|
|
98
|
+
// layer can never hide behind patterns-only output again.
|
|
99
|
+
const llmStatus = result.llm_status;
|
|
100
|
+
if (llmStatus) {
|
|
101
|
+
console.log(llmStatus.ran
|
|
102
|
+
? ` ai claim layer: on (${llmStatus.model ?? "unknown model"})`
|
|
103
|
+
: ` ai claim layer: off (${llmStatus.reason ?? "unknown reason"})`);
|
|
104
|
+
}
|
|
94
105
|
const detected = result.gates.filter((g) => g.detected);
|
|
95
106
|
if (detected.length > 0) {
|
|
96
107
|
console.log(` gates: ${detected.map((g) => g.kind).join(", ")}`);
|
|
@@ -136,6 +147,7 @@ async function cmdCheck(issueUrl, asJson, args) {
|
|
|
136
147
|
claims: merged.claims,
|
|
137
148
|
gates: merged.gates,
|
|
138
149
|
llm_claims: merged.llm_claims,
|
|
150
|
+
llm_status: merged.llm_status,
|
|
139
151
|
};
|
|
140
152
|
// Maintainer-only repos (inspector, servers) close outside PRs on sight;
|
|
141
153
|
// the contribution that lands is a verified issue comment. Say so right
|
|
@@ -155,6 +167,7 @@ async function cmdCheck(issueUrl, asJson, args) {
|
|
|
155
167
|
duplicateOf: snapshot.duplicateOf ?? [],
|
|
156
168
|
protocol: merged.protocol,
|
|
157
169
|
llm_claims: merged.llm_claims ?? [],
|
|
170
|
+
llm_status: merged.llm_status ?? null,
|
|
158
171
|
suggestion,
|
|
159
172
|
}, null, 2));
|
|
160
173
|
return;
|
|
@@ -201,6 +214,12 @@ async function cmdStatus(issueUrl, asJson) {
|
|
|
201
214
|
console.log(` gates: ${detected.length > 0 ? detected.map((g) => g.kind).join(", ") : "none detected"}`);
|
|
202
215
|
console.log(` protocol ${status.repo_protocol ? `honored by repo (lease ${status.repo_protocol.lease_days}d)` : "not adopted by this repo; claims read as signals only"}`);
|
|
203
216
|
console.log(` checked at ${status.checked_at} (fresh for ${Math.round(status.stale_after_seconds / 3600)}h)`);
|
|
217
|
+
// Pacing (v0.9.2): the local posting ledger keeps claim cadence visible
|
|
218
|
+
// so the tool never trips GitHub's anti-spam flag the way the 2026-10-17
|
|
219
|
+
// campaign pace did.
|
|
220
|
+
for (const line of pacingSummary(checkPacing(readLedger(), Date.now(), pacingConfigFromEnv()))) {
|
|
221
|
+
console.log(` ${line}`);
|
|
222
|
+
}
|
|
204
223
|
}
|
|
205
224
|
async function cmdScan(repoRef, asJson, args) {
|
|
206
225
|
const { owner, repo } = parseRepoRef(repoRef);
|
|
@@ -227,10 +246,24 @@ async function cmdScan(repoRef, asJson, args) {
|
|
|
227
246
|
for (const issue of issues) {
|
|
228
247
|
try {
|
|
229
248
|
const { merged } = await checkIssueWithProtocol(owner, repo, issue.number, { externalGates });
|
|
230
|
-
results.push({
|
|
249
|
+
results.push({
|
|
250
|
+
url: issue.url,
|
|
251
|
+
title: issue.title,
|
|
252
|
+
verdict: merged.verdict,
|
|
253
|
+
reasons: merged.reasons,
|
|
254
|
+
flags: merged.flags,
|
|
255
|
+
llm_status: merged.llm_status ?? null,
|
|
256
|
+
});
|
|
231
257
|
}
|
|
232
258
|
catch (err) {
|
|
233
|
-
results.push({
|
|
259
|
+
results.push({
|
|
260
|
+
url: issue.url,
|
|
261
|
+
title: issue.title,
|
|
262
|
+
verdict: "ERROR",
|
|
263
|
+
reasons: [err instanceof Error ? err.message : String(err)],
|
|
264
|
+
flags: [],
|
|
265
|
+
llm_status: null,
|
|
266
|
+
});
|
|
234
267
|
}
|
|
235
268
|
}
|
|
236
269
|
const rank = { GO: 0, RISKY: 1, GATED: 2, STALE: 3, TAKEN: 4, ERROR: 5 };
|
|
@@ -240,6 +273,11 @@ async function cmdScan(repoRef, asJson, args) {
|
|
|
240
273
|
return;
|
|
241
274
|
}
|
|
242
275
|
console.log(`Scan of ${owner}/${repo}: ${results.length} candidate issues, GO first`);
|
|
276
|
+
// v0.9.2: say whether the AI claim layer ran on this scan. Per-issue
|
|
277
|
+
// statuses ride in the JSON; the human line states the environment.
|
|
278
|
+
console.log(llmEnabled()
|
|
279
|
+
? ` ai claim layer: on (${llmModelId()}); per-issue layer status in --json`
|
|
280
|
+
: ` ai claim layer: off (FIREWORKS_API_KEY not set); verdicts are patterns-only`);
|
|
243
281
|
if (fallbackUsed) {
|
|
244
282
|
console.log(`(fallback pass: no label-tagged starter issues found, showing the most recent open unassigned issues)`);
|
|
245
283
|
}
|
|
@@ -253,30 +291,10 @@ async function cmdScan(repoRef, asJson, args) {
|
|
|
253
291
|
}
|
|
254
292
|
async function cmdFriction(repoRef, asJson) {
|
|
255
293
|
const { owner, repo } = parseRepoRef(repoRef);
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
]);
|
|
261
|
-
const gates = parseGates(contributing, { collaboratorsOnlyPolicy: policy.collaboratorsOnly });
|
|
262
|
-
const report = scoreFriction({
|
|
263
|
-
owner,
|
|
264
|
-
repo,
|
|
265
|
-
gates,
|
|
266
|
-
externalPRMergeRate: null,
|
|
267
|
-
medianFirstReviewHours: null,
|
|
268
|
-
maintainerIssueResponseHours: null,
|
|
269
|
-
openGoodFirstIssueCount: starterCount,
|
|
270
|
-
note: "live",
|
|
271
|
-
});
|
|
272
|
-
// Merge velocity is a signal, never a score input. Best-effort: one
|
|
273
|
-
// /pulls call, silent when it fails.
|
|
274
|
-
try {
|
|
275
|
-
report.mergeVelocity = await fetchMergeVelocity(owner, repo);
|
|
276
|
-
}
|
|
277
|
-
catch {
|
|
278
|
-
report.mergeVelocity = null;
|
|
279
|
-
}
|
|
294
|
+
// v0.9.3: one shared pipeline (fetchFrictionSummary) for the CLI, the
|
|
295
|
+
// MCP repo_friction tool, and preflight, so gates come from the full
|
|
296
|
+
// policy source set everywhere instead of a single CONTRIBUTING read.
|
|
297
|
+
const report = await fetchFrictionSummary(owner, repo);
|
|
280
298
|
if (asJson) {
|
|
281
299
|
console.log(JSON.stringify(report, null, 2));
|
|
282
300
|
return;
|
|
@@ -286,6 +304,7 @@ async function cmdFriction(repoRef, asJson) {
|
|
|
286
304
|
console.log(` - ${reason}`);
|
|
287
305
|
if (report.reasons.length === 0)
|
|
288
306
|
console.log(" - no gates or penalties detected");
|
|
307
|
+
const starterCount = report.signals.openGoodFirstIssueCount ?? null;
|
|
289
308
|
if (starterCount !== null)
|
|
290
309
|
console.log(` open starter issues: ${starterCount}`);
|
|
291
310
|
if (report.mergeVelocity)
|
|
@@ -343,11 +362,34 @@ async function cmdClaim(issueUrl, args) {
|
|
|
343
362
|
}
|
|
344
363
|
const { snapshot, merged } = await checkIssueWithProtocol(owner, repo, number, {});
|
|
345
364
|
printVerdict(snapshot, merged, false);
|
|
346
|
-
const
|
|
365
|
+
const minIntervalRaw = flagValue(args, "--min-interval");
|
|
366
|
+
// Pacing (v0.9.2) reconciliation: an unconfirmed earlier claim attempt is
|
|
367
|
+
// re-checked against the issue's comments before any repost. The live
|
|
368
|
+
// client lists comments; a claim comment carrying the protocol marker
|
|
369
|
+
// from the current viewer (or any author) means the post landed.
|
|
370
|
+
const restClient = createRestClient();
|
|
371
|
+
const plan = await claimIssue(restClient, snapshot, {
|
|
347
372
|
yes: args.includes("--yes"),
|
|
348
373
|
force: args.includes("--force"),
|
|
349
374
|
plan: flagValue(args, "--plan"),
|
|
350
375
|
etaDays,
|
|
376
|
+
minIntervalS: minIntervalRaw !== undefined ? Number(minIntervalRaw) : undefined,
|
|
377
|
+
confirmPost: async () => {
|
|
378
|
+
try {
|
|
379
|
+
const comments = await fetchComments(owner, repo, number);
|
|
380
|
+
let viewer;
|
|
381
|
+
try {
|
|
382
|
+
viewer = await restClient.getViewer();
|
|
383
|
+
}
|
|
384
|
+
catch {
|
|
385
|
+
viewer = undefined;
|
|
386
|
+
}
|
|
387
|
+
return comments.some((c) => c.body.includes(CLAIM_MARKER) && (!viewer || c.author === viewer));
|
|
388
|
+
}
|
|
389
|
+
catch {
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
},
|
|
351
393
|
});
|
|
352
394
|
if (args.includes("--json")) {
|
|
353
395
|
console.log(JSON.stringify({
|
|
@@ -378,6 +420,10 @@ async function cmdClaim(issueUrl, args) {
|
|
|
378
420
|
console.log(plan.commentBody);
|
|
379
421
|
console.log(`---`);
|
|
380
422
|
console.log(`Re-run with --yes (and GITHUB_TOKEN set) to post it.`);
|
|
423
|
+
// Pacing posture (v0.9.2): informational in dry runs; enforced on post.
|
|
424
|
+
const dryPacing = checkPacing(readLedger(), Date.now(), pacingConfigFromEnv());
|
|
425
|
+
for (const line of pacingSummary(dryPacing))
|
|
426
|
+
console.log(` ${line}`);
|
|
381
427
|
}
|
|
382
428
|
}
|
|
383
429
|
async function cmdPrep(issueUrl, args) {
|
|
@@ -483,6 +529,12 @@ async function cmdPr(issueUrl, args) {
|
|
|
483
529
|
console.log(`Re-run with --yes (and GITHUB_TOKEN set) to open it.`);
|
|
484
530
|
}
|
|
485
531
|
}
|
|
532
|
+
/** v0.9.2: name the actual outcome when every failing check is an external blocker. */
|
|
533
|
+
function ciVerdictLine(verdict) {
|
|
534
|
+
return verdict === "NO CODE FAILURES"
|
|
535
|
+
? "Verdict: NO CODE FAILURES (all blockers external)"
|
|
536
|
+
: `Verdict: ${verdict}`;
|
|
537
|
+
}
|
|
486
538
|
async function cmdCi(prUrl, asJson) {
|
|
487
539
|
const result = await triagePr(prUrl);
|
|
488
540
|
if (asJson) {
|
|
@@ -494,7 +546,7 @@ async function cmdCi(prUrl, asJson) {
|
|
|
494
546
|
console.log(` head ${result.headSha.slice(0, 7)} <- base ${result.baseRef}`);
|
|
495
547
|
if (result.checks.length === 0) {
|
|
496
548
|
console.log(` No failing checks on the PR head.`);
|
|
497
|
-
console.log(
|
|
549
|
+
console.log(ciVerdictLine(result.verdict));
|
|
498
550
|
return;
|
|
499
551
|
}
|
|
500
552
|
for (const c of result.checks) {
|
|
@@ -508,7 +560,7 @@ async function cmdCi(prUrl, asJson) {
|
|
|
508
560
|
for (const line of c.failureLines)
|
|
509
561
|
console.log(` > ${line}`);
|
|
510
562
|
}
|
|
511
|
-
console.log(
|
|
563
|
+
console.log(ciVerdictLine(result.verdict));
|
|
512
564
|
}
|
|
513
565
|
async function cmdReview(prUrl, asJson) {
|
|
514
566
|
const result = await triageReview(prUrl);
|