mirror of
https://github.com/prdlk/leetcode.git
synced 2026-09-16 23:16:26 +00:00
7.0 KiB
7.0 KiB
Repository Guidelines
Project Overview
LeetCode interview-prep campaign (8 weeks, 2026-08-17 → Oct 11) run as a repo: solution files under work/, a Blume docs site under docs/, and GitHub Actions automation that reconciles issues, publishes docs, and drives a spaced-repetition system (SRS). Issues model the curriculum: ~24 topic issues own ~161 problem sub-issues (set:core|optional|deferred, diff:*); milestones are phases; a user-level GitHub Project ("Interview Prep", #2) mirrors review state.
Architecture & Data Flow
Two subsystems, one direction of truth:
flowchart LR
work[work/ solutions] -->|bun run sync| docs[docs/solutions/*.mdx]
work -->|close-solved.yml| PI[problem issues]
PI -->|close-topics.yml| TI[topic issues]
SRS[.github/srs/srs.json] -->|srs-scheduler| Today[📋 Today issue]
Today -->|/done comments| Logger[srs-logger] --> SRS
SRS -->|mirror, best-effort| Proj[GitHub Project fields]
SRS -->|gate.yml| Gate[weekly gate issue + docs/gate-log.md]
- Reconcile, don't react.
close-solved.ts,close-topics.ts, and the SRS scripts recompute desired state from scratch each run: re-runs are no-ops, backfills need no special casing, closing is one-directional (nothing ever reopens). .github/srs/srs.jsonis the single source of truth. Project fields (Target Date,SRS Stage,First Attempt) are a best-effort mirror viascripts/srs-project.ts: every GraphQL failure becomes a warning, never an error — an srs.json update must never be lost to a mirror failure. Topic rows'Target Dateis never written (problem rows only).- Determinism = idempotency. Drill/gate sampling uses a seeded PRNG (
rng()insrs.ts, FNV-1a → mulberry32, seed = date / ISO week), so running a workflow twice picks identical problems. - Chained workflows:
GITHUB_TOKEN-driven issue closes fire noissuesevents, soclose-topics.ymlchains offworkflow_runof Close Solved instead.
Key Directories
| Path | Purpose |
|---|---|
work/<Difficulty>/<Category>/<num>.<slug>.{js,py} |
Solutions, e.g. work/Easy/Array/1.two-sum.py. Machine-parsed header comment (title / Difficulty: / URL / ─ rule / statement) — preserve its exact shape |
scripts/ |
Flat Bun TS: automation entries (shebang + top-level await) and libraries (no shebang, side-effect-free on import) |
docs/ |
Blume site. docs/solutions/(<category>)/<num>-<slug>.mdx generated by sync; (algorithms)/, (data-structures)/ hand-written explainers |
.github/srs/ |
Machine state: srs.json (bot-committed), schedule.json (day → topic issue, human-edited), badge.json (shields endpoint) |
.github/workflows/ |
deploy, close-solved, close-topics, srs-scheduler, srs-logger, gate, srs-setup |
Development Commands
bun run pick # scaffold a solution via leetcode-cli (fuzzy picker)
bun run test # run ONE solution against LeetCode's judge (not a test suite)
bun run sync # work/ → docs/solutions/ pages
bun run dev|build # Blume docs site
bun run close-solved -- --dry-run # issue reconcilers (also DRY_RUN=1)
bun run close-topics -- --dry-run
SRS_DRY=1 SRS_TODAY=2026-08-30 bun scripts/srs-scheduler.ts # preview a brief
bun scripts/srs-logger.ts --issue N --author prdlk --body "/done 704 pass"
bun scripts/srs-gate.ts create|close --issue N
Code Conventions & Common Patterns
- Scripts are either entries or libraries. Entries (
close-*.ts,srs-scheduler|logger|gate|setup.ts) use shebang + top-levelawaitand run their pipeline linearly. Libraries (github.ts,report.ts,srs.ts,srs-project.ts) must stay side-effect-free on import — nothing touches network/credentials until a factory (github(),projectMirror()) is awaited. - Shared plumbing:
github()givesrepo,api()(throwsMETHOD path -> status body),list()(paginating async generator),closeIssue()(comment first, then close — a failed PATCH still leaves a trace).report.tsgivesprintTable/markdownTable/writeStepSummary. - Narrow API payloads with guards, not inline casts:
if (!("number" in value) || typeof value.number !== "number") return;(seereadProblemIssueinclose-solved.ts). Named-const casts only with a reason. - Dry-run everything: reconcilers take
--dry-run/DRY_RUN=1; SRS takesSRS_DRY=1plus overridesSRS_TODAY,SRS_STATE,SRS_SCHEDULE,SRS_GATE_LOG,SRS_BADGE— pointSRS_STATEat a scratch copy to exercise logic safely. - Dates: always ET calendar strings (
YYYY-MM-DD), arithmetic anchored at noon UTC (atNooninsrs.ts) to dodge DST. Nevernew Date()math directly. - Style: section-divider comments (
// ── name ───), file-top doc comments explaining the why and invariants, 2-space JSON with trailing newline,Mapfor dynamic keys /Recordfor static tables, no tiny one-expression wrapper functions. - Known intentional duplication:
close-solved.tsre-implements header stripping instead of importing fromsync.tsbecausesync.tsruns its pipeline on import. Don't "deduplicate" it.
Important Files
scripts/srs.ts— SRS domain: ladder (new → +2 → +5 → +10 → retired; fail resets to+2),fetchCatalog()(walks topic sub-issues, parsesLC <n> · <name> · <diff> · <set>titles), campaign math (CAMPAIGN_START).scripts/sync.ts— work→docs contract: only## Solutiononward is script-owned on existing pages; human prose is never touched; never hand-write solution pages or edit inside## Solution..github/srs/srs.json,docs/gate-log.md,.github/srs/badge.json— bot-committed (github-actions[bot],[skip ci]). Don't hand-edit; fix via scripts.blume.config.ts— site base/leetcode;README.mdcampaign table doubles as topic-map input tosync.ts(readmeTopics(),TOPIC_ALIASES).- Workflows share concurrency group
srs-state(never race on srs.json);PROJECT_PATsecret is required for user-Project GraphQL (defaultGITHUB_TOKENcannot), used by srs-scheduler/logger/setup only.
Runtime/Tooling Preferences
- Bun only: run scripts with
bun scripts/<name>.ts, install withbun install --frozen-lockfile;bun.lockis the sole lockfile. Node 22 appears only indeploy.ymlbecause Blume requires it. - No tsconfig, no ESLint, no Prettier — match surrounding style by hand.
@types/bunis the only type dependency. - Automation workflows skip
bun install(scripts use Bun builtins +fetchonly) — keep new automation dependency-free. - Local GitHub auth falls back to
gh auth token; scripts run fine outside Actions.
Testing & QA
- No test framework, no
*.test.*files —bun run testsubmits one solution to LeetCode's judge. - QA is dry-runs + scratch state: verify schedulers/reconcilers with
--dry-run/SRS_DRY=1and a copiedSRS_STATEbefore live runs; idempotency check = run twice,cmpoutput. - Docs changes:
bunx blume build --isolatedmust pass with no new warnings (thenrm -rf .blume-verify); after sync, review only created pages (prose transforms are heuristic).