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.
Files changed (114) hide show
  1. divapply-0.4.4/.dockerignore +34 -0
  2. divapply-0.4.4/.github/workflows/ci.yml +92 -0
  3. divapply-0.4.4/.github/workflows/publish.yml +79 -0
  4. {divapply-0.4.2 → divapply-0.4.4}/.gitignore +19 -0
  5. divapply-0.4.4/CHANGELOG.md +45 -0
  6. divapply-0.4.4/Dockerfile +23 -0
  7. divapply-0.4.4/PKG-INFO +321 -0
  8. divapply-0.4.4/PUBLISHING.md +77 -0
  9. divapply-0.4.4/README.md +281 -0
  10. divapply-0.4.2/MIGRATION_CHECKLIST.md → divapply-0.4.4/docs/MIGRATION.md +1 -1
  11. divapply-0.4.4/docs/OPERATIONS.md +92 -0
  12. divapply-0.4.4/docs/PRIVACY.md +36 -0
  13. {divapply-0.4.2 → divapply-0.4.4}/install.ps1 +4 -0
  14. {divapply-0.4.2 → divapply-0.4.4}/install.sh +6 -1
  15. divapply-0.4.4/profile.example.json +120 -0
  16. {divapply-0.4.2 → divapply-0.4.4}/pyproject.toml +5 -13
  17. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/__init__.py +1 -1
  18. divapply-0.4.4/src/divapply/apply/answers.py +115 -0
  19. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/apply/dashboard.py +1 -1
  20. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/apply/launcher.py +306 -673
  21. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/apply/prompt.py +183 -114
  22. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/cli.py +667 -26
  23. divapply-0.4.4/src/divapply/config/employers.yaml +32 -0
  24. divapply-0.4.4/src/divapply/config/searches.example.yaml +87 -0
  25. divapply-0.4.4/src/divapply/config/sites.yaml +78 -0
  26. divapply-0.4.4/src/divapply/config.py +513 -0
  27. divapply-0.4.4/src/divapply/database.py +1074 -0
  28. divapply-0.4.4/src/divapply/discovery/filters.py +73 -0
  29. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/discovery/jobspy.py +247 -37
  30. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/discovery/smartextract.py +117 -46
  31. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/discovery/workday.py +56 -41
  32. divapply-0.4.4/src/divapply/editor.py +988 -0
  33. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/enrichment/detail.py +30 -16
  34. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/llm.py +55 -7
  35. divapply-0.4.4/src/divapply/migrations/__init__.py +74 -0
  36. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/pipeline.py +143 -95
  37. divapply-0.4.4/src/divapply/privacy.py +21 -0
  38. divapply-0.4.4/src/divapply/runtime.py +196 -0
  39. divapply-0.4.4/src/divapply/scoring/composite.py +165 -0
  40. divapply-0.4.4/src/divapply/scoring/context.py +16 -0
  41. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/scoring/cover_letter.py +8 -14
  42. divapply-0.4.4/src/divapply/scoring/embedding.py +49 -0
  43. divapply-0.4.4/src/divapply/scoring/keywords.py +209 -0
  44. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/scoring/pdf.py +42 -22
  45. divapply-0.4.4/src/divapply/scoring/scorer.py +440 -0
  46. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/scoring/tailor.py +74 -53
  47. divapply-0.4.4/src/divapply/scoring/ultimate.py +154 -0
  48. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/scoring/validator.py +37 -15
  49. divapply-0.4.4/src/divapply/security.py +155 -0
  50. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/social.py +25 -7
  51. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/view.py +171 -96
  52. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/wizard/init.py +9 -2
  53. divapply-0.4.4/tests/conftest.py +12 -0
  54. divapply-0.4.4/tests/test_answer_bank.py +24 -0
  55. divapply-0.4.4/tests/test_apply_launcher.py +564 -0
  56. divapply-0.4.4/tests/test_apply_prompt.py +175 -0
  57. divapply-0.4.4/tests/test_backup.py +108 -0
  58. divapply-0.4.4/tests/test_cli_help.py +64 -0
  59. divapply-0.4.4/tests/test_config_loading.py +60 -0
  60. divapply-0.4.4/tests/test_coursework_summary.py +105 -0
  61. divapply-0.4.4/tests/test_credentials_config.py +30 -0
  62. divapply-0.4.4/tests/test_dashboard_view.py +81 -0
  63. divapply-0.4.4/tests/test_discovery_filters.py +170 -0
  64. divapply-0.4.4/tests/test_editor.py +345 -0
  65. divapply-0.4.4/tests/test_enrichment_detail_edges.py +132 -0
  66. divapply-0.4.4/tests/test_export_redaction.py +92 -0
  67. divapply-0.4.4/tests/test_hybrid_scoring.py +245 -0
  68. divapply-0.4.4/tests/test_lifecycle_and_dedup.py +324 -0
  69. divapply-0.4.4/tests/test_llm_aliases.py +17 -0
  70. divapply-0.4.4/tests/test_migrations.py +17 -0
  71. divapply-0.4.4/tests/test_pdf_template.py +79 -0
  72. divapply-0.4.4/tests/test_pipeline_stage_dispatch.py +50 -0
  73. divapply-0.4.4/tests/test_runtime_edges.py +24 -0
  74. divapply-0.4.4/tests/test_scoring_parser.py +38 -0
  75. divapply-0.4.4/tests/test_security.py +83 -0
  76. divapply-0.4.4/tests/test_smartextract_config.py +44 -0
  77. divapply-0.4.4/tests/test_smartextract_edges.py +103 -0
  78. divapply-0.4.4/tests/test_social_credentials.py +46 -0
  79. divapply-0.4.4/tests/test_tailor_trace.py +19 -0
  80. {divapply-0.4.2 → divapply-0.4.4}/tests/test_tier.py +11 -11
  81. divapply-0.4.4/tests/test_ultimate_resume.py +102 -0
  82. divapply-0.4.4/tests/test_validator_modes.py +94 -0
  83. divapply-0.4.4/tests/test_workday_config.py +58 -0
  84. divapply-0.4.4/tests/test_workday_edges.py +156 -0
  85. {divapply-0.4.2 → divapply-0.4.4}/tools/bootstrap.ps1 +6 -1
  86. divapply-0.4.2/.github/workflows/ci.yml +0 -29
  87. divapply-0.4.2/.github/workflows/publish.yml +0 -38
  88. divapply-0.4.2/CHANGELOG.md +0 -28
  89. divapply-0.4.2/PKG-INFO +0 -278
  90. divapply-0.4.2/PUBLISHING.md +0 -54
  91. divapply-0.4.2/README.md +0 -231
  92. divapply-0.4.2/profile.example.json +0 -61
  93. divapply-0.4.2/src/divapply/config/employers.yaml +0 -31
  94. divapply-0.4.2/src/divapply/config/searches.example.yaml +0 -113
  95. divapply-0.4.2/src/divapply/config/sites.yaml +0 -107
  96. divapply-0.4.2/src/divapply/config.py +0 -445
  97. divapply-0.4.2/src/divapply/database.py +0 -635
  98. divapply-0.4.2/src/divapply/scoring/scorer.py +0 -230
  99. divapply-0.4.2/src/divapply/scoring/ultimate.py +0 -214
  100. {divapply-0.4.2 → divapply-0.4.4}/.env.example +0 -0
  101. {divapply-0.4.2 → divapply-0.4.4}/CONTRIBUTING.md +0 -0
  102. {divapply-0.4.2 → divapply-0.4.4}/LICENSE +0 -0
  103. {divapply-0.4.2 → divapply-0.4.4/docs}/AI_ASSISTANCE.md +0 -0
  104. {divapply-0.4.2 → divapply-0.4.4}/install.cmd +0 -0
  105. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/__main__.py +0 -0
  106. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/apply/__init__.py +0 -0
  107. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/apply/chrome.py +0 -0
  108. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/config/coursework.seed.json +0 -0
  109. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/discovery/__init__.py +0 -0
  110. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/enrichment/__init__.py +0 -0
  111. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/scoring/__init__.py +0 -0
  112. {divapply-0.4.2 → divapply-0.4.4}/src/divapply/wizard/__init__.py +0 -0
  113. {divapply-0.4.2 → divapply-0.4.4}/tests/test_migration.py +0 -0
  114. {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"]
@@ -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.