Skip to content

feat(repo-finder): compile search filters from user preferences#29

Open
imkp1 wants to merge 3 commits into
gaurav0107:mainfrom
imkp1:feat/repo-finder-preferences
Open

feat(repo-finder): compile search filters from user preferences#29
imkp1 wants to merge 3 commits into
gaurav0107:mainfrom
imkp1:feat/repo-finder-preferences

Conversation

@imkp1

@imkp1 imkp1 commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Stacked on #28 — merge that first. Its four commits ride along in this diff until it lands. The files this PR owns are scripts/lib/preferences.sh, scripts/repo-finder/build_queries.sh, commands/preferences.md, the two new tests, and the preference-related edits to agents/repo-finder.md, commands/repo-finder.md, agents/SHARED_STATE.md, and schemas/repo_shortlist.schema.json.

The problem

/repo-finder's filters are constants. agents/repo-finder.md Step 1 hardcodes language:java and language:python, and no command accepts a preference — /repo-finder takes an integer N and rejects anything else. Ask for Go, get Python. There is no path by which "I want Go" changes a query.

The design

~/.superhuman/preferences.md, owned by the user. It sits at the root of ~/.superhuman/, not under global/, because everything under global/ is machine-written state the plugin owns. This file is theirs.

## Filters
languages: go, rust
topics: backend, infrastructure, llm:5000, any
stars: 2000

## Notes
Prefer small focused libraries over sprawling frameworks.
I'd rather fix bugs than add features.

The two halves bind differently, and being explicit about which is which is the point:

  • ## Filters is mechanical. Parsed by scripts/lib/preferences.sh, compiled 1:1 into GitHub search qualifiers by scripts/repo-finder/build_queries.sh. GitHub topics are the tag taxonomy, so topics pass straight through — nothing invented, nothing to maintain.
  • ## Notes is advisory. No code can filter on "focused rather than sprawling". The agent applies it at tie-breaks and issue selection only, never to a numeric score, and must disclose in the shortlist's notes field when it did. Treating prose as a filter is how the current version ended up ignoring its own stars:>20000.

Query shape follows the qualifier asymmetry

Qualifier Repeated Evidence
language: OR language:go language:rust topic:cli → first page is Go ∪ Rust, nothing outside
topic: AND topic:cli topic:terminal → 21 results vs 109/44 alone

So all languages collapse into one query and each topic gets its own. Query count is |topics|, not |languages| × |topics| — adding a language costs zero queries. Emitting two topic: qualifiers on one line silently returns only repos tagged with every topic, often none, exit 0, no error; build_queries.sh refuses to emit one.

Everything fails loudly

Each of these is reported by GitHub as success, which is why they are enforced at emit time rather than trusted:

  • a typo'd qualifier key (langauge:go) is parsed as free text → total_count: 0, exit 0
  • a bare OR or a parenthesized qualifier-OR → total_count: 0, exit 0
  • a second topic: → a quietly intersected, usually empty set

Malformed preferences exit 10 rather than degrade to an unfiltered scan. A stars: 2000-60000 range is a loud error, not a quietly honored ceiling.

No star ceiling

main has never had one — all nine current queries are lower-bound only. A ceiling is a guess about what the scorer already measures per repo (median response time, median merge time, external-merge ratio, pre-approval templates), and it fails asymmetrically: ollama (~176K), ragflow (~85K) and netdata (~80K) sit above any plausible cap, so it would silently delete the category DEFAULT_PROFILE exists to find.

The default path is a pure refactor

No preferences file means DEFAULT_PROFILE, whose five queries are byte-identical to the ones the agent carried inline (golden-file test, no network). /contribute, /contribute-loop and /contribution-fleet on a fresh machine cannot regress, because the queries are literally the same bytes. It deliberately keeps union semantics — generating it from the strict language AND topic shape would drop a Rust ML repo and an untagged Java repo from a fresh machine's candidate set, a composition change for users who never asked for one. The strict shape is opt-in.

One nudge line points at /preferences, shown once per install via a preferences_nudged key in the existing last_version.json.

Scoring

Category Preference Order and the 3e category bonus are deleted, not replaced. With filtering server-side every candidate matches by construction, so a bonus for matching is a constant added to every row and ranks nothing. Its 10% goes to signals that discriminate: responsiveness 30→35%, outside-contributor track 20→25%.

Testing

tests/scripts/test_parse_preferences.sh and test_build_queries.sh, both network-free and bash 3.2-clean, so they gate on ubuntu and macOS. They pin: exactly one topic: per query; query count == topic count; adding a language adds zero queries; the qualifier-key allowlist; no boolean operators (repeated language: is not one); no negation; no catch-all; floor-only stars; any compiles to a topic-less query; omitted topics:topics: any; per-entry floors override the global one; a ## Notes sentence changes no query; the nudge fires once; and byte-equality of the default profile.

No yq: scripts/profiler/parse_workflows.sh already depends on it and it is not installed on a stock macOS box. Since CI installs it, a second dependency would go green in CI and dead on the user's laptop. awk + jq only.

Verified live: a go, rust × cli, llm:5000, any profile returns only Go and Rust repos, one query per topic, with the 5K floor applied to llm alone.

Summary by CodeRabbit

  • New Features

    • Added user-configurable /preferences via ~/.superhuman/preferences.md (languages/topics/min stars) with advisory ## Notes.
    • Enhanced /repo-finder with per-run override flags (non-persistent) and deterministic repo/issue selection behavior.
  • Documentation

    • Expanded guidance across preference format, query compilation, and selection/tie-break rules; updated README and command docs.
  • Bug Fixes

    • Improved determinism and selection integrity (strict qualifier handling, no query widening, notes only as tie-break guidance), plus stronger shortlist/coverage reporting.
  • Tests / Chores

    • Added extensive shell regression tests for parsing, query building, curated-list filtering, schema validation, and zsh/bash safety; improved contributor/repo-finder args parsing.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change adds user-owned repository preferences, strict parsing and query compilation, run-scoped finder overrides, deterministic candidate and issue processing, shortlist and triage contract updates, and shell word-splitting regression coverage.

Changes

Repository discovery workflow

Layer / File(s) Summary
Preference format and parser
agents/SHARED_STATE.md, commands/preferences.md, scripts/lib/preferences.sh, tests/scripts/test_parse_preferences.sh, README.md, CONTRIBUTING.md
Defines the preferences format, validates filters, compiles normalized JSON, and documents persistence and ownership.
Preference-to-query compilation
scripts/repo-finder/build_queries.sh, tests/fixtures/default_queries.txt, tests/scripts/test_build_queries.sh, CHANGELOG.md, schemas/repo_shortlist.schema.json
Compiles validated preferences into deterministic GitHub queries with default handling, nudging, qualifier validation, and resolved criteria schema updates.
Run-scoped repository-finder overrides
commands/repo-finder.md, tests/scripts/test_repo_finder_args.sh, tests/scripts/test_repo_shortlist_schema.sh
Adds bounded CLI overrides, temporary preference validation, inherited values, cleanup, and shell-based rendering.
Candidate selection and shortlist contract
agents/repo-finder.md, scripts/repo-finder/curated_list_filter.sh, tests/scripts/test_curated_list_filter.sh
Updates candidate retrieval, curated-list filtering, scoring, issue selection, timeline batching, and shortlist output criteria.
Triage and runtime contracts
scripts/orchestrator/triage_filter.sh, scripts/orchestrator/reputation_gate.sh, tests/scripts/test_triage_filter.sh, tests/scripts/test_reputation_gate.sh, install.sh
Expands triage matching and kept-issue payloads, supports deriving the plugin root from the gate script location, and checks JSON-schema prerequisites.

Shell word-splitting safety

Layer / File(s) Summary
Line-oriented shell processing and regression coverage
agents/builder.md, agents/issue-selector.md, commands/contribution-fleet.md, scripts/lib/state.sh, tests/scripts/test_zsh_word_splitting.sh
Replaces unsafe unquoted iterations with line-oriented loops and tests fallback validation and related paths under zsh-style execution.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant Preferences
  participant RepoFinder
  participant QueryBuilder
  participant GitHub
  participant IssueSelection
  participant Shortlist
  User->>Preferences: author filters and notes
  RepoFinder->>Preferences: read resolved preferences
  RepoFinder->>QueryBuilder: compile and validate queries
  QueryBuilder-->>RepoFinder: deterministic search queries
  RepoFinder->>GitHub: search repositories and fetch issues
  GitHub-->>RepoFinder: projected candidates and timeline data
  RepoFinder->>IssueSelection: filter, score, and select issues
  IssueSelection-->>RepoFinder: ranked repository records
  RepoFinder->>Shortlist: validate and render shortlist JSON
Loading

Possibly related PRs

Suggested reviewers: gaurav0107

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: compiling repo-finder search filters from user preferences.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@imkp1 imkp1 force-pushed the feat/repo-finder-preferences branch from e69837a to acedffb Compare July 13, 2026 16:00

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
agents/repo-finder.md (1)

671-724: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Example criteria.queries array is inconsistent with the stated "one query per topic" rule.

The example lists two topic entries (backend, llm) but only one query string in queries, contradicting the rule stated just above it ("one search query per entry... Query count is |topics|"). This is illustrative-only, but a reader copying this shape would infer one query covers both topics.

📝 Proposed fix
-    "queries": ["language:go language:rust topic:backend stars:>2000 archived:false"],
+    "queries": [
+      "language:go language:rust topic:backend stars:>2000 archived:false",
+      "language:go language:rust topic:llm stars:>5000 archived:false"
+    ],
🤖 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 `@agents/repo-finder.md` around lines 671 - 724, Update the example
criteria.queries array so it contains one distinct search query for each topic
entry in criteria.topics, demonstrating separate queries for backend and llm
while preserving the resolved filters and other payload fields.
🧹 Nitpick comments (1)
commands/repo-finder.md (1)

76-86: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Ad hoc sed re-parses the saved preferences file instead of reusing the shared parser.

Extracting languages:/topics:/stars: via sed -n 's/^[[:space:]]*languages:[[:space:]]*//p' duplicates logic that scripts/lib/preferences.sh (sourced elsewhere for prefs_path(), per context) presumably already implements with proper validation/normalization. If the preferences file format gains quoting, comments, or multi-line values later, this sed-based reader silently drifts from the real parser's semantics instead of failing loudly.

Do you want me to check whether scripts/lib/preferences.sh already exposes a per-field accessor this wrapper could call instead?

🤖 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 `@commands/repo-finder.md` around lines 76 - 86, Replace the ad hoc sed
extraction in the LANGS, TOPICS, and MIN_STARS inheritance block with the shared
preferences parser/accessors from scripts/lib/preferences.sh. Reuse its existing
per-field lookup and normalization behavior for the saved profile, while
preserving the current rule that only unset command-line axes inherit saved
values.
🤖 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 `@agents/SHARED_STATE.md`:
- Around line 56-59: The agents/SHARED_STATE.md section at lines 56-59 should
describe global/ as repo-agnostic state, not exclusively plugin-owned or
machine-written state, while preserving the distinction that preferences.md is
user-owned. Update commands/preferences.md lines 6-8 to identify root-owned
preferences.md without claiming all global/ files are machine-written.

In `@commands/preferences.md`:
- Around line 10-11: Document that the default profile uses a >5K-star floor for
topic:llm while the ai-ml, java, python, and devtools searches use >20K. Update
prefs_summary in scripts/lib/preferences.sh and the one-time nudge in
scripts/repo-finder/build_queries.sh to describe these distinct active filters
accurately; apply the documentation change in commands/preferences.md as well.
- Around line 94-104: Update the topic-validation loop around the GitHub query
to normalize each topic before querying: strip any trailing numeric floor such
as “:5000”, skip the reserved “any” entry entirely, and use the normalized topic
in the search and warning message. Keep validation based on total_count for
actual GitHub topics.

In `@commands/repo-finder.md`:
- Around line 24-56: Update the argument tokenization around set -- $ARGUMENTS
to disable pathname expansion before parsing, while preserving the existing
whitespace splitting and case-based flag handling. Restore the shell’s prior
globbing state after tokenization so the rest of the script is unaffected.

In `@scripts/lib/preferences.sh`:
- Around line 135-172: Update the topic parsing flow around topic_list to track
whether any parsed topic is the literal “any” entry, then reject the
configuration with exit 10 when that entry is present and lang_list is empty.
Preserve existing topic validation and default-topic behavior, and add a
regression test covering empty languages with any.

---

Outside diff comments:
In `@agents/repo-finder.md`:
- Around line 671-724: Update the example criteria.queries array so it contains
one distinct search query for each topic entry in criteria.topics, demonstrating
separate queries for backend and llm while preserving the resolved filters and
other payload fields.

---

Nitpick comments:
In `@commands/repo-finder.md`:
- Around line 76-86: Replace the ad hoc sed extraction in the LANGS, TOPICS, and
MIN_STARS inheritance block with the shared preferences parser/accessors from
scripts/lib/preferences.sh. Reuse its existing per-field lookup and
normalization behavior for the saved profile, while preserving the current rule
that only unset command-line axes inherit saved values.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 70a05970-b7f4-403f-b7b7-2db17c6a728e

📥 Commits

Reviewing files that changed from the base of the PR and between a9ab17a and 5d94275.

📒 Files selected for processing (11)
  • agents/SHARED_STATE.md
  • agents/repo-finder.md
  • commands/preferences.md
  • commands/repo-finder.md
  • schemas/repo_shortlist.schema.json
  • scripts/lib/preferences.sh
  • scripts/repo-finder/build_queries.sh
  • tests/fixtures/default_queries.txt
  • tests/scripts/test_build_queries.sh
  • tests/scripts/test_parse_preferences.sh
  • tests/scripts/test_repo_shortlist_schema.sh

Comment thread agents/SHARED_STATE.md Outdated
Comment thread commands/preferences.md Outdated
Comment thread commands/preferences.md Outdated
Comment thread commands/repo-finder.md
Comment thread scripts/lib/preferences.sh Outdated
@imkp1 imkp1 force-pushed the feat/repo-finder-preferences branch from acedffb to 8838f62 Compare July 13, 2026 16:04

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
tests/scripts/test_build_queries.sh (1)

151-153: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Clarify that none.md is intentionally never created.

$tmpdir/none.md is referenced repeatedly (Lines 153, 193, 208-209, 216) as a nonexistent path standing in for "no preferences file exists," but no write none.md call ever creates it, and nothing states this is deliberate. A future contributor could easily "fix" this by adding a write none <<EOF ... EOF call, silently changing these tests from exercising the absent-file path to the present-empty-file path.

📝 Suggested clarifying comment
+# `none.md` is deliberately never created by `write` — its absence is what
+# exercises the "no preferences file" / DEFAULT_PROFILE path below.
 ALL="$tmpdir/all.txt"
 { run cross3; run anytopic; run floors
   bash "$BUILD" --file "$tmpdir/none.md" --no-nudge 2>/dev/null; } > "$ALL"

Also applies to: 190-194

🤖 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 `@tests/scripts/test_build_queries.sh` around lines 151 - 153, Add an explicit
comment near the first `$tmpdir/none.md` usage in the test setup stating that
`none.md` is intentionally not created and represents an absent preferences
file. Keep the existing references and test behavior unchanged so these cases
continue exercising the nonexistent-file path.
schemas/repo_shortlist.schema.json (1)

8-14: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Consider requiring criteria to enforce the disclosure guarantee it documents.

The criteria description explicitly frames this field as the audit trail for "what actually ran" — but it's not in the top-level required list, so a write path that drops it would still validate. Since the whole point of this feature is that a mismatch between intent and actual search is visible in the file, making it optional lets that guarantee silently lapse.

♻️ Suggested fix
-  "required": ["generated_at", "repos"],
+  "required": ["generated_at", "repos", "criteria"],
🤖 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 `@schemas/repo_shortlist.schema.json` around lines 8 - 14, Update the top-level
required list in the schema to include criteria alongside generated_at and
repos, preserving the existing criteria property definition and its disclosure
semantics.
🤖 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 `@agents/repo-finder.md`:
- Around line 686-688: Update the example queries associated with the topics
configuration so it contains one query per topic: retain the backend query with
its configured minimum stars and add the corresponding llm query using
stars:>5000, both preserving the existing language and archived filters. Ensure
the example’s criteria.queries count matches the two entries in topics.

---

Nitpick comments:
In `@schemas/repo_shortlist.schema.json`:
- Around line 8-14: Update the top-level required list in the schema to include
criteria alongside generated_at and repos, preserving the existing criteria
property definition and its disclosure semantics.

In `@tests/scripts/test_build_queries.sh`:
- Around line 151-153: Add an explicit comment near the first `$tmpdir/none.md`
usage in the test setup stating that `none.md` is intentionally not created and
represents an absent preferences file. Keep the existing references and test
behavior unchanged so these cases continue exercising the nonexistent-file path.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c60ef077-fa57-41b3-bcb6-9f61a4b7e702

📥 Commits

Reviewing files that changed from the base of the PR and between 5d94275 and 8838f62.

📒 Files selected for processing (15)
  • CHANGELOG.md
  • CONTRIBUTING.md
  • README.md
  • agents/SHARED_STATE.md
  • agents/repo-finder.md
  • commands/preferences.md
  • commands/repo-finder.md
  • schemas/repo_shortlist.schema.json
  • scripts/lib/preferences.sh
  • scripts/repo-finder/build_queries.sh
  • skills/superhuman/SKILL.md
  • tests/fixtures/default_queries.txt
  • tests/scripts/test_build_queries.sh
  • tests/scripts/test_parse_preferences.sh
  • tests/scripts/test_repo_shortlist_schema.sh
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests/fixtures/default_queries.txt
  • agents/SHARED_STATE.md
  • scripts/lib/preferences.sh

Comment thread agents/repo-finder.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
README.md (1)

179-180: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document /repo-finder overrides in the Codex equivalent table.

The adjacent mapping still shows only /repo-finder [N], so Codex users are not told how to pass the new language, topic, and min-stars per-run overrides documented elsewhere. Add the supported flags and clarify that they are not persisted.

🤖 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 `@README.md` around lines 179 - 180, Update the Codex equivalent table entry
for /repo-finder in README.md to document the supported per-run language, topic,
and min-stars overrides, and explicitly state that these flags are not
persisted. Keep the existing /repo-finder [N] behavior and adjacent mappings
unchanged.
🤖 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.

Outside diff comments:
In `@README.md`:
- Around line 179-180: Update the Codex equivalent table entry for /repo-finder
in README.md to document the supported per-run language, topic, and min-stars
overrides, and explicitly state that these flags are not persisted. Keep the
existing /repo-finder [N] behavior and adjacent mappings unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8fcdb126-2ccf-4b70-8921-cdcb03171ea0

📥 Commits

Reviewing files that changed from the base of the PR and between 8838f62 and edd6bd7.

📒 Files selected for processing (7)
  • README.md
  • agents/SHARED_STATE.md
  • commands/preferences.md
  • commands/repo-finder.md
  • scripts/lib/preferences.sh
  • scripts/repo-finder/build_queries.sh
  • tests/scripts/test_parse_preferences.sh
🚧 Files skipped from review as they are similar to previous changes (6)
  • agents/SHARED_STATE.md
  • scripts/lib/preferences.sh
  • commands/repo-finder.md
  • tests/scripts/test_parse_preferences.sh
  • commands/preferences.md
  • scripts/repo-finder/build_queries.sh

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/scripts/test_zsh_word_splitting.sh (1)

41-53: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Interpolated $ROOT/$tmp in zsh -c "..." (CWE-78 pattern, low real risk here).

Static analysis flags both zsh -c calls for splicing variables into the -c script string. In practice $ROOT (from pwd) and $tmp (from mktemp -d) aren't attacker-controlled in this test, so exploitability is minimal — but a repo path containing a stray quote would still break the test. Passing values as positional args instead of interpolating would harden this if you want to close the gap.

🤖 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 `@tests/scripts/test_zsh_word_splitting.sh` around lines 41 - 53, Harden both
zsh -c invocations in the validate_json checks by passing ROOT, tmp, and the
relevant filenames as positional arguments to the shell script instead of
interpolating them into the command string. Update the embedded script to
consume those arguments while preserving the existing valid-document acceptance
and missing-field rejection assertions.

Source: Linters/SAST tools

🤖 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 `@agents/issue-selector.md`:
- Around line 69-84: Update the NORM tokenization command in the label-filter
block to stop treating hyphens as delimiters by removing `-` from the `tr`
delimiter set. Preserve the existing case arms and newline splitting so
hyphenated labels such as `release-notes` and `copy-edit` remain intact and
match correctly.

---

Nitpick comments:
In `@tests/scripts/test_zsh_word_splitting.sh`:
- Around line 41-53: Harden both zsh -c invocations in the validate_json checks
by passing ROOT, tmp, and the relevant filenames as positional arguments to the
shell script instead of interpolating them into the command string. Update the
embedded script to consume those arguments while preserving the existing
valid-document acceptance and missing-field rejection assertions.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 27f538c4-cdbe-4360-a26a-b898f58ba817

📥 Commits

Reviewing files that changed from the base of the PR and between dc8e30c and d639582.

📒 Files selected for processing (7)
  • agents/builder.md
  • agents/issue-selector.md
  • agents/repo-finder.md
  • commands/contribution-fleet.md
  • commands/repo-finder.md
  • scripts/lib/state.sh
  • tests/scripts/test_zsh_word_splitting.sh
🚧 Files skipped from review as they are similar to previous changes (2)
  • commands/repo-finder.md
  • agents/repo-finder.md

Comment thread agents/issue-selector.md Outdated
@imkp1 imkp1 force-pushed the feat/repo-finder-preferences branch 3 times, most recently from 81e0c57 to fb86cb3 Compare July 14, 2026 17:49
@imkp1

imkp1 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 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 `@agents/repo-finder.md`:
- Around line 494-514: Remove the silent `|| echo '[]'` fallbacks and stderr
suppression from both label-filtered `gh issue list` calls in the `$ISSUES`
fetch block. Make failures from either command propagate under the documented
abort-on-error behavior, while preserving the existing union, deduplication, and
successful empty-result behavior for repositories without matching labels.

In `@commands/repo-finder.md`:
- Around line 131-138: Update the override validation block around
build_queries.sh so failures from build_queries.sh, including malformed
preferences, cannot be masked by the sed pipeline. Enable pipefail for this
command or separate the commands while preserving the existing Invalid override
cleanup and exit behavior.
- Around line 109-119: Scope the saved-value extraction in the LANGS, TOPICS,
and MIN_STARS inheritance blocks to the ## Filters section only, stopping before
the next section heading. Preserve the existing key-specific extraction and
fallback behavior while preventing matching lines in ## Notes or other sections
from being used as filters.

In `@README.md`:
- Around line 182-189: Update the default-profile description in the Usage
section to distinguish the topic:llm threshold: state that llm repositories use
the >5K-star cutoff while AI/ML, Java, Python, and dev-tools use >20K, matching
DEFAULT_PROFILE in build_queries.sh and the corresponding preferences
documentation.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7f533af3-a00d-4593-9f30-d0f581d39193

📥 Commits

Reviewing files that changed from the base of the PR and between dc8e30c and fb86cb3.

📒 Files selected for processing (27)
  • CHANGELOG.md
  • CONTRIBUTING.md
  • README.md
  • agents/SHARED_STATE.md
  • agents/builder.md
  • agents/issue-selector.md
  • agents/repo-finder.md
  • commands/contribution-fleet.md
  • commands/preferences.md
  • commands/repo-finder.md
  • schemas/repo_shortlist.schema.json
  • scripts/lib/preferences.sh
  • scripts/lib/state.sh
  • scripts/orchestrator/reputation_gate.sh
  • scripts/orchestrator/triage_filter.sh
  • scripts/repo-finder/build_queries.sh
  • scripts/repo-finder/curated_list_filter.sh
  • skills/superhuman/SKILL.md
  • tests/fixtures/default_queries.txt
  • tests/scripts/test_build_queries.sh
  • tests/scripts/test_curated_list_filter.sh
  • tests/scripts/test_parse_preferences.sh
  • tests/scripts/test_repo_finder_args.sh
  • tests/scripts/test_repo_shortlist_schema.sh
  • tests/scripts/test_reputation_gate.sh
  • tests/scripts/test_triage_filter.sh
  • tests/scripts/test_zsh_word_splitting.sh
🚧 Files skipped from review as they are similar to previous changes (9)
  • tests/fixtures/default_queries.txt
  • scripts/lib/state.sh
  • scripts/lib/preferences.sh
  • agents/SHARED_STATE.md
  • agents/builder.md
  • commands/contribution-fleet.md
  • agents/issue-selector.md
  • tests/scripts/test_build_queries.sh
  • CONTRIBUTING.md

Comment thread agents/repo-finder.md
Comment thread commands/repo-finder.md
Comment thread commands/repo-finder.md
Comment thread README.md
@imkp1 imkp1 force-pushed the feat/repo-finder-preferences branch from fb86cb3 to ac6523d Compare July 14, 2026 18:36

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (1)
scripts/repo-finder/build_queries.sh (1)

78-89: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Unquoted for tok in $q risks pathname expansion on glob metacharacters.

Word splitting on $q is intentional here, but it also enables pathname expansion. If a user's language:/topic: value contains a glob character (*, ?, [), this loop can silently expand it against files in the working directory instead of validating the literal token — defeating the "loud failure" guarantee this whole function exists to provide. None of the visible charset guards (boolean/paren/negation/ceiling checks) block glob metacharacters specifically.

🛡️ Proposed fix: disable globbing for the tokenizing loop
+  set -f
   for tok in $q; do
     case "$tok" in
       *:*) key="${tok%%:*}" ;;
       *)   die "bare word in query: '$tok' in '$q' (free text is not a filter)" ;;
     esac
     case "$key" in
       language) langs=$((langs + 1)) ;;
       topic)    topics=$((topics + 1)) ;;
       stars|archived) ;;
       *) die "unknown qualifier key '$key' in '$q' (allowed: language, topic, stars, archived)" ;;
     esac
   done
+  set +f

Please confirm whether scripts/lib/preferences.sh already restricts language/topic charset to exclude glob metacharacters — if so this is just defensive hardening; if not, it's a real gap.

🤖 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 `@scripts/repo-finder/build_queries.sh` around lines 78 - 89, Update the
tokenizing loop around the `for tok in $q` statement to disable pathname
expansion while preserving intentional word splitting, then restore the previous
globbing setting after the loop. Keep the existing qualifier validation and
`die` behavior unchanged, and verify whether `scripts/lib/preferences.sh`
already excludes glob metacharacters from language/topic values; if not, retain
this hardening as the required validation safeguard.
🤖 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 `@commands/preferences.md`:
- Line 160: Add the text language identifier to the fenced code block containing
the interactive compile-output example in preferences.md, preserving its
existing contents.

In `@commands/repo-finder.md`:
- Line 145: Update the Agent example code fence in repo-finder.md to include the
text language identifier, satisfying MD040 while preserving the example content.
- Around line 104-108: Replace predictable temporary paths with securely
allocated mktemp files: in commands/repo-finder.md lines 104-108 allocate
OVERRIDE exclusively, and in lines 122-129 write only to it and remove it via
cleanup traps on every exit path; in commands/preferences.md lines 117-123
securely allocate the live-check profile and query output, and in lines 188-191
securely create the persisted-file temporary path before atomic rename. Preserve
existing SAVED, OVERRIDE, and preference-processing behavior.

In `@README.md`:
- Line 186: Update the three newly added fenced code blocks in README.md to
include explicit language identifiers: use markdown, text, and bash
respectively, preserving each block’s existing contents.

In `@scripts/lib/preferences.sh`:
- Around line 135-189: Update the reserved-topic guard in the preferences parser
around topic_list construction and validation so it recognizes any topic entry
whose name is “any”, regardless of an optional star floor such as any:5000.
Reject it when lang_list is empty before build_queries emits output, preserving
the existing bare-any behavior; add a regression case in the parser tests
covering any:5000 with empty languages.

In `@tests/scripts/test_zsh_word_splitting.sh`:
- Around line 62-64: Broaden the unsafe shell-expansion pattern assigned to hits
in test_zsh_word_splitting.sh to detect braced and unbraced forms in for loops,
set --, and command substitutions, while allowing variable and function names
containing uppercase letters and digits. Preserve the existing exclusions and
failure behavior, or replace the regex check with an equivalent ShellCheck
SC2086-based validation.
- Around line 33-34: Update the zsh invocations around validate_json to keep the
-c script body constant and pass the root, schema, and valid-file paths as
positional arguments, referenced via $1, $2, and $3 inside the script. Apply the
same change to both affected test cases, preserving their existing validation
behavior while preventing path contents from being interpreted as shell syntax.

---

Nitpick comments:
In `@scripts/repo-finder/build_queries.sh`:
- Around line 78-89: Update the tokenizing loop around the `for tok in $q`
statement to disable pathname expansion while preserving intentional word
splitting, then restore the previous globbing setting after the loop. Keep the
existing qualifier validation and `die` behavior unchanged, and verify whether
`scripts/lib/preferences.sh` already excludes glob metacharacters from
language/topic values; if not, retain this hardening as the required validation
safeguard.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 617bd757-1e93-4377-84f6-562841433ffa

📥 Commits

Reviewing files that changed from the base of the PR and between fb86cb3 and ac6523d.

📒 Files selected for processing (27)
  • CHANGELOG.md
  • CONTRIBUTING.md
  • README.md
  • agents/SHARED_STATE.md
  • agents/builder.md
  • agents/issue-selector.md
  • agents/repo-finder.md
  • commands/contribution-fleet.md
  • commands/preferences.md
  • commands/repo-finder.md
  • schemas/repo_shortlist.schema.json
  • scripts/lib/preferences.sh
  • scripts/lib/state.sh
  • scripts/orchestrator/reputation_gate.sh
  • scripts/orchestrator/triage_filter.sh
  • scripts/repo-finder/build_queries.sh
  • scripts/repo-finder/curated_list_filter.sh
  • skills/superhuman/SKILL.md
  • tests/fixtures/default_queries.txt
  • tests/scripts/test_build_queries.sh
  • tests/scripts/test_curated_list_filter.sh
  • tests/scripts/test_parse_preferences.sh
  • tests/scripts/test_repo_finder_args.sh
  • tests/scripts/test_repo_shortlist_schema.sh
  • tests/scripts/test_reputation_gate.sh
  • tests/scripts/test_triage_filter.sh
  • tests/scripts/test_zsh_word_splitting.sh
🚧 Files skipped from review as they are similar to previous changes (13)
  • tests/scripts/test_repo_shortlist_schema.sh
  • CONTRIBUTING.md
  • agents/issue-selector.md
  • tests/fixtures/default_queries.txt
  • scripts/repo-finder/curated_list_filter.sh
  • scripts/lib/state.sh
  • scripts/orchestrator/triage_filter.sh
  • commands/contribution-fleet.md
  • agents/builder.md
  • schemas/repo_shortlist.schema.json
  • tests/scripts/test_triage_filter.sh
  • tests/scripts/test_build_queries.sh
  • agents/repo-finder.md

Comment thread commands/preferences.md Outdated
Comment thread commands/repo-finder.md
Comment thread commands/repo-finder.md Outdated
Comment thread README.md Outdated
Comment thread scripts/lib/preferences.sh Outdated
Comment thread tests/scripts/test_zsh_word_splitting.sh Outdated
Comment thread tests/scripts/test_zsh_word_splitting.sh Outdated
/repo-finder searched a hardcoded profile. It now compiles GitHub search
qualifiers from ~/.superhuman/preferences.md, authored by /preferences.

The file has two halves that bind differently. `## Filters` is mechanical:
build_queries.sh compiles languages, topics and a star floor 1:1 into qualifiers,
and rejects a profile it cannot compile rather than degrading to an unfiltered
scan. `## Notes` is advisory prose: it applies at tie-breaks and issue selection,
discloses itself in the shortlist's `notes` field when it does, and may never move
a numeric score.

Languages OR inside one query and cost nothing; topics AND, so each costs one
query — hence a 20-topic cap and no cap on languages. `stars` is a floor with no
ceiling: a ceiling guesses at what the responsiveness scorer already measures per
repo, and silently deletes the largest active repos.

Filters are read through parse_preferences, never by grepping the file: a `sed`
over the whole document also matches `## Notes`, so a profile whose Filters block
omits an axis would inherit prose into a hard filter. Per-run overrides compile
first and print second, so build_queries.sh's exit 10 is not swallowed by the
pipeline that formats its output.

Also in this change:

- curated_list_filter.sh: hard-skip curated lists and courses. Lists answer issues
  fast and merge outside PRs readily, so they score well on 60% of the rubric while
  offering nothing to contribute. Pedagogy topics are strong signals: `language=null`
  cannot fire on a profile that pins `languages:`, since every candidate then arrives
  from a query carrying `language:go language:python`.
- triage_filter.sh: Stage-A issue triage, with KEEP rows carrying the issue payload
  the Step-4 rubric scores and may not re-fetch.
- Stage-B timelines chunk at 20 GraphQL aliases; more exceed the node limit, which
  errors rather than truncating.
- The issue fetch no longer falls back to `[]` on error. An unused label already
  returns `[]` with exit 0, so the fallback only ever masked real failures.
- state.sh: warn when jsonschema is absent — the fallback checks top-level keys
  only, so a shortlist with null rows would validate clean.
@imkp1 imkp1 force-pushed the feat/repo-finder-preferences branch from ac6523d to 9fb88eb Compare July 15, 2026 03:32

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 `@commands/preferences.md`:
- Around line 95-145: Update the live query loop around the gh api invocation to
distinguish command failures from legitimate zero counts. Capture the API result
with explicit failure handling, emit an API-specific error, and exit or
otherwise stop the check when the request fails; only apply the existing
zero-result and ranking warnings when a successful response yields a numeric
total_count.

In `@tests/scripts/test_parse_preferences.sh`:
- Line 8: Update the CLAUDE_PLUGIN_ROOT assignment in test_parse_preferences.sh
to use the same CDPATH= and cd -- root-resolution pattern as the sibling test
scripts, preserving the existing dirname and path traversal behavior.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0c3a413d-6efb-462b-8b17-14550cfa422b

📥 Commits

Reviewing files that changed from the base of the PR and between ac6523d and 9fb88eb.

📒 Files selected for processing (27)
  • CHANGELOG.md
  • CONTRIBUTING.md
  • README.md
  • agents/SHARED_STATE.md
  • agents/builder.md
  • agents/issue-selector.md
  • agents/repo-finder.md
  • commands/contribution-fleet.md
  • commands/preferences.md
  • commands/repo-finder.md
  • schemas/repo_shortlist.schema.json
  • scripts/lib/preferences.sh
  • scripts/lib/state.sh
  • scripts/orchestrator/reputation_gate.sh
  • scripts/orchestrator/triage_filter.sh
  • scripts/repo-finder/build_queries.sh
  • scripts/repo-finder/curated_list_filter.sh
  • skills/superhuman/SKILL.md
  • tests/fixtures/default_queries.txt
  • tests/scripts/test_build_queries.sh
  • tests/scripts/test_curated_list_filter.sh
  • tests/scripts/test_parse_preferences.sh
  • tests/scripts/test_repo_finder_args.sh
  • tests/scripts/test_repo_shortlist_schema.sh
  • tests/scripts/test_reputation_gate.sh
  • tests/scripts/test_triage_filter.sh
  • tests/scripts/test_zsh_word_splitting.sh
🚧 Files skipped from review as they are similar to previous changes (17)
  • tests/fixtures/default_queries.txt
  • scripts/repo-finder/curated_list_filter.sh
  • agents/issue-selector.md
  • scripts/lib/state.sh
  • tests/scripts/test_repo_shortlist_schema.sh
  • agents/SHARED_STATE.md
  • tests/scripts/test_triage_filter.sh
  • schemas/repo_shortlist.schema.json
  • CONTRIBUTING.md
  • agents/builder.md
  • commands/contribution-fleet.md
  • scripts/orchestrator/triage_filter.sh
  • scripts/lib/preferences.sh
  • commands/repo-finder.md
  • README.md
  • tests/scripts/test_build_queries.sh
  • agents/repo-finder.md

Comment thread commands/preferences.md
Comment thread tests/scripts/test_parse_preferences.sh Outdated
imkp1 added 2 commits July 15, 2026 09:31
Distinguish gh api failures (rate limit / auth / network) from genuine
zero-result queries in the preferences live check, and add the CDPATH=/--
cd guard to test_parse_preferences.sh to match sibling test scripts.
…ll survivors with fill-to-N

gaurav0107#3: install.sh now installs the jsonschema Python package (escalating past
PEP 668), so validate_json runs the real schema validator on user machines
instead of silently degrading to a top-level-key check that cannot see inside
repos[]/scores/best_issue.

gaurav0107#2: Step 1 stops truncating to a fixed top-50 before scoring; Step 3 scores
every survivor in deterministic order; Step 4 walks the score-ranked list
filling until N repos are kept or survivors are exhausted, replacing the
hardcoded top-15 slice. A repo shortfall now means the field is thin, not that
the scan stopped early. Coverage {candidates, survivors, scored, returned} is
recorded in the shortlist (new optional schema field) and rendered, so a partial
scan is visible in the artifact.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@install.sh`:
- Around line 109-112: Update the jsonschema installation fallback in the
install.sh dependency-install flow to remove the unconditional
--break-system-packages attempt. Prefer installing into a project-owned virtual
environment, or only invoke that flag when an explicit user opt-in is enabled,
while preserving the existing non-breaking installation paths and failure
behavior.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ec810a18-e1d7-4a89-9666-764d14fc1d56

📥 Commits

Reviewing files that changed from the base of the PR and between fac199b and 462beb8.

📒 Files selected for processing (4)
  • agents/repo-finder.md
  • commands/repo-finder.md
  • install.sh
  • schemas/repo_shortlist.schema.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • schemas/repo_shortlist.schema.json
  • commands/repo-finder.md
  • agents/repo-finder.md

Comment thread install.sh
Comment on lines +109 to +112
python3 -m pip install --quiet jsonschema 2>/dev/null \
|| python3 -m pip install --quiet --user jsonschema 2>/dev/null \
|| python3 -m pip install --quiet --break-system-packages jsonschema 2>/dev/null \
|| true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate install.sh and inspect the relevant section with context.
git ls-files | rg '(^|/)install\.sh$'

# Show a compact map of the file first, then the surrounding lines.
FILE="$(git ls-files | rg '(^|/)install\.sh$' | head -n 1)"
echo "FILE=$FILE"
wc -l "$FILE"
sed -n '1,220p' "$FILE" | cat -n | sed -n '80,140p'

Repository: gaurav0107/superhuman

Length of output: 3459


🏁 Script executed:

#!/bin/bash
set -euo pipefail

git ls-files | rg '(^|/)install\.sh$'

Repository: gaurav0107/superhuman

Length of output: 170


Avoid automatic --break-system-packages fallback in install.sh:109-112.
This can alter a distro-managed Python environment once the normal install paths fail. Gate it behind explicit user opt-in or use a project-owned virtual environment instead.

🤖 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 `@install.sh` around lines 109 - 112, Update the jsonschema installation
fallback in the install.sh dependency-install flow to remove the unconditional
--break-system-packages attempt. Prefer installing into a project-owned virtual
environment, or only invoke that flag when an explicit user opt-in is enabled,
while preserving the existing non-breaking installation paths and failure
behavior.

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