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
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ change its layout or introduction.
- Ten most recently published GitHub Releases across all public repos. Drafts
are excluded; prereleases are labeled. Git tags without a release do not appear.
- Five latest posts from [the writing RSS feed](https://2389.ai/research/writing/index.xml).
- Ten public repos with the most stars, with counts, descriptions, and fork/archive
labels. Ties sort alphabetically, ignoring case first. All public repos qualify;
star counts come from the existing repository requests.
- An alphabetical, expandable directory of **every public repo**, including
forks and archived projects. Repository and release requests fetch all pages.

Expand Down
25 changes: 25 additions & 0 deletions docs/superpowers/plans/2026-10-04-profile.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,28 @@ Owner: orchestrator after generator interfaces are settled.
- Independent review: spec, code quality, and workflow integration approved with no findings. Parent fresh-eyes review found no additional issues. Generated Markdown renders through GitHub's Markdown API.
- Second live generation returned `Unchanged`. GitHub browser inspection confirmed desktop/mobile rendering, an expandable directory with 117 entries, and no horizontal overflow at a 390px viewport.
- Implementation committed as `da4382b`; [draft PR #1](https://github.com/2389-research/.github/pull/1) opened. Both initial GitHub CI runs passed. Next step: review and merge; the default-branch schedule is not active until then. Compaction count: 0.

## Follow-up: top starred repos

Doctor Biz merged PR #1 and requested a section near the bottom for top-starred repos.
Add `## Top starred repos` immediately before the repository directory. Show ten
public repositories sorted by descending `stargazers_count`, then case-insensitive
name and exact name for stable ties. Include star counts and existing descriptions,
with the same archived/fork labels as the directory. Use all public repositories;
do not add filtering beyond the current privacy filter. Reuse the current API
responses and daily workflow. Validate star counts as nonnegative integers.

- [x] TDD: ranking, numeric counts, tie order, ten-item limit, public-only selection,
section placement, invalid counts, and HTTP collection through rendering.
- [x] Implement the small model/parser/render change; document the section and
extend the real API E2E check for star counts and descending order.
- [x] Run `scripts/check`, live E2E, generate the profile, and inspect its rendering.
- [x] Review the follow-up for delivery on `feat/top-starred-repos`; leave merging
to Doctor Biz.

Validation: 18 offline tests, Ruff format/lint, strict mypy, and actionlint pass.
Live E2E passes against real APIs; GitHub's Markdown renderer shows ten ranked
entries immediately before the directory. Review caught and fixed a test that
compared star counts across separate live reads. Independent re-review and
fresh-eyes review have no remaining findings. The existing daily job refreshes
the new section without workflow changes.
1 change: 1 addition & 0 deletions gotchas.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
- Research posts come from `https://2389.ai/research/writing/index.xml`. The parent research feed was empty when checked on 2026-10-04.
- “Tagged releases” means published GitHub Releases, confirmed by Doctor Biz. Draft releases and private repositories must never appear.
- The org already exceeds GitHub's 100-repo page size. Fetch every page before generating the directory.
- The top-starred section uses `stargazers_count` from the same repository responses. Star counts can change between live API reads; exact ranking expectations belong in stable fixture tests.
13 changes: 13 additions & 0 deletions profile/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@ We're an applied AI lab in Chicago. We build tools for agents, share our researc
- [Tracker Runner: a control plane for Tracker pipelines](https://2389.ai/research/writing/tracker-runner/) — 2026-09-10
- [Tracker Grew Up: Two Months of Making Agent Pipelines Boring](https://2389.ai/research/writing/tracker-grew-up/) — 2026-09-08

## Top starred repos

- [claude\-plugins](https://github.com/2389-research/claude-plugins) — 28 plugins and MCP servers for Claude Code — TDD, multi\-agent orchestration, iterative refinement, binary RE, structured decisions\. Install any skill in one command\. — 95 stars
- [dippin\-lang](https://github.com/2389-research/dippin-lang) — Dippin: a DSL for authoring AI pipeline workflows — 32 stars
- [landing\-page\-design](https://github.com/2389-research/landing-page-design) — Create high\-converting, visually distinctive landing pages with Vibe Discovery process and anti\-AI\-slop principles — 21 stars
- [tracker](https://github.com/2389-research/tracker) — 21 stars
- [binary\-re](https://github.com/2389-research/binary-re) — Agentic binary reverse engineering for ELF binaries on ARM64, ARMv7, x86\_64 \- hypothesis\-driven analysis with radare2, Ghidra, GDB, QEMU — 18 stars
- [thrifty](https://github.com/2389-research/thrifty) — Tiered\-delegation task execution for Claude Code: strong model plans, cheap models execute in parallel, mid model verifies against acceptance criteria\. — 17 stars
- [simmer](https://github.com/2389-research/simmer) — Iterative artifact refinement with investigation\-first judge board \- constructs problem\-specific judges that read the code, understand the problem, and propose evidence\-based improvements — 15 stars
- [mcp\-socialmedia](https://github.com/2389-research/mcp-socialmedia) — 14 stars
- [summarize\-meetings](https://github.com/2389-research/summarize-meetings) — Batch\-process meeting transcripts from Obsidian vault into structured summaries with knowledge graph updates, people notes, and concept extraction — 13 stars
- [review\-squad](https://github.com/2389-research/review-squad) — Dispatch panels of specialized subagents to review projects — expert audits, first\-impression personas, task\-completion flows, and pedantic nitpicks — 12 stars

## Repository directory

<details>
Expand Down
14 changes: 14 additions & 0 deletions profile/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class Repository:
archived: bool
fork: bool
pushed: datetime | None
stars: int


@dataclass(frozen=True)
Expand Down Expand Up @@ -86,6 +87,9 @@ def parse_repositories(records: list[dict[str, Any]]) -> list[Repository]:
description = record.get("description")
if description is not None and not isinstance(description, str):
raise ValueError("Invalid repository description")
stars = record.get("stargazers_count")
if type(stars) is not int or stars < 0:
raise ValueError("Missing or invalid stargazers_count")
repositories.append(
Repository(
text_field(record, "name"),
Expand All @@ -96,6 +100,7 @@ def parse_repositories(records: list[dict[str, Any]]) -> list[Repository]:
timestamp(text_field(record, "pushed_at"))
if record.get("pushed_at") is not None
else None,
stars,
)
)
return repositories
Expand Down Expand Up @@ -283,6 +288,15 @@ def render_profile(
)
if not posts:
lines.append("No research posts yet.")
lines.extend(["", "## Top starred repos", ""])
top_starred = sorted(
repositories, key=lambda r: (-r.stars, r.name.casefold(), r.name)
)[:10]
lines.extend(
f"{repository_line(repo)} — {repo.stars} stars" for repo in top_starred
)
if not top_starred:
lines.append("No public repositories yet.")
lines.extend(
[
"",
Expand Down
22 changes: 20 additions & 2 deletions tests/e2e_generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ def test_public_sources_generate_complete_profile(self) -> None:
if token:
headers["Authorization"] = f"Bearer {token}"
url = "https://api.github.com/orgs/2389-research/repos?type=public&per_page=100"
names: list[str] = []
names: set[str] = set()
while url:
with urlopen(Request(url, headers=headers), timeout=30) as response:
names.extend(
names.update(
repo["name"] for repo in json.load(response) if not repo["private"]
)
next_page = re.search(
Expand Down Expand Up @@ -54,6 +54,24 @@ def test_public_sources_generate_complete_profile(self) -> None:
self.assertIn(
f"](https://github.com/2389-research/{name})", directory_section
)
self.assertIn("## Top starred repos", content)
top_starred = content.split("## Top starred repos")[1].split("## ")[0]
ranked = re.findall(
r"^- \[.*\]\(https://github.com/2389-research/([^)]*)\)"
r".* — (\d+) stars$",
top_starred,
re.MULTILINE,
)
ranking = [(name, int(count)) for name, count in ranked]
self.assertEqual(len(ranking), min(10, len(names)))
self.assertEqual(len({name for name, _ in ranking}), len(ranking))
for name, count in ranking:
self.assertIn(name, names)
self.assertGreaterEqual(count, 0)
self.assertEqual(
ranking,
sorted(ranking, key=lambda row: (-row[1], row[0].casefold(), row[0])),
)
releases = content.split("## Latest releases")[1].split("## ")[0]
self.assertIn("/releases/tag/", releases)
self.assertGreater(releases.count("- ["), 0)
Expand Down
90 changes: 90 additions & 0 deletions tests/test_generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def repo(name: str, **fields: Any) -> dict[str, Any]:
"archived": False,
"fork": False,
"pushed_at": "2026-01-01T00:00:00Z",
"stargazers_count": 0,
**fields,
}

Expand Down Expand Up @@ -77,6 +78,69 @@ def test_directory_is_complete_sorted_and_labels_archives_and_forks(self) -> Non
self.assertIn("fork", directory)
self.assertNotIn("private", directory)

def test_top_starred_ranks_numerically_limits_to_ten_and_breaks_ties(self) -> None:
records = [repo(f"repo-{n}", stargazers_count=n) for n in range(10)]
records += [
repo("zeta", stargazers_count=100),
repo("beta", stargazers_count=20),
repo("alpha", stargazers_count=20),
repo("Alpha", stargazers_count=20),
]
output = generate.render_profile(generate.parse_repositories(records), [], [])
self.assertIn("## Top starred repos", output)
section = output.split("## Top starred repos")[1].split("## ")[0]
lines = [line for line in section.splitlines() if line.startswith("- [")]
expected = ["zeta", "Alpha", "alpha", "beta"] + [
f"repo-{n}" for n in range(9, 3, -1)
]
self.assertEqual(len(lines), 10)
for line, name in zip(lines, expected, strict=True):
self.assertIn(f"](https://github.com/2389-research/{name})", line)
self.assertTrue(lines[0].endswith(" — 100 stars"))
self.assertTrue(lines[-1].endswith(" — 4 stars"))
self.assertEqual(
output.split("## Top starred repos")[1].split("## ")[1].splitlines()[0],
"Repository directory",
)

def test_top_starred_includes_all_public_repo_types_and_existing_labels(
self,
) -> None:
records = [
repo("archive", archived=True, stargazers_count=4),
repo("fork", fork=True, stargazers_count=3),
repo(".github", stargazers_count=2),
repo("empty", pushed_at=None, stargazers_count=0),
repo("secret", private=True, stargazers_count=100),
]
output = generate.render_profile(generate.parse_repositories(records), [], [])
self.assertIn("## Top starred repos", output)
section = output.split("## Top starred repos")[1].split("## ")[0]
self.assertEqual(section.count("- ["), 4)
self.assertIn("(archived) — Useful code — 4 stars", section)
self.assertIn("(fork) — Useful code — 3 stars", section)
self.assertIn("/2389-research/.github)", section)
self.assertIn("/2389-research/empty) — Useful code — 0 stars", section)
self.assertNotIn("secret", section)

def test_repository_star_counts_must_be_nonnegative_integers(self) -> None:
for count in [-1, 1.5, "5", None, True, False]:
with (
self.subTest(count=count),
self.assertRaisesRegex(ValueError, "stargazers_count"),
):
generate.parse_repositories([repo("alpha", stargazers_count=count)])
record = repo("alpha")
del record["stargazers_count"]
with self.assertRaisesRegex(ValueError, "stargazers_count"):
generate.parse_repositories([record])

def test_top_starred_empty_state(self) -> None:
output = generate.render_profile([], [], [])
self.assertIn("## Top starred repos", output)
section = output.split("## Top starred repos")[1].split("## ")[0]
self.assertIn("No public repositories yet.", section)

def test_recent_activity_uses_push_time_and_limits_to_eight_active_repos(
self,
) -> None:
Expand Down Expand Up @@ -302,6 +366,32 @@ def test_bad_or_failed_sources_preserve_output(self) -> None:
)
self.assertEqual(path.read_text(), "last good profile\n")

def test_refresh_renders_star_counts_from_every_repository_page(self) -> None:
self.respond(
"/orgs/2389-research/repos?type=public&per_page=100",
[repo("alpha", stargazers_count=9)],
Link=f'<{self.base}/page2>; rel="next"',
)
self.respond(
"/page2",
[
repo("beta", stargazers_count=100, archived=True, fork=True),
repo("secret", private=True, stargazers_count=999),
],
)
self.respond("/repos/2389-research/beta/releases?per_page=100", [])
with tempfile.TemporaryDirectory() as directory:
path = Path(directory) / "README.md"
generate.refresh(path, api_url=self.base, feed_url=f"{self.base}/feed")
output = path.read_text()
self.assertIn("## Top starred repos", output)
section = output.split("## Top starred repos")[1].split("## ")[0]
self.assertLess(section.index("beta"), section.index("alpha"))
self.assertIn("(archived, fork) — Useful code — 100 stars", section)
self.assertIn("Useful code — 9 stars", section)
self.assertNotIn("secret", output)
self.assertEqual(len(self.requests), 5)

def test_http_failure_reports_status_without_retaining_open_response(self) -> None:
self.responses["/failure"] = (503, b"unavailable", {})
with self.assertRaisesRegex(OSError, "HTTP 503 from") as failure:
Expand Down
Loading