Skip to content

fix(grant-scout): harden Linear access, dedup, and anti-fabrication (supersedes #19)#25

Open
Oba-One wants to merge 1 commit into
mainfrom
fix/grant-scout-hardening
Open

fix(grant-scout): harden Linear access, dedup, and anti-fabrication (supersedes #19)#25
Oba-One wants to merge 1 commit into
mainfrom
fix/grant-scout-hardening

Conversation

@Oba-One
Copy link
Copy Markdown
Member

@Oba-One Oba-One commented Jun 3, 2026

Why

The 2026-05-28 run failed two ways: "Linear unreachable" (again) and a fabricated opportunity — "EF ESP passkey-support RFP", which is a real-but-archived program (RESR-37) re-surfaced as NEW with an invented RFP framing. Root-caused to this spec. Five root causes → eight coordinated fixes (one file: routines/claude/guild-grant-scout.md).

What changed

Linear connectivity

  • Canonical Linear path is now the GraphQL API + LINEAR_API_KEY (headless-safe). The OAuth MCP connector lapses between runs and a cron can't re-consent, so it's now optional, not the dependency.
  • Fail-closed: if Linear is unreachable / the key is unset, the run posts one status line and exits — it never scouts without dedup (scouting blind is what let archived programs re-surface as NEW).

Correct Linear routing (independent of connectivity)

  • Reads are workspace-wide by funding:* label (was: Product team only). The pipeline moved to Research / Grant Scouting on 2026-05-30 and awards live in Product, so the old single-team query silently missed half the pipeline.
  • New prospects/drafts are created in Research / Grant Scouting; awards graduate to Product. Dedup is keyed on funder URL, not just title (a reworded title is the same grant).

Anti-fabrication

  • Phase 2 existence gate — every opportunity must resolve to a funder-controlled page. Confirmed → surface; Disproven → reject (the EF-ESP case); Couldn't-fetch (403 / paywall / rolling) → surface tagged ⚠️ unverified — human confirm (so bot-blocked climate / Africa / gov portals aren't punished); no URL → "Unverified leads". Rolling / always-open counts as open.
  • Quota reframed: 6–8 is breadth of scanning, not an opportunity count. A quiet week beats a fabricated one.
  • Folds in fix(grant-scout): stop fabricated prior-grant claims; de-hardcode metrics #19: removes the "Evidence Commons" false-prior-grant claim + the hardcoded "13 live gardens"; adds a verify-claims-vs-primary-source guardrail.

Output

  • Discord posts now carry bare grant URLs (rich previews, top ≤5 by fit) and group Linear links <>-suppressed (private workspace, no previews). Adds a 🔍 Unverified-leads section and a run-start health line in the memo.

⚠️ Action required before / at merge

  1. Set LINEAR_API_KEY in the guild-routines env — a Linear personal API key (header is Authorization: <key>, no Bearer). Until it's set, every run correctly fail-closes to a no-op status post.
  2. Close fix(grant-scout): stop fabricated prior-grant claims; de-hardcode metrics #19 as superseded — it edits the same lines; merging both would conflict.

The thin-wrapper trigger re-reads this file each run, so it ships on merge with no trigger reconfig.

🤖 Generated with Claude Code

Addresses the 2026-05-28 run failures (Linear "unreachable" + the fabricated
"EF ESP passkey-support RFP"). Eight coordinated fixes:

- Linear via the GraphQL API + LINEAR_API_KEY as the canonical headless-safe
  path (an OAuth connector that lapses can't re-consent in a cron); fail-closed
  when Linear is unreachable instead of scouting with no dedup.
- Read funding:* workspace-wide; create non-awarded grants in Research /
  Grant Scouting (the pipeline moved off the Product team on 2026-05-30);
  awards graduate to Product. Dedup keyed on funder URL, not just title.
- Phase 2 existence gate: every opportunity must resolve to a funder page
  fetched this run; unconfirmable -> "Unverified leads", never a prospect.
- Reframe the 6-8 "NEW" quota to breadth-of-scanning; a quiet week beats a
  fabricated one.
- Discord output: bare grant URLs (previews, top <=5 by fit), Linear links
  grouped and <>-suppressed (private workspace, no previews).
- Run-start preflight + a health line in the memo.
- Folds in #19: removes the "Evidence Commons" false-prior-grant claim and the
  hardcoded "13 live gardens"; adds a verify-claims-vs-primary-source guardrail.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Prevented duplicate and fabricated grant opportunities through stricter verification and existence-checking gates.
  • Documentation

    • Enhanced grant candidate verification classifications and deduplication rules.
    • Improved fail-safe behavior and Linear integration reliability.
    • Clarified Discord reporting format for better link preview control.

Walkthrough

The PR updates the Guild Grant Scout routine specification to add fail-closed Linear integration, enforce existence verification before scoring or surfacing opportunities, restructure Linear issue routing and workspace-wide deduping, and standardize Discord/memo output with expanded safety guardrails.

Changes

Guild Grant Scout Routine Enhancement

Layer / File(s) Summary
Phase 0: Linear Integration Preflight & Fail-Closed Behavior
routines/claude/guild-grant-scout.md
Phase 0 now requires explicit Linear GraphQL endpoint probing with workspace-wide funding:* queries, resolves team/project/label IDs by name at runtime, and enforces fail-closed early exit (skipping scouting, posting single Discord status, and Phase 6 memo) when Linear is unreachable. Green Goods context is updated to pull current Season One pilot counts at runtime instead of hardcoded values.
Phases 1–2: Candidate Discovery & Existence Verification Gating
routines/claude/guild-grant-scout.md
Phase 1 emphasizes existence-verification gating alongside fit scoring, requires breadth scanning across all three primary targets (Coop, Green Goods, PGSP). Phase 2 expands candidate verification into explicit outcome classes (Confirmed, Disproven, Couldn't auto-verify, No funder URL), forbids fabricating opportunities by fusing assumed topics with funders, and prevents re-surfacing of known programs as NEW after disproval.
Phase 4: Linear Issue Lifecycle & Workspace-Wide Deduping
routines/claude/guild-grant-scout.md
Issue creation/update rules now require dynamic ID resolution by name (no hardcoding), enforce workspace-wide deduping keyed primarily by funder URL host+path, route non-awarded prospects to Research "Grant Scouting" project with awards graduating to Product, and handle duplicates by commenting instead of recreating issues.
Phases 5–6 & Guardrails: Discord Reporting, Memos & Safety Constraints
routines/claude/guild-grant-scout.md
Phase 5 Discord template is redesigned to control link previews: grant URLs are plain-bare for top entries, Linear URLs are wrapped in <> in grouped tracking sections, and verified-but-unconfirmed items remain in new-opportunities with ⚠️ tag. Phase 6 adds preflight/surface health bullet, standardizes "New opportunities surfaced" and "Unverified leads" memo sections with funder URL, deadlines, fit score, and Linear URLs, and records unverified leads for human confirmation. Guardrails are expanded to enforce non-interactive execution, detailed fail-closed behavior when required surfaces are unavailable, and reinforced existence-verification requirements throughout.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A scout hops through the grant-funding trees,
Checking Linear for gates with ease,
No fabricated blooms shall pass the gate—
Existence first, then we celebrate! 🌱✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(grant-scout): harden Linear access, dedup, and anti-fabrication (supersedes #19)' directly and clearly summarizes the main changes: hardening Linear connectivity, fixing deduplication, preventing fabricated opportunities, and superseding PR #19.
Description check ✅ Passed The description is directly related to the changeset, providing clear motivation (two failures from 2026-05-28), detailed explanation of changes across Linear connectivity, routing, anti-fabrication measures, and output formatting, along with explicit action items required before merge.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/grant-scout-hardening

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@routines/claude/guild-grant-scout.md`:
- Line 54: The line describing "Green Goods" contains the guild-wide phrase
"Season One" which violates the repo documentation policy; edit the markdown in
guild-grant-scout.md to remove the "Season One" framing (e.g., change "Season
One pilot live on Arbitrum — pull current garden / gardener / operator counts at
runtime per the Phase 2/3 metrics step; cite 'as of {date}'" to a neutral phrase
like "pilot live on Arbitrum — pull current garden / gardener / operator counts
at runtime per the Phase 2/3 metrics step; cite 'as of {date}'" or otherwise
omit any "Season" wording) so the entry for "**Green Goods**" no longer contains
guild-wide "Season" language.
- Around line 43-44: Update the cross-file lifecycle contract so all referenced
docs and routine catalog entries reflect the Research-first routing (non-awarded
issues in Research's "Grant Scouting" project with canonical funding:* labels,
awarded grants moved to Product), or explicitly mark this spec as superseding
older Product-centered docs; search for references to "funding:*", "Grant
Scouting", "LINEAR_API_KEY", and any doc/routine entries that describe grant
lifecycle or Linear routing and change their text/headers to match this new
Research-first behavior (or add a clear supersession note), and ensure the
fail-closed Phase 0 / Linear-as-canonical guidance is consistently stated across
the routine catalog and related docs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cf3c8787-0908-4d31-bd22-99f8c9126e46

📥 Commits

Reviewing files that changed from the base of the PR and between c42b910 and 43693d5.

📒 Files selected for processing (1)
  • routines/claude/guild-grant-scout.md
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{md,yml}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{md,yml}: Do not reintroduce the former dev-guild PM URL or old migration language for project-management state
Do not introduce guild-wide 'Season' framing in documentation
Do not describe the dev guild as the entire Greenpill Network in documentation
Avoid growth-hacking and trend-chasing voice in documentation: no FOMO, virality, leaderboards, streaks, or 'AI-first' framing

Files:

  • routines/claude/guild-grant-scout.md
🧠 Learnings (6)
📚 Learning: 2026-05-31T05:16:36.572Z
Learnt from: CR
Repo: greenpill-dev-guild/.github PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-05-31T05:16:36.572Z
Learning: Treat `package.json`, lockfiles, package-manager config, `.github/workflows/**`, `AGENTS.md`, `CLAUDE.md`, `.codex/**`, and `.claude/**` as security-sensitive surfaces and call out any changes in final summaries

Applied to files:

  • routines/claude/guild-grant-scout.md
📚 Learning: 2026-05-31T05:16:51.577Z
Learnt from: CR
Repo: greenpill-dev-guild/.github PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-05-31T05:16:51.577Z
Learning: Applies to {package.json,*lock*,*.lock.json,.npmrc,.yarnrc*,.github/workflows/**,AGENTS.md,CLAUDE.md,.codex/**,.claude/**} : Treat `package.json`, lockfiles, package-manager config, `.github/workflows/**`, `AGENTS.md`, `CLAUDE.md`, `.codex/**`, and `.claude/**` as security-sensitive surfaces and call out any changes in final summaries

Applied to files:

  • routines/claude/guild-grant-scout.md
📚 Learning: 2026-05-31T05:16:36.572Z
Learnt from: CR
Repo: greenpill-dev-guild/.github PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-05-31T05:16:36.572Z
Learning: Name Linear as the project-management source of truth; use GitHub for public execution/RFCs/code review, Drive for memos/evidence, and Discord/Telegram/calls for discussion

Applied to files:

  • routines/claude/guild-grant-scout.md
📚 Learning: 2026-05-31T05:16:51.577Z
Learnt from: CR
Repo: greenpill-dev-guild/.github PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-05-31T05:16:51.577Z
Learning: Linear is the project-management source of truth; GitHub owns public execution/RFCs/code review; Drive owns memos and evidence; Discord/Telegram/calls own discussion

Applied to files:

  • routines/claude/guild-grant-scout.md
📚 Learning: 2026-05-31T05:16:36.572Z
Learnt from: CR
Repo: greenpill-dev-guild/.github PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-05-31T05:16:36.572Z
Learning: Keep the guild voice grounded in public goods, transparency, and building in public; avoid hype framing

Applied to files:

  • routines/claude/guild-grant-scout.md
📚 Learning: 2026-05-31T05:16:51.577Z
Learnt from: CR
Repo: greenpill-dev-guild/.github PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-05-31T05:16:51.577Z
Learning: Applies to **/{CONTRIBUTING.md,GOVERNANCE.md,SECURITY.md,SUPPORT.md} : Treat contact emails, disclosure SLAs, payout timing, and governance claims as sensitive public commitments and do not change them casually

Applied to files:

  • routines/claude/guild-grant-scout.md
🪛 LanguageTool
routines/claude/guild-grant-scout.md

[style] ~78-~78: Consider an alternative for the overused word “exactly”.
Context: ...ntly misses half the pipeline — this is exactly what re-surfaces already-tracked progra...

(EXACTLY_PRECISELY)


[uncategorized] ~473-~473: The official name of this software platform is spelled with a capital “H”.
Context: ...nt lifecycle Issues anywhere else — not .github (no GitHub Issues, ever), not project ...

(GITHUB)

Comment on lines +43 to +44
- **Linear is the canonical surface for grant lifecycle.** Non-awarded grants (prospect / drafting / submitted) live as Issues in the **Research team's `Grant Scouting` project**, tracked with the canonical `funding:*` lifecycle labels. **Awarded grants graduate** to the **Product team** into a bounded award/delivery project when delivery, reporting, compliance, or funder follow-through needs project-level management. Because awards live in Product and everything else in Research, **always read `funding:*` workspace-wide — never scope a read to a single team** (a team-scoped read silently misses half the pipeline and causes already-tracked programs to re-surface as "NEW"). Resolve team/project/label IDs by name at the start of every run.
- **Reach Linear via the GraphQL API with `LINEAR_API_KEY` — this is the canonical, headless-safe path.** A scheduled run must not depend on an interactive OAuth connector that can silently lapse between runs. Endpoint `https://api.linear.app/graphql`; headers `Authorization: $LINEAR_API_KEY` and `Content-Type: application/json`; body `{"query": "..."}` (reads) or `{"query": "mutation ..."}` (writes), e.g. via `curl`. The Linear MCP connector may be used when present, but never rely on it. If `LINEAR_API_KEY` is unset or the API is unreachable, you have lost the canonical dedup + write surface — follow the **fail-closed rule in Phase 0** (do not scout; post one status line; exit). Never scout without Linear.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Sync cross-file Linear lifecycle contracts with this new Research-first routing.

These lines change the lifecycle contract (non-awarded in Research, awards in Product), but referenced docs still describe lifecycle issues as Product-centered. Please update the related docs/routine catalog in the same PR (or explicitly mark this spec as superseding them) to avoid operator drift and conflicting automation assumptions.

Based on learnings, “Linear is the project-management source of truth; GitHub owns public execution/RFCs/code review; Drive owns memos and evidence; Discord/Telegram/calls own discussion”.

Also applies to: 271-272, 275-277, 281-281

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@routines/claude/guild-grant-scout.md` around lines 43 - 44, Update the
cross-file lifecycle contract so all referenced docs and routine catalog entries
reflect the Research-first routing (non-awarded issues in Research's "Grant
Scouting" project with canonical funding:* labels, awarded grants moved to
Product), or explicitly mark this spec as superseding older Product-centered
docs; search for references to "funding:*", "Grant Scouting", "LINEAR_API_KEY",
and any doc/routine entries that describe grant lifecycle or Linear routing and
change their text/headers to match this new Research-first behavior (or add a
clear supersession note), and ensure the fail-closed Phase 0 /
Linear-as-canonical guidance is consistently stated across the routine catalog
and related docs.

What this guild is uniquely positioned to win funding for:

- **Green Goods** — offline-first regenerative documentation platform. Passkey auth, EAS attestations, Arbitrum production deployment with real users (Season One: 13 live gardens), Envio indexer. Strongest grant evidence in the guild — production code + production users.
- **Green Goods** — offline-first regenerative documentation platform. Passkey auth, EAS attestations, Arbitrum production deployment with real users (Season One pilot live on Arbitrum — pull current garden / gardener / operator counts at runtime per the Phase 2/3 metrics step; cite "as of {date}", never a hardcoded number), Envio indexer. Strongest grant evidence in the guild — production code + production users.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Remove guild-wide “Season One” framing from this line.

This introduces “Season One” wording in documentation, which conflicts with the repo documentation policy for .md files.

As per coding guidelines, “Do not introduce guild-wide 'Season' framing in documentation”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@routines/claude/guild-grant-scout.md` at line 54, The line describing "Green
Goods" contains the guild-wide phrase "Season One" which violates the repo
documentation policy; edit the markdown in guild-grant-scout.md to remove the
"Season One" framing (e.g., change "Season One pilot live on Arbitrum — pull
current garden / gardener / operator counts at runtime per the Phase 2/3 metrics
step; cite 'as of {date}'" to a neutral phrase like "pilot live on Arbitrum —
pull current garden / gardener / operator counts at runtime per the Phase 2/3
metrics step; cite 'as of {date}'" or otherwise omit any "Season" wording) so
the entry for "**Green Goods**" no longer contains guild-wide "Season" language.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant