Compare commits
2 Commits
3a65bf5d59
...
69fec5fe2e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
69fec5fe2e | ||
|
|
6a4fe59811 |
@@ -33,6 +33,21 @@
|
|||||||
* 11. Drift to low performance — a goal that erodes toward actual performance, so a
|
* 11. Drift to low performance — a goal that erodes toward actual performance, so a
|
||||||
* Reinforcing loop ratchets both downward.
|
* Reinforcing loop ratchets both downward.
|
||||||
*
|
*
|
||||||
|
* Next, the dynamic the book is named for, and the one the gallery has saved until a
|
||||||
|
* reader knows every piece it needs:
|
||||||
|
*
|
||||||
|
* 12. Overshoot and collapse — a Reinforcing engine running on a *non-renewable*
|
||||||
|
* Stock (the first with no inflow): it overshoots the
|
||||||
|
* limit instead of settling at it, the dark twin of
|
||||||
|
* "Limits to growth" — the ceiling erodes, so it crashes.
|
||||||
|
*
|
||||||
|
* Last, the language pointed at a live debate — a classic trap (Shifting the burden to
|
||||||
|
* the intervenor, ch. 5) wearing today's clothes:
|
||||||
|
*
|
||||||
|
* 13. AI deskilling spiral — handing the burden of code quality to AI atrophies the
|
||||||
|
* Expertise that holds quality up, so the team leans on AI
|
||||||
|
* harder and Technical debt spirals: addiction, not a fix.
|
||||||
|
*
|
||||||
* These are plain data built from the same tested constructors the store uses
|
* These are plain data built from the same tested constructors the store uses
|
||||||
* (factory.ts), so every sample is a valid Model by construction. `build()`
|
* (factory.ts), so every sample is a valid Model by construction. `build()`
|
||||||
* mints fresh ids on each call, so loading a sample twice never collides.
|
* mints fresh ids on each call, so loading a sample twice never collides.
|
||||||
@@ -571,6 +586,152 @@ function driftToLowPerformance(): Model {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overshoot and collapse — the dark twin of "Limits to growth". The same
|
||||||
|
* Reinforcing engine runs, but the limit here is a *non-renewable* Resource that
|
||||||
|
* only depletes: a Stock with no inflow, the first in the gallery. An economy
|
||||||
|
* (Capital) lives off it — extraction grows with both the Resource left and the
|
||||||
|
* Capital deployed (Resource, Capital → [+] → extraction), and the revenue is
|
||||||
|
* reinvested as new Capital (extraction → [+] → investment → Capital), so the loop
|
||||||
|
* Capital → extraction → investment → Capital carries no `−` → Reinforcing. Capital
|
||||||
|
* climbs and extraction accelerates, but every unit burned is gone for good, so the
|
||||||
|
* Resource crosses the break-even level, the engine starves, and depreciation
|
||||||
|
* (Capital → [+] → depreciation, a Balancing drain) takes Capital down: it peaks,
|
||||||
|
* then collapses. Contrast "Predator and prey", whose prey regrows and so settles
|
||||||
|
* into oscillation — a finite Resource cannot, so it overshoots and crashes instead.
|
||||||
|
*/
|
||||||
|
function overshootAndCollapse(): Model {
|
||||||
|
// Resource on the left drains only downward (no inflow). Capital on the right runs
|
||||||
|
// a full Source → investment → Capital → depreciation → Sink column. The two
|
||||||
|
// coupling links — Capital → extraction and extraction → investment — cross in the
|
||||||
|
// open centre, where the R badge lands.
|
||||||
|
const resource = makeStock({ x: -240, y: 0 }, "Resource")
|
||||||
|
resource.initialValue = 1000
|
||||||
|
const extractionSink = makeCloud({ x: -240, y: 360 })
|
||||||
|
const extraction = makeFlow({ x: -240, y: 160 }, "extraction", resource.id, extractionSink.id)
|
||||||
|
// extraction = factor × Resource × Capital (both `+`): more capital extracts
|
||||||
|
// faster, scarcer resource slower. The bilinear term the non-negative floor tames.
|
||||||
|
extraction.rule = { kind: "proportional", factor: 0.0004 }
|
||||||
|
const capital = makeStock({ x: 240, y: 0 }, "Capital")
|
||||||
|
capital.initialValue = 5
|
||||||
|
const investmentSource = makeCloud({ x: 240, y: -360 })
|
||||||
|
const investment = makeFlow({ x: 240, y: -160 }, "investment", investmentSource.id, capital.id)
|
||||||
|
// investment = factor × extraction (its one `+` input): the revenue reinvested —
|
||||||
|
// a Flow feeding a Flow, the edge that closes the Reinforcing loop through Capital.
|
||||||
|
investment.rule = { kind: "proportional", factor: 0.5 }
|
||||||
|
const depreciationSink = makeCloud({ x: 240, y: 360 })
|
||||||
|
const depreciation = makeFlow({ x: 240, y: 160 }, "depreciation", capital.id, depreciationSink.id)
|
||||||
|
// depreciation = factor × Capital (its `+` input): the Balancing drain that wins
|
||||||
|
// once the Resource can no longer feed investment.
|
||||||
|
depreciation.rule = { kind: "proportional", factor: 0.04 }
|
||||||
|
return model(
|
||||||
|
"Overshoot and collapse",
|
||||||
|
[
|
||||||
|
resource,
|
||||||
|
extractionSink,
|
||||||
|
extraction,
|
||||||
|
capital,
|
||||||
|
investmentSource,
|
||||||
|
investment,
|
||||||
|
depreciationSink,
|
||||||
|
depreciation,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
link(resource, extraction, "+"),
|
||||||
|
link(capital, extraction, "+"),
|
||||||
|
link(extraction, investment, "+"),
|
||||||
|
link(capital, depreciation, "+"),
|
||||||
|
],
|
||||||
|
// Capital starts at 5, overshoots to ~250 by t≈39, and collapses back near its
|
||||||
|
// starting level by t=150 — the full boom-and-bust arc, no dead tail.
|
||||||
|
{ start: 0, stop: 150, dt: 1 },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AI deskilling spiral — a classic trap in today's clothes: "Shifting the burden to
|
||||||
|
* the intervenor" (Thinking in Systems, ch. 5), where leaning on an outside fixer
|
||||||
|
* atrophies your own capacity to solve the problem, so you depend on the fixer ever
|
||||||
|
* more. Here the intervenor is AI. Technical debt drives reliance on it (the more cruft
|
||||||
|
* and delivery pressure, the more you reach for the model: Technical debt → [+] → AI
|
||||||
|
* reliance); AI churns out plausible code that adds debt (AI reliance → [+] → debt
|
||||||
|
* accrual) and lets skills lapse (AI reliance → [+] → atrophy, draining Expertise); and
|
||||||
|
* a thinner-skilled team refactors less (Expertise → [+] → refactoring, the Balancing
|
||||||
|
* payoff that now weakens). The loop Technical debt → AI reliance → atrophy → Expertise
|
||||||
|
* → refactoring → Technical debt carries two `−` (the two outflows) → Reinforcing: the
|
||||||
|
* spiral. The hopeful brake is learning — practice pulling Expertise back toward its
|
||||||
|
* ceiling (skill ceiling → [+], Expertise → [−] → learning: a Balancing loop) — but
|
||||||
|
* tuned here it loses to the spiral. (Code quality and lead time aren't nodes: quality
|
||||||
|
* reads as the inverse of Technical debt, lead time as the inverse of Expertise;
|
||||||
|
* "model price" lives in the AI-reliance factor — cheaper models, higher reliance.)
|
||||||
|
*/
|
||||||
|
function aiDeskillingSpiral(): Model {
|
||||||
|
// Two lanes — Expertise on top, Technical debt below — each a full Source → inflow →
|
||||||
|
// Stock → outflow → Sink. The AI reliance Converter sits between them, reading the
|
||||||
|
// debt below and feeding both atrophy (top lane) and debt accrual: the couplings that
|
||||||
|
// close the Reinforcing spiral cross the open centre.
|
||||||
|
const skillCeiling = makeConverter({ x: -360, y: -300 }, "skill ceiling")
|
||||||
|
skillCeiling.rule = { kind: "constant", value: 100 }
|
||||||
|
const learningSource = makeCloud({ x: -540, y: -120 })
|
||||||
|
const expertise = makeStock({ x: -180, y: -120 }, "Expertise")
|
||||||
|
expertise.initialValue = 70
|
||||||
|
const learning = makeFlow({ x: -360, y: -120 }, "learning", learningSource.id, expertise.id)
|
||||||
|
// learning = factor × (skill ceiling − Expertise): practice pulls skill back up — the
|
||||||
|
// Balancing brake. The further from mastery, the harder you study.
|
||||||
|
learning.rule = { kind: "gap", factor: 0.04 }
|
||||||
|
const atrophySink = makeCloud({ x: 300, y: -120 })
|
||||||
|
const atrophy = makeFlow({ x: 80, y: -120 }, "atrophy", expertise.id, atrophySink.id)
|
||||||
|
// atrophy = factor × AI reliance: the more you offload to AI, the faster unused skills
|
||||||
|
// lapse — the side effect that makes this an addiction, not a fix.
|
||||||
|
atrophy.rule = { kind: "proportional", factor: 0.6 }
|
||||||
|
const accrualSource = makeCloud({ x: -540, y: 120 })
|
||||||
|
const debt = makeStock({ x: -180, y: 120 }, "Technical debt")
|
||||||
|
debt.initialValue = 20
|
||||||
|
const accrual = makeFlow({ x: -360, y: 120 }, "debt accrual", accrualSource.id, debt.id)
|
||||||
|
// debt accrual = factor × AI reliance: AI emits plausible code faster than anyone
|
||||||
|
// reviews it, so debt grows the more you lean on it.
|
||||||
|
accrual.rule = { kind: "proportional", factor: 0.9 }
|
||||||
|
const refactorSink = makeCloud({ x: 300, y: 120 })
|
||||||
|
const refactoring = makeFlow({ x: 80, y: 120 }, "refactoring", debt.id, refactorSink.id)
|
||||||
|
// refactoring = factor × Expertise × Technical debt: skilled teams pay debt down in
|
||||||
|
// proportion to how much there is — the Balancing payoff the spiral starves.
|
||||||
|
refactoring.rule = { kind: "proportional", factor: 0.0009 }
|
||||||
|
const reliance = makeConverter({ x: -180, y: 0 }, "AI reliance")
|
||||||
|
// AI reliance = factor × Technical debt: the factor is how cheap and available models
|
||||||
|
// are — lower model price, higher reliance per unit of debt.
|
||||||
|
reliance.rule = { kind: "proportional", factor: 0.1 }
|
||||||
|
return model(
|
||||||
|
"AI deskilling spiral",
|
||||||
|
[
|
||||||
|
skillCeiling,
|
||||||
|
learningSource,
|
||||||
|
expertise,
|
||||||
|
learning,
|
||||||
|
atrophySink,
|
||||||
|
atrophy,
|
||||||
|
accrualSource,
|
||||||
|
debt,
|
||||||
|
accrual,
|
||||||
|
refactorSink,
|
||||||
|
refactoring,
|
||||||
|
reliance,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
link(skillCeiling, learning, "+"),
|
||||||
|
link(expertise, learning, "-"),
|
||||||
|
link(reliance, atrophy, "+"),
|
||||||
|
link(debt, reliance, "+"),
|
||||||
|
link(reliance, accrual, "+"),
|
||||||
|
link(expertise, refactoring, "+"),
|
||||||
|
link(debt, refactoring, "+"),
|
||||||
|
],
|
||||||
|
// Expertise slides 70 → ~6 and Technical debt spirals 20 → ~150 over the window —
|
||||||
|
// the Reinforcing loop clearly taking off, stopped (like "Escalation") before it
|
||||||
|
// runs away off-chart.
|
||||||
|
{ start: 0, stop: 50, dt: 1 },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/** The gallery, ordered simplest first. */
|
/** The gallery, ordered simplest first. */
|
||||||
export const SAMPLES: Sample[] = [
|
export const SAMPLES: Sample[] = [
|
||||||
{ title: "Bathtub", blurb: "A stock filled and drained — no feedback yet.", build: bathtub },
|
{ title: "Bathtub", blurb: "A stock filled and drained — no feedback yet.", build: bathtub },
|
||||||
@@ -624,4 +785,14 @@ export const SAMPLES: Sample[] = [
|
|||||||
blurb: "Goals erode toward actual: a Reinforcing slide downhill.",
|
blurb: "Goals erode toward actual: a Reinforcing slide downhill.",
|
||||||
build: driftToLowPerformance,
|
build: driftToLowPerformance,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Overshoot and collapse",
|
||||||
|
blurb: "A growth engine burns a finite Resource: it peaks, then crashes.",
|
||||||
|
build: overshootAndCollapse,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "AI deskilling spiral",
|
||||||
|
blurb: "Leaning on AI to hold quality erodes the expertise that holds it: shifting the burden.",
|
||||||
|
build: aiDeskillingSpiral,
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user