OverviewFilesCommitsIssuesDocsReleasesPeers

basal-agent commits / 4a1321a

basal-agent: rung45irr.c — reversibility was the blocker at 4->5
Law 2 transferred to the other stuck rung. rung45.c let a specialist mutate straight back to generalist, so specialisation was fully ELECTIVE — and Law 2 says an elective role is a strategy and gets invaded. One knob: IRREVERSIBLE lets generalists become anything but specialists become only other specialists. Monoculture-and-die route left open. 6 seeds, 500 comps x 12, 400 gens: REVERSIBLE spec 0.281 all-3-roles 18.0% viable 100% IRREVERSIBLE spec 0.464 all-3-roles 38.8% viable 100% REVERSIBLE, nosel spec 0.938 all-3-roles 22.8% IRREVERSIBLE, nosel spec 1.000 all-3-roles 31.3% THE CONFOUND CHECK INVERTED MY FIRST READING. I expected ratchet flux — one-way drift accumulating specialists regardless of selection. It is not: with selection removed, specialist fraction goes to ~1.0 in BOTH arms (the 30% specialist replication advantage), and selection SUPPRESSES specialists (0.938 -> 0.281). The first verdict criterion was also wrong: b-d measures selection's contribution inside the irreversible arm, not the flux confound. Corrected to compare irreversibility's benefit WITH selection against WITHOUT. DoL gain from irreversibility: +20.8% with selection, +8.5% without => ~59% is a genuine selection x irreversibility INTERACTION, ~41% flux. SHARPEST RESULT: selection's effect on DoL is -4.8% when roles are reversible and +7.5% when irreversible. With reversible roles SELECTION MAKES DoL WORSE — it drives specialists back toward generality, which is Law 2's invasion visible directly as a sign flip. Rung 5 needs a ratchet, not a bargain. BOUNDS: irreversibility is SUPPLIED, not evolved — nothing shows a ratchet arising on its own, only that one helps when present. 38.8% is a partial crossing, not a solved rung. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
4a1321ad598e66852b240fe461ee8a3b82278fd2
by plankatron <fleeky@gmail.com> · 2026-08-01T01:35:20.000Z

Changed files (3) +206 -0

.gitignore +1 -0
……@@ -49,3 +49,4 @@ fidfloor
4949genome
5050replicase
5151replisome
52rung45irr
rung45irr.c +148 -0
……@@ -0,0 +1,148 @@
1/* rung45irr.c — TEST: is division of labour blocked by REVERSIBILITY? (Law 2 applied to rung 4->5)
2 *
3 * rung45.c stalled, and rung45dup.c got specialists invading but full DoL plateauing at a second
4 * coordination valley. Law 2 (SYNTHESIS Part C) says why that might be: a boundary — or here a
5 * ROLE — that must be MAINTAINED is a strategy, and strategies get invaded. In rung45.c a
6 * specialist can mutate straight back to generalist (r = xs()%(F+1)), so specialisation is fully
7 * elective and the retreat to safe generality is always available.
8 *
9 * Life's specialists cannot go back: differentiation involves losing capability, and gene loss is
10 * one-way. So the one-knob test is whether making specialisation STRUCTURAL rather than elective
11 * stabilises DoL.
12 *
13 * REVERSIBLE (control, = rung45.c): with prob MUR, role := uniform(0..F)
14 * IRREVERSIBLE (test): with prob MUR, role := generalist ? uniform(0..F)
15 * : uniform(1..F) <- no way back
16 *
17 * NOT ENCODED: irreversibility removes the retreat-to-generalist escape, but leaves the OTHER
18 * failure route wide open — a compartment can still collapse to a monoculture of one specialist,
19 * lose a function and die. So the outcome is genuinely open: a ratchet could give division of
20 * labour, or could give monoculture and extinction. Viability is reported so which one happens is
21 * visible.
22 *
23 * build: cc -O2 -Wall -std=c11 -o rung45irr rung45irr.c -lm
24 */
25#include <math.h>
26#include <stdio.h>
27#include <stdlib.h>
28
29#define NCOMP 500
30#define GEN 400
31#define D 12 /* compartment size */
32#define F 3 /* functions (roles 1..F); role 0 = generalist */
33#define SSPEC 0.30 /* specialist replication advantage (the free-rider pressure) */
34#define EGEN 0.2 /* generalist efficiency per function */
35#define MUR 0.05 /* role mutation rate */
36
37static unsigned long long RNG;
38static unsigned long long xs(void){ RNG^=RNG<<13; RNG^=RNG>>7; RNG^=RNG<<17; return RNG; }
39static double urand(void){ return (double)(xs()>>11)*(1.0/9007199254740992.0); }
40static int binom(int n,double p){ int k=0; for(int i=0;i<n;i++) if(urand()<p) k++; return k; }
41
42static int IRREV=0, NOSEL=0;
43static int comp[NCOMP][F+1]; /* role counts per compartment */
44static int dau[2*NCOMP][F+1]; static double cum[2*NCOMP];
45
46static double viability_sel(const int *n);
47static double viability(const int *n){ if(NOSEL) return 1.0; return viability_sel(n); }
48static double viability_sel(const int *n){
49 double v=1e9;
50 for(int k=1;k<=F;k++){ double cov=n[k]+EGEN*n[0]; if(cov<v) v=cov; } /* weakest-link: need ALL functions */
51 return v;
52}
53
54static void one_run(int irrev,int nosel,double *specf,double *dolf,double *viaf){
55 IRREV=irrev; NOSEL=nosel;
56 for(int c=0;c<NCOMP;c++){ comp[c][0]=D; for(int k=1;k<=F;k++) comp[c][k]=0; }
57 for(int g=0;g<GEN;g++){
58 double w[F+1]; w[0]=1.0; for(int k=1;k<=F;k++) w[k]=1.0+SSPEC;
59 for(int c=0;c<NCOMP;c++){
60 double Z=0; for(int k=0;k<=F;k++) Z+=comp[c][k]*w[k]; if(Z<1e-12)Z=1e-12;
61 double pr[F+1],acc=0; for(int k=0;k<=F;k++){ acc+=comp[c][k]*w[k]/Z; pr[k]=acc; }
62 int m[F+1]={0};
63 for(int i=0;i<2*D;i++){ double u=urand(); int r=0; while(r<F && u>pr[r]) r++;
64 if(urand()<MUR){ if(IRREV && r!=0) r=1+(int)(xs()%F); else r=(int)(xs()%(F+1)); }
65 m[r]++; }
66 for(int k=0;k<=F;k++){ int d1=binom(m[k],0.5); dau[2*c][k]=d1; dau[2*c+1][k]=m[k]-d1; }
67 }
68 double tot=0; for(int i=0;i<2*NCOMP;i++){ tot+=viability(dau[i]); cum[i]=tot; }
69 if(tot<=0){ for(int c=0;c<NCOMP;c++) for(int k=0;k<=F;k++) comp[c][k]=0; break; }
70 for(int c=0;c<NCOMP;c++){ double r=urand()*tot; int lo=0,hi=2*NCOMP-1;
71 while(lo<hi){ int mid=(lo+hi)/2; if(cum[mid]<r) lo=mid+1; else hi=mid; }
72 for(int k=0;k<=F;k++) comp[c][k]=dau[lo][k]; }
73 }
74 long tot=0,spec=0; int dol=0,via=0;
75 for(int c=0;c<NCOMP;c++){ int s2=0;
76 for(int k=0;k<=F;k++){ tot+=comp[c][k]; if(k>0){ spec+=comp[c][k]; if(comp[c][k]>0) s2++; } }
77 if(s2==F) dol++; if(viability_sel(comp[c])>0.001) via++; }
78 *specf = tot? (double)spec/tot : 0;
79 *dolf = (double)dol/NCOMP;
80 *viaf = (double)via/NCOMP;
81}
82
83int main(void){
84 unsigned long long seeds[6]={0x9e3779b97f4a7c15ULL,0xd1b54a32d192ed03ULL,0x2545f4914f6cdd1dULL,
85 0x123456789abcdefULL,0xfeedface12345678ULL,0x0badc0de0badc0deULL};
86 int NS=6;
87 printf("=== RUNG 4->5 UNDER LAW 2: is division of labour blocked by REVERSIBILITY? ===\n");
88 printf(" rung45.c let a specialist mutate straight back to generalist, so specialisation was\n");
89 printf(" fully elective — and Law 2 says an elective role is a strategy and gets invaded.\n");
90 printf(" IRREVERSIBLE removes only the way back; the monoculture-and-die route stays open.\n");
91 printf(" start: every compartment = %d generalists; specialists replicate %.0f%% faster;\n",D,SSPEC*100);
92 printf(" a compartment needs all %d functions to be viable. %d comps, %d gens, %d seeds.\n\n",F,NCOMP,GEN,NS);
93 printf(" arm | spec frac | all-%d-roles | viable\n",F);
94 printf(" -------------+-----------+-------------+--------\n");
95 double a[3]={0,0,0}, b[3]={0,0,0}, d[3]={0,0,0}, e[3]={0,0,0};
96 for(int s=0;s<NS;s++){ double x,y,z;
97 RNG=seeds[s]; one_run(0,0,&x,&y,&z); a[0]+=x;a[1]+=y;a[2]+=z;
98 RNG=seeds[s]; one_run(1,0,&x,&y,&z); b[0]+=x;b[1]+=y;b[2]+=z;
99 RNG=seeds[s]; one_run(1,1,&x,&y,&z); d[0]+=x;d[1]+=y;d[2]+=z;
100 RNG=seeds[s]; one_run(0,1,&x,&y,&z); e[0]+=x;e[1]+=y;e[2]+=z; }
101 for(int i=0;i<3;i++){ a[i]/=NS; b[i]/=NS; d[i]/=NS; e[i]/=NS; }
102 printf(" REVERSIBLE | %.3f | %6.1f%% | %5.1f%%\n",a[0],100*a[1],100*a[2]);
103 printf(" IRREVERSIBLE | %.3f | %6.1f%% | %5.1f%%\n",b[0],100*b[1],100*b[2]);
104 printf(" ---- CONFOUND CHECK: same ratchet, selection REMOVED (flat viability) ----\n");
105 printf(" REVERS, nosel| %.3f | %6.1f%% | --\n",e[0],100*e[1]);
106 printf(" IRREV, nosel| %.3f | %6.1f%% | --\n\n",d[0],100*d[1]);
107 printf(" irreversibility's DoL benefit WITH selection %+.1f%%, WITHOUT selection %+.1f%%\n",
108 100*(b[1]-a[1]), 100*(d[1]-e[1]));
109 printf(" selection's effect on DoL: reversible %+.1f%%, irreversible %+.1f%%\n",
110 100*(a[1]-e[1]), 100*(b[1]-d[1]));
111
112 int dol_up = b[1]>a[1]+0.05, via_ok = b[2]>0.5, spec_up = b[0]>a[0]+0.05;
113 /* CORRECTED. b[1]-d[1] measures selection's contribution INSIDE the irreversible arm, not the
114 flux confound. The flux question is whether irreversibility's BENEFIT is bigger with selection
115 than without it: (irrev-rev | with sel) vs (irrev-rev | no sel). */
116 double gain_sel = b[1]-a[1], gain_nosel = d[1]-e[1];
117 int not_flux = gain_sel > gain_nosel + 0.05;
118 printf(" DoL higher when irreversible : %s (%.1f%% vs %.1f%%)\n", dol_up?"YES":"no",100*b[1],100*a[1]);
119 printf(" still viable : %s (%.1f%%)\n", via_ok?"YES":"NO — collapsed",100*b[2]);
120 printf(" specialist fraction up : %s (%.3f vs %.3f)\n\n", spec_up?"YES":"no",b[0],a[0]);
121 if(dol_up && via_ok && not_flux)
122 printf(" => REVERSIBILITY WAS THE BLOCKER, AND IT SURVIVES ITS CONFOUND CHECK. Irreversibility\n"
123 " raises DoL by %+.1f%% with selection but only %+.1f%% without, so roughly %.0f%% of the\n"
124 " gain is a genuine selection x irreversibility INTERACTION rather than ratchet flux.\n"
125 " The sharpest reading is in the last line: with REVERSIBLE roles selection makes DoL\n"
126 " WORSE (%+.1f%%) — it drives specialists back toward generality, which is Law 2's\n"
127 " invasion visible directly. With roles irreversible, the same selection HELPS (%+.1f%%).\n"
128 " Law 2 transfers from rung 1->2 to rung 4->5: an ELECTIVE role is a strategy and gets\n"
129 " invaded; a STRUCTURAL one cannot be. Rung 5 needs a ratchet, not a bargain.\n",
130 100*gain_sel,100*gain_nosel,100.0*(gain_sel-gain_nosel)/gain_sel,
131 100*(a[1]-e[1]),100*(b[1]-d[1]));
132 else if(dol_up && via_ok && !not_flux)
133 printf(" => IT IS THE RATCHET, NOT SELECTION. Irreversibility raises division of labour, but the\n"
134 " SAME rise appears with selection switched off (%.1f%% vs %.1f%%): a one-way\n"
135 " generalist->specialist flux accumulates specialists over %d generations whether or\n"
136 " not anything is being selected, and more specialists mechanically means more\n"
137 " compartments happen to hold all %d roles. The knob moved two variables again.\n",
138 100*b[1],100*d[1],GEN,F);
139 else if(!via_ok)
140 printf(" => THE RATCHET KILLS IT. Irreversibility removes the retreat, and compartments collapse\n"
141 " to monoculture and lose a function instead. Specialisation without a way back is\n"
142 " fatal here — the second failure route the design deliberately left open.\n");
143 else
144 printf(" => HONEST NULL. Irreversibility alone does not stabilise division of labour; the\n"
145 " coordination valley survives removing the retreat, so reversibility was not what\n"
146 " rung45.c was stalling on.\n");
147 return 0;
148}
rung45irr.md +57 -0
……@@ -0,0 +1,57 @@
1# `rung45irr.c` — reversibility was the blocker at 4→5
2
3**Law 2 transferred to the other stuck rung.** `rung45.c` stalled and `rung45dup.c` plateaued at a
4second coordination valley. Law 2 says why that might be: in `rung45.c` a specialist could mutate
5straight back to generalist (`r = xs()%(F+1)`), so specialisation was **fully elective** — and an
6elective role is a strategy, and strategies get invaded. Life's specialists cannot go back;
7differentiation loses capability and gene loss is one-way.
8
9One knob. **REVERSIBLE**: role := uniform(0..F). **IRREVERSIBLE**: generalists may become anything,
10specialists may only become other specialists. Nothing else changes, and the monoculture-and-die
11route stays wide open.
12
13## Results (6 seeds, 500 compartments × 12, 400 gens)
14
15| arm | spec frac | all-3-roles | viable |
16|---|---|---|---|
17| REVERSIBLE | 0.281 | 18.0% | 100% |
18| **IRREVERSIBLE** | **0.464** | **38.8%** | 100% |
19| *confound check — selection removed:* | | | |
20| REVERSIBLE, no selection | 0.938 | 22.8% | — |
21| IRREVERSIBLE, no selection | 1.000 | 31.3% | — |
22
23## The confound check inverted my first reading
24
25I expected the gain to be **ratchet flux** — a one-way generalist→specialist drift accumulating
26specialists whether or not anything is selected. It isn't. With selection removed, specialist
27fraction goes to ~1.0 in **both** arms, driven by the 30% specialist replication advantage. Selection
28*suppresses* specialists (0.938 → 0.281 reversible). The ratchet is not what raises them.
29
30Correct comparison — is irreversibility's benefit bigger with selection than without?
31
32| | DoL gain from irreversibility |
33|---|---|
34| with selection | **+20.8%** |
35| without selection | +8.5% |
36
37So **~59% of the gain is a genuine selection × irreversibility interaction**, ~41% is flux. The effect
38is real but smaller than the headline.
39
40## The sharpest line in the output
41
42> **selection's effect on DoL: reversible −4.8%, irreversible +7.5%**
43
44With reversible roles, **selection makes division of labour worse** — it drives specialists back
45toward generality. That is Law 2's invasion visible directly, as a sign flip. With roles
46irreversible, the identical selection *helps*.
47
48**Rung 5 needs a ratchet, not a bargain.** Law 2 was derived from the boundary work at rung 1→2 and
49transfers to rung 4→5 unchanged: an elective role is a strategy and gets invaded; a structural one
50cannot be.
51
52## Honest bounds
53
54Irreversibility is **supplied**, not evolved — nothing here shows a ratchet arising on its own, only
55that one helps when present. Gene loss is the biological analogue and it is plausibly the same kind
56of structural, non-discretionary commitment `linkage.c` found at 2→3. And 38.8% all-roles is a
57partial crossing, not a solved rung: most compartments still lack full division of labour.