Complete schema, defaults, and validation rules for all TOML configuration files. See ARCHITECTURE.md for how these feed into the pipeline.
| File | Purpose | Required |
|---|---|---|
config/settings.toml |
Board config, scoring weights, Ollama connection, output, ChromaDB | Yes |
config/role_archetypes.toml |
Target role descriptions with positive/negative signals | Yes |
config/global_rubric.toml |
Universal evaluation dimensions (culture, structure, comp) | Yes |
data/resume.md |
Your resume in plain Markdown | Yes (for indexing) |
| Key | Type | Default | Description |
|---|---|---|---|
enabled |
list[str] |
(required) | Board names to search on every run |
overnight_boards |
list[str] |
[] |
Boards requiring extended throttling (e.g., LinkedIn) |
session_storage_dir |
str |
"data" |
Directory for Playwright session cookie files |
Each enabled board must have a corresponding [boards.<name>] section.
| Key | Type | Default | Description |
|---|---|---|---|
searches |
list[str] |
(required) | Search URLs or query terms |
max_pages |
int |
3 |
Maximum search result pages to paginate |
headless |
bool |
true |
Run browser without visible window |
browser_channel |
str | null |
null |
System browser for CDP mode: "msedge", "chrome", "chromium" |
rate_limit_range |
[float, float] |
(required) | [min, max] seconds of random jitter between search-URL navigations and between JD detail-page requests |
login_url |
str | null |
null |
Override login URL for login --board command |
stealth |
bool |
false |
Enable playwright-stealth patches (fingerprint masking) |
throttle_max_retries |
int |
3 |
Max retries on throttle detection (board-specific) |
throttle_base_delay |
float |
2.0 |
Base delay in seconds for exponential throttle backoff; doubles each consecutive throttle (e.g., 4 → 8 → 16 s with base 4.0). Resets on success. |
When browser_channel is set, the session manager launches the real system
browser and connects via Chrome DevTools Protocol instead of Playwright's
bundled Chromium. This bypasses Cloudflare bot detection.
| Key | Type | Default | Valid Range | Description |
|---|---|---|---|---|
archetype_weight |
float |
0.5 |
0.0–1.0 | Weight for role-archetype similarity |
fit_weight |
float |
0.3 |
0.0–1.0 | Weight for resume similarity |
history_weight |
float |
0.2 |
0.0–1.0 | Weight for past-decision similarity |
comp_weight |
float |
0.15 |
0.0–1.0 | Weight for compensation alignment |
negative_weight |
float |
0.4 |
0.0–1.0 | Penalty multiplier for negative signals |
culture_weight |
float |
0.2 |
0.0–1.0 | Weight for culture/work-model alignment |
base_salary |
float |
220000 |
> 0 | Reference salary for compensation scoring |
disqualify_on_llm_flag |
bool |
true |
— | Enable LLM-based disqualification |
min_score_threshold |
float |
0.45 |
0.0–1.0 | Exclude listings scoring below this |
missing_comp_score |
float |
0.5 |
0.0–1.0 | Score when no salary data found (neutral) |
chunk_overlap |
int |
2000 |
> 0 | Character overlap between JD chunks |
dedup_similarity_threshold |
float |
0.95 |
0.0–1.0 | Cosine threshold for near-deduplication |
max_parallel |
int |
2 |
1–8 | Concurrent scoring tasks (coordinate with OLLAMA_NUM_PARALLEL) |
Weights are not required to sum to 1.0. They are applied as raw multipliers in the fusion formula (see SCORING_ENGINE.md).
history_weight— Start at 0.2. After ~50 decisions, consider raising to 0.3. After ~200, the history collection may be your strongest signal.culture_weight— Start at 0.2. Global positive signals encode environment preferences that JDs express inconsistently — "async-first" and "remote-first" appear explicitly in some JDs and implicitly (or not at all) in others. The history signal eventually complements this as culture-based yes/no decisions accumulate.negative_weight— Start at 0.4. A strong negative match (adtech, surveillance, chaos culture) should meaningfully suppress ranking even when positive signals are present.
| Key | Type | Default | Description |
|---|---|---|---|
base_url |
str |
"http://localhost:11434" |
Ollama API endpoint (must start with http:// or https://) |
llm_model |
str |
"mistral:7b" |
Model for disqualification and classification |
embed_model |
str |
"nomic-embed-text" |
Model for embedding generation |
slow_llm_threshold_ms |
int |
30000 |
Log warning when LLM calls exceed this |
classify_system_prompt |
str |
(required) | System message for the LLM classifier |
max_retries |
int |
3 |
Maximum retry attempts for transient Ollama failures |
base_delay |
float |
1.0 |
Base delay in seconds for exponential backoff |
max_embed_chars |
int |
8000 |
Maximum characters sent to the embedding model |
head_ratio |
float |
0.6 |
Fraction of max_embed_chars allocated to head (vs. tail) during truncation |
retryable_status_codes |
list[int] |
[408, 429, 500, 502, 503, 504] |
HTTP status codes that trigger retry |
| Key | Type | Default | Description |
|---|---|---|---|
default_format |
str |
"markdown" |
Export format: "markdown", "csv", "json" |
output_dir |
str |
"./output" |
Directory for results and JD files |
open_top_n |
int |
5 |
Number of top results to open in browser tabs |
jd_dir |
str |
"output/jds" |
Directory for individual JD markdown files |
decisions_dir |
str |
"data/decisions" |
Directory for JSONL decision audit logs |
log_dir |
str |
"data/logs" |
Directory for structured JSONL session logs |
eval_history_path |
str |
"data/eval_history.jsonl" |
Append-only file for eval run metrics |
| Key | Type | Default | Description |
|---|---|---|---|
persist_dir |
str |
"./data/chroma_db" |
ChromaDB storage directory |
| Key | Type | Default | Description |
|---|---|---|---|
screen_prompt |
str |
(required) | Prompt for LLM injection screening pass (reviews JD text for AI-directed instructions) |
| Key | Type | Default | Description |
|---|---|---|---|
cdp_timeout |
float |
15.0 |
Seconds to wait for CDP browser to start accepting connections |
Optional per-channel browser binary paths. When provided for a channel, these paths are used exclusively (no fallback to platform defaults).
| Key | Type | Default | Description |
|---|---|---|---|
msedge |
list[str] |
(platform defaults) | Paths to Microsoft Edge binary |
chrome |
list[str] |
(platform defaults) | Paths to Google Chrome binary |
chromium |
list[str] |
(platform defaults) | Paths to Chromium binary |
Compensation scoring curve defined as { ratio, score } pairs. Ratios are
relative to base_salary (e.g., ratio = 0.90 means 90% of base). The
scorer linearly interpolates between adjacent bands.
| Key | Type | Valid Range | Description |
|---|---|---|---|
ratio |
float |
0.0–1.0+ | comp_max / base_salary threshold |
score |
float |
0.0–1.0 | Score assigned at this ratio |
Constraints: Must have ≥2 entries. Ratios must be strictly descending (highest first). Above the top band → top score. Below the bottom band → bottom score.
| Key | Type | Default | Description |
|---|---|---|---|
resume_path |
str |
"data/resume.md" |
Path to resume file |
archetypes_path |
str |
"config/role_archetypes.toml" |
Path to role archetypes |
global_rubric_path |
str |
"config/global_rubric.toml" |
Path to global rubric |
The config loader (config.py) validates on startup:
| Rule | Error Type | Triggered When |
|---|---|---|
| All weight fields in [0.0, 1.0] | VALIDATION |
Weight outside range |
base_salary > 0 |
VALIDATION |
Zero or negative salary |
ollama.base_url starts with http:// or https:// |
VALIDATION |
Invalid URL scheme |
Each board in enabled has a [boards.<name>] section |
CONFIG |
Missing board section |
global_rubric_path file exists on disk |
CONFIG |
File not found |
| TOML syntax is valid | PARSE |
Malformed TOML |
Defines the roles you're targeting. Each archetype produces one document in
the role_archetypes ChromaDB collection and contributes negative signals
to the negative_signals collection.
[[archetypes]]
name = "AI Systems Engineer / AI Platform Architect"
description = """
Multi-paragraph narrative describing the ideal role.
The more specific, the better the embedding match quality.
"""
signals_positive = [
"LLM systems and agentic workflows",
"Vector database design",
"Evaluation and observability for AI systems",
]
signals_negative = [
"Primarily frontend or UI development",
"Junior or entry-level role",
]| Field | Type | Required | Description |
|---|---|---|---|
name |
str |
Yes | Unique identifier for the archetype |
description |
str |
Yes | Rich narrative (embedded with positive signals) |
signals_positive |
list[str] |
No | Keywords/phrases that boost archetype match |
signals_negative |
list[str] |
No | Keywords/phrases indexed as negative signals |
Embedding synthesis: The indexer combines description + signals_positive
into a single embedding text. This creates richer vectors that capture both
the narrative role description and concrete skill keywords.
Archetype ordering reflects priority: Archetypes are listed in priority order — the first entry is treated as the primary career target. Order them from most desired to least desired role type.
Universal evaluation dimensions that apply to all roles regardless of
archetype. Each dimension produces documents in two collections:
global_positive_signals (one doc per dimension) and negative_signals
(one doc per negative signal).
[[dimensions]]
name = "Culture & Work Model"
signals_positive = [
"Remote-first or distributed team",
"Async communication culture",
"Psychological safety emphasis",
]
signals_negative = [
"Mandatory return-to-office",
"Startup burnout culture",
"Military-style hierarchy",
]| Field | Type | Required | Description |
|---|---|---|---|
name |
str |
Yes | Dimension name (stored as metadata) |
signals_positive |
list[str] |
No | Positive indicators for this dimension |
signals_negative |
list[str] |
No | Negative indicators (indexed as penalty signals) |
- Role Scope — cross-team influence, organizational reach
- Technical Depth — infrastructure, platform, distributed systems
- Operational Burden — on-call ownership vs. platform engineering
- Industry Alignment — devtools, climate, health-tech vs. adtech, gambling
- Employment Structure — direct hire vs. staffing agencies
- Seniority Mismatch — Staff/Principal expectations vs. offered level
- Compensation Red Flags — transparent range, market alignment
- Culture & Work Model — remote, async, autonomy, sustainability
- Neurodivergence Compatibility — clear communication, low context-switching
- Ethical Alignment — mission-driven, privacy-respecting
- Use full sentences. Signals like "Cross-team architectural influence
and organizational scope" embed with significantly better cosine
discrimination than short keyword phrases like "architecture ownership."
nomic-embed-textis a sentence-transformer — it produces richer vectors from complete thoughts. - Neurodivergence Compatibility is the weakest signal. JDs rarely use
language like "low-meeting culture" directly. This dimension will
strengthen as the
decisionshistory collection builds up examples of culture-based yes/no verdicts.
Plain Markdown file. The indexer splits on ## headings, producing one
ChromaDB document per section. ### sub-headings are kept within their
parent section.
The # title heading (if present) is skipped — only ## sections are indexed.
Playwright's storage_state saves cookies per board to separate JSON files
under session_storage_dir (default data/). Re-authentication is only
needed when sessions expire. Each board gets its own file
(<board_name>_session.json).