WW-75 — Offer Review & Decision (council-specced design)¶
Plain-language version: You Got an Offer
Council-gated design, 2026-07-11. Full 3-stage council (Claude / Codex / Gemini / Grok, fable tier; local seat failed) + house councils (gaming: qwen3-next:80b, gpt-oss:20b; streaming: gpt-oss:120b). Unanimous peer ranking: Grok > Claude > Codex > Gemini. Chairman synthesis is the basis of this doc. Report:
llm-council/reports/2026-07-11_130158_design-question-for-workwingman-local-first-elec.md(condensed copy inllm-council/reports/COUNCIL-LOG.md).
1. What this feature is — and is not¶
When the user receives a job offer, WorkWingman helps them work through accept / negotiate / wait. Three levers, not an offer-ranking oracle. The app informs the decision; it never makes it.
Explicitly not built (council-unanimous): a personality test battery, earnings-call NLP/analysis, LLM-drafted per-user negotiation emails, automated "accept" recommendations, any composite offer score.
2. Evaluation axes (priority-ordered by irreversibility)¶
- Real comp — base + bonus + haircut equity, normalized post-tax and cost-of-living-adjusted
against the current situation. Reuses
CityComparisonService,IncomeTaxEstimator,CompensationInsights,JobImpact, and the equity valuation chain (Stooq → Alpha Vantage → Barchart). - Timing / opportunity cost — offer deadline vs pipeline state, runway pressure. Hardest to model honestly; easiest to fake-precision. See §5.
- Hard constraints — geo, family, visa, notice/non-compete. These are gates, not weighted axes: a dealbreaker is never averaged away by a good salary.
- Growth delta — role vs the user's stated direction (needs a thin goals model, greenfield).
- Stability — will the job exist in two years; equity marked to reality. See §6.
- Fit — skills via existing
FitAssessment; culture via interview-retro signal. See §7.
Noise (deliberately excluded): daily stock volatility charts, earnings-call analysis, personality typing, benefits micro-comparison, uncalibrated fit percentages.
3. Data gaps — minimal intake (≤8 questions lifetime)¶
Delivered via a new OfferGapAnalyzer on the ProfileGapAnalyzer pattern (pure static checks,
no I/O): surfaces only fields missing for this decision, never re-asks answered ones.
Onboarding (optional, deferrable):
- 3 ranked growth themes (skills / domain / scope) + free-text direction → IntakeProfile.GrowthGoals
- One-question risk stance (stable pay vs upside)
- Household constraint flag (sole earner, dependents)
- Must-have / dealbreaker list (feeds the hard-constraint gates)
Offer-time (required, just-in-time):
- Offer facts: base / bonus / sign-on / equity / benefits notes / location terms (hard requirement)
- Deadline + exploding-offer flag
- Runway, bucketed <2 / 2–6 / 6+ months (rides FinancialProfile-style local-only encryption)
- Work-values rank, once, if never answered (§7)
4. Output shape — Kerr findings (mandatory, binding)¶
Hope = the user makes a good career decision. Folly = rewarding "maximize the app's number."
Banned metrics and their failure modes:
| Banned | Kerr failure |
|---|---|
| Composite 0–100 offer score | False precision; implicit salary weighting; users optimize the score, not the decision |
| Point pipeline probability ("62%") | Guaranteed over-trust at n<10; no honest basis |
| Equity point-dollars ("RSUs = $340k") | Optimism bias; paper value presented as cash |
| "Negotiation success likelihood" | Pure theater, no data |
| Culture-fit % | Unmeasurable; gamed by fluffy retros |
| Company "health score" | Finance theater sliding toward investment advice |
| "Accept" as primary CTA | App decides an irreversible life choice |
What ships instead (precedent: FitLevel 4-enum, qualified-only ValueMetrics):
- Multi-axis card — each axis an ordinal band Strong / Mixed / Weak / Unknown, with Unknown
first-class: missing data must never silently read as neutral.
- Narrative tradeoff line per axis, citing stored numbers/sources.
- Scenario cards — Accept now / Counter at X band / Ask N-day extension / Wait on Pipeline B —
each with explicit assumptions and unknowns.
- Decision journal — the last screen records the user's own decision + reasoning. Feeds future
calibration; the app closes the loop as a journal, never a verdict.
- ValueMetrics extension counts offer/decision events only — never a "good decision" score.
Residual gameables in this design itself (flagged, keep visible): users can re-rank growth themes to justify a company they already want; retro gut-feel is self-report, not ground truth. Both are labeled self-report in the UI.
5. Pipeline expected value + response timing¶
Honesty ruling: per-user stage calibration is statistically dishonest below ~15 outcomes per
stage. Until then, use published stage-conversion base rates as coarse ranges (screen 10–20%,
onsite 25–40%, post-final 40–60%), displayed as qualitative bands Unlikely / Possible / Likely with
the caption "based on typical rates, not your history." Optional single-band nudge from retro
gut-feel ≥4, labeled self-report. No point percentages, no P10/P90 machinery implying rigor the
tiny-N data cannot support.
Timing advisor (stage-lag heuristic): compare the offer deadline against each pending pipeline's stage lag — a pipeline at recruiter screen is ≈3–5 weeks from an offer, so waiting is −EV against a 1-week exploding offer; a pipeline post-onsite makes an extension worth asking. Flag waiting as −EV when runway is Low + no late-stage pipelines + exploding deadline.
Extension asks: ship static, verified templates (study-content-verification precedent) — not per-user LLM generation. Never auto-send anything.
6. Company stability context¶
Shallow and decision-focused. One StabilityContext panel: three enum signals + source links + the
fixed framing string "company-stability context, not investment advice."
- In: layoff/WARN headlines, revenue trend direction over 4 quarters (up/flat/down enum), RSU volatility haircut band for high-vol tickers, private-company caveat ("paper value, illiquid").
- Out: earnings-call NLP, DCF, analyst targets, chart analytics.
Grounding fact (Grok, verified): FMP is registry-only (ApiKeyProviderRegistry IsWired=false,
no FmpSource adapter exists); Alpha Vantage IS DI-wired. No phase blocks on FMP — the stability
panel starts with Alpha Vantage + user-pasted links, and degrades gracefully keyless (posted-range +
BLS only).
7. Work-style fit (no personality test)¶
Use O*NET Work Importance work-values (Achievement / Independence / Recognition / Relationships / Support / Working Conditions) — validated, public-domain, one 6-item drag-rank, asked once via the gap analyzer. MBTI rejected unanimously. RIASEC rejected as fit-for-purpose (it measures vocational interests for career choice, not offer-vs-offer environment match — it is not pseudoscience).
Mapping: values rank = stated preference; retro HowItFelt average + WhatWasHard/Surprises
themes = observed culture signal; a mismatch surfaces as one narrative line on the Fit axis —
never a score, never a veto.
8. Architecture¶
Offer entity (LocalJsonStore, per-offer — current equity is a single profile grant and needs
per-offer instances):
Offer: Id, JobId, ApplicationId, ReceivedAt, Deadline, ExplodingFlag,
Status (Pending|Negotiating|Accepted|Declined|Expired),
Comp { Base, Bonus, SignOn, EquityGrantIds[] }, BenefitsNotes, LocationTerms,
NegotiationNotes, Decision (null|Accept|Negotiate|Wait), DecisionRationale,
ExtensionAsked, EvidenceRefs, CreatedAt/UpdatedAt
Comp fields ride FinancialProfile-style local-only encryption.
New services: OfferService (CRUD), OfferEvaluationService (orchestrator → banded axes +
scenarios), PipelineOutlookService (stage priors + timing heuristics), OfferGapAnalyzer,
StabilityContextService (wraps Alpha Vantage; FMP later).
Reused: CityComparisonService, IncomeTaxEstimator, CompensationInsights, JobImpact,
equity valuation chain, FitAssessment, InterviewRetro, FinancialProfile.
Extended: EquityGrant to per-offer; IntakeProfile gains GrowthGoals + WorkValues;
ValueMetrics gains offer events.
Known gap to schedule: IncomeTaxEstimator is Single-filing-only.
9. Phases¶
- MVP:
Offerentity + CRUD, deadline tracker, comp normalization card (JobImpact/COL/tax reuse), banded multi-axis view with Unknown, scenario stubs (no EV math), static extension templates, decision journal. - Pipeline outlook (stage-range priors, qualitative bands), timing advisor, multi-offer side-by-side.
- Work-values rank + retro rollup into the Fit axis.
StabilityContext(Alpha Vantage; FMP when an adapter exists), LLM narrative drafts verified against stored facts.
Hard rules: no composite score, no auto-accept, no auto-send, user confirms everything irreversible.
10. House-council dissent log¶
All house seats agreed on: skip the personality test, no MBTI, lightweight work-values, shallow finance (layoff risk in, stock charts out), small-sample honesty on pipeline estimates.
Overruled dissent: streaming gpt-oss:120b proposed a composite 0–100 "KERR score" alongside the axes —
rejected against the unanimous frontier ban and the existing FitLevel/ValueMetrics precedent.
Gaming seats used numeric per-axis scores (e.g. "8/10") — ruled to ordinal bands instead.