Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions .github/workflows/discovery.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Candidate Discovery

on:
schedule:
- cron: "20 14 * * *"
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

permissions:
contents: write

jobs:
discover:
runs-on: ubuntu-latest
name: Update discovered candidates
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd

- name: Set up uv
uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff
with:
enable-cache: true

- name: Install Python tooling
run: cd python && uv sync --locked

- name: Discover candidates
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
cd python
uv run python -m lean_pool.aggregator discover \
--discovered ../candidates/discovered.yml

- name: Commit new discoveries
run: |
if git diff --quiet -- candidates/discovered.yml; then
echo "No new discoveries."
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add candidates/discovered.yml
git commit -m "Update discovered Lean candidates"
git push
3 changes: 3 additions & 0 deletions candidates/discovered.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
version: 1
github: {}
arxiv: {}
10 changes: 10 additions & 0 deletions python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,14 @@ uv run pytest # run tests
uv run ruff check # lint
uv run ruff format # format
uv run python -m lean_pool.quality --repo .. # repository quality gates
uv run python -m lean_pool.aggregator discover
```

## Candidate discovery

`.github/workflows/discovery.yml` runs daily at 14:20 UTC and updates
`candidates/discovered.yml` with recent GitHub/arXiv Lean project
matches.

The YAML file is keyed by canonical GitHub repository and arXiv ID, so
reruns add only new discoveries instead of appending duplicates.
127 changes: 127 additions & 0 deletions python/lean_pool/aggregator/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
``raw_data/clones/`` so downstream classification can read source
files locally.
- ``render``: regenerate the candidates README table from those files.
- ``discover``: query GitHub and arXiv for recent untracked Lean
projects and add them to ``candidates/discovered.yml``.
"""

import json
Expand All @@ -20,6 +22,17 @@
DEFAULT_PARALLELISM,
clone_all,
)
from lean_pool.aggregator.discovery import (
DEFAULT_LOOKBACK_DAYS,
github_token_from_environment,
load_known_repository_keys,
render_discovery_report,
save_discovery_report,
update_discovered_file,
)
from lean_pool.aggregator.discovery import (
discover as run_discovery,
)
from lean_pool.aggregator.manual import (
fetch_manual_packages,
load_manual_packages,
Expand Down Expand Up @@ -48,6 +61,7 @@
DEFAULT_DECISIONS = CANDIDATES_DIR / "decisions.jsonl"
DEFAULT_README = CANDIDATES_DIR / "README.md"
DEFAULT_PROJECTS_YML = REPO_ROOT / "LeanPool" / "projects.yml"
DEFAULT_DISCOVERED = CANDIDATES_DIR / "discovered.yml"


@click.group()
Expand Down Expand Up @@ -285,5 +299,118 @@ def render(
)


@cli.command("discover")
@click.option(
"--lookback-days",
type=int,
default=DEFAULT_LOOKBACK_DAYS,
show_default=True,
help="How many days of GitHub and arXiv activity to scan.",
)
@click.option(
"--manifest",
"manifest_path",
type=click.Path(dir_okay=False, path_type=Path),
default=DEFAULT_MANIFEST,
show_default=True,
help="Reservoir manifest JSON used to suppress already-tracked repos.",
)
@click.option(
"--manual-list",
"manual_list_path",
type=click.Path(dir_okay=False, path_type=Path),
default=DEFAULT_MANUAL_LIST,
show_default=True,
help="Manual GitHub URL list used to suppress already-tracked repos.",
)
@click.option(
"--manual-data",
"manual_data_path",
type=click.Path(dir_okay=False, path_type=Path),
default=DEFAULT_MANUAL_DATA,
show_default=True,
help="Manual package metadata used to suppress already-tracked repos.",
)
@click.option(
"--projects-yml",
"projects_yml_path",
type=click.Path(dir_okay=False, path_type=Path),
default=DEFAULT_PROJECTS_YML,
show_default=True,
help="Lean Pool project registry used to suppress already-merged repos.",
)
@click.option(
"--include-known/--skip-known",
default=False,
show_default=True,
help="Include repositories that are already tracked locally.",
)
@click.option(
"--max-github-results-per-query",
type=int,
default=100,
show_default=True,
help="Maximum GitHub search results fetched for each query.",
)
@click.option(
"--output",
"output_path",
type=click.Path(dir_okay=False, path_type=Path),
default=None,
help="Optional local markdown report path.",
)
@click.option(
"--discovered",
"discovered_path",
type=click.Path(dir_okay=False, path_type=Path),
default=DEFAULT_DISCOVERED,
show_default=True,
help="YAML file to update with newly discovered GitHub/arXiv entries.",
)
def discover(
lookback_days: int,
manifest_path: Path,
manual_list_path: Path,
manual_data_path: Path,
projects_yml_path: Path,
include_known: bool,
max_github_results_per_query: int,
output_path: Path | None,
discovered_path: Path,
) -> None:
"""Query GitHub/arXiv for recent untracked Lean projects."""
known = load_known_repository_keys(
manifest_path=manifest_path,
manual_list_path=manual_list_path,
manual_data_path=manual_data_path,
projects_yml_path=projects_yml_path,
)
result = run_discovery(
lookback_days=lookback_days,
known_repositories=set(known),
github_token=github_token_from_environment(),
include_known=include_known,
max_github_results_per_query=max_github_results_per_query,
)
report = render_discovery_report(result)
if output_path is not None:
save_discovery_report(report, output_path)
update = update_discovered_file(result, discovered_path)

candidate_count = sum(
1 for repository in result.github_repositories if repository.signal != "low"
)
click.echo(
f"Discovery found {candidate_count} candidate repos, "
f"{len(result.github_repositories)} untracked repos total, "
f"{len(result.arxiv_papers)} arXiv matches, and skipped "
f"{result.known_repositories_skipped} known repos."
)
click.echo(
f"Updated {discovered_path}: {update.added_github} new GitHub repos, "
f"{update.added_arxiv} new arXiv papers."
)


if __name__ == "__main__":
cli()
Loading
Loading