You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3.2 KiB
3.2 KiB
gimme-job Project Rules for Claude Code
Core Principles
-
gimme-job is an "AI-assisted learning, non-AI runtime" project.
- During runtime scraping, only adapter code and manifest YAML files are used — no AI calls.
- Claude Code is invoked ONLY when learning a new site or repairing a broken adapter.
-
Runtime must never require AI.
- All adapters must work with pure Python + Playwright, reading from site manifests.
- Do not add AI/LLM calls inside adapter
prepare(),apply_search(),apply_filters(),collect_cards(),paginate(), ornormalize().
-
Use Chrome persistent profile
JobAgentfor browser automation.- Always use
playwright.chromium.launch_persistent_context()withuser_data_dirpointing toworkspace/chrome-profiles/JobAgent/. - Never use
browser.new_context()orplaywright.chromium.launch()directly.
- Always use
-
Do not introduce
storage_stateas a new strategy.- Chrome profile reuse is the only session persistence mechanism.
-
Summarization uses Ollama
qwen3.5:9bonly.- No other LLM should be called during the run pipeline.
-
Final notification target is KakaoTalk self-memo.
- Fall back to local Markdown file only when KakaoTalk fails.
-
When a site fails, set
repair_needed=True— never silently ignore failures.- After 2 consecutive failures, mark the site as
repair_needed. repair_neededsites are skipped duringrun, noted in the summary.
- After 2 consecutive failures, mark the site as
-
Selector robustness rules:
- Prefer
aria-label,data-*attributes, and semantic HTML over CSS class names. - Avoid brittle
nth-childselectors unless no better option exists. - Always define fallback selectors (list multiple selectors per field).
- Handle zero-result states explicitly —
ZERO_RESULTS_EXPECTEDis a normal exit.
- Prefer
When Generating or Patching Adapters
Each site adapter must implement the BaseJobSiteAdapter protocol from gimme_job/adapters/base.py:
prepare(page, config)— navigate to start URL, wait for page readinessapply_search(page, query)— inject keywords/locationapply_filters(page, query)— apply date/type filters via UIcollect_cards(page, config)— extract all visible job cards asRawJobCardpaginate(page, page_index, config)— advance to next page, returnFalsewhen donenormalize(raw)— clean/normalize aRawJobCardintoJobPostingCandidate
Each site also requires:
sites/{site_id}.yaml— manifest YAMLgimme_job/adapters/{site_id}.py— adapter Python filetests/adapters/test_{site_id}.py— smoke testworkspace/manifests/{site_id}.learning-report.md— learning report
The smoke test must verify:
- The search page opens successfully
- Either result cards are detected OR a zero-result state is explicitly handled
- At least 2 fields can be extracted from a card (or zero-result confirmed)
File Locations
- Site manifests:
sites/{site_id}.yaml - Adapters:
gimme_job/adapters/{site_id}.py - Adapter tests:
tests/adapters/test_{site_id}.py - Prompts:
gimme_job/prompts/ - Templates:
gimme_job/templates/ - Workspace artifacts:
workspace/(captures, traces, screenshots, dom, manifests, generated) - Database: configured via
GIMME_JOB_DB_PATHenv var (default:gimme_job.db)