diff --git a/js/003-data/gameVariableData.js b/js/003-data/gameVariableData.js
index 2a74acd4bc8948d5d3332a17e1c85cb3c3a68478..3917af571e652db9c0b65aea566790dab2888879 100644
--- a/js/003-data/gameVariableData.js
+++ b/js/003-data/gameVariableData.js
@@ -586,6 +586,7 @@ App.Data.resetOnNGPlus = {
 			cum: 0,
 			births: 0,
 			kills: 0,
+			income: 0,
 
 			/** @type {FC.Zeroable<string>} */
 			fate: 0,
diff --git a/js/003-data/policiesData.js b/js/003-data/policiesData.js
index 3a33b033719eadf4f393bf1825a793d2a2342f90..52277641a54a6146d044ff15fe0d76c2e54c3e1d 100644
--- a/js/003-data/policiesData.js
+++ b/js/003-data/policiesData.js
@@ -1040,7 +1040,7 @@ App.Data.Policies.Selection = {
 		"policies.retirement.kills": [
 			{
 				title: "Champion Gladiatrix Retirement",
-				get text() { return `slaves will be rewarded with their freedom once they have killed ${V.policies.retirement.kills === 0 ? "a set number of" : num(V.policies.retirement.kills)} of their fellow slaves in the pit.`; },
+				get text() { return `slaves will be rewarded with their freedom once they have killed ${V.policies.retirement.kills === 0 ? "a set number" : num(V.policies.retirement.kills)} of their fellow slaves in the pit.`; },
 				get activatedText() {
 					const el = new DocumentFragment();
 					let div = document.createElement("div");
@@ -1067,6 +1067,36 @@ App.Data.Policies.Selection = {
 				get requirements() { return (V.policies.retirement.fate === "citizen"); },
 			}
 		],
+		"policies.retirement.income": [
+			{
+				title: "Purchase Retirement",
+				get text() { return `slaves can buy their freedom once they have earned ${V.policies.retirement.income === 0 ? "a set amount" : cashFormat(V.policies.retirement.income)} minus any expenses.`; },
+				get activatedText() {
+					const el = new DocumentFragment();
+					let div = document.createElement("div");
+					el.append(`slaves can buy with their freedom once they have earned ${cashFormat(V.policies.retirement.income)} minus any expenses.`);
+					div.append(`Set a new retirement requirement:`);
+					div.append(
+						App.UI.DOM.makeElement(
+							"div",
+							App.UI.DOM.makeTextBox(
+								V.policies.retirement.income,
+								v => {
+									V.policies.retirement.income = Math.clamp(v, 1, 1e12);
+									App.UI.reload();
+								},
+								true
+							),
+							"indent"
+						)
+					);
+					el.append(div);
+					return el;
+				},
+				enable: 2_000_000,
+				get requirements() { return (V.policies.retirement.fate === "citizen"); },
+			}
+		],
 	},
 	MenialRetirementPolicies: {
 		"policies.retirement.menial2Citizen": [
diff --git a/src/002-config/fc-version.js b/src/002-config/fc-version.js
index 4489b7ae8c42d490a2da6c9fc0d4d48e82c63c21..89a508868d51a8fa70514a571059ed5006f91c92 100644
--- a/src/002-config/fc-version.js
+++ b/src/002-config/fc-version.js
@@ -10,5 +10,5 @@ App.Version = {
 	 * The release numbers got messed up, this is corrected in `src/js/eventHandlers.js` and `/src/data/patches/patch.js`.
 	 * The two line above and this line should be safe to remove after release 2001.
 	 */
-	release: 1277,
+	release: 1278,
 };
diff --git a/src/data/patches/releases/1278_incomeRetirement.js b/src/data/patches/releases/1278_incomeRetirement.js
new file mode 100644
index 0000000000000000000000000000000000000000..04ed8ee316ad63df2173a9a0de237eb3be5453a0
--- /dev/null
+++ b/src/data/patches/releases/1278_incomeRetirement.js
@@ -0,0 +1,7 @@
+App.Patch.register({
+	releaseID: 1278,
+	descriptionOfChanges: "Adds income retirement policy.",
+	pre: (div) => {
+		V.policies.retirement.income = 0;
+	},
+});
diff --git a/src/endWeek/saDevotion.js b/src/endWeek/saDevotion.js
index acf94dd5a94326b2a88ea9a081f38a43ddc9804f..1675013605e8d72ce750801ea6bfca010a8605b8 100644
--- a/src/endWeek/saDevotion.js
+++ b/src/endWeek/saDevotion.js
@@ -626,6 +626,19 @@ App.SlaveAssignment.devotion = function saDevotion(slave) {
 							r.push(`since ${he} knows just a bit more murder in the pit will win ${his} freedom.`);
 						}
 					}
+					if (V.policies.retirement.income > 0) {
+						if ((slave.lifetimeCashIncome - slave.lifetimeCashExpenses) >= V.policies.retirement.income * 0.6) {
+							if (slave.devotion >= -20) {
+								r.push(`${He}'s <span class="devotion inc">more obedient</span> and <span class="trust inc">more tolerant,</span>`);
+								slave.devotion += 1;
+								slave.trust += 1;
+							} else {
+								r.push(`${He} does ${his} best to <span class="trust inc">stay strong,</span>`);
+								slave.trust += 1;
+							}
+							r.push(`since ${he} knows ${he} can soon buy ${his} freedom if ${he} continues earning.`);
+						}
+					}
 				}
 			}
 		}
diff --git a/src/js/utilsSlave.js b/src/js/utilsSlave.js
index f70c055af6385f460d145e3dd5f1595dffaaf223..567eb7ce4d1158677a81138910065dbb3ff0d86f 100644
--- a/src/js/utilsSlave.js
+++ b/src/js/utilsSlave.js
@@ -3300,6 +3300,10 @@ globalThis.retirementReady = function(slave) {
 	if (V.policies.retirement.kills > 0 && slave.counter.pitKills >= V.policies.retirement.kills) {
 		return true;
 	}
+	if (V.policies.retirement.income > 0 && (slave.lifetimeCashIncome - slave.lifetimeCashExpenses) >= V.policies.retirement.income) {
+		return true;
+	}
+
 
 	// no retirement for you
 	return false;
diff --git a/src/npc/descriptions/style/collar.js b/src/npc/descriptions/style/collar.js
index 953462bb634b467e1c8a8502bb5910c3a524956c..2f78e16b86c3949ae44eb25bdadf19fadb1c12d3 100644
--- a/src/npc/descriptions/style/collar.js
+++ b/src/npc/descriptions/style/collar.js
@@ -172,6 +172,8 @@ App.Desc.collar = function(slave) {
 				r.push(`${V.policies.retirement.births - slave.counter.births}, for the number of pregnancies still between ${him} and freedom.`);
 			} else if (V.policies.retirement.kills > 0) {
 				r.push(`${V.policies.retirement.kills - slave.counter.pitKills}, for the number of lives still between ${him} and freedom.`);
+			}  else if (V.policies.retirement.income > 0) {
+				r.push(`${cashFormat(V.policies.retirement.income - slave.lifetimeCashIncome + slave.lifetimeCashExpenses)}, for the amount ${he} still needs to earn to buy ${his} freedom.`);
 			} else if (V.policies.retirement.physicalAgePolicy === 0) {
 				r.push(`${(52 * (V.retirementAge - (slave.actualAge + 1))) + (52 - slave.birthWeek)}, the number of weeks of sexual slavery ahead of ${him}.`);
 			} else {