Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = true

[*.cs]
indent_style = space
indent_size = 4
csharp_new_line_before_open_brace = all
csharp_style_var_elsewhere = false:suggestion
csharp_style_var_for_built_in_types = false:suggestion
csharp_style_var_when_type_is_apparent = false:suggestion
20 changes: 20 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: ci
on:
push:
pull_request:
jobs:
build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Restore
run: dotnet restore SentinelCareer.sln
- name: Build
run: dotnet build SentinelCareer.sln --no-restore -c Release
- name: Test
run: dotnet test SentinelCareer.sln --no-build -c Release
- name: Format check
run: dotnet format SentinelCareer.sln --verify-no-changes
20 changes: 20 additions & 0 deletions .github/workflows/package-windows.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: package-windows
on:
workflow_dispatch:
push:
tags:
- 'v*'
jobs:
package:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- run: dotnet publish src/SentinelCareer.Web -c Release -r win-x64 --self-contained false -o artifacts/web
- run: dotnet publish src/SentinelCareer.Workers -c Release -r win-x64 --self-contained false -o artifacts/workers
- uses: actions/upload-artifact@v4
with:
name: sentinelcareer-win
path: artifacts
17 changes: 17 additions & 0 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: security
on:
push:
pull_request:
jobs:
dependency-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- run: dotnet list SentinelCareer.sln package --vulnerable --include-transitive
- uses: github/codeql-action/init@v3
with:
languages: csharp
- uses: github/codeql-action/analyze@v3
20 changes: 20 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
bin/
obj/
.vs/
.idea/
*.user
*.suo
*.db
*.sqlite
TestResults/
artifacts/
.env
.env.*
.python-version
__pycache__/
.pytest_cache/
.mypy_cache/
.venv/
*.pyc
node_modules/
playwright-report/
20 changes: 20 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.7" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.4" />
<PackageVersion Include="Npgsql" Version="8.0.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.7" />
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
<PackageVersion Include="CsvHelper" Version="32.0.3" />
<PackageVersion Include="FluentValidation" Version="11.9.2" />
<PackageVersion Include="xunit" Version="2.9.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.7" />
<PackageVersion Include="Playwright" Version="1.45.0" />
</ItemGroup>
</Project>
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# SentinelCareer

SentinelCareer is a Windows-local AI-assisted job intelligence platform for a single operator, focused on India-first senior opportunities in operations/governance/risk/transformation leadership.

## Architecture
- `SentinelCareer.Web`: ASP.NET Core Razor dashboard.
- `SentinelCareer.Workers`: background ingestion/scoring workers (Windows service-capable).
- `SentinelCareer.Domain`: entities and deterministic scoring rules.
- `SentinelCareer.Application`: use-cases, normalization, scoring engine, dedupe, interview prep orchestration.
- `SentinelCareer.Infrastructure`: EF Core + Npgsql, adapters, repositories, notifications, source-run persistence, seeding.
- `SentinelCareer.PythonWorkers`: optional parsing/model helpers.

## Windows-local productionization highlights
- One-command setup: `pwsh ./scripts/setup-local.ps1`
- One-command startup: `pwsh ./scripts/start-local.ps1`
- One-command workers: `pwsh ./scripts/run-workers.ps1`
- Real Windows toast attempt via PowerShell + Windows runtime API with fallback logging.
- Source-run start/end persistence for troubleshooting.
- Backup/restore scripts for local PostgreSQL (`backup-db.ps1`, `restore-db.ps1`).

## Validation & calibration pack (current)
Seeded validation pack includes:
- 10 watchlist companies
- 5 executive search sources
- 3 public-sector/strategic portals
- 3 event/expo/industry sources
- 3 tender/EOI/procurement sources
- 2 selective job boards

## Windows local setup
1. Install .NET SDK 8+ and PostgreSQL 15+.
2. Run `pwsh ./scripts/setup-local.ps1`.
3. Start app stack with `pwsh ./scripts/start-local.ps1`.
4. Validate host E2E + evidence capture with `pwsh ./scripts/windows-e2e-validate.ps1`.
5. Verify evidence completeness with `pwsh ./scripts/review-host-evidence.ps1`.

## Backup and restore
- Backup: `pwsh ./scripts/backup-db.ps1`
- Restore: `pwsh ./scripts/restore-db.ps1 -Input .\backup\sentinelcareer-YYYYMMDD-HHMMSS.sql`

## Testing
- Domain scoring threshold tests.
- Application scoring/normalization/dedupe tests.
- Infrastructure adapter tests.
- Worker notification semantics tests.
- PostgreSQL integration tests (when `SENTINELCAREER_TEST_PG` is set).
- Python parser tests.

## Docs
- `docs/windows-setup.md`
- `docs/runbook.md`
- `docs/productionization-report.md`
- `docs/calibration-report.md`
- `docs/windows-host-validation.md`
- `docs/host-validation-report.md`
- `docs/remediation-report.md`
39 changes: 39 additions & 0 deletions SentinelCareer.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SentinelCareer.Contracts", "src/SentinelCareer.Contracts/SentinelCareer.Contracts.csproj", "{10000000-0000-0000-0000-000000000001}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SentinelCareer.Domain", "src/SentinelCareer.Domain/SentinelCareer.Domain.csproj", "{10000000-0000-0000-0000-000000000002}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SentinelCareer.Application", "src/SentinelCareer.Application/SentinelCareer.Application.csproj", "{10000000-0000-0000-0000-000000000003}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SentinelCareer.Infrastructure", "src/SentinelCareer.Infrastructure/SentinelCareer.Infrastructure.csproj", "{10000000-0000-0000-0000-000000000004}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SentinelCareer.Web", "src/SentinelCareer.Web/SentinelCareer.Web.csproj", "{10000000-0000-0000-0000-000000000005}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SentinelCareer.Workers", "src/SentinelCareer.Workers/SentinelCareer.Workers.csproj", "{10000000-0000-0000-0000-000000000006}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SentinelCareer.Domain.Tests", "tests/SentinelCareer.Domain.Tests/SentinelCareer.Domain.Tests.csproj", "{10000000-0000-0000-0000-000000000007}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SentinelCareer.Application.Tests", "tests/SentinelCareer.Application.Tests/SentinelCareer.Application.Tests.csproj", "{10000000-0000-0000-0000-000000000008}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SentinelCareer.Infrastructure.Tests", "tests/SentinelCareer.Infrastructure.Tests/SentinelCareer.Infrastructure.Tests.csproj", "{10000000-0000-0000-0000-000000000009}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SentinelCareer.IntegrationTests", "tests/SentinelCareer.IntegrationTests/SentinelCareer.IntegrationTests.csproj", "{10000000-0000-0000-0000-00000000000A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SentinelCareer.Web.SmokeTests", "tests/SentinelCareer.Web.SmokeTests/SentinelCareer.Web.SmokeTests.csproj", "{10000000-0000-0000-0000-00000000000B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SentinelCareer.Workers.Tests", "tests/SentinelCareer.Workers.Tests/SentinelCareer.Workers.Tests.csproj", "{10000000-0000-0000-0000-00000000000C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
3 changes: 3 additions & 0 deletions docs/adr-001-deterministic-scoring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ADR-001 Deterministic-first Scoring
Decision: keep numeric scoring deterministic and auditable, with optional LLM rewrite limited to language cleanup.
Status: accepted.
3 changes: 3 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Architecture Summary
SentinelCareer uses a modular monorepo with .NET-first services and optional Python workers.
Data flow: Source registry -> Adapter ingestion -> Normalization -> Dedupe/merge -> Deterministic scoring -> alerts + dashboard + interview prep.
28 changes: 28 additions & 0 deletions docs/calibration-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Calibration report

## Issues found
- Mid-level roles with generic operations language could score too high.
- Compensation parsing had weak handling for ranges/crore/currency variants.
- Notification semantics needed explicit codification for new>=80 and +5 improvements.
- Triage flow needed operator decisioning and clearer score movement/history.
- Worker retries needed stronger timeout/jitter/per-item failure isolation.

## Calibration changes applied
- Updated deterministic scoring rules to penalize mid-level cues and out-of-sector generic operations context.
- Strengthened exclusion penalties for engineering/analyst/sales cues.
- Improved compensation parsing/conversion logic for LPA/lakh/crore and USD/EUR/GBP.
- Added review workflow persistence (`Status`, `OperatorNotes`) with dashboard controls.
- Added score delta and score history display in triage.
- Added source pack seeding for validation coverage counts.
- Added tests for compensation edges, duplicate boundary behavior, score threshold transitions, parser edge cases, and notification semantics.

## Known limitations
- Validation sources are configured as representative endpoints; production source-specific selectors still require site-by-site hardening.
- Windows desktop notifications are still a logger-backed stub.
- Full integration test against live PostgreSQL was not executable in this environment due missing `dotnet` runtime.

## Recommended next phase
- Run full Windows local validation against real endpoints and tune source-specific parsers.
- Add PostgreSQL-backed integration suite for ingestion/reconciliation workflows.
- Replace notification stub with real Windows toast integration.
- Expand migration history to fully align all domain entities and future review fields.
28 changes: 28 additions & 0 deletions docs/host-validation-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Host validation report

## Environment used
- Host: (fill Windows version/build)
- .NET SDK: (fill)
- PostgreSQL: (fill)
- Validation date/time: (fill)

## Issues found
- (fill)

## Fixes applied
- (fill)

## Evidence captured
- restore/build logs
- migration output
- source-run summary
- API output
- web/worker logs
- dashboard screenshots
- notification evidence

## Remaining limitations
- (fill)

## Recommended next phase
- (fill)
28 changes: 28 additions & 0 deletions docs/productionization-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Productionization report

## Issues found
- Notification implementation was a logging stub, not real Windows toast.
- Source-run lifecycle status was not persisted for troubleshooting.
- Source adapters had weak live-endpoint resilience and limited fallback parsing.
- Integration coverage for PostgreSQL persistence workflows was shallow.
- Windows-local operations lacked explicit one-command setup/start and backup/restore scripts.

## Fixes applied
- Added Windows-host E2E validation script (`scripts/windows-e2e-validate.ps1`) and host validation documentation/report template.
- Implemented real Windows-local toast attempt using PowerShell + Windows runtime Toast API, with safe fallback logging.
- Added source-run persistence methods and wired worker to start/complete source run records.
- Improved adapter anti-brittleness patterns with HTTP fetch fallback, selector fallback extraction, and source-specific logs.
- Added PostgreSQL-backed integration tests for migration/table visibility and review workflow persistence (env-driven).
- Added one-command scripts: setup/start and backup/restore.
- Updated Windows setup and runbook docs with troubleshooting and recovery guidance.

## Remaining limitations
- Full automated E2E execution could not be run in this environment because `dotnet` is unavailable; use the host validation script on Windows.
- Live source parsers are still generic templates; source-specific selectors need iterative tuning per endpoint.
- Toast behavior depends on Windows runtime availability and PowerShell execution policy.

## Recommended next phase
- Run full Windows laptop validation pass and capture runtime logs/screenshots.
- Add source-specific parser contract tests with HTML fixtures per high-priority endpoint.
- Add scheduled backup rotation and restore verification job.
- Expand integration suite with source-run and score-history round-trip assertions using dedicated test DB.
27 changes: 27 additions & 0 deletions docs/remediation-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Remediation report

## Evidence reviewed
- No `artifacts/host-validation/` payload was present in this environment at review time.
- Existing host-validation scripts/docs were reviewed for failure ambiguity and evidence completeness gaps.

## Issues found
- Missing host-validation evidence prevented concrete runtime issue attribution.
- `windows-e2e-validate.ps1` had ambiguous failure behavior (continued across failing steps) and no explicit status summary.
- Notification proof extraction was not explicit.
- Evidence completeness checks were manual and error-prone.

## Fixes applied
- Hardened `windows-e2e-validate.ps1` with strict mode, step gating, explicit success/failure summary, and notification evidence extraction.
- Fixed notification evidence matching to use regex pattern detection for toast log lines.
- Added `review-host-evidence.ps1` to validate expected host evidence files and generate `evidence-review.txt`.
- Extended evidence review script with quick diagnostics for common web/worker/migration failure signatures.
- Updated host-validation docs to include required evidence set and review workflow.

## Remaining limitations
- Actual Windows runtime issues cannot be conclusively diagnosed until host evidence is generated and reviewed.
- Live endpoint parser tuning remains constrained without concrete failing endpoint logs/HTML captures.

## Next recommended phase
1. Execute `pwsh ./scripts/windows-e2e-validate.ps1` on the target Windows host.
2. Execute `pwsh ./scripts/review-host-evidence.ps1`.
3. Share `artifacts/host-validation/*` (including screenshots and notification logs) for issue-specific remediation.
33 changes: 33 additions & 0 deletions docs/runbook.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Operator runbook

## Setup / startup
1. `pwsh ./scripts/setup-local.ps1`
2. `pwsh ./scripts/start-local.ps1`

## Windows host E2E validation
- Run `pwsh ./scripts/windows-e2e-validate.ps1`.
- Run `pwsh ./scripts/review-host-evidence.ps1`.
- Review files in `artifacts/host-validation`.

## Validate end-to-end local execution
- PostgreSQL running and reachable.
- Migration applied (`JobOpportunities` table exists).
- Seed loaded (validation pack sources/watchlist).
- Web UI reachable.
- Worker logs show scheduled ingestion/scoring cycles.
- Source run statuses persisted (`SourceRuns` table).
- Notification attempt logged/visible.
- Shutdown is graceful.

## Operations
- Monitor logs for `SourceRunStart/End`, retry warnings, and source-level run status.
- Use Opportunities page to mark pursue/review/ignore and capture notes.
- Verify score history and score delta movement for key opportunities.
- Confirm alerts fire only for new >=80 and +5 score improvements.

## Troubleshooting
- Source fetch failure: check `AdapterFetchFallback` entries and endpoint env vars (`SENTINELCAREER_COMPANY_SOURCE`, `SENTINELCAREER_EXEC_SOURCE`).
- Parser empty: check `AdapterParseEmpty` and inspect endpoint HTML drift.
- No notifications: verify Windows session notifications enabled and check worker logs for PowerShell toast errors.
- If a source repeatedly fails, disable it in `Sources` table and continue.
- If DB corruption suspected, restore from last backup using `restore-db.ps1`.
22 changes: 22 additions & 0 deletions docs/scoring-model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Scoring model

Required sub-scores:
- profile_fit
- compensation_fit
- geography_fit
- seniority_fit
- industry_fit
- source_credibility
- freshness
- opportunity_potential

Bands:
- >=80 pursue immediately
- 65-79 review manually
- <65 track only

Hardening notes:
- India-first and seniority alignment are positively weighted.
- Compensation uses baseline 35L and premium 50L thresholds.
- Explicit penalties are applied for excluded role families (engineering-heavy, SOC analyst, sales-only cues).
- Explanation text now includes deterministic reason statements for operator triage.
Loading
Loading