divapply 0.4.2__tar.gz → 0.4.4__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.
- divapply-0.4.4/.dockerignore +34 -0
- divapply-0.4.4/.github/workflows/ci.yml +92 -0
- divapply-0.4.4/.github/workflows/publish.yml +79 -0
- {divapply-0.4.2 → divapply-0.4.4}/.gitignore +19 -0
- divapply-0.4.4/CHANGELOG.md +45 -0
- divapply-0.4.4/Dockerfile +23 -0
- divapply-0.4.4/PKG-INFO +321 -0
- divapply-0.4.4/PUBLISHING.md +77 -0
- divapply-0.4.4/README.md +281 -0
- divapply-0.4.2/MIGRATION_CHECKLIST.md → divapply-0.4.4/docs/MIGRATION.md +1 -1
- divapply-0.4.4/docs/OPERATIONS.md +92 -0
- divapply-0.4.4/docs/PRIVACY.md +36 -0
- {divapply-0.4.2 → divapply-0.4.4}/install.ps1 +4 -0
- {divapply-0.4.2 → divapply-0.4.4}/install.sh +6 -1
- divapply-0.4.4/profile.example.json +120 -0
- {divapply-0.4.2 → divapply-0.4.4}/pyproject.toml +5 -13
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/__init__.py +1 -1
- divapply-0.4.4/src/divapply/apply/answers.py +115 -0
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/apply/dashboard.py +1 -1
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/apply/launcher.py +306 -673
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/apply/prompt.py +183 -114
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/cli.py +667 -26
- divapply-0.4.4/src/divapply/config/employers.yaml +32 -0
- divapply-0.4.4/src/divapply/config/searches.example.yaml +87 -0
- divapply-0.4.4/src/divapply/config/sites.yaml +78 -0
- divapply-0.4.4/src/divapply/config.py +513 -0
- divapply-0.4.4/src/divapply/database.py +1074 -0
- divapply-0.4.4/src/divapply/discovery/filters.py +73 -0
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/discovery/jobspy.py +247 -37
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/discovery/smartextract.py +117 -46
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/discovery/workday.py +56 -41
- divapply-0.4.4/src/divapply/editor.py +988 -0
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/enrichment/detail.py +30 -16
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/llm.py +55 -7
- divapply-0.4.4/src/divapply/migrations/__init__.py +74 -0
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/pipeline.py +143 -95
- divapply-0.4.4/src/divapply/privacy.py +21 -0
- divapply-0.4.4/src/divapply/runtime.py +196 -0
- divapply-0.4.4/src/divapply/scoring/composite.py +165 -0
- divapply-0.4.4/src/divapply/scoring/context.py +16 -0
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/scoring/cover_letter.py +8 -14
- divapply-0.4.4/src/divapply/scoring/embedding.py +49 -0
- divapply-0.4.4/src/divapply/scoring/keywords.py +209 -0
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/scoring/pdf.py +42 -22
- divapply-0.4.4/src/divapply/scoring/scorer.py +440 -0
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/scoring/tailor.py +74 -53
- divapply-0.4.4/src/divapply/scoring/ultimate.py +154 -0
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/scoring/validator.py +37 -15
- divapply-0.4.4/src/divapply/security.py +155 -0
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/social.py +25 -7
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/view.py +171 -96
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/wizard/init.py +9 -2
- divapply-0.4.4/tests/conftest.py +12 -0
- divapply-0.4.4/tests/test_answer_bank.py +24 -0
- divapply-0.4.4/tests/test_apply_launcher.py +564 -0
- divapply-0.4.4/tests/test_apply_prompt.py +175 -0
- divapply-0.4.4/tests/test_backup.py +108 -0
- divapply-0.4.4/tests/test_cli_help.py +64 -0
- divapply-0.4.4/tests/test_config_loading.py +60 -0
- divapply-0.4.4/tests/test_coursework_summary.py +105 -0
- divapply-0.4.4/tests/test_credentials_config.py +30 -0
- divapply-0.4.4/tests/test_dashboard_view.py +81 -0
- divapply-0.4.4/tests/test_discovery_filters.py +170 -0
- divapply-0.4.4/tests/test_editor.py +345 -0
- divapply-0.4.4/tests/test_enrichment_detail_edges.py +132 -0
- divapply-0.4.4/tests/test_export_redaction.py +92 -0
- divapply-0.4.4/tests/test_hybrid_scoring.py +245 -0
- divapply-0.4.4/tests/test_lifecycle_and_dedup.py +324 -0
- divapply-0.4.4/tests/test_llm_aliases.py +17 -0
- divapply-0.4.4/tests/test_migrations.py +17 -0
- divapply-0.4.4/tests/test_pdf_template.py +79 -0
- divapply-0.4.4/tests/test_pipeline_stage_dispatch.py +50 -0
- divapply-0.4.4/tests/test_runtime_edges.py +24 -0
- divapply-0.4.4/tests/test_scoring_parser.py +38 -0
- divapply-0.4.4/tests/test_security.py +83 -0
- divapply-0.4.4/tests/test_smartextract_config.py +44 -0
- divapply-0.4.4/tests/test_smartextract_edges.py +103 -0
- divapply-0.4.4/tests/test_social_credentials.py +46 -0
- divapply-0.4.4/tests/test_tailor_trace.py +19 -0
- {divapply-0.4.2 → divapply-0.4.4}/tests/test_tier.py +11 -11
- divapply-0.4.4/tests/test_ultimate_resume.py +102 -0
- divapply-0.4.4/tests/test_validator_modes.py +94 -0
- divapply-0.4.4/tests/test_workday_config.py +58 -0
- divapply-0.4.4/tests/test_workday_edges.py +156 -0
- {divapply-0.4.2 → divapply-0.4.4}/tools/bootstrap.ps1 +6 -1
- divapply-0.4.2/.github/workflows/ci.yml +0 -29
- divapply-0.4.2/.github/workflows/publish.yml +0 -38
- divapply-0.4.2/CHANGELOG.md +0 -28
- divapply-0.4.2/PKG-INFO +0 -278
- divapply-0.4.2/PUBLISHING.md +0 -54
- divapply-0.4.2/README.md +0 -231
- divapply-0.4.2/profile.example.json +0 -61
- divapply-0.4.2/src/divapply/config/employers.yaml +0 -31
- divapply-0.4.2/src/divapply/config/searches.example.yaml +0 -113
- divapply-0.4.2/src/divapply/config/sites.yaml +0 -107
- divapply-0.4.2/src/divapply/config.py +0 -445
- divapply-0.4.2/src/divapply/database.py +0 -635
- divapply-0.4.2/src/divapply/scoring/scorer.py +0 -230
- divapply-0.4.2/src/divapply/scoring/ultimate.py +0 -214
- {divapply-0.4.2 → divapply-0.4.4}/.env.example +0 -0
- {divapply-0.4.2 → divapply-0.4.4}/CONTRIBUTING.md +0 -0
- {divapply-0.4.2 → divapply-0.4.4}/LICENSE +0 -0
- {divapply-0.4.2 → divapply-0.4.4/docs}/AI_ASSISTANCE.md +0 -0
- {divapply-0.4.2 → divapply-0.4.4}/install.cmd +0 -0
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/__main__.py +0 -0
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/apply/__init__.py +0 -0
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/apply/chrome.py +0 -0
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/config/coursework.seed.json +0 -0
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/discovery/__init__.py +0 -0
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/enrichment/__init__.py +0 -0
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/scoring/__init__.py +0 -0
- {divapply-0.4.2 → divapply-0.4.4}/src/divapply/wizard/__init__.py +0 -0
- {divapply-0.4.2 → divapply-0.4.4}/tests/test_migration.py +0 -0
- {divapply-0.4.2 → divapply-0.4.4}/tools/extract_transcript.ps1 +0 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
.git
|
|
2
|
+
.github
|
|
3
|
+
.pytest_cache
|
|
4
|
+
.ruff_cache
|
|
5
|
+
__pycache__
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*.egg-info
|
|
8
|
+
build
|
|
9
|
+
dist
|
|
10
|
+
.venv
|
|
11
|
+
.vendor
|
|
12
|
+
|
|
13
|
+
# User/runtime data must be mounted at runtime, not baked into images.
|
|
14
|
+
.divapply
|
|
15
|
+
.applypilot
|
|
16
|
+
profile.json
|
|
17
|
+
resume.txt
|
|
18
|
+
resume.pdf
|
|
19
|
+
answers.yaml
|
|
20
|
+
credentials.yaml
|
|
21
|
+
*.env
|
|
22
|
+
.env.*
|
|
23
|
+
*.db
|
|
24
|
+
*.sqlite
|
|
25
|
+
*.sqlite3
|
|
26
|
+
tailored_resumes
|
|
27
|
+
cover_letters
|
|
28
|
+
chrome-workers
|
|
29
|
+
apply-workers
|
|
30
|
+
logs
|
|
31
|
+
apply_logs
|
|
32
|
+
screenshots
|
|
33
|
+
social_screenshots
|
|
34
|
+
.mcp*.json
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: ["main"]
|
|
7
|
+
tags-ignore: ["v*"]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ci-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
test:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
strategy:
|
|
18
|
+
fail-fast: false
|
|
19
|
+
matrix:
|
|
20
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout
|
|
24
|
+
uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
27
|
+
uses: actions/setup-python@v5
|
|
28
|
+
with:
|
|
29
|
+
python-version: ${{ matrix.python-version }}
|
|
30
|
+
cache: pip
|
|
31
|
+
|
|
32
|
+
- name: Install dependencies
|
|
33
|
+
run: python -m pip install --upgrade pip && python -m pip install -e ".[dev]"
|
|
34
|
+
|
|
35
|
+
- name: Lint
|
|
36
|
+
run: ruff check .
|
|
37
|
+
|
|
38
|
+
- name: Test
|
|
39
|
+
run: pytest -q
|
|
40
|
+
|
|
41
|
+
package:
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
needs: test
|
|
44
|
+
|
|
45
|
+
steps:
|
|
46
|
+
- name: Checkout
|
|
47
|
+
uses: actions/checkout@v4
|
|
48
|
+
|
|
49
|
+
- name: Set up Python
|
|
50
|
+
uses: actions/setup-python@v5
|
|
51
|
+
with:
|
|
52
|
+
python-version: "3.12"
|
|
53
|
+
cache: pip
|
|
54
|
+
|
|
55
|
+
- name: Build package
|
|
56
|
+
run: |
|
|
57
|
+
python -m pip install --upgrade pip build twine
|
|
58
|
+
python -m build
|
|
59
|
+
python -m twine check dist/*
|
|
60
|
+
|
|
61
|
+
- name: Smoke test wheel install
|
|
62
|
+
run: |
|
|
63
|
+
python -m venv .venv-smoke
|
|
64
|
+
. .venv-smoke/bin/activate
|
|
65
|
+
python -m pip install --upgrade pip
|
|
66
|
+
WHEEL="$(ls dist/*.whl)"
|
|
67
|
+
python -m pip install "$WHEEL[full]"
|
|
68
|
+
divapply --version
|
|
69
|
+
divapply selfcheck
|
|
70
|
+
|
|
71
|
+
- name: Upload distribution artifacts
|
|
72
|
+
uses: actions/upload-artifact@v4
|
|
73
|
+
with:
|
|
74
|
+
name: python-dist
|
|
75
|
+
path: dist/*
|
|
76
|
+
if-no-files-found: error
|
|
77
|
+
|
|
78
|
+
container:
|
|
79
|
+
runs-on: ubuntu-latest
|
|
80
|
+
needs: test
|
|
81
|
+
|
|
82
|
+
steps:
|
|
83
|
+
- name: Checkout
|
|
84
|
+
uses: actions/checkout@v4
|
|
85
|
+
|
|
86
|
+
- name: Build image
|
|
87
|
+
run: docker build -t divapply:ci .
|
|
88
|
+
|
|
89
|
+
- name: Smoke test image
|
|
90
|
+
run: |
|
|
91
|
+
docker run --rm divapply:ci --version
|
|
92
|
+
docker run --rm divapply:ci selfcheck
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: release-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: false
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
release:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
environment:
|
|
16
|
+
name: pypi
|
|
17
|
+
url: https://pypi.org/p/divapply
|
|
18
|
+
permissions:
|
|
19
|
+
contents: write
|
|
20
|
+
id-token: write
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout
|
|
24
|
+
uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- name: Set up Python
|
|
27
|
+
uses: actions/setup-python@v5
|
|
28
|
+
with:
|
|
29
|
+
python-version: "3.12"
|
|
30
|
+
cache: pip
|
|
31
|
+
|
|
32
|
+
- name: Install build tools
|
|
33
|
+
run: python -m pip install --upgrade pip build twine
|
|
34
|
+
|
|
35
|
+
- name: Validate release version
|
|
36
|
+
shell: python
|
|
37
|
+
run: |
|
|
38
|
+
import pathlib
|
|
39
|
+
import re
|
|
40
|
+
import tomllib
|
|
41
|
+
|
|
42
|
+
tag_version = "${{ github.ref_name }}".removeprefix("v")
|
|
43
|
+
pyproject_version = tomllib.loads(pathlib.Path("pyproject.toml").read_text())["project"]["version"]
|
|
44
|
+
init_text = pathlib.Path("src/divapply/__init__.py").read_text()
|
|
45
|
+
init_version = re.search(r'__version__\s*=\s*"([^"]+)"', init_text).group(1)
|
|
46
|
+
|
|
47
|
+
if tag_version != pyproject_version or tag_version != init_version:
|
|
48
|
+
raise SystemExit(
|
|
49
|
+
f"Version mismatch: tag={tag_version}, pyproject={pyproject_version}, __init__={init_version}"
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
changelog = pathlib.Path("CHANGELOG.md").read_text(encoding="utf-8")
|
|
53
|
+
if f"## {tag_version}" not in changelog:
|
|
54
|
+
raise SystemExit(f"CHANGELOG.md is missing a section for {tag_version}")
|
|
55
|
+
|
|
56
|
+
- name: Build package
|
|
57
|
+
run: python -m build
|
|
58
|
+
|
|
59
|
+
- name: Check package metadata
|
|
60
|
+
run: python -m twine check dist/*
|
|
61
|
+
|
|
62
|
+
- name: Smoke test built wheel
|
|
63
|
+
run: |
|
|
64
|
+
python -m venv .venv-smoke
|
|
65
|
+
. .venv-smoke/bin/activate
|
|
66
|
+
python -m pip install --upgrade pip
|
|
67
|
+
WHEEL="$(ls dist/*.whl)"
|
|
68
|
+
python -m pip install "$WHEEL[full]"
|
|
69
|
+
divapply --version
|
|
70
|
+
divapply selfcheck
|
|
71
|
+
|
|
72
|
+
- name: Publish package to PyPI
|
|
73
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
74
|
+
|
|
75
|
+
- name: Create GitHub release
|
|
76
|
+
uses: softprops/action-gh-release@v2
|
|
77
|
+
with:
|
|
78
|
+
generate_release_notes: true
|
|
79
|
+
files: dist/*
|
|
@@ -1,19 +1,38 @@
|
|
|
1
1
|
# User data (NEVER commit)
|
|
2
|
+
.divapply/
|
|
3
|
+
.applypilot/
|
|
2
4
|
profile.json
|
|
3
5
|
resume.txt
|
|
4
6
|
resume.pdf
|
|
7
|
+
answers.yaml
|
|
5
8
|
*.env
|
|
6
9
|
.env.*
|
|
7
10
|
!.env.example
|
|
11
|
+
coursework/
|
|
12
|
+
transcripts/
|
|
13
|
+
# Local search config can carry personal targeting rules; the example
|
|
14
|
+
# version (src/divapply/config/searches.example.yaml) stays tracked.
|
|
15
|
+
/searches.yaml
|
|
16
|
+
searches.local.yaml
|
|
8
17
|
|
|
9
18
|
# Runtime artifacts
|
|
10
19
|
*.db
|
|
20
|
+
*.db-wal
|
|
21
|
+
*.db-shm
|
|
22
|
+
*.sqlite
|
|
23
|
+
*.sqlite3
|
|
24
|
+
divapply.db*
|
|
25
|
+
applypilot.db*
|
|
11
26
|
tailored_resumes/
|
|
12
27
|
cover_letters/
|
|
13
28
|
chrome-workers/
|
|
14
29
|
apply-workers/
|
|
15
30
|
apply_logs/
|
|
16
31
|
logs/
|
|
32
|
+
*.log
|
|
33
|
+
screenshots/
|
|
34
|
+
social_screenshots/
|
|
35
|
+
.mcp-apply-*.json
|
|
17
36
|
.venv/
|
|
18
37
|
.vendor/
|
|
19
38
|
academic_progress.txt
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to DivApply will be documented here.
|
|
4
|
+
|
|
5
|
+
## Unreleased
|
|
6
|
+
|
|
7
|
+
- Future work will continue under the DivApply branding.
|
|
8
|
+
|
|
9
|
+
## 0.4.4
|
|
10
|
+
|
|
11
|
+
- Added `divapply edit` as the local browser setup editor for profile and search configuration.
|
|
12
|
+
- Simplified profile/search examples around no-password profile data and tiered search queries.
|
|
13
|
+
- Preserved rich profile fields when saving through the editor, including references, certifications, and education metadata.
|
|
14
|
+
- Improved scoring/search setup compatibility for simple `skills`, preferred roles, and ApplyPilot-style search YAML.
|
|
15
|
+
- Added dashboard/accessibility, discovery, enrichment, Workday, SmartExtract, scoring, and editor regression coverage.
|
|
16
|
+
- Cleaned root documentation by moving migration and AI disclosure notes under `docs/`.
|
|
17
|
+
|
|
18
|
+
## 0.4.3
|
|
19
|
+
|
|
20
|
+
- Fixed neutral job scoring edge cases for preferred qualifications and hard requirement gaps.
|
|
21
|
+
- Kept company and source/job-board fields separate in scoring, apply prompts, logs, traces, and exports.
|
|
22
|
+
- Fixed ultimate resume job selection to prioritize highest fit scores before recency.
|
|
23
|
+
- Hardened resume and cover letter HTML escaping for generated PDFs.
|
|
24
|
+
- Added regression coverage for scoring, apply prompt context, PDF template output, and safe exports.
|
|
25
|
+
|
|
26
|
+
## 0.4.2
|
|
27
|
+
|
|
28
|
+
- Added a PyPI trusted-publishing workflow for `pip install divapply` releases.
|
|
29
|
+
- Reworked the README around the simple pip-first install path.
|
|
30
|
+
- Kept the GitHub clone installers as fallback/development options.
|
|
31
|
+
|
|
32
|
+
## 0.4.1
|
|
33
|
+
|
|
34
|
+
- Fixed the GitHub Actions PyPI publish workflow so it requests repository contents access before checkout.
|
|
35
|
+
- Kept the DivApply release/docs branding aligned with the Codex-assisted development disclosure.
|
|
36
|
+
|
|
37
|
+
## 0.4.0
|
|
38
|
+
|
|
39
|
+
- Renamed the project from ApplyPilot to DivApply.
|
|
40
|
+
- Moved the Python package to `src/divapply/`.
|
|
41
|
+
- Kept the public CLI entry point as `divapply`.
|
|
42
|
+
- Added a Windows bootstrap install flow for fresh GitHub clones.
|
|
43
|
+
- Added legacy migration support for previous `~/.applypilot` data.
|
|
44
|
+
- Added hidden coursework storage for profile matching.
|
|
45
|
+
- Added one-page resume shaping and tighter PDF layout defaults.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
|
|
3
|
+
ENV DIVAPPLY_DIR=/data \
|
|
4
|
+
PYTHONUNBUFFERED=1 \
|
|
5
|
+
PIP_NO_CACHE_DIR=1
|
|
6
|
+
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
|
|
9
|
+
RUN useradd --create-home --uid 10001 appuser \
|
|
10
|
+
&& mkdir -p /data \
|
|
11
|
+
&& chown -R appuser:appuser /data
|
|
12
|
+
|
|
13
|
+
COPY pyproject.toml README.md LICENSE ./
|
|
14
|
+
COPY src ./src
|
|
15
|
+
|
|
16
|
+
RUN python -m pip install --upgrade pip \
|
|
17
|
+
&& python -m pip install .
|
|
18
|
+
|
|
19
|
+
USER appuser
|
|
20
|
+
VOLUME ["/data"]
|
|
21
|
+
|
|
22
|
+
ENTRYPOINT ["divapply"]
|
|
23
|
+
CMD ["--help"]
|
divapply-0.4.4/PKG-INFO
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: divapply
|
|
3
|
+
Version: 0.4.4
|
|
4
|
+
Summary: DivApply: AI-assisted end-to-end job application pipeline
|
|
5
|
+
Project-URL: Homepage, https://github.com/InnitDivine/DivApply
|
|
6
|
+
Project-URL: Repository, https://github.com/InnitDivine/DivApply
|
|
7
|
+
Project-URL: Issues, https://github.com/InnitDivine/DivApply/issues
|
|
8
|
+
Author: InnitDivine
|
|
9
|
+
License-Expression: AGPL-3.0-only
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ai,apply,automation,job-application,job-search,resume
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: License :: OSI Approved :: GNU Affero General Public License v3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Office/Business
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Requires-Dist: beautifulsoup4>=4.12
|
|
21
|
+
Requires-Dist: httpx>=0.24
|
|
22
|
+
Requires-Dist: pandas>=2.0
|
|
23
|
+
Requires-Dist: playwright>=1.40
|
|
24
|
+
Requires-Dist: python-dotenv>=1.2.2
|
|
25
|
+
Requires-Dist: pyyaml>=6.0
|
|
26
|
+
Requires-Dist: rich>=13.0
|
|
27
|
+
Requires-Dist: typer>=0.9.0
|
|
28
|
+
Provides-Extra: coursework
|
|
29
|
+
Requires-Dist: pypdf>=4.0; extra == 'coursework'
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pip-audit>=2.10; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: ruff>=0.1; extra == 'dev'
|
|
34
|
+
Provides-Extra: full
|
|
35
|
+
Requires-Dist: pypdf>=4.0; extra == 'full'
|
|
36
|
+
Requires-Dist: python-jobspy<1.2,>=1.1.82; extra == 'full'
|
|
37
|
+
Provides-Extra: jobspy-runtime
|
|
38
|
+
Requires-Dist: python-jobspy<1.2,>=1.1.82; extra == 'jobspy-runtime'
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
|
|
41
|
+
# DivApply
|
|
42
|
+
|
|
43
|
+
DivApply is a local-first job application assistant. It can find jobs, enrich postings, score fit, tailor resumes, write cover letters, export PDFs, and optionally help with browser-based applications.
|
|
44
|
+
|
|
45
|
+
It is designed to stay factual: it works from your profile, resume, saved preferences, and optional coursework notes. It should not invent jobs, credentials, degrees, tools, dates, metrics, or experience.
|
|
46
|
+
|
|
47
|
+
## What It Does
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
discover -> enrich -> score -> tailor -> cover -> pdf -> apply
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- Finds jobs from configured searches and direct sources.
|
|
54
|
+
- Expands postings with full descriptions and application links.
|
|
55
|
+
- Scores jobs against your real experience and required criteria.
|
|
56
|
+
- Separates required qualifications from preferred/nice-to-have items.
|
|
57
|
+
- Generates one-page tailored resumes and cover letters.
|
|
58
|
+
- Exports safe job tracking data.
|
|
59
|
+
- Can run browser apply flows only when you confirm it.
|
|
60
|
+
|
|
61
|
+
## Quick Start
|
|
62
|
+
|
|
63
|
+
Use Python 3.12 for the smoothest setup.
|
|
64
|
+
|
|
65
|
+
Recommended CLI install with `pipx`:
|
|
66
|
+
|
|
67
|
+
```powershell
|
|
68
|
+
python -m pip install --user pipx
|
|
69
|
+
python -m pipx ensurepath
|
|
70
|
+
pipx install "divapply[full]"
|
|
71
|
+
pipx run --spec playwright playwright install chromium firefox
|
|
72
|
+
divapply init
|
|
73
|
+
divapply edit
|
|
74
|
+
divapply doctor
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Virtualenv install:
|
|
78
|
+
|
|
79
|
+
```powershell
|
|
80
|
+
python -m venv .venv
|
|
81
|
+
.\.venv\Scripts\Activate.ps1
|
|
82
|
+
python -m pip install --upgrade pip
|
|
83
|
+
python -m pip install "divapply[full]"
|
|
84
|
+
python -m playwright install chromium firefox
|
|
85
|
+
divapply init
|
|
86
|
+
divapply edit
|
|
87
|
+
divapply doctor
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Install directly from GitHub before a PyPI release is available:
|
|
91
|
+
|
|
92
|
+
```powershell
|
|
93
|
+
python -m pip install "divapply[full] @ git+https://github.com/InnitDivine/DivApply.git"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Use `divapply` without extras for the lightest install. Use `divapply[coursework]` for PDF transcript import, `divapply[jobspy-runtime]` for JobSpy-backed board discovery, or `divapply[full]` for both.
|
|
97
|
+
|
|
98
|
+
Auto-apply mode also needs Node.js 18+ and an agent CLI such as Codex or Claude Code.
|
|
99
|
+
|
|
100
|
+
## Clone Setup
|
|
101
|
+
|
|
102
|
+
Use this if you want the repo files locally.
|
|
103
|
+
|
|
104
|
+
```powershell
|
|
105
|
+
git clone https://github.com/InnitDivine/DivApply.git
|
|
106
|
+
cd DivApply
|
|
107
|
+
.\install.ps1
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Update an existing clone:
|
|
111
|
+
|
|
112
|
+
```powershell
|
|
113
|
+
git pull
|
|
114
|
+
python -m pip install --upgrade -e ".[full]"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## First Run
|
|
118
|
+
|
|
119
|
+
```powershell
|
|
120
|
+
divapply init
|
|
121
|
+
divapply edit
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
This creates your local app folder and setup files:
|
|
125
|
+
|
|
126
|
+
- `profile.json` - personal details, work history, preferences
|
|
127
|
+
- `resume.txt` - master resume facts
|
|
128
|
+
- `searches.yaml` - job searches and filters
|
|
129
|
+
- `.env` - API keys and runtime settings
|
|
130
|
+
- `divapply.db` - local jobs database
|
|
131
|
+
|
|
132
|
+
These files are private and ignored by git.
|
|
133
|
+
|
|
134
|
+
Use `divapply edit` as the normal setup screen after initialization. It opens a local-only browser editor for:
|
|
135
|
+
|
|
136
|
+
- Personal/contact details
|
|
137
|
+
- Target work type and hourly pay
|
|
138
|
+
- Preferred roles and skills
|
|
139
|
+
- Work history, education, certifications, references, projects, and real metrics
|
|
140
|
+
- Search locations, query tiers, job boards, and filters
|
|
141
|
+
|
|
142
|
+
The editor saves `profile.json` and `searches.yaml` for you, so most users do not need to hand-edit JSON or YAML.
|
|
143
|
+
|
|
144
|
+
## Daily Workflow
|
|
145
|
+
|
|
146
|
+
```powershell
|
|
147
|
+
divapply doctor
|
|
148
|
+
divapply run
|
|
149
|
+
divapply status
|
|
150
|
+
divapply export jobs --out jobs.csv
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Useful targeted runs:
|
|
154
|
+
|
|
155
|
+
```powershell
|
|
156
|
+
divapply run discover enrich
|
|
157
|
+
divapply run score tailor cover
|
|
158
|
+
divapply explain https://example.com/job
|
|
159
|
+
divapply ultimate https://example.com/job
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Use dry runs before any real browser submission:
|
|
163
|
+
|
|
164
|
+
```powershell
|
|
165
|
+
divapply apply --dry-run
|
|
166
|
+
divapply apply --gen --url https://example.com/job
|
|
167
|
+
divapply apply --yes
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Search Config
|
|
171
|
+
|
|
172
|
+
`searches.yaml` controls what DivApply looks for.
|
|
173
|
+
|
|
174
|
+
Example:
|
|
175
|
+
|
|
176
|
+
```yaml
|
|
177
|
+
queries:
|
|
178
|
+
- query: "student assistant"
|
|
179
|
+
tier: 1
|
|
180
|
+
- query: "front desk part time"
|
|
181
|
+
tier: 2
|
|
182
|
+
- query: "customer service"
|
|
183
|
+
tier: 3
|
|
184
|
+
locations:
|
|
185
|
+
- location: "Logan, UT"
|
|
186
|
+
remote: false
|
|
187
|
+
- location: "Remote"
|
|
188
|
+
remote: true
|
|
189
|
+
location:
|
|
190
|
+
accept_patterns:
|
|
191
|
+
- "Logan"
|
|
192
|
+
- "Cache Valley"
|
|
193
|
+
- "Remote"
|
|
194
|
+
reject_patterns:
|
|
195
|
+
- "Salt Lake City"
|
|
196
|
+
country: "USA"
|
|
197
|
+
boards:
|
|
198
|
+
- indeed
|
|
199
|
+
- linkedin
|
|
200
|
+
defaults:
|
|
201
|
+
results_per_site: 50
|
|
202
|
+
hours_old: 168
|
|
203
|
+
exclude_titles:
|
|
204
|
+
- "senior"
|
|
205
|
+
- "director"
|
|
206
|
+
- "clearance required"
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Tier `1` should be your best, most specific searches. Tier `2` should be strong adjacent matches. Tier `3` should be broad fallback searches.
|
|
210
|
+
|
|
211
|
+
## Resume Rules
|
|
212
|
+
|
|
213
|
+
Treat `resume.txt` as the source of truth.
|
|
214
|
+
|
|
215
|
+
- Keep it broad, truthful, and complete.
|
|
216
|
+
- Add only real work, projects, education, certifications, tools, and dates.
|
|
217
|
+
- Generated resumes are job-specific views of the master resume.
|
|
218
|
+
- Coursework can help matching, but it is not copied into resumes unless it belongs there.
|
|
219
|
+
|
|
220
|
+
Validation modes:
|
|
221
|
+
|
|
222
|
+
```powershell
|
|
223
|
+
divapply run score tailor --validation strict
|
|
224
|
+
divapply run score tailor --validation normal
|
|
225
|
+
divapply run score tailor --validation lenient
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Scoring
|
|
229
|
+
|
|
230
|
+
DivApply blends:
|
|
231
|
+
|
|
232
|
+
- Required/preferred keyword matching
|
|
233
|
+
- Local similarity scoring
|
|
234
|
+
- LLM judgment
|
|
235
|
+
|
|
236
|
+
Required gaps matter more than preferred gaps. Missing preferred certifications should not block a good job match. Missing required non-substitutable items, such as a required license, degree, or clearance, can cap the score.
|
|
237
|
+
|
|
238
|
+
Inspect a job:
|
|
239
|
+
|
|
240
|
+
```powershell
|
|
241
|
+
divapply explain https://example.com/job
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Exports
|
|
245
|
+
|
|
246
|
+
```powershell
|
|
247
|
+
divapply export jobs --out jobs.csv
|
|
248
|
+
divapply export jobs --out jobs.json --format json
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Exports include safe fields such as title, company, source site, URLs, fit score, lifecycle dates, and redacted apply errors. They do not print your full profile, resume, transcript text, or secrets.
|
|
252
|
+
|
|
253
|
+
## Answer Bank
|
|
254
|
+
|
|
255
|
+
Save reusable factual answers for application forms:
|
|
256
|
+
|
|
257
|
+
```powershell
|
|
258
|
+
divapply answers add "How many years of Python experience do you have?" "2 years."
|
|
259
|
+
divapply answers list
|
|
260
|
+
divapply answers match "Years using Python?"
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Answers are local-only and must stay supported by your profile or resume.
|
|
264
|
+
|
|
265
|
+
## Coursework
|
|
266
|
+
|
|
267
|
+
Optional coursework data can improve matching without exposing transcript text.
|
|
268
|
+
|
|
269
|
+
```powershell
|
|
270
|
+
divapply import-coursework path\to\transcript.json
|
|
271
|
+
divapply coursework-summary
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Supported formats: JSON, CSV, text, and PDF if `pypdf` is installed.
|
|
275
|
+
|
|
276
|
+
## Safety
|
|
277
|
+
|
|
278
|
+
- Real auto-apply requires confirmation.
|
|
279
|
+
- Use `--dry-run` first on new sites.
|
|
280
|
+
- Do not upload private files to git.
|
|
281
|
+
- Review generated resumes before sending them.
|
|
282
|
+
- Do not let the browser agent enter SSNs, bank info, payment details, ID uploads, or biometric verification.
|
|
283
|
+
|
|
284
|
+
Privacy details: [docs/PRIVACY.md](docs/PRIVACY.md)
|
|
285
|
+
|
|
286
|
+
## Common Commands
|
|
287
|
+
|
|
288
|
+
```powershell
|
|
289
|
+
divapply init
|
|
290
|
+
divapply edit
|
|
291
|
+
divapply doctor
|
|
292
|
+
divapply selfcheck
|
|
293
|
+
divapply run
|
|
294
|
+
divapply run -w 4
|
|
295
|
+
divapply status
|
|
296
|
+
divapply dashboard
|
|
297
|
+
divapply explain JOB_URL
|
|
298
|
+
divapply export jobs --out jobs.csv
|
|
299
|
+
divapply backup
|
|
300
|
+
divapply ultimate JOB_URL_OR_TITLE_FRAGMENT
|
|
301
|
+
divapply apply --dry-run
|
|
302
|
+
divapply apply --yes
|
|
303
|
+
divapply migrate
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Development
|
|
307
|
+
|
|
308
|
+
```powershell
|
|
309
|
+
git clone https://github.com/InnitDivine/DivApply.git
|
|
310
|
+
cd DivApply
|
|
311
|
+
.\install.ps1 -Dev
|
|
312
|
+
python -m pytest -q
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Release notes: [CHANGELOG.md](CHANGELOG.md)
|
|
316
|
+
|
|
317
|
+
Publishing notes: [PUBLISHING.md](PUBLISHING.md)
|
|
318
|
+
|
|
319
|
+
Operations notes: [docs/OPERATIONS.md](docs/OPERATIONS.md)
|
|
320
|
+
|
|
321
|
+
AI assistance disclosure: [docs/AI_ASSISTANCE.md](docs/AI_ASSISTANCE.md)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Publishing DivApply to PyPI
|
|
2
|
+
|
|
3
|
+
This repo is set up for PyPI Trusted Publishing through GitHub Actions. No PyPI API token is needed.
|
|
4
|
+
|
|
5
|
+
## One-Time PyPI Setup
|
|
6
|
+
|
|
7
|
+
Create or sign in to a PyPI account, then add a trusted publisher for DivApply.
|
|
8
|
+
|
|
9
|
+
Use these values:
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
PyPI project name: divapply
|
|
13
|
+
Owner: InnitDivine
|
|
14
|
+
Repository name: DivApply
|
|
15
|
+
Workflow filename: publish.yml
|
|
16
|
+
Environment name: pypi
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
If PyPI asks for the full workflow path, use:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
.github/workflows/publish.yml
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Release
|
|
26
|
+
|
|
27
|
+
Before tagging, run the local checks:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
python -m pytest -q
|
|
31
|
+
ruff check .
|
|
32
|
+
python -m build
|
|
33
|
+
python -m twine check dist/*
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Update the version in both files:
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
pyproject.toml
|
|
40
|
+
src/divapply/__init__.py
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Add the same version section to:
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
CHANGELOG.md
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Commit the version change, then tag and push:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
git tag v0.4.4
|
|
53
|
+
git push origin main
|
|
54
|
+
git push origin v0.4.4
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The `Release` workflow will build the package, verify the tag matches `pyproject.toml`, `src/divapply/__init__.py`, and `CHANGELOG.md`, publish to PyPI, and create a GitHub Release with the built artifacts. After the workflow succeeds, users can install with:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install "divapply[full]"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Before the next PyPI release, users can install the latest `main` directly from GitHub:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pip install "divapply[full] @ git+https://github.com/InnitDivine/DivApply.git"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Verify
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
python -m pip install --upgrade "divapply[full]"
|
|
73
|
+
divapply --version
|
|
74
|
+
divapply doctor
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The workflow only runs from `v*` tags and verifies that the tag matches both version files plus the changelog before publishing.
|