Felipe Tavares — brain glyph brand mark Felipe Tavares
Incubating Founder & architect

Selfwright

An open-core, local-first personal operating system for career, expertise, influence, and knowledge.

Architecture
API-first, DDD, modular monolith, hexagonal
ATS pass rate (acceptance roles)
0%
Holistic fit (closeout roles)
4.6-4.7 / 5.0
  • TypeScript
  • Hexagonal architecture (ports & adapters)
  • Domain-Driven Design
  • PostgreSQL + pgvector
  • Claude (Anthropic) via a co-piloted generation path
  • Python (agents, on-demand)
  • Problem

    Career tools optimize for volume and keyword-fit, not truth.

  • Approach

    A locked truth layer, honesty walls, and scored drifts as the moat.

  • Architecture

    API-first, DDD, modular monolith, hexagonal — TypeScript-first, Python on-demand.

  • Results

    100% ATS pass rate, 4.6-4.7/5.0 holistic fit on acceptance roles.

Measured, not claimed

Pulled from Selfwright's own eval suite, fitness functions, and acceptance-test docs — a snapshot, curated Jul 3, 2026. Refreshed by hand when it changes, not on every commit.

01

Eval-suite pass rate — fitness functions

Tier-1 checks (CI-safe, no private data)
17 passed · 0 failed
Tier-2 checks (need local truth-layer data)
2 skipped

Selfwright `pnpm fitness` @ a2fdc25

02

Eval-suite pass rate — deterministic-core unit tests

Tests passed
329 / 329 across 26 files

Selfwright `pnpm --filter @selfwright/core test` @ a2fdc25

03

ATS pass-through

ATS pass rate (acceptance roles, ≥0.80 gate)
100%

Selfwright docs/phase1-acceptance-test-2026-06-30.md

04

Fit-score demonstrations

Holistic fit (LLM-tier DoD close-out roles)
4.6-4.7 / 5.0

Selfwright docs/phase2-t2.2-dod-closeout-2026-07-03.md

05

Runtime/cost — deterministic vs. LLM tier

Deterministic tier (ATS, scoring, tailoring, fitness)
$0 — no LLM call
LLM tier (cover/research, co-piloted)
$0 metered — subscription-based, no per-call API billing (ADR 0006)

Selfwright docs/metrics.md

On real acceptance roles, Selfwright holds a 100% ATS pass rate and 4.6–4.7/5.0 holistic fit on co-piloted cover letters and research. Those numbers come from a fitness suite that grades every output against the same criteria before it counts as done — not cherry-picked examples. The framework is being prepared for open source.

What makes the numbers trustworthy is the architecture. Selfwright is a personal operating system for career, expertise, and knowledge, built around one constraint: every output traces back to a locked evidence registry.

The platform

A locked truth layer, honesty walls, scored “drifts,” and verifiable generation are the moat — and the discipline generalizes well beyond the CV. The platform is built around four compounding goals, in build order: (1) a career engine — apply to roles with truthful, ATS-tuned, archetype-tailored CVs and covers, and auto-discover suitable roles; (2) a coach — sharper interview and networking prep, deliberate skill-gap closing; (3) content — propose and support thought-leadership writing; (4) expertise — become a functional and technical expert across the software, data, and AI engineering spaces it touches.

Architecture

Selfwright is built API-first, Domain-Driven Design, Modular Monolith, Hexagonal (ports & adapters), in a TypeScript-first stack, with Python added on-demand for AI agents. The domain core is pure TypeScript with zero framework, provider, or storage imports — everything external (LLM calls, storage, memory, rendering, notifications) is reached only through a port, implemented by a swappable adapter. The git-based truth layer (identity, evidence registry, skills, comp floors, honesty boundaries) is the state of record; a PostgreSQL projection (with pgvector) provides a rebuildable index for semantic retrieval and reporting — never the source of truth itself.

Quality is enforced by TDD on the deterministic core (scoring, ATS, tailoring, drift application), an eval harness on LLM-touching paths, CI grading gates, and a fitness-function suite — including a data-leak gate as the top safety control, since the framework repo must never contain the personal, PII-bearing truth layer. The framework/personal-data boundary is clean by design: the framework is open-core and is being prepared for open source; personal data lives only in the private Selfwright-data repository, which is never public.

Decisions & trade-offs

No LLM gateway, no API keys — co-piloted generation instead. The original design routed model calls through a LiteLLM gateway (tiered Claude Haiku → Sonnet → Opus). That assumed either an API-key-billed provider or a self-hosted proxy in front of one. The owner ruled both out on cost and complexity grounds versus an already-paid Claude subscription. The redesign: Selfwright deterministically assembles a truth-grounded prompt and stops — no LLM call, no network access. The Claude Code session already running Selfwright produces the text, and a deterministic validator (validateCoverArtifact / validateResearchArtifact) gates the result before it counts as done. The LlmPort interface stays in place as a dormant, optional seam — an escape hatch (ClaudeCliAdapter, shelling claude --print) exists for future headless automation, but nothing instantiates it by default. Trade-off accepted: cover and research became multi-step flows (prompt → co-pilot fills it in → --check) instead of one-shot commands.

Drift application as a governed operation, not a keyword union. “Drifts” are the one sanctioned, scored, ledgered exception to the truth floor — a way to advisory-tune emphasis per company without fabricating anything. A prior implementation’s inject_drifts only unioned keywords and crashed on real, career_plan-shaped overlays. The fix: an object-only schema, confidence-band gating, and structured provenance, so a drift is applied as a governed, auditable operation rather than a silent text merge.

A real regression caught by grounding validators against real documents, not synthetic sentences. validateResearchArtifact originally ran truth-tracing over an entire research document against the personal evidence registry. A real company-research document is mostly sentences about the target company (revenue, org structure, tech stack) that have no reason to overlap with the candidate’s evidence — so any genuine research artifact would fail the check. The shipped test only ever exercised a single synthetic sentence, so the bug didn’t surface until the validator ran against real, multi-paragraph prose during the Phase 2 close-out. Fixed by scoping truth-tracing to sentences that actually reference the candidate (first-person pronoun or name), while honesty-boundary scanning still covers the full text.

Deterministic tier first, LLM tier second. Phase 1’s definition of done was split into a deterministic tier (ATS ≥ 0.80 on all six acceptance roles, tailor succeeding for every role including drift-injecting overlays, zod-validated overlays, a non-degenerate fit score) and an LLM tier (co-piloted cover/research passing the truth-trace validator with holistic fit ≥ 4.0). Splitting the DoD this way meant the deterministic core could be proven solid before any generation path existed to test against it.

What this demonstrates

A real hexagonal/DDD system with an enforced port boundary. A fitness-function suite that catches architectural drift and truth violations automatically. TDD on the deterministic core and an eval harness on LLM paths — applied to a genuinely constrained problem: building useful AI-assisted tooling without an API-key budget, by re-architecting around the harness already available.

On real acceptance roles it holds a 100% ATS pass rate and 4.6–4.7/5.0 holistic fit on co-piloted cover letters and research.

Status

Selfwright is in incubation: Phase 0 (scaffold, safety nets) and Phase 1 (career-core parity) are complete, Phase 2 (co-pilot close-out, scanner, skills/harness layer) is underway — the scanner, skills, and slash-command surface have shipped; multi-harness adapters, the Postgres/pgvector projection, and memory via mem0 remain open. It replaces and extends a prior working system (career_plan), which stays live in parallel until feature parity is reached.