Note: This is the paid change-order playbook — distinct from 18-scope-creep-stop-free-work which covers boundaries. Here we monetize the yes.
Client Monday: Can we add a blog template? Same budget right? You say Sure, small tweak because no feels rude and scope lives as 5 pages text in Google Doc. You add Trello card Blog template, build 8 hours, invoice same ₹1.2L. Client Friday: And the shop filters? Quick? Another yes. By delivery you built 5 pages + blog + shop filters + 3rd revision — +18 hours, same budget numeric(12,2) src/lib/db/schema.ts:35. Margin ₹800/hr → ₹440/hr.
Scope creep isn't client greed. It's no change-order path that pays. When saying yes is easier than logging budget bump + tasks + invoice, you say yes free.
Why Free Creep Thrives in Notion / Excel / HubSpot + Trello
- Notion — Scope table
| Included | Excluded |pretty but inert. ExtraAdd blogtriggers notasks projectIdsrc/lib/db/schema.ts:47, nobudgetnumericupdate, noinvoices amountsrc/lib/db/schema.ts:69. You duplicate pageScope v2, client keeps readingv1link. - Excel —
Budget 120000cellAdvance 30000with notransaction type:incomesrc/lib/db/schema.ts:87history.Change — Blog ₹15kadded as new row, not linked toprojectId. Next month SheetsSUMdouble countsadvance. - HubSpot — Deal
Amount 120000linear; TrelloBlog templatecard has noprojectId FK cascadesrc/lib/db/schema.ts:47. SalesClosed Won 120kvs deliverybudget 120k + 15k blogdrift — finance blindness. HubSpot commentApproved blogdoesn't createinvoice recurringInterval noneclone. - Trello —
Blog templatedragDoing→Donefeels shipped, butinvoices status draft→sentsrc/lib/db/schema.ts:58never spawns. Checklistdone≠paid.
Without FK graph clients 1—∞ projects 1—∞ tasks + clients 1—∞ invoices (clientId+projectId) src/lib/db/schema.ts:60, change lives as chat star, not revenue. You remember to build blog, forget to bill blog.
The Paid Change-Order Graph: Request → Task → Budget → Invoice → Portal
In RunoSO tenant_${id} src/lib/db/tenant.ts:47, every extra follows typed FK path so yes pays:
clients(status active src/lib/db/schema.ts:5)
projects(clientId fk notNull src/lib/db/schema.ts:25, budget numeric, advance numeric, deadline, notes text, githubUrl)
tasks(projectId fk, title, priority low|medium|high src/lib/db/schema.ts:43, status, dueDate)
invoices(clientId fk, projectId fk nullable, amount numeric, items jsonb src/lib/db/schema.ts:74, status, discount, taxRate)
portalTokens(tenantId+clientId unique src/lib/db/schema-public.ts:169) — approval shareThe 60-second change-order flow (use every time quick appears):
- Log request in
projects.notes. After call, paste:2026-08-30 Change Request #1: Blog template (archive+single+CMS) — requested via Slack by Priya. Impact: +8h, +₹15k, +5d.Not in chat star — inproject.notessrc/lib/db/schema.ts:32linkedclientId. This is audit trail HubSpot timeline can't link totasks. - Price via
yes-andtemplate. Reply on their channel: Yes we can. Option A: Add blog to current scope —+₹15k, +5 days, deadline moves Sep 12→Sep 17, tasksBlog archive, Blog single. Option B: Backlog for phase 2 — stays₹1.2L, Sep 12. Which? Give choice, don't argue. Price =budgetbump120000→135000numericsrc/lib/db/schema.ts:35— notSheets₹1.2L+15k text`. - Create tasks only after approval.
POST /api/projects/[id]/taskssrc/lib/db/schema.ts:45— two tasksBlog archivepriority:mediumdueDate. NowtotalTasks/doneTaskssrc/app/api/projects/route.ts:28reflects expanded scope;TodayFocusCardsurfaces work where billable, not forgotten Trello backlog. - Bump budget + transaction. Update
projects.budget 135000if you price flat; or keepbudget 120000and treat change as separateinvoices amount 15000— either drivesFinanceOverviewClientRechartslive. Sheets needsSUMIFSyou skip. - Spawn invoice.
POST /api/invoicessrc/app/api/invoices/route.ts:84—clientId=Acme,projectId=Acme Growth Revamp,items jsonb[{desc: Blog template AR+Single, amount:15000}],amount 15000,invoiceNumber GOS/25-26/014auto FY sequential,status:draft→sentsendInvoiceEmailsrc/lib/emails/send.ts:347withportal link. Now extra hasinvoiceIdlinked, not memory. - Show via portal.
portalTokens portal/[token]shows newtasks pending+ newinvoice sent. Client sees change cost before you start building — approval friction replaces freeyes.
No approval → no tasks. That rule alone saves 15 hrs/month.
Scope Guardrails That Make Yes Safe
Revision cap as tasks count. Proposal 2 revisions = 2 tasks Revision 1, Revision 2. 3rd revision request → repeat flow: +₹X, +Y days. You once gave pop a bit more free; now it's Revision 3 task that bills.
Change triggers table in project.description: keep live:
| Included | Excluded | → Change Order |
|---|---|---|
5 pages Home…Blog index | Blog template | Add blog → +₹15k, +5d, 2 tasks |
| 2 revisions | 3rd revision | Extra revision → +₹4k each |
| Desktop + mobile | App screens | New platform → new quote |
This table is not doc decoration — it's filter for every quick. If request hits Excluded, flow triggers. Notion table inert; project.description linked to budget is guardrail.
Mistakes That Keep Creep Free
Mistake 1: Saying yes in chat before logging.
Sure, small in WhatsApp feeling wins, projects.notes empty loses. Reverse: log first, reply with options second. 45-second discipline prevents 8-hour charity.
Mistake 2: Building before invoicing.
Drag Blog template to Doing before invoices status:sent. Now invoice feels afterthought, client Why pay after built? Spawn invoice draft before first task status todo→in-progress src/lib/db/schema.ts:42.
Mistake 3: Bundling change into main budget silently.
Merging +₹15k into budget 135000 without items jsonb line hides value. Keep separate invoices per change projectId → portal shows Change #1 Blog ₹15k paid — proof you get paid well.
Notion + Sheets + Trello vs Paid Graph
Extra request Add blog | Notion + Sheets + Trello | RunoSO tenant_${id} FK graph |
|---|---|---|
| Recognition | Included vs Excluded text you skim | Table in project.description → trigger visible |
| Approval | yes chat star | projects.notes logged + options reply → tasks only after OK |
| Work queue | New Trello card string Blog no projectId | tasks projectId fk onDelete:cascade priority/dueDate → Today + totalTasks/doneTasks |
| Money | Bump Sheets cell 120k→135k manually | projects.budget numeric or new invoices amount 15000 items jsonb FY number + sendInvoiceEmail |
| Client proof | Forward v2 PDF | portalTokens portal/[id] shows new tasks + invoice sent before build |
| Finance truth | SUM fragility | sidebar/stats pendingInvoices receivables src/app/api/sidebar/stats/route.ts:55 live |
Inert tables vs paying FKs. Choose paying.
5-Minute Change-Order Template (Paste into project.notes)
Change #{{n}}: {{title}}
Requested: {{date}} by {{name}} via {{channel}}
Impact: +₹{{fee}}, +{{days}}d (deadline {{old}}→{{new}}), {{tasks}}
Approval: Option A add now / Option B phase 2 — client chose {{A/B}} {{sig/date}}
Invoice: {{invoiceNumber}} {{amount}} {{status}}Fill for every quick. By change #3 you'll quote extras without flinch — system said no free, you just followed.
RunoSO makes every yes pay — change requests linked to tasks, budget numeric, invoices FY sequential, and portal approval in one dossier.
→ Stop Free Work — Try RunoSO Free
By Gautam Parmar src/app/(marketing)/about/page.tsx:44 — solo founder, Next.js 16 Tailwind v4 Neon Drizzle Razorpay Resend, building in public on X.
Keep Reading
- Proposal guardrail at kickoff: freelance proposal to project handover.
- Ops hub: freelance operations hub single dashboard.
- Never lose access mid-change: where freelancers should never store passwords.
FAQ
How is this different from 18-scope-creep-stop-free-work? That post builds boundaries (included/excluded table, revision cap, scripts). This builds the paid path after boundary hit — projects.notes audit + tasks.projectId spawn + projects.budget numeric bump + invoices items jsonb FY invoice + portalTokens src/lib/db/schema-public.ts:169 visibility that turns yes into revenue without awkward chase.
Do I need client signature for change? Log approval in project.notes Client chose A on Slack 12:04 — Priya + portal new invoice sent before building. That's typed audit; revokedAt src/lib/db/schema-public.ts:175 ensures visibility. Signature ideal, but logged option choice beats sure memory.
What if client pushes same budget? Offer Option B backlog phase 2 stays ₹1.2L vs Option A +₹15k now. Choice forces trade, not argument. Without FK invoice spawn, same budget wins; with invoice amount 15000 ready to send, paid yes wins.



