Try it
Use it the same way it works on the site.
Open the tool →Where it comes from
Drop it into an automation
Studio node — script.javascript
Map address and whatever else you know (sqft, condition tier, arv, contract price) — anything you leave out stays a labeled assumption into this step from what the automation already knows. It runs the same math as the tool page and hands the result to whatever comes next.
{
"kind": "script.javascript",
"name": "Offers Are Outputs",
"config": {
"code": "// Loads this component's engine and runs it with the inputs mapped\n// above. The engine is the same file the tool page itself loads, so\n// the page and this step can never disagree.\nconst { compute } = require('./engine.js');\nmodule.exports = function (inputs) {\n return compute(inputs);\n};\n",
"inputs": {
"__stressOn": "{{vars.__stressOn}}",
"__frame": "{{vars.__frame}}",
"size": "{{vars.size}}",
"rehab": "{{vars.rehab}}",
"value": "{{vars.value}}",
"repairs": "{{vars.repairs}}",
"timeline": "{{vars.timeline}}",
"costs": "{{vars.costs}}",
"floors": "{{vars.floors}}",
"financing": "{{vars.financing}}",
"wholesale": "{{vars.wholesale}}",
"legacy": "{{vars.legacy}}",
"subto": "{{vars.subto}}",
"sellerFinance": "{{vars.sellerFinance}}",
"hybrid": "{{vars.hybrid}}",
"wrap": "{{vars.wrap}}",
"brrrr": "{{vars.brrrr}}"
},
"outputs": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$defs": {
"missingItem": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "dot-path of the unset input, e.g. 'value.arv'"
},
"label": {
"type": "string",
"description": "the field's human label, from META"
}
},
"required": [
"path",
"label"
]
},
"usedInput": {
"type": "object",
"properties": {
"path": {
"type": "string"
},
"label": {
"type": "string"
},
"unit": {
"type": "string"
},
"value": {},
"source": {
"type": "string",
"description": "human-readable source label, e.g. 'comps', 'assumed (default)'"
},
"note": {
"type": "string"
}
},
"required": [
"path",
"label",
"value",
"source"
]
},
"provenanceEntry": {
"type": "object",
"description": "the 'show your work' record behind one number — what the provenance panel renders when a user clicks a figure.",
"properties": {
"label": {
"type": "string"
},
"plain": {
"type": "string",
"description": "one-paragraph plain-language explanation"
},
"formula": {
"type": "string",
"description": "the worked arithmetic, as shown text"
},
"inputs": {
"type": "array",
"items": {
"$ref": "#/$defs/usedInput"
}
}
},
"required": [
"label",
"plain",
"formula",
"inputs"
]
},
"candidate": {
"type": "object",
"properties": {
"name": {
"type": "string",
"enum": [
"floor profit",
"floor profit as % of ARV",
"floor return on cash"
]
},
"mao": {
"type": "number",
"description": "maximum allowable offer this floor alone would produce"
}
},
"required": [
"name",
"mao"
]
},
"floorSolveResult": {
"type": "object",
"description": "output of the shared floor-solve used by the cash and fix-and-flip strategies: three floors (profit $, profit % of ARV, return on cash) are each solved for an offer; the lowest — the binding one — wins.",
"properties": {
"ARV": {
"type": "number"
},
"Repairs": {
"type": "number"
},
"sellingCostsPct": {
"type": "number"
},
"holdingCostsPerMonth": {
"type": "number"
},
"holdMonths": {
"type": "number"
},
"cushion": {
"type": "number"
},
"contingency": {
"type": "number"
},
"sellingCosts": {
"type": "number"
},
"holdingCosts": {
"type": "number"
},
"K": {
"type": "number",
"description": "ARV minus repairs, cushion, contingency, selling costs, and holding costs"
},
"C": {
"type": "number",
"description": "total non-financed cost stack (repairs + cushion + contingency + selling + holding)"
},
"a": {
"type": "number",
"description": "cash-invested multiplier (1 when unfinanced)"
},
"b": {
"type": "number",
"description": "offer-cost multiplier from financing (1 when unfinanced)"
},
"offer": {
"type": "number",
"description": "the solved maximum allowable offer — the headline number"
},
"profit": {
"type": "number"
},
"cashInvested": {
"type": "number"
},
"returnPct": {
"type": [
"number",
"null"
]
},
"binding": {
"type": "string",
"enum": [
"floor profit",
"floor profit as % of ARV",
"floor return on cash"
]
},
"candidates": {
"type": "array",
"items": {
"$ref": "#/$defs/candidate"
}
},
"financeNote": {
"oneOf": [
{
"type": "null"
},
{
"type": "object",
"properties": {
"interestFrac": {
"type": "number"
},
"pointsFrac": {
"type": "number"
},
"ltcPct": {
"type": "number"
},
"ratePct": {
"type": "number"
},
"points": {
"type": "number"
}
}
}
]
},
"profitFloor": {
"type": "number"
},
"returnFloorPct": {
"type": "number"
},
"profitFloorPctArv": {
"type": "number"
}
},
"required": [
"offer",
"profit",
"cashInvested",
"binding",
"candidates"
]
},
"wholesaleResult": {
"type": "object",
"properties": {
"ceilingLine": {
"type": "number",
"description": "the most a cash buyer will pay: ceilingPct% of ARV minus repairs"
},
"feeSpread": {
"type": "number",
"description": "ceilingLine minus contractPrice — the wholesale fee, an OUTPUT; can be negative ('no room')"
},
"contractPrice": {
"type": "number"
},
"hasRoom": {
"type": "boolean"
},
"ceilingPct": {
"type": "number"
},
"ARV": {
"type": "number"
},
"Repairs": {
"type": "number"
}
},
"required": [
"ceilingLine",
"feeSpread",
"contractPrice",
"hasRoom"
]
},
"wrapGate": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"value": {
"type": "number"
},
"floor": {
"type": "number"
},
"pass": {
"type": "boolean"
}
},
"required": [
"name",
"value",
"floor",
"pass"
]
},
"wrapCase": {
"type": "object",
"properties": {
"resalePrice": {
"type": "number"
},
"newNotePrincipal": {
"type": "number"
},
"buyerPayment": {
"type": "number"
},
"existingPay": {
"type": "number"
},
"spread": {
"type": "number",
"description": "buyer's new-note payment minus your existing payment"
},
"noteEquity": {
"type": "number"
},
"downPaymentProfit": {
"type": "number"
},
"gates": {
"type": "array",
"items": {
"$ref": "#/$defs/wrapGate"
},
"minItems": 3,
"maxItems": 3
}
},
"required": [
"spread",
"noteEquity",
"downPaymentProfit",
"gates"
]
},
"sellerViewLine": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"label": {
"type": "string"
},
"value": {
"type": [
"number",
"null"
],
"description": "null when the line is not ready (an underlying input is unknown)"
},
"plain": {
"type": "string"
},
"ready": {
"type": "boolean"
}
},
"required": [
"key",
"label",
"value",
"plain",
"ready"
]
}
},
"type": "object",
"description": "compute(inputs) return value. Every number rendered anywhere in the tool's UI comes from this object — nothing is computed a second time in a view layer.",
"properties": {
"legacy": {
"type": "object",
"description": "the four inert 'museum' formulas (70% rule, lender ceiling, time-decayed 70%, seller-script), for comparison only — never a competing answer.",
"properties": {
"missing": {
"type": "array",
"items": {
"$ref": "#/$defs/missingItem"
}
},
"seventyRule": {
"type": "object",
"properties": {
"value": {
"type": "number"
}
}
},
"lenderCeiling": {
"type": "object",
"properties": {
"value": {
"type": "number"
}
}
},
"timeDecayed": {
"type": "object",
"properties": {
"value": {
"type": "number"
},
"rate": {
"type": "number"
}
}
},
"sellerScript": {
"type": "object",
"properties": {
"value": {
"type": "number"
}
}
}
}
},
"strategies": {
"type": "object",
"properties": {
"cash": {
"type": "object",
"properties": {
"question": {
"type": "string"
},
"missing": {
"type": "array",
"items": {
"$ref": "#/$defs/missingItem"
}
},
"base": {
"$ref": "#/$defs/floorSolveResult"
},
"stress": {
"$ref": "#/$defs/floorSolveResult"
},
"stressMissing": {
"type": "array",
"items": {
"$ref": "#/$defs/missingItem"
}
},
"range": {
"type": "array",
"items": {
"type": "number"
},
"minItems": 2,
"maxItems": 2,
"description": "[stressed offer, calm offer]"
}
},
"required": [
"question"
]
},
"wholesale": {
"type": "object",
"properties": {
"question": {
"type": "string"
},
"missing": {
"type": "array",
"items": {
"$ref": "#/$defs/missingItem"
}
},
"base": {
"$ref": "#/$defs/wholesaleResult"
},
"stress": {
"$ref": "#/$defs/wholesaleResult"
},
"range": {
"type": "array",
"items": {
"type": "number"
},
"minItems": 2,
"maxItems": 2,
"description": "[stressed feeSpread, calm feeSpread]"
}
},
"required": [
"question"
]
},
"fixflip": {
"type": "object",
"properties": {
"question": {
"type": "string"
},
"missing": {
"type": "array",
"items": {
"$ref": "#/$defs/missingItem"
}
},
"base": {
"$ref": "#/$defs/floorSolveResult"
},
"stress": {
"$ref": "#/$defs/floorSolveResult"
},
"stressMissing": {
"type": "array",
"items": {
"$ref": "#/$defs/missingItem"
}
},
"range": {
"type": "array",
"items": {
"type": "number"
},
"minItems": 2,
"maxItems": 2
}
},
"required": [
"question"
]
},
"brrrr": {
"type": "object",
"properties": {
"question": {
"type": "string"
},
"missing": {
"type": "array",
"items": {
"$ref": "#/$defs/missingItem"
}
},
"refi": {
"type": "object",
"properties": {
"refiA": {
"type": "number",
"description": "refinance basis A: refi LTV x ARV"
},
"refiB": {
"type": "number",
"description": "refinance basis B: refi LTV x (purchase + repairs)"
},
"refiAmount": {
"type": "number",
"description": "min(refiA, refiB) — the governing basis"
},
"governingBasis": {
"type": "string",
"enum": [
"appraised ARV",
"purchase + documented rehab"
]
}
}
},
"scenarios": {
"type": "array",
"description": "required minimum rent at the entered refi rate, +0.5pt, and +1.0pt",
"items": {
"type": "object",
"properties": {
"rate": {
"type": "number"
},
"monthlyPI": {
"type": "number"
},
"annualDebtService": {
"type": "number"
},
"targetNOI": {
"type": "number"
},
"requiredRent": {
"type": "number"
}
}
}
},
"cashLeftInDeal": {
"type": "number"
},
"allIn": {
"type": "number"
},
"acqFinancingCosts": {
"type": "number"
},
"maxPurchase": {
"type": "object",
"description": "the hold strategy's ceiling — same shape as the wholesale ceiling, using refi LTV",
"properties": {
"value": {
"type": "number"
},
"acqFinancingCosts": {
"type": "number"
},
"pointsCost": {
"type": "number"
},
"interest": {
"type": "number"
}
}
},
"atExpectedRent": {
"type": "object",
"properties": {
"rent": {
"type": "number"
},
"noi": {
"type": "number"
},
"capRate": {
"type": "number"
},
"dscr": {
"type": [
"number",
"null"
]
}
}
}
},
"required": [
"question"
]
},
"subto": {
"type": "object",
"properties": {
"question": {
"type": "string"
},
"missing": {
"type": "array",
"items": {
"$ref": "#/$defs/missingItem"
}
},
"result": {
"type": "object",
"properties": {
"walkAway": {
"type": "number"
},
"closing": {
"type": "number"
},
"buyerMonthlyCost": {
"type": "number"
}
}
}
},
"required": [
"question"
]
},
"sellerFinance": {
"type": "object",
"properties": {
"question": {
"type": "string"
},
"missing": {
"type": "array",
"items": {
"$ref": "#/$defs/missingItem"
}
},
"result": {
"type": "object",
"properties": {
"monthlyPayment": {
"type": "number"
},
"totalPaid": {
"type": "number"
},
"totalInterest": {
"type": "number"
},
"impliedPrice": {
"type": "number"
}
}
}
},
"required": [
"question"
]
},
"hybrid": {
"type": "object",
"properties": {
"question": {
"type": "string"
},
"missing": {
"type": "array",
"items": {
"$ref": "#/$defs/missingItem"
}
},
"error": {
"type": "string",
"description": "set instead of result when cash-at-closing plus the existing balance exceed the price (no room for a note)"
},
"result": {
"type": "object",
"properties": {
"notePrincipal": {
"type": "number"
},
"notePayment": {
"type": "number"
},
"blendedMonthly": {
"type": "number"
}
}
}
},
"required": [
"question"
]
},
"wrap": {
"type": "object",
"properties": {
"question": {
"type": "string"
},
"missing": {
"type": "array",
"items": {
"$ref": "#/$defs/missingItem"
}
},
"base": {
"$ref": "#/$defs/wrapCase"
},
"stress": {
"$ref": "#/$defs/wrapCase"
},
"range": {
"type": "array",
"items": {
"type": "number"
},
"minItems": 2,
"maxItems": 2,
"description": "[stressed spread, calm spread], $/month"
}
},
"required": [
"question"
]
}
},
"required": [
"cash",
"wholesale",
"fixflip",
"brrrr",
"subto",
"sellerFinance",
"hybrid",
"wrap"
]
},
"provenance": {
"type": "object",
"description": "keyed by strategy.slot (e.g. 'cash.base', 'wholesale.stress', 'brrrr.maxPurchase', 'legacy.seventyRule') — one entry per number a user can click 'show your work' on.",
"additionalProperties": {
"$ref": "#/$defs/provenanceEntry"
}
},
"sellerView": {
"type": "object",
"description": "the cost-defense stack — a second rendering of numbers already computed above, never a second set of numbers.",
"properties": {
"frame": {
"type": "string",
"enum": [
"flip",
"rental"
]
},
"ready": {
"type": "boolean",
"description": "false if any line's underlying input is still unknown — the honesty gate"
},
"lines": {
"type": "array",
"items": {
"$ref": "#/$defs/sellerViewLine"
}
},
"monthsToSell": {
"type": "object",
"properties": {
"value": {
"type": [
"number",
"null"
]
},
"ready": {
"type": "boolean"
}
}
},
"number": {
"type": "object",
"description": "the final withheld-until-ready number: the cash offer in the flip frame, the hold strategy's max purchase in the rental frame",
"properties": {
"value": {
"type": [
"number",
"null"
]
},
"ready": {
"type": "boolean"
}
}
},
"closingSentence": {
"type": "string"
}
},
"required": [
"frame",
"ready",
"lines",
"number",
"closingSentence"
]
},
"meta": {
"type": "object",
"properties": {
"assumptions": {
"type": "integer",
"description": "count of used inputs whose source is an assumption (default/assumption/portal)"
},
"facts": {
"type": "integer",
"description": "count of used inputs whose source is a fact (comps/bid/termsheet/pulled)"
},
"usedList": {
"type": "array",
"description": "only the fields this run's provenance entries actually referenced — never an orphan default",
"items": {
"type": "object",
"properties": {
"path": {
"type": "string"
},
"source": {
"type": "string",
"description": "raw source tag, e.g. 'default', 'comps'"
},
"value": {},
"note": {
"type": "string"
}
}
}
}
},
"required": [
"assumptions",
"facts",
"usedList"
]
}
},
"required": [
"legacy",
"strategies",
"provenance",
"sellerView",
"meta"
]
}
}
}
Let the agent use it
To use this today: create a new process, choose skill, paste this.
## What this does Turns an address plus what you know into an offer range, with every input's source and every number's work shown. ## Prerequisites - You can reach /tools/offers-are-outputs.html. ## Steps 1. Open /tools/offers-are-outputs.html. 2. Enter address and whatever else you know (sqft, condition tier, arv, contract price) — anything you leave out stays a labeled assumption. 3. Read the result — it shows where every number came from. 4. Hand the result to whatever comes next. This step doesn't save or send anything by itself. ## ⛔ Warnings - never presents a number whose input is unknown — every strategy panel and the seller-view stack withhold the figure and name what's missing instead of guessing - never claims a valuation — ARV is always labeled by its route (comps, portal estimate, or the area's typical $/sq ft) and a placeholder area rate is marked [OWNER-DEFAULT], never presented as researched - user is the approver — this computes a range against policy the user set (their own floors, their own cushion and contingency); it does not recommend, guarantee, or pick a strategy for them - every default the engine fills in is labeled with its source and, for owner placeholders, tagged [OWNER-DEFAULT] in the assumptions ledger — nothing is silently assumed - the seller view's final number is withheld until every line feeding it is ready (the honesty gate) — a partial stack never rounds up to a shown total - the wholesale fee is computed as an output (ceiling minus contract price), never entered directly, and a negative spread renders as 'no room,' never as a negative dollar figure ## User attention You approve before anything this produces reaches a seller or buyer. ## Teardown Nothing to undo. This step doesn't save or send anything by itself.
Guardrails
- never presents a number whose input is unknown — every strategy panel and the seller-view stack withhold the figure and name what's missing instead of guessing
- never claims a valuation — ARV is always labeled by its route (comps, portal estimate, or the area's typical $/sq ft) and a placeholder area rate is marked [OWNER-DEFAULT], never presented as researched
- user is the approver — this computes a range against policy the user set (their own floors, their own cushion and contingency); it does not recommend, guarantee, or pick a strategy for them
- every default the engine fills in is labeled with its source and, for owner placeholders, tagged [OWNER-DEFAULT] in the assumptions ledger — nothing is silently assumed
- the seller view's final number is withheld until every line feeding it is ready (the honesty gate) — a partial stack never rounds up to a shown total
- the wholesale fee is computed as an output (ceiling minus contract price), never entered directly, and a negative spread renders as 'no room,' never as a negative dollar figure