AI EngineeringZero to ProductionHome·About·What’s new·Contact
Career & Interview Prep · Project CR

Land the role & grow to tech-lead

The final capstone: a structured job-search plan, the first-90-days playbook, and the map from engineer → senior → tech-lead — turning everything you built into a career. Runnable planning tools.

⏱️ ~2 hours🏗️ Capstone project🎯 Beginner→Tech-lead
What you'll buildYour personal launch plan: a concrete job-search campaign, then the first-90-days playbook and the map from engineer → senior → tech-lead. This turns everything you've built in this course into a career, with runnable planning tools.

Learning objectives

  • Run a structured job search, not a scattershot one.
  • Execute a strong first 90 days.
  • Understand the engineer→senior→lead progression.
  • Own your growth deliberately.
▶ Runnable companionThe tools here are saved under code/proj-cr-launch/ — run them against your own resume, stories, and offers.

You've probably lived the bad version of this. You fire off forty applications in a weekend, feel productive, then hear nothing for three weeks — and you have no idea whether the problem is your resume, your targeting, or just the odds. That silence is the trap: with no measurement, every rejection feels random and you can't tell what to change. So you either apply harder (more volume, same broken funnel) or give up. Neither is a decision — both are guesses.

The fix is to stop treating the search as a lottery and start treating it as a sales pipeline you can measure. Think of how a shop tracks customers: how many walked in, how many tried something on, how many bought. Each drop-off point tells the manager something specific — lots of foot traffic but no sales is a pricing problem, not a marketing one. Your job search has the same stages: applied → phone screen → onsite → offer, and each transition has a conversion rate you can watch.

Why this matters more than raw effort: the rate at each stage diagnoses a different problem. A low applied→screen rate means your resume or targeting is off (fix CR1, apply to better-fit roles). Strong screens but no onsites means your phone presence or take-homes need work. Onsites that never convert to offers means interview prep (CR2–CR5). The single number "response rate" is your first vital sign — it separates "not enough at-bats" from "the at-bats aren't landing." The common mistake is to conflate them and grind on volume when the funnel itself is leaking. Measure first, then push the volume × quality dial that's actually stuck.

each stage is narrower — the conversion rate between two stages tells you what to fix applied phone screen onsite offer resume / targeting? phone / take-home? interview prep? volume The search is a funnel, not a lottery. Applications narrow at every stage; the drop-off between two stages — not the raw count — names the specific thing to fix.
🗺️ How to read this diagram

Read top to bottom — that's the order an application travels, from "applied" down to a signed "offer". Each bar is deliberately narrower than the one above it.

  • The widening-to-narrowing bars are the four stages: applied (widest, blue) → phone screen → onsite → offer (green, the goal). Their shrinking width is the funnel — most applications fall out along the way.
  • The dashed downward arrows are the transitions between stages, and the note beside each one names the conversion rate you'd inspect there: a weak applied→screen points at resume/targeting, a weak onsite→offer points at interview prep.
  • The "volume" label on the top bar is the payoff: to keep the bottom bars full you need enough at the top — so a healthy search watches both the width (volume) and the drop-offs (quality).

In short: don't stare at rejections — watch which transition leaks, and fix that one thing.

Example code for learning — review, test, and adapt it before running against real or production systems. Commands can create, change, or delete resources. See the Terms & Disclaimer.
Python · a job-search tracker (runs)
job_tracker.pyfrom collections import Counter

applications = [
    {"company": "A", "stage": "offer"},
    {"company": "B", "stage": "onsite"},
    {"company": "C", "stage": "rejected"},
    {"company": "D", "stage": "phone screen"},
    {"company": "E", "stage": "applied"},
    {"company": "F", "stage": "onsite"},
]
funnel = Counter(a["stage"] for a in applications)
total = len(applications)
print("pipeline:", dict(funnel))
advanced = sum(1 for a in applications if a["stage"] not in ("applied", "rejected"))
print(f"response rate: {round(100*advanced/total)}% ({advanced}/{total} advancing)")
# healthy: keep enough in early stages to backfill as some drop
pipeline: {'offer': 1, 'onsite': 2, 'rejected': 1, 'phone screen': 1, 'applied': 1}
response rate: 83% (5/6 advancing)
▶ How this works

A job search works best run like a pipeline: many applications, each moving through stages (applied → phone screen → onsite → offer). This little tracker counts how many of your applications are at each stage and works out your response rate, so you can see the search's health at a glance.

  1. from collections import Counter brings in a handy tool that tallies how often each value appears in a list.
  2. applications is a list of small dictionaries, one per company, each recording its current stage. This is your search represented as data.
  3. funnel = Counter(a["stage"] for a in applications) counts how many applications sit in each stage. total = len(applications) is the overall count.
  4. advanced = sum(1 for a in applications if a["stage"] not in ("applied", "rejected")) counts the ones that got past the first step and weren't rejected — i.e. still alive. The last print turns that into a percentage response rate.

What the output means: pipeline: {...} shows the count at each stage, and response rate: 83% (5/6 advancing) means 5 of 6 applications moved forward. A low rate is a signal to improve your resume or targeting (CR1); a high rate means keep the volume up.

Try this: Replace the sample applications with your own list and update each stage as things progress. Re-run whenever something changes to watch your real funnel.

2 · The first 90 days intermediate

Here's the failure that quietly derails good engineers. They land the role, feel the pressure to prove they deserve it, and in week one propose rewriting the flaky module everyone complains about. It's technically correct — and it torches their credibility. They don't yet know why the module is the way it is, they haven't earned the right to make big calls, and the "hero rewrite" reads as arrogance to a team that's been living with the tradeoffs for years. The offer got you in the door; the first 90 days decide whether people trust you with anything that matters.

The mental model to carry in is trust as a bank balance you deposit into before you withdraw. Every small, reliable delivery is a deposit; every big ask or risky change is a withdrawal. You start at roughly zero, so early on you make many tiny deposits — a clean bug fix, a test that catches a real regression, a doc that unblocks someone — before you spend that balance on a large, ambiguous project. The staged plan below (setup, then small safe changes, then a real feature) is exactly that curve: it front-loads deposits so that by week 12 your account can afford real scope.

Why phase it deliberately instead of just "working hard"? Because effort spent in the wrong order is invisible or even negative. Shipping a big feature in week two that nobody asked for doesn't build trust — it signals you skipped the listening. The common mistake is confusing activity with impact: the fastest way to be valued is to prove you can move a small thing through the whole pipeline cleanly (the DF→TQ→CD loop) before you touch anything load-bearing. Land small and reliable first; the ambitious work becomes possible precisely because you did.

trust is a balance: many small deposits early, before the one big withdrawal Weeks 1–2 setup · read · meet Weeks 3–6 small safe changes Weeks 7–12 own a feature end-to-end time → tiny deposits now you can spend it Front-load the deposits. The three phases build trust in order — setup, then small safe wins, then a real feature — so the rising curve of credibility can finally afford ambitious scope by week 12.
🗺️ How to read this diagram

Scan the three boxes left to right — that's calendar time — and then follow the rising blue curve underneath, which is your accumulated trust over the same span.

  • The three top boxes are the phases: Weeks 1–2 setup and listening (blue), Weeks 3–6 small safe changes, Weeks 7–12 owning a feature (green). The blue arrows between them show they run in strict order — you don't skip ahead.
  • The curve climbing left to right is the trust "bank balance"; each dot is a phase's deposit, small at first and larger as you prove yourself.
  • The payoff is the top-right: only after the earlier deposits does the balance rise enough to "spend" on the big, ambiguous feature — a hero rewrite in week two would be a withdrawal against an empty account.

In short: earn trust in phases; the ambitious work becomes affordable only after the small wins bank it.

  1. Weeks 1-2: set up, read the code, get the app running (DF/CD skills), meet the team, ask questions.
  2. Weeks 3-6: ship small, safe changes (a bug fix, a test) to learn the pipeline and build trust.
  3. Weeks 7-12: take a real feature end-to-end; understand the domain and the users.
  4. Throughout: write things down, over-communicate, and find the person who explains the 'why'.
First impressions compoundShipping a small, well-tested, cleanly-deployed change in week 2 (exactly the DF→TQ→CD loop) signals competence fast. Don't try to rewrite everything — earn trust with reliable small wins first.

3 · Advanced — engineer → senior advanced

A frustration you may hit around year two or three: you're a stronger coder than half the seniors on your team — cleaner PRs, faster tickets — and yet the promotion keeps not coming. It feels unfair, and the usual (wrong) conclusion is "I need to code even better." But the seniors aren't ahead because they type faster. They're ahead because someone can hand them a vague problem and walk away, confident it'll come back solved, well-considered, and safe.

That's the whole shift in one word: autonomy. Picture the difference between a skilled line cook and a sous-chef. The cook executes tickets beautifully but needs the tickets. The sous-chef can be told "we're low on the fish, figure out the specials tonight" and will handle sourcing, pricing, plating, and the tradeoffs in between — no ticket required. Senior is the sous-chef: given an outcome and ambiguity, you decompose it, make the calls, and own the result.

Why the industry pays so much more for this: ambiguity is expensive to resolve, and every problem a senior absorbs is one a manager or staff engineer doesn't have to. Your value stops being "lines of correct code" and becomes "one fewer thing anyone else has to think about." The common trap is treating senior as a coding-skill milestone and grinding LeetCode or refactors to reach it — while never volunteering for the fuzzy, unowned problem that would actually demonstrate autonomy. The evidence a promotion committee wants isn't cleaner code; it's a system or feature you owned end-to-end, tradeoffs and all, without hand-holding.

the shift is autonomy: given an outcome + ambiguity, you own the whole path Engineer defined ticket executes it needs the ticket Senior · autonomy vague outcome decompose make calls own result no ticket required Senior is autonomy, not typing speed. The engineer needs a defined ticket to execute; the senior takes a vague outcome and owns the whole chain — decompose, make the tradeoff calls, own the result — which is the surface a promotion committee is buying.
🗺️ How to read this diagram

Compare the two panels side by side: the left is how an engineer creates value, the right is how a senior does — the width difference is the point.

  • The left panel (Engineer) is a short chain: a defined ticket handed in (amber), then executes it. It stops there — the work only starts once someone else has drawn the edges.
  • The right panel (Senior, green) starts from a vague outcome (amber) and fans into a longer owned chain — decompose → make calls → own result. Nobody hands over a ticket; you create the plan and absorb the ambiguity.
  • The payoff labels — "needs the ticket" versus "no ticket required" — name the exact difference a promotion committee pays for: one fewer ambiguous problem anyone else has to think about.

In short: you become senior by owning the fuzzy, unowned problem end-to-end — not by executing well-defined tickets faster.

4 · Professional — the impact ladder professional

The most demoralizing sentence in a performance review is "you did great work, but it wasn't at the next level." You put in the hours, closed the tickets, stayed late — and it still didn't count. That's because promotion committees don't measure effort; they can't see it. They measure scope of ownership: how large and how ambiguous a surface you demonstrably held. The ladder below is that scale made explicit, and reading it as "how much do I own?" rather than "how hard do I work?" is the reframe that unsticks careers.

Think of it like being trusted with a bigger area of a map. A junior is handed a well-lit, well-defined trail — the task's edges are drawn for them. A mid-level engineer owns a whole feature, dark corners included. A senior owns a system and the people learning to navigate it. A staff/lead owns a direction across systems and teams — the part of the map nobody has surveyed yet. Each rung isn't more of the same work; it's a categorically larger and vaguer territory you're accountable for.

Why frame it as a ladder rather than a checklist of skills? Because the levels are cumulative and ordered — you don't skip owning a feature to go straight to setting cross-team direction, any more than you'd hand the un-surveyed map to someone who's never walked a marked trail. The practical payoff is diagnostic: locate the largest surface you honestly own today, and the very next rung tells you what to reach for. The common mistake is inflating your self-placement (claiming "senior" for one lucky system) — which backfires, because the rung above will expect artifacts you can't produce. Name your tier honestly; the ladder's value is that it points, unambiguously, at the next thing to build.

each rung up = a larger, vaguer surface you own — the width is the scope Junior · a task Mid · a feature Senior · a system + mentors Staff / Lead · a cross-team direction widest scope defined edges Promotion tracks scope, not hours. The rungs widen as you climb — from a well-defined task to a whole cross-team direction — and the levels are cumulative, so you reach the next one by owning a larger, vaguer surface than the last.
🗺️ How to read this diagram

Read bottom to top, the way you climb a ladder. The bars get wider as you rise — that width is the whole point: it stands for how much (and how ambiguous) a surface you own.

  • The narrowest bar at the bottom is Junior, owning a single well-defined task (its edges are drawn for you). Each bar above widens: Mid owns a feature, Senior owns a system and mentors, Staff / Lead (widest, green) owns a direction across teams.
  • The upward arrows mean the rungs are ordered and cumulative — you don't leap from a task straight to cross-team direction.
  • The "widest scope" / "defined edges" labels mark the two ends of the scale; locating the largest surface you honestly own places you on a rung, and the bar just above names what to reach for.

In short: climb by owning a bigger, blurrier surface — not by working harder on the same one.

LevelScope of impact
Juniorcompletes well-defined tasks
Midowns features with some guidance
Seniorowns systems; makes tradeoffs; mentors
Staff/Leaddrives cross-team technical direction & multiplies others

5 · Tech-lead — multiply, don't just build tech-lead

Here's the counterintuitive failure that traps the best individual engineers. Newly-minted tech-leads keep doing what made them great — they grab the hardest tickets, write the trickiest code, become the bottleneck for every important decision. The team ships less, not more, because everything now routes through one person, and that person is drowning. The skill that earned the title is exactly the wrong instinct for the job.

The shift is from being a strong worker to being a force multiplier, and the arithmetic is the whole point. As a senior you add your own output — call it 1×. As a tech-lead, if you make five engineers 30% more effective by unblocking them, setting clear direction, and raising the quality bar, you've added 1.5× of output without writing a line yourself. Think of a great orchestra conductor: they play no instrument during the performance, yet the music is unmistakably shaped by them. Your leverage is now the team's collective throughput, not your keyboard.

Why this is genuinely hard, and where people go wrong: multiplying is often invisible and delayed, while coding is visible and immediate — so under pressure the ego reaches for the ticket instead of the mentoring conversation, because the ticket feels like progress. The best thing you can do some days is write no code at all: unblock a stuck engineer, kill an ambiguous requirement before it wastes a week, or translate a business goal into a technical plan the team can run. Your success metric flips accordingly — you're now measured by what the team ships, and a tech-lead whose team stalls the moment they take a vacation has multiplied nothing. Build the team's capacity, not just the product.

The tech-lead shift is from your output to the team's: you set technical direction, unblock people, uphold quality standards (the DF/TQ/CD/SD tech-lead tiers you learned), mentor, and translate between business and engineering. Your success is measured by what the team ships, not just you.

the leverage flips from your keyboard to the team's throughput Senior 1× your own output Tech-lead 5 eng × +30% = +1.5× · you write no code multiply Multiply, don't just build. A senior contributes one unit of their own output; a tech-lead who lifts five engineers by ~30% adds ~1.5× — without touching the keyboard — which is why the metric flips to what the team ships.
🗺️ How to read this diagram

Compare the two panels side by side: the left is how a senior creates value, the right is how a tech-lead does — the arrow between them is the shift the section is about.

  • The left panel (Senior) shows a single tall bar: 1×, your own hands-on output. That one bar is the whole contribution.
  • The right panel (Tech-lead, green) shows five smaller bars — the engineers you make ~30% more effective by unblocking, directing, and raising the bar. Together they add roughly +1.5× even though you wrote no code yourself.
  • The "multiply" arrow is the payoff: your leverage stops being your keyboard and becomes the team's collective throughput — which is exactly why success is now measured by what the team ships.

In short: five engineers lifted a little beats one engineer coding a lot — that's the tech-lead's arithmetic.

Python · a growth self-assessment (runs)
growth.pydef growth_stage(signals):
    """signals: dict of bool — what you're consistently doing."""
    score = sum(signals.values())
    if signals.get("multiplies_team") and signals.get("sets_direction"):
        return "tech-lead track"
    if signals.get("owns_systems") and signals.get("mentors"):
        return "senior"
    if signals.get("owns_features"):
        return "mid"
    return "growing toward mid"

me = {
    "owns_features": True, "owns_systems": True, "mentors": True,
    "sets_direction": False, "multiplies_team": False,
}
print("current stage:", growth_stage(me))
print("next: build 'sets_direction' + 'multiplies_team' -> tech-lead")
current stage: senior
next: build 'sets_direction' + 'multiplies_team' -> tech-lead
▶ How this works

This is a self-assessment: you tick off which senior/lead behaviours you're consistently doing, and it tells you roughly what career stage that puts you at — and what to build next to reach the following rung.

  1. signals is a dictionary of True/False facts about your habits — do you own features, own systems, mentor, set technical direction, multiply the team?
  2. The function checks them from the top down, strongest first: if you both multiplies_team and sets_direction, you're on the "tech-lead track"; else if you owns_systems and mentors, you're "senior"; and so on. The first matching rule wins, so it reports your highest solid level.
  3. me fills in the honest current picture — here owning features and systems and mentoring, but not yet setting direction or multiplying the team.
  4. The two print lines report the stage and spell out the exact two signals to develop next to move up.

What the output means: current stage: senior — the True signals matched the "senior" rule but not the tech-lead one. The next line names the gap: build sets_direction and multiplies_team to reach the tech-lead track.

Try this: Set the flags to your own honest yes/no. Whatever two are False just below your current stage are your concrete goals for the next 6–12 months.

This is the whole journey, closedYou started at "never used a terminal" and end with a plan to reach tech-lead. Every section's essential→tech-lead ladder was preparing you for this: the skills, the leadership habits, and now the map to apply them. That's a complete path.

🪜 Practice ladder beginner → industry

Six graded exercises, easy to real-world. Try each before opening its solution.

Exercise 1 · A job-search pipeline trackerBeginner

Context: Run the job search like a funnel you can measure, not a black box you guess at. The response rate tells you where to intervene — a weak resume, or interviews you're not converting.

Your task: Build job_tracker.py that counts applications by stage and computes a response rate.

Requirements:

  • Count applications at each funnel stage (applied → screen → onsite → offer)
  • Compute a response rate = anything past 'applied' over the total
  • Handle an empty pipeline without dividing by zero
  • Return the per-stage counts alongside the rate
  • Runs offline over a list of furthest-stage-reached values

💡 Hint: A Counter over the furthest stage each application reached gives the funnel; a low response rate says fix targeting, not interview prep.

Show solution

Treat the search as a measurable pipeline — the response rate tells you where to intervene:

from collections import Counter

STAGES = ["applied", "screen", "onsite", "offer"]

def funnel(applications):
    # applications: list of the furthest stage each reached
    c = Counter(applications)
    counts = {s: c.get(s, 0) for s in STAGES}
    total = sum(counts.values())
    responded = total - counts["applied"]        # anything past 'applied'
    return {"counts": counts, "total": total,
            "response_rate": round(responded/total, 2) if total else 0.0}

apps = ["applied","applied","screen","onsite","applied","offer"]
print(funnel(apps))
# response_rate ~0.5 -> half your applications got a reply

A low response rate means fix the resume/targeting; strong responses but no offers means fix interview prep. The funnel tells you which, so effort goes where it moves the needle.

Exercise 2 · A first-90-days plan with staged goalsIntermediate

Context: A new role needs a plan, not vibes. Staged goals turn 'make a good impression' into concrete milestones — buying trust with small safe wins before taking on risk.

Your task: Build plan_90_days() returning the goal for a given week band.

Requirements:

  • Weeks 1–2: setup (env, access, read the codebase, meet the team)
  • Weeks 3–6: ship small, safe changes to build trust
  • Weeks 7–12: own a feature end-to-end
  • Beyond ramp: higher-scope, more ambiguous work
  • Runs offline for any week number

💡 Hint: Map week ranges to goals; by week 12 you should own something end-to-end, which is the evidence a review looks for.

Show solution

Staged goals turn "make a good impression" into concrete, checkable milestones:

def plan_90_days(week):
    if 1 <= week <= 2:
        return "setup: env, access, read the codebase, meet the team"
    if 3 <= week <= 6:
        return "ship small safe changes: build trust with low-risk PRs"
    if 7 <= week <= 12:
        return "own a feature end-to-end: design, build, ship, measure"
    return "beyond ramp: take on ambiguous, higher-scope work"

for w in (1, 4, 9, 14):
    print(f"week {w:>2}: {plan_90_days(w)}")

Early wins are small and safe by design — you're buying trust and context before taking on risk. By week 12 you should own something end-to-end, which is the evidence a review looks for.

Exercise 3 · Map contributions to the impact ladderAdvanced

Context: Promotion is about scope of ownership, not effort. Effort is invisible; owned scope is not — a feature, then a system, then a direction.

Your task: Build impact_tier(signals) that classifies work as junior/mid/senior/staff-lead from what the person owns.

Requirements:

  • Classify from ownership signals, not hours worked
  • Owning features → mid
  • Owning systems and mentoring → senior
  • Setting direction and multiplying the team → staff/tech-lead
  • Runs offline over a signals dict

💡 Hint: Check the highest-scope signals first so the tier reflects the largest surface the person demonstrably owns.

Show solution

The ladder is defined by scope of ownership — naming your tier honestly shows you what to reach for next:

def impact_tier(signals):
    # signals: booleans about what you demonstrably own
    if signals.get("sets_direction") and signals.get("multiplies_team"):
        return "staff/tech-lead"
    if signals.get("owns_systems") and signals.get("mentors"):
        return "senior"
    if signals.get("owns_features"):
        return "mid"
    return "junior"

print(impact_tier({"owns_features": True}))                       # mid
print(impact_tier({"owns_systems": True, "mentors": True}))       # senior
print(impact_tier({"sets_direction": True, "multiplies_team": True}))  # staff

Effort is invisible; owned scope is not. Moving up means owning larger, more ambiguous surface area — a feature, then a system, then a direction — and having the artifacts to prove it.

Exercise 4 · A growth self-assessment that names the next two signalsExpert

Context: Growth stalls when you don't know what to build next. The useful output isn't your current tier — it's the next two concrete signals to develop, the shortest path up.

Your task: Build growth.py that reads current signals and returns the two nearest unmet signals to develop.

Requirements:

  • An ordered ladder of signals so gaps surface in a sensible sequence
  • Return the person's current strengths
  • Return the next two unmet signals to develop
  • Two concrete targets beat a vague 'grow more'
  • Runs offline over a signals dict

💡 Hint: Order the ladder (feature ownership and mentoring before system ownership and direction) and take the first two signals not yet met.

Show solution

The useful output isn't your current tier — it's the next two things to work on:

LADDER = ["owns_features", "mentors", "owns_systems",
          "sets_direction", "multiplies_team"]

def next_signals(signals, n=2):
    unmet = [s for s in LADDER if not signals.get(s)]
    return unmet[:n]

def assess(signals):
    have = [s for s in LADDER if signals.get(s)]
    return {"strengths": have, "develop_next": next_signals(signals)}

print(assess({"owns_features": True, "mentors": True}))
# develop_next: ['owns_systems', 'sets_direction']

Ordering the ladder means the gaps come out in a sensible sequence: master feature ownership and mentoring before reaching for system ownership and direction-setting. Two concrete targets beat a vague "grow more".

Exercise 5 · Score yourself against a role rubricProfessional

Context: Interviews score you on dimensions, and averages hide the gap that sinks you. Scoring yourself against the same rubric surfaces the one dimension to fix before applying widely.

Your task: Build a rubric scorer over portfolio, resume evidence, search execution, interview readiness, and first-90-days plan, flagging any dimension below bar.

Requirements:

  • Score all five dimensions
  • Flag every dimension below a bar (e.g. 3 of 5)
  • Report the average and a ready/not-ready verdict
  • Name the specific below-bar dimensions, not just the average
  • Runs offline over a scores dict

💡 Hint: Return the below-bar map, not just the mean — a strong portfolio can't rescue a search you're not running consistently.

Show solution

Self-scoring against the same rubric interviewers use surfaces your weakest dimension before they do:

DIMENSIONS = ["portfolio", "resume_evidence", "search_execution",
              "interview_readiness", "first_90_plan"]
BAR = 3   # out of 5

def score_readiness(scores):
    weak = {d: s for d, s in scores.items() if s < BAR}
    avg = sum(scores.values()) / len(scores)
    return {"avg": round(avg, 1), "below_bar": weak,
            "ready": len(weak) == 0}

s = {"portfolio": 4, "resume_evidence": 3, "search_execution": 2,
     "interview_readiness": 4, "first_90_plan": 3}
print(score_readiness(s))
# below_bar: {'search_execution': 2} -> fix this before applying widely

Averages hide the gap that sinks you; the below_bar map names the one dimension to fix first. A strong portfolio can't rescue a search you're not running consistently.

Exercise 6 · Evaluate a real offer beyond the headline numberIndustry scenario

Context: An offer is more than base salary. A weighted comparator stops the biggest base number from dominating a decision that growth and risk should shape.

Your task: Build an offer comparator scoring comp, growth, and risk so you decide on total value, not just the headline number.

Requirements:

  • Comp combines base, equity, and bonus (normalized)
  • Growth captures scope and mentorship
  • Risk penalizes short runway and unclear role
  • A weighted score combines all three; weights are tunable to your priorities
  • Compare two contrasting offers offline (e.g. startup vs big-co)

💡 Hint: Normalize comp to a comparable scale and subtract a risk penalty; let the score check your gut, not replace it — tune the weights to what you value.

Show solution

A weighted comparator stops the biggest base number from dominating a decision it shouldn't:

def offer_value(o, weights=None):
    w = weights or {"comp": 0.5, "growth": 0.3, "risk": 0.2}
    comp = (o["base"] + o["equity_annual"] + o["bonus"]) / 100_000  # normalize
    growth = o["scope"] * 0.5 + o["mentorship"] * 0.5               # 0-5 each
    risk_penalty = (5 - o["runway_years"]) + (5 - o["role_clarity"])
    score = w["comp"]*comp + w["growth"]*growth - w["risk"]*risk_penalty
    return round(score, 2)

startup = {"base":150_000,"equity_annual":60_000,"bonus":0,"scope":5,
           "mentorship":2,"runway_years":2,"role_clarity":3}
bigco   = {"base":200_000,"equity_annual":40_000,"bonus":30_000,"scope":3,
           "mentorship":4,"runway_years":5,"role_clarity":5}
print("startup:", offer_value(startup), " bigco:", offer_value(bigco))

Comp is half the story: growth (will you own real scope, get mentored?) and risk (runway, role clarity) can flip the decision. Tune the weights to your own priorities and let the score check your gut, not replace it.

✓ Checkpoint — you can move on when you can…

  • Run a structured, measured job search.
  • Execute a strong first 90 days.
  • Explain the engineer→senior→lead progression.
  • Assess your stage and plan the next rung deliberately.
📋 Grade your launch plan — is this a campaign or a scattershot?
DimensionMeets the barAbove the bar (staff)
Portfolio qualityYou have 1–2 shipped, runnable projects with a README that states the problem, the approach, and how it was verified.Projects are deployed/live with evidence (metrics, before/after, tests) that a stranger can evaluate in five minutes without you present.
Resume evidenceBullets are outcome-oriented (impact + number), not task lists; each claim maps to something you can demo or discuss.Every bullet is defensible under drill-down: you can explain the tradeoff, the alternative, and what you'd do differently.
Search executionThe search is run as a tracked pipeline (targets, applications, stages) with a measured response rate, not random applying.You keep enough volume in early stages to backfill drop-off, tailor materials per target, and iterate the funnel when the rate is low.
Interview readinessYou have STAR stories prepared (CR2) and can pass the coding/system-design bars (CR3/CR4) for your target level.Stories are calibrated to the level you're targeting, and you can turn any resume line into a 2-minute structured answer on demand.
First-90-days planYou have a concrete ramp: set up + read code (weeks 1–2), ship small safe changes (3–6), own a feature (7–12).The plan names how you'll earn trust with a well-tested, cleanly-deployed early win and how you'll find the person who explains the 'why'.
Growth self-awarenessYou can place yourself honestly on the impact ladder (junior→staff) and name the two signals to build next.You have a deliberate 6–12 month plan to develop the next rung's signals (owns systems, mentors, sets direction, multiplies the team).

Score each dimension 0 (missing), 1 (meets bar), or 2 (above bar). 0–4: keep building. 5–8: a solid, defensible submission. 9–12: staff-level — you could hand this to a reviewer and defend every call. Any dimension at 0 blocks shipping regardless of the total.

Knowledge check check yourself

✓ Knowledge check

Why does the project frame the job search as a measured pipeline (tracking stages and response rate) instead of applying widely?

Show answer
Applying randomly wastes effort; running it as a funnel with volume × quality lets you see the search's health — a low response rate signals fixing the resume or targeting, a high one signals keeping volume up — so you improve deliberately rather than guess.
✓ Knowledge check

According to the impact ladder, what actually distinguishes the tech-lead shift from strong senior work?

Show answer
The shift is from your output to the team's: you set technical direction, unblock and mentor others, and are measured by what the team ships — not just your own code. The self-assessment gates tech-lead on sets_direction + multiplies_team, not just owning systems.
© 2026 studybydoing.in · AI Engineering: Zero to Production · All rights reserved. · About · Privacy Policy · Terms · Contact
Educational content, provided as-is and without warranty. Code samples are examples — review, test, and adapt them before using in production. See the Terms of Use & Disclaimer. Use at your own risk.
© studybydoing.in