@reneturcios/greenlight 0.17.1 → 0.18.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/README.md CHANGED
@@ -38,12 +38,12 @@ Every verdict and every report cites its evidence: the quoted policy line, the c
38
38
  ## Who it is for
39
39
 
40
40
  * **Contributors (human).** Run `check` before you spend an evening on an issue. Run `scan` when you are picking what to work on. Run `ci-prep` before you push.
41
- * **AI agents and coding tools.** One command (`init --agent claude-code`, also cursor, copilot, windsurf, cline) installs the MCP config plus the one behavior rule: check Greenlight before opening a PR. Agents waste the most tokens fixing already-taken issues; 31 MCP tools make the whole engine available mid-run.
41
+ * **AI agents and coding tools.** One command (`init --agent claude-code`, also cursor, copilot, windsurf, cline) installs the MCP config plus the one behavior rule: check Greenlight before opening a PR. Agents waste the most tokens fixing already-taken issues; 32 MCP tools make the whole engine available mid-run.
42
42
  * **Maintainers.** `guard` on each incoming PR, `radar` across the whole open queue, `digest` for the weekly triage, and the roadmap below for the control room: stale-claim sweeps, policy enforcement, AI-PR filtering.
43
43
 
44
44
  ## Proof, stated plainly
45
45
 
46
- * 1039 tests, all passing, including a fixture corpus pinned to real campaign cases (a taken issue, a weak PR mention, claim-first gates, scoped claims, half-shipped issues, stale claims, paused-PR workflows).
46
+ * 1045 tests, all passing, including a fixture corpus pinned to real campaign cases (a taken issue, a weak PR mention, claim-first gates, scoped claims, half-shipped issues, stale claims, paused-PR workflows).
47
47
  * Dogfooded on real campaigns: the toolkit has authored 80+ pull requests across dozens of public open-source repos. Every feature exists because a real contribution died without it.
48
48
  * Distributed everywhere the audience already looks: npm (`@reneturcios/greenlight`), the MCP Registry, and GHCR (`ghcr.io/cloudcorprecords/greenlight`), plus Docker and direct MCP stdio.
49
49
  * Two living datasets ship with it: the Contribution Friction Index (`data/friction-index.json`) and the Agent Policy Index (505 repos, 127 gated, 19 agent bans, published at `docs/policy.html`), both built from real campaign field work, not scraped guesses.
@@ -103,7 +103,7 @@ One command sets it up:
103
103
  npx @reneturcios/greenlight init --agent claude-code
104
104
  ```
105
105
 
106
- (also `cursor`, `copilot`, `windsurf`, `cline`; repeat `--agent` for more than one). Init copies the MCP config into your project and installs the workflow instruction snippet that teaches your agent the one behavior rule: **check Greenlight before it opens a PR.** Prefer doing it by hand? The [`integrations/`](integrations/README.md) drop-in pack has ready-to-copy MCP configs plus the same snippets. Then verify with a "list your MCP tools" prompt; the greenlight server carries 31 tools (see the list below).
106
+ (also `cursor`, `copilot`, `windsurf`, `cline`; repeat `--agent` for more than one). Init copies the MCP config into your project and installs the workflow instruction snippet that teaches your agent the one behavior rule: **check Greenlight before it opens a PR.** Prefer doing it by hand? The [`integrations/`](integrations/README.md) drop-in pack has ready-to-copy MCP configs plus the same snippets. Then verify with a "list your MCP tools" prompt; the greenlight server carries 32 tools (see the list below).
107
107
 
108
108
  ## CLI
109
109
 
@@ -283,7 +283,7 @@ The same engine is exposed over stdio for coding agents (Claude, Cursor, Cline).
283
283
  }
284
284
  ```
285
285
 
286
- Tools (31):
286
+ Tools (32):
287
287
 
288
288
  * `check_issue` - verdict for one issue URL
289
289
  * `scan_repo` - rank a repo's open issues, GO first (label-tagged starter issues, falling back to recent open unassigned issues; `deep: true` timeline-x-rays the candidates first)
@@ -293,6 +293,7 @@ Tools (31):
293
293
  * `verify` - honest base-vs-head test delta for a checked-out repo (red-first, never raw counts)
294
294
  * `shipcheck` - release-readiness: GitHub release, npm version, registry record, and GHCR tag, GO / NO-GO per surface
295
295
  * `passport` - contributor passport for a GitHub login: ledger profile, merged PR count, honor ratio
296
+ * `bounty_check` - bounty-liveness classification for one issue: live platform, unverifiable claim, or dead platform
296
297
  * `claim_issue` - verdict-gated claim comment (dry run unless `execute: true`)
297
298
  * `prep_issue` - fork and branch check plus a local PREP.md checklist with the repo's learned conventions (dry run unless `execute: true`)
298
299
  * `open_pr` - DCO-aware PR opening from a fork branch (dry run unless `execute: true`)
@@ -338,7 +339,7 @@ The verdict engine is deterministic (no LLM) and checks, in order:
338
339
 
339
340
  Friction score starts at 100 and subtracts gate weights (assignment -25, vouch -35, collaborators-only -50, paused unsolicited PRs -40, scoped pause -20, external PRs auto-closed -50, discussion-first -10, claim-first -5, CLA/DCO -5 each, detected behavioral gate -20), adjusts for external PR merge rate and review/response times when computable, and adds up to +10 for open good-first-issues. Unknown signals stay null and are skipped, never guessed. See `src/friction.ts` for the exact formula.
340
341
 
341
- A behavioral gate is not a policy file: it is read from what maintainers do. `friction` walks the closed-PR list until it has the 15 most recent closed-unmerged PRs within a 12-month recency bound (older closures are excluded, with a "stale signal" note when the newest closure itself is older than the bound), then reads maintainer-side comments for AI-rejection evidence (AI attribution plus rejection language, explicit phrases like "AI slop" or an invoked "AI policy", with welcoming overrides like "AI-assisted PRs are welcome" suppressing the signal). Two independent PRs mark the repo as behaviorally gated; a single weak signal is carried as a warning, while a single explicit rejection phrase detects on its own. `friction --json` reports it as the top-level `behavioral_gate` field (`detected`, `strength`, `threshold`, `evidence` with PR numbers, quotes, and URLs, `notes`); that field is the canonical location, and `signals.behavioralGate` is kept as an identical mirror for index-pipeline compatibility. Index pipelines like the rebaseline read the canonical field to reclassify repos whose written policy is silent but whose practice is hostile. API cost is bounded at 18 calls: up to 3 list calls to collect 15 closed-unmerged PRs plus one comment page per PR; skip it with `--no-behavioral`.
342
+ A behavioral gate is not a policy file: it is read from what maintainers do. `friction` walks the closed-PR list until it has the 15 most recent closed-unmerged PRs within a 12-month recency bound (older closures are excluded, with a "stale signal" note when the newest closure itself is older than the bound), then reads maintainer-side comments for AI-rejection evidence (AI attribution plus rejection language, explicit phrases like "AI slop" or an invoked "AI policy", with welcoming overrides like "AI-assisted PRs are welcome" suppressing the signal). Two independent PRs mark the repo as behaviorally gated; a single weak signal is carried as a warning, while a single explicit rejection phrase detects on its own. `friction --json` reports it as the top-level `behavioral_gate` field (`detected`, `strength`, `threshold`, `evidence` with PR numbers, quotes, and URLs, `notes`); that field is the canonical location, and `signals.behavioralGate` is kept as an identical mirror for index-pipeline compatibility. Index pipelines like the rebaseline read the canonical field to reclassify repos whose written policy is silent but whose practice is hostile. API cost is bounded at 48 calls: up to 3 list calls to collect 15 closed-unmerged PRs plus up to 3 evidence pages per PR (issue comments, reviews, review comments); skip it with `--no-behavioral`.
342
343
 
343
344
  `wave` turns the Agent Policy Index into a build queue in one command: pure-open repos with outsider merge share, star band, and starter issues are x-rayed with the existing xray engine (CLEAR / RISKY / TAKEN with competing PRs named), repos with detected behavioral gates are excluded, repos where you already have an open PR are skipped, and the run stops with marked partial results when the core API budget falls under the floor (default 800) or search throttling hits. Human and `--json` output; every stage reports the API calls it used. Candidates rank by winnability by default (outsider merge share, then friction, then stars); `--sort stars` restores the old order.
344
345
 
@@ -346,7 +347,7 @@ A scoped intake pause ("not accepting pull requests that add new formatting opti
346
347
 
347
348
  Autopilot keeps a standing branch-health board: per-PR mergeable, mergeable_state, base SHA, and behind-count persist in its state between runs, render in the report output, and ride along in the `autopilot_report` MCP tool (`branch_health`, `branch_board`).
348
349
 
349
- Three more CLI commands are agent-callable MCP tools: `verify` (honest base-vs-head test delta), `shipcheck` (release, npm, registry, and GHCR readiness), and `passport` (claim-ledger contributor profile).
350
+ Four more CLI commands are agent-callable MCP tools: `verify` (honest base-vs-head test delta), `shipcheck` (release, npm, registry, and GHCR readiness), `passport` (claim-ledger contributor profile), and `bounty` (bounty-liveness for one issue).
350
351
 
351
352
  ### Agent-policy gates and triage holds
352
353
 
@@ -4,12 +4,19 @@ export interface BehavioralClosedPR {
4
4
  author: string;
5
5
  closedAt: string;
6
6
  }
7
+ /**
8
+ * One maintainer-authored text blob on a closed-unmerged PR.
9
+ * v0.18.0 (item 5): maintainer rejections often live in review bodies
10
+ * and line comments, not issue comments, so all three surfaces feed the
11
+ * same matcher. `source` defaults to "comment" for older callers.
12
+ */
7
13
  export interface BehavioralMaintainerComment {
8
14
  pr: number;
9
15
  author: string;
10
16
  association: string;
11
17
  body: string;
12
18
  url: string;
19
+ source?: "comment" | "review" | "review_comment";
13
20
  }
14
21
  export interface BehavioralSignal {
15
22
  pr: number;
@@ -19,6 +26,8 @@ export interface BehavioralSignal {
19
26
  url: string;
20
27
  /** True for explicit phrases like "AI slop"; weaker signals can still count toward strength. */
21
28
  strong: boolean;
29
+ /** Which surface carried the evidence: "comment" | "review" | "review_comment". */
30
+ source?: "comment" | "review" | "review_comment";
22
31
  }
23
32
  export interface BehavioralGate {
24
33
  /** True when strength >= threshold: the maintainer rejects AI-built PRs in practice. */
@@ -53,9 +62,10 @@ export declare function partitionByRecency(prs: BehavioralClosedPR[], nowMs: num
53
62
  newestClosedAt: string | null;
54
63
  };
55
64
  /**
56
- * API cost contract: 1-3 calls to walk the closed-PR list (stops early
57
- * once 15 unmerged PRs are found) plus at most one comment page per
58
- * closed-unmerged PR.
65
+ * API cost contract (v0.18.0, item 5): 1-3 calls to walk the closed-PR
66
+ * list (stops early once 15 unmerged PRs are found) plus up to three
67
+ * evidence pages per closed-unmerged PR (issue comments, reviews,
68
+ * review comments).
59
69
  */
60
70
  export declare const BEHAVIORAL_MAX_API_CALLS: number;
61
71
  /** Pure: does one comment body read as maintainer AI-rejection evidence? */
package/dist/behavior.js CHANGED
@@ -17,9 +17,10 @@
17
17
  * itself is older than the bound). The closed-PR list is
18
18
  * walked (newest first, up to 3 pages of 30) until 15 unmerged PRs are
19
19
  * collected, because merged PRs carry no closure evidence and an
20
- * active repo's unmerged closures can sit pages deep. Comment fetches
21
- * (first page, per_page=100) run only for those unmerged PRs, so the
22
- * total cost is 1-3 list calls + up to 15 comment calls (18 max).
20
+ * active repo's unmerged closures can sit pages deep. Evidence fetches
21
+ * (first page, per_page=100) run only for those unmerged PRs, on all
22
+ * three surfaces (issue comments, reviews, review comments), so the
23
+ * total cost is 1-3 list calls + up to 3 pages x 15 PRs (48 max).
23
24
  * - Maintainer-side only: comment author_association must be OWNER,
24
25
  * MEMBER, or COLLABORATOR, and the comment author must not be the PR
25
26
  * author (a maintainer closing their own PR is not evidence against
@@ -80,11 +81,12 @@ export function partitionByRecency(prs, nowMs, months = BEHAVIORAL_RECENCY_MONTH
80
81
  return { fresh, staleCount, newestClosedAt };
81
82
  }
82
83
  /**
83
- * API cost contract: 1-3 calls to walk the closed-PR list (stops early
84
- * once 15 unmerged PRs are found) plus at most one comment page per
85
- * closed-unmerged PR.
84
+ * API cost contract (v0.18.0, item 5): 1-3 calls to walk the closed-PR
85
+ * list (stops early once 15 unmerged PRs are found) plus up to three
86
+ * evidence pages per closed-unmerged PR (issue comments, reviews,
87
+ * review comments).
86
88
  */
87
- export const BEHAVIORAL_MAX_API_CALLS = 3 + BEHAVIORAL_MAX_PRS;
89
+ export const BEHAVIORAL_MAX_API_CALLS = 3 + 3 * BEHAVIORAL_MAX_PRS;
88
90
  const AI_TERMS = /\b(ai|a\.i\.|llm|llms|chatgpt|copilot|Muse|gemini|gpt-?4|gpt-?3|generated|slop)\b/i;
89
91
  const REJECTION_TERMS = /\b(clos(?:e|ed|ing|ure)?|not\s+accept(?:ing|s)?|won['’]t|will\s+not|do\s+not|don['’]t|reject(?:ed|s|ion)?|declin(?:e|ed)|low[\s-]?effort|slop|refus(?:e|ed|ing)|spam|not\s+welcome|polic(?:y|ies))\b/i;
90
92
  /** Explicit phrases: unmistakable even without the two-term rule. */
@@ -128,7 +130,7 @@ export function detectBehavioralGateFromData(prs, comments) {
128
130
  const evidence = [];
129
131
  const prsWithSignal = new Set();
130
132
  const notes = [];
131
- notes.push(`scanned ${prs.length} closed-unmerged PRs, ${comments.length} maintainer comments on them`);
133
+ notes.push(`scanned ${prs.length} closed-unmerged PRs, ${comments.length} maintainer-authored texts on them (issue comments, reviews, review comments)`);
132
134
  for (const c of comments) {
133
135
  if (!MAINTAINER_ASSOCIATIONS.has(String(c.association ?? "")))
134
136
  continue;
@@ -147,6 +149,7 @@ export function detectBehavioralGateFromData(prs, comments) {
147
149
  quote: truncateQuote(c.body),
148
150
  url: c.url,
149
151
  strong,
152
+ source: c.source ?? "comment",
150
153
  });
151
154
  prsWithSignal.add(c.pr);
152
155
  }
@@ -200,16 +203,44 @@ export async function detectBehavioralGate(owner, repo, opts = {}) {
200
203
  // v0.17.1: drop stale closures before paying comment calls for them.
201
204
  const recency = partitionByRecency(closedUnmerged, nowMs);
202
205
  const live = recency.fresh;
206
+ // v0.18.0 (item 5): maintainer rejections live on three surfaces.
207
+ // One bounded page each: issue comments, reviews, review comments.
203
208
  const comments = [];
204
209
  for (const pr of live) {
205
- const list = (await apiGet(`/repos/${owner}/${repo}/issues/${pr.number}/comments?per_page=100`));
206
- for (const c of list ?? []) {
210
+ const issueComments = (await apiGet(`/repos/${owner}/${repo}/issues/${pr.number}/comments?per_page=100`));
211
+ for (const c of issueComments ?? []) {
207
212
  comments.push({
208
213
  pr: pr.number,
209
214
  author: String(c.user?.login ?? ""),
210
215
  association: String(c.author_association ?? ""),
211
216
  body: String(c.body ?? ""),
212
217
  url: c.html_url,
218
+ source: "comment",
219
+ });
220
+ }
221
+ const reviews = (await apiGet(`/repos/${owner}/${repo}/pulls/${pr.number}/reviews?per_page=100`));
222
+ for (const r of reviews ?? []) {
223
+ const body = String(r.body ?? "").trim();
224
+ if (!body)
225
+ continue; // bare APPROVE/REQUEST_CHANGES votes carry no text
226
+ comments.push({
227
+ pr: pr.number,
228
+ author: String(r.user?.login ?? ""),
229
+ association: String(r.author_association ?? ""),
230
+ body,
231
+ url: r.html_url,
232
+ source: "review",
233
+ });
234
+ }
235
+ const reviewComments = (await apiGet(`/repos/${owner}/${repo}/pulls/${pr.number}/comments?per_page=100`));
236
+ for (const c of reviewComments ?? []) {
237
+ comments.push({
238
+ pr: pr.number,
239
+ author: String(c.user?.login ?? ""),
240
+ association: String(c.author_association ?? ""),
241
+ body: String(c.body ?? ""),
242
+ url: c.html_url,
243
+ source: "review_comment",
213
244
  });
214
245
  }
215
246
  }
@@ -1 +1 @@
1
- {"version":3,"file":"behavior.js","sourceRoot":"","sources":["../src/behavior.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"behavior.js","sourceRoot":"","sources":["../src/behavior.ts"],"names":[],"mappings":"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"}
package/dist/bounty.d.ts CHANGED
@@ -19,6 +19,14 @@ export interface BountySignal {
19
19
  /** Evidence string for the flag, or "" when flag is null. */
20
20
  evidence: string;
21
21
  }
22
+ /** Live: fetch the issue and classify its bounty advertising (v0.18.0, item 23). */
23
+ export declare function detectBountyForIssue(owner: string, repo: string, number: number): Promise<{
24
+ issueUrl: string;
25
+ repo: string;
26
+ labels: string[];
27
+ title: string;
28
+ signal: BountySignal | null;
29
+ }>;
22
30
  export declare function detectBounty(input: {
23
31
  labels: string[];
24
32
  title: string;
package/dist/bounty.js CHANGED
@@ -11,6 +11,21 @@
11
11
  const DEAD_PLATFORMS = {
12
12
  algora: "algora.io 404s and its public API returns zero items (dead since 2025)",
13
13
  };
14
+ import { apiGet, resolveCanonicalRepo } from "./github.js";
15
+ /** Live: fetch the issue and classify its bounty advertising (v0.18.0, item 23). */
16
+ export async function detectBountyForIssue(owner, repo, number) {
17
+ const canon = await resolveCanonicalRepo(owner, repo);
18
+ const data = (await apiGet(`/repos/${canon.owner}/${canon.repo}/issues/${number}`));
19
+ const labels = (data.labels ?? []).map((l) => String(l.name ?? ""));
20
+ const title = String(data.title ?? "");
21
+ return {
22
+ issueUrl: String(data.html_url ?? ""),
23
+ repo: canon.fullName,
24
+ labels,
25
+ title,
26
+ signal: detectBounty({ labels, title, body: String(data.body ?? "") }),
27
+ };
28
+ }
14
29
  const PLATFORM_RE = /(algora|opire|issuehunt|polar|gitcoin|oss[-.]?hunter|bountysource)/i;
15
30
  function normalizePlatform(name) {
16
31
  return name.toLowerCase().replace(/[-.]/g, "");
@@ -1 +1 @@
1
- {"version":3,"file":"bounty.js","sourceRoot":"","sources":["../src/bounty.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAeH,MAAM,cAAc,GAA2B;IAC7C,MAAM,EAAE,wEAAwE;CACjF,CAAC;AAEF,MAAM,WAAW,GAAG,qEAAqE,CAAC;AAE1F,SAAS,iBAAiB,CAAC,IAAY;IACrC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAI5B;IACC,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzE,MAAM,aAAa,GACjB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QACf,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrE,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IAEhC,MAAM,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3D,MAAM,EAAE,GAAG,oCAAoC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAE7C,IAAI,QAAQ,IAAI,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzC,OAAO;YACL,QAAQ;YACR,MAAM;YACN,IAAI,EAAE,sBAAsB;YAC5B,QAAQ,EAAE,iBAAiB,QAAQ,qBAAqB,cAAc,CAAC,QAAQ,CAAC,EAAE;SACnF,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO;YACL,QAAQ,EAAE,SAAS;YACnB,MAAM;YACN,IAAI,EAAE,mBAAmB;YACzB,QAAQ,EAAE,sEAAsE;SACjF,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AACxD,CAAC"}
1
+ {"version":3,"file":"bounty.js","sourceRoot":"","sources":["../src/bounty.ts"],"names":[],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -17,6 +17,7 @@
17
17
  * greenlight ci-prep <path> [--base <ref>] [--json] [--act]
18
18
  * greenlight babysit [--prs urls] [--mine --repos o/r] [--account] [--claims-only] [--json]
19
19
  * greenlight autopilot [--author login] [--prs urls] [--max-prs N] [--apply] [--max-fixes N] [--json]
20
+ * greenlight bounty <issue-url> [--json]
20
21
  * greenlight sync [--author login] [--tracker csv|json] [--stale-days N] [--write] [--json]
21
22
  * greenlight portfolio [--author login] [--json]
22
23
  * greenlight init [--agent <tool>...] [--dry-run] [--force]
@@ -28,7 +29,7 @@
28
29
  * The claim/prep/pr commands default to a DRY RUN: nothing is posted or
29
30
  * created without --yes, and writes require GITHUB_TOKEN (or GH_TOKEN).
30
31
  */
31
- import { parseIssueUrl, buildIssueSnapshot, scanCandidates, RateLimitError, fetchComments, apiCallsUsed, } from "./github.js";
32
+ import { parseIssueUrl, buildIssueSnapshot, scanCandidates, RateLimitError, fetchComments, apiCallsUsed, resolveCanonicalRepo, } from "./github.js";
32
33
  import { xrayIssue, xrayIssues, sortXrayResults, applyXrayDemotion } from "./xray.js";
33
34
  import { CLAIM_MARKER } from "./protocol.js";
34
35
  import { llmEnabled, llmModelId } from "./llm-claims.js";
@@ -64,6 +65,7 @@ import { detectBehavioralGate } from "./behavior.js";
64
65
  import { viaApiClaim, viaApiRelease, viaApiHeartbeat, deviceFlowLogin, browserLoginFlow, defaultTokenStore, } from "./claim-api.js";
65
66
  import { buildEvidencePack } from "./evidence.js";
66
67
  import { buildPassport } from "./passport.js";
68
+ import { detectBountyForIssue } from "./bounty.js";
67
69
  import { renderLabelsDryRun } from "./guard.js";
68
70
  import { writeFileSync } from "node:fs";
69
71
  import { createRequire } from "node:module";
@@ -151,7 +153,14 @@ function loadExternalGates(args) {
151
153
  }
152
154
  }
153
155
  async function cmdCheck(issueUrl, asJson, args) {
154
- const { owner, repo, number } = parseIssueUrl(issueUrl);
156
+ const parsed = parseIssueUrl(issueUrl);
157
+ // v0.18.0 (item 15): resolve renames before any name-based fetch.
158
+ const canon = await resolveCanonicalRepo(parsed.owner, parsed.repo);
159
+ const { owner, repo } = canon;
160
+ const number = parsed.number;
161
+ const renameNote = canon.renamed
162
+ ? `repo renamed: ${parsed.owner}/${parsed.repo} -> ${canon.fullName}`
163
+ : null;
155
164
  // The check pipeline merges the legacy verdict with the Claim Protocol
156
165
  // state: a protocol claim verdict overrides legacy claim inference, but
157
166
  // never gates or cross-referenced PR evidence (see mergeProtocolVerdict).
@@ -194,9 +203,12 @@ async function cmdCheck(issueUrl, asJson, args) {
194
203
  llm_claims: merged.llm_claims ?? [],
195
204
  llm_status: merged.llm_status ?? null,
196
205
  suggestion,
206
+ renamedFrom: renameNote ? `${parsed.owner}/${parsed.repo}` : null,
197
207
  }, null, 2));
198
208
  return;
199
209
  }
210
+ if (renameNote)
211
+ console.log(renameNote);
200
212
  printVerdict(snapshot, result, false);
201
213
  for (const line of merged.protocolLines)
202
214
  console.log(` ${line}`);
@@ -247,7 +259,14 @@ async function cmdStatus(issueUrl, asJson) {
247
259
  }
248
260
  }
249
261
  async function cmdScan(repoRef, asJson, args) {
250
- const { owner, repo } = parseRepoRef(repoRef);
262
+ const parsed = parseRepoRef(repoRef);
263
+ // v0.18.0 (item 15): the old name 422s the candidate search; resolve
264
+ // first and say so in the output.
265
+ const canon = await resolveCanonicalRepo(parsed.owner, parsed.repo);
266
+ const { owner, repo } = canon;
267
+ const scanRenameNote = canon.renamed ? `repo renamed: ${parsed.owner}/${parsed.repo} -> ${canon.fullName}` : null;
268
+ if (scanRenameNote && !asJson)
269
+ console.log(scanRenameNote);
251
270
  const { issues, fallbackUsed } = await scanCandidates(owner, repo, {
252
271
  fallback: !args.includes("--no-fallback"),
253
272
  limit: 10,
@@ -322,7 +341,7 @@ async function cmdScan(repoRef, asJson, args) {
322
341
  results.sort((a, b) => (rank[a.verdict] ?? 9) - (rank[b.verdict] ?? 9));
323
342
  }
324
343
  if (asJson) {
325
- console.log(JSON.stringify({ repo: `${owner}/${repo}`, fallback: fallbackUsed, results }, null, 2));
344
+ console.log(JSON.stringify({ repo: `${owner}/${repo}`, renamedFrom: canon.renamed ? `${parsed.owner}/${parsed.repo}` : null, fallback: fallbackUsed, results }, null, 2));
326
345
  return;
327
346
  }
328
347
  console.log(`Scan of ${owner}/${repo}: ${results.length} candidate issues, GO first`);
@@ -413,7 +432,9 @@ async function cmdFriction(repoRef, asJson, args = []) {
413
432
  console.log(JSON.stringify(report, null, 2));
414
433
  return;
415
434
  }
416
- console.log(`Friction for ${owner}/${repo}: ${report.score}/100 (100 = easiest)`);
435
+ console.log(`Friction for ${report.owner}/${report.repo}: ${report.score}/100 (100 = easiest)`);
436
+ if (report.resolvedFrom)
437
+ console.log(` repo renamed: ${report.resolvedFrom} -> ${report.owner}/${report.repo}`);
417
438
  for (const reason of report.reasons)
418
439
  console.log(` - ${reason}`);
419
440
  if (report.reasons.length === 0)
@@ -1281,6 +1302,38 @@ async function cmdPassport(login, args) {
1281
1302
  console.log(passport.markdown);
1282
1303
  }
1283
1304
  }
1305
+ /**
1306
+ * `greenlight bounty <issue-url>` (v0.18.0, item 23): is the bounty this
1307
+ * issue advertises actually alive? The classifier never raises a
1308
+ * verdict: bounties are context, not landability. What it kills is
1309
+ * chasing a dead platform (algora has been dead since 2025; thousands
1310
+ * of issues still wear its labels).
1311
+ */
1312
+ async function cmdBounty(issueUrl, args) {
1313
+ const { owner, repo, number } = parseIssueUrl(issueUrl);
1314
+ const result = await detectBountyForIssue(owner, repo, number);
1315
+ if (args.includes("--json")) {
1316
+ console.log(JSON.stringify(result, null, 2));
1317
+ return;
1318
+ }
1319
+ if (!result.signal) {
1320
+ console.log(`No bounty advertised on ${result.repo}#${number} ("${result.title}").`);
1321
+ return;
1322
+ }
1323
+ const s = result.signal;
1324
+ const head = s.amount ? `Bounty: ${s.amount}` : "Bounty advertised";
1325
+ const via = s.platform ? ` via ${s.platform}` : " (no platform named)";
1326
+ console.log(`${head}${via} on ${result.repo}#${number}`);
1327
+ if (s.flag === "bounty-platform-dead") {
1328
+ console.log(` DEAD PLATFORM: ${s.evidence}`);
1329
+ }
1330
+ else if (s.flag === "bounty-unverified") {
1331
+ console.log(` UNVERIFIED: ${s.evidence}`);
1332
+ }
1333
+ else {
1334
+ console.log(` platform is named and not known-dead; verify terms on the platform before counting on payment`);
1335
+ }
1336
+ }
1284
1337
  async function cmdDigest(repoRef, args) {
1285
1338
  const asJson = args.includes("--json");
1286
1339
  const limitRaw = flagValue(args, "--limit");
@@ -1587,6 +1640,8 @@ async function main() {
1587
1640
  return await cmdEvidence(target, args);
1588
1641
  if (command === "passport" && target)
1589
1642
  return await cmdPassport(target, args);
1643
+ if (command === "bounty" && target)
1644
+ return await cmdBounty(target, args);
1590
1645
  if (command && NEEDS_TARGET[command]) {
1591
1646
  // Known command with a missing argument: name the need and show its
1592
1647
  // help, instead of the generic overview.