kestrel-agent 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. kestrel_agent-0.1.0/.env.example +18 -0
  2. kestrel_agent-0.1.0/.github/workflows/ci.yml +41 -0
  3. kestrel_agent-0.1.0/.github/workflows/publish.yml +56 -0
  4. kestrel_agent-0.1.0/.gitignore +49 -0
  5. kestrel_agent-0.1.0/CHANGELOG.md +58 -0
  6. kestrel_agent-0.1.0/CONTRIBUTING.md +118 -0
  7. kestrel_agent-0.1.0/LICENSE +661 -0
  8. kestrel_agent-0.1.0/NOTICE +21 -0
  9. kestrel_agent-0.1.0/PKG-INFO +143 -0
  10. kestrel_agent-0.1.0/PRIVACY.md +44 -0
  11. kestrel_agent-0.1.0/README.md +95 -0
  12. kestrel_agent-0.1.0/SECURITY.md +76 -0
  13. kestrel_agent-0.1.0/docs/assets/README.md +65 -0
  14. kestrel_agent-0.1.0/docs/assets/kestrel-mark.png +0 -0
  15. kestrel_agent-0.1.0/docs/assets/kestrel-wordmark.png +0 -0
  16. kestrel_agent-0.1.0/profile.example.json +61 -0
  17. kestrel_agent-0.1.0/pyproject.toml +97 -0
  18. kestrel_agent-0.1.0/scripts/dogfood_agent_transcript.py +1042 -0
  19. kestrel_agent-0.1.0/src/kestrel/__init__.py +4 -0
  20. kestrel_agent-0.1.0/src/kestrel/__main__.py +6 -0
  21. kestrel_agent-0.1.0/src/kestrel/agent_protocol.py +1544 -0
  22. kestrel_agent-0.1.0/src/kestrel/apply/__init__.py +2 -0
  23. kestrel_agent-0.1.0/src/kestrel/apply/chrome.py +351 -0
  24. kestrel_agent-0.1.0/src/kestrel/apply/claude.py +129 -0
  25. kestrel_agent-0.1.0/src/kestrel/apply/dashboard.py +226 -0
  26. kestrel_agent-0.1.0/src/kestrel/apply/droid.py +253 -0
  27. kestrel_agent-0.1.0/src/kestrel/apply/engines.py +218 -0
  28. kestrel_agent-0.1.0/src/kestrel/apply/eventlog.py +113 -0
  29. kestrel_agent-0.1.0/src/kestrel/apply/launcher.py +1511 -0
  30. kestrel_agent-0.1.0/src/kestrel/apply/planning.py +330 -0
  31. kestrel_agent-0.1.0/src/kestrel/apply/prompt.py +706 -0
  32. kestrel_agent-0.1.0/src/kestrel/cli.py +1302 -0
  33. kestrel_agent-0.1.0/src/kestrel/config/employers.yaml +128 -0
  34. kestrel_agent-0.1.0/src/kestrel/config/searches.example.yaml +123 -0
  35. kestrel_agent-0.1.0/src/kestrel/config/sites.yaml +181 -0
  36. kestrel_agent-0.1.0/src/kestrel/config.py +568 -0
  37. kestrel_agent-0.1.0/src/kestrel/database.py +1561 -0
  38. kestrel_agent-0.1.0/src/kestrel/discovery/__init__.py +1 -0
  39. kestrel_agent-0.1.0/src/kestrel/discovery/composio.py +606 -0
  40. kestrel_agent-0.1.0/src/kestrel/discovery/filters.py +64 -0
  41. kestrel_agent-0.1.0/src/kestrel/discovery/jobspy.py +533 -0
  42. kestrel_agent-0.1.0/src/kestrel/discovery/salary.py +180 -0
  43. kestrel_agent-0.1.0/src/kestrel/discovery/smartextract.py +1102 -0
  44. kestrel_agent-0.1.0/src/kestrel/discovery/workday.py +564 -0
  45. kestrel_agent-0.1.0/src/kestrel/engine_auth.py +300 -0
  46. kestrel_agent-0.1.0/src/kestrel/enrichment/__init__.py +1 -0
  47. kestrel_agent-0.1.0/src/kestrel/enrichment/detail.py +983 -0
  48. kestrel_agent-0.1.0/src/kestrel/enrichment/remote.py +40 -0
  49. kestrel_agent-0.1.0/src/kestrel/enrichment/seniority.py +68 -0
  50. kestrel_agent-0.1.0/src/kestrel/llm.py +727 -0
  51. kestrel_agent-0.1.0/src/kestrel/onboarding.py +2406 -0
  52. kestrel_agent-0.1.0/src/kestrel/pipeline.py +707 -0
  53. kestrel_agent-0.1.0/src/kestrel/portal/__init__.py +10 -0
  54. kestrel_agent-0.1.0/src/kestrel/portal/app.py +1863 -0
  55. kestrel_agent-0.1.0/src/kestrel/portal/assistant.py +188 -0
  56. kestrel_agent-0.1.0/src/kestrel/portal/auth.py +138 -0
  57. kestrel_agent-0.1.0/src/kestrel/portal/automation.py +552 -0
  58. kestrel_agent-0.1.0/src/kestrel/portal/queries.py +322 -0
  59. kestrel_agent-0.1.0/src/kestrel/portal/runner.py +618 -0
  60. kestrel_agent-0.1.0/src/kestrel/portal/settings.py +274 -0
  61. kestrel_agent-0.1.0/src/kestrel/portal/static/ext-sse.js +385 -0
  62. kestrel_agent-0.1.0/src/kestrel/portal/static/htmx.min.js +1 -0
  63. kestrel_agent-0.1.0/src/kestrel/portal/static/kestrel-dark.png +0 -0
  64. kestrel_agent-0.1.0/src/kestrel/portal/static/kestrel-mark.png +0 -0
  65. kestrel_agent-0.1.0/src/kestrel/portal/static/kestrel-mono.png +0 -0
  66. kestrel_agent-0.1.0/src/kestrel/portal/static/kestrel-wordmark.png +0 -0
  67. kestrel_agent-0.1.0/src/kestrel/portal/static/portal.css +1178 -0
  68. kestrel_agent-0.1.0/src/kestrel/portal/system_check.py +300 -0
  69. kestrel_agent-0.1.0/src/kestrel/portal/templates/automation.html +15 -0
  70. kestrel_agent-0.1.0/src/kestrel/portal/templates/base.html +39 -0
  71. kestrel_agent-0.1.0/src/kestrel/portal/templates/dashboard.html +88 -0
  72. kestrel_agent-0.1.0/src/kestrel/portal/templates/engine.html +13 -0
  73. kestrel_agent-0.1.0/src/kestrel/portal/templates/jobs.html +86 -0
  74. kestrel_agent-0.1.0/src/kestrel/portal/templates/login.html +26 -0
  75. kestrel_agent-0.1.0/src/kestrel/portal/templates/onboarding.html +11 -0
  76. kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/assistant_panel.html +16 -0
  77. kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/automation_cards.html +98 -0
  78. kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/board_view_params.html +15 -0
  79. kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/engine_gates.html +76 -0
  80. kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/events.html +9 -0
  81. kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/fit_assessment.html +27 -0
  82. kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/job_card.html +95 -0
  83. kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/job_detail.html +111 -0
  84. kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/job_missing.html +3 -0
  85. kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/jobs_board.html +60 -0
  86. kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/jobs_progress.html +5 -0
  87. kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/onboarding_chat.html +397 -0
  88. kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/onboarding_surface.html +120 -0
  89. kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/runs_table.html +31 -0
  90. kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/system_checks.html +18 -0
  91. kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/workers.html +22 -0
  92. kestrel_agent-0.1.0/src/kestrel/portal/templates/preview.html +36 -0
  93. kestrel_agent-0.1.0/src/kestrel/portal/templates/run_log.html +24 -0
  94. kestrel_agent-0.1.0/src/kestrel/portal/templates/runs.html +21 -0
  95. kestrel_agent-0.1.0/src/kestrel/portal/templates/settings.html +88 -0
  96. kestrel_agent-0.1.0/src/kestrel/portal/templates/system_check.html +22 -0
  97. kestrel_agent-0.1.0/src/kestrel/portal/templates/versions.html +53 -0
  98. kestrel_agent-0.1.0/src/kestrel/scoring/__init__.py +2 -0
  99. kestrel_agent-0.1.0/src/kestrel/scoring/cover_letter.py +359 -0
  100. kestrel_agent-0.1.0/src/kestrel/scoring/docs.py +60 -0
  101. kestrel_agent-0.1.0/src/kestrel/scoring/pdf.py +619 -0
  102. kestrel_agent-0.1.0/src/kestrel/scoring/scorer.py +419 -0
  103. kestrel_agent-0.1.0/src/kestrel/scoring/tailor.py +683 -0
  104. kestrel_agent-0.1.0/src/kestrel/scoring/validator.py +475 -0
  105. kestrel_agent-0.1.0/src/kestrel/security.py +44 -0
  106. kestrel_agent-0.1.0/src/kestrel/view.py +413 -0
  107. kestrel_agent-0.1.0/src/kestrel/wizard/__init__.py +1 -0
  108. kestrel_agent-0.1.0/src/kestrel/wizard/init.py +529 -0
  109. kestrel_agent-0.1.0/tests/__init__.py +0 -0
  110. kestrel_agent-0.1.0/tests/conftest.py +216 -0
  111. kestrel_agent-0.1.0/tests/e2e/__init__.py +0 -0
  112. kestrel_agent-0.1.0/tests/e2e/conftest.py +196 -0
  113. kestrel_agent-0.1.0/tests/e2e/test_automation.py +226 -0
  114. kestrel_agent-0.1.0/tests/e2e/test_full_journey.py +385 -0
  115. kestrel_agent-0.1.0/tests/e2e/test_jobs_board.py +235 -0
  116. kestrel_agent-0.1.0/tests/e2e/test_onboarding_wizard.py +404 -0
  117. kestrel_agent-0.1.0/tests/e2e/test_smoke.py +36 -0
  118. kestrel_agent-0.1.0/tests/e2e/test_system_check.py +44 -0
  119. kestrel_agent-0.1.0/tests/test_agent_apply_verbs.py +412 -0
  120. kestrel_agent-0.1.0/tests/test_agent_coexistence.py +206 -0
  121. kestrel_agent-0.1.0/tests/test_agent_journey.py +278 -0
  122. kestrel_agent-0.1.0/tests/test_agent_materials.py +509 -0
  123. kestrel_agent-0.1.0/tests/test_agent_protocol.py +549 -0
  124. kestrel_agent-0.1.0/tests/test_agent_scoring.py +428 -0
  125. kestrel_agent-0.1.0/tests/test_apply_guardrails.py +414 -0
  126. kestrel_agent-0.1.0/tests/test_apply_loop_bugs.py +427 -0
  127. kestrel_agent-0.1.0/tests/test_apply_prompt_truthfulness.py +231 -0
  128. kestrel_agent-0.1.0/tests/test_apply_status_writers.py +498 -0
  129. kestrel_agent-0.1.0/tests/test_audit_r3_deferred_data.py +415 -0
  130. kestrel_agent-0.1.0/tests/test_audit_r3_deferred_protocol.py +510 -0
  131. kestrel_agent-0.1.0/tests/test_audit_r3_protocol_remediation.py +616 -0
  132. kestrel_agent-0.1.0/tests/test_audit_r3_remediation.py +766 -0
  133. kestrel_agent-0.1.0/tests/test_audit_wave2_f3_f4.py +155 -0
  134. kestrel_agent-0.1.0/tests/test_chrome_clone.py +109 -0
  135. kestrel_agent-0.1.0/tests/test_cli_entry_point.py +47 -0
  136. kestrel_agent-0.1.0/tests/test_cli_json_output.py +222 -0
  137. kestrel_agent-0.1.0/tests/test_composio_discovery.py +697 -0
  138. kestrel_agent-0.1.0/tests/test_deep_filter_layer1.py +483 -0
  139. kestrel_agent-0.1.0/tests/test_document_history.py +437 -0
  140. kestrel_agent-0.1.0/tests/test_engine_auth.py +470 -0
  141. kestrel_agent-0.1.0/tests/test_engine_selection.py +788 -0
  142. kestrel_agent-0.1.0/tests/test_file_permissions.py +121 -0
  143. kestrel_agent-0.1.0/tests/test_infra_attempt_budget.py +159 -0
  144. kestrel_agent-0.1.0/tests/test_jobs_board_filters.py +387 -0
  145. kestrel_agent-0.1.0/tests/test_jobs_board_nav.py +282 -0
  146. kestrel_agent-0.1.0/tests/test_jobs_cards.py +139 -0
  147. kestrel_agent-0.1.0/tests/test_jobs_filter_cli.py +451 -0
  148. kestrel_agent-0.1.0/tests/test_jobs_rerank.py +485 -0
  149. kestrel_agent-0.1.0/tests/test_jobs_verbs.py +278 -0
  150. kestrel_agent-0.1.0/tests/test_launcher_url_escape.py +111 -0
  151. kestrel_agent-0.1.0/tests/test_llm_gemini_header.py +69 -0
  152. kestrel_agent-0.1.0/tests/test_llm_probe.py +222 -0
  153. kestrel_agent-0.1.0/tests/test_llm_retry_cap.py +112 -0
  154. kestrel_agent-0.1.0/tests/test_model_dropdown.py +415 -0
  155. kestrel_agent-0.1.0/tests/test_onboarding_agent.py +766 -0
  156. kestrel_agent-0.1.0/tests/test_onboarding_choices.py +1025 -0
  157. kestrel_agent-0.1.0/tests/test_onboarding_prefill.py +639 -0
  158. kestrel_agent-0.1.0/tests/test_pdf_busy_loop.py +398 -0
  159. kestrel_agent-0.1.0/tests/test_pipeline_bugs.py +898 -0
  160. kestrel_agent-0.1.0/tests/test_portal_auth.py +192 -0
  161. kestrel_agent-0.1.0/tests/test_portal_automation.py +634 -0
  162. kestrel_agent-0.1.0/tests/test_portal_automation_ui.py +626 -0
  163. kestrel_agent-0.1.0/tests/test_portal_engine_gate.py +368 -0
  164. kestrel_agent-0.1.0/tests/test_portal_onboarding.py +331 -0
  165. kestrel_agent-0.1.0/tests/test_portal_pages.py +355 -0
  166. kestrel_agent-0.1.0/tests/test_portal_revamp.py +279 -0
  167. kestrel_agent-0.1.0/tests/test_portal_runner.py +480 -0
  168. kestrel_agent-0.1.0/tests/test_portal_settings.py +285 -0
  169. kestrel_agent-0.1.0/tests/test_portal_sse.py +249 -0
  170. kestrel_agent-0.1.0/tests/test_portal_system_check.py +320 -0
  171. kestrel_agent-0.1.0/tests/test_prompt_security.py +217 -0
  172. kestrel_agent-0.1.0/tests/test_provider_selection.py +428 -0
  173. kestrel_agent-0.1.0/tests/test_remote_flag.py +115 -0
  174. kestrel_agent-0.1.0/tests/test_rename_migration.py +204 -0
  175. kestrel_agent-0.1.0/tests/test_resume_upload_paths.py +159 -0
  176. kestrel_agent-0.1.0/tests/test_salary_bands.py +250 -0
  177. kestrel_agent-0.1.0/tests/test_scoring_rescore.py +406 -0
  178. kestrel_agent-0.1.0/tests/test_scoring_validator.py +130 -0
  179. kestrel_agent-0.1.0/tests/test_security_redaction.py +67 -0
  180. kestrel_agent-0.1.0/tests/test_smoke.py +51 -0
  181. kestrel_agent-0.1.0/tests/test_zero_terminal_copy.py +171 -0
@@ -0,0 +1,18 @@
1
+ # Kestrel Environment Configuration
2
+ # Copy to ~/.kestrel/.env and fill in your values.
3
+
4
+ # LLM Provider (pick one)
5
+ GEMINI_API_KEY= # Gemini 2.0 Flash (recommended, cheapest)
6
+ # OPENAI_API_KEY= # OpenAI (GPT-4o-mini)
7
+ # LLM_URL=http://127.0.0.1:8080/v1 # Local LLM (llama.cpp, Ollama)
8
+ # LLM_MODEL= # Override model name
9
+
10
+ # Auto-Apply (optional)
11
+ CAPSOLVER_API_KEY= # For CAPTCHA solving during auto-apply
12
+
13
+ # Auto-Apply engine (optional; default: claude)
14
+ # AUTOAPPLY_ENGINE=droid # claude | droid
15
+ # FACTORY_API_KEY= # Required when the engine is droid (child env only)
16
+
17
+ # Proxy (optional, for scraping)
18
+ # PROXY=host:port:user:pass
@@ -0,0 +1,41 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_dispatch:
8
+
9
+ concurrency:
10
+ group: ci-${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ test:
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ python-version: ["3.11", "3.12", "3.13"]
20
+
21
+ steps:
22
+ - name: Checkout
23
+ uses: actions/checkout@v4
24
+
25
+ - name: Set up Python ${{ matrix.python-version }}
26
+ uses: actions/setup-python@v5
27
+ with:
28
+ python-version: ${{ matrix.python-version }}
29
+ cache: pip
30
+
31
+ - name: Install dependencies
32
+ run: pip install -e ".[dev]"
33
+
34
+ - name: Install Playwright Chromium
35
+ run: playwright install --with-deps chromium
36
+
37
+ - name: Lint
38
+ run: ruff check .
39
+
40
+ - name: Test
41
+ run: pytest -v
@@ -0,0 +1,56 @@
1
+ # Publish kestrel-agent to PyPI on version tags (v*), via OIDC trusted publishing.
2
+ #
3
+ # MANUAL SETUP REQUIRED BEFORE THE FIRST TAG (release runbook):
4
+ #
5
+ # 1. The PyPI project `kestrel-agent` must be registered before the first
6
+ # publication. Registration happens on first upload — but with trusted
7
+ # publishing, the project must instead be pre-created on PyPI with the
8
+ # pending publisher configured (PyPI -> Publishing -> add a pending
9
+ # trusted publisher), because a tag-triggered workflow cannot claim an
10
+ # unregistered project name without a human in the loop.
11
+ # 2. Configure the trusted-publisher entry on PyPI for
12
+ # `Vontarius-Ventures/kestrel`:
13
+ # - owner: Vontarius-Ventures
14
+ # - repository: kestrel
15
+ # - workflow name: publish.yml
16
+ # - environment: pypi
17
+ # (Note the repository name is `kestrel`, while this file lives in the
18
+ # private repo `VontariusF/ApplyPilot` until the public cut; the entry
19
+ # must point at the public repo.)
20
+ # 3. The `pypi` GitHub environment must exist on the target repo with the
21
+ # OIDC id-token permission (granted here via `permissions.id-token`).
22
+ #
23
+ # Kestrel is an AGPL-3.0 fork of Pickle-Pixel/ApplyPilot; see NOTICE and
24
+ # README for upstream attribution.
25
+
26
+ name: Publish kestrel-agent to PyPI
27
+
28
+ on:
29
+ push:
30
+ tags:
31
+ - "v*"
32
+
33
+ jobs:
34
+ publish:
35
+ runs-on: ubuntu-latest
36
+ environment: pypi
37
+ permissions:
38
+ id-token: write # required for OIDC trusted publishing
39
+
40
+ steps:
41
+ - name: Checkout
42
+ uses: actions/checkout@v4
43
+
44
+ - name: Set up Python
45
+ uses: actions/setup-python@v5
46
+ with:
47
+ python-version: "3.12"
48
+
49
+ - name: Install build tools
50
+ run: pip install build
51
+
52
+ - name: Build kestrel-agent distribution
53
+ run: python -m build
54
+
55
+ - name: Publish kestrel-agent to PyPI
56
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,49 @@
1
+ # User data (NEVER commit)
2
+ profile.json
3
+ resume.txt
4
+ resume.pdf
5
+ *.env
6
+ .env.*
7
+ !.env.example
8
+
9
+ # Runtime artifacts
10
+ *.db
11
+ tailored_resumes/
12
+ cover_letters/
13
+ chrome-workers/
14
+ apply-workers/
15
+ apply_logs/
16
+ logs/
17
+
18
+ # MCP configs (per-machine)
19
+ .mcp*.json
20
+
21
+ # Python
22
+ __pycache__/
23
+ *.py[cod]
24
+ *$py.class
25
+ *.egg-info/
26
+ dist/
27
+ build/
28
+ *.egg
29
+
30
+ # IDE
31
+ .vscode/
32
+ .idea/
33
+ *.swp
34
+ *.swo
35
+
36
+ # OS
37
+ .DS_Store
38
+ Thumbs.db
39
+
40
+ # Owner secrets (never ship or commit)
41
+ *.local
42
+ .env*.local
43
+
44
+ # Local SQLite databases (never commit)
45
+ *.sqlite3
46
+ *.sqlite3-journal
47
+
48
+ # Claude Code
49
+ .claude/
@@ -0,0 +1,58 @@
1
+ # Changelog
2
+
3
+ All notable changes to Kestrel will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2026-11-09
9
+
10
+ First public release of Kestrel, the open-source job-search and application
11
+ assistant.
12
+
13
+ ### About
14
+
15
+ Kestrel helps candidates discover and evaluate jobs, prepare tailored
16
+ application materials, and manage applications through a human-supervised,
17
+ localhost-first workflow. This release is cut from a fresh versioning start:
18
+ `0.1.0` restarts the version lineage and this changelog begins anew.
19
+
20
+ ### Lineage
21
+
22
+ Kestrel is a fork of [ApplyPilot](https://github.com/Pickle-Pixel/ApplyPilot)
23
+ by Pickle-Pixel, released under the GNU Affero General Public License
24
+ v3.0. Upstream copyright is retained; Kestrel's changes continue to be
25
+ distributed under AGPL-3.0. See `LICENSE` and `NOTICE` for attribution
26
+ details.
27
+
28
+ ### Added (carried from the fork)
29
+
30
+ - 6-stage pipeline: discover, enrich, score, tailor, cover letter, apply
31
+ - Multi-source job discovery: Indeed, LinkedIn, Glassdoor, ZipRecruiter, Google Jobs
32
+ - Workday employer portal support with a preconfigured employer registry
33
+ - Direct career site scraping with a 3-tier extraction cascade
34
+ (JSON-LD, CSS selectors, AI fallback)
35
+ - AI-powered job scoring (1-10 fit scale with rationale) and composable
36
+ filters with reranking and score history
37
+ - Resume tailoring with factual preservation (no fabrication) and
38
+ per-job cover letter generation
39
+ - Autonomous browser-based application submission via Playwright, with
40
+ plan-then-confirm controls, attempt limits, and human-gated submissions
41
+ - Typer-based CLI (`kestrel`), machine-readable `status --json` and
42
+ `doctor --json` output, and an agent-driven onboarding flow
43
+ - Optional single-user FastAPI portal (localhost, auth by default)
44
+ - Multi-provider LLM support (Gemini, OpenAI, local models via
45
+ OpenAI-compatible endpoints)
46
+ - Local SQLite storage under `~/.kestrel`
47
+
48
+ ### Changed from upstream
49
+
50
+ - Package distribution and PyPI name: `kestrel-agent` (CLI: `kestrel`)
51
+ - Default data directory: `~/.kestrel` (migrates from `~/.applypilot`
52
+ on first run; `KESTREL_DIR` replaces `APPLYPILOT_DIR` with the legacy
53
+ variable still honored as a fallback)
54
+ - Environment namespace: `KESTREL_*` replaces `APPLYPILOT_*`, with legacy
55
+ fallbacks for compatibility
56
+ - Privacy: removed personal fixtures, machine-specific paths, and
57
+ internal transcripts; rebalanced the example employer registry toward a
58
+ geographically neutral sample
@@ -0,0 +1,118 @@
1
+ # Contributing to Kestrel
2
+
3
+ Thank you for your interest in contributing to Kestrel — an AGPL-3.0 fork of
4
+ [Pickle-Pixel/ApplyPilot](https://github.com/Pickle-Pixel/ApplyPilot). This
5
+ guide covers development setup, the gates every change must pass, and the
6
+ ground rules for what never enters the repository.
7
+
8
+ ## Development Setup
9
+
10
+ ### Prerequisites
11
+
12
+ - Python 3.11 or higher
13
+ - Git
14
+
15
+ ### Clone and Install
16
+
17
+ ```bash
18
+ git clone https://github.com/Vontarius-Ventures/kestrel.git
19
+ cd kestrel
20
+ pip install -e ".[dev]"
21
+ playwright install chromium
22
+ ```
23
+
24
+ This installs Kestrel in editable mode with the development dependencies
25
+ (pytest, ruff, and the portal stack) and downloads the Chromium browser
26
+ binary for Playwright.
27
+
28
+ ### Verify the installation
29
+
30
+ ```bash
31
+ kestrel --version
32
+ kestrel doctor --json
33
+ ```
34
+
35
+ ## Must-pass gates
36
+
37
+ These must pass before you open a PR — CI runs them, and a red gate blocks
38
+ the merge:
39
+
40
+ ```bash
41
+ ruff check . # lint (src + tests)
42
+ pytest tests -m "not e2e" # unit suite (non-e2e)
43
+ ```
44
+
45
+ For portal or onboarding changes, also run the browser e2e suite
46
+ (`pytest tests/e2e`); Chromium must be installed once per machine
47
+ (`playwright install chromium`) — without it the e2e tests silently SKIP,
48
+ and a skipped gate is no gate.
49
+
50
+ ## How to contribute
51
+
52
+ 1. Check existing [issues](https://github.com/Vontarius-Ventures/kestrel/issues)
53
+ to avoid duplicating work; for new features, open an issue first to
54
+ discuss the approach.
55
+ 2. Fork the repo and create a feature branch from `main`.
56
+ 3. Write code with type hints and docstrings, and add tests for new
57
+ functionality — bug fixes need a regression test.
58
+ 4. Run the must-pass gates above.
59
+ 5. Submit a PR with a clear description of what changed and why.
60
+
61
+ ### Adding Workday employers and career sites
62
+
63
+ Workday employer portals live in `src/kestrel/config/employers.yaml`; direct
64
+ career sites in `src/kestrel/config/sites.yaml`. Find the portal URL and
65
+ Workday instance/tenant (or the site's CSS selectors for job listings), add
66
+ an entry following the existing format, and verify with
67
+ `kestrel run --stage discover` against that employer or site before
68
+ submitting.
69
+
70
+ ## Code style
71
+
72
+ - **Type hints** on all function signatures.
73
+ - **Docstrings** (Google style) on all public functions and classes.
74
+ - **snake_case** for functions and variables, **PascalCase** for classes.
75
+ - **Imports** sorted by Ruff (isort-compatible); **line length** 120
76
+ characters.
77
+ - Auto-fix what Ruff can fix: `ruff check src/ --fix`.
78
+
79
+ ## Ground rules — never commit
80
+
81
+ These are hard rules, enforced by review; violations are removed on sight:
82
+
83
+ - **Keys, tokens, or credentials of any kind** — API keys, OAuth tokens,
84
+ session cookies, password files.
85
+ - **`.env*.local` and `*.local` files** — local-only configuration and
86
+ secrets stay on your machine. `.env.example` (placeholders only) is the
87
+ template that ships.
88
+ - **Personal machine details** — home-directory paths, hostnames, IPs,
89
+ usernames, deployed-service configs (e.g., launchd plists).
90
+ - **Local databases** — SQLite files and their journals.
91
+ - **Live resume/profile data** — `profile.json` and `resume.txt` are
92
+ git-ignored; commit only the `profile.example.json` / example fixtures.
93
+
94
+ ## Project structure
95
+
96
+ ```
97
+ kestrel/
98
+ ├── src/kestrel/ # Main package
99
+ │ ├── cli.py # CLI entry points
100
+ │ ├── pipeline.py # Stage orchestration (tailor, cover letters, PDF)
101
+ │ ├── discovery/ # Stage 1: job discovery scrapers
102
+ │ ├── enrichment/ # Stage 2: description extraction
103
+ │ ├── scoring/ # Stage 3: AI scoring
104
+ │ ├── apply/ # Stage 6: browser automation (Claude/Droid engines)
105
+ │ ├── portal/ # Localhost web portal
106
+ │ ├── wizard/ # Onboarding wizard
107
+ │ ├── agent_protocol.py # Host-driven agent protocol (JSON verbs)
108
+ │ ├── database.py # SQLite store
109
+ │ └── config/ # Bundled YAML configs (employers, sites, searches)
110
+ ├── tests/ # Test suite (unit + e2e)
111
+ └── pyproject.toml # Package configuration
112
+ ```
113
+
114
+ ## License
115
+
116
+ By contributing to Kestrel, you agree that your contributions will be
117
+ licensed under the [GNU Affero General Public License v3.0](LICENSE).
118
+ Kestrel retains upstream ApplyPilot attribution per [NOTICE](NOTICE).