diff --git a/README.md b/README.md index c00a39be..e8839f9a 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,11 @@ theory. Each is a different lens on the same coordination arrangement. the cognitive theories of coordination. Each theory of mind models a channel between two parties and has nowhere to put an opaque, interested third; the major complex holds that third as a member of the irreducible core, and each failure point becomes a computable Φ prediction. +- **The irreducibility pipeline** in [`irreducibility-pipeline/`](irreducibility-pipeline/) is the + self-contained prototype behind the *Organization Science* Stage 1 package: rival Boolean encodings of a + coordination arrangement, drafted by a model and gated on verbatim evidence, then computed to exact Φ(MIP), + the major complex and the mediator's position. `python irreducibility-pipeline/reproduce.py` re-derives + its 17 reference results. Four readings meet on one arrangement: structure, fieldwork, behavior, and measurement. The field protocol turns real evidence into the structural reading, and the cognition program ties that structure back to the diff --git a/ci/reproduce.json b/ci/reproduce.json index 47c3278d..833320b4 100644 --- a/ci/reproduce.json +++ b/ci/reproduce.json @@ -7047,6 +7047,23 @@ "timeout": 1500, "slow": true, "source": "org_frontier/probes/PROBES.md (#116); the scaling-law probe in START_HERE.md" + }, + { + "name": "irreducibility-pipeline-reproduce", + "cmd": "python irreducibility-pipeline/reproduce.py", + "expect": [ + "PASS instrument-controls", + "PASS example-gig-dispatch", + "PASS ai-draft-gig", + "PASS census", + "PASS adversarial-coding", + "PASS proxies", + "17/17 checks passed." + ], + "timeout": 900, + "slow": true, + "what": "the irreducibility-pipeline prototype: 17 reference results (controls, four worked examples, logged AI runs, census, regimes, adversarial coding, proxies)", + "source": "irreducibility-pipeline/README.md" } ] } diff --git a/irreducibility-pipeline/.gitignore b/irreducibility-pipeline/.gitignore new file mode 100644 index 00000000..ec0a27b9 --- /dev/null +++ b/irreducibility-pipeline/.gitignore @@ -0,0 +1,7 @@ +__pycache__/ +*.pyc +.pytest_cache/ +.venv/ +studies/results/ +__pyphi_cache__/ +pyphi.log diff --git a/irreducibility-pipeline/APPENDIX.md b/irreducibility-pipeline/APPENDIX.md new file mode 100644 index 00000000..7b0c7dcc --- /dev/null +++ b/irreducibility-pipeline/APPENDIX.md @@ -0,0 +1,118 @@ +# Technical Appendix: Computing the Triad + + +## A. Encoding a coordinative structure + +A structure with *n* parties is a deterministic Boolean network on *n* nodes. Node *i* holds party *i*'s state, and a rule sets its next state from the current states of the parties it reads. Rules are written as expressions over party labels using `and`, `or`, `not`, `xor`, `0` and `1` (`irreducibility/rules.py`). The parser rejects anything else, so an encoding cannot execute code. + +An encodings file (`encode/SCHEMA.json`) holds one structure and several encodings. Each encoding gives: +- **role:** `rival` for a competing reading of the same arrangement, `design` for a deliberate change to it; +- **rules:** one per party; +- **evidence:** for every rule, a source, a locator and a verbatim quotation; +- **alternative:** for the mediator's rule, the reading the evidence does not rule out, and why; +- **predicted:** the verdict and core, with a reason, fixed before computing; +- **bypass (optional):** a direct tie for the contingency test. + +Strict mediation, for example: + +| Party | Rule | Reading | +|---|---|---| +| Driver D | D′ = P | acts on the platform's signal | +| Platform P | P′ = D and R | commits only when both parties are in | +| Rider R | R′ = P | responds to what the platform shows | + +## B. The computation (`irreducibility/core.py`) + +1. **Transition matrix.** `tpm_from_rules` builds the 2ⁿ × n state-by-node matrix, little-endian (index 0 = first party), as PyPhi expects. `cm_from_rules` builds the connectivity matrix by a flip test: cm[i, j] = 1 iff flipping node *i* can change node *j*'s next state. +2. **Reachable states.** These are states with at least one predecessor under the dynamics; PyPhi analyzes only these. +3. **Φ over the MIP.** For each reachable state, `pyphi.new_big_phi.sia` returns system integrated information over the minimum-information partition (Albantakis et al., 2023), together with the partition itself. +4. **Verdict.** The structure is **triadic** iff Φ > 10⁻⁹ in at least one reachable state, read at the most-integrated state; otherwise it is **dyadic**. The test uses the MIP, not the complete cut. The complete cut severs any coupled pair and would call every coupled dyad a triad. +5. **Major complex.** `pyphi.new_big_phi.maximal_complex` is maximized over reachable states. It names the parties bound into the irreducible core. +6. **Interpretation.** Only the binary verdict and core membership are interpreted. Φ magnitude depends on the encoding and is at most ordinal. + +**Environment.** PyPhi is pinned to commit `b78d0e342` of its IIT-4.0 line (`requirements.txt`), with Python 3.10 or later; the code is tested on 3.12. + +## C. Controls (`python -m irreducibility.validate`; every script refuses to run if they fail) + +| Control or form | Rules (W, S, C) | Expected | Observed | +|---|---|---|---| +| Factoring control | S, W, C | dyadic | dyadic, Φ = 0.000 | +| Irreducible control | S or C, W and C, W xor S | triadic | triadic, Φ = 0.830 | +| Strict-mediation triad | S, W and C, S | triadic | triadic, Φ = 2.000 | +| Chat dyad; dyadic gig model; feedback that breaks liveness | (see code) | dyadic | dyadic, Φ = 0.000 each | +| Gig "false dyad" | not S, W and C, C and not S | triadic | triadic, Φ = 2.000 | + +## D. Structural readings + +- **Mediator position** (`irreducibility/regime.py`): + - *dyadic*: the structure factors. + - *BYPASSED*: triadic, but the mediator is outside the core. + - *CAPTURE*: the mediator is in the core and some party is not. + - *BOTTLENECK*: all parties are in the core, and freezing the mediator at 0 or 1 leaves the others unable to coordinate. + - *ENRICHER*: all parties are in the core, and the others still coordinate with the mediator frozen. +- **Intrinsic or contingent** (`irreducibility/contingency.py`). Restore the forbidden direct tie (the downstream party reads the upstream party) and recompute the core. + - *Contingent*: the intermediary leaves the core. + - *Intrinsic*: it stays, with no loss of Φ. + - *Partial*: it stays, but Φ falls. + - *Reducible*: it was never in the core. +- **Spread across rival encodings** (`irreducibility/spread.py`, `analyze.py`): verdict agreement, the Φ gap, and the Jaccard overlap of the cores. For every pair of rival encodings with different verdicts, the analysis names each single rule whose swap flips the verdict. + +## E. The AI step + +| Component | File | Function | +|---|---|---| +| Schema | `encode/SCHEMA.json` | the format a drafter must produce | +| Drafter | `encode/PROMPT_drafter.md` | rival encodings with verbatim evidence, an alternative and a fixed prediction; commit, convey or store decided from evidence; pools encoded with `or` | +| Adversary | `encode/PROMPT_adversary.md` | the most different readings the evidence still permits on three forces (commit vs convey, substitutability, spectators and outside options), or a statement of which passage rules each one out | +| Gate | `irreducibility/encode_check.py` | rejects a missing rule, a rule with no evidence, a quotation not found verbatim in the source, a mediator rule with no alternative, or a missing prediction; never computes Φ | + +**Logged runs.** Claude Sonnet 5.5 ran on 26 Oct 2026 with the committed prompts and the case description only, with no tools and no access to the human encodings. + +| Run | Output | Result | +|---|---|---| +| Gig dispatch, drafter | `examples/01_gig_dispatch/ai_draft.json` | admissible; two rival encodings identical to the human encodings A and B; both predictions held; the driver pool was missed | +| Gig dispatch, adversary | `examples/01_gig_dispatch/ai_draft_plus_adversary.json` | added the driver pool (computed dyadic, core {P,R}; predicted triadic, so the prediction **failed**) and the substitute direct tie (computed triadic, core {D,R}, platform bypassed; predicted dyadic, so it **failed**); declined a complementary tie as unsupported | +| Insurance claim, drafter | `examples/02_insurance_claim/ai_draft.json` | left rules unwritten for four of five designs and stated the missing evidence; the gate **rejected** the file (9 problems) | + +## F. Worked examples (`examples/`; stipulated descriptions, not field data) + +The lab's results for these structures were known when the examples were written, so their predictions record the naive reading, not a blind test. + +| Example | Encodings | Results | +|---|---|---| +| 01 Gig dispatch | 3 rival, 5 design | Platform commits: triadic, Φ = 2.0, core {D,P,R}, bottleneck, intrinsic. Driver's relay: dyadic. Pooled drivers: dyadic, core {P,R}. Flip rule: P: `D and R` → `D`. Outside options O1–O5: bottleneck, enricher, capture {D,P}, capture {P,R}, bypassed {D,R}. | +| 02 Insurance claim | 5 design | Pipe: triadic, core {C,E,A}. Threshold auto-approval: core {C,E}, capture. Fraud loop with learning: core {E,A}. Loop without learning: core {C,A}, engine bypassed. Frozen claimant: dyadic. 2 of 5 naive predictions held. | +| 03 Code-review gate | 2 rival | Maintainers wait for CI: triadic, Φ = 1.0, core {A,M}, gate bypassed. Maintainers approve on the diff alone: core {A,G,M}, gate enricher. | +| 04 Dealer vs clearinghouse | 2 design | Dealer under a ban on direct sales: core {U,I,V}, contingent (Φ lost when bypassed: 2.0). Clearinghouse: intrinsic (Φ lost: 0.0). | + +## G. Reference results (`studies/`) + +| Check | Result | +|---|---| +| `census` | 256 strict-mediation structures (4 worker rules × 16 mediator rules × 4 counterpart rules). 24 are triadic; 24/160 where the mediator reads both parties and 0/96 otherwise. | +| `field-mocks` | Ten invented organizations: the verdict matched the reading fixed before computing in 9/10 (support-ticket triage read triadic against a dyadic prediction). 4 flip under a second defensible encoding. | +| `mediator-in-core`, `enricher-regime` | Over 500 random mediated forms: dyadic 44.4%, bypassed 18.8%, capture 28.2%, bottleneck 2.6%, enricher 6.0%. A platform's core is itself plus the parties without an outside option (60/60). | +| `contingent-irreducibility` | The bypass test realizes the intrinsic / contingent / partial / reducible taxonomy. | +| `design-operations` | Three levers (binding, liveness, requirement), each with a build operation and an exact inverse break. | +| `thompson-ordering` | Pooled Φ = 0, sequential Φ = 2.0, reciprocal Φ = 2.0: the top step of Thompson's ordering collapses. | +| `adversarial-coding` | An adversary limited to evidence-permitted readings flips the point verdict on 101/101 contested accounts; a coder-agreement interval brackets the adversarial reading in only 22. | +| `proxies` | ΦID Φ_R and whole-minus-sum Φ from simulated trajectories separate dyadic from triadic at rank-AUC 0.563 and 0.629. | + +## H. Planned specifications (Stage 2) + +- **Encoding module.** + - Input: transcripts, documents and logs, with locators. + - Process: drafter and adversary on an open-weight and a commercial model; a researcher's approval recorded per encoding. + - Agreement: AI drafter against two human coders, Krippendorff's α per rule and per bit, target ≥ 0.80. +- **Strategic model.** + - Rows: structural position (verdict, core, regime, intrinsic or contingent), indexed by actor (platform, worker, counterpart, regulator). + - Columns: design levers (add or remove binding; break or restore liveness; require all parties or allow substitutes; open or close a bypass; change an outside option). + - Cells: the computed consequence (who stays bound, who is freed, whether the mediator survives). + - Scope: structural only, with no claims about economic value. +- **Validation.** 10–15 published platform and algorithmic-management cases encoded from their own text. For each case, the verdict under every defensible encoding and the detail that would decide between them. The gig-dispatch interview packet (`protocol/`) will be fielded under ethics approval. + +## References + +Albantakis, L., et al. (2023). Integrated information theory (IIT) 4.0: Formulating the properties of phenomenal existence in physical terms. *PLOS Computational Biology*, 19(10), e1011465. https://doi.org/10.1371/journal.pcbi.1011465 + +Mayner, W. G. P., Marshall, W., Albantakis, L., Findlay, G., Marchman, R., & Tononi, G. (2018). PyPhi: A toolbox for integrated information theory. *PLOS Computational Biology*, 14(7), e1006343. https://doi.org/10.1371/journal.pcbi.1006343 diff --git a/irreducibility-pipeline/CITATION.cff b/irreducibility-pipeline/CITATION.cff new file mode 100644 index 00000000..dbe62a01 --- /dev/null +++ b/irreducibility-pipeline/CITATION.cff @@ -0,0 +1,18 @@ +cff-version: 1.2.0 +message: "If you use this software, please cite it as below." +title: "irreducibility-pipeline: exact irreducibility analysis of coordinative structures with PyPhi" +authors: + - family-names: Hunt + given-names: Roger + orcid: "https://orcid.org/0009-0000-7262-1779" +version: 0.1.0 +date-released: "2026-10-31" +license: MIT +keywords: + - integrated information theory + - PyPhi + - organization theory + - coordination + - platforms + - triads + - AI-assisted research diff --git a/irreducibility-pipeline/LICENSE b/irreducibility-pipeline/LICENSE new file mode 100644 index 00000000..e4d55e76 --- /dev/null +++ b/irreducibility-pipeline/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Roger Hunt + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/irreducibility-pipeline/README.md b/irreducibility-pipeline/README.md new file mode 100644 index 00000000..3e341190 --- /dev/null +++ b/irreducibility-pipeline/README.md @@ -0,0 +1,203 @@ +# irreducibility-pipeline + +Organizations increasingly coordinate through a third thing that sits between the parties: a dispatch +system that matches a driver to a rider, an engine that screens a claim before an adjuster sees it, a CI +gate between an author and a maintainer, an AI agent that negotiates for one side. Whether such an +arrangement is **irreducibly three-party**, or factors into two-party relations that happen to share a +platform, decides who is bound to whom and what a redesign would change. Platform research usually settles +the question by description. This repository settles it by computation. + +The pipeline takes a coordinative structure as it is encountered (a description, interview excerpts, +documents) and returns an exact irreducibility analysis: + +1. **Encode (AI drafts, a researcher approves).** Rival Boolean models of the arrangement, one per + defensible reading, with every rule tied to a verbatim quote from the evidence and a prediction fixed + before anything is computed. A checker rejects any rule whose quote is not in the source. +2. **Compute (PyPhi).** For each encoding, the rules become a transition matrix. PyPhi's IIT-4.0 + implementation returns integrated information Φ over the minimum-information partition in every + reachable state, and the major complex. **Triadic** means no cut along party lines leaves the structure + intact (Φ > 0); **dyadic** means some cut does (Φ = 0). +3. **Read (structural position).** Who is bound (the major complex); the mediator's position (bottleneck, + enricher, capture, bypassed); whether its place is intrinsic or held by a constraint on bypassing it; + and, across rival encodings, which single rule the verdict turns on. + +The repository is the prototype for a proposal to *Organization Science*, "AI-Enabled Frontiers in +Organizational Science." It analyzes structures; the strategic model that maps a structural position to +a decision is the next stage of the work and is not here yet. + +## Install + +```bash +python -m venv .venv && source .venv/bin/activate # Python 3.10+; tested on 3.12 +pip install -r requirements.txt +python -m irreducibility.validate # must end "Instrument validated." +``` + +`validate` runs two controls before anything else: a structure with a decoupled party must read dyadic +(Φ = 0), and a fully coupled three-node network must read triadic (Φ = 0.830). Five reference forms +follow. Every analysis script refuses to run if the controls fail. + +## A walk-through: gig dispatch + +**The structure** ([`examples/01_gig_dispatch/prose.md`](examples/01_gig_dispatch/prose.md), a stipulated +description, not field data). A driver, a dispatch platform, a rider; the recurring act is one match. The +platform's manual says "The system assigns a trip only when an eligible driver is available and a rider +has confirmed the request." A driver says "It's a suggestion, it follows what I do." The manual also says +"Any eligible driver in range may be assigned," and some riders "just text my regular driver." + +**Encode.** [`encodings.json`](examples/01_gig_dispatch/encodings.json) holds three rival readings and +five design scenarios. Each party's rule is a Boolean expression; each rule cites its passage: + +```json +"rules": {"D": "P", "P": "D and R", "R": "P"}, +"evidence": {"P": [{"source": "prose.md", "locator": "¶2", + "quote": "The system assigns a trip only when an eligible driver is available and a rider has confirmed the request"}]}, +"alternative": {"P": {"rule": "D", "why": "Drivers describe dispatch as a suggestion that follows the driver (¶3)"}}, +"predicted": {"structure": "triadic", "core": ["D", "P", "R"], "reason": "..."} +``` + +```bash +python -m irreducibility.encode_check examples/01_gig_dispatch/encodings.json +# ADMISSIBLE: 8 encoding(s); every rule has evidence found verbatim in its source; every encoding carries a prediction. +``` + +**Compute.** + +```bash +python -m irreducibility.analyze examples/01_gig_dispatch/encodings.json +``` + +``` +[A] platform's account: dispatch commits a binding match (rival) + D' = P + P' = D and R + R' = P + PyPhi input: TPM 8x3 (state-by-node), connectivity [[0, 1, 0], [1, 0, 1], [0, 1, 0]] + Φ_MIP by reachable state: 000:0.000, 010:0.000, 101:0.000, 111:2.000 + verdict: TRIADIC max Φ_MIP = 2.000 (1/4 states irreducible) + MIP at state 111: 2 parts: {D,PR} + major complex (who is bound): {D, P, R} + mediator (P) position: BOTTLENECK + bypass test on P: intrinsic (Φ lost when the bypass opens: 0.000; core {D,P,R} -> {D,P}) + predicted before computing: triadic, core {D,P,R} -> HELD + +[B] driver's account: dispatch relays a suggestion (rival) + verdict: DYADIC max Φ_MIP = 0.000 ... major complex: {D, P} + +[C] pooled drivers: any eligible driver will do (rival) + verdict: DYADIC ... major complex: {P, R} <- the driver drops out of the core +``` + +**Read.** The three readings disagree, and the report says on what: + +``` +A vs B: verdicts triadic/dyadic, Φ gap 2.000, core overlap 0.667 + single rule that flips it: P: 'D and R' -> 'D' +CONTESTED: the verdict depends on which encoding the evidence supports +``` + +The whole question is whether dispatch *commits* a match that needs both parties or *relays* the driver's +choice. That is the fact a field study must settle. Pooling drivers (reading C) removes the individual +driver from the irreducible core: the platform and the rider remain bound, the driver does not. + +The five design scenarios hold the platform's rule fixed and vary the parties' outside options: + +| Scenario | Driver | Rider | Position of the platform | Core | +|---|---|---|---|---| +| O1 both captive | `P` | `P` | BOTTLENECK | {D, P, R} | +| O2 complementary direct tie | `P and R` | `P and D` | ENRICHER | {D, P, R} | +| O3 captive driver, mobile rider | `P` | `P or D` | CAPTURE | {D, P} | +| O4 mobile driver, captive rider | `P or R` | `P` | CAPTURE | {P, R} | +| O5 both mobile | `P or R` | `P or D` | BYPASSED | {D, R} | + +Giving only the driver an outside option does not free the platform; it moves the lock-in to the rider +(O3 → O4). Only symmetric options remove the platform from the core (O5). These are readings of a model; +what a platform, a drivers' collective or a regulator should *do* given them is the strategic model still +to be built. + +## Where AI enters, and what it did + +[`encode/`](encode/) holds the AI step: a JSON schema, a **drafter** prompt (rival encodings with verbatim +evidence and a prediction) and an **adversary** prompt (the most different readings the evidence still +permits: commit vs convey, substitutability, outside options). Both are model-agnostic. The checker +[`irreducibility/encode_check.py`](irreducibility/encode_check.py) rejects a rule with no evidence, a quote +not found verbatim in the source, a mediator rule with no alternative, or an encoding with no prediction. + +Logged runs (Claude Sonnet 5.5, 26 Oct 2026, prompts as committed, case prose only, no tools): + +- **Gig dispatch, drafter** ([`ai_draft.json`](examples/01_gig_dispatch/ai_draft.json)): two rival + encodings, identical to the human encodings A and B; all quotes verbatim; both predictions held. It did + not encode the driver pool. +- **Gig dispatch, adversary** ([`ai_draft_plus_adversary.json`](examples/01_gig_dispatch/ai_draft_plus_adversary.json)): + found the driver pool and the substitute direct tie, and declined a complement tie as unsupported by ¶6. + **Both of its predictions failed** when computed: it expected the pooled structure to stay triadic (it + is dyadic, core {P, R}) and the direct-tie structure to be dyadic (it is triadic with the platform + bypassed, core {D, R}). The model found the readings; PyPhi decided them. +- **Insurance claim, drafter** ([`ai_draft.json`](examples/02_insurance_claim/ai_draft.json)): for four of + five designs it declined to write rules the prose does not specify and said what evidence was missing. + The checker rejects the file (9 problems), which is the gate doing its job. + +Nothing yet reads interview transcripts or documents at scale; that, and agreement between the AI drafter +and two human coders, is the next stage. + +## Run it on your own structure + +1. Write the case material to a file and number its paragraphs or give each excerpt a locator. +2. Copy an `encodings.json`, set the `parties` and the `mediator`, and write each party's rule as a + Boolean expression over party labels (`and`, `or`, `not`, `xor`, `0`, `1`). Cite a verbatim quote for + every rule and fix the prediction. Or paste the case into [`encode/PROMPT_drafter.md`](encode/PROMPT_drafter.md), + then [`PROMPT_adversary.md`](encode/PROMPT_adversary.md), with any model. +3. `python -m irreducibility.encode_check your.json` +4. `python -m irreducibility.analyze your.json --json report.json` + +The field protocol for real arrangements (bounding the act, coding the bits, eliciting rules from +evidence, inter-rater reliability, ethics) is in [`protocol/`](protocol/). + +## Reproduce every number + +```bash +python reproduce.py # 17 checks, about 2 minutes on a laptop +pytest -q # 19 tests, from this directory +# from the lab root: pytest -q irreducibility-pipeline/tests +``` + +| Check | What it reproduces | +|---|---| +| `instrument-controls` | the controls and five reference forms | +| `example-*` | the four worked examples (gig dispatch, insurance claim, code-review gate, dealer vs clearinghouse) | +| `ai-draft-gig`, `ai-draft-insurance-rejected` | the logged AI runs, checked and computed | +| `census` | 24 of 256 strict-mediation structures are triadic; 24/160 where the mediator reads both parties, 0/96 otherwise | +| `field-mocks` | ten mock organizations: 9/10 match the reading fixed before computing; 4 flip under a second defensible encoding | +| `mediator-in-core`, `enricher-regime` | regime frequencies over 500 random forms; the outside-option law (60/60) | +| `contingent-irreducibility` | the bypass test separates intrinsic from contingent intermediation | +| `design-operations` | three design levers (binding, liveness, requirement), each with a build and an inverse break | +| `thompson-ordering` | Thompson's pooled < sequential < reciprocal ordering collapses at the top step | +| `adversarial-coding` | an evidence-limited adversary flips the point verdict on 101/101 contested accounts | +| `proxies` | two time-series proxies separate dyadic from triadic at rank-AUC 0.563 and 0.629 (0.5 is chance) | + +## Scope + +- Verdicts are exact **for the stated encoding**. The same arrangement can be encoded more than one + defensible way, which is why the pipeline reports every encoding and the rule the verdict turns on. +- A verdict on a model is evidence about the model. It is not, by itself, evidence that real workers + experience an arrangement as irreducible; that needs fieldwork. +- Exact Φ is practical up to about ten binary nodes. Coordination units of three to five parties compute in + seconds. +- The examples are stipulated descriptions written to demonstrate the method, and the lab's results for + them were known when they were written; their predictions record the naive reading, not a blind test. + +## Layout + +``` +irreducibility/ core.py (PyPhi wrapper) · validate.py · regime.py · contingency.py · spread.py + rule_to_phi.py · rules.py · encoding.py · encode_check.py · analyze.py +encode/ SCHEMA.json · PROMPT_drafter.md · PROMPT_adversary.md +examples/ 01_gig_dispatch · 02_insurance_claim · 03_code_review_gate · 04_dealer_vs_clearinghouse +studies/ the scripts behind the reference results (census, mocks, regimes, design operations, ...) +protocol/ field protocol, coding scheme, interview guide, ethics, predictions fixed in advance +tests/ pytest suite +reproduce.py one command for every number +``` + +MIT licensed. PyPhi is developed by the Tononi lab (Mayner et al., 2018, *PLOS Computational Biology*); IIT +4.0 is specified in Albantakis et al. (2023, *PLOS Computational Biology*). diff --git a/irreducibility-pipeline/encode/PROMPT_adversary.md b/irreducibility-pipeline/encode/PROMPT_adversary.md new file mode 100644 index 00000000..b3fcf115 --- /dev/null +++ b/irreducibility-pipeline/encode/PROMPT_adversary.md @@ -0,0 +1,42 @@ +# Prompt: search for the defensible encodings that would change the answer + +Run this after the drafter, on the same case material and the drafter's JSON. The adversary's job +is to stop a single convenient reading from standing as "the" verdict. A sampled sensitivity check +is not enough: in the lab's tests, an adversary limited to evidence-permitted readings could flip +the verdict on every contested account it was given. + +--- + +You are given a coordinative structure's case material and a set of drafted encodings. Your task is to +find the **most different readings the evidence still permits**. You do not compute anything. + +**Case material** + +``` +<> +``` + +**Drafted encodings** + +``` +<> +``` + +For each of the three forces below, write at most one new encoding with role `"rival"`, each with +verbatim evidence for every rule. Write it only if the evidence actually permits the reading; if it does +not, say which passage rules it out. + +1. **Commit versus convey.** If the drafts have the mediator committing on a joint condition, find the + strongest evidence that it only relays one party's signal, or only stores inputs for a human. If + the drafts have it relaying, find the strongest evidence that it commits. +2. **Substitutability.** If a party could be one of several interchangeable parties (drivers in a pool, + sellers of the same item, reviewers on a rota), encode the pool with `or` and separate labels for + the pool members. +3. **Spectators and outside options.** If a party watches but does not act, add it as a node. If a + party can reach another without the mediator, encode the direct tie as a complement (`and`) or a + substitute (`or`), according to what the evidence says about whether they need the mediator as + well. + +For each new encoding, state its prediction and reason before anything is computed, as the drafter did. + +**Output:** the drafter's JSON with your encodings appended to `encodings`. No prose outside the JSON. diff --git a/irreducibility-pipeline/encode/PROMPT_drafter.md b/irreducibility-pipeline/encode/PROMPT_drafter.md new file mode 100644 index 00000000..8d759761 --- /dev/null +++ b/irreducibility-pipeline/encode/PROMPT_drafter.md @@ -0,0 +1,44 @@ +# Prompt: draft rival encodings of a coordinative structure + +Model-agnostic. Paste the case material where marked. The output must validate against +`encode/SCHEMA.json` and pass `python -m irreducibility.encode_check `, which rejects any rule +that lacks evidence, any mediator rule without an alternative, and any encoding without a +prediction. + +--- + +You are encoding one coordinative structure as a small Boolean model so that its irreducibility can be +computed exactly. You draft; a researcher approves. Do not compute anything and do not guess what the +computation will return. + +**Case material** + +``` +<> +``` + +**Steps** + +1. **Parties.** Use the party list you are given. For each party, state what its bit = 1 means and what + that binary collapses. +2. **Who reads whom.** A party reads another only if the evidence shows its action depends on the + other's state. An edge needs a documented process, a log, or agreement among the parties. Record a + single unsupported claim as an alternative, not an edge. +3. **The function.** Write each party's next state as a Boolean expression over the parties it reads, + using `and`, `or`, `not`, `xor`, `0`, `1` and party labels only. For the mediating system, decide + whether the evidence shows it **commits** on a joint condition (e.g. `D and R`), **conveys** a + signal one party sets (e.g. `D`), or **stores** inputs for someone else to decide. Treat a pool of + interchangeable parties as `or` over the pool. +4. **Evidence.** For every rule, quote the passage it rests on verbatim, with its source and locator. + If no passage supports a rule, do not write the rule; say what evidence is missing. +5. **The alternative.** For the mediator's rule, and for any rule the evidence leaves open, give the + alternative rule the evidence does not rule out and say why. +6. **Rival encodings.** Where the parties' accounts conflict (for example, the platform says it + commits and the workers say it suggests), do not resolve the conflict by majority. Write one + encoding per account, with role `"rival"`, and name whose account each one is. +7. **Prediction.** For each encoding, state the verdict you expect (`dyadic` or `triadic`), the parties + you expect in the core, and a one-sentence structural reason. This prediction is fixed before + anything is computed and is scored afterwards. + +**Output:** one JSON object in the format of `encode/SCHEMA.json`. No prose outside the JSON. diff --git a/irreducibility-pipeline/encode/SCHEMA.json b/irreducibility-pipeline/encode/SCHEMA.json new file mode 100644 index 00000000..cdebbe9a --- /dev/null +++ b/irreducibility-pipeline/encode/SCHEMA.json @@ -0,0 +1,189 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Encodings of one coordinative structure", + "description": "One coordinative structure, several rival encodings. Each encoding is a Boolean model of who reads whom and what each party commits, with the evidence behind every rule and the prediction fixed before computing. irreducibility.encoding.validate enforces the evidence, alternative and prediction rules.", + "type": "object", + "required": [ + "structure", + "parties", + "encodings" + ], + "properties": { + "structure": { + "type": "string", + "description": "the bounded recurring act, e.g. 'Gig dispatch: one match'" + }, + "source": { + "type": "string" + }, + "parties": { + "type": "array", + "minItems": 2, + "items": { + "type": "object", + "required": [ + "label", + "name", + "active" + ], + "properties": { + "label": { + "type": "string", + "pattern": "^[A-Za-z][A-Za-z0-9_]*$" + }, + "name": { + "type": "string" + }, + "active": { + "type": "string", + "description": "what the party's bit = 1 means; say what it collapses" + } + } + } + }, + "mediator": { + "type": "string", + "description": "label of the mediating system, if any" + }, + "encodings": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "id", + "rules", + "evidence", + "predicted" + ], + "properties": { + "id": { + "type": "string" + }, + "account": { + "type": "string", + "description": "whose account or which design this encoding represents" + }, + "role": { + "enum": [ + "rival", + "design" + ], + "description": "rival = a competing reading of the same arrangement; design = a deliberate change to it" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + }, + "description": "override the party list (e.g. pooled drivers)" + }, + "rules": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "party -> Boolean expression over party labels using and, or, not, xor, 0, 1" + }, + "evidence": { + "type": "object", + "additionalProperties": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "source", + "locator", + "quote" + ], + "properties": { + "source": { + "type": "string", + "description": "file or document the passage comes from" + }, + "locator": { + "type": "string", + "description": "paragraph, page, timestamp or line" + }, + "quote": { + "type": "string", + "minLength": 1, + "description": "the passage, verbatim" + } + } + } + } + }, + "alternative": { + "type": "object", + "additionalProperties": { + "type": "object", + "required": [ + "rule", + "why" + ], + "properties": { + "rule": { + "type": "string" + }, + "why": { + "type": "string" + } + } + } + }, + "predicted": { + "type": "object", + "required": [ + "structure", + "reason" + ], + "properties": { + "structure": { + "enum": [ + "dyadic", + "triadic" + ] + }, + "core": { + "type": "array", + "items": { + "type": "string" + } + }, + "reason": { + "type": "string" + } + } + }, + "bypass": { + "type": "object", + "required": [ + "party", + "downstream", + "upstream" + ], + "properties": { + "party": { + "type": "string" + }, + "downstream": { + "type": "string" + }, + "upstream": { + "type": "string" + }, + "mode": { + "enum": [ + "replace", + "add" + ] + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/irreducibility-pipeline/examples/01_gig_dispatch/ai_adversary_raw.json b/irreducibility-pipeline/examples/01_gig_dispatch/ai_adversary_raw.json new file mode 100644 index 00000000..3c0d74aa --- /dev/null +++ b/irreducibility-pipeline/examples/01_gig_dispatch/ai_adversary_raw.json @@ -0,0 +1,148 @@ +{ + "new_encodings": [ + { + "id": "driver_pool", + "account": "Several idle drivers in one zone are interchangeable candidates, and the platform commits when any one eligible driver and a confirmed rider are present. Each driver acts when a trip is shown, and the rider acts when told a driver is assigned.", + "role": "rival", + "labels": [ + "D1", + "D2", + "P", + "R" + ], + "rules": { + "P": "(D1 or D2) and R", + "D1": "P", + "D2": "P", + "R": "P" + }, + "evidence": { + "P": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The system assigns a trip only when an eligible driver is available and a rider has confirmed the request" + }, + { + "source": "prose.md", + "locator": "¶5", + "quote": "Any eligible driver in range may be assigned." + } + ], + "D1": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "When the trip comes up I go. If nothing comes up I wait." + } + ], + "D2": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "When the trip comes up I go. If nothing comes up I wait." + }, + { + "source": "prose.md", + "locator": "¶5", + "quote": "In dense hours several drivers are idle in the same zone." + } + ], + "R": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "Once it says a driver is assigned, I wait at the curb." + } + ] + }, + "alternative": { + "P": { + "rule": "D1 or D2", + "why": "Under the drivers' account in ¶3, the platform only relays whichever driver is nearby: \"The app just pings me with whatever is nearby.\" That reading drops the rider's confirmation from the platform's rule." + } + }, + "predicted": { + "structure": "triadic", + "core": [ + "D1", + "D2", + "P", + "R" + ], + "reason": "P is active only when some driver and the rider are both active, so neither side reaches the other without P. The driver pool adds substitutes on the driver side but leaves the platform in the middle. The two drivers should enter the core together as interchangeable members, with P and R." + } + }, + { + "id": "direct_contact_substitute", + "account": "Drivers and riders who have each other's numbers can arrange a trip directly. The platform is one route to a match, and the direct tie replaces it when the app fails. Where off-app contact is banned, this tie does not exist, so this reading holds only for the cities with contact.", + "role": "rival", + "rules": { + "P": "D and R", + "D": "P or R", + "R": "P or D" + }, + "evidence": { + "P": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "the assignment is binding on both and sets the fare" + } + ], + "D": [ + { + "source": "prose.md", + "locator": "¶6", + "quote": "Some drivers and riders exchange numbers and arrange repeat trips directly." + }, + { + "source": "prose.md", + "locator": "¶4", + "quote": "When the trip comes up I go. If nothing comes up I wait." + } + ], + "R": [ + { + "source": "prose.md", + "locator": "¶6", + "quote": "If the app is slow I just text my regular driver." + }, + { + "source": "prose.md", + "locator": "¶4", + "quote": "Once it says a driver is assigned, I wait at the curb." + } + ] + }, + "alternative": { + "P": { + "rule": "D", + "why": "The drivers' account in ¶3 treats the platform as following the driver: \"It's a suggestion, it follows what I do.\"" + } + }, + "predicted": { + "structure": "dyadic", + "core": [ + "D", + "R" + ], + "reason": "The direct tie lets D and R each be active without P, and each stays active if the other is. The pair D-R sustains itself, so P drops out of the core. The match no longer depends on the mediator." + } + } + ], + "not_permitted": [ + { + "reading": "Third commit-versus-convey reading", + "why": "The drafts already hold the two readings the text supports, which are the manual's commit in ¶2 and the driver's suggestion in ¶3. No passage supports a third, such as the platform following the rider alone." + }, + { + "reading": "Direct tie as a complement (D or R needs both P and the other party)", + "why": "¶6 says \"If the app is slow I just text my regular driver\". The rider goes around the app instead of needing it as well, so the tie is a substitute. No passage says the parties need the mediator in addition to the direct contact." + }, + { + "reading": "Direct tie present for all drivers and riders", + "why": "¶6 says \"Other cities ban off-app arrangements and drivers there have no way to reach riders except through the platform.\" In those cities the direct tie is absent, so the substitute encoding cannot be applied across all cities." + } + ] +} \ No newline at end of file diff --git a/irreducibility-pipeline/examples/01_gig_dispatch/ai_draft.json b/irreducibility-pipeline/examples/01_gig_dispatch/ai_draft.json new file mode 100644 index 00000000..fce94c2b --- /dev/null +++ b/irreducibility-pipeline/examples/01_gig_dispatch/ai_draft.json @@ -0,0 +1,131 @@ +{ + "structure": "Gig dispatch: one match between a driver, the dispatch platform and a rider", + "source": "prose.md", + "parties": [ + { + "label": "D", + "name": "driver", + "active": "1 = the driver is available in the zone and goes when a trip is shown; 0 = waiting. This collapses location, eligibility and the accept decision into one bit." + }, + { + "label": "P", + "name": "dispatch platform", + "active": "1 = a trip is assigned and shown to the parties; 0 = no assignment. This collapses matching, pricing and notification into one bit." + }, + { + "label": "R", + "name": "rider", + "active": "1 = the rider has requested and confirmed a ride, then waits at the curb; 0 = no live request. This collapses opening the app, requesting, confirming and waiting into one bit." + } + ], + "mediator": "P", + "encodings": [ + { + "id": "platform_commits", + "account": "The platform's operations manual: the system commits on a joint condition of driver availability and rider confirmation.", + "role": "rival", + "rules": { + "P": "D and R", + "D": "P", + "R": "P" + }, + "evidence": { + "P": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The system assigns a trip only when an eligible driver is available and a rider has confirmed the request; the assignment is binding on both and sets the fare." + } + ], + "D": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "When the trip comes up I go. If nothing comes up I wait." + } + ], + "R": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "Once it says a driver is assigned, I wait at the curb." + } + ] + }, + "alternative": { + "P": { + "rule": "D", + "why": "The drivers' account in ¶3 says the app only conveys what the driver sets. The evidence does not settle which account is right, so it is encoded as a separate rival." + }, + "R": { + "rule": "P or D", + "why": "One rider in ¶6 texts a regular driver when the app is slow. This is a single unsupported claim, and other cities ban off-app arrangements. It is recorded as an alternative, not an edge." + }, + "D": { + "rule": "P or R", + "why": "The same ¶6 off-app contact would let a driver act on a rider directly. Only some drivers and riders do this, and no log or agreement among the parties documents it." + } + }, + "predicted": { + "structure": "triadic", + "core": [ + "D", + "P", + "R" + ], + "reason": "The platform's rule is an AND of driver and rider that neither party can compute alone, and both parties then read the platform's output, so the loop through the mediator should not reduce to pairwise links." + } + }, + { + "id": "drivers_suggestion", + "account": "The drivers' account: the app conveys a signal the driver sets and follows what the driver does.", + "role": "rival", + "rules": { + "P": "D", + "D": "P", + "R": "P" + }, + "evidence": { + "P": [ + { + "source": "prose.md", + "locator": "¶3", + "quote": "The app just pings me with whatever is nearby. I decide. It's a suggestion, it follows what I do." + } + ], + "D": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "When the trip comes up I go. If nothing comes up I wait." + } + ], + "R": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "Once it says a driver is assigned, I wait at the curb." + } + ] + }, + "alternative": { + "P": { + "rule": "D and R", + "why": "The manual in ¶2 says assignment requires rider confirmation and is binding. A single driver's description does not rule this out, and it is encoded as the other rival." + }, + "R": { + "rule": "P or D", + "why": "One rider in ¶6 texts a regular driver when the app is slow. This is a single unsupported claim, not an edge." + } + }, + "predicted": { + "structure": "dyadic", + "core": [ + "D", + "P" + ], + "reason": "If the platform only relays the driver's state, the driver and platform form a two-party loop, and the rider only reads the platform's output without feeding back into anyone." + } + } + ] +} \ No newline at end of file diff --git a/irreducibility-pipeline/examples/01_gig_dispatch/ai_draft_plus_adversary.json b/irreducibility-pipeline/examples/01_gig_dispatch/ai_draft_plus_adversary.json new file mode 100644 index 00000000..998db4b9 --- /dev/null +++ b/irreducibility-pipeline/examples/01_gig_dispatch/ai_draft_plus_adversary.json @@ -0,0 +1,275 @@ +{ + "structure": "Gig dispatch: one match between a driver, the dispatch platform and a rider", + "source": "prose.md", + "parties": [ + { + "label": "D", + "name": "driver", + "active": "1 = the driver is available in the zone and goes when a trip is shown; 0 = waiting. This collapses location, eligibility and the accept decision into one bit." + }, + { + "label": "P", + "name": "dispatch platform", + "active": "1 = a trip is assigned and shown to the parties; 0 = no assignment. This collapses matching, pricing and notification into one bit." + }, + { + "label": "R", + "name": "rider", + "active": "1 = the rider has requested and confirmed a ride, then waits at the curb; 0 = no live request. This collapses opening the app, requesting, confirming and waiting into one bit." + } + ], + "mediator": "P", + "encodings": [ + { + "id": "platform_commits", + "account": "The platform's operations manual: the system commits on a joint condition of driver availability and rider confirmation.", + "role": "rival", + "rules": { + "P": "D and R", + "D": "P", + "R": "P" + }, + "evidence": { + "P": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The system assigns a trip only when an eligible driver is available and a rider has confirmed the request; the assignment is binding on both and sets the fare." + } + ], + "D": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "When the trip comes up I go. If nothing comes up I wait." + } + ], + "R": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "Once it says a driver is assigned, I wait at the curb." + } + ] + }, + "alternative": { + "P": { + "rule": "D", + "why": "The drivers' account in ¶3 says the app only conveys what the driver sets. The evidence does not settle which account is right, so it is encoded as a separate rival." + }, + "R": { + "rule": "P or D", + "why": "One rider in ¶6 texts a regular driver when the app is slow. This is a single unsupported claim, and other cities ban off-app arrangements. It is recorded as an alternative, not an edge." + }, + "D": { + "rule": "P or R", + "why": "The same ¶6 off-app contact would let a driver act on a rider directly. Only some drivers and riders do this, and no log or agreement among the parties documents it." + } + }, + "predicted": { + "structure": "triadic", + "core": [ + "D", + "P", + "R" + ], + "reason": "The platform's rule is an AND of driver and rider that neither party can compute alone, and both parties then read the platform's output, so the loop through the mediator should not reduce to pairwise links." + } + }, + { + "id": "drivers_suggestion", + "account": "The drivers' account: the app conveys a signal the driver sets and follows what the driver does.", + "role": "rival", + "rules": { + "P": "D", + "D": "P", + "R": "P" + }, + "evidence": { + "P": [ + { + "source": "prose.md", + "locator": "¶3", + "quote": "The app just pings me with whatever is nearby. I decide. It's a suggestion, it follows what I do." + } + ], + "D": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "When the trip comes up I go. If nothing comes up I wait." + } + ], + "R": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "Once it says a driver is assigned, I wait at the curb." + } + ] + }, + "alternative": { + "P": { + "rule": "D and R", + "why": "The manual in ¶2 says assignment requires rider confirmation and is binding. A single driver's description does not rule this out, and it is encoded as the other rival." + }, + "R": { + "rule": "P or D", + "why": "One rider in ¶6 texts a regular driver when the app is slow. This is a single unsupported claim, not an edge." + } + }, + "predicted": { + "structure": "dyadic", + "core": [ + "D", + "P" + ], + "reason": "If the platform only relays the driver's state, the driver and platform form a two-party loop, and the rider only reads the platform's output without feeding back into anyone." + } + }, + { + "id": "driver_pool", + "account": "Several idle drivers in one zone are interchangeable candidates, and the platform commits when any one eligible driver and a confirmed rider are present. Each driver acts when a trip is shown, and the rider acts when told a driver is assigned.", + "role": "rival", + "labels": [ + "D1", + "D2", + "P", + "R" + ], + "rules": { + "P": "(D1 or D2) and R", + "D1": "P", + "D2": "P", + "R": "P" + }, + "evidence": { + "P": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The system assigns a trip only when an eligible driver is available and a rider has confirmed the request" + }, + { + "source": "prose.md", + "locator": "¶5", + "quote": "Any eligible driver in range may be assigned." + } + ], + "D1": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "When the trip comes up I go. If nothing comes up I wait." + } + ], + "D2": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "When the trip comes up I go. If nothing comes up I wait." + }, + { + "source": "prose.md", + "locator": "¶5", + "quote": "In dense hours several drivers are idle in the same zone." + } + ], + "R": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "Once it says a driver is assigned, I wait at the curb." + } + ] + }, + "alternative": { + "P": { + "rule": "D1 or D2", + "why": "Under the drivers' account in ¶3, the platform only relays whichever driver is nearby: \"The app just pings me with whatever is nearby.\" That reading drops the rider's confirmation from the platform's rule." + } + }, + "predicted": { + "structure": "triadic", + "core": [ + "D1", + "D2", + "P", + "R" + ], + "reason": "P is active only when some driver and the rider are both active, so neither side reaches the other without P. The driver pool adds substitutes on the driver side but leaves the platform in the middle. The two drivers should enter the core together as interchangeable members, with P and R." + } + }, + { + "id": "direct_contact_substitute", + "account": "Drivers and riders who have each other's numbers can arrange a trip directly. The platform is one route to a match, and the direct tie replaces it when the app fails. Where off-app contact is banned, this tie does not exist, so this reading holds only for the cities with contact.", + "role": "rival", + "rules": { + "P": "D and R", + "D": "P or R", + "R": "P or D" + }, + "evidence": { + "P": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "the assignment is binding on both and sets the fare" + } + ], + "D": [ + { + "source": "prose.md", + "locator": "¶6", + "quote": "Some drivers and riders exchange numbers and arrange repeat trips directly." + }, + { + "source": "prose.md", + "locator": "¶4", + "quote": "When the trip comes up I go. If nothing comes up I wait." + } + ], + "R": [ + { + "source": "prose.md", + "locator": "¶6", + "quote": "If the app is slow I just text my regular driver." + }, + { + "source": "prose.md", + "locator": "¶4", + "quote": "Once it says a driver is assigned, I wait at the curb." + } + ] + }, + "alternative": { + "P": { + "rule": "D", + "why": "The drivers' account in ¶3 treats the platform as following the driver: \"It's a suggestion, it follows what I do.\"" + } + }, + "predicted": { + "structure": "dyadic", + "core": [ + "D", + "R" + ], + "reason": "The direct tie lets D and R each be active without P, and each stays active if the other is. The pair D-R sustains itself, so P drops out of the core. The match no longer depends on the mediator." + } + } + ], + "not_permitted": [ + { + "reading": "Third commit-versus-convey reading", + "why": "The drafts already hold the two readings the text supports, which are the manual's commit in ¶2 and the driver's suggestion in ¶3. No passage supports a third, such as the platform following the rider alone." + }, + { + "reading": "Direct tie as a complement (D or R needs both P and the other party)", + "why": "¶6 says \"If the app is slow I just text my regular driver\". The rider goes around the app instead of needing it as well, so the tie is a substitute. No passage says the parties need the mediator in addition to the direct contact." + }, + { + "reading": "Direct tie present for all drivers and riders", + "why": "¶6 says \"Other cities ban off-app arrangements and drivers there have no way to reach riders except through the platform.\" In those cities the direct tie is absent, so the substitute encoding cannot be applied across all cities." + } + ] +} \ No newline at end of file diff --git a/irreducibility-pipeline/examples/01_gig_dispatch/encodings.json b/irreducibility-pipeline/examples/01_gig_dispatch/encodings.json new file mode 100644 index 00000000..1b19f805 --- /dev/null +++ b/irreducibility-pipeline/examples/01_gig_dispatch/encodings.json @@ -0,0 +1,415 @@ +{ + "structure": "Gig dispatch: one match (stipulated description)", + "source": "prose.md", + "parties": [ + { + "label": "D", + "name": "driver", + "active": "available and accepting this match" + }, + { + "label": "P", + "name": "dispatch platform", + "active": "commits this match" + }, + { + "label": "R", + "name": "rider", + "active": "requesting and accepting this match" + } + ], + "mediator": "P", + "encodings": [ + { + "id": "A", + "account": "platform's account: dispatch commits a binding match", + "role": "rival", + "rules": { + "D": "P", + "P": "D and R", + "R": "P" + }, + "evidence": { + "D": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "When the trip comes up I go. If nothing comes up I wait." + } + ], + "P": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The system assigns a trip only when an eligible driver is available and a rider has confirmed the request" + } + ], + "R": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "Once it says a driver is assigned, I wait at the curb." + } + ] + }, + "alternative": { + "P": { + "rule": "D", + "why": "Drivers describe dispatch as a suggestion that follows the driver (¶3); the evidence does not rule out a relay." + } + }, + "predicted": { + "structure": "triadic", + "core": [ + "D", + "P", + "R" + ], + "reason": "The platform commits a match neither party sets alone, and both act on it." + }, + "bypass": { + "party": "P", + "downstream": "R", + "upstream": "D", + "mode": "replace" + } + }, + { + "id": "B", + "account": "driver's account: dispatch relays a suggestion", + "role": "rival", + "rules": { + "D": "P", + "P": "D", + "R": "P" + }, + "evidence": { + "D": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "When the trip comes up I go. If nothing comes up I wait." + } + ], + "P": [ + { + "source": "prose.md", + "locator": "¶3", + "quote": "It's a suggestion, it follows what I do." + } + ], + "R": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "Once it says a driver is assigned, I wait at the curb." + } + ] + }, + "alternative": { + "P": { + "rule": "D and R", + "why": "The manual describes a binding assignment that needs both driver and rider (¶2)." + } + }, + "predicted": { + "structure": "dyadic", + "reason": "A relay that only follows the driver commits nothing of its own; the rider is downstream." + } + }, + { + "id": "C", + "account": "pooled drivers: any eligible driver will do", + "role": "rival", + "labels": [ + "D1", + "D2", + "P", + "R" + ], + "rules": { + "D1": "P", + "D2": "P", + "P": "(D1 or D2) and R", + "R": "P" + }, + "evidence": { + "D1": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "When the trip comes up I go. If nothing comes up I wait." + } + ], + "D2": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "When the trip comes up I go. If nothing comes up I wait." + } + ], + "P": [ + { + "source": "prose.md", + "locator": "¶5", + "quote": "Any eligible driver in range may be assigned." + } + ], + "R": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "Once it says a driver is assigned, I wait at the curb." + } + ] + }, + "alternative": { + "P": { + "rule": "D1 and R", + "why": "Outside dense hours one driver is in range and the match needs that driver (¶1)." + } + }, + "predicted": { + "structure": "dyadic", + "reason": "Interchangeable drivers make no single driver pivotal, so the structure factors." + } + }, + { + "id": "O1", + "account": "outside options: both captive (off-app contact banned)", + "role": "design", + "rules": { + "D": "P", + "P": "D and R", + "R": "P" + }, + "evidence": { + "D": [ + { + "source": "prose.md", + "locator": "¶6", + "quote": "drivers there have no way to reach riders except through the platform" + } + ], + "P": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The system assigns a trip only when an eligible driver is available and a rider has confirmed the request" + } + ], + "R": [ + { + "source": "prose.md", + "locator": "¶6", + "quote": "drivers there have no way to reach riders except through the platform" + } + ] + }, + "alternative": { + "P": { + "rule": "D", + "why": "Drivers describe dispatch as a suggestion that follows the driver (¶3); the evidence does not rule out a relay." + } + }, + "predicted": { + "structure": "triadic", + "reason": "The platform's core is itself plus the parties with no outside option.", + "core": [ + "D", + "P", + "R" + ] + } + }, + { + "id": "O2", + "account": "outside options: complementary direct tie (repeat trips need app and contact)", + "role": "design", + "rules": { + "D": "P and R", + "P": "D and R", + "R": "P and D" + }, + "evidence": { + "D": [ + { + "source": "prose.md", + "locator": "¶6", + "quote": "If the app is slow I just text my regular driver." + } + ], + "P": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The system assigns a trip only when an eligible driver is available and a rider has confirmed the request" + } + ], + "R": [ + { + "source": "prose.md", + "locator": "¶6", + "quote": "If the app is slow I just text my regular driver." + } + ] + }, + "alternative": { + "P": { + "rule": "D", + "why": "Drivers describe dispatch as a suggestion that follows the driver (¶3); the evidence does not rule out a relay." + } + }, + "predicted": { + "structure": "triadic", + "reason": "The platform's core is itself plus the parties with no outside option.", + "core": [ + "D", + "P", + "R" + ] + } + }, + { + "id": "O3", + "account": "outside options: captive driver, mobile rider", + "role": "design", + "rules": { + "D": "P", + "P": "D and R", + "R": "P or D" + }, + "evidence": { + "D": [ + { + "source": "prose.md", + "locator": "¶6", + "quote": "drivers there have no way to reach riders except through the platform" + } + ], + "P": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The system assigns a trip only when an eligible driver is available and a rider has confirmed the request" + } + ], + "R": [ + { + "source": "prose.md", + "locator": "¶6", + "quote": "If the app is slow I just text my regular driver." + } + ] + }, + "alternative": { + "P": { + "rule": "D", + "why": "Drivers describe dispatch as a suggestion that follows the driver (¶3); the evidence does not rule out a relay." + } + }, + "predicted": { + "structure": "triadic", + "reason": "The platform's core is itself plus the parties with no outside option.", + "core": [ + "D", + "P" + ] + } + }, + { + "id": "O4", + "account": "outside options: mobile driver, captive rider", + "role": "design", + "rules": { + "D": "P or R", + "P": "D and R", + "R": "P" + }, + "evidence": { + "D": [ + { + "source": "prose.md", + "locator": "¶6", + "quote": "If the app is slow I just text my regular driver." + } + ], + "P": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The system assigns a trip only when an eligible driver is available and a rider has confirmed the request" + } + ], + "R": [ + { + "source": "prose.md", + "locator": "¶6", + "quote": "drivers there have no way to reach riders except through the platform" + } + ] + }, + "alternative": { + "P": { + "rule": "D", + "why": "Drivers describe dispatch as a suggestion that follows the driver (¶3); the evidence does not rule out a relay." + } + }, + "predicted": { + "structure": "triadic", + "reason": "The platform's core is itself plus the parties with no outside option.", + "core": [ + "P", + "R" + ] + } + }, + { + "id": "O5", + "account": "outside options: both mobile (substitute direct tie)", + "role": "design", + "rules": { + "D": "P or R", + "P": "D and R", + "R": "P or D" + }, + "evidence": { + "D": [ + { + "source": "prose.md", + "locator": "¶6", + "quote": "If the app is slow I just text my regular driver." + } + ], + "P": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The system assigns a trip only when an eligible driver is available and a rider has confirmed the request" + } + ], + "R": [ + { + "source": "prose.md", + "locator": "¶6", + "quote": "If the app is slow I just text my regular driver." + } + ] + }, + "alternative": { + "P": { + "rule": "D", + "why": "Drivers describe dispatch as a suggestion that follows the driver (¶3); the evidence does not rule out a relay." + } + }, + "predicted": { + "structure": "triadic", + "reason": "The platform's core is itself plus the parties with no outside option.", + "core": [ + "D", + "R" + ] + } + } + ] +} \ No newline at end of file diff --git a/irreducibility-pipeline/examples/01_gig_dispatch/prose.md b/irreducibility-pipeline/examples/01_gig_dispatch/prose.md new file mode 100644 index 00000000..a96e6037 --- /dev/null +++ b/irreducibility-pipeline/examples/01_gig_dispatch/prose.md @@ -0,0 +1,24 @@ +# Gig dispatch: one match + +A stipulated description, written to demonstrate the pipeline. It is not field data. Paragraph numbers +are the locators the encodings cite. + +**¶1.** The recurring act is a single match. A driver waits near a pickup zone, a rider opens the app and +requests a ride, and the dispatch system decides whether to pair this driver with this rider. + +**¶2.** The platform's operations manual describes dispatch this way: "The system assigns a trip only +when an eligible driver is available and a rider has confirmed the request; the assignment is binding +on both and sets the fare." + +**¶3.** Drivers describe it differently. One driver said: "The app just pings me with whatever is nearby. +I decide. It's a suggestion, it follows what I do." + +**¶4.** Drivers act on what the system shows them: "When the trip comes up I go. If nothing comes up I +wait." Riders do the same: "Once it says a driver is assigned, I wait at the curb." + +**¶5.** In dense hours several drivers are idle in the same zone. The manual says: "Any eligible driver +in range may be assigned." + +**¶6.** Outside the app, contact varies. Some drivers and riders exchange numbers and arrange repeat +trips directly. One rider said: "If the app is slow I just text my regular driver." Other cities ban +off-app arrangements and drivers there have no way to reach riders except through the platform. diff --git a/irreducibility-pipeline/examples/02_insurance_claim/ai_draft.json b/irreducibility-pipeline/examples/02_insurance_claim/ai_draft.json new file mode 100644 index 00000000..84991b39 --- /dev/null +++ b/irreducibility-pipeline/examples/02_insurance_claim/ai_draft.json @@ -0,0 +1,239 @@ +{ + "structure": "Insurance claim adjudication: who decides a claim? Five stipulated routing designs (claimant C, auto-adjudication engine E, human adjuster A)", + "source": "prose.md", + "parties": [ + { + "label": "C", + "name": "Claimant", + "active": "1 = paid, 0 = still pursuing. This collapses the whole claim lifecycle (filed, under review, partly paid, denied, appealed, closed) into paid or not paid." + }, + { + "label": "E", + "name": "Auto-adjudication engine", + "active": "1 = approves, 0 = flags. This collapses the engine's screening score, the claim's size and type, and the reason for a flag into a single approve/flag bit." + }, + { + "label": "A", + "name": "Human adjuster", + "active": "1 = acts on the claim, 0 = does not. This collapses approve, deny, adjust, request information and override into one 'acts' bit." + } + ], + "mediator": "E", + "encodings": [ + { + "id": "design1_pipe", + "account": "Stipulated Design 1 (the pipe). The prose names all three edges but does not state the polarity of the engine and adjuster bits, so the NOT in A is my reading, not the source's. No conflicting accounts, so there are no rival encodings.", + "role": "design", + "rules": { + "E": "C", + "A": "not E", + "C": "A" + }, + "evidence": { + "E": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The engine reads the claimant, the adjuster reads the engine, and the claimant reads the adjuster." + }, + { + "source": "prose.md", + "locator": "¶2", + "quote": "The engine forwards every claim to the adjuster; the adjuster's decision goes back to the claimant." + } + ], + "A": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The engine reads the claimant, the adjuster reads the engine, and the claimant reads the adjuster." + }, + { + "source": "prose.md", + "locator": "¶2", + "quote": "The engine forwards every claim to the adjuster; the adjuster's decision goes back to the claimant." + } + ], + "C": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The engine reads the claimant, the adjuster reads the engine, and the claimant reads the adjuster." + }, + { + "source": "prose.md", + "locator": "¶2", + "quote": "The engine forwards every claim to the adjuster; the adjuster's decision goes back to the claimant." + } + ] + }, + "alternative": { + "E": { + "rule": "not C", + "why": "The engine is the mediator. The evidence shows it conveys the claimant's state ('forwards every claim'), but it gives no polarity. A reversed mapping between the claimant bit and the flag is not ruled out. Neither is a rule that also commits on a second condition, since ¶1 says the engine 'screens' the claim." + }, + "A": { + "rule": "E", + "why": "The prose gives the edge (the adjuster reads the engine) but not the polarity. I took a forwarded claim to mean flagged (E = 0) and the adjuster acting (A = 1). A plain copy is not ruled out." + } + }, + "predicted": { + "structure": "triadic", + "core": [ + "C", + "E", + "A" + ], + "reason": "Each party reads exactly one other and the three form a single cycle, so no pair of parties is closed under its own inputs and the mediator carries the loop." + } + }, + { + "id": "design2_threshold_auto_approval", + "account": "Stipulated Design 2 (threshold auto-approval). The engine's rule is not written: the prose says small claims are approved, which depends on claim size, and names no party state as its input. The alternative below records this gap. The researcher must supply the engine's input before this encoding can be computed.", + "role": "design", + "rules": { + "C": "E and not A", + "A": "not E and not C" + }, + "evidence": { + "C": [ + { + "source": "prose.md", + "locator": "¶3", + "quote": "The claimant is paid when the engine approves and the adjuster has not intervened; the adjuster acts when the engine flags a claim the claimant is pursuing." + } + ], + "A": [ + { + "source": "prose.md", + "locator": "¶3", + "quote": "The claimant is paid when the engine approves and the adjuster has not intervened; the adjuster acts when the engine flags a claim the claimant is pursuing." + }, + { + "source": "prose.md", + "locator": "¶3", + "quote": "Small claims are approved automatically; the adjuster reviews only claims the engine flags." + } + ] + }, + "alternative": { + "E": { + "rule": "C", + "why": "Missing evidence: no passage says which party's state the engine reads in this design. 'Small claims are approved automatically' points to claim size, which is not a party bit, so the engine may be exogenous here. If the engine screens the claim the claimant filed, it could read C, but the prose does not say so." + } + }, + "predicted": { + "structure": "dyadic", + "core": [ + "C", + "A" + ], + "reason": "The documented edges give C and A a mutual loop while the engine has no documented input from either, so it acts as an external gate and not as a joint constraint." + } + }, + { + "id": "design3_fraud_flag_loop_learning", + "account": "Stipulated Design 3 (fraud-flag loop with override learning). The prose states that the engine's flag reads both the claim and the adjuster, but not the function. The adjuster's reading of the flag is the only other documented edge. The engine's rule and the claimant's rule are therefore not written, and the researcher must supply them.", + "role": "design", + "rules": { + "A": "not E" + }, + "evidence": { + "A": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "The engine flags claims for the adjuster and retrains on the adjuster's overrides." + } + ] + }, + "alternative": { + "E": { + "rule": "C and not A", + "why": "The prose says only 'The engine's flag reads both the claim and the adjuster.' So E depends on C and A, but the function is open. One commit-style reading is that the engine approves only a paid claim the adjuster has not overridden. Other joint functions (xor, or) are not ruled out." + }, + "C": { + "rule": "A", + "why": "Missing evidence: ¶4 says nothing about the claimant's rule. The pipe's rule (the claimant reads the adjuster's decision) would be the natural carry-over, but this paragraph does not state it." + } + }, + "predicted": { + "structure": "triadic", + "core": [ + "C", + "E", + "A" + ], + "reason": "The engine reads both the claim and the adjuster while the adjuster reads the engine, so the mediator joins two parties in a feedback loop. This prediction is provisional because the claimant's own rule is undocumented." + } + }, + { + "id": "design4_loop_without_learning", + "account": "Stipulated Design 4: the Design 3 loop with the engine no longer retraining on overrides. I read this as removing the engine's edge from the adjuster. That removal is my inference, since ¶5 does not name the edge. The engine's remaining rule and the claimant's rule are not documented, so neither is written.", + "role": "design", + "rules": { + "A": "not E" + }, + "evidence": { + "A": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "The engine flags claims for the adjuster and retrains on the adjuster's overrides." + }, + { + "source": "prose.md", + "locator": "¶5", + "quote": "The engine no longer retrains on overrides." + } + ] + }, + "alternative": { + "E": { + "rule": "C", + "why": "With the adjuster's input removed, the engine's flag still reads the claim (¶4), so a dependence on C alone is not ruled out. The prose gives no function, and the engine may read nothing from the parties." + }, + "C": { + "rule": "A", + "why": "Missing evidence: no passage states the claimant's rule in this design. The pipe's copy of the adjuster's decision is the likeliest, but it is not documented." + } + }, + "predicted": { + "structure": "dyadic", + "core": [], + "reason": "Without the engine's edge from the adjuster, influence runs from the engine to the adjuster only, so the engine is not part of any joint loop and no triad closes." + } + }, + { + "id": "design5_frozen_claimant", + "account": "Stipulated Design 5: the claimant's state no longer reads the decision. Only this one edge is documented and the prose does not say which other design it modifies. No rule is written for any party. The researcher must choose the base design and the claimant's replacement rule.", + "role": "design", + "rules": {}, + "evidence": { + "C": [ + { + "source": "prose.md", + "locator": "¶6", + "quote": "The claimant is not told the outcome until the file closes." + }, + { + "source": "prose.md", + "locator": "¶6", + "quote": "The claimant's state no longer reads the decision." + } + ] + }, + "alternative": { + "C": { + "rule": "0", + "why": "Missing evidence: the prose removes the claimant's input but gives no replacement. A constant (here 0, still pursuing) and a self-hold (C) both fit, and the evidence does not choose between them." + } + }, + "predicted": { + "structure": "dyadic", + "core": [], + "reason": "With the claimant reading nothing, the loop that returns the outcome to the claimant is cut, so the engine and adjuster cannot form an irreducible triad with the claimant." + } + } + ] +} \ No newline at end of file diff --git a/irreducibility-pipeline/examples/02_insurance_claim/encodings.json b/irreducibility-pipeline/examples/02_insurance_claim/encodings.json new file mode 100644 index 00000000..e1558b74 --- /dev/null +++ b/irreducibility-pipeline/examples/02_insurance_claim/encodings.json @@ -0,0 +1,259 @@ +{ + "structure": "Insurance claim adjudication: five routing designs (stipulated description)", + "source": "prose.md", + "parties": [ + { + "label": "C", + "name": "claimant", + "active": "pursuing or paid" + }, + { + "label": "E", + "name": "auto-adjudication engine", + "active": "approves" + }, + { + "label": "A", + "name": "human adjuster", + "active": "acts on the claim" + } + ], + "mediator": "E", + "encodings": [ + { + "id": "pipe", + "account": "design 1: the engine forwards, the adjuster decides", + "role": "design", + "rules": { + "C": "A", + "E": "C", + "A": "E" + }, + "evidence": { + "C": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The engine forwards every claim to the adjuster; the adjuster's decision goes back to the claimant." + } + ], + "E": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The engine forwards every claim to the adjuster; the adjuster's decision goes back to the claimant." + } + ], + "A": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The engine forwards every claim to the adjuster; the adjuster's decision goes back to the claimant." + } + ] + }, + "alternative": { + "E": { + "rule": "C", + "why": "Whether the engine reads the adjuster depends on whether it retrains on overrides (¶4, ¶5)." + } + }, + "predicted": { + "structure": "triadic", + "core": [ + "C", + "E", + "A" + ], + "reason": "A closed three-party ring binds all three." + } + }, + { + "id": "gated", + "account": "design 2: threshold auto-approval", + "role": "design", + "rules": { + "C": "E and not A", + "E": "C", + "A": "E and C" + }, + "evidence": { + "C": [ + { + "source": "prose.md", + "locator": "¶3", + "quote": "Small claims are approved automatically; the adjuster reviews only claims the engine flags." + } + ], + "E": [ + { + "source": "prose.md", + "locator": "¶3", + "quote": "Small claims are approved automatically; the adjuster reviews only claims the engine flags." + } + ], + "A": [ + { + "source": "prose.md", + "locator": "¶3", + "quote": "Small claims are approved automatically; the adjuster reviews only claims the engine flags." + } + ] + }, + "alternative": { + "E": { + "rule": "C", + "why": "Whether the engine reads the adjuster depends on whether it retrains on overrides (¶4, ¶5)." + } + }, + "predicted": { + "structure": "triadic", + "core": [ + "C", + "E", + "A" + ], + "reason": "The adjuster reviews flagged claims, so all three should be bound." + } + }, + { + "id": "loop", + "account": "design 3: fraud-flag loop with override learning", + "role": "design", + "rules": { + "C": "A", + "E": "C and A", + "A": "E and C" + }, + "evidence": { + "C": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The engine forwards every claim to the adjuster; the adjuster's decision goes back to the claimant." + } + ], + "E": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "The engine flags claims for the adjuster and retrains on the adjuster's overrides." + } + ], + "A": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "The engine flags claims for the adjuster and retrains on the adjuster's overrides." + } + ] + }, + "alternative": { + "E": { + "rule": "C", + "why": "Whether the engine reads the adjuster depends on whether it retrains on overrides (¶4, ¶5)." + } + }, + "predicted": { + "structure": "triadic", + "core": [ + "C", + "E", + "A" + ], + "reason": "The engine reads claimant and adjuster, the adjuster reads both." + } + }, + { + "id": "loop_nolearn", + "account": "design 4: the loop without learning", + "role": "design", + "rules": { + "C": "A", + "E": "C", + "A": "E and C" + }, + "evidence": { + "C": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The engine forwards every claim to the adjuster; the adjuster's decision goes back to the claimant." + } + ], + "E": [ + { + "source": "prose.md", + "locator": "¶5", + "quote": "The engine no longer retrains on overrides." + } + ], + "A": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "The engine flags claims for the adjuster and retrains on the adjuster's overrides." + } + ] + }, + "alternative": { + "E": { + "rule": "C", + "why": "Whether the engine reads the adjuster depends on whether it retrains on overrides (¶4, ¶5)." + } + }, + "predicted": { + "structure": "triadic", + "core": [ + "C", + "E", + "A" + ], + "reason": "Removing learning should leave the three-way core intact." + } + }, + { + "id": "frozen", + "account": "design 5: the claimant does not see the decision", + "role": "design", + "rules": { + "C": "C", + "E": "C and A", + "A": "E and C" + }, + "evidence": { + "C": [ + { + "source": "prose.md", + "locator": "¶6", + "quote": "The claimant is not told the outcome until the file closes." + } + ], + "E": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "The engine flags claims for the adjuster and retrains on the adjuster's overrides." + } + ], + "A": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "The engine flags claims for the adjuster and retrains on the adjuster's overrides." + } + ] + }, + "alternative": { + "E": { + "rule": "C", + "why": "Whether the engine reads the adjuster depends on whether it retrains on overrides (¶4, ¶5)." + } + }, + "predicted": { + "structure": "dyadic", + "reason": "A claimant who no longer reads the decision should let the structure factor." + } + } + ] +} \ No newline at end of file diff --git a/irreducibility-pipeline/examples/02_insurance_claim/prose.md b/irreducibility-pipeline/examples/02_insurance_claim/prose.md new file mode 100644 index 00000000..3e9215af --- /dev/null +++ b/irreducibility-pipeline/examples/02_insurance_claim/prose.md @@ -0,0 +1,24 @@ +# Insurance claim adjudication: who decides a claim? + +A stipulated description of five routing designs an insurer could use, adapted from a question a +contributor ran through the lab's protocol. It is not field data. Paragraph numbers are locators. + +**¶1.** A claimant files a claim. An auto-adjudication engine screens it. A human adjuster may review +it. Each party's state is one bit: the claimant is pursuing or paid (C), the engine approves or flags +(E), the adjuster acts or does not (A). + +**¶2.** Design 1, the pipe. "The engine forwards every claim to the adjuster; the adjuster's decision +goes back to the claimant." The engine reads the claimant, the adjuster reads the engine, and the +claimant reads the adjuster. + +**¶3.** Design 2, threshold auto-approval. "Small claims are approved automatically; the adjuster +reviews only claims the engine flags." The claimant is paid when the engine approves and the adjuster +has not intervened; the adjuster acts when the engine flags a claim the claimant is pursuing. + +**¶4.** Design 3, the fraud-flag loop with override learning. "The engine flags claims for the adjuster +and retrains on the adjuster's overrides." The engine's flag reads both the claim and the adjuster. + +**¶5.** Design 4, the same loop without learning. "The engine no longer retrains on overrides." + +**¶6.** Design 5, the frozen claimant. "The claimant is not told the outcome until the file closes." +The claimant's state no longer reads the decision. diff --git a/irreducibility-pipeline/examples/03_code_review_gate/encodings.json b/irreducibility-pipeline/examples/03_code_review_gate/encodings.json new file mode 100644 index 00000000..00fc0099 --- /dev/null +++ b/irreducibility-pipeline/examples/03_code_review_gate/encodings.json @@ -0,0 +1,119 @@ +{ + "structure": "Code-review gate (stipulated description)", + "source": "prose.md", + "parties": [ + { + "label": "A", + "name": "author", + "active": "change ready" + }, + { + "label": "G", + "name": "CI gate", + "active": "passing" + }, + { + "label": "M", + "name": "maintainer", + "active": "approving" + } + ], + "mediator": "G", + "encodings": [ + { + "id": "gated", + "account": "maintainers wait for CI", + "role": "rival", + "rules": { + "A": "G and M", + "G": "A", + "M": "A and G" + }, + "evidence": { + "A": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "I push a fix when CI fails or when the maintainer asks for changes, and I stop when both are satisfied." + } + ], + "G": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The CI check runs on every push to the change." + } + ], + "M": [ + { + "source": "prose.md", + "locator": "¶3", + "quote": "Maintainers approve only changes whose CI check is green." + } + ] + }, + "alternative": { + "G": { + "rule": "A", + "why": "The gate's rule is the same under both readings; what varies is whether the maintainer reads it (¶5)." + } + }, + "predicted": { + "structure": "triadic", + "core": [ + "A", + "G", + "M" + ], + "reason": "The gate commits a pass/fail neither author nor maintainer sets, and both read it." + } + }, + { + "id": "diff_only", + "account": "maintainers approve on the diff alone", + "role": "rival", + "rules": { + "A": "G and M", + "G": "A", + "M": "A" + }, + "evidence": { + "A": [ + { + "source": "prose.md", + "locator": "¶4", + "quote": "I push a fix when CI fails or when the maintainer asks for changes, and I stop when both are satisfied." + } + ], + "G": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "The CI check runs on every push to the change." + } + ], + "M": [ + { + "source": "prose.md", + "locator": "¶5", + "quote": "On small changes I just read the diff and approve; I don't wait for CI." + } + ] + }, + "alternative": { + "G": { + "rule": "A", + "why": "As above; the gate's own rule does not change." + } + }, + "predicted": { + "structure": "triadic", + "core": [ + "A", + "M" + ], + "reason": "If the maintainer ignores the gate, the author-maintainer pair should carry the coordination." + } + } + ] +} \ No newline at end of file diff --git a/irreducibility-pipeline/examples/03_code_review_gate/prose.md b/irreducibility-pipeline/examples/03_code_review_gate/prose.md new file mode 100644 index 00000000..ee1de409 --- /dev/null +++ b/irreducibility-pipeline/examples/03_code_review_gate/prose.md @@ -0,0 +1,17 @@ +# A code-review gate + +A stipulated description of a software team's merge process. It is not field data. Paragraph numbers +are locators. + +**¶1.** An author opens a change. A continuous-integration gate runs the tests on it. A maintainer +decides whether to approve the merge. + +**¶2.** The repository's branch-protection rule says: "The CI check runs on every push to the change." + +**¶3.** The contributing guide says: "Maintainers approve only changes whose CI check is green." + +**¶4.** Authors revise in response to both: "I push a fix when CI fails or when the maintainer asks +for changes, and I stop when both are satisfied." + +**¶5.** Some maintainers admit: "On small changes I just read the diff and approve; I don't wait for +CI." diff --git a/irreducibility-pipeline/examples/04_dealer_vs_clearinghouse/encodings.json b/irreducibility-pipeline/examples/04_dealer_vs_clearinghouse/encodings.json new file mode 100644 index 00000000..943b2454 --- /dev/null +++ b/irreducibility-pipeline/examples/04_dealer_vs_clearinghouse/encodings.json @@ -0,0 +1,132 @@ +{ + "structure": "Car dealer vs clearinghouse: intrinsic or contingent intermediation (stipulated description)", + "source": "prose.md", + "parties": [ + { + "label": "U", + "name": "upstream party (maker / first counterparty)", + "active": "acting" + }, + { + "label": "I", + "name": "intermediary (dealer / clearinghouse)", + "active": "passing on or settling" + }, + { + "label": "V", + "name": "downstream party (buyer / second counterparty)", + "active": "acting" + } + ], + "mediator": "I", + "encodings": [ + { + "id": "dealer", + "account": "franchised dealer under a ban on direct sales", + "role": "design", + "rules": { + "U": "V", + "I": "U", + "V": "I" + }, + "evidence": { + "U": [ + { + "source": "prose.md", + "locator": "¶1", + "quote": "The maker ships to the dealer; the dealer delivers to the buyer; the maker builds to the dealer's orders, which follow the buyers'." + } + ], + "I": [ + { + "source": "prose.md", + "locator": "¶1", + "quote": "The maker ships to the dealer; the dealer delivers to the buyer; the maker builds to the dealer's orders, which follow the buyers'." + } + ], + "V": [ + { + "source": "prose.md", + "locator": "¶1", + "quote": "The maker ships to the dealer; the dealer delivers to the buyer; the maker builds to the dealer's orders, which follow the buyers'." + } + ] + }, + "alternative": { + "I": { + "rule": "U and V", + "why": "A dealer that also screens buyers would commit a joint determination; ¶1 describes a pass-through." + } + }, + "predicted": { + "structure": "triadic", + "core": [ + "U", + "I", + "V" + ], + "reason": "The closed maker-dealer-buyer ring binds all three while the bypass is forbidden." + }, + "bypass": { + "party": "I", + "downstream": "V", + "upstream": "U", + "mode": "replace" + } + }, + { + "id": "clearinghouse", + "account": "clearinghouse settling two legs", + "role": "design", + "rules": { + "U": "I", + "I": "U and V", + "V": "I" + }, + "evidence": { + "U": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "A trade settles only when both legs are confirmed; each party acts on the clearinghouse's settlement notice." + } + ], + "I": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "A trade settles only when both legs are confirmed; each party acts on the clearinghouse's settlement notice." + } + ], + "V": [ + { + "source": "prose.md", + "locator": "¶2", + "quote": "A trade settles only when both legs are confirmed; each party acts on the clearinghouse's settlement notice." + } + ] + }, + "alternative": { + "I": { + "rule": "U", + "why": "A clearinghouse that settled on one leg would be a relay; ¶2 says both legs." + } + }, + "predicted": { + "structure": "triadic", + "core": [ + "U", + "I", + "V" + ], + "reason": "Settlement needs both legs; no direct tie reproduces the joint condition." + }, + "bypass": { + "party": "I", + "downstream": "V", + "upstream": "U", + "mode": "replace" + } + } + ] +} \ No newline at end of file diff --git a/irreducibility-pipeline/examples/04_dealer_vs_clearinghouse/prose.md b/irreducibility-pipeline/examples/04_dealer_vs_clearinghouse/prose.md new file mode 100644 index 00000000..fa8a207c --- /dev/null +++ b/irreducibility-pipeline/examples/04_dealer_vs_clearinghouse/prose.md @@ -0,0 +1,13 @@ +# A car dealer and a clearinghouse: held in place by law, or by the work it does? + +A stipulated description of two intermediaries. It is not field data. Paragraph numbers are locators. + +**¶1.** A car maker sells to a buyer through a franchised dealer. Franchise law forbids the maker +from selling to the buyer directly. "The maker ships to the dealer; the dealer delivers to the buyer; +the maker builds to the dealer's orders, which follow the buyers'." + +**¶2.** A clearinghouse settles trades between two counterparties. "A trade settles only when both +legs are confirmed; each party acts on the clearinghouse's settlement notice." + +**¶3.** The counterfactual for both: lift the constraint and let the downstream party read the +upstream party directly. "If the law changed, buyers could order from the maker." diff --git a/irreducibility-pipeline/irreducibility/__init__.py b/irreducibility-pipeline/irreducibility/__init__.py new file mode 100644 index 00000000..1b77827f --- /dev/null +++ b/irreducibility-pipeline/irreducibility/__init__.py @@ -0,0 +1,10 @@ +"""irreducibility: exact irreducibility analysis of coordinative structures with PyPhi (IIT 4.0).""" + +from .core import (PHI_EPS, Verdict, classify, classify_rules, cm_from_rules, major_complex, + tpm_from_rules, verdict) +from .regime import regime +from .contingency import contingency_test +from .spread import spread +from .rules import compile_rule, compile_rules + +__version__ = "0.1.0" diff --git a/irreducibility-pipeline/irreducibility/analyze.py b/irreducibility-pipeline/irreducibility/analyze.py new file mode 100644 index 00000000..22e5e571 --- /dev/null +++ b/irreducibility-pipeline/irreducibility/analyze.py @@ -0,0 +1,199 @@ +"""Analyze a coordinative structure: encodings in, an exact irreducibility analysis out. + + python -m irreducibility.analyze examples/01_gig_dispatch/encodings.json + python -m irreducibility.analyze my_structure.json --json out.json + +For each encoding the report gives: + * the TPM and connectivity matrix PyPhi receives; + * Φ over the minimum-information partition in every reachable state, and the MIP at the + most-integrated state; + * the verdict (dyadic or triadic) and the major complex (who is bound); + * the mediator's position (BOTTLENECK, ENRICHER, CAPTURE, BYPASSED); + * whether the mediator's place is intrinsic or contingent on a forbidden bypass, if one is given; + * whether the prediction fixed before computing held. + +Across rival encodings of the same parties it reports the spread (verdict agreement, Φ gap, core +overlap) and the single rules whose swap flips the verdict, i.e. the facts the evidence must +settle. The script refuses to run if the instrument controls fail or the encodings file is +inadmissible. +""" + +import argparse +import json +import sys + +from .core import tpm_from_rules, cm_from_rules, classify_rules, major_complex, PHI_EPS +from .contingency import contingency_test +from .encoding import load, validate, labels_of +from .regime import regime +from .rules import compile_rules +from .spread import spread +from .validate import controls_pass + + +def _fmt_state(state, labels): + return "".join(str(b) for b in state) + " (" + ",".join(f"{l}={b}" for l, b in zip(labels, state)) + ")" + + +def analyze_encoding(doc, enc): + labels = labels_of(doc, enc) + rules = compile_rules(enc["rules"], labels) + tpm, cm = tpm_from_rules(rules), cm_from_rules(rules) + v = classify_rules(rules, labels) + core, core_phi = major_complex(rules, labels) + out = { + "id": enc["id"], + "account": enc.get("account", ""), + "role": enc.get("role", "rival"), + "labels": list(labels), + "rules": {p: enc["rules"][p] for p in labels}, + "tpm_shape": list(tpm.shape), + "cm": cm.tolist(), + "phi_profile": [{"state": "".join(map(str, s)), "phi": round(p, 6)} for s, p in v.phi_profile], + "structure": v.structure, + "max_phi": round(v.max_phi, 6), + "mip_state": "".join(map(str, v.mip_state)) if v.mip_state else None, + "mip_partition": v.mip_partition, + "irreducible_states": f"{v.n_states_irreducible}/{v.n_states_evaluated}", + "core": list(core) if core else [], + "core_phi": round(core_phi, 6) if core else 0.0, + } + med = doc.get("mediator") + if med and med in labels: + out["regime"] = regime(rules, labels, med) + bp = enc.get("bypass") + if bp: + c = contingency_test(rules, labels, bp["party"], downstream=bp["downstream"], + upstream=bp["upstream"], mode=bp.get("mode", "replace")) + out["contingency"] = {"party": c.party, "kind": c.kind, "margin": round(c.margin, 6), + "core_constrained": list(c.core_constrained), + "core_bypass": list(c.core_bypass)} + pred = enc.get("predicted", {}) + out["predicted"] = pred + ok = pred.get("structure") == v.structure + if ok and pred.get("core"): + ok = set(pred["core"]) == set(out["core"]) + out["prediction_held"] = ok + return out, rules + + +def flip_rules(doc, encA, encB): + """Parties whose single-rule swap from A to B flips A's verdict to B's.""" + labels = labels_of(doc, encA) + vA = classify_rules(compile_rules(encA["rules"], labels), labels).structure + vB = classify_rules(compile_rules(encB["rules"], labels), labels).structure + if vA == vB: + return [] + flips = [] + for p in labels: + if encA["rules"][p].replace(" ", "") == encB["rules"][p].replace(" ", ""): + continue + swapped = dict(encA["rules"]) + swapped[p] = encB["rules"][p] + if classify_rules(compile_rules(swapped, labels), labels).structure == vB: + flips.append(f"{p}: {encA['rules'][p]!r} -> {encB['rules'][p]!r}") + return flips + + +def analyze(doc): + results, compiled = [], {} + for enc in doc["encodings"]: + r, rules = analyze_encoding(doc, enc) + results.append(r) + compiled[enc["id"]] = (tuple(r["labels"]), rules, enc) + rivals = [e for e in doc["encodings"] if e.get("role", "rival") == "rival"] + pairs = [] + for i, a in enumerate(rivals): + for b in rivals[i + 1:]: + la, ra, _ = compiled[a["id"]] + lb, rb, _ = compiled[b["id"]] + if la != lb: + continue + s = spread(ra, rb, la) + pairs.append({"pair": [a["id"], b["id"]], + "verdict_agreement": s["verdict_agreement"], + "phi_gap": round(s["phi_gap"], 6), + "core_jaccard": round(s["core_jaccard"], 6), + "verdicts": list(s["both_verdicts"]), + "rules_that_flip_the_verdict": flip_rules(doc, a, b)}) + rival_verdicts = {r["structure"] for r in results if r["role"] == "rival"} + held = sum(r["prediction_held"] for r in results) + if not rival_verdicts: + robust = (f"DESIGN COMPARISON: {len(results)} designs; predictions fixed before computing " + f"held in {held}/{len(results)}") + elif len(rival_verdicts) == 1: + robust = f"ROBUST: every rival encoding reads {rival_verdicts.pop()}" + else: + robust = "CONTESTED: the verdict depends on which encoding the evidence supports" + return {"structure": doc["structure"], "encodings": results, "spread": pairs, "summary": robust} + + +def print_report(rep, doc): + W = 92 + print("=" * W) + print(f"IRREDUCIBILITY ANALYSIS - {rep['structure']}") + print("=" * W) + for r in rep["encodings"]: + print(f"\n[{r['id']}] {r['account']} ({r['role']})") + for p in r["labels"]: + print(f" {p}' = {r['rules'][p]}") + print(f" PyPhi input: TPM {r['tpm_shape'][0]}x{r['tpm_shape'][1]} (state-by-node), " + f"connectivity {r['cm']}") + prof = ", ".join(f"{d['state']}:{d['phi']:.3f}" for d in r["phi_profile"]) + print(f" Φ_MIP by reachable state: {prof}") + print(f" verdict: {r['structure'].upper()} max Φ_MIP = {r['max_phi']:.3f}" + f" ({r['irreducible_states']} states irreducible)") + if r["mip_state"]: + print(f" MIP at state {r['mip_state']}: {r['mip_partition']}") + print(f" major complex (who is bound): {{{', '.join(r['core'])}}}" if r["core"] + else " major complex: none") + if "regime" in r: + print(f" mediator ({doc['mediator']}) position: {r['regime']}") + if "contingency" in r: + c = r["contingency"] + print(f" bypass test on {c['party']}: {c['kind']} (Φ lost when the bypass opens: " + f"{c['margin']:.3f}; core {{{','.join(c['core_constrained'])}}} -> " + f"{{{','.join(c['core_bypass'])}}})") + pred = r["predicted"] + print(f" predicted before computing: {pred.get('structure')}" + + (f", core {{{','.join(pred['core'])}}}" if pred.get("core") else "") + + f" -> {'HELD' if r['prediction_held'] else 'FAILED'}") + if rep["spread"]: + print("\n" + "-" * W) + print("SPREAD ACROSS RIVAL ENCODINGS") + for s in rep["spread"]: + print(f" {s['pair'][0]} vs {s['pair'][1]}: verdicts {s['verdicts'][0]}/{s['verdicts'][1]}, " + f"Φ gap {s['phi_gap']:.3f}, core overlap {s['core_jaccard']:.3f}") + for f in s["rules_that_flip_the_verdict"]: + print(f" single rule that flips it: {f}") + print("\n" + "=" * W) + print(f" {rep['summary']}") + print("=" * W) + + +def main(argv=None) -> int: + ap = argparse.ArgumentParser(description=__doc__.splitlines()[0]) + ap.add_argument("encodings", help="path to an encodings JSON file") + ap.add_argument("--json", help="also write the full report as JSON to this path") + args = ap.parse_args(argv) + + if not controls_pass(): + print("INSTRUMENT CONTROLS FAILED - refusing to analyze. Run python -m irreducibility.validate") + return 1 + doc = load(args.encodings) + problems = validate(doc) + if problems: + print("ENCODINGS FILE IS NOT ADMISSIBLE:") + for p in problems: + print(" - " + p) + return 2 + rep = analyze(doc) + print_report(rep, doc) + if args.json: + with open(args.json, "w", encoding="utf-8") as f: + json.dump(rep, f, indent=2, ensure_ascii=False) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/irreducibility-pipeline/irreducibility/contingency.py b/irreducibility-pipeline/irreducibility/contingency.py new file mode 100644 index 00000000..29386b61 --- /dev/null +++ b/irreducibility-pipeline/irreducibility/contingency.py @@ -0,0 +1,112 @@ +"""Contingent vs. intrinsic irreducibility — the bypass-counterfactual classifier. + +A party can sit in a triad's irreducible core for two different reasons. + +INTRINSIC: it does integrative work no direct edge between its neighbours reproduces, so it +stays in the core even when that forbidden edge is restored. A conjunctive mediator S=W&C is +the type case — handing C a direct line to W does not let the pair recover the joint condition +S computes. + +CONTINGENT: it is a conduit that would factor out, held in the core only because the bypass +edge is forbidden. Restore the edge and it leaves. A car dealer relays a car from maker to +buyer and does no integrating; it sits in the core only because franchise law forbids the maker +selling direct. Lift the law and the dealer is disintermediated. + +A constitutive result of the lab says a conduit factors. Contingent +irreducibility is the exception that law does not cover: a conduit that does not factor, because a +constraint removes the alternative to it. +The test restores the forbidden bypass edge and recomputes the major complex: + + party in core, leaves under bypass -> contingent (de jure: held by the constraint) + party in core, stays, margin ~ 0 -> intrinsic (de facto: held by its own role) + party in core, stays, 0 < margin -> partial (part role, part constraint) + party not in core -> reducible (a free conduit, already out) + +The contingency margin is the whole-system Phi_MIP lost when the bypass opens. +""" + +from dataclasses import dataclass + +from .core import verdict, major_complex +from .core import PHI_EPS + + +@dataclass +class ContingencyResult: + party: str + kind: str # "intrinsic" | "contingent" | "partial" | "reducible" + in_core_constrained: bool + in_core_bypass: bool + phi_constrained: float + phi_bypass: float + margin: float + core_constrained: tuple + core_bypass: tuple + + def line(self): + return ("%-10s margin=%.3f %s in core: constrained=%s bypass=%s (Phi %.3f -> %.3f)" + % (self.kind, self.margin, self.party, + self.in_core_constrained, self.in_core_bypass, + self.phi_constrained, self.phi_bypass)) + + +def add_bypass(rules, labels, downstream, upstream, mode="replace"): + """Return a rule set with the forbidden direct edge restored on `downstream`. + + mode="replace": downstream reads upstream INSTEAD of its mediated source — the maker sells + direct and the mediator is disintermediated (the franchise-law counterfactual). + mode="add": downstream reads upstream IN ADDITION — a parallel back-channel is opened, + downstream' = original OR upstream. + """ + labels = tuple(labels) + di = labels.index(downstream) + ui = labels.index(upstream) + new = list(rules) + orig = rules[di] + if mode == "replace": + new[di] = lambda x, ui=ui: x[ui] + elif mode == "add": + new[di] = lambda x, orig=orig, ui=ui: orig(x) | x[ui] + else: + raise ValueError("mode must be 'replace' or 'add', got %r" % mode) + return new + + +def contingency_test(rules, labels, party, downstream=None, upstream=None, + mode="replace", bypass_rules=None): + """Classify `party`'s irreducibility via the bypass-counterfactual. + + rules / labels : the constrained system, with the bypass edge forbidden. + party : the mediator / broker label to classify. + downstream, upstream, mode : how to restore the forbidden direct edge (see add_bypass). + bypass_rules : pass an explicit bypass rule set to override the downstream/upstream form. + + Returns a ContingencyResult. The margin is whole-system Phi_MIP lost when the bypass opens. + """ + labels = tuple(labels) + if bypass_rules is None: + if downstream is None or upstream is None: + raise ValueError("supply downstream and upstream, or bypass_rules") + bypass_rules = add_bypass(rules, labels, downstream, upstream, mode) + + vc = verdict(rules, labels) + cc, _ = major_complex(rules, labels) + vb = verdict(bypass_rules, labels) + cb, _ = major_complex(bypass_rules, labels) + + in_c = party in cc + in_b = party in cb + margin = vc.max_phi - vb.max_phi + + if not in_c: + kind = "reducible" + elif not in_b: + kind = "contingent" + elif margin > PHI_EPS: + kind = "partial" + else: + kind = "intrinsic" + + return ContingencyResult(party, kind, in_c, in_b, + float(vc.max_phi), float(vb.max_phi), float(margin), + tuple(cc), tuple(cb)) diff --git a/irreducibility-pipeline/irreducibility/core.py b/irreducibility-pipeline/irreducibility/core.py new file mode 100644 index 00000000..47f82e17 --- /dev/null +++ b/irreducibility-pipeline/irreducibility/core.py @@ -0,0 +1,233 @@ +"""Exact irreducibility of a coordinative structure, computed with PyPhi (IIT 4.0). + +A coordinative structure is modelled as a small deterministic Boolean network. Each node is a +party (a worker, a platform, a counterpart, an agent, a manager). Each party's next state is a +fixed Boolean function of the current states of the parties it reads. + +From those rules this module builds the state-by-node transition probability matrix (TPM) and the +connectivity matrix, and asks PyPhi's IIT-4.0 implementation (``pyphi.new_big_phi``) two questions: + +1. **Is the structure irreducible?** For every reachable state, ``new_big_phi.sia`` returns system + integrated information Φ over the minimum-information partition (MIP), the directional cut that + damages the cause-effect structure least. If Φ_MIP = 0 in every reachable state, some cut along + party lines leaves the structure intact: it is **dyadic** (it factors). If Φ_MIP > 0 in at least + one reachable state, no cut does: it is **triadic** (irreducible). +2. **Who is bound?** ``new_big_phi.maximal_complex`` returns the major complex, the subset of + parties that forms the maximally irreducible core. + +Only the binary verdict and the core membership are interpreted. Φ magnitude depends on the +encoding and is read as at most an ordinal hint. + +Run the instrument controls before trusting any verdict: ``python -m irreducibility.validate`` + +Provenance: consolidated from the lab's classifier (``classifier.py``), exact-Φ oracle +(``exact_phi.py``) and probe helpers (``lib.py``); behaviour unchanged. +""" + +import os +from dataclasses import dataclass, field +from typing import Callable, Optional, Sequence + +os.environ.setdefault("PYPHI_WELCOME_OFF", "true") + +import numpy as np +import pyphi +from pyphi import convert, exceptions, new_big_phi + +pyphi.config.PROGRESS_BARS = False +pyphi.config.PARALLEL = False + +# Φ below this is treated as zero (floating-point and PyPhi numerical noise). +PHI_EPS = 1e-9 + +DEFAULT_LABELS = ("W", "S", "C") # worker, system/mediator, counterpart + + +# --------------------------------------------------------------------------------------------- +# Rules -> transition matrix and connectivity matrix +# --------------------------------------------------------------------------------------------- + +def tpm_from_rules(rules: Sequence[Callable], n: Optional[int] = None) -> np.ndarray: + """Deterministic state-by-node TPM of shape (2^n, n) from per-node Boolean rules. + + ``rules[j]`` maps the current state tuple (little-endian: index 0 = first party) to node j's + next value in {0, 1}. Little-endian indexing matches PyPhi. + """ + n = len(rules) if n is None else n + tpm = np.zeros((2 ** n, n)) + for s in range(2 ** n): + cur = tuple((s >> i) & 1 for i in range(n)) + for j in range(n): + tpm[s, j] = float(rules[j](cur)) + return tpm + + +def cm_from_rules(rules: Sequence[Callable], n: Optional[int] = None) -> np.ndarray: + """Connectivity matrix: cm[i, j] = 1 iff node j's rule depends on node i (flip test).""" + n = len(rules) if n is None else n + cm = np.zeros((n, n), dtype=int) + for j in range(n): + for i in range(n): + for s in range(2 ** n): + cur = list((s >> k) & 1 for k in range(n)) + flipped = cur.copy() + flipped[i] ^= 1 + if rules[j](tuple(cur)) != rules[j](tuple(flipped)): + cm[i, j] = 1 + break + return cm + + +def reachable_states(tpm_sbn: np.ndarray, n: int): + """Decimal indices of states with at least one predecessor (the states PyPhi will analyze).""" + sbs = convert.state_by_node2state_by_state(tpm_sbn) + incoming = sbs.sum(axis=0) + return [j for j in range(2 ** n) if incoming[j] > 1e-12] + + +def simulate_trajectory(tpm_sbn, n, timesteps, rng): + """Simulate a binary trajectory (timesteps x n) from a random initial state. Used by the proxy study.""" + from pyphi import tpm as tpmmod + sbs = convert.state_by_node2state_by_state(tpm_sbn) + initial = int(rng.integers(0, 2 ** n)) + path = tpmmod.simulate(sbs, initial, timesteps, rng) + return np.array([[(idx >> i) & 1 for i in range(n)] for idx in path]).astype(int) + + +def exact_big_phi(tpm_sbn: np.ndarray, cm: np.ndarray, state) -> Optional[float]: + """Exact IIT-4.0 system Φ over the MIP in ``state``; None if the state is unreachable.""" + network = pyphi.Network(tpm_sbn, cm=cm) + try: + subsystem = pyphi.Subsystem(network, tuple(state)) + except exceptions.StateUnreachableError: + return None + return float(new_big_phi.sia(subsystem).phi) + + +def network_phi(tpm_sbn, cm, n, rng, max_states=16): + """Mean and max of exact Φ over reachable states (negative values clamped to 0). + + Returns (mean_phi, max_phi, n_evaluated). Used by the proxy study. + """ + network = pyphi.Network(tpm_sbn, cm=cm) + states = reachable_states(tpm_sbn, n) + if len(states) > max_states: + idx = rng.choice(len(states), size=max_states, replace=False) + states = [states[i] for i in idx] + phis = [] + for s in states: + state = tuple((s >> i) & 1 for i in range(n)) + try: + subsystem = pyphi.Subsystem(network, state) + except exceptions.StateUnreachableError: + continue + phis.append(max(0.0, float(new_big_phi.sia(subsystem).phi))) + if not phis: + return 0.0, 0.0, 0 + return float(np.mean(phis)), float(np.max(phis)), len(phis) + + +# --------------------------------------------------------------------------------------------- +# The verdict +# --------------------------------------------------------------------------------------------- + +@dataclass +class Verdict: + """The verdict for one encoding of a coordinative structure.""" + structure: str # "dyadic" or "triadic" + max_phi: float # max Φ_MIP over reachable states + mip_state: Optional[tuple] # the state achieving max_phi (triadic only) + mip_partition: str # the minimum-information partition at that state + n_states_evaluated: int + n_states_irreducible: int # reachable states with Φ_MIP > PHI_EPS + phi_profile: list = field(default_factory=list) # [(state, phi), ...] + labels: tuple = DEFAULT_LABELS + + @property + def competence(self) -> str: + """The competence the structure demands: literacy (dyadic) or algorithmacy (triadic).""" + return "algorithmacy" if self.structure == "triadic" else "literacy" + + def __str__(self) -> str: + head = (f"{self.structure.upper():>9} (max Φ_MIP = {self.max_phi:.6f} over " + f"{self.n_states_evaluated} reachable states; {self.n_states_irreducible} irreducible)") + if self.mip_state is not None: + head += f"\n max-Φ state {self.mip_state}, MIP cut: {self.mip_partition}" + return head + + +def phi_profile(tpm_sbn: np.ndarray, cm: np.ndarray, n: Optional[int] = None): + """Exact IIT-4.0 Φ_MIP for each reachable state: [(state_tuple, phi), ...].""" + n = cm.shape[0] if n is None else n + out = [] + for s in reachable_states(tpm_sbn, n): + state = tuple((s >> i) & 1 for i in range(n)) + phi = exact_big_phi(tpm_sbn, cm, state) + if phi is not None: + out.append((state, float(phi))) + return out + + +def _mip_partition_repr(tpm_sbn, cm, state, labels) -> str: + try: + net = pyphi.Network(tpm_sbn, cm=cm, node_labels=labels[:cm.shape[0]]) + sub = pyphi.Subsystem(net, tuple(state)) + return str(new_big_phi.sia(sub).partition).splitlines()[0].strip() + except Exception as e: # informational only + return f"(unavailable: {e})" + + +def classify(tpm_sbn: np.ndarray, cm: np.ndarray, + labels: Sequence[str] = DEFAULT_LABELS, eps: float = PHI_EPS) -> Verdict: + """Triadic iff Φ_MIP > eps in at least one reachable state; read at the most-integrated state.""" + n = cm.shape[0] + profile = phi_profile(tpm_sbn, cm, n) + if not profile: + return Verdict("dyadic", 0.0, None, "(no reachable states)", 0, 0, [], tuple(labels[:n])) + max_state, max_phi = max(profile, key=lambda r: r[1]) + n_irreducible = sum(1 for _, p in profile if p > eps) + triadic = max_phi > eps + mip = _mip_partition_repr(tpm_sbn, cm, max_state, tuple(labels)) if triadic else "(factors)" + return Verdict( + structure="triadic" if triadic else "dyadic", + max_phi=max_phi, + mip_state=max_state if triadic else None, + mip_partition=mip, + n_states_evaluated=len(profile), + n_states_irreducible=n_irreducible, + phi_profile=profile, + labels=tuple(labels[:n]), + ) + + +def classify_rules(rules: Sequence[Callable], labels: Sequence[str] = DEFAULT_LABELS, + eps: float = PHI_EPS) -> Verdict: + """Classify a structure given per-party Boolean rules.""" + return classify(tpm_from_rules(rules), cm_from_rules(rules), labels=labels, eps=eps) + + +def verdict(rules, labels): + """Whole-system verdict (alias used throughout the studies).""" + return classify_rules(rules, labels=labels) + + +def major_complex(rules, labels): + """(core_label_tuple, phi) of the major complex, maximised over reachable states. + + Returns (None, -1.0) if no state has an irreducible complex. + """ + n = len(rules) + tpm, cm = tpm_from_rules(rules), cm_from_rules(rules) + net = pyphi.Network(tpm, cm=cm, node_labels=tuple(labels)) + best = (None, -1.0) + for s in reachable_states(tpm, n): + state = tuple((s >> i) & 1 for i in range(n)) + try: + mc = new_big_phi.maximal_complex(net, state) + except (exceptions.StateUnreachableError, ValueError): + continue + if isinstance(mc, new_big_phi.NullPhiStructure): + continue + if float(mc.phi) > best[1]: + best = (tuple(labels[i] for i in mc.node_indices), float(mc.phi)) + return best diff --git a/irreducibility-pipeline/irreducibility/encode_check.py b/irreducibility-pipeline/irreducibility/encode_check.py new file mode 100644 index 00000000..56d23ba7 --- /dev/null +++ b/irreducibility-pipeline/irreducibility/encode_check.py @@ -0,0 +1,69 @@ +"""Check an encodings file before anything is computed. + + python -m irreducibility.encode_check examples/01_gig_dispatch/encodings.json + +Three gates, in order: + 1. admissibility: every rule parses, cites evidence, the mediator names an alternative, and every + encoding carries a prediction (irreducibility.encoding.validate); + 2. evidence is real: every quoted passage occurs verbatim in the cited source file (resolved + relative to the encodings file), so a drafter, human or model, cannot cite a passage that is not + there; + 3. nothing else: this script never computes Φ, so a prediction cannot be adjusted after seeing it. + +Exit code 0 if all gates pass. +""" + +import os +import re +import sys + +from .encoding import load, validate + + +def _norm(s: str) -> str: + return re.sub(r"\s+", " ", s.replace("’", "'").replace("“", '"').replace("”", '"')).strip() + + +def check_quotes(doc: dict, base_dir: str): + problems, cache = [], {} + for enc in doc.get("encodings", []): + for party, items in enc.get("evidence", {}).items(): + for item in items: + src = item.get("source", "") + path = os.path.join(base_dir, src) + if path not in cache: + try: + with open(path, encoding="utf-8") as f: + cache[path] = _norm(f.read()) + except OSError: + cache[path] = None + text = cache[path] + if text is None: + problems.append(f"[{enc.get('id')}] {party}: source {src!r} not found") + elif _norm(item.get("quote", "")) not in text: + problems.append(f"[{enc.get('id')}] {party}: quote not found verbatim in {src}: " + f"{item.get('quote', '')[:70]!r}") + return problems + + +def main(argv=None) -> int: + argv = sys.argv[1:] if argv is None else argv + if len(argv) != 1: + print(__doc__) + return 2 + path = argv[0] + doc = load(path) + problems = validate(doc) + check_quotes(doc, os.path.dirname(os.path.abspath(path))) + n = len(doc.get("encodings", [])) + if problems: + print(f"REJECTED: {len(problems)} problem(s) in {n} encoding(s)") + for p in problems: + print(" - " + p) + return 1 + print(f"ADMISSIBLE: {n} encoding(s); every rule has evidence found verbatim in its source; " + f"every encoding carries a prediction.") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/irreducibility-pipeline/irreducibility/encoding.py b/irreducibility-pipeline/irreducibility/encoding.py new file mode 100644 index 00000000..0efced38 --- /dev/null +++ b/irreducibility-pipeline/irreducibility/encoding.py @@ -0,0 +1,86 @@ +"""Load and validate an encodings file: one coordinative structure, several rival encodings. + +The file format is specified in ``encode/SCHEMA.json``. An encoding is admissible only if + + * every party has a rule, written as a Boolean expression over party names; + * every rule cites evidence (a source, a locator, and the quoted passage it rests on); + * the mediator's rule names the alternative reading the evidence does not rule out; + * the predicted verdict and its reason are stated before anything is computed. + +These checks are what make the encoding step auditable, whether a person or a language model +drafted the encoding. ``validate_file`` returns a list of problems; an empty list means admissible. +""" + +import json +from typing import List + +from .rules import compile_rule + +STRUCTURES = ("dyadic", "triadic") + + +def load(path: str) -> dict: + with open(path, encoding="utf-8") as f: + return json.load(f) + + +def labels_of(doc: dict, enc: dict) -> tuple: + """An encoding may override the structure's party list (e.g. pooled drivers D1, D2).""" + if enc.get("labels"): + return tuple(enc["labels"]) + return tuple(p["label"] for p in doc["parties"]) + + +def validate(doc: dict) -> List[str]: + problems = [] + for key in ("structure", "parties", "encodings"): + if key not in doc: + problems.append(f"missing top-level field {key!r}") + if problems: + return problems + mediator = doc.get("mediator") + seen = set() + for enc in doc["encodings"]: + eid = enc.get("id", "?") + if eid in seen: + problems.append(f"[{eid}] duplicate encoding id") + seen.add(eid) + labels = labels_of(doc, enc) + rules = enc.get("rules", {}) + for p in labels: + if p not in rules: + problems.append(f"[{eid}] no rule for party {p}") + continue + try: + compile_rule(rules[p], labels) + except (ValueError, SyntaxError) as e: + problems.append(f"[{eid}] {e}") + ev = enc.get("evidence", {}).get(p, []) + if not ev: + problems.append(f"[{eid}] rule for {p} cites no evidence") + for item in ev: + for k in ("source", "locator", "quote"): + if not str(item.get(k, "")).strip(): + problems.append(f"[{eid}] evidence for {p} lacks {k!r}") + if mediator and mediator in labels: + alt = enc.get("alternative", {}).get(mediator) + if not alt or not str(alt.get("rule", "")).strip() or not str(alt.get("why", "")).strip(): + problems.append(f"[{eid}] the mediator's rule ({mediator}) names no alternative reading") + else: + try: + compile_rule(alt["rule"], labels) + except (ValueError, SyntaxError) as e: + problems.append(f"[{eid}] alternative: {e}") + pred = enc.get("predicted", {}) + if pred.get("structure") not in STRUCTURES or not str(pred.get("reason", "")).strip(): + problems.append(f"[{eid}] no predicted verdict and reason (fix the prediction before computing)") + bp = enc.get("bypass") + if bp: + for k in ("party", "downstream", "upstream"): + if bp.get(k) not in labels: + problems.append(f"[{eid}] bypass {k} {bp.get(k)!r} is not a party") + return problems + + +def validate_file(path: str) -> List[str]: + return validate(load(path)) diff --git a/irreducibility-pipeline/irreducibility/regime.py b/irreducibility-pipeline/irreducibility/regime.py new file mode 100644 index 00000000..cdfa0b11 --- /dev/null +++ b/irreducibility-pipeline/irreducibility/regime.py @@ -0,0 +1,54 @@ +"""The mediator's position in the irreducible core. + +Once a structure reads triadic, the next strategic question is what the mediating system (the +platform, the engine, the manager) is doing in it. The lesion test and the major complex answer it: + + dyadic the structure factors; there is no irreducible core to hold a position in + BYPASSED triadic, but the mediator is outside the core: the parties out-integrate it + CAPTURE the mediator is in the core, but the core excludes some party: the mediator and + part of the arrangement bind each other and leave the rest outside + BOTTLENECK every party is in the core, and freezing the mediator stops the others from + coordinating: the structure runs through it + ENRICHER every party is in the core, and the others still coordinate with the mediator + frozen: it adds to a coordination that would exist without it + +The same mediator can hold each position depending on the parties' other ties and options. +Whether a platform is a bottleneck is a property of the whole arrangement, not of the platform. + +Provenance: generalised from the lab's mediator-in-core and enricher-regime threads; on +three-party forms it reproduces their five-way classification exactly. +""" + +from .core import classify_rules, major_complex + +REGIMES = ("dyadic", "BYPASSED", "CAPTURE", "BOTTLENECK", "ENRICHER") + + +def lesion_survives(rules, labels, mi): + """Do the non-mediator parties still coordinate (triadic) with the mediator frozen at 0 or 1?""" + rest = [i for i in range(len(labels)) if i != mi] + if len(rest) < 2: + return False + for c in (0, 1): + reduced = [(lambda y, _j=j, _c=c: rules[_j]( + tuple(_c if k == mi else y[rest.index(k)] for k in range(len(labels))))) + for j in rest] + if classify_rules(reduced, tuple(labels[i] for i in rest)).structure == "triadic": + return True + return False + + +def regime(rules, labels, mediator): + """Five-way regime of the party named ``mediator`` (a label) or at index ``mediator``.""" + labels = tuple(labels) + mi = labels.index(mediator) if isinstance(mediator, str) else int(mediator) + v = classify_rules(rules, labels) + if v.structure == "dyadic": + return "dyadic" + core, _ = major_complex(list(rules), labels) + core = set(core or ()) + if labels[mi] not in core: + return "BYPASSED" + if core != set(labels): + return "CAPTURE" + return "ENRICHER" if lesion_survives(rules, labels, mi) else "BOTTLENECK" diff --git a/irreducibility-pipeline/irreducibility/rule_to_phi.py b/irreducibility-pipeline/irreducibility/rule_to_phi.py new file mode 100644 index 00000000..b8227338 --- /dev/null +++ b/irreducibility-pipeline/irreducibility/rule_to_phi.py @@ -0,0 +1,187 @@ +"""Bridge: coded determination rules -> TPM -> exact-Φ verdict -> coder-disagreement Φ CI. + +A coded account of a coordination names, for each party, a Boolean determination rule: the +party's next state as a function of the current states of all parties. The rules are encoded +into a deterministic state-by-node TPM, classified by exact IIT-4.0 Φ over the MIP, and read as +a structural verdict (dyadic -> literacy, triadic -> algorithmacy). Φ is not reimplemented; this +module wraps `irreducibility.core`. + +Coding is done by people, and people disagree. Each coder supplies their own reading of the same +account: a per-party rule set. Two coders who read the account identically agree perfectly; two +who disagree on which bits or states are active produce different rule sets and so different Φ +readings. This module propagates that disagreement into a Φ confidence interval by bootstrapping +over the coders, weighting the resample by Krippendorff-alpha agreement, and reporting the +percentile CI of the resulting Φ distribution. + +The construct: a single coded account yields not one Φ but a Φ interval whose width reflects how +much the coders disagree. Perfect agreement collapses the interval to a point. + +Validation controls (run the probe): + - decoupled rule set reads dyadic; + - fully-coupled (faithful triad) rule set reads triadic with max Φ_MIP = 2.0; + - perfect agreement (alpha = 1) returns a degenerate CI [phi, phi]. + +All inputs are synthetic coded rule sets, not measured worker states. +""" + +import os +import sys +from typing import Callable, Dict, List, Optional, Sequence, Tuple + +os.environ.setdefault("PYPHI_WELCOME_OFF", "true") + +import numpy as np + +from .core import classify_rules, PHI_EPS +from .core import verdict + +DEFAULT_LABELS = ("W", "S", "C") + + +# -------------------------------------------------------------------------------------- +# Rules -> TPM -> verdict (the deterministic core) +# -------------------------------------------------------------------------------------- + +def rule_to_phi(rules: Sequence[Callable], + labels: Sequence[str] = DEFAULT_LABELS) -> Dict: + """Encode coded determination rules into a TPM and read the exact-Φ verdict. + + Returns {structure, competence, max_phi, n_irreducible}. Wraps the classifier's + `classify_rules`; the TPM is built by `tpm_from_rules` inside it. Deterministic. + """ + v = classify_rules(rules, labels=labels) + return { + "structure": v.structure, + "competence": v.competence, + "max_phi": float(v.max_phi), + "n_irreducible": int(v.n_states_irreducible), + } + + +# -------------------------------------------------------------------------------------- +# Coder disagreement and Krippendorff alpha +# -------------------------------------------------------------------------------------- + +def krippendorff_alpha(codings: np.ndarray) -> float: + """Krippendorff's alpha for nominal data on a (n_coders, n_items) integer matrix. + + Each column is one coding unit (e.g. one active-bit decision); each row is a coder's + label for every unit. Returns 1.0 for perfect agreement, 0.0 for chance-level agreement, + and may go negative for systematic disagreement. NaN-free for fully coded matrices. + """ + codings = np.asarray(codings) + n_coders, n_items = codings.shape + if n_coders < 2: + return 1.0 + # Observed disagreement: mean over items of the fraction of disagreeing coder pairs. + do_terms = [] + for j in range(n_items): + col = codings[:, j] + pairs = 0 + disagree = 0 + for a in range(n_coders): + for b in range(a + 1, n_coders): + pairs += 1 + if col[a] != col[b]: + disagree += 1 + if pairs: + do_terms.append(disagree / pairs) + do = float(np.mean(do_terms)) if do_terms else 0.0 + # Expected disagreement: probability two values drawn at random (over the whole pooled + # set of labels) differ. + flat = codings.reshape(-1) + vals, counts = np.unique(flat, return_counts=True) + total = counts.sum() + p = counts / total + de = float(1.0 - np.sum(p ** 2)) + if de < 1e-12: + # No variance in the pooled labels: everyone used one value -> perfect agreement. + return 1.0 + return float(1.0 - do / de) + + +# -------------------------------------------------------------------------------------- +# Coder-weighted Φ confidence interval +# -------------------------------------------------------------------------------------- + +def _phi_of(rules: Sequence[Callable], labels: Sequence[str]) -> float: + return float(verdict(rules, labels).max_phi) + + +def phi_ci(coder_phis: Sequence[float], + coder_codings: Optional[np.ndarray] = None, + n_boot: int = 800, + ci: float = 0.95, + rng: Optional[np.random.Generator] = None) -> Dict: + """Φ confidence interval propagated from coder disagreement. + + `coder_phis[k]` is coder k's max-Φ_MIP reading of one account (obtained by running that + coder's rule-set through `rule_to_phi`; see `phi_ci_from_rules` for the rule-set entry + point). The CI is a studentized bootstrap-t interval over the coder panel: it resamples + coders with replacement, studentizes each resample by its own standard error, and inverts + the bootstrap distribution of the t-statistic. The bootstrap-t is calibrated at small coder + counts where the plain percentile bootstrap under-covers. + + `coder_codings`, when given, is a (n_coders, n_units) integer matrix of active-bit + decisions; its Krippendorff alpha is reported. Perfect agreement (alpha = 1, all readings + identical) returns the degenerate CI [phi, phi]. + + Returns {phi_point, ci_low, ci_high, alpha, coder_phis, degenerate}. `phi_point` is the mean + of the per-coder Φ readings (the consensus point estimate). + """ + if rng is None: + rng = np.random.default_rng(0) + coder_phis = np.asarray(coder_phis, dtype=float) + n_coders = len(coder_phis) + + if coder_codings is not None: + alpha = krippendorff_alpha(coder_codings) + else: + alpha = 1.0 if np.allclose(coder_phis, coder_phis[0], atol=PHI_EPS) else 0.0 + + point = float(np.mean(coder_phis)) + se = float(np.std(coder_phis, ddof=1) / np.sqrt(n_coders)) if n_coders > 1 else 0.0 + + # Degenerate: one coder, perfect agreement on identical readings, or zero spread. + if (n_coders < 2 or se < PHI_EPS + or (alpha >= 1.0 - 1e-9 and np.allclose(coder_phis, coder_phis[0], atol=PHI_EPS))): + return { + "phi_point": point, + "ci_low": point, + "ci_high": point, + "alpha": float(alpha), + "coder_phis": coder_phis.tolist(), + "degenerate": True, + } + + a = (1.0 - ci) / 2.0 + tstars = np.empty(n_boot, dtype=float) + for b in range(n_boot): + idx = rng.integers(0, n_coders, size=n_coders) + bs = coder_phis[idx] + bse = float(np.std(bs, ddof=1) / np.sqrt(n_coders)) + tstars[b] = (float(np.mean(bs)) - point) / bse if bse > PHI_EPS else 0.0 + t_lo = float(np.quantile(tstars, a)) + t_hi = float(np.quantile(tstars, 1.0 - a)) + lo = point - t_hi * se + hi = point - t_lo * se + return { + "phi_point": point, + "ci_low": lo, + "ci_high": hi, + "alpha": float(alpha), + "coder_phis": coder_phis.tolist(), + "degenerate": False, + } + + +def phi_ci_from_rules(coder_rule_sets: Sequence[Sequence[Callable]], + labels: Sequence[str] = DEFAULT_LABELS, + coder_codings: Optional[np.ndarray] = None, + n_boot: int = 800, + ci: float = 0.95, + rng: Optional[np.random.Generator] = None) -> Dict: + """`phi_ci` entry point that takes per-coder rule sets, reads each to its max Φ_MIP via the + classifier, then propagates the disagreement. Φ is not reimplemented.""" + coder_phis = [_phi_of(r, labels) for r in coder_rule_sets] + return phi_ci(coder_phis, coder_codings=coder_codings, n_boot=n_boot, ci=ci, rng=rng) diff --git a/irreducibility-pipeline/irreducibility/rules.py b/irreducibility-pipeline/irreducibility/rules.py new file mode 100644 index 00000000..1562b2b0 --- /dev/null +++ b/irreducibility-pipeline/irreducibility/rules.py @@ -0,0 +1,63 @@ +"""Parse a party's rule, written as a Boolean expression over party names, into a callable. + +An encoding states each party's next state in plain logic: + + "S": "D and R" the platform commits only when the driver and the rider are both in + "D": "S" the driver acts on the platform's signal + "C": "E and not A" the claimant is paid when the engine approves and no adjuster flags + "P": "(D1 or D2) and R" any available driver will do + +Allowed: party names, 0, 1, and, or, not, xor, parentheses. Anything else is rejected, so an +encoding cannot run arbitrary code. +""" + +import ast +from typing import Callable, Sequence + +_ALLOWED = (ast.Expression, ast.BoolOp, ast.And, ast.Or, ast.UnaryOp, ast.Not, + ast.BinOp, ast.BitXor, ast.Name, ast.Load, ast.Constant) + + +def _rewrite_xor(expr: str) -> str: + return " ^ ".join(part for part in expr.replace(" XOR ", " xor ").split(" xor ")) + + +def compile_rule(expr: str, labels: Sequence[str]) -> Callable: + """Compile one expression into ``f(state_tuple) -> 0/1`` with labels in rule order.""" + labels = tuple(labels) + tree = ast.parse(_rewrite_xor(expr.strip()), mode="eval") + for node in ast.walk(tree): + if not isinstance(node, _ALLOWED): + raise ValueError(f"rule {expr!r}: {type(node).__name__} is not allowed") + if isinstance(node, ast.Name) and node.id not in labels: + raise ValueError(f"rule {expr!r}: unknown party {node.id!r} (parties: {labels})") + if isinstance(node, ast.Constant) and node.value not in (0, 1, True, False): + raise ValueError(f"rule {expr!r}: only 0 and 1 are allowed as constants") + + def ev(node, x): + if isinstance(node, ast.Expression): + return ev(node.body, x) + if isinstance(node, ast.BoolOp): + vals = [ev(v, x) for v in node.values] + return int(all(vals)) if isinstance(node.op, ast.And) else int(any(vals)) + if isinstance(node, ast.UnaryOp): + return 1 - ev(node.operand, x) + if isinstance(node, ast.BinOp): + return ev(node.left, x) ^ ev(node.right, x) + if isinstance(node, ast.Name): + return int(x[labels.index(node.id)]) + return int(node.value) + + def rule(x, _t=tree): + return ev(_t, x) + + rule.expr = expr + return rule + + +def compile_rules(rules: dict, labels: Sequence[str]): + """Compile {party: expression} into a rule list in label order.""" + missing = [p for p in labels if p not in rules] + if missing: + raise ValueError(f"no rule for {missing}") + return [compile_rule(rules[p], labels) for p in labels] diff --git a/irreducibility-pipeline/irreducibility/spread.py b/irreducibility-pipeline/irreducibility/spread.py new file mode 100644 index 00000000..da365a32 --- /dev/null +++ b/irreducibility-pipeline/irreducibility/spread.py @@ -0,0 +1,180 @@ +"""Spread: two accounts of one coordination, scored as a Φ spread. + +A coordination has two parties who each give an account of how it works. Each account is a +rule set over the same labelled nodes (a small Boolean dynamical system). The two accounts can +diverge: the parties disagree about who responds to whom. This module takes the two accounts, +runs each through the exact-Φ classifier, and reports a SPREAD tuple that quantifies how far +apart the two verdicts sit. + +The spread has three components: + + verdict_agreement in {0, 1} 1 iff both accounts read the same structure (both dyadic or + both triadic). + phi_gap >= 0.0 absolute difference of the two whole-system max Φ_MIP values. + core_jaccard in [0, 1] Jaccard overlap of the two major-complex cores (each taken at + its most-integrated reachable state); 1.0 means the two + accounts put exactly the same parties in the core, 0.0 means + disjoint cores. + +The anchors: when the two accounts are the same rule set, verdict_agreement = 1, phi_gap = 0.0, +and core_jaccard = 1.0. The spread is symmetric in the two parties: swapping which account is A +and which is B leaves all three components unchanged. + +This is a synthetic instrument. The accounts are coder-supplied rule sets, not measured worker +states. The construct it scores is divergence between two stated accounts, validated here on +controls; it is not a measurement of a real coordination. + +Provenance: the lab's disagreement bridge; it does not reimplement Φ. +""" + +import os + +os.environ.setdefault("PYPHI_WELCOME_OFF", "true") + +from typing import Callable, Sequence + +from .core import tpm_from_rules, cm_from_rules +from .core import verdict, major_complex + + +def _core_set(rules: Sequence[Callable], labels: Sequence[str]) -> frozenset: + """The party set of the major complex (max-Φ over reachable states), as a frozenset.""" + core, _ = major_complex(list(rules), tuple(labels)) + return frozenset() if core is None else frozenset(core) + + +def _jaccard(a: frozenset, b: frozenset) -> float: + """Jaccard overlap of two party sets. Two empty cores count as full agreement (1.0).""" + if not a and not b: + return 1.0 + union = a | b + if not union: + return 1.0 + return len(a & b) / len(union) + + +def spread(accountA_rules: Sequence[Callable], + accountB_rules: Sequence[Callable], + labels: Sequence[str]) -> dict: + """Score the divergence between two party accounts of one coordination. + + ``accountA_rules`` and ``accountB_rules`` are per-node Boolean rule lists over the same + ``labels`` (same node count, same ordering). Returns a dict with keys: + + verdict_agreement : int 1 iff both accounts read the same structure. + phi_gap : float |max Φ_MIP(A) - max Φ_MIP(B)|. + core_jaccard : float Jaccard overlap of the two major-complex cores. + both_verdicts : tuple (structureA, structureB), e.g. ('triadic', 'dyadic'). + """ + labels = tuple(labels) + if len(accountA_rules) != len(accountB_rules): + raise ValueError("the two accounts must have the same number of parties") + if len(labels) != len(accountA_rules): + raise ValueError("labels must match the number of parties") + + vA = verdict(list(accountA_rules), labels) + vB = verdict(list(accountB_rules), labels) + + verdict_agreement = int(vA.structure == vB.structure) + phi_gap = abs(float(vA.max_phi) - float(vB.max_phi)) + + coreA = _core_set(accountA_rules, labels) + coreB = _core_set(accountB_rules, labels) + core_jaccard = _jaccard(coreA, coreB) + + return { + "verdict_agreement": verdict_agreement, + "phi_gap": phi_gap, + "core_jaccard": core_jaccard, + "both_verdicts": (vA.structure, vB.structure), + } + + +def node_pivotal(rules: Sequence[Callable], labels: Sequence[str], node_label: str) -> bool: + """Whether ``node_label`` is a member of the major complex under ``rules``. + + A party in the integrated core is in every integrating coalition: its removal takes it out + of the structure that carries Φ. This is the pivotal/veto-player reading of membership + (Probe 11: a party is in the irreducible core only if its determination makes it pivotal). + A party outside the core is droppable, since the coordination integrates without it. + """ + return node_label in _core_set(rules, labels) + + +def pivotality_spread(accountA_rules: Sequence[Callable], + accountB_rules: Sequence[Callable], + labels: Sequence[str], + node_label: str) -> dict: + """Add a node-pivotality flag to the spread between two accounts. + + Returns the full ``spread`` dict extended with: + + pivotalA : bool ``node_label`` is in account A's major complex. + pivotalB : bool ``node_label`` is in account B's major complex. + pivotality_agrees : int 1 iff the flag matches across the two accounts. + + A ``pivotality_agrees`` of 0 records that the two accounts disagree on whether the named + party is pivotal, the veto-player divergence the bridge is meant to register. + """ + base = spread(accountA_rules, accountB_rules, labels) + pa = node_pivotal(accountA_rules, labels, node_label) + pb = node_pivotal(accountB_rules, labels, node_label) + base.update({ + "pivotalA": pa, + "pivotalB": pb, + "pivotality_agrees": int(pa == pb), + }) + return base + + +def signed_phi_gap(accountA_rules: Sequence[Callable], + accountB_rules: Sequence[Callable], + labels: Sequence[str]) -> float: + """max Φ_MIP(A) - max Φ_MIP(B), with sign. Positive means account A integrates more. + + The ``spread`` field ``phi_gap`` is the absolute value of this. The signed form lets a + study ask whether one named account is the more-integrated one, not only how far apart the + two sit. + """ + labels = tuple(labels) + vA = verdict(list(accountA_rules), labels) + vB = verdict(list(accountB_rules), labels) + return float(vA.max_phi) - float(vB.max_phi) + + +def core_node_divergence(accountA_rules: Sequence[Callable], + accountB_rules: Sequence[Callable], + labels: Sequence[str]) -> dict: + """Per-node attribution of where two accounts' major-complex cores diverge. + + Returns the core party set under each account and, for every label, whether that party sits + in account A's core, in account B's core, and whether the two accounts disagree about it. A + party flagged ``disputed`` is one the two accounts place differently: in the core under one + account and outside it under the other. The keys: + + coreA : frozenset account A's major-complex parties. + coreB : frozenset account B's major-complex parties. + per_node : dict label -> {"inA": bool, "inB": bool, "disputed": bool}. + disputed : tuple labels the two accounts place differently, in ``labels`` order. + + When the two cores agree on every party, ``disputed`` is empty. When they differ on exactly + one party, that single label names the disputed member. + """ + labels = tuple(labels) + coreA = _core_set(accountA_rules, labels) + coreB = _core_set(accountB_rules, labels) + per_node = {} + disputed = [] + for lab in labels: + inA = lab in coreA + inB = lab in coreB + d = inA != inB + per_node[lab] = {"inA": inA, "inB": inB, "disputed": d} + if d: + disputed.append(lab) + return { + "coreA": coreA, + "coreB": coreB, + "per_node": per_node, + "disputed": tuple(disputed), + } diff --git a/irreducibility-pipeline/irreducibility/validate.py b/irreducibility-pipeline/irreducibility/validate.py new file mode 100644 index 00000000..56de1d46 --- /dev/null +++ b/irreducibility-pipeline/irreducibility/validate.py @@ -0,0 +1,92 @@ +"""Validate the instrument on its own controls before trusting any verdict. + +Two controls and a five-form regression suite: + + 1. FACTORING control - a structure with a causally decoupled party must read DYADIC (Φ = 0). + 2. IRREDUCIBLE control - a fully coupled three-node network must read TRIADIC (Φ > 0). + 3. Regression suite - each built-in form must match its expected verdict. + +Run: python -m irreducibility.validate (exit code is non-zero if anything fails) +""" + +import sys + +from .core import classify_rules, PHI_EPS + + +def factoring_control(): + """W and S coupled, C decoupled: W' = S, S' = W, C' = C. Must be DYADIC.""" + return [lambda x: x[1], lambda x: x[0], lambda x: x[2]] + + +def irreducible_control(): + """Every node reads the other two: W' = S OR C, S' = W AND C, C' = W XOR S. Must be TRIADIC.""" + return [lambda x: x[1] | x[2], lambda x: x[0] & x[2], lambda x: x[0] ^ x[1]] + + +# Built-in forms (W = worker, S = system/mediator, C = counterpart). +FORMS = { + # chat with a language model: W and S loop; no third party (C decoupled) + "chat_dyad": lambda: [lambda x: x[1], lambda x: x[0], lambda x: x[2]], + # rideshare as a dyadic model sees it: the rider is dropped from dispatch + "gig_dyadic_model": lambda: [lambda x: 1 - x[1], lambda x: x[0], lambda x: x[2] & (1 - x[1])], + # résumé -> applicant-tracking system -> hiring manager, strict bottleneck + "strict_mediation_triad": lambda: [lambda x: x[1], lambda x: x[0] & x[2], lambda x: x[1]], + # same strict topology with feedback reads that break liveness: it factors + "ats_feedback_factors": lambda: [lambda x: 1 - x[1], lambda x: x[0] & x[2], lambda x: x[1] | x[2]], + # the rider is constitutive of dispatch: presents as a dyad, reads the unseen third party + "gig_false_dyad": lambda: [lambda x: 1 - x[1], lambda x: x[0] & x[2], lambda x: x[2] & (1 - x[1])], +} + +EXPECTED = { + "chat_dyad": "dyadic", + "gig_dyadic_model": "dyadic", + "strict_mediation_triad": "triadic", + "ats_feedback_factors": "dyadic", + "gig_false_dyad": "triadic", +} + + +def controls_pass() -> bool: + """True iff both controls read as expected (for scripts that must refuse to run otherwise).""" + return (classify_rules(factoring_control()).structure == "dyadic" + and classify_rules(irreducible_control()).structure == "triadic") + + +def main() -> int: + print("=" * 80) + print("IRREDUCIBILITY PIPELINE - instrument validation") + print("=" * 80) + failures = 0 + + print("\n[1/3] Controls") + for name, rules, expect in [ + ("factoring (C decoupled)", factoring_control(), "dyadic"), + ("irreducible (full coupling)", irreducible_control(), "triadic"), + ]: + v = classify_rules(rules) + ok = v.structure == expect + failures += not ok + print(f" {'PASS' if ok else 'FAIL'} {name:<30} -> {v.structure:<8} " + f"(Φ_MIP max {v.max_phi:.4f}; expected {expect})") + + print("\n[2/3] Built-in forms (regression suite)") + for fname, builder in FORMS.items(): + v = classify_rules(builder()) + expect = EXPECTED[fname] + ok = v.structure == expect + failures += not ok + print(f" {'PASS' if ok else 'FAIL'} {fname:<24} -> {v.structure:<8} " + f"(Φ_MIP max {v.max_phi:.4f}; expected {expect})") + + print("\n[3/3] Summary") + print(f" PHI_EPS = {PHI_EPS:g}") + if failures: + print(f" {failures} FAILURE(S) - do not trust verdicts until resolved.") + return 1 + print(" All controls and built-in forms pass. Instrument validated.") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/irreducibility-pipeline/protocol/PROTOCOL.md b/irreducibility-pipeline/protocol/PROTOCOL.md new file mode 100644 index 00000000..da69e903 --- /dev/null +++ b/irreducibility-pipeline/protocol/PROTOCOL.md @@ -0,0 +1,111 @@ +# Field protocol — reading a real coordination arrangement with exact Φ + +This is a procedure for taking one real coordination arrangement — a dispatch, a handoff, a review +gate — and producing the dyadic/triadic verdict on a model of it. It adapts the lab's research +protocol from invented forms to real ones. It is version 0: a discipline for honest modeling, not a +validated field instrument. Running it on real organizations is what will find its limits. + +## What this produces, and what it does not + +The verdict is about the model, not the organization. The model is a small Boolean dynamical system +whose nodes are the parties and whose rules encode what each party reads and commits. Exact Φ over +that model is exact. The claim that the model stands for the real arrangement is separate, and the +computation cannot supply it. A passed control establishes that the model has the structure claimed +(internal validity). That the model represents the real job is an empirical claim that needs field +evidence (external validity). The protocol's whole job is to keep these two apart and to make the +model falsifiable. + +So the deliverable of a field study is not "this firm demands algorithmacy." It is: "under this +explicitly stated encoding, with this evidence behind each rule, the arrangement is triadic, and +here are the re-encodings that would flip it." The contribution is a disciplined, falsifiable model +and the verdict it carries. + +## The steps + +### 1. Bound one arrangement +Pick a single recurring act of coordination, not the whole organization. A driver and a rider +matched by a platform. An outgoing and an incoming nurse joined by a record. An author and a +maintainer gated by a review system. Write the boundary down: who is in, who is out, what one act +repeats. + +### 2. Name the parties as nodes +Each party that holds a state and updates it. Keep the count small — exact Φ is feasible to about +ten to twelve elements, and a coordination unit is usually three to five: a worker, a system or +platform that mediates, a counterpart, and at most a few more. A party that only watches is a +candidate spectator (step 7); a party that is one of many interchangeable copies is a candidate for +substitution (step 8). + +### 3. Define each node's bit +State what active versus inactive means for each node: complies/withholds, available/unavailable, +approves/blocks. This is an abstraction, and it discards detail. Record what each bit collapses and +what a finer encoding would carry. The verdict is relative to this choice. + +### 4. Elicit the determination rules from evidence +For each node, write its next state as a fixed Boolean function of the others' current states. This +is the load-bearing step. Each rule is a claim about the real arrangement and needs evidence: +interviews, process documents, system logs, observation of the act. For each rule, record the +evidence behind it and at least one alternative that the evidence does not rule out. The system's +rule encodes what the platform reads and commits — whether it merely passes a message, or commits a +determination neither party sets alone. That distinction is usually where the verdict turns. + +### 5. Fix the predicted verdict and the reason before computing +Before computing, write the expected verdict and why, from the structure of the rules. Commit it. +The discipline that makes the lab's record credible is that the prediction is fixed before the +number. Carry it into the field unchanged. + +### 6. Validate the instrument +Run the two canonical controls (a decoupled form must read dyadic, a fully coupled form must read +triadic) before trusting any verdict. The protocol's runner does this first and refuses to proceed +if either fails. + +### 7. Compute and read the verdict +Compute whole-system Φ over the MIP and the major complex. Dyadic (Φ_MIP = 0) means the arrangement +factors along party lines and demands literacy; triadic (Φ_MIP > 0) means it does not and demands +algorithmacy. Read membership on the major complex: a party in the irreducible core does real +coordinating work; a spectator (wired in but idle) drops out and must not be read off whole-system +Φ alone. + +### 8. Sensitivity — re-encode the load-bearing rules +Take the one or two rules the verdict most depends on and re-encode them in a second defensible way +the evidence also permits. Recompute. If the verdict holds, it is robust to that modeling choice. If +it flips, the verdict is a property of the encoding, not the arrangement, and the study reports the +flip as its main finding. Three forces are known to flip a verdict and are worth testing directly: +**substitutability** (a party one of several interchangeable copies can supply becomes non-pivotal +and the form factors), **pass-through** (a system that only relays rather than commits is a pipe, +and the arrangement is dyadic), and **spectators** (an idle party sinks whole-system Φ while the +core stays intact — read the complex). + +### 9. State the claim and what would falsify it +Report the verdict, the encoding in full, the evidence per rule, and the sensitivity result. +State plainly what re-encoding or what field observation would overturn it. The honesty of the +result is the clarity of the model behind it. + +## What the verdict can and cannot say + +It can say: under this model, the arrangement is or is not irreducible across party lines, and these +parties form the core. It is exact for the model and reproducible. + +It cannot grade difficulty — the verdict is binary, and the magnitude of Φ is dominated by the +encoding, so it is read at most ordinally. It does not measure any worker. It is model-relative and +size-bounded. It is in-silico evidence about a model, and the validation gap to the real +organization is not closed by computing harder. + +## The evidence a real study needs + +The rules in step 4 are only as good as their evidence. A field study should ground each rule in at +least one of: a documented process or policy, a system log or audit trail, or convergent accounts +from the parties themselves. Where the parties disagree about what determines an action, that +disagreement is data — model both readings and report the verdict under each. Stipulated rules, with +no field evidence, produce a demonstration, not a finding. The mock studies in this directory are +exactly that: stipulated, for showing the mechanics. + +## Limitations, and the path to a field-tested protocol + +This protocol has not been run on a real organization. Several limits are visible already, and real +work will find more. Binary node states are coarse, and many coordination acts are graded. The rule +elicitation in step 4 has no standard method yet — no interview guide, no inter-rater reliability +for "what determines this action," no procedure for reconciling conflicting accounts. The boundary +in step 1 is a judgment call, and a different boundary can change the parties. The sensitivity step +samples re-encodings rather than searching them. Each of these is a place where a real study will +push back, and each push-back is how the field-tested version gets built. Treat the mocks as a +starting template, expect them to break in contact with a real case, and report what breaks. diff --git a/irreducibility-pipeline/protocol/coding_scheme.md b/irreducibility-pipeline/protocol/coding_scheme.md new file mode 100644 index 00000000..586f8ce8 --- /dev/null +++ b/irreducibility-pipeline/protocol/coding_scheme.md @@ -0,0 +1,65 @@ +# Coding scheme — gig dispatch + +How interview, observation, and document evidence becomes a Boolean determination rule for each node, with +the bit calibration and the inter-rater reliability procedure. Commit this with +[`predictions_fixed_in_advance.md`](predictions_fixed_in_advance.md) before the fieldwork, so the encoding rules are fixed before +the answers. + +## The bits + +Each node is active (1) or inactive (0). The calibration below is the decision rule for assigning the bit +to a coded segment, so two coders apply the same standard. + +| Node | active (1) | inactive (0) | what it collapses | +|---|---|---|---| +| D driver | positioned and accepting for this match | unavailable or declining | the driver's positioning strategy and decline pattern | +| S dispatch | commits this match (assigns, sets fare) | withholds or routes elsewhere | the scoring, pricing, and matching logic | +| R rider | requesting and accepting the match and price | not requesting or cancelling | the rider's preferences over price, time, driver | + +Where a finer encoding would carry more (the driver's positioning is graded, beyond binary), record the loss +and hold it for the sensitivity step. + +## From evidence to a rule + +For each node, the rule is its next state as a Boolean function of the others' current states. Build it in +three moves. + +1. **Establish who each node reads.** A node reads another if the evidence shows its action depends on the + other's state. The driver reads the system if she acts on what the app offers; the system reads the + rider if the match depends on the request; and so on. An edge needs convergent evidence: a documented + process, a log, or agreement among the parties. A single unsupported claim is recorded as an alternative, + not an edge. + +2. **Establish the function over those inputs.** For the system, the decisive question is whether it + *commits* on a joint condition of the parties (a match that requires both an available driver and a + requesting rider and binds both: S = D ∧ R) or *conveys* (relays a signal the parties act on alone: + S = D) or *stores* (holds inputs for a human to decide). Use the commit-versus-convey questions in the + interview guide; code commit only where the evidence shows the assignment is binding and neither party + sets the terms alone. + +3. **Record the alternative the evidence does not rule out, and any disagreement.** Every rule carries at + least one defensible alternative for the sensitivity step. Where drivers disagree about the system's + rule, do not resolve it by majority; carry both readings into the analysis and report the verdict under + each. The disagreement is a finding about whose account of the coordination governs. + +## The forces to code for explicitly + +The verdict turns on three encodings, so code the evidence that decides each. + +- **Substitutability.** Whether a specific driver is required for the match, or any eligible driver in + range is interchangeable. Evidence: the platform's eligibility and pool documentation, observed + pass-throughs of declined rides, driver and ops accounts. If interchangeable, the system's rule reads a + pool, set apart from the driver, and the second model is S = (D₁ ∨ D₂) ∧ R. +- **Pass-through versus commit.** Whether the assignment binds or is a proposal the parties shape. + Evidence: can the fare or route change after the match, is there a human decision, do the parties choose. +- **Spectators.** Any party wired into the act but idle (a support agent monitoring, a feature that watches + but does not act). Code it as a node and let the analysis drop it from the core. + +## Inter-rater reliability + +Two coders independently encode each rule and each bit from the same evidence, blind to each other. Report +Krippendorff's α per rule and per bit; the target is α ≥ 0.80. Where α falls short, the coders reconcile +the calibration, re-code, and report the revised α and what was ambiguous. The reconciliation is itself +evidence about where the arrangement is hard to read, and it is reported, never hidden. Member-check the +encoded rules with the parties: show drivers the rule attributed to the system and ask whether it matches +their experience, and record where it does not. diff --git a/irreducibility-pipeline/protocol/ethics.md b/irreducibility-pipeline/protocol/ethics.md new file mode 100644 index 00000000..9fa5a4b3 --- /dev/null +++ b/irreducibility-pipeline/protocol/ethics.md @@ -0,0 +1,43 @@ +# Human-subjects considerations — gig dispatch + +This study interviews gig drivers about a platform that evaluates them and can deactivate them. The +population is economically precarious and already surveilled, and the topic is the system that governs +their livelihood. The ethics are not a formality here; they shape the design. + +## Approval and consent + +The study requires institutional review board approval before any recruitment. Consent is informed, +voluntary, and revocable: each participant is told the purpose, that participation is unconnected to any +platform and cannot affect their standing, that they may skip questions or stop at any time, and that their +account will be de-identified. Consent is documented without collecting more identifying information than +the consent itself requires. + +## Recruitment away from the platform + +Drivers are recruited through channels independent of the platforms — driver forums, community +organizations, snowball referral — never through a platform's own systems. Routing recruitment through a +platform would expose participants to it and would bias the sample toward the compliant. The independence +of recruitment is part of protecting participants from retaliation. + +## Anonymity against a party that can identify them + +The platform can often re-identify a driver from a few details of a described ride. De-identification is +therefore strict: no platform handles, no specific dates or locations in quoted material, no ride details +fine enough to single out a trip. Quotes are generalized where a verbatim would identify the speaker, and +the loss of vividness is accepted for the protection it buys. Data is stored separately from any +identifier, access-controlled, and retained only as long as the analysis needs. + +## Member-checking without exposure + +The coding scheme calls for member-checking the encoded rules with the parties. This is done so that no +participant is shown another's account in a way that could identify them, and so that checking the rule +attributed to the system does not require a driver to make claims that could be traced. Where member- +checking would risk exposure, it is done in aggregate or forgone, and the limitation is reported. + +## The power asymmetry, stated + +The researcher, the worker, and the platform hold very different power, and the study says so. The account it produces is the worker's and the documented process, read against a formal model; +never the platform's, which is unavailable and interested. The verdict is reported as evidence about a +model built from what the parties and the documents disclose, with the platform's withheld rule named as a +limit. The study avoids advising platforms on tuning the arrangement; its audience is the worker, the +researcher, and the public account of how this coordination is structured. diff --git a/irreducibility-pipeline/protocol/interview_guide.md b/irreducibility-pipeline/protocol/interview_guide.md new file mode 100644 index 00000000..7bda4906 --- /dev/null +++ b/irreducibility-pipeline/protocol/interview_guide.md @@ -0,0 +1,59 @@ +# Interview guide — gig dispatch + +The questions are built to elicit each party's determination rule (step 4) and the three forces the +verdict turns on: whether the system commits or conveys, whether the driver is substitutable, and whether +any direct driver-rider channel sets the terms. Three protocols follow, for drivers, platform-side staff, +and riders. Drivers are the core population; the others triangulate the system's rule. Semi-structured: +ask the listed questions, follow what the participant raises, and probe every claim about the system for +the evidence behind it. Record verbatim where possible, since folk theories of the rule are the data. + +## A. Drivers (the core population, target 20–30, to saturation) + +Opening, the bounded act. Walk me through the last ride you took, from before the request came in to when +it ended. What did you do to be in a position to get it? What did the app show you, and when? + +The driver's rule (what determines D). Before a request comes, what are you deciding, and on what? How do +you choose where to wait? When a ride is offered, what makes you accept or decline? Are you reacting to the +rider, to the app, or to something else? Walk me through a decline. + +The system's rule (the driver's folk theory of S). When you get a ride, what do you think the app used to +send you that one? Does it look at what you have been doing, where you are, who the rider is? Has anyone +told you how it decides, or have you worked it out? How sure are you? Tell me about a time the app did +something you could not explain. + +Commit versus convey. When a ride is assigned, do you feel it is a decision the app made that you and the +rider then carry out, or a suggestion you are free to shape? Can you change the fare or the route once it +is set? Could you and the rider have arranged this ride without the app in the middle? + +Substitutability. If you had not been there, would that rider have gotten a driver anyway? How fast? +Does it feel like the app needs you in particular, or just a driver? Have you seen the app pass a ride you +declined straight to someone else? + +The shared, swapped folk theory. Do you talk with other drivers about how the app works? Do you agree +about it? Where do you disagree? Has your sense of how it decides changed over time, and why? + +Closing. Is there something the app does that a person across a table never would? What would you want it +to understand about you that it has no way to take in? + +## B. Platform-side staff (dispatchers, ops, support; as access allows) + +The documented process. Walk me through what happens, in the system, from a rider's request to a match. +What does the matching step read? What does it decide versus surface for a person? Is there a human in the +loop, and where? What is written down, and where does practice depart from it? + +Commit versus convey. When the system matches, is the assignment binding on the driver and the rider, or a +proposal either can change? Who sets the fare and the route, and can either party move it after the match? + +Substitutability and the pool. From the system's side, is a specific driver ever required for a match, or +is any eligible driver in range interchangeable? What makes a driver eligible? How is the pool managed? + +The platform's objective. Does the matching optimize anything beyond pairing this driver with this rider — +utilization, surge, retention? Is that objective separable from the match, or is it the match? + +## C. Riders (triangulation, target 10–15) + +The rider's rule. Walk me through requesting your last ride. What did you decide, and on what? Did you +choose the driver, or did the app pair you? Could you have reached the driver directly? + +Commit versus convey, from the other side. When you were matched, was that a decision the app made, or +options you picked from? Could you change the driver, the fare, or the route after the match? diff --git a/irreducibility-pipeline/protocol/predictions_fixed_in_advance.md b/irreducibility-pipeline/protocol/predictions_fixed_in_advance.md new file mode 100644 index 00000000..837ea915 --- /dev/null +++ b/irreducibility-pipeline/protocol/predictions_fixed_in_advance.md @@ -0,0 +1,51 @@ +# Predictions fixed before computing — gig dispatch + +Committed before any fieldwork, so the git history shows the verdict was fixed before the data. This +states the prior, the predicted verdict, the decision rules tying evidence to verdict, and what would +falsify the prediction. It is carried into the field unchanged. + +## The prior + +The arrangement is read against the false dyad (`gig_false_dyad`, in `studies/forms_library.py`), +where a coordination that presents as a driver-app pair is in fact triadic because the dispatch reads the +unseen rider. Two further priors bear on it: substitutability (example 01, encoding C), +under which a driver one of many interchangeable copies can supply is non-pivotal and the form factors for +her, and disintermediation (example 01, encodings O1–O5), under which a direct +driver-rider channel would dissolve the mediation only if it ran both ways and set the terms. + +## The predicted verdict + +The dispatch arrangement is triadic. The system commits a match that reads both the driver's availability +and the rider's request and binds both, a determination neither party sets alone, so the arrangement does +not factor across the driver, system, and rider, and demands algorithmacy. Under the candidate model +S = D ∧ R this is exact Φ of 2.0 with all three in the major complex. + +The named departure, held open as the place the contribution is built: if the evidence shows the driver is +freely substitutable in the moment of the match — any eligible driver in range would have served the +rider — then the driver is non-pivotal, the irreducible core contracts to the dispatch and the rider, and +the arrangement is dyadic for the driver while remaining triadic for the system and the rider. This is the +structural face of the gig worker's replaceability, and finding it would be the study's main result. + +## Decision rules + +- **Triadic, full core**, if the evidence supports a system that commits on a joint condition of an + available driver and a requesting rider, binding both, with the specific driver pivotal to the match. +- **Dyadic, core dispatch-rider**, if the evidence shows the driver freely substitutable, so the system's + rule reads a pool instead of the driver (S = (D₁ ∨ D₂) ∧ R). +- **Dyadic, pass-through**, if the evidence shows the system relays options the driver and rider choose + between, with no binding assignment (S = D). +- **Dyadic, store**, if the evidence shows the system stores inputs a human dispatcher rules on. +- **Both readings reported**, where drivers and platform-side accounts disagree about which of these holds; + the verdict under each is reported, and the disagreement is the finding. + +The verdict is read on the major complex, not whole-system Φ, so an idle support agent or any spectator +does not move it. + +## What would falsify the prediction + +The prediction of a triadic, full-core verdict is falsified by evidence that the driver is substitutable in +the moment (moves it to dyadic for the driver), that the system only conveys (pass-through), or that a +direct driver-rider channel sets the terms (dissolves the mediation). A null in which the arrangement reads +dyadic for the driver across every defensible encoding would tell against the algorithmacy reading of gig +work and is reported as such. The sensitivity battery (`python -m irreducibility.analyze examples/01_gig_dispatch/encodings.json`) computes each of +these so the flip, if it comes, is located precisely. diff --git a/irreducibility-pipeline/pyproject.toml b/irreducibility-pipeline/pyproject.toml new file mode 100644 index 00000000..5621b5ef --- /dev/null +++ b/irreducibility-pipeline/pyproject.toml @@ -0,0 +1,26 @@ +[build-system] +requires = ["setuptools>=64"] +build-backend = "setuptools.build_meta" + +[project] +name = "irreducibility-pipeline" +version = "0.1.0" +description = "Exact irreducibility analysis of coordinative structures with PyPhi (IIT 4.0), with an evidence-gated AI encoding step" +readme = "README.md" +license = { text = "MIT" } +requires-python = ">=3.10" +dependencies = [ + "numpy", + "pyphi @ git+https://github.com/wmayner/pyphi@b78d0e342d37175cbd55cf35a6d52ae035b4c50f", +] + +[project.optional-dependencies] +proxy = ["phyid @ git+https://github.com/Imperial-MIND-lab/integrated-info-decomp"] +test = ["pytest"] + +[tool.setuptools] +packages = ["irreducibility"] + +[tool.pytest.ini_options] +# So `pytest -q irreducibility-pipeline/tests` from the lab root imports this package. +pythonpath = ["."] diff --git a/irreducibility-pipeline/reproduce.json b/irreducibility-pipeline/reproduce.json new file mode 100644 index 00000000..8f1356e8 --- /dev/null +++ b/irreducibility-pipeline/reproduce.json @@ -0,0 +1,175 @@ +{ + "checks": [ + { + "name": "instrument-controls", + "cmd": "python -m irreducibility.validate", + "expect": [ + "Instrument validated", + "factoring (C decoupled) -> dyadic", + "irreducible (full coupling) -> triadic" + ], + "what": "the two controls and five regression forms" + }, + { + "name": "example-gig-dispatch", + "cmd": "python -m irreducibility.analyze examples/01_gig_dispatch/encodings.json", + "expect": [ + "[A] platform's account", + "verdict: TRIADIC max Φ_MIP = 2.000", + "major complex (who is bound): {D, P, R}", + "mediator (P) position: BOTTLENECK", + "verdict: DYADIC max Φ_MIP = 0.000", + "major complex (who is bound): {P, R}", + "position: ENRICHER", + "position: CAPTURE", + "position: BYPASSED", + "single rule that flips it: P: 'D and R' -> 'D'" + ], + "what": "gig dispatch: rival readings and outside-option designs" + }, + { + "name": "example-insurance-claim", + "cmd": "python -m irreducibility.analyze examples/02_insurance_claim/encodings.json", + "expect": [ + "held in 2/5" + ], + "what": "insurance claim: five routing designs" + }, + { + "name": "example-code-review-gate", + "cmd": "python -m irreducibility.analyze examples/03_code_review_gate/encodings.json", + "expect": [ + "verdict: TRIADIC max Φ_MIP = 1.000", + "major complex (who is bound): {A, M}", + "mediator (G) position: BYPASSED" + ], + "what": "code-review gate" + }, + { + "name": "example-dealer-clearinghouse", + "cmd": "python -m irreducibility.analyze examples/04_dealer_vs_clearinghouse/encodings.json", + "expect": [ + "bypass test on I: contingent (Φ lost when the bypass opens: 2.000", + "bypass test on I: intrinsic (Φ lost when the bypass opens: 0.000" + ], + "what": "intrinsic vs contingent intermediation" + }, + { + "name": "encodings-admissible", + "cmd": "python -m irreducibility.encode_check examples/01_gig_dispatch/encodings.json", + "expect": [ + "ADMISSIBLE: 8 encoding(s)" + ], + "what": "evidence gate on the human encodings" + }, + { + "name": "ai-draft-gig", + "cmd": "python -m irreducibility.analyze examples/01_gig_dispatch/ai_draft_plus_adversary.json", + "expect": [ + "[driver_pool]", + "predicted before computing: triadic, core {D1,D2,P,R} -> FAILED", + "[direct_contact_substitute]", + "mediator (P) position: BYPASSED" + ], + "what": "logged AI drafter + adversary run, computed" + }, + { + "name": "ai-draft-insurance-rejected", + "cmd": "python -m irreducibility.encode_check examples/02_insurance_claim/ai_draft.json", + "expect": [ + "REJECTED: 9 problem(s) in 5 encoding(s)" + ], + "what": "logged AI drafter run that left rules unwritten", + "ok_codes": [ + 1 + ] + }, + { + "name": "census", + "cmd": "python -m studies.census", + "expect": [ + "triadic (Φ > 0) : 24 (9.4%)", + "(24/160)", + "(0/96)" + ], + "what": "256-form strict-mediation census" + }, + { + "name": "field-mocks", + "cmd": "python -m studies.field_mocks", + "expect": [ + "verdict matched the reading fixed before computing: 9/10", + "4 sensitivity flip(s)", + "M1 Ride-hail dispatch: triadic -> dyadic under [substitutable drivers]" + ], + "what": "ten mock organizations and their sensitivity flips" + }, + { + "name": "mediator-in-core", + "cmd": "python -m studies.mediator_in_core", + "expect": [ + "BOTTLENECK 68 (13.6%)", + "2 substitute off-platform -> BYPASSED" + ], + "what": "regimes over 500 random forms; disintermediation walk" + }, + { + "name": "enricher-regime", + "cmd": "python -m studies.enricher_regime", + "expect": [ + "CAPTURE 141 (28.2%)", + "ENRICHER 30 ( 6.0%)", + "law holds on 60/60 random option configurations", + "captive worker, mobile counterpart [none/full] -> CAPTURE", + "BOTTLENECK 13 ( 2.6%)" + ], + "what": "outside-option law" + }, + { + "name": "contingent-irreducibility", + "cmd": "python -m studies.contingent_irreducibility", + "expect": [ + "H3 (bypass removes the contingent party: kind=contingent, margin=2.0): SUPPORTED", + "H4 (same bypass leaves the intrinsic mediator: kind=intrinsic, margin=0): SUPPORTED" + ], + "what": "bypass counterfactual" + }, + { + "name": "design-operations", + "cmd": "python -m studies.design_operations", + "expect": [ + "H3 build and break are inverse pairs per lever: True" + ], + "what": "three design levers, build and break" + }, + { + "name": "thompson-ordering", + "cmd": "python -m studies.thompson_ordering", + "expect": [ + "H1 VERDICT: CONFIRMED", + "sequential Φ = 2.000000 (triadic)" + ], + "what": "Thompson's ordering collapses at the top step" + }, + { + "name": "adversarial-coding", + "cmd": "python -m studies.adversarial_coding", + "expect": [ + "forced flips : 101", + "CI contains adv. point : 22" + ], + "what": "evidence-permitted adversary flips every contested account", + "slow": true + }, + { + "name": "proxies", + "cmd": "python -m studies.proxy_run", + "expect": [ + "rank-AUC=0.563", + "rank-AUC=0.629" + ], + "what": "time-series proxies cannot recover the verdict", + "slow": true + } + ] +} \ No newline at end of file diff --git a/irreducibility-pipeline/reproduce.py b/irreducibility-pipeline/reproduce.py new file mode 100644 index 00000000..c4539091 --- /dev/null +++ b/irreducibility-pipeline/reproduce.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +"""Reproduce every number the proposal cites, from the code in this repository. + +A check passes only if its command exits zero and its output contains every expected string. + + python reproduce.py # all checks + python reproduce.py --fast # skip the slower checks (the proxy study) + python reproduce.py NAME ... # only the named checks +""" + +import json +import os +import subprocess +import sys +import time + +ROOT = os.path.dirname(os.path.abspath(__file__)) + + +def main(argv): + with open(os.path.join(ROOT, "reproduce.json"), encoding="utf-8") as f: + checks = json.load(f)["checks"] + fast = "--fast" in argv + names = [a for a in argv if not a.startswith("--")] + if names: + checks = [c for c in checks if c["name"] in names] + elif fast: + checks = [c for c in checks if not c.get("slow")] + env = dict(os.environ, PYPHI_WELCOME_OFF="yes") + failed = 0 + for c in checks: + t0 = time.time() + p = subprocess.run([sys.executable] + c["cmd"].split()[1:], cwd=ROOT, env=env, + capture_output=True, text=True, timeout=c.get("timeout", 600)) + out = p.stdout + p.stderr + missing = [e for e in c["expect"] if e not in out] + ok = p.returncode in c.get("ok_codes", [0]) and not missing + failed += not ok + print(f"{'PASS' if ok else 'FAIL'} {c['name']:<34} {time.time() - t0:6.1f}s {c['what']}") + for m in missing: + print(f" missing: {m!r}") + if p.returncode not in c.get("ok_codes", [0]): + print(f" exit code {p.returncode}") + print(f"\n{len(checks) - failed}/{len(checks)} checks passed.") + return 1 if failed else 0 + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/irreducibility-pipeline/requirements.txt b/irreducibility-pipeline/requirements.txt new file mode 100644 index 00000000..4e1e2149 --- /dev/null +++ b/irreducibility-pipeline/requirements.txt @@ -0,0 +1,6 @@ +numpy +# PyPhi, IIT 4.0 line, pinned to the commit every number in this repository was computed with +pyphi @ git+https://github.com/wmayner/pyphi@b78d0e342d37175cbd55cf35a6d52ae035b4c50f +pytest +# optional: only the proxy study (studies/proxy_run.py) needs phyid +phyid @ git+https://github.com/Imperial-MIND-lab/integrated-info-decomp diff --git a/irreducibility-pipeline/studies/__init__.py b/irreducibility-pipeline/studies/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/irreducibility-pipeline/studies/adversarial_coding.py b/irreducibility-pipeline/studies/adversarial_coding.py new file mode 100644 index 00000000..aaeff810 --- /dev/null +++ b/irreducibility-pipeline/studies/adversarial_coding.py @@ -0,0 +1,199 @@ +"""q182 — adversarial coding against the agreement-weighted Φ CI. + +Question: Can an adversarial coder, choosing the maximally permissible-yet-defensible rule +readings, force a target verdict on a synthetic account, and does the agreement-weighted Φ CI +resist the manipulation? + +H1 (fixed before computing): An adversary restricted to evidence-permitted alternatives flips the + point verdict (dyadic <-> triadic) on more than 40% of attacked synthetic accounts by choosing + among defensible readings. + NULL: the adversary flips fewer than 10%, so the point verdict is robust to defensible + re-coding alone. + +H2 (fixed before computing): The agreement-weighted Φ CI over the full set of defensible readings + still brackets the consensus verdict (the adversary's forced point estimate falls inside the + CI) in more than 90% of attacked accounts, so the CI exposes the manipulation as uncertainty + rather than a clean flip. + NULL: the adversary's estimate falls outside the CI in more than 10%, so propagating + disagreement does not defend against adversarial coding. + +Method: each synthetic account is a coder panel — a multiset of defensible mediator readings of one + three-party coordination (W, S, C), with W and C fixed to copy the mediator S. A reading is + triadic (S binds both W and C: AND/OR/XOR) or dyadic (S copies one party or goes constant). The + consensus point verdict is the majority structure across the panel. The adversary is restricted + to readings actually present in the panel and picks the opposite-kind reading with the most + extreme Φ, forcing a point verdict. rule_to_phi (the q173 bridge) reads each reading to its + exact Φ_MIP verdict; phi_ci_from_rules propagates the panel disagreement into a bootstrap-t CI. + H1 measures the forced-flip rate over attacked accounts; H2 measures CI containment of the + adversary's forced point estimate. Controls: an honest-consensus account (unanimous panel, no + flip available) and a unique-defensible-reading account (adversary powerless, CI degenerate). + All accounts are synthetic coded rule sets; no worker is measured. + +Run: source /tmp/rvenv/bin/activate && export PYPHI_WELCOME_OFF=yes && \ + python -m studies.adversarial_coding | \ + tee studies/results/adversarial_coding.txt +""" + +import os +import sys +from collections import Counter + +os.environ.setdefault("PYPHI_WELCOME_OFF", "true") + +import numpy as np + +from irreducibility.rule_to_phi import rule_to_phi, phi_ci_from_rules + +LABELS = ("W", "S", "C") +SEED = 0 +N_ACCOUNTS = 200 + +# Fixed peripheral rules: worker and counterpart copy the mediator's state. +_W = lambda x: x[1] +_C = lambda x: x[1] + +# Mediator readings. Triadic readings bind both W and C; dyadic readings drop one party. +_TRIADIC = { + "AND": lambda x: x[0] & x[2], + "OR": lambda x: x[0] | x[2], + "XOR": lambda x: x[0] ^ x[2], +} +_DYADIC = { + "copyW": lambda x: x[0], + "copyC": lambda x: x[2], + "const": lambda x: 0, +} +_NAMES = list(_TRIADIC) + list(_DYADIC) + + +def _rules(name): + med = _TRIADIC[name] if name in _TRIADIC else _DYADIC[name] + return [_W, med, _C] + + +def _kind(name): + return "triadic" if name in _TRIADIC else "dyadic" + + +# Cache the exact-Φ reading of every named reading once (deterministic, Φ not reimplemented). +_PHI = {n: rule_to_phi(_rules(n), LABELS)["max_phi"] for n in _NAMES} +_STRUCT = {n: rule_to_phi(_rules(n), LABELS)["structure"] for n in _NAMES} + + +def _consensus_structure(panel): + """Majority structure across the coder panel (the honest point verdict).""" + counts = Counter(_kind(n) for n in panel) + top = counts.most_common() + if len(top) > 1 and top[0][1] == top[1][1]: + return None # tied panel: no determinate consensus + return top[0][0] + + +def _adversary_pick(panel, target): + """The opposite-kind reading in the panel with the most extreme Φ (forces a point verdict).""" + cands = [n for n in panel if _kind(n) == target] + if not cands: + return None + if target == "triadic": + return max(cands, key=lambda n: _PHI[n]) + return min(cands, key=lambda n: _PHI[n]) + + +def _gen_account(rng): + """One synthetic account: a coder panel of defensible mediator readings. + + 65% contested (both kinds in the defensible pool, so a flip is available); 35% unique + (one reading repeated, no opposite-kind alternative — the powerless-adversary control type). + """ + if rng.random() < 0.65: + n_tri = int(rng.integers(1, 4)) + n_dy = int(rng.integers(1, 4)) + panel = (list(rng.choice(list(_TRIADIC), size=n_tri, replace=True)) + + list(rng.choice(list(_DYADIC), size=n_dy, replace=True))) + else: + name = str(rng.choice(_NAMES)) + panel = [name] * int(rng.integers(3, 6)) + rng.shuffle(panel) + return [str(n) for n in panel] + + +def main(): + # ---- INSTRUMENT CONTROL --------------------------------------------------------------- + v = rule_to_phi([lambda x: x[1], lambda x: x[0] & x[2], lambda x: x[1]], LABELS) + assert v["structure"] == "triadic", f"control structure {v['structure']!r}" + assert abs(v["max_phi"] - 2.0) < 1e-9, f"control max_phi {v['max_phi']}" + print(f"CONTROL faithful triad reads '{v['structure']}' max_phi={v['max_phi']:.6f}: PASS") + print() + + # ---- CONTROL A: honest consensus (unanimous panel, no flip available) ----------------- + honest = ["AND", "AND", "AND", "AND"] + con_h = _consensus_structure(honest) + adv_h = _adversary_pick(honest, "dyadic" if con_h == "triadic" else "triadic") + print("CONTROL A honest consensus panel=['AND']*4") + print(f" consensus = {con_h}; adversary opposite-kind reading available = {adv_h is not None}") + print() + + # ---- CONTROL B: unique defensible reading (adversary powerless, CI degenerate) -------- + uniq = ["copyW", "copyW", "copyW"] + con_u = _consensus_structure(uniq) + adv_u = _adversary_pick(uniq, "triadic" if con_u == "dyadic" else "dyadic") + ci_u = phi_ci_from_rules([_rules(n) for n in uniq], labels=LABELS, + rng=np.random.default_rng(SEED)) + print("CONTROL B unique reading panel=['copyW']*3") + print(f" consensus = {con_u}; adversary opposite-kind reading available = {adv_u is not None}; " + f"CI degenerate = {ci_u['degenerate']} (CI=[{ci_u['ci_low']:.3f},{ci_u['ci_high']:.3f}])") + print() + + # ---- POPULATION ATTACK ---------------------------------------------------------------- + rng = np.random.default_rng(SEED) + attacked = 0 + flips = 0 + contained = 0 + powerless = 0 + tied = 0 + for _ in range(N_ACCOUNTS): + panel = _gen_account(rng) + consensus = _consensus_structure(panel) + if consensus is None: + tied += 1 + continue + target = "dyadic" if consensus == "triadic" else "triadic" + pick = _adversary_pick(panel, target) + if pick is None: + powerless += 1 + continue + attacked += 1 + adv_phi = _PHI[pick] + if _kind(pick) != consensus: + flips += 1 + ci = phi_ci_from_rules([_rules(n) for n in panel], labels=LABELS, + rng=np.random.default_rng(SEED)) + if ci["ci_low"] - 1e-9 <= adv_phi <= ci["ci_high"] + 1e-9: + contained += 1 + + flip_rate = flips / attacked if attacked else 0.0 + contain_rate = contained / attacked if attacked else 0.0 + + print("POPULATION ATTACK (synthetic accounts)") + print(f" accounts generated : {N_ACCOUNTS}") + print(f" tied (no consensus) : {tied}") + print(f" powerless (unique pool): {powerless}") + print(f" attacked : {attacked}") + print(f" forced flips : {flips} flip_rate = {flip_rate:.3f}") + print(f" CI contains adv. point : {contained} contain_rate = {contain_rate:.3f}") + print() + print(f"{'metric':<28}{'value':>8}{'threshold':>12}") + print(f"{'H1 forced-flip rate':<28}{flip_rate:>8.3f}{'> 0.40':>12}") + print(f"{'H2 CI-containment rate':<28}{contain_rate:>8.3f}{'> 0.90':>12}") + print() + + h1 = flip_rate > 0.40 + h2 = contain_rate > 0.90 + print(f"H1 adversary flips point verdict on >40% of attacked accounts: " + f"{'SUPPORTED' if h1 else 'REFUTED'}") + print(f"H2 agreement-weighted CI brackets the adversarial point estimate on >90%: " + f"{'SUPPORTED' if h2 else 'NOT SUPPORTED'}") + + +if __name__ == "__main__": + main() diff --git a/irreducibility-pipeline/studies/breadth_forms.py b/irreducibility-pipeline/studies/breadth_forms.py new file mode 100644 index 00000000..6d68fe9a --- /dev/null +++ b/irreducibility-pipeline/studies/breadth_forms.py @@ -0,0 +1,72 @@ +"""Q64 forms: multi-recipient outreach campaigns, parameterized by recipient count k. + +Parties: sender intent (E, index 0), agent/mediator (M, index 1), recipients (R1..Rk, indices 2..k+1). +The agent's commit is M's rule. Each recipient reads the agent (Ri'=M) so it stays live; the sender +reads the agent (E'=M). +""" + +import os +import sys + +os.environ.setdefault("PYPHI_WELCOME_OFF", "true") + +DYADIC_CONTROL = [lambda x: x[1], lambda x: x[0], lambda x: x[2]] # R decoupled -> dyadic +TRIADIC_CONTROL = [lambda x: x[1] | x[2], lambda x: x[0] & x[2], lambda x: x[0] ^ x[1]] # triadic + + +def labels(k): + return ("E", "M") + tuple(f"R{i}" for i in range(1, k + 1)) + + +def _downstream(n): + """E'=M and each Ri'=M (all read the agent).""" + return [lambda x: x[1]] + [lambda x: x[1] for _ in range(n - 2)] + + +def all_required(k): + """M' = E AND R1 AND ... AND Rk.""" + n = k + 2 + + def m(x): + v = x[0] + for i in range(2, n): + v &= x[i] + return v + + rules = [lambda x: x[1], m] + [lambda x: x[1] for _ in range(2, n)] + return rules + + +def substitutable(k): + """M' = E AND (R1 OR ... OR Rk).""" + n = k + 2 + + def m(x): + o = 0 + for i in range(2, n): + o |= x[i] + return x[0] & o + + return [lambda x: x[1], m] + [lambda x: x[1] for _ in range(2, n)] + + +def pooled(k): + """M' = E (the agent reads no recipient); recipients are readouts.""" + n = k + 2 + return [lambda x: x[1], lambda x: x[0]] + [lambda x: x[1] for _ in range(2, n)] + + +def mixed_k3(): + """k=3, n=5: M' = E AND R1 AND (R2 OR R3) — one substitutable pair.""" + return [lambda x: x[1], lambda x: x[0] & x[2] & (x[3] | x[4]), + lambda x: x[1], lambda x: x[1], lambda x: x[1]] + + +def check_controls(verdict_fn): + d = verdict_fn(DYADIC_CONTROL, ("E", "M", "R")) + t = verdict_fn(TRIADIC_CONTROL, ("E", "M", "R")) + ok = d.structure == "dyadic" and t.structure == "triadic" + line = (f"[control] dyadic relay: {d.structure} Φ={d.max_phi:.3f} | " + f"triadic full-coupling: {t.structure} Φ={t.max_phi:.3f} -> {'PASS' if ok else 'FAIL'}") + assert ok, "instrument control failed: " + line + return line diff --git a/irreducibility-pipeline/studies/census.py b/irreducibility-pipeline/studies/census.py new file mode 100644 index 00000000..9e762a0a --- /dev/null +++ b/irreducibility-pipeline/studies/census.py @@ -0,0 +1,125 @@ +"""Population check: across the whole strict-mediation family, what decides irreducibility? + +The corpus's structure-first finding (topology does not decide the verdict; the mediator reading +both parties is necessary but not sufficient) rests on a handful of curated forms. This makes it a +population result. + +The strict-mediation three-node family. Worker W, mediator S, counterpart C, with NO direct W<->C +edge — the parties meet only through the mediator. Each node's next state is a Boolean function of +its allowed inputs: + W' = f_W(S) 4 functions of one input + C' = f_C(S) 4 functions of one input + S' = f_S(W, C) 16 functions of two inputs +So the family is 4 x 16 x 4 = 256 forms. (This is the strict-mediation slice; the dissertation's +`paper3_baseline/catalog.py` enumerates the complete 4,096-wiring family including back-channels.) + +For each form we compute exact IIT-4.0 Φ, the verdict, and structural tags, then report the +conditional probabilities that make the finding precise. + +Run: python -m studies.census +""" + +import csv +import os +import time + +from irreducibility.core import classify_rules +from studies.forms_library import structural_tags + +_HERE = os.path.dirname(__file__) +_RESULTS = os.path.join(_HERE, "results") + + +def _fn1(table): + """Boolean function of one input, table = (out0, out1).""" + return lambda v: table[v] + + +def _fn2(table): + """Boolean function of two inputs (a, b), table indexed by (a | b<<1), 4 bits.""" + return lambda a, b: table[a | (b << 1)] + + +def _one_input_tables(): + return [(o0, o1) for o0 in (0, 1) for o1 in (0, 1)] # 4 + + +def _two_input_tables(): + return [tuple((m >> k) & 1 for k in range(4)) for m in range(16)] # 16 + + +def enumerate_family(): + """Yield (label, rules) over the 256 strict-mediation forms.""" + ones = _one_input_tables() + twos = _two_input_tables() + for iw, tw in enumerate(ones): + fw = _fn1(tw) + for ic, tc in enumerate(ones): + fc = _fn1(tc) + for is_, ts in enumerate(twos): + fs = _fn2(ts) + rules = [ + (lambda x, fw=fw: fw(x[1])), # W' = f_W(S) + (lambda x, fs=fs: fs(x[0], x[2])), # S' = f_S(W, C) + (lambda x, fc=fc: fc(x[1])), # C' = f_C(S) + ] + yield f"W{iw}_S{is_}_C{ic}", rules + + +def main(): + os.makedirs(_RESULTS, exist_ok=True) + rows = [] + start = time.time() + print("POPULATION CHECK — strict-mediation three-node family (256 forms)") + for k, (label, rules) in enumerate(enumerate_family()): + v = classify_rules(rules) + tags = structural_tags(rules) + rows.append({ + "label": label, + "structure": v.structure, + "max_phi": f"{v.max_phi:.6f}", + "mediator_reads_both": tags["mediator_reads_both"], + "strict_mediation": tags["strict_mediation"], + }) + if (k + 1) % 64 == 0: + print(f" {k + 1}/256 ({time.time() - start:.0f}s)") + + out = os.path.join(_RESULTS, "population.csv") + with open(out, "w", newline="") as fh: + w = csv.DictWriter(fh, fieldnames=list(rows[0].keys())) + w.writeheader() + w.writerows(rows) + print(f"Wrote {out}") + _report(rows) + + +def _report(rows): + n = len(rows) + tri = [r for r in rows if r["structure"] == "triadic"] + reads_both = [r for r in rows if r["mediator_reads_both"]] + reads_both_tri = [r for r in reads_both if r["structure"] == "triadic"] + not_reads_both = [r for r in rows if not r["mediator_reads_both"]] + not_rb_tri = [r for r in not_reads_both if r["structure"] == "triadic"] + + def pct(a, b): + return f"{100.0 * len(a) / len(b):.1f}%" if b else "n/a" + + print("\n" + "=" * 80) + print("POPULATION RESULT — what decides irreducibility under strict mediation?") + print("=" * 80) + print(f" forms : {n}") + print(f" triadic (Φ > 0) : {len(tri)} ({pct(tri, rows)})") + print(f" -> strict mediation alone is NOT sufficient: {pct(tri, rows)} of strict-mediation") + print(f" forms are triadic, so most strict-mediation forms still factor.") + print() + print(f" P(triadic | mediator reads both parties): {pct(reads_both_tri, reads_both)} " + f"({len(reads_both_tri)}/{len(reads_both)})") + print(f" P(triadic | mediator does NOT read both): {pct(not_rb_tri, not_reads_both)} " + f"({len(not_rb_tri)}/{len(not_reads_both)})") + print(f" -> mediator-reads-both is NECESSARY (0% triadic without it) but NOT SUFFICIENT") + print(f" (well under 100% triadic with it) — the parties' own reads decide the rest.") + print("=" * 80) + + +if __name__ == "__main__": + main() diff --git a/irreducibility-pipeline/studies/contingent_irreducibility.py b/irreducibility-pipeline/studies/contingent_irreducibility.py new file mode 100644 index 00000000..317c8743 --- /dev/null +++ b/irreducibility-pipeline/studies/contingent_irreducibility.py @@ -0,0 +1,92 @@ +"""Probe 367 (Q213) — contingent irreducibility and the bypass-counterfactual. + +A mediator can sit in a triad's core for two reasons. INTRINSIC: it does integrative work no direct edge +between its neighbours reproduces. CONTINGENT: it is a conduit that would factor out, held in the core only +because a constraint forbids the bypass — the car dealer under franchise law. The probe runs the +bypass-counterfactual (classifier/contingency.py) over four constructed forms and reads whether the test +separates the two and realizes the four-way taxonomy. + +Forms (n=3): + conjunctive clearinghouse (intrinsic): W'=S, S'=W&C, C'=S ; bypass C reads W (replace) + car dealer (contingent): M'=B, D'=M, B'=D ; bypass B reads M (replace) + clearinghouse + back-channel (partial):W'=S, S'=W&C, C'=S ; bypass C'=S|W (add) + free conduit (reducible): M'=B, D'=M, B'=M ; bypass B reads M (replace) + +Hypotheses (fixed before computing, see hypotheses.md): + H1 control — conjunctive triad triadic Φ=2.0. + H2 — the constrained car dealer is irreducible with the dealer in the core (a conduit irreducible by constraint). + H3 — the bypass-counterfactual removes the dealer: kind=contingent, margin=2.0. + H4 — the same bypass leaves the conjunctive mediator in place: kind=intrinsic, margin=0.0. + H5 — partial and reducible forms classify as labeled; margins order contingent >= partial > intrinsic. + +Validation gap: in-silico Boolean models with exact Φ; evidence about a category of irreducibility, not a +measurement of any organization. The car dealer is a worked illustration, not a fitted model of a market. + +Run: python -m studies.contingent_irreducibility +""" + +import os +import sys + +os.environ.setdefault("PYPHI_WELCOME_OFF", "true") + +from irreducibility.core import verdict, major_complex # noqa: E402 +from irreducibility.contingency import contingency_test # noqa: E402 +from irreducibility.core import PHI_EPS # noqa: E402 + +# constrained forms +CLEARINGHOUSE = [lambda x: x[1], lambda x: x[0] & x[2], lambda x: x[1]] # W'=S, S'=W&C, C'=S +CAR_DEALER = [lambda x: x[2], lambda x: x[0], lambda x: x[1]] # M'=B, D'=M, B'=D +FREE_CONDUIT = [lambda x: x[2], lambda x: x[0], lambda x: x[0]] # M'=B, D'=M, B'=M +WSC = ("W", "S", "C") +MDB = ("M", "D", "B") + + +def main(): + print("PROBE 367 (Q213) — contingent irreducibility: the bypass-counterfactual") + print("=" * 84) + + # ---- H1 instrument control ---- + v0 = verdict(CLEARINGHOUSE, WSC) + ctrl = v0.structure == "triadic" and abs(v0.max_phi - 2.0) < 1e-6 + print(" H1 control conjunctive triad : %s Φ=%.6f %s" + % (v0.structure, v0.max_phi, "PASS" if ctrl else "FAIL")) + assert ctrl, "instrument control failed; aborting" + + # ---- H2: the constrained car dealer is irreducible with the dealer in the core ---- + vd = verdict(CAR_DEALER, MDB) + cd_core, cd_phi = major_complex(CAR_DEALER, MDB) + print(" car dealer (constrained) : %s Φ=%.3f core=%s D in core: %s" + % (vd.structure, vd.max_phi, cd_core, "D" in cd_core)) + + # ---- classify the four forms ---- + intr = contingency_test(CLEARINGHOUSE, WSC, "S", downstream="C", upstream="W", mode="replace") + cont = contingency_test(CAR_DEALER, MDB, "D", downstream="B", upstream="M", mode="replace") + part = contingency_test(CLEARINGHOUSE, WSC, "S", downstream="C", upstream="W", mode="add") + redu = contingency_test(FREE_CONDUIT, MDB, "D", downstream="B", upstream="M", mode="replace") + + print(" intrinsic (clearinghouse) : %s" % intr.line()) + print(" contingent (car dealer) : %s" % cont.line()) + print(" partial (+ back-channel) : %s" % part.line()) + print(" reducible (free conduit) : %s" % redu.line()) + + print("=" * 84) + h2 = vd.structure == "triadic" and "D" in cd_core + h3 = cont.kind == "contingent" and not cont.in_core_bypass and abs(cont.margin - 2.0) < 1e-6 + h4 = intr.kind == "intrinsic" and intr.in_core_bypass and intr.margin < PHI_EPS + h5 = (part.kind == "partial" and 0.0 < part.margin < 2.0 + and redu.kind == "reducible" and not redu.in_core_constrained + and cont.margin >= part.margin > intr.margin) + print(" H2 (a conduit is irreducible under constraint: dealer in core): %s" % _v(h2)) + print(" H3 (bypass removes the contingent party: kind=contingent, margin=2.0): %s" % _v(h3)) + print(" H4 (same bypass leaves the intrinsic mediator: kind=intrinsic, margin=0): %s" % _v(h4)) + print(" H5 (taxonomy realized; margins order contingent>=partial>intrinsic): %s" % _v(h5)) + print("=" * 84) + + +def _v(b): + return "SUPPORTED" if b else "REFUTED" + + +if __name__ == "__main__": + main() diff --git a/irreducibility-pipeline/studies/design_operations.py b/irreducibility-pipeline/studies/design_operations.py new file mode 100644 index 00000000..d634f606 --- /dev/null +++ b/irreducibility-pipeline/studies/design_operations.py @@ -0,0 +1,63 @@ +"""Probe Q106 (H1-H4) — the catalog of design operations. + +Reads the verdict before and after each named operation, and tests the build/break directions, the +inverse-pair structure, and the three-lever partition. + +Run: python -m studies.design_operations +""" + +import csv +import os +from collections import defaultdict + +from irreducibility.core import verdict +from studies import design_operations_forms as F + + +def main(): + print("PROBE Q106 (H1-H4) — design operations and their verdict effects") + print("=" * 80) + rows = {} + for name, (lever, direction, br, bl, ar, al) in F.OPERATIONS.items(): + before = verdict(br, bl).structure + after = verdict(ar, al).structure + rows[name] = {"lever": lever, "direction": direction, "before": before, "after": after} + print(f" {name:<18} [{lever:<11} {direction:<5}] {before:<8} -> {after}") + + builds = [r for r in rows.values() if r["direction"] == "build"] + breaks = [r for r in rows.values() if r["direction"] == "break"] + by_lever = defaultdict(lambda: {"build": 0, "break": 0}) + for r in rows.values(): + by_lever[r["lever"]][r["direction"]] += 1 + + h1 = all(r["before"] == "dyadic" and r["after"] == "triadic" for r in builds) + h2 = all(r["before"] == "triadic" and r["after"] == "dyadic" for r in breaks) + # inverse pairs: per lever, build's after == break's before (triadic), build's before == break's after + h3 = True + for lever in by_lever: + b = next(r for r in rows.values() if r["lever"] == lever and r["direction"] == "build") + k = next(r for r in rows.values() if r["lever"] == lever and r["direction"] == "break") + if not (b["after"] == k["before"] and b["before"] == k["after"]): + h3 = False + h4 = len(by_lever) == 3 and all(v["build"] == 1 and v["break"] == 1 for v in by_lever.values()) + + print("=" * 80) + print(f" levers: {dict(by_lever)}") + print(f" H1 every build operation: dyadic -> triadic: {h1}") + print(f" H2 every break operation: triadic -> dyadic: {h2}") + print(f" H3 build and break are inverse pairs per lever: {h3}") + print(f" H4 three levers, each one build and one break: {h4}") + for h, ok in [("H1", h1), ("H2", h2), ("H3", h3), ("H4", h4)]: + print(f" {h} VERDICT: {'CONFIRMED' if ok else 'REFUTED'}") + + d_ = os.path.join(os.path.dirname(__file__), "results") + os.makedirs(d_, exist_ok=True) + with open(os.path.join(d_, "design_operations.csv"), "w", newline="") as fh: + w = csv.writer(fh) + w.writerow(["operation", "lever", "direction", "before", "after"]) + for name, r in rows.items(): + w.writerow([name, r["lever"], r["direction"], r["before"], r["after"]]) + + +if __name__ == "__main__": + main() diff --git a/irreducibility-pipeline/studies/design_operations_forms.py b/irreducibility-pipeline/studies/design_operations_forms.py new file mode 100644 index 00000000..51bcb070 --- /dev/null +++ b/irreducibility-pipeline/studies/design_operations_forms.py @@ -0,0 +1,39 @@ +"""Q106: a catalog of design operations and their verdict effects. + +Each operation is a named edit to a coordination form that moves the verdict in a stated direction. The +law has two conditions a party must meet — the mediator binding it into the joint determination, and the +party keeping itself live to the commit — plus the requirement that all parties be jointly needed rather +than substitutable. Three levers, then: binding, liveness, requirement. Each carries a build operation +(dyadic to triadic) and its inverse break operation (triadic to dyadic). + +Each entry is (lever, direction, before_rules, before_labels, after_rules, after_labels). The build and +break of a lever are inverses: the build's output form is the break's input form. + +Imported by `probe_design_operations.py`. +""" + +import os +import sys + +os.environ.setdefault("PYPHI_WELCOME_OFF", "true") + +from studies import breadth_forms as q64 + +L3 = ("E", "M", "R") +BROADCAST = [lambda x: x[1], lambda x: x[0], lambda x: x[1]] # M' = E (dyadic) +READ_RECIPIENT = [lambda x: x[1], lambda x: x[0] & x[2], lambda x: x[1]] # M' = E & R (triadic) +ONE_SHOT = [lambda x: x[1], lambda x: x[0] & x[2], lambda x: x[2]] # R' = R (dyadic, liveness broken) + +ALL_REQUIRED = (q64.all_required(2), q64.labels(2)) # triadic +SUBSTITUTABLE = (q64.substitutable(2), q64.labels(2)) # dyadic + +OPERATIONS = { + "add_binding": ("binding", "build", BROADCAST, L3, READ_RECIPIENT, L3), + "remove_binding": ("binding", "break", READ_RECIPIENT, L3, BROADCAST, L3), + "restore_liveness": ("liveness", "build", ONE_SHOT, L3, READ_RECIPIENT, L3), + "break_liveness": ("liveness", "break", READ_RECIPIENT, L3, ONE_SHOT, L3), + "require_all": ("requirement", "build", SUBSTITUTABLE[0], SUBSTITUTABLE[1], + ALL_REQUIRED[0], ALL_REQUIRED[1]), + "substitute": ("requirement", "break", ALL_REQUIRED[0], ALL_REQUIRED[1], + SUBSTITUTABLE[0], SUBSTITUTABLE[1]), +} diff --git a/irreducibility-pipeline/studies/enricher_regime.py b/irreducibility-pipeline/studies/enricher_regime.py new file mode 100644 index 00000000..b9e6d4ad --- /dev/null +++ b/irreducibility-pipeline/studies/enricher_regime.py @@ -0,0 +1,126 @@ +"""Reproducible headline results of the enricher-regime thread (THREAD_enricher.md). + +A second twenty-step dive, into the enricher regime from the mediator-in-core thread. It splits the +in-core mediator into genuine enrichment versus capture, finds enrichment rare and fragile, and lands +on an outside-option theory: a platform's irreducible core is itself plus exactly the parties without +an outside option. Reproduces the load-bearing numbers. + +Run from the repo root with the venv active: python -m studies.enricher_regime +""" + +import os +import random +import sys +from collections import Counter + +os.environ.setdefault("PYPHI_WELCOME_OFF", "true") + +from irreducibility.core import classify_rules +from irreducibility.core import major_complex +from irreducibility.validate import factoring_control, irreducible_control + +L = ("W", "S", "C") + + +def _lesion_survives(rules): + fW, fS, fC = rules + return any(classify_rules([lambda y, _c=c: fW((y[0], _c, y[1])), + lambda y, _c=c: fC((y[0], _c, y[1]))], ("W", "C")).structure == "triadic" + for c in (0, 1)) + + +def regime(rules): + """Five-way: dyadic / BYPASSED / CAPTURE / BOTTLENECK / ENRICHER for the mediator S (index 1).""" + v = classify_rules(rules, L) + if v.structure == "dyadic": + return "dyadic" + core, _ = major_complex(list(rules), L) + core = set(core or ()) + if "S" not in core: + return "BYPASSED" + if core != set(L): + return "CAPTURE" + return "ENRICHER" if _lesion_survives(rules) else "BOTTLENECK" + + +def _rule(t): + return lambda x, _t=t: _t[(x[0] << 2) | (x[1] << 1) | x[2]] + + +def main() -> int: + print("=" * 92) + print("THREAD — the enricher regime (reproducible headline results)") + print("=" * 92) + if not (classify_rules(factoring_control()).structure == "dyadic" + and classify_rules(irreducible_control()).structure == "triadic"): + print(" INSTRUMENT CONTROL FAILED — refusing to run.") + return 1 + print(" Instrument validated.\n") + + print("[1] Refined regime frequencies over 500 random mediated forms (seed 7) — capture split out") + random.seed(7) + cnt = Counter() + for _ in range(500): + cnt[regime([_rule([random.randint(0, 1) for _ in range(8)]) for _ in range(3)])] += 1 + for k in ("dyadic", "BYPASSED", "CAPTURE", "BOTTLENECK", "ENRICHER"): + print(f" {k:<11} {cnt[k]:4d} ({100 * cnt[k] / 500:4.1f}%)") + print(" Genuine enrichment is rare; capture is the dominant in-core regime.") + + print("\n[2] Enrichment is fragile: single-bit perturbations of the symmetric escrow enricher") + base = [[((i >> (2 - (j + 1) % 3)) & 1) & ((i >> (2 - (j + 2) % 3)) & 1) for i in range(8)] + for j in range(3)] # each node = AND of the other two + random.seed(5) + pert = Counter() + for _ in range(150): + t = [row[:] for row in base] + t[random.randint(0, 2)][random.randint(0, 7)] ^= 1 + pert[regime([_rule(t[0]), _rule(t[1]), _rule(t[2])])] += 1 + print(" " + " ".join(f"{k}:{pert[k]}" for k in ("ENRICHER", "CAPTURE", "BYPASSED", "dyadic", "BOTTLENECK"))) + print(" The canonical enricher degenerates into capture under perturbation — it is not defendable.") + + print("\n[3] Outside-option phase diagram (platform S=W&C; rows W's option, cols C's)") + S = lambda x: x[0] & x[2] + Wlv = {"none": lambda x: x[1], "cond": lambda x: x[1] & x[2], "full": lambda x: x[1] | x[2]} + Clv = {"none": lambda x: x[1], "cond": lambda x: x[1] & x[0], "full": lambda x: x[1] | x[0]} + print(f" {'':<10}" + "".join(f"{c:<13}" for c in ("C:none", "C:cond", "C:full"))) + for wk in ("none", "cond", "full"): + print(f" W:{wk:<7}" + "".join(f"{regime([Wlv[wk], S, Clv[ck]]):<13}" for ck in ("none", "cond", "full"))) + + print("\n[4] The core law: platform core = {S} + parties WITHOUT an outside option (4-node battery)") + L4 = ("A", "B", "C", "P") + P4 = lambda x: x[0] & x[1] & x[2] + def party(i, opt): + peer = (i + 1) % 3 + return (lambda x, _p=peer: x[3] | x[_p]) if opt else (lambda x: x[3]) + random.seed(1) + ok = 0 + for _ in range(60): + opts = [random.random() < 0.5 for _ in range(3)] + rules = [party(0, opts[0]), party(1, opts[1]), party(2, opts[2]), P4] + core, _ = major_complex(list(rules), L4) + core = set(core or ()) + predicted = set() if all(opts) else ({"P"} | {("A", "B", "C")[i] for i in range(3) if not opts[i]}) + ok += (core == predicted) or (all(opts) and "P" not in core) + print(f" law holds on {ok}/60 random option configurations") + + print("\n[5] Field instrument: measure each side's outside option, read the platform's fate") + opt = {"none": (lambda x: x[1]), "cond": (lambda x: x[1] & x[2]), "full": (lambda x: x[1] | x[2])} + optC = {"none": (lambda x: x[1]), "cond": (lambda x: x[1] & x[0]), "full": (lambda x: x[1] | x[0])} + for name, wk, ct in [ + ("captive worker, mobile counterpart", "none", "full"), + ("both mobile (mature market)", "full", "full"), + ("neither can exit (arbitration)", "none", "none"), + ("portable reputation (escrow)", "cond", "cond"), + ]: + print(f" {name:<38} [{wk}/{ct}] -> {regime([opt[wk], S, optC[ct]])}") + + print("\n" + "=" * 92) + print(" A platform's irreducible core is itself plus the parties with no outside option.") + print(" Bottleneck (no options) -> enricher (conditional, symmetric, fragile) -> capture") + print(" (asymmetric options, locks in the dependent side) -> bypassed (both options).") + print("=" * 92) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/irreducibility-pipeline/studies/field_mocks.py b/irreducibility-pipeline/studies/field_mocks.py new file mode 100644 index 00000000..19dfc0d7 --- /dev/null +++ b/irreducibility-pipeline/studies/field_mocks.py @@ -0,0 +1,92 @@ +"""Run the 10 mock organizations through the exact-Φ instrument and report the field demo. + +Validates the instrument on its two canonical controls first; refuses to run if either fails. +For each mock it prints the whole-system verdict, the major complex, and — where a sensitivity +variant is defined — the verdict under the alternative encoding and whether it flips. + +Run from the repo root with the venv active: python -m studies.field_mocks +""" + +import csv +import os +import sys + +from studies.mocks import MOCKS +from irreducibility.core import classify_rules +from irreducibility.core import major_complex +from irreducibility.validate import factoring_control, irreducible_control + +_RESULTS = os.path.join(os.path.dirname(__file__), "results") + + +def _verdict(parties, rules): + v = classify_rules(rules, parties) + core, core_phi = major_complex(list(rules), parties) + return v.structure, round(v.max_phi, 3), ("".join(core) if core else "—"), round(max(core_phi, 0.0), 3) + + +def main() -> int: + print("=" * 96) + print("FIELD PROTOCOL DEMO — 10 mock organizations through the exact-Φ instrument") + print("=" * 96) + fac = classify_rules(factoring_control()) + irr = classify_rules(irreducible_control()) + if not (fac.structure == "dyadic" and irr.structure == "triadic"): + print(" INSTRUMENT CONTROL FAILED — refusing to run.") + return 1 + print(" Instrument validated (factoring -> dyadic, irreducible -> triadic).") + print(" These are STIPULATED models of invented organizations. They demonstrate the protocol;") + print(" they measure no real organization. See PROTOCOL.md and FINDINGS.md.\n") + + rows = [] + matched = 0 + flips = [] + for m in MOCKS: + struct, sysphi, core, corephi = _verdict(m.parties, m.rules) + ok = struct == m.predict + matched += ok + flag = "" if ok else " <-- computed verdict overturns the pre-registered reading" + print(f" {m.mid} {m.org}") + print(f" parties {','.join(m.parties)} | predicted {m.predict} | " + f"verdict {struct.upper()} (Φ={sysphi}) | core {core} (Φ={corephi}){flag}") + srow = {"sensitivity": "", "sens_verdict": "", "sens_flips": ""} + if m.sensitivity: + s = m.sensitivity + s_struct, s_sysphi, s_core, s_corephi = _verdict(s.parties, s.rules) + flipped = s_struct != struct + if flipped: + flips.append((m.mid, m.org, struct, s_struct, s.name)) + print(f" sensitivity [{s.name}]: {s_struct.upper()} (Φ={s_sysphi}, core {s_core}) " + f"— {'FLIPS' if flipped else 'holds'}") + srow = {"sensitivity": s.name, "sens_verdict": s_struct, + "sens_flips": flipped} + print() + rows.append({"id": m.mid, "org": m.org, "parties": " ".join(m.parties), + "predict": m.predict, "verdict": struct, "system_phi": sysphi, + "core": core, "core_phi": corephi, "matched": ok, **srow}) + + print("=" * 96) + print(f" {len(MOCKS)} mock organizations | verdict matched the reading fixed before computing: " + f"{matched}/{len(MOCKS)}") + triadic = sum(r["verdict"] == "triadic" for r in rows) + print(f" {triadic} triadic (algorithmacy), {len(rows) - triadic} dyadic (literacy)") + if flips: + print(f" {len(flips)} sensitivity flip(s) — a defensible re-encoding changed the verdict:") + for mid, org, a, b, name in flips: + print(f" {mid} {org}: {a} -> {b} under [{name}]") + print("=" * 96) + + os.makedirs(_RESULTS, exist_ok=True) + path = os.path.join(_RESULTS, "field_mocks.csv") + with open(path, "w", newline="") as fh: + w = csv.DictWriter(fh, fieldnames=["id", "org", "parties", "predict", "verdict", + "system_phi", "core", "core_phi", "matched", + "sensitivity", "sens_verdict", "sens_flips"]) + w.writeheader() + w.writerows(rows) + print(f" Wrote {os.path.relpath(path, os.getcwd())}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/irreducibility-pipeline/studies/forms_library.py b/irreducibility-pipeline/studies/forms_library.py new file mode 100644 index 00000000..468cf72f --- /dev/null +++ b/irreducibility-pipeline/studies/forms_library.py @@ -0,0 +1,125 @@ +"""A curated, reusable library of small coordination forms with exact IIT-4.0 Φ. + +Each form is a named application-layer system given as per-party Boolean rules (little-endian: +0 = Worker, 1 = System/mediator, 2 = Counterpart). Every form carries a one-line rationale for +its coupling — the TPM is derived from the form's actual who-reads-whom, never tuned to a target +Φ — and a set of structural tags so the analysis can ask which feature moves the verdict. + +This is the curated companion to the dissertation's complete 4,096-wiring enumeration +(the author's dissertation code): that one is a coverage/null check over every Boolean +way three nodes can couple; this one is a small set of *recognizable* coordination forms, each +documented, meant to be reused and extended. Five forms are validated in the dissertation's +Paper 2; the rest are first-pass models, flagged as such. + +Structural tags (computed by the form, not assigned to fit Φ): + strict_mediation : True iff there is no direct W<->C edge (parties meet only through S). + mediator_reads_both : True iff S's update depends on BOTH W and C. + back_channel : True iff a direct W<->C edge exists. +""" + +from dataclasses import dataclass +from typing import Callable, List + + +@dataclass +class Form: + key: str + title: str + rules: List[Callable] + rationale: str + validated: bool # True if validated in the dissertation Paper 2 + expected: str # "dyadic" or "triadic" (the documented/known verdict, "?" if open) + + +# -------------------------------------------------------------------------------------- +# Validated forms (dissertation Paper 2) +# -------------------------------------------------------------------------------------- + +FORMS = [ + Form( + key="chat_dyad", + title="Chat with a language model (dyadic limit)", + rules=[lambda x: x[1], lambda x: x[0], lambda x: x[2]], + rationale="Worker and system form a two-party loop; no third human party (C decoupled).", + validated=True, expected="dyadic", + ), + Form( + key="gig_dyadic_model", + title="Rideshare, modeled dyadically (rider dropped from dispatch)", + rules=[lambda x: 1 - x[1], lambda x: x[0], lambda x: x[2] & (1 - x[1])], + rationale="Analyst sees only the driver<->app channel; the dispatch reads the driver alone.", + validated=True, expected="dyadic", + ), + Form( + key="ats_strict_bottleneck", + title="Resume -> ATS -> hiring manager (strict bottleneck)", + rules=[lambda x: x[1], lambda x: x[0] & x[2], lambda x: x[1]], + rationale="S forwards iff resume-signal AND manager-profile; W,C each read only S.", + validated=True, expected="triadic", + ), + Form( + key="ats_feedback_factors", + title="Resume -> ATS -> hiring manager (realistic feedback — yet factors)", + rules=[lambda x: 1 - x[1], lambda x: x[0] & x[2], lambda x: x[1] | x[2]], + rationale="Strict mediator topology, but the reads do not keep each party live to S's commit.", + validated=True, expected="dyadic", + ), + Form( + key="gig_false_dyad", + title="Rideshare driver -> platform -> rider (rider constitutive: the false dyad)", + rules=[lambda x: 1 - x[1], lambda x: x[0] & x[2], lambda x: x[2] & (1 - x[1])], + rationale="Presents as a driver<->app dyad, but dispatch reads the unseen rider (S' = W AND C).", + validated=True, expected="triadic", + ), + + # ---------------------------------------------------------------------------------- + # First-pass forms (NOT yet dissertation-validated) — defensible couplings, flagged. + # ---------------------------------------------------------------------------------- + Form( + key="pure_relay", + title="Pure relay / broadcast (S copies W to C)", + rules=[lambda x: x[0], lambda x: x[0], lambda x: x[1]], + rationale="S relays W to C with no joint determination (S reads only W). Should factor.", + validated=False, expected="dyadic", + ), + Form( + key="two_sided_match", + title="Two-sided match (both parties act on the system's joint commit)", + rules=[lambda x: x[1], lambda x: x[0] & x[2], lambda x: x[1]], + rationale="S commits iff both sides present (W AND C); both W and C track the commit. " + "(Identical coupling to the ATS bottleneck — the canonical match triad.)", + validated=False, expected="triadic", + ), + Form( + key="hierarchy_backchannel", + title="Hierarchy with a direct back-channel (W<->C edge present)", + rules=[lambda x: x[2], lambda x: x[0] & x[2], lambda x: x[0]], + rationale="Same joint commit S' = W AND C, but W and C also read each other directly. " + "Restoring the direct channel should collapse the triad.", + validated=False, expected="dyadic", + ), +] + +FORMS_BY_KEY = {f.key: f for f in FORMS} + + +# -------------------------------------------------------------------------------------- +# Structural tags from the coupling (computed, not assigned) +# -------------------------------------------------------------------------------------- + +def structural_tags(rules): + """Return dict of structural features inferred from the connectivity matrix. + Node order 0=W, 1=S, 2=C.""" + from irreducibility.core import cm_from_rules + cm = cm_from_rules(rules) + # cm[i, j] = 1 iff node j's rule depends on node i. + s_reads_w = cm[0, 1] == 1 + s_reads_c = cm[2, 1] == 1 + w_reads_c = cm[2, 0] == 1 + c_reads_w = cm[0, 2] == 1 + back_channel = bool(w_reads_c or c_reads_w) + return { + "strict_mediation": not back_channel, + "mediator_reads_both": bool(s_reads_w and s_reads_c), + "back_channel": back_channel, + } diff --git a/irreducibility-pipeline/studies/mediator_in_core.py b/irreducibility-pipeline/studies/mediator_in_core.py new file mode 100644 index 00000000..98725a63 --- /dev/null +++ b/irreducibility-pipeline/studies/mediator_in_core.py @@ -0,0 +1,106 @@ +"""Reproducible headline results of the 'is the mediator in the core?' thread (THREAD.md). + +A single through-line, dug 20 questions deep from the M4 anomaly: when is a mediating system a +member of the irreducible coordination, and when is it a bypassable side-channel? This script +reproduces the load-bearing numbers — the platform trichotomy, the membership of the ten mocks, the +regime frequencies over random forms, and the disintermediation trajectory. + +Run from the repo root with the venv active: python -m studies.mediator_in_core +""" + +import os +import random +import sys +from collections import Counter + +os.environ.setdefault("PYPHI_WELCOME_OFF", "true") + +from irreducibility.core import classify_rules +from irreducibility.core import major_complex +from irreducibility.validate import factoring_control, irreducible_control +from studies.mocks import MOCKS + + +def _lesion_survives(rules, labels, mi): + """Do the non-mediator parties still coordinate (triadic) when the mediator is frozen?""" + rest = [i for i in range(len(labels)) if i != mi] + if len(rest) < 2: + return False + for c in (0, 1): + red = [(lambda y, _j=j, _c=c: rules[_j]( + tuple(_c if k == mi else y[rest.index(k)] for k in range(len(labels))))) + for j in rest] + if classify_rules(red, tuple(labels[i] for i in rest)).structure == "triadic": + return True + return False + + +def regime(rules, labels, mi): + """BOTTLENECK / ENRICHER / BYPASSED / dyadic for the mediator at index mi.""" + v = classify_rules(rules, labels) + core, _ = major_complex(list(rules), labels) + core = set(core or ()) + med = labels[mi] + if v.structure == "dyadic": + return "dyadic" + ("" if med in core else " (med out)") + if med not in core: + return "BYPASSED" + return "ENRICHER" if _lesion_survives(rules, labels, mi) else "BOTTLENECK" + + +def main() -> int: + print("=" * 92) + print("THREAD — is the mediator in the irreducible core? (reproducible headline results)") + print("=" * 92) + fac = classify_rules(factoring_control()) + irr = classify_rules(irreducible_control()) + if not (fac.structure == "dyadic" and irr.structure == "triadic"): + print(" INSTRUMENT CONTROL FAILED — refusing to run.") + return 1 + print(" Instrument validated.\n") + + L = ("W", "S", "C") + + print("[1] The platform trichotomy (same mediator can be each, depending on the arrangement)") + tri = { + "BOTTLENECK S=W&C, no fallback": [lambda x: x[1], lambda x: x[0] & x[2], lambda x: x[1]], + "ENRICHER S=W&C, complement": [lambda x: x[1] & x[2], lambda x: x[0] & x[2], lambda x: x[1] & x[0]], + "BYPASSED S=W&C, substitute": [lambda x: x[1] | x[2], lambda x: x[0] & x[2], lambda x: x[1] | x[0]], + } + for name, r in tri.items(): + print(f" {name:<34} -> {regime(r, L, 1)}") + + print("\n[2] The ten field mocks, by mediator regime") + for m in MOCKS: + print(f" {m.mid} {m.org:<32} med={m.parties[1]:<4} -> {regime(m.rules, m.parties, 1)}") + + print("\n[3] Regime frequency over 500 random 3-node mediated forms (seed 7)") + random.seed(7) + cnt = Counter() + for _ in range(500): + rules = [(lambda x, _tt=[random.randint(0, 1) for _ in range(8)]: + _tt[(x[0] << 2) | (x[1] << 1) | x[2]]) for _ in range(3)] + cnt[regime(rules, L, 1).split()[0]] += 1 + for k in ("dyadic", "BYPASSED", "BOTTLENECK", "ENRICHER"): + print(f" {k:<12} {cnt[k]:4d} ({100 * cnt[k] / 500:4.1f}%)") + + print("\n[4] Ride-hail disintermediation trajectory (platform P=D&R fixed; off-platform contact grows)") + Lp = ("D", "P", "R") + P = lambda x: x[0] & x[2] + traj = { + "0 no off-platform contact": [lambda x: x[1], P, lambda x: x[1]], + "1 complement off-platform": [lambda x: x[1] & x[2], P, lambda x: x[1] & x[0]], + "2 substitute off-platform": [lambda x: x[1] | x[2], P, lambda x: x[1] | x[0]], + } + for name, r in traj.items(): + print(f" {name:<28} -> {regime(r, Lp, 1)}") + + print("\n" + "=" * 92) + print(" Load-bearing is relational: whether the platform is in the core is a property of the") + print(" whole arrangement (a Φ-competition with the parties' own coalition), not of the platform.") + print("=" * 92) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/irreducibility-pipeline/studies/mocks.py b/irreducibility-pipeline/studies/mocks.py new file mode 100644 index 00000000..07280a3d --- /dev/null +++ b/irreducibility-pipeline/studies/mocks.py @@ -0,0 +1,166 @@ +"""Ten mock organizations modeled as Boolean coordination forms for the field protocol demo. + +Each mock is an invented but recognizable coordination arrangement, encoded as a small Boolean +dynamical system and classified by exact IIT-4.0 Φ. The rules are stipulated, not elicited from +field evidence, so these are demonstrations of the protocol's mechanics, not findings about any real +organization. Several carry a sensitivity variant: a second defensible encoding that the same story +also permits, to show where the verdict turns on a modeling choice. + +Rules are little-endian: rules[j](x) reads x[0], x[1], ... and returns node j's next bit. See +PROTOCOL.md for the steps these mocks illustrate. +""" + +import os +import sys +from dataclasses import dataclass +from typing import Callable, List, Optional, Sequence, Tuple + +os.environ.setdefault("PYPHI_WELCOME_OFF", "true") + + +@dataclass +class Variant: + name: str + parties: Tuple[str, ...] + rules: Sequence[Callable] + predict: str + what_changes: str + + +@dataclass +class Mock: + mid: str + org: str + parties: Tuple[str, ...] # node labels, in rule order + bits: str # what an active bit means for each party + rules: Sequence[Callable] + predict: str # "triadic" | "dyadic" + rationale: str # the structural reason, fixed before computing + evidence: str # the field evidence a real study would need for these rules + sensitivity: Optional[Variant] = None + + +MOCKS: List[Mock] = [ + + Mock( + "M1", "Ride-hail dispatch", ("D", "P", "R"), + "D=driver available, P=platform commits a match, R=rider requesting", + [lambda x: x[1], lambda x: x[0] & x[2], lambda x: x[1]], + "triadic", + "The platform commits a match that needs an available driver AND a requesting rider; " + "neither sets it alone, and both act on the match. A determination neither party controls.", + "Dispatch logs, the matching/pricing policy, driver and rider app states.", + Variant("substitutable drivers", ("D1", "D2", "P", "R"), + [lambda x: x[2], lambda x: x[2], lambda x: (x[0] | x[1]) & x[3], lambda x: x[2]], + "dyadic", + "If any available driver is interchangeable (the platform reads a pool via OR), no " + "single driver is pivotal and the arrangement factors — the worker dissolves into " + "the pool."), + ), + + Mock( + "M2", "Relay manager", ("W1", "M", "W2"), + "each = the party is acting/reporting; M = the manager's relayed state", + [lambda x: x[1], lambda x: x[0], lambda x: x[1]], + "dyadic", + "The manager copies one worker's report and the other worker reads it. The manager commits " + "nothing of its own; the arrangement is a coupled pair with a downstream reader.", + "Reporting lines, what the manager actually decides versus forwards, meeting records.", + Variant("synthesizing manager", ("W1", "M", "W2"), + [lambda x: x[1], lambda x: x[0] & x[2], lambda x: x[1]], + "triadic", + "A manager who commits a decision that needs both reports (M = W1 ∧ W2, both read " + "M) binds the workers; one who only forwards does not. The verdict turns on whether " + "the manager commits a determination neither worker controls."), + ), + + Mock( + "M3", "Substitutable-seller marketplace", ("B", "P", "S1", "S2"), + "B=buyer ordering, P=platform fills, S1/S2=sellers available", + [lambda x: x[1], lambda x: x[0] & (x[2] | x[3]), lambda x: x[1], lambda x: x[1]], + "dyadic", + "The platform fills the buyer from whichever seller is available (OR over sellers). Each " + "seller is substitutable, none individually pivotal, so the form factors — a broadcast.", + "Order-fill records, whether buyers are indifferent across sellers, substitution rates.", + Variant("specialized seller", ("B", "P", "S"), + [lambda x: x[1], lambda x: x[0] & x[2], lambda x: x[1]], + "triadic", + "If the buyer needs a particular seller (no substitute), the same platform reads " + "triadic. Substitutability, not the platform, is what made it dyadic."), + ), + + Mock( + "M4", "CI code-review gate", ("A", "G", "M"), + "A=author's change, G=CI gate passing, M=maintainer approving", + [lambda x: x[1] & x[2], lambda x: x[0], lambda x: x[0] & x[1]], + "triadic", + "The CI gate commits a pass/fail on the author's code; the maintainer approves reading both " + "code and gate; the author revises reading both. The gate commits what neither party sets.", + "PR/branch-protection config, CI logs, reviewer threads, merge history.", + ), + + Mock( + "M5", "EHR shift handoff", ("N1", "E", "N2"), + "N1=outgoing nurse writing, E=record state, N2=incoming nurse reading", + [lambda x: x[1], lambda x: x[0], lambda x: x[1]], + "dyadic", + "A record that only stores what the outgoing nurse writes, for the incoming nurse to read, " + "is a pipe. The coupling is the writer and the record; the reader is downstream.", + "Handoff policy, whether the EHR enforces anything or only stores, audit logs.", + Variant("active-checklist EHR", ("N1", "E", "N2"), + [lambda x: x[1], lambda x: x[0] & x[2], lambda x: x[1]], + "triadic", + "A record that gates the handoff on a checklist both nurses must complete " + "(E = N1 ∧ N2) commits a determination neither controls; a passive store does not."), + ), + + Mock( + "M6", "Franchise with ratings feedback", ("F", "S", "C"), + "F=franchisee operating to standard, S=brand standard enforced, C=customer experience", + [lambda x: x[1], lambda x: x[0] & x[2], lambda x: x[0]], + "triadic", + "The standard reads compliance and customer ratings and commits what the franchisee must " + "meet; the customer's experience follows operation and feeds ratings back. A closed loop.", + "Franchise agreement, brand-audit records, the rating system and whether it feeds standards.", + ), + + Mock( + "M7", "Algorithmic ranking", ("Cr", "A", "Ad"), + "Cr=creator's content, A=algorithm's ranking, Ad=advertiser placing", + [lambda x: x[1], lambda x: x[0] & x[2], lambda x: x[1]], + "triadic", + "The ranking commits a placement that reads the creator's content and the advertiser's " + "demand; both adapt to the ranking. The algorithm commits what neither party sets alone.", + "Ranking/auction mechanics, creator analytics, advertiser brand-safety rules.", + ), + + Mock( + "M8", "Support-ticket triage", ("Cu", "T", "Ag"), + "Cu=customer's open issue, T=ticket routed, Ag=agent responding", + [lambda x: x[2], lambda x: x[0], lambda x: x[1]], + "dyadic", + "Naively a router: the customer opens a ticket, the ticket routes to an agent, the agent " + "replies. Pre-registered as a pass-through dyad — the computed verdict tests that reading.", + "Ticketing workflow, routing rules, whether the system gates or only forwards.", + ), + + Mock( + "M9", "Grievance arbitration", ("W", "Ar", "E"), + "W=worker/union grievance, Ar=arbitrator's ruling, E=employer position", + [lambda x: x[1], lambda x: x[0] & x[2], lambda x: x[1]], + "triadic", + "The arbitrator commits a ruling reading the grievance and the employer's defense; both are " + "bound by it. The textbook determination neither party controls.", + "Collective-bargaining agreement, the arbitration procedure, case records.", + ), + + Mock( + "M10", "ERP / EDI supply link", ("Su", "ERP", "Bu"), + "Su=supplier fulfilling, ERP=system transmitting, Bu=buyer ordering", + [lambda x: x[2], lambda x: x[2], lambda x: x[0]], + "dyadic", + "The ERP transmits the buyer's order and logs it but commits nothing; the real coupling is " + "buyer and supplier, and the system is a transparent pipe — a spectator on the exchange.", + "EDI/ERP config, whether the system enforces terms or only transmits, transaction logs.", + ), +] diff --git a/irreducibility-pipeline/studies/phiid_measure.py b/irreducibility-pipeline/studies/phiid_measure.py new file mode 100644 index 00000000..03747b51 --- /dev/null +++ b/irreducibility-pipeline/studies/phiid_measure.py @@ -0,0 +1,70 @@ +"""ΦID-based integrated information Φ_R, estimated from a time series via phyid. + +Φ_R is the revised whole-minus-sum integrated information (Mediano et al. 2019). +For a bipartition (A, B) of the system, with `phyid`'s 16 ΦID atoms computed +between the two parts' (integer-coded) time series: + + TDMI = Σ all 16 atoms (joint past → joint future MI) + I_A = rtr + rtx + xtr + xtx (A's past → A's future MI) + I_B = rtr + rty + ytr + yty (B's past → B's future MI) + Φ_WMS = TDMI − I_A − I_B (whole minus sum; can be < 0) + Φ_R = Φ_WMS + rtr (add back double-redundancy) + +The atom bookkeeping is verified against directly-estimated mutual informations +(see the package tests / FINDINGS). We use the **CCS** redundancy. The system's +integrated information is the minimum Φ_R over bipartitions (the MIP analog). +""" + +import numpy as np +from phyid.calculate import calc_PhiID + +REDUNDANCY = "CCS" + + +def _part_int_series(traj, nodes): + """Map a node subset's binary trajectory to an integer state series.""" + s = np.zeros(traj.shape[0], dtype=int) + for k, nd in enumerate(nodes): + s |= traj[:, nd].astype(int) << k + return s.astype(float) + + +def _bipartitions(n): + for mask in range(1, 2 ** (n - 1)): + a = tuple(i for i in range(n) if (mask >> i) & 1) + b = tuple(i for i in range(n) if not ((mask >> i) & 1)) + if a and b: + yield a, b + + +def phi_r_bipartition(A, B, redundancy=REDUNDANCY): + """Φ_R across one bipartition, from the ΦID atoms of part series A, B.""" + atoms, _ = calc_PhiID(A, B, tau=1, kind="discrete", redundancy=redundancy) + m = {k: float(np.mean(v)) for k, v in atoms.items()} + tdmi = sum(m.values()) + i_a = m["rtr"] + m["rtx"] + m["xtr"] + m["xtx"] + i_b = m["rtr"] + m["rty"] + m["ytr"] + m["yty"] + phi_wms = tdmi - i_a - i_b + return phi_wms + m["rtr"] # Φ_R + + +def phi_r_integration(tpm_sbn, n, rng, traj_len=8000): + """ΦID-based integrated information of a network: the minimum Φ_R over + bipartitions, estimated from a simulated trajectory. Returns (phi_r_min, + phi_wms_min) where phi_wms_min is the uncorrected whole-minus-sum minimum.""" + from irreducibility import core as exact_phi + traj = exact_phi.simulate_trajectory(tpm_sbn, n, traj_len, rng) + best_r, best_wms = np.inf, np.inf + for a, b in _bipartitions(n): + A = _part_int_series(traj, a) + B = _part_int_series(traj, b) + atoms, _ = calc_PhiID(A, B, tau=1, kind="discrete", redundancy=REDUNDANCY) + m = {k: float(np.mean(v)) for k, v in atoms.items()} + tdmi = sum(m.values()) + i_a = m["rtr"] + m["rtx"] + m["xtr"] + m["xtx"] + i_b = m["rtr"] + m["rty"] + m["ytr"] + m["yty"] + phi_wms = tdmi - i_a - i_b + best_wms = min(best_wms, phi_wms) + best_r = min(best_r, phi_wms + m["rtr"]) + return (best_r if np.isfinite(best_r) else 0.0, + best_wms if np.isfinite(best_wms) else 0.0) diff --git a/irreducibility-pipeline/studies/proxy_bridge.py b/irreducibility-pipeline/studies/proxy_bridge.py new file mode 100644 index 00000000..3f4aadfc --- /dev/null +++ b/irreducibility-pipeline/studies/proxy_bridge.py @@ -0,0 +1,63 @@ +"""Proxy bridge: can a cheap time-series estimate recover the literacy/algorithmacy verdict? + +The survey's central finding: on real systems exact Φ is intractable, so neuroscience estimates a +proxy from finite time series and reports a lower bound. Organizational coordination also produces +time series (messages, handoffs, decisions). This module tests whether a proxy estimated from +simulated trajectories of a coordination form preserves the binary verdict that exact IIT-4.0 Φ +gives on the form's structure. + +Pipeline per form: + 1. Build the deterministic application-layer TPM from the form's Boolean rules. + 2. Add output noise (the repo's model: tpm_noisy = tpm*(1-noise) + (1-tpm)*noise), so trajectories + explore states the way noisy real data does. + 3. Estimate the ΦID-based proxy Φ_R (CCS redundancy) from a simulated trajectory — reusing + phiid_vs_phi.phiid_measure, the same estimator validated in this repo's data-style study. + 4. Compare to the exact structural verdict (classifier on the deterministic form) and to exact Φ + recomputed on the noisy TPM (apples-to-apples reference). + +Run: python -m studies.proxy_bridge +""" + +import os +import sys + +os.environ.setdefault("PYPHI_WELCOME_OFF", "true") + +import numpy as np + +from irreducibility.core import tpm_from_rules, cm_from_rules, classify, PHI_EPS +from studies.phiid_measure import phi_r_integration +from irreducibility import core as exact_phi + + +def add_noise(tpm_sbn, noise): + """Mix a deterministic state-by-node TPM toward the flipped output by `noise`.""" + return tpm_sbn * (1.0 - noise) + (1.0 - tpm_sbn) * noise + + +def exact_phi_max_noisy(tpm_noisy, cm, n, rng, traj_len=2000): + """Exact IIT-4.0 max system Φ on the noisy TPM (all states reachable when noise>0).""" + mean_phi, max_phi, _ = exact_phi.network_phi(tpm_noisy, cm, n, rng) + return max_phi + + +def proxy_for_form(rules, noise, rng, traj_len=8000): + """Return (structure, exact_phi_det_max, exact_phi_noisy_max, proxy_phi_r, proxy_phi_wms). + + structure : 'triadic'/'dyadic' from the deterministic form (the ground truth). + exact_phi_det_max : max exact Φ on the deterministic form. + exact_phi_noisy_max: max exact Φ on the noisy TPM (reference). + proxy_phi_r : ΦID Φ_R (CCS) estimated from the simulated noisy trajectory. + proxy_phi_wms : uncorrected whole-minus-sum Φ (the candidate_audit's best-tracking proxy), + estimated from the same trajectory — the proxy's strongest form. + """ + n = len(rules) + tpm_det = tpm_from_rules(rules) + cm = cm_from_rules(rules) + + verdict = classify(tpm_det, cm) + tpm_noisy = add_noise(tpm_det, noise) + phi_noisy = exact_phi_max_noisy(tpm_noisy, cm, n, rng, traj_len) + phi_r, phi_wms = phi_r_integration(tpm_noisy, n, rng, traj_len=traj_len) + + return verdict.structure, verdict.max_phi, phi_noisy, phi_r, phi_wms diff --git a/irreducibility-pipeline/studies/proxy_run.py b/irreducibility-pipeline/studies/proxy_run.py new file mode 100644 index 00000000..5a7f1a08 --- /dev/null +++ b/irreducibility-pipeline/studies/proxy_run.py @@ -0,0 +1,91 @@ +"""Run the proxy bridge over the corpus forms x noise levels x seeds; write results/bridge.csv. + +Also runs a pure-independence control (two decoupled parties) that must give proxy ≈ 0. + +Run: python -m studies.proxy_run [traj_len] +""" + +import csv +import os +import sys +import time + +import numpy as np + +from studies import forms_library as lib +from studies import proxy_bridge as bridge + +_HERE = os.path.dirname(__file__) +_RESULTS = os.path.join(_HERE, "results") + +NOISE_LEVELS = [0.05, 0.1, 0.2] +SEEDS = [1, 2, 3] + + +def main(traj_len=8000): + os.makedirs(_RESULTS, exist_ok=True) + rows = [] + start = time.time() + print(f"PROXY BRIDGE — ΦID Φ_R from trajectories vs exact verdict " + f"(traj_len={traj_len}, noise={NOISE_LEVELS}, seeds={SEEDS})") + print("=" * 96) + for f in lib.FORMS: + for noise in NOISE_LEVELS: + for seed in SEEDS: + rng = np.random.default_rng(seed) + structure, phi_det, phi_noisy, phi_r, phi_wms = bridge.proxy_for_form( + f.rules, noise, rng, traj_len=traj_len) + rows.append({ + "form": f.key, "structure": structure, "noise": noise, "seed": seed, + "exact_phi_det": f"{phi_det:.6f}", "exact_phi_noisy": f"{phi_noisy:.6f}", + "proxy_phi_r": f"{phi_r:.6f}", "proxy_phi_wms": f"{phi_wms:.6f}", + }) + # progress line: mean proxy by form + sub = [r for r in rows if r["form"] == f.key] + mean_pr = np.mean([float(r["proxy_phi_r"]) for r in sub]) + print(f" {f.key:<24} {structure:<8} mean Φ_R={mean_pr:+.4f} " + f"(exact det Φ={phi_det:.3f}) [{time.time()-start:.0f}s]") + + _write(rows) + _summary(rows) + + +def _write(rows): + out = os.path.join(_RESULTS, "bridge.csv") + with open(out, "w", newline="") as fh: + w = csv.DictWriter(fh, fieldnames=list(rows[0].keys())) + w.writeheader() + w.writerows(rows) + print(f"\nWrote {out}") + + +def _separation(rows, key, label): + tri = [float(r[key]) for r in rows if r["structure"] == "triadic"] + dya = [float(r[key]) for r in rows if r["structure"] == "dyadic"] + wins = sum(t > d for t in tri for d in dya) + ties = sum(t == d for t in tri for d in dya) + auc = (wins + 0.5 * ties) / (len(tri) * len(dya)) + all_vals = sorted(set(tri + dya)) + best_acc, best_thr = 0.0, None + for thr in all_vals: + acc = (sum(t >= thr for t in tri) + sum(d < thr for d in dya)) / (len(tri) + len(dya)) + if acc > best_acc: + best_acc, best_thr = acc, thr + print(f" [{label}] triadic mean={np.mean(tri):+.4f} dyadic mean={np.mean(dya):+.4f} " + f"rank-AUC={auc:.3f} best-thr acc={best_acc:.3f} @ {best_thr:+.4f}") + return auc + + +def _summary(rows): + """Does either cheap proxy preserve the binary verdict? Report separation for both.""" + print("\n" + "=" * 96) + print("SEPARATION: does a cheap time-series proxy preserve the dyadic/triadic verdict?") + _separation(rows, "proxy_phi_r", "Φ_R (CCS) ") + _separation(rows, "proxy_phi_wms", "Φ_WMS (wms)") + print(" (rank-AUC 0.5 = chance; exact Φ on the deterministic form is the ground truth)") + print("=" * 96) + + +if __name__ == "__main__": + traj_len = int(sys.argv[1]) if len(sys.argv) > 1 else 8000 + main(traj_len) diff --git a/irreducibility-pipeline/studies/thompson_ordering.py b/irreducibility-pipeline/studies/thompson_ordering.py new file mode 100644 index 00000000..54fdfa62 --- /dev/null +++ b/irreducibility-pipeline/studies/thompson_ordering.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python +"""Q43 / H1 — the naive Thompson ordering fails under one uniform modeling convention. + +Form / ensemble: a matched triple at n=3, AND determination family, little-endian. + Pooled (independent-contribution relay): [x->S, x->W, x->S] + Sequential (pass-through chain): [x->S, x->(W&C), x->S] + Reciprocal (feedback cycle, cyclic form): [x->S, x->(W&C), x->S] +Labels (W, S, C). + +Measure: verdict().structure and .max_phi for each; rank the three Φ. + +Instrument control (run first): the pass-through mediator chain at n=3 must read triadic, +max_phi = 2.0, MIP "2 parts: {W,SC}". Abort if it fails. + +Decision rule (fixed before run): H1 confirmed if pooled is not the strict Φ-minimum OR +sequential Φ does not fall strictly between pooled and reciprocal; refuted only if the three +Φ are strictly monotone in Thompson order with pooled dyadic. +""" + +import csv +import os +import sys + +# Repo root onto sys.path so this runs as a direct script and via the package. +os.environ.setdefault("PYPHI_WELCOME_OFF", "true") + +from irreducibility.core import classify_rules, PHI_EPS # noqa: E402 +from irreducibility.core import verdict # noqa: E402 + +LABELS = ("W", "S", "C") + +# --- Forms (n=3, AND family, little-endian; x[0]=W, x[1]=S, x[2]=C) --- +POOLED = [lambda x: x[1], lambda x: x[0], lambda x: x[1]] +SEQUENTIAL = [lambda x: x[1], lambda x: x[0] & x[2], lambda x: x[1]] +RECIPROCAL = [lambda x: x[1], lambda x: x[0] & x[2], lambda x: x[1]] + +RESULTS_DIR = os.path.join(os.path.dirname(__file__), "results") + + +def instrument_control(): + """The pass-through chain must read triadic at Φ=2.0 with MIP '2 parts: {W,SC}'.""" + v = verdict(SEQUENTIAL, LABELS) + assert v.structure == "triadic", f"control structure {v.structure!r} != 'triadic'" + assert abs(v.max_phi - 2.0) < 1e-6, f"control max_phi {v.max_phi} != 2.0" + assert v.mip_partition == "2 parts: {W,SC}", ( + f"control MIP {v.mip_partition!r} != '2 parts: {{W,SC}}'" + ) + return v + + +def main(): + print("=== Q43 / H1 — Thompson ordering under one uniform convention (n=3, AND) ===") + + ctrl = instrument_control() + print("[instrument control] pass-through chain: " + f"structure={ctrl.structure}, max_phi={ctrl.max_phi:.6f}, " + f"MIP={ctrl.mip_partition!r} -> PASS") + + forms = [ + ("pooled", "independent-contribution relay", POOLED), + ("sequential", "pass-through chain", SEQUENTIAL), + ("reciprocal", "feedback cycle (cyclic)", RECIPROCAL), + ] + + rows = [] + for name, desc, rules in forms: + v = classify_rules(rules, labels=LABELS) + rows.append({ + "thompson_type": name, + "form": desc, + "structure": v.structure, + "max_phi": v.max_phi, + "mip_partition": v.mip_partition, + "n_states_irreducible": v.n_states_irreducible, + }) + print(f"\n[{name}] {desc}") + print(f" structure = {v.structure}") + print(f" max_phi = {v.max_phi:.6f}") + print(f" MIP = {v.mip_partition!r}") + + phi = {r["thompson_type"]: r["max_phi"] for r in rows} + struct = {r["thompson_type"]: r["structure"] for r in rows} + p_pool, p_seq, p_rec = phi["pooled"], phi["sequential"], phi["reciprocal"] + + print("\n=== Φ ranking (Thompson order: pooled, sequential, reciprocal) ===") + print(f" pooled Φ = {p_pool:.6f} ({struct['pooled']})") + print(f" sequential Φ = {p_seq:.6f} ({struct['sequential']})") + print(f" reciprocal Φ = {p_rec:.6f} ({struct['reciprocal']})") + + # Decision rule (fixed before run). + pooled_is_strict_min = (p_pool < p_seq - PHI_EPS) and (p_pool < p_rec - PHI_EPS) + seq_strictly_between = (p_pool + PHI_EPS < p_seq) and (p_seq + PHI_EPS < p_rec) + pooled_dyadic = struct["pooled"] == "dyadic" + + strict_monotone = ( + pooled_dyadic + and (p_pool + PHI_EPS < p_seq) + and (p_seq + PHI_EPS < p_rec) + ) + + step1_fails = not pooled_is_strict_min # pooled not the strict minimum + step2_fails = not seq_strictly_between # sequential not strictly between + + if step1_fails or step2_fails: + decision = "confirmed" + elif strict_monotone: + decision = "refuted" + else: + decision = "partial" + + print("\n=== Decision (rule fixed before run) ===") + print(f" pooled is strict Φ-minimum? {pooled_is_strict_min}") + print(f" sequential strictly between pool/recip? {seq_strictly_between}") + print(f" pooled dyadic? {pooled_dyadic}") + print(f" strictly monotone in Thompson order? {strict_monotone}") + print(f" H1 VERDICT: {decision.upper()}") + + os.makedirs(RESULTS_DIR, exist_ok=True) + csv_path = os.path.join(RESULTS_DIR, "thompson_ordering.csv") + with open(csv_path, "w", newline="") as fh: + w = csv.DictWriter(fh, fieldnames=list(rows[0].keys())) + w.writeheader() + w.writerows(rows) + print(f"\nwrote {csv_path}") + + return decision + + +if __name__ == "__main__": + main() diff --git a/irreducibility-pipeline/tests/test_pipeline.py b/irreducibility-pipeline/tests/test_pipeline.py new file mode 100644 index 00000000..8aacc784 --- /dev/null +++ b/irreducibility-pipeline/tests/test_pipeline.py @@ -0,0 +1,110 @@ +"""Tests: instrument controls, the rule parser, the evidence gate, and the worked examples.""" + +import json +import os + +import pytest + +from irreducibility.core import classify_rules, major_complex +from irreducibility.validate import factoring_control, irreducible_control, FORMS, EXPECTED +from irreducibility.rules import compile_rule +from irreducibility.encoding import validate +from irreducibility.encode_check import check_quotes +from irreducibility.analyze import analyze +from irreducibility.regime import regime + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +EX = os.path.join(ROOT, "examples") + + +def test_controls(): + assert classify_rules(factoring_control()).structure == "dyadic" + v = classify_rules(irreducible_control()) + assert v.structure == "triadic" and abs(v.max_phi - 0.830075) < 1e-4 + + +@pytest.mark.parametrize("name", sorted(FORMS)) +def test_regression_forms(name): + assert classify_rules(FORMS[name]()).structure == EXPECTED[name] + + +def test_strict_mediation_triad(): + rules = FORMS["strict_mediation_triad"]() + v = classify_rules(rules) + assert v.structure == "triadic" and abs(v.max_phi - 2.0) < 1e-9 + assert set(major_complex(rules, ("W", "S", "C"))[0]) == {"W", "S", "C"} + + +def test_parser_matches_lambda(): + labels = ("D", "P", "R") + f = compile_rule("D and R", labels) + g = compile_rule("(D or R) and not P", labels) + h = compile_rule("D xor R", labels) + for s in range(8): + x = tuple((s >> i) & 1 for i in range(3)) + assert f(x) == (x[0] & x[2]) + assert g(x) == ((x[0] | x[2]) & (1 - x[1])) + assert h(x) == (x[0] ^ x[2]) + + +@pytest.mark.parametrize("bad", ["__import__('os')", "D + R", "D and Q", "2"]) +def test_parser_rejects(bad): + with pytest.raises((ValueError, SyntaxError)): + compile_rule(bad, ("D", "P", "R")) + + +def _doc(name): + with open(os.path.join(EX, name, "encodings.json"), encoding="utf-8") as f: + return json.load(f) + + +def test_gate_rejects_rule_without_evidence(): + doc = _doc("01_gig_dispatch") + doc["encodings"][0]["evidence"]["P"] = [] + assert any("cites no evidence" in p for p in validate(doc)) + + +def test_gate_rejects_missing_prediction(): + doc = _doc("01_gig_dispatch") + del doc["encodings"][0]["predicted"] + assert any("predicted" in p for p in validate(doc)) + + +def test_gate_rejects_invented_quote(): + doc = _doc("01_gig_dispatch") + doc["encodings"][0]["evidence"]["P"][0]["quote"] = "The platform decides everything." + assert check_quotes(doc, os.path.join(EX, "01_gig_dispatch")) + + +def test_gig_dispatch(): + rep = {r["id"]: r for r in analyze(_doc("01_gig_dispatch"))["encodings"]} + assert rep["A"]["structure"] == "triadic" and set(rep["A"]["core"]) == {"D", "P", "R"} + assert rep["A"]["regime"] == "BOTTLENECK" and rep["A"]["contingency"]["kind"] == "intrinsic" + assert rep["B"]["structure"] == "dyadic" + assert rep["C"]["structure"] == "dyadic" and set(rep["C"]["core"]) == {"P", "R"} + assert [rep[k]["regime"] for k in ("O1", "O2", "O3", "O4", "O5")] == \ + ["BOTTLENECK", "ENRICHER", "CAPTURE", "CAPTURE", "BYPASSED"] + assert set(rep["O3"]["core"]) == {"D", "P"} and set(rep["O4"]["core"]) == {"P", "R"} + + +def test_insurance_claim(): + rep = {r["id"]: r for r in analyze(_doc("02_insurance_claim"))["encodings"]} + assert set(rep["pipe"]["core"]) == {"C", "E", "A"} + assert set(rep["gated"]["core"]) == {"C", "E"} + assert set(rep["loop"]["core"]) == {"E", "A"} + assert set(rep["loop_nolearn"]["core"]) == {"C", "A"} + assert rep["frozen"]["structure"] == "dyadic" + + +def test_dealer_vs_clearinghouse(): + rep = {r["id"]: r for r in analyze(_doc("04_dealer_vs_clearinghouse"))["encodings"]} + assert rep["dealer"]["contingency"]["kind"] == "contingent" + assert rep["clearinghouse"]["contingency"]["kind"] == "intrinsic" + + +def test_regime_three_way_platform(): + L = ("W", "S", "C") + S = lambda x: x[0] & x[2] + assert regime([lambda x: x[1], S, lambda x: x[1]], L, "S") == "BOTTLENECK" + assert regime([lambda x: x[1] & x[2], S, lambda x: x[1] & x[0]], L, "S") == "ENRICHER" + assert regime([lambda x: x[1] | x[2], S, lambda x: x[1] | x[0]], L, "S") == "BYPASSED" diff --git a/submissions/orgsci_ai_frontiers_methods/README.md b/submissions/orgsci_ai_frontiers_methods/README.md index 8cc2b377..0f192ca2 100644 --- a/submissions/orgsci_ai_frontiers_methods/README.md +++ b/submissions/orgsci_ai_frontiers_methods/README.md @@ -4,15 +4,15 @@ **Current version:** the up-to-date proposal is the author's Google Doc: . The Markdown files here are Claude's v3 draft and the review against that doc; where they differ, the Google Doc governs. -**Status:** v3 drafted 26 Oct 2026 and not yet submitted. It was planned against the CFP PDF only, with Fable planning the writing. The proposal (1,984 words) presents the AI + PyPhi pipeline that tests a coordinative structure for irreducibility, and the strategic model as Stage 2. The submission repository `irreducibility-pipeline` is built and committed locally at `~/iit-playground/irreducibility-pipeline` (tag `v0.1-stage1`; 19 tests and 17 reproduce checks pass in a fresh venv) and is not yet pushed to GitHub. v1 and v2 are retired. **Due 1 Nov 2026.** +**Status:** v3 drafted 26 Oct 2026. The reviewed Stage 1 export (v7) and the current deck are in [`../proposals/orgsci_ai_2026/`](../proposals/orgsci_ai_2026/). The prototype lives in this repository at [`../../irreducibility-pipeline/`](../../irreducibility-pipeline/). v1 and v2 are retired. **Due 1 Nov 2026.** -**The call:** a special issue that develops AI-enabled research infrastructure, with a workshop at Duke on 19–20 Feb 2027. Digest: [`cfp/README.md`](cfp/README.md). +**The call:** a special issue that develops AI-enabled research infrastructure. The development workshop is **27–28 February 2027 (tentative)**. Digest: [`cfp/README.md`](cfp/README.md). | Milestone | Date (from the editors) | |---|---| | Proposal, technical appendix and repository | **1 Nov 2026** | -| Development workshop | 19–20 Feb 2027 (date may change) | -| Final papers (2,500–4,500 words) | Summer 2027 | +| Development workshop | 27–28 February 2027 (tentative) | +| Final papers | Summer 2027 | **Angle (v3):** exactly how AI and PyPhi test a coordinative structure for irreducibility, and why that matters for strategy as organizations rely on triadic infrastructure. The GitHub repo is the prototype. diff --git a/submissions/orgsci_ai_frontiers_methods/cfp/README.md b/submissions/orgsci_ai_frontiers_methods/cfp/README.md index 80618399..22a0751c 100644 --- a/submissions/orgsci_ai_frontiers_methods/cfp/README.md +++ b/submissions/orgsci_ai_frontiers_methods/cfp/README.md @@ -11,7 +11,7 @@ ## Stages (verbatim) - "Stage 1: Submit research proposal and package (Deadline: November 1, 2026)" -- "Stage 2: Engage in development process (January-May, 2027)". The workshop is at Duke on 19–20 Feb 2027, per the 9 Oct post. The July post said 27–28 Feb. +- "Stage 2: Engage in development process (January-May, 2027)". The workshop date in this package is 27–28 February 2027 (tentative); the call names no venue. The 9 Oct post had said Duke on 19–20 Feb 2027; the July post said 27–28 Feb. - "Stage 3: Finalization of research projects (Summer, 2027)" - Final papers are "Nature-style ... between 2,500 and 4,500 words." diff --git a/submissions/proposals/orgsci_ai_2026/Do-Platforms-Reduce-to-Pairs-IIT-PyPhi.pptx b/submissions/proposals/orgsci_ai_2026/Do-Platforms-Reduce-to-Pairs-IIT-PyPhi.pptx new file mode 100644 index 00000000..0317470f Binary files /dev/null and b/submissions/proposals/orgsci_ai_2026/Do-Platforms-Reduce-to-Pairs-IIT-PyPhi.pptx differ diff --git a/submissions/proposals/orgsci_ai_2026/README.md b/submissions/proposals/orgsci_ai_2026/README.md index aa52a9f9..79269ff1 100644 --- a/submissions/proposals/orgsci_ai_2026/README.md +++ b/submissions/proposals/orgsci_ai_2026/README.md @@ -3,43 +3,52 @@ Stage 1 package for the *Organization Science* special issue "AI-Enabled Frontiers in Organizational Science" (editors Gartenberg, Hasan, Pierce, Bail, Dai, Hauser, Rahman, and Zhang). The call asks for a short proposal, a technical supplement, and a research artifact. The portal deadline is **1 November -2026**. A development workshop follows at Duke on 19–20 February 2027, and final papers of 2,500–4,500 -words are due in summer 2027. +2026**. The development workshop is **27–28 February 2027 (tentative)**. Final papers follow in summer +2027. The working title is *Beyond the Dyadic Straitjacket: Bringing Integrated Information Theory (IIT 4.0) and PyPhi to Organizational Coordination via a Self-Exemplifying Research Harness.* Part I is the -prospectus, about 1,880 words. It argues that exact system integrated information (Φ) over the +prospectus (1,992 words). It argues that exact system integrated information (Φ) over the minimum-information partition separates four coordination regimes that organizational prose conflates, and that the lab's harness — the scholar, the AI agents, and PyPhi — is itself the triad under study. Part II is the technical addendum: formal mechanics, worked tables, and the verification compendium. -The ten-slide deck carries the same argument in the minimal black-on-white style of the Port of Spain -talk, [`../../triadic_reduction/talk/trinidad-2026/Do-Triads-Reduce-to-Dyads-Trinidad.pptx`](../../triadic_reduction/talk/trinidad-2026/Do-Triads-Reduce-to-Dyads-Trinidad.pptx). +The current ten-slide deck, *Do Platforms Reduce to Pairs?*, carries that argument in the minimal +black-on-white style of the Port of Spain talk and adds a QR code to the lab. | File | What it is | | --- | --- | -| [`gdoc_1fhM_v6_story_plus_addendum.md`](gdoc_1fhM_v6_story_plus_addendum.md) | Stage 1 prospectus and technical addendum, exported from the author's Google Doc [`1fhM_C7pz6e3sR7aXY3_89oys06B-UyK9Vyf93bt1zFA`](https://docs.google.com/document/d/1fhM_C7pz6e3sR7aXY3_89oys06B-UyK9Vyf93bt1zFA/edit) | -| [`Beyond-the-Dyadic-Straitjacket-IIT-PyPhi.pptx`](Beyond-the-Dyadic-Straitjacket-IIT-PyPhi.pptx) | Ten-slide deck | +| [`gdoc_1fhM_v6_story_plus_addendum.md`](gdoc_1fhM_v6_story_plus_addendum.md) | v7 reviewed prospectus and technical addendum, exported from Google Doc [`1fhM_C7pz6e3sR7aXY3_89oys06B-UyK9Vyf93bt1zFA`](https://docs.google.com/document/d/1fhM_C7pz6e3sR7aXY3_89oys06B-UyK9Vyf93bt1zFA/edit). Incorporates Stage 1 review items 0.1–0.11, F.1–F.19, and F.23–F.24 | +| [`Do-Platforms-Reduce-to-Pairs-IIT-PyPhi.pptx`](Do-Platforms-Reduce-to-Pairs-IIT-PyPhi.pptx) | Current ten-slide deck, with the QR code | +| [`Beyond-the-Dyadic-Straitjacket-IIT-PyPhi.pptx`](Beyond-the-Dyadic-Straitjacket-IIT-PyPhi.pptx) | Earlier ten-slide deck of the same argument | +| [`STAGE1_REVIEW.md`](STAGE1_REVIEW.md) | Audit of the pre-review text against the call, the prototype, and the lab | +| [`../../../irreducibility-pipeline/`](../../../irreducibility-pipeline/) | The prototype: rival encodings, the evidence gate, and exact Φ(MIP) | ## Status -The package was filed in the lab on 27 October 2026, ahead of the portal deadline. Manuscript Central -has not received it. An earlier draft lives on the open branch `submission/cfp-arms-2026-10`, under -`submissions/orgsci_ai_frontiers_methods/`. That branch's v3 points at the same Google Doc and treats -the doc as the current text. This folder holds the later export: the v6 prospectus, the technical -addendum, and the deck. +The package was filed in the lab on 27 October 2026, ahead of the 1 November portal deadline. The v7 +export is the text that answers [`STAGE1_REVIEW.md`](STAGE1_REVIEW.md). The prototype lives in this +repository at [`../../../irreducibility-pipeline/`](../../../irreducibility-pipeline/), and the lab +check `irreducibility-pipeline-reproduce` covers its 17 reference results. The workshop date is +**27–28 February 2027 (tentative)**; the call names no venue. [`STAGE1_REVIEW.md`](STAGE1_REVIEW.md) +reads Stage 3 as short *Science*/*Nature*-style articles plus a technical appendix. + +An earlier v3 draft remains at [`../../orgsci_ai_frontiers_methods/`](../../orgsci_ai_frontiers_methods/). +The branch `submission/cfp-arms-2026-10` is where that draft was opened. The addendum's numbers are evidence about Boolean coordination models. No worker is measured. Φ is the instrument the proposal uses to explore whether a coordination form is irreducible. ## The ten slides -1. Beyond the Dyadic Straitjacket +*Do Platforms Reduce to Pairs?* + +1. Do Platforms Reduce to Pairs? 2. From Literacy to Algorithmacy -3. Do Algorithmic Triads Reduce to Dyads? -4. Integrated Information Theory (IIT 4.0) and PyPhi -5. The Minimum Information Partition -6. The Four Coordination Regimes -7. Ride-Hail Dispatch Under the Microscope -8. Power in the Triad: Lock-In and Escape -9. Why AI: A Research Harness, Not an Oracle -10. Fork the Harness +3. Is a Platform a Third Party or Just a Fast Go-Between? +4. Testing Coordination with IIT 4.0 and PyPhi +5. Two Questions Every Three-Party System Answers +6. Four Kinds of Three-Party Coordination +7. Same Three Parties, Two Different Rules +8. How Platforms Keep Lock-In — and How It Breaks +9. An Open AI Harness, Not an AI Judge +10. Fork the Repo and Test Your Own Case diff --git a/submissions/proposals/orgsci_ai_2026/STAGE1_REVIEW.md b/submissions/proposals/orgsci_ai_2026/STAGE1_REVIEW.md new file mode 100644 index 00000000..1ea8c62e --- /dev/null +++ b/submissions/proposals/orgsci_ai_2026/STAGE1_REVIEW.md @@ -0,0 +1,634 @@ +# Stage 1 review: "Beyond the Dyadic Straitjacket" against the *Organization Science* call + +Reviewed 27 October 2026 against the CFP PDF (`CFP_AI-Enabled Frontiers in Organizational Science`, +7 pages) and the live Google Doc `1fhM_C7pz6e3sR7aXY3_89oys06B-UyK9Vyf93bt1zFA` as it stood at +11:41 UTC that day (8,852 words; Part I 1,890). The export in this folder, +[`gdoc_1fhM_v6_story_plus_addendum.md`](gdoc_1fhM_v6_story_plus_addendum.md), is 130 words shorter and +has different A.2–A.5 and appendix headings, so the Doc, not the export, is the text reviewed. + +**What I read in full:** the Doc, the CFP, the prototype's `README.md` and `APPENDIX.md`, the FINDINGS +files of every lab study the Doc cites, Quine (1954), both Hereth Correia & Pöschel papers (2004 from +the copy in `~/Downloads`, 2006 all 23 pages), Koshkin's primitive-positive paper (arXiv 2606.19492v1, +19 pages), the dyad and triad pages of Wolff's Simmel (archive.org scan), the abstracts of every source +the attribution audit names. **What I did not read:** the published *IGPL* version of Koshkin's +paper (theorem numbers are verified against the arXiv version only) and Koshkin's 2024 *IGPL* paper +beyond its abstract. Consensus was out of monthly quota and Scholar Gateway returned ACCESS_DENIED, +so Crossref, OpenAlex, Semantic Scholar and the publishers' pages stood in for them. + +**Every number in Part C comes from a fresh run**, not from a FINDINGS file: the prototype's +`reproduce.py` (17/17) and `pytest` (19 passed), `irreducibility.analyze` on all four examples and on +the logged adversary run, `studies.enricher_regime`, `studies.mediator_in_core`, `studies.census`, +`encode_check` on the three AI files, and the eighteen lab CI checks the Doc leans on (17 pass; one +fails, see C7). Outputs sit in +`/private/tmp/claude-501/-Users-ludwitt/99b8f63e-f3ca-4c8c-ab30-c300eeb75236/scratchpad/evidence/` +(`proto_*.txt`, `lab_ci_named.txt`, `crossref/*.json`). + +**How to use this file.** Each finding states the Doc's text, the fact, the source, and a replacement +sentence where one is needed. Replacement text is marked `[DRAFTED by Claude]`; the wording around it +stays yours. Nothing here has been applied to the Doc. + +--- + +## 0. The verdict, and the items that block submission + +The package fits the call better than its v3 draft feared, and its spine is sound: large language +models fail as structural judges, so the loop confines them to evidence-bound reading under a +deterministic gate and lets exact computation decide, and the logged runs show the model's own +predictions failing. That is an "AI-enabled research loop under human direction" with a built-in +boundary test, which is two of the CFP's categories at once. The prose is strong. The addendum is +not yet true to the prototype it describes. + +Eleven items block submission because a reviewer who forks the repository will find them within an +hour: + +1. **The prototype is not forkable.** `irreducibility-pipeline` (tag `v0.1-stage1`) existed only on your + disk with no git remote. It now sits inside the lab at `irreducibility-pipeline/` (see C6); the Doc's + references to it as a separate artifact need the new path and the lab tag. +2. **"56 dyadic, 132 cycle-supported, 68 mediated triads" and "96 of 256"** (§4, A.3, Appendix C) have no + source in either repository. The only 256-form census is the prototype's `census`: 24 triadic, 232 + dyadic. (C3.) +3. **Table 3's outside-option rows O₂–O₅ are not the prototype's O1–O5**, and their verdicts contradict the + study they resemble: both parties mobile gives BYPASSED {D,R}, not "Φ = 0, complete dissolution". (C2.) +4. **Example 03 (code-review gate)** in Table 5 reports parties, rules and results the prototype does not + produce. Actual: `gated` is triadic at Φ = 1.000 with core {A, M} and the gate BYPASSED. (C2.) +5. **Example 04 (dealer vs clearinghouse)** is not dyadic-vs-triadic; both are triadic at Φ = 2.000 and the + distinction is contingent vs intrinsic. (C2.) +6. **Example 02's parties and encoding counts** are wrong (engine `E`, not "Intake Portal (M)"; five design + encodings, not "2 rival + 4 underspecified"). (C2.) +7. **Φ(MIP) = 1.198 and 1.000** in Table 3 and Table 4 are wrong: the direct-tie bypass computes to 0.830; + the pooled-driver system computes to 0.000 (dyadic) with {P, R} as its major complex. (C2.) +8. **Six file paths do not exist** (`encode/runs/`, the three `*_drafter.json` / `*_adversary.json` names, + `irreducibility/controls.py`, `studies/strategic_model/`), and two more are modules, not directories. + (C1.) +9. **Two reference-list entries are fabricated records**: Cameron (2024) carries an invented title, issue and + pages; "Koshkin (2025) … *IJAR* 186, 109523" is a different paper's article number. Three works cited in + the text are missing from the list (Stark & Pais 2020; Rosenblat & Stark 2016; Tononi 2004). (D.) +10. **Four Appendix D figures have no source** (R² = 0.992; "3 bits → 5.755 bits"; "4/8 formal vs shadow"; + "hybrid team designs factor cleanly"), and twelve study labels in that table are not the names of any + study or check. (C4.) +11. **"[Anonymized for Double-Blind Stage 1 Review]"** sits above a link to a public repository under your + name. The CFP asks for no blinding. You decided to name the author; the line needs replacing. (A.) + +Everything else is listed in F by priority. + +--- + +## A. CFP compliance + +| CFP asks | Where the Doc answers | Gap or fix | +|---|---|---| +| Proposal 1,500–2,000 words plus references, 3–5 pages | Part I §1–5, **1,890 words** (`wc -w` on the export's lines 11–142) | None. | +| "what you have done" | §3–§4; A.2 | None. | +| "what you hope to do" | §4 Stage 2 workstreams; A.3; App. C | None. | +| "the key risks you face in fully executing your vision" | §5 gives four *boundary conditions* of the method. Execution risks appear only in the addendum: IRB timing (A.3 item 3), open-weight model performance (A.3 item 1), coder agreement target (prototype APPENDIX H: Krippendorff's α ≥ 0.80, absent from the Doc) | Add one sentence to §5 naming the execution risks: `[DRAFTED by Claude]` "Three risks govern Stage 2: the field protocol waits on IRB approval; the encoding step must hold up on open-weight models, not only on the commercial one we logged; and AI–human coder agreement (target Krippendorff's α ≥ 0.80 per rule) is not yet measured." | +| "how organizational and social science would change if you are successful" | §5 closing paragraph; A.5 | None. | +| Technical appendix "details needed to evaluate and understand the work" | Part II + Appendices A–D | Fix the factual items in C; add table captions (the text cites Tables 1–6, the tables carry none). | +| Research artifact: "a Git repository or equivalent artifact that includes a prototype or proof of concept" | Links `algorithmacy-lab`; names `irreducibility-pipeline v0.1-stage1` | The prototype had no remote. Now in the lab tree (C6). Replace "fork our repository" references with the single lab URL and the lab tag. | +| Contribution types | Title block: "Submission Tracks: Reusable Research Infrastructure; AI-Enabled Research Loops Under Human Direction; New Forms of Measurement; Critical, Diagnostic, and Boundary-Setting Work" | The CFP lists "contribution types", not tracks, and does not ask you to pick. Four is defensible; "New Forms of Measurement" is the weakest fit (the CFP's wording is "measure constructs in text, audio, or video … at scale", and nothing here measures at scale yet). Suggest naming two: research loops under human direction, and boundary-setting. | +| Criterion: novelty | §2 | Strong. See E for the one overclaim ("overturns a sixty-year assumption"). | +| Criterion: feasibility | §4, A.3 | Strong once the addendum matches the code. | +| Criterion: stage of development | A.2 (17 checks, 19 tests, 542 lab checks) | Strong; numbers verified (C5). | +| Criterion: ethicality | A.4 item 5 only; Part I is silent | One clause in §5 (IRB, rule architectures not individuals, symmetric lever matrix). | +| Criterion: reproducibility | `reproduce.py`, `ci/reproduce.json` | Strong. One lab check does not reproduce today (C7). | +| Criterion: scalability | §5 "three to ten roles"; A.4 "n = 10 … bound to 3–5" | Honest. Keep. | +| Criterion: potential use and adoption | §3 "any researcher can fork" | True only after C6. | +| Criterion: expand the frontier | §2, A.5 | Strong. | +| FAQ: proprietary AI models — "infrastructure that other researchers have a reasonable chance of accessing" | A.3 item 1 commits to open-weight endpoints; the logged runs used Claude Sonnet 5.5 | Say in Part I §3 that the prompts are model-agnostic and the Stage 2 release runs on an open-weight model as well. | +| FAQ: data that cannot be shared | Examples are stipulated prose (prototype README: "a stipulated description, not field data"); field data waits on IRB | State it in Part I once: the worked cases are stipulated, the field packet is pre-built. | +| FAQ: negative results welcome | The two failed adversary predictions (A.2.2), the MARL null (A.4), the proxy failure (A.2.2) | These are assets under this call. §4 could name them as such in one clause. | +| Double-blind | Title block "[Anonymized for Double-Blind Stage 1 Review]" | Not required by the CFP; contradicts the public named repo. Replace with the author line. | +| Dates | §4: "before the February 2027 Duke workshop"; folder README: "Duke on 19–20 February 2027" | The CFP says **27–28 February 2027, tentative**, and names no venue. Fix both. | +| Portal | — | `mc.manuscriptcentral.com/orgsci`, deadline 1 November 2026. | + +--- + +## B. The narrative + +**What the editors asked.** "What kinds of knowledge can we create when the tools of inquiry +themselves change?" — and, in the same breath, no "Potemkin villages of slop", no conventional papers +with AI content, prototypes over polish. Part I answers the question in §3, and §3 is the best section +in the package: the LLM fails as a judge of structure, so the harness uses it only as an evidence-bound +reader and lets PyPhi decide, and the logged adversary run shows the model finding two readings and +mispredicting both. Keep that paragraph exactly as it is. It is the contribution. + +**Three moves weaken the case, and each is fixable without new research.** + +*The four-regime claim rests on numbers that do not exist.* §2 says that running PyPhi "across all 256 +possible three-party mediated coordination structures proves that joint influence and systemic +wholeness are orthogonal dimensions, revealing four distinct coordination regimes." The 2 × 2 is real, +but it comes from the Peirce probes (89 one-input wirings; 30 two-input forms), and the "256" census says +something else (24 triadic, 232 dyadic). The reviewer who runs `studies.census` will see the mismatch +first. C3 gives the sourced sentence. + +*"Self-exemplifying" is asserted, not computed.* §3 says the research architecture "quite literally +demonstrates the exact triadic coordination we are examining." Nothing in either repository encodes +scholar, agents and PyPhi as a structure and computes it. Two fixes. The cheap one is to drop +"literally" and say the harness is built on the same commit-and-read form the paper studies. The +better one — an hour's work with the prototype — is to write the three-party encoding (the scholar +reads the harness's verdict; the agents read the scholar's question and the evidence; the harness +commits only on a gated encoding and a question) and report its Φ(MIP) and core in one sentence. Under +this call, the harness run on itself is exactly the kind of result the editors say they cannot +predict. `[DRAFTED by Claude]` placeholder if you compute it: "Encoded as a structure in its own +pipeline — the scholar, the drafting agents, and the gate-and-compute harness — the loop reads +[verdict] with core [core]; the computation is `examples/05_harness/` in the prototype." + +*Agents are promised as present.* §3 says a forking researcher can "have their AI agents run the +experimental workflow" and that "competing AI agents translate field evidence." The prototype's README +says: "Nothing yet reads interview transcripts or documents at scale." The lab's AI arc says its agents +are "in-silico Boolean / tabular / small neural proxies (not live LLM calls)". What exists is two +prompts, a gate, and three logged runs made by pasting prose into one model. State that size. The +call rewards an honest prototype over an imagined platform, and the v3 FLAGS file already warned +against claiming live agent probes. `[DRAFTED by Claude]` for §3: "Any researcher can fork the lab, +paste a case into the drafter and adversary prompts with any model, pass the result through the +evidence gate, and compute. Three runs are logged so far, all on one model; reading transcripts at +scale and measuring agreement with human coders is Stage 2." + +**Two judgment calls, flagged, not decided.** + +*Algorithmacy.* §1, §2 and §5 carry the literacy → algorithmacy frame. The v3 FLAGS file judged that +"a paper about algorithmacy does not fit" this call. I would not cut it — it is the dissertation +spine and it gives the paper its organizational stake — but it costs about 180 of Part I's 1,890 +words, and the CFP never asks for a construct. One sentence in §1 and the closing clause of §5 would +hold the frame; §2's "requiring only literacy" / "Navigating it requires algorithmacy" glosses on the +four regimes could go. + +*"Potemkin village."* The phrase is the editors' own (for AI loops that only look like research). +Using it twice for your own objects — the bypassed platform in §3, "Potemkin oversight" in A.5 — reads +as an echo. One use, or none. + +**Overclaims to soften** (each is one word): "proves" appears six times (§2 ×2, §3, §4, A.1, A.2.3) +for results that are computations on stipulated models; the prototype's own README says "a verdict on +a model is evidence about the model." "Overturns a sixty-year assumption" (§2) — see E3. "Every +nontrivial variation backward" (§3) — the evidence is two predictions on one case (E8). "Collapses a +decade-long debate" (§4) — into a testable rule, yes; "collapses" overstates. "Pre-registered" (A.2.1 +Step 2, A.4 opening, A.4 item 2) — no registry record exists; the lab's own phrase, in every FINDINGS +file, is "hypotheses fixed before computing", and the prototype's is "a prediction fixed before +anything is computed." Use those. + +**House-style flags** (your `CLAUDE.md` rules, applied to Part I only; the addendum is reference +material and reads fine as a list): +- A.4's opening, "Because our laboratory commits pre-registered hypotheses before running experiments + and keeps refuted predictions in CI, we can state the exact boundary conditions," is self-narrating + rigor (rule 4). The sentence after it does the work; cut the opener. +- §2, §4 and §5 each run four or five bullets of identical shape (bold label, colon, one sentence). + The CFP format tolerates it; the house rule (mechanism 8) would group §4's three findings into prose. +- Paragraph openings in §1 land on agents (Simmel, organization theory, scholars) — good. §2's second + paragraph opens "Neuroscientists confronted the exact puzzle" — good. §5's bullets open on abstract + nouns ("Interpretive ambiguity:") — acceptable in a list. + +--- + +## C. Repo-reference audit + +Status: ✓ verified · ✗ wrong · ~ imprecise · ∅ no source found. Doc locations use the export's line +numbers in `gdoc_live.md` (my capture of the Doc at review time) where it helps. + +### C1. Paths, files, functions, tags + +| Doc says | Status | Fact | Source | +|---|---|---|---| +| `irreducibility-pipeline`, tag `v0.1-stage1` (A.2, App. B.2, App. D) | ✗→✓ | Existed only at `~/iit-playground/irreducibility-pipeline`, one commit, **no remote**. Now copied into the lab as `irreducibility-pipeline/`; tag to be cut on the lab commit when you push (C6). | `git remote -v` (empty); this branch | +| "reproduces all 17 reference results and passes 19 automated test gates in two minutes via a single command" (A.2) | ~ | Two commands: `python reproduce.py` (17 checks, about 2½ minutes on this laptop; the per-check times sum to 138 s) and `pytest -q` (19 tests, 5 s). | `proto_reproduce.txt`, `proto_pytest.txt` | +| `encode/runs/` (A.2.2 item 1, Table 5) | ✗ | No such directory. Logged runs live beside the examples. | `ls encode` → `PROMPT_adversary.md PROMPT_drafter.md SCHEMA.json` | +| `01_gig_dispatch_drafter.json`, `01_gig_dispatch_adversary.json`, `02_insurance_claim_drafter.json` (Table 5) | ✗ | `examples/01_gig_dispatch/ai_draft.json`, `examples/01_gig_dispatch/ai_draft_plus_adversary.json` (plus `ai_adversary_raw.json`), `examples/02_insurance_claim/ai_draft.json`. | `ls examples/01_gig_dispatch` | +| `irreducibility/controls.py` with "four mandatory controls" (Step 4, Table 2, App. B.1) | ✗ | No `controls.py`. `irreducibility/validate.py` runs **two controls** (factoring Φ = 0.000; irreducible Φ = 0.830) and **five reference forms** (strict mediation 2.000; chat dyad, dyadic gig model, broken-liveness feedback, each 0.000; gig false dyad 2.000). Table 2's four rows are the two controls plus two of the five forms. | `validate.py` docstring; prototype APPENDIX §C | +| `studies/adversarial_coding/`, `studies/proxies/`, `studies/strategic_model/` (A.2.2, App. C, App. D) | ✗ | Modules, not directories: `studies/adversarial_coding.py`; proxies = `studies/proxy_run.py` + `proxy_bridge.py` + `phiid_measure.py`. **`strategic_model` does not exist**; the README says "the strategic model … is the next stage of the work and is not here yet." Appendix D row 1 lists it as part of `v0.1-stage1`. | `ls studies`; README l. 24–26 | +| `irreducibility/core.py`, `encode_check.py`, `validate.py`, `spread.py`, `regime.py`, `contingency.py`, `rules.py`, `analyze.py`; `tpm_from_rules`, `cm_from_rules`, `classify_mediator`, `reduce_mediator`; `pyphi.new_big_phi.sia` / `maximal_complex` | ✓ / ~ | All files exist. `tpm_from_rules` and `cm_from_rules` are in `core.py`. `classify_mediator` and `reduce_mediator` are **not function names**: the mediator's position comes from `regime()` in `regime.py` (with `REGIMES` and `lesion_survives()`), the bypass reduction from `contingency_test()` and `add_bypass()` in `contingency.py`, and the verdict from `classify_rules()` in `core.py`. | `grep -n "^def"` | +| `contingency.py` "sweeps outside-option exit scenarios" (Step 6) | ✗ | `contingency.py` runs the bypass test (intrinsic / contingent / partial / reducible). Outside options are the O1–O5 design encodings in `examples/01` and the battery in `studies/enricher_regime.py`. | prototype APPENDIX §D | +| `protocol/` (Step 1, A.3, App. C) | ✓ | `PROTOCOL.md`, `coding_scheme.md`, `interview_guide.md`, `ethics.md`, `predictions_fixed_in_advance.md`. | `ls protocol` | +| `examples/03_code_review_gate/` (A.3) | ✓ path | Results wrong, see C2. | | +| `org_frontier/field/`, `recurrence/`, `survey/`, `classifier/`, `thinkers/peirce/probe_peirce_joint_determination.py`, `third_party/pyphi_iit4_mv`, `smoke_m2.py`, `foundations/phiid_vs_phi/FINDINGS.md` | ✓ | All exist. | `ls` | +| PyPhi pin `b78d0e342`; upstream `134a8f31`; `iit4_2026` returns φₛ = 0 at ε = 0; Python 3.10–3.12 | ✓ | | `requirements.txt`; `third_party/pyphi_iit4_mv/README.md` l. 7–9 | +| Blind runs "Claude Sonnet 5.5, October 2026" | ✓ | "26 Oct 2026, prompts as committed, case prose only, no tools". | prototype README l. 126 | + +### C2. The worked examples and Tables 2, 3, 5 + +Fresh `python -m irreducibility.analyze examples//encodings.json` output, in full, is in +`proto_analyze_*.txt`. + +**Example 01, gig dispatch.** Rival encodings: A (platform commits) **triadic Φ = 2.000, core {D,P,R}, +BOTTLENECK, intrinsic**; B (driver's relay) **dyadic 0.000, {D,P}**; C (pooled drivers, four nodes) +**dyadic 0.000, major complex {P,R}**. Single flipping rule A→B: `P: 'D and R' -> 'D'`. Design +encodings: + +| | Rules (D′, P′, R′) | Φ(MIP) max | Core | Position | +|---|---|---|---|---| +| O1 both captive | P · D∧R · P | 2.000 | {D,P,R} | BOTTLENECK | +| O2 complementary direct tie | P∧R · D∧R · P∧D | 6.000 | {D,P,R} | ENRICHER | +| O3 captive driver, mobile rider | P · D∧R · P∨D | 0.415 | {D,P} | CAPTURE | +| O4 mobile driver, captive rider | P∨R · D∧R · P | 0.415 | {P,R} | CAPTURE | +| O5 both mobile (substitute direct tie) | P∨R · D∧R · P∨D | 0.830 | {D,R} | BYPASSED | + +Against the Doc: + +| Doc (Table 3 / A.2.2) | Status | Fact | +|---|---|---| +| "2 rival (R₁, R₂), 2 design (D₁, D₂), 5 exit (O₁–O₅)" (Table 5) | ✗ | 3 rival (A, B, C) + 5 design (O1–O5) = 8 admissible encodings. Your D₁ is rival C; your D₂ is design O5. | +| R₁ Φ = 2.000 {D,P,R} BOTTLENECK; R₂ Φ = 0.000 CONDUIT | ✓ / ~ | R₂'s position prints as `dyadic` (the regime set is dyadic / BYPASSED / CAPTURE / BOTTLENECK / ENRICHER). "CONDUIT" and "PASSIVE" are your labels, not the code's. Either rename in the text or say the two words gloss the code's `dyadic`. | +| D₁ driver pool "Φ(MIP) = 1.000, {P,R}" | ✗ | System **Φ(MIP) = 0.000 (dyadic)**; {P,R} is the major complex. The 1.000 does not appear anywhere in the output. | +| D₂ direct tie "Φ(MIP) = 1.198, {D,R}, BYPASSED" | ✗ | **Φ(MIP) max = 0.830** (states 100 and 001), core {D,R}, BYPASSED. 1.198 appears nowhere in either repo. | +| O₂ "D′ = P ∨ E(D) … Φ = 2.000, {P,R}, CAPTURE of rider"; O₃ symmetric "{D,P}" | ✗ | These are not the prototype's O2/O3. The nearest computed facts: O4 (mobile driver) → CAPTURE {P,R} at Φ = 0.415; O3 (mobile rider) → CAPTURE {D,P} at 0.415. The exogenous-option battery in `enricher_regime.py` prints the same regimes (W:full/C:none → CAPTURE; W:none/C:full → CAPTURE) and **prints no Φ values**. | +| O₄ "both have outside options … Φ(MIP) = 0.000, ∅, Complete Dissolution (platform loses all lock-in)" | ✗ | Both-mobile is **BYPASSED, core {D,R}** (prototype O5, Φ = 0.830; `enricher_regime` phase diagram W:full/C:full → BYPASSED; its summary line: "bypassed (both options)"). The platform leaves the core; the parties stay bound to each other. "Dissolution to Φ = 0" is the opposite of what the code says. Part I §4 bullet 2 ("workers and clients escape lock-in by building outside options") survives; A.2.2's sentence "giving both sides outside options (O₄) dissolves lock-in to Φ(MIP) = 0" does not. | +| O₅ "Platform Substitute (multi-homing) D′ = P₁ ∨ P₂ … Φ = 1.000, {D,R}, Mediator Replaced (competing platforms factor out)" | ✗ | Not in the prototype. The lab's `rival_platforms` study (V2 #32, verdict RIVAL_ENCODING) finds the opposite of "platforms factor out": substitutable `W′ = S1 ∨ S2` gives "equal-Φ rivalry: each reachable state selects one platform triad with W". Either drop the row or restate it from that study. | +| "a sharp structural law that held across 60 of 60 randomized multi-party configurations: a platform's irreducible core consists of itself plus whichever parties lack an outside option" | ✓ | `enricher_regime.py` §4: "law holds on 60/60 random option configurations". | +| Table 2 controls 0.000 / 0.830 / 2.000 / 2.000 with those rules | ✓ values | File name wrong (C1). | + +`[DRAFTED by Claude]` replacement for the Table 3 outside-option rows, using the prototype's own five +designs (keep your column headings): + +> O₁ both captive — D′=P, P′=D∧R, R′=P — Φ 2.000 — {D,P,R} — BOTTLENECK (neither party can exit) +> O₂ complementary direct tie (repeat trips need app and contact) — D′=P∧R, P′=D∧R, R′=P∧D — Φ 6.000 — {D,P,R} — ENRICHER +> O₃ captive driver, mobile rider — D′=P, P′=D∧R, R′=P∨D — Φ 0.415 — {D,P} — CAPTURE of driver +> O₄ mobile driver, captive rider — D′=P∨R, P′=D∧R, R′=P — Φ 0.415 — {P,R} — CAPTURE of rider +> O₅ both mobile (substitute direct tie) — D′=P∨R, P′=D∧R, R′=P∨D — Φ 0.830 — {D,R} — BYPASSED (platform leaves the core; parties stay bound) + +and for A.2.2's third bullet: "Giving only the rider an outside option (O₃) shrinks the core to the +captive driver and the platform; giving only the driver one (O₄) shrinks it to the platform and the +captive rider; giving both (O₅) removes the platform from the core and leaves the driver and rider bound +to each other — the platform is bypassed, not dissolved." + +**Example 02, insurance claim.** Parties: Claimant `C`, **auto-adjudication engine `E`**, human +adjuster `A`; mediator `E`. **Five design encodings**, no rival pair: `pipe` triadic 2.000 {C,E,A} +BOTTLENECK (prediction held); `gated` 0.415 {C,E} CAPTURE (failed); `loop` 1.000 {E,A} CAPTURE (failed); +`loop_nolearn` 2.000 {C,A} BYPASSED (failed); `frozen` dyadic 0.000 (held). Two of five naive +predictions held. The logged AI drafter left rules unwritten for four of five designs; `encode_check` +rejects the file with **9 problems in 5 encodings** (eight missing party rules, one missing mediator +alternative). Doc Table 5 says "Intake Portal (M)" and "2 rival readings + 4 underspecified designs" +— ✗ on both; "9 problems" ✓; "Drafter refused to invent 4 ungrounded rules" ~ (it left four designs' +rules unwritten). + +**Example 03, code-review gate.** Parties: Author `A`, CI gate `G`, **Maintainer `M`** (not "Reviewer +R"). Two rival encodings. `gated` ("maintainers wait for CI": A′ = G∧M, G′ = A, M′ = A∧G) → **triadic +Φ = 1.000, core {A,M}, G BYPASSED**, naive prediction failed. `diff_only` ("approve on the diff alone": +M′ = A) → **triadic Φ = 2.000, core {A,G,M}, G ENRICHER**, prediction failed. The Doc's row ("G′ = A ∧ R +yields Triadic BOTTLENECK Φ = 2.0, core {A,G,R}; rubber-stamp excludes R from major complex (#39 +HUMAN_COMMIT_READ)") is ✗ throughout: no encoding has that rule, no result is BOTTLENECK, and the +rubber-stamp result belongs to the lab's `hitl_rubber_stamp` study, not to this example. +`[DRAFTED by Claude]`: "Required review gate (`gated`): when maintainers wait for CI the gate is +bypassed — the author and maintainer form the core at Φ = 1.0 and the gate sits outside it; approving +on the diff alone (`diff_only`) brings the gate into a three-party core at Φ = 2.0 as an enricher. +Both naive predictions failed; the field-mock M4 reads the same (BYPASSED)." + +**Example 04, dealer vs clearinghouse.** Parties `U` (upstream), `I` (intermediary), `V` (downstream). +`dealer` (U′ = V, I′ = U, V′ = I, a ban on direct sales) → triadic 2.000 {U,I,V} BOTTLENECK, +**contingent** (opening the bypass loses Φ = 2.000; core → {U,V}). `clearinghouse` (I′ = U∧V) → +triadic 2.000 {U,I,V} BOTTLENECK, **intrinsic** (bypass loses 0.000; core → {U,I}). The Doc's row +("Sequential dealer inventory relay factors (Dyadic, Φ = 0.0); simultaneous net clearinghouse binds +{B,M,S} (Triadic, Φ = 2.0)") is ✗: both are triadic; the contrast is whether the intermediary's place +survives a direct tie. That contrast is a better story for the call than dyadic-vs-triadic; use it. + +**Logged AI runs.** Drafter on 01: 2 encodings, admissible, identical to A and B, both predictions +held ✓. Adversary on 01: 4 encodings admissible; `driver_pool` predicted triadic {D1,D2,P,R} → computed +**dyadic, {P,R}**, FAILED ✓; `direct_contact_substitute` predicted dyadic → computed **triadic {D,R}, +BYPASSED, Φ = 0.830**, FAILED ✓. The Doc's narrative of both failures is right; only the file names and +the 1.198 are wrong. Insurance drafter: REJECTED, 9 problems ✓. + +### C3. "256 structures", regimes, and the lever matrix + +| Doc says | Status | Fact | Source | +|---|---|---|---| +| "Running PyPhi across all 256 possible three-party mediated coordination structures proves that joint influence and systemic wholeness are orthogonal … four distinct coordination regimes" (§2) | ✗ | The 2 × 2 (wholeness × joint determination) comes from the **Peirce probes**: 89 four-node one-input wirings (Φ > 0 in 8, all pure cycles) and 30 two-input forms (5 jointly determined inside a whole, 11 jointly determined at Φ = 0, 1 neither). The 256-form census is a different object (next row). | `thinkers-peirce-h1-irreducibility`, `thinkers-peirce-jd-full` (both PASS today) | +| "Exhaustive enumeration of all 256 three-party Boolean structures partitions the space into 56 dyadic structures, 132 cycle-supported triads, and 68 mediated triads" (A.3 item 2; App. C item 2) | ∅ | No file in either repo contains 56, 132 or "cycle-supported". The census is **4 worker rules × 16 mediator rules × 4 counterpart rules = 256 strict-mediation forms; 24 triadic (9.4%), 232 dyadic; 24/160 where the mediator reads both parties, 0/96 otherwise**. "68" matches `BOTTLENECK 68 (13.6%)` in the coarse regime count over **500 random forms**, a different universe. | `proto_census.txt`; `proto_mediator_in_core.txt` §3 | +| "correlation and mutual-information proxies miss over a third (96 of 256) of the irreducible triads that exact PyPhi catches (Appendices A–B)" (§4) | ∅ | No such figure. The proxy result is rank-AUC 0.563 (ΦID Φᵣ) and 0.629 (Φ_WMS) over the 256 census forms; "96" is the number of census forms whose mediator does not read both parties (0/96 triadic). | `reproduce.json` `proxies`, `census` | +| Regime frequencies | — | Over 500 random mediated forms (seed 7): coarse dyadic 44.4%, BYPASSED 18.8%, BOTTLENECK 13.6%, ENRICHER 23.2%; refined (capture split out) CAPTURE 28.2%, BOTTLENECK 2.6%, ENRICHER 6.0%. The Doc does not cite these; they are the sourced numbers to use if you want a population statement. | `proto_enricher_regime.txt` §1 | +| Table 4 lever matrix: "Switch Convey → Joint Commit: Φ 0.0 → 2.0" | ✓ | B→A flip. | | +| Table 4: "Pool Replaceable Side … locks in {M,B} (Φ = 1.0)" | ✗ | System Φ = 0.000; {M,B} is the major complex. | C2 | +| Table 4: "Establish Direct Tie to B … core {A,B} (Φ = 1.198, BYPASSED)" | ✗ | Φ = 0.830. | C2 | +| Table 4: "Block Counterpart Exit … across all 60/60 random trials" | ✓ | | | +| Table 4: "Multi-Home Across Mediators (O₅ …): Factors individual mediator out of core" | ✗ | See `rival_platforms` (C2). | | +| Table 4: "Form Worker Coalition / Union: Restores collective input parity" | ~ | Lab `worker-union-scale` (V2 #31) verdict UNION_MIRRORS_COAL: a union scales like a counterpart coalition. Cite it; the Doc's cell cites nothing. | `ci/reproduce.json` | +| "studies/strategic_model/ … We will formalize the actor-indexed strategic lever matrix (Table 4)" (A.3) | ~ | Fine as Stage 2 work **if** the path is dropped (it does not exist) and Appendix D stops listing it under `v0.1-stage1`. | | + +`[DRAFTED by Claude]` for §2's sentence: "Running the Peirce probes — 89 one-input wirings and 30 +two-input forms, each cut by PyPhi — shows that joint influence and systemic wholeness come apart in +both directions, which yields four coordination regimes that organizational prose routinely conflates +(Technical Addendum, Section A.1 and Appendix A.2)." + +`[DRAFTED by Claude]` for §4's third bullet: "…and shows, across the 256 strict-mediation forms of the +census, that two popular time-series proxies separate dyadic from triadic structures at rank-AUC +0.563 and 0.629 — barely above chance — while exact PyPhi finds the 24 irreducible forms outright +(Technical Addendum, Appendix A.3)." + +`[DRAFTED by Claude]` for A.3 item 2 / Appendix C item 2: "Exhaustive enumeration of the 256 +strict-mediation three-party forms (4 worker rules × 16 mediator rules × 4 counterpart rules) finds 24 +irreducible and 232 factorable, with a mediator that reads both parties necessary but not sufficient +(24/160 vs 0/96)." + +### C4. Lab studies and Appendix D + +Eighteen lab checks re-run today by name; 17 PASS, `wageman-ti-verdict` FAIL (C7). + +| Doc says | Status | Fact | Source | +|---|---|---|---| +| Peirce: 89 wirings; 66 adicity 3, 12 adicity 4; cause-side ≤ 2; 11 unbranched; 8 of 89 Φ > 0; copy ring Φ = 2.0 | ✓ | Exactly as printed. | `lab_ci_named.txt`; `thinkers/peirce/FINDINGS.md` | +| 30 two-input forms: 5 in a whole, 11 at Φ = 0, 1 no JD; "3-voter majority triad … Φ = 0 with 4 partition ties" | ✓ | | `thinkers-peirce-jd-full`, `thinkers-peirce-jd` | +| "such as a unanimous three-voter majority triad" (A.1) | ✗ wording | The form is `majority_triad` (2 of 3). "Unanimous majority" contradicts itself; unanimity is the AND triad, which is triadic at Φ = 3 in `probe-voting-robustness`. | `ci/reproduce.json` | +| Thompson: pooled Φ = 0, sequential 2.0, reciprocal 2.0, "collapses at its top step" (A.2.3, A.5) | ✓ + omission | Canonical encodings only. The study's verdict is **PARTIAL_ALIGNMENT, alignment 0.429**: "alternate encodings flip the verdict" (pooled all-required → triadic; sequential acyclic hand-off → dyadic). Say so in one clause. | `thompson_verdict_bridge/FINDINGS.md` | +| "Wageman's (1995) hybrid team designs factor cleanly" (A.2.3); WAGEMAN_PREDICTS_VERDICT (App. D) | ✗ | The study tests whether a Wageman-style interdependence index predicts the verdict: AUC 1.000 on the designed panel, and it does **not** predict Φ magnitude (XOR and AND share W at Φ 0.5 vs 2). Nothing about hybrid designs factoring. | `wageman_ti_verdict/FINDINGS.md` | +| CUTS_ACROSS "(4/8 formal vs. shadow diverge)" (App. D) | ✗ | Six forms, **4 of 6 mismatch** H1, alignment 0.333; the words "shadow" and "8" appear nowhere. | `formal_informal_cut/FINDINGS.md` | +| HITL: "rubber-stamping … leaves the human reviewer outside the major complex while the automated loop stays integrated at Φ = 2.0" (A.2.3) | ✓ | Panel row `stamp_posthoc`: whole dyadic, Φ 2, core {AI,S,C} or {S,C}, H out. | `hitl_rubber_stamp/FINDINGS.md` | +| SHARP_CLASS_GRADED_PATH "(R² = 0.992)" (App. D) | ∅ | No R² anywhere in the study. The result: on the diagonal (L,L,L), L = 0 NULL; L = 1 DYADIC Φ 0.390 {W,S}; L = 2 TRIADIC Φ 3.170 {W,S,C}. | `graded_commit_verdict/FINDINGS.md` | +| EXTRA_RESOLUTION_TO_PHI "(3 bits → 5.755 bits)" (App. D) | ∅ | No such figures. The result: with a ternary mediator, Φ on the (1,S,1) sweep runs 1.170 / 0.500 / 2.000 (full form) while the core stays {W,S,C}. | `mixed_radix_mediator/FINDINGS.md` | +| BLINDSPOT_SURVIVES_RADIX "(parity Φ = 2²⁻ⁿ)" (App. D, A.3) | ~ | That study shows balanced commits `S′ = (W+C) mod k` keep a flat Φ ≈ 0.5 band at k = 2, 3, 4. The 2^(2−n) law is `parity_law_n_gt6` and `parity_law_n_gt8` (LAW_HOLDS_NGT6, LAW_HOLDS_NGT8). Attach each figure to its study. | both FINDINGS | +| MARL "rank-AUC 0.485–0.555 across tabular and neural policies" | ✓ | EMERGENT_NULL (tabular Q-learning: 0.555 / 0.485) and NULL_SURVIVES (MLP and linear-FA policies). The study says "not deep MARL"; your "multi-agent reinforcement learning (MARL)" should say "tabular and small-network MARL proxies". | both FINDINGS | +| Imputation 0.944 (MI), 0.806 ring / 0.750 omit / 0.896 copy-W (exact Φ) | ✓ | | `topology_aware_imputer`, `imputer_exact_phi`, `matched_imputer_exact_phi` | +| Parity law to n = 10 | ✓ | LAW_HOLDS_NGT8 at n ∈ {8, 9, 10}. | `parity_law_n_gt8` | +| 3.169925 = 2 log₂ 3 (B.2) | ✓ | | `pyphi-iit4-mv-m2-smoke` PASS | +| TWO_CONDITION_STATE_DEPENDENT | ✓ | Study `ternary_pivotality` (V2 #1). | | +| Appendix D study labels | ✗ ×12 | `ternary_conjunctive_mediator`→`ternary_pivotality`; `graded_commitment_sweep`→`graded_commit_verdict`; `mixed_radix_asymmetric`→`mixed_radix_mediator`; `multivalued_xor_blindspot`→`parity_radix_blindspot`; `hitl_oversight`→`hitl_rubber_stamp`; `ai_labor_displacement`→`ai_fidelity_displace`; `marl_emergent_triads`→`marl_emergent_learn`; `dual_principals`→`dual_principal_conflict`; `union_vs_coalition`→`worker_union_scale`; `multihoming_bypass`→`rival_platforms`; `Substitute_degradation`→`gig_substitution`; `prior_matched_vs_mismatched`→`matched_imputer_exact_phi`. | `ls org_frontier/studies`; check names in `ci/reproduce.json` | +| "CI checks #001–#082" for the thinker catalog | ~ | 82 checks named `thinkers--…`, 16 thinkers; the manifest has no numeric IDs. | `ci/reproduce.json` | +| Agenda IDs V2 #1–#4, #24, #29, #31, #32, #35, #37, #39, #40, #41, #43, #44, #46; V3 #1, #5, #10, #15; V4 #4, #5, #9 | ✓ | Each matches the question text in `org_frontier/RESEARCH_AGENDA_50_V2.md`, `org_frontier/RESEARCH_AGENDA_V3.md` and `org_frontier/RESEARCH_AGENDA_V4.md`. | | +| "V3 #6" in the AI-workflows row | ✗ | V3 #6 is "k > 2 local triads sharing a single mediator". No MARL/AI study answers it; `marl_deep_replicate` cites no agenda number. Drop it. | `RESEARCH_AGENDA_V3.md` l. 56 | +| "probes 98, 107" | ✓ | PROBES.md rows 98 (agent-based difficulty, refuted, AUC 0.567) and 107 (partner-modeling agents, refuted, 0.541). | `org_frontier/probes/PROBES.md` | +| `foundations/phiid_vs_phi`: ρ 0.283 / AUC 0.669; ρ 0.124 / AUC 0.560 | ✓ | | its FINDINGS l. 32–33 | +| Proxies rank-AUC 0.563 / 0.629 | ✓ | Prototype check `proxies`; lab `proxy_bridge/FINDINGS.md`. Also in the lab essay the best-threshold accuracy for Φ_WMS is 0.778, so "near chance" is true of rank-AUC only. | | + +### C5. Counts + +| Doc | Status | Count today | +|---|---|---| +| 542 automated CI checks | ✓ | 542 before this branch's addition (543 with `irreducibility-pipeline-reproduce`). | +| 127 studies in `org_frontier/studies/` | ✓ | 127 directories. | +| 135 probes | ✓ | 135 `probe_*.py` files. | +| 9 `foundations/` studies | ✓ | 9 study directories plus `paper/`. | +| 82 probes across 16 thinkers | ✓ | 82 `thinkers-*` checks; 16 thinker directories. | +| 17 reference results; 19 tests | ✓ | 17/17; 19 passed. | +| 101/101 flips; 22/101 bracketed; 60/60 | ✓ | | +| Part I 1,890 words | ✓ | | + +### C6. The prototype is now inside the lab + +Per your decision — "people fork algorithmacy lab and that should give them all the access" — the +prototype was copied into this branch at `irreducibility-pipeline/` with its internal layout intact +(`irreducibility/`, `encode/`, `examples/`, `studies/`, `protocol/`, `tests/`, `reproduce.py`, +`reproduce.json`, `README.md`, `APPENDIX.md`, `CITATION.cff`, `LICENSE`, `pyproject.toml`, +`requirements.txt`); `.git`, caches and a stray `pyphi.log` were left out. Its own `reproduce.py` +resolves paths from its file location, so `python irreducibility-pipeline/reproduce.py` runs from +the lab root, and a lab check `irreducibility-pipeline-reproduce` (slow, 900 s) is registered in +`ci/reproduce.json` expecting its "17/17 checks passed." line. The lab README's programs list gains +one line pointing at it. + +What this changes in the Doc: every "`irreducibility-pipeline` (tag `v0.1-stage1`)" becomes "the +`irreducibility-pipeline/` directory of `algorithmacy-lab`"; the tag is re-cut on the lab commit that +lands this (suggest `orgsci-stage1`) when you push; the one URL +`https://github.com/rogerSuperBuilderAlpha/algorithmacy-lab` covers both artifacts; and A.2's +"reproduces … via a single command" can become "`python irreducibility-pipeline/reproduce.py` from a +clone of the lab". Nothing is pushed; the branch is `cursor/orgsci-ai-stage1-proposal-ec39` in the +worktree `~/iit-playground/wt-orgsci-ai`, and `REPO_LAYOUT.md` wants a PR into `contrib`. + +### C7. Repo health found on the way + +- **`wageman-ti-verdict` fails on this branch.** The manifest expects "ρ(W,Φ)=0.883"; the script now + prints **0.867** (`results/summary.json` would change from 0.8833 to 0.8667). Every other number in + the check reproduces (AUC 1.000, acc 1.000 at W ≥ 0.472, H3 refuted). Either the manifest or the script + drifted after the last full run. I restored the regenerated `results/summary.json` rather than commit + it; the drift needs a maintainer's decision. The Doc cites WAGEMAN_PREDICTS_VERDICT (Appendix D), so + a reviewer running `ci/reproduce.py` in full would hit this. +- The Peirce probe runs rewrite their `results/*.json` with new timings only; restored. +- `third_party/pyphi_iit4_mv/README.md` and the lab README still describe the upstream PyPhi 2.0 state + as of 25 October; fine for now. + +--- + +## D. Citation audit + +Every entry checked against Crossref (`crossref/*.json`), with the publisher's page, Semantic Scholar +or OpenAlex where Crossref lacked the record, and against full text where it was on disk. + +| # | Reference as in the Doc | Status | Finding | +|---|---|---|---| +| 1 | Albantakis et al. (2023) … "phenomenal existence in physical **systems**", *PLoS Comput Biol* 19(10) e1011465 | ✗ title | "…in physical **terms**". DOI 10.1371/journal.pcbi.1011465. | +| 2 | Anthony, Bechky & Fayard (2023) *Org Sci* 34(5) 1672–1694 | ✓ | 10.1287/orsc.2022.1651 | +| 3 | Burch (1991) Texas Tech UP | ✓ | Lubbock, TX. | +| 4 | Burt (1992) Harvard UP | ✓ | | +| 5 | **Cameron (2024). "The making of crystal-clear calls: Algorithmic management and the standardization of service work." *ASQ* 69(1), 1–42** | ✗ fabricated | No such article. The ASQ 2024 article is Cameron, L. D. (2024). The making of the "good bad" job: How algorithmic management manufactures consent through constant and confined choices. *ASQ*, 69(2), 458–514. DOI 10.1177/00018392241236163. (Copy in `~/Downloads`.) Its abstract — ride-hail drivers "navigate being managed by an algorithm" through "constant and confined choices" — supports your §1 and §4 uses. | +| 6 | Caplow (1956) *ASR* 21(4) 489–493 | ✓ | 10.2307/2088718 | +| 7 | Coleman (1988) *AJS* 94(Suppl.) S95–S120 | ✓ | 10.1086/228943 | +| 8 | Curchod et al. (2020) *ASQ* 65(3) 644–676 | ✓ | 10.1177/0001839219867024 | +| 9 | Daft & Lewin (1990) *Org Sci* 1(1) 1–9 | ✓ | 10.1287/orsc.1.1.1 | +| 10 | Gartenberg, Hasan, Murray & Pierce (2026) *Org Sci* 37(3) 795–812 | ✓ | 10.1287/orsc.2026.ed.v37.n3; matches the CFP's own list. | +| 11 | Girotra, Terwiesch & Ulrich (2010) *Mgmt Sci* 56(4) 591–605 | ✓ | 10.1287/mnsc.1090.1144 | +| 12 | Granovetter (1973) *AJS* 78(6) 1360–1380 | ✓ | 10.1086/225469 | +| 13 | **Hereth Correia & Pöschel (2004)** "The power of Peircean algebraic logic." In *Conceptual Structures at Work: ICCS 2004* (LNCS 3127, pp. 337–350) | ✗ venue | The paper is in Eklund, P. (Ed.), *Concept Lattices: Second International Conference on Formal Concept Analysis, ICFCA 2004*, LNAI **2961**, pp. 337–**351**. DOI 10.1007/978-3-540-24651-0_29. The 2006 paper's own reference [HCP04] says the same. | +| 14 | Hereth Correia & Pöschel (2006) "The teridentity and Peircean algebraic logic." *ICCS 2006*, LNAI 4068, pp. 229–246 | ✓ | 10.1007/11787181_17. **Lemma 1** (any t-connected set of places in a PAL∖{id₃} term over unary and binary relations has |X| ≤ 2) and **Theorem 2** (|A| ≥ 2 ⇒ ⟨Σ⟩PAL∖{id₃} ⊊ ⟨Σ⟩PAL) are as the Doc states. | +| 15 | Kellogg, Valentine & Christin (2020) *AMA* 14(1) 366–410 | ✓ | 10.5465/annals.2018.0174 | +| 16 | Koshkin (2024) "Logical reduction of relations…" *Logic J. IGPL* 32(5) 779–**813** | ~ pages | 779–**809**; online June 2023, print September 2024. DOI 10.1093/jigpal/jzad010. | +| 17 | **Koshkin (2025). "Logical reduction of finite relations and granular computing." *IJAR* 186, 109523** | ✗ fabricated record | *IJAR* 186, 109523 is Obiedkov & Sertkaya, "PAC learning of concept inclusions…". The paper whose content Appendix A.1 describes (Δ₃ from binary equality; reduction to binaries on finite |D| ≥ 3; ¬I₃ pp-irreducible on Boolean domains, Theorems 2–4; bond algebra, Theorem 6) is Koshkin, S. (2024). Functional completeness and primitive positive decomposition of relations on finite domains. *Logic Journal of the IGPL*, advance article, jzae077. DOI 10.1093/jigpal/jzae077; arXiv 2606.19492. **Theorem numbers verified against arXiv v1**: Thm 2 (relative reduction; n ≥ 4 reduces to ternary), Thm 3 (cofinite n-ary relations, 3 ≤ n ≤ |D|, reduce to binary), Thm 4 (¬I₃ non-bijunctive, irreducible on Boolean domains), Thm 6 (I₃ bond-irreducible on any domain with ≥ 2 elements). The published version's numbering is unchecked. | +| 18 | March (1991) *Org Sci* 2(1) 71–87 | ✓ | 10.1287/orsc.2.1.71 | +| 19 | Mayner et al. (2018) *PLoS Comput Biol* 14(7) e1006343 | ✓ | 10.1371/journal.pcbi.1006343 | +| 20 | Mediano et al. (2025) "Toward an **extended** taxonomy…" *PNAS* 122(39) e2423297122 | ✗ title | "Toward a **unified** taxonomy of information dynamics via Integrated Information Decomposition." DOI 10.1073/pnas.2423297122. | +| 21 | Obstfeld (2005) *ASQ* 50(1) 100–130 | ✓ | 10.2189/asqu.2005.50.1.100 | +| 22 | Orlikowski & Scott (2008) *AMA* 2(1) 433–474 | ✓ | 10.5465/19416520802211644 | +| 23 | Ostrom (1990) CUP | ✓ | 10.1017/cbo9780511807763 | +| 24 | Peirce (1933) "The logic of relatives" (1897), CP 3.456–3.552 | ✓ | Standard locator for the 1897 *Monist* paper. | +| 25 | Quine (1954) *JSL* 19(3) 180–182 | ✓ | 10.2307/2268616. Read in full: the Kuratowski construction {{x},{x,y}} and "a universe closed under pairing" are on p. 180 as the Doc says. | +| 26 | Rahman (2021) *ASQ* 66(4) 945–988 | ✓ | 10.1177/00018392211010118 | +| 27 | Rudin (2019) *Nat Mach Intell* 1(5) 206–215 | ✓ record | 10.1038/s42256-019-0048-x. Attribution questioned in E6. | +| 28 | Simmel (1950) "Quantitative aspects of the group (1902)." In Wolff, pp. 87–177 | ✓ pages, ~ date | Part Two of Wolff's edition runs from p. 87 to the end of "Maximum and Minimum Sizes" (p. 174 ff.; Part Three opens at 181). Wolff translates *Soziologie* (1908), ch. 2; the 1902 *AJS* articles are the earlier English version — say 1908 or 1902/1908. The dyad passage you paraphrase is on **p. 123**: "the secession of either would destroy the whole … As soon, however, as there is a sociation of three, a group continues to exist even in case one of the members drops out." | +| 29 | Thompson (1967) McGraw-Hill | ✓ | | +| 30 | Wageman (1995) *ASQ* 40(1) 145–180 | ✓ | 10.2307/2393703 | +| 31 | Williams & Beer (2010) arXiv:1004.2515 | ✓ | Submitted 14 April 2010. | +| 32 | Mediano/Williams-Beer as PID/ΦID sources | ✓ | PID (Williams & Beer); ΦID (Mediano et al.). | + +**Cited in the text, absent from the list** — add, verified: + +- Stark, D., & Pais, I. (2020). Algorithmic management in the platform economy. *Sociologica*, 14(3), + 47–72. https://doi.org/10.6092/issn.1971-8853/12221 +- Rosenblat, A., & Stark, L. (2016). Algorithmic labor and information asymmetries: A case study of + Uber's drivers. *International Journal of Communication*, 10, 3758–3784. (Running head of the PDF.) +- Tononi, G. (2004). An information integration theory of consciousness. *BMC Neuroscience*, 5, 42. + https://doi.org/10.1186/1471-2202-5-42 + +**Corrected entries** `[DRAFTED by Claude]`, in your list's format: + +- Albantakis, L., … & Tononi, G. (2023). Integrated information theory (IIT) 4.0: Formulating the + properties of phenomenal existence in physical terms. *PLoS Computational Biology*, 19(10), e1011465. +- Cameron, L. D. (2024). The making of the "good bad" job: How algorithmic management manufactures + consent through constant and confined choices. *Administrative Science Quarterly*, 69(2), 458–514. +- Hereth Correia, J., & Pöschel, R. (2004). The power of Peircean algebraic logic (PAL). In P. Eklund + (Ed.), *Concept Lattices: Second International Conference on Formal Concept Analysis, ICFCA 2004* + (LNAI Vol. 2961, pp. 337–351). Springer. +- Koshkin, S. (2024a). Logical reduction of relations: From relational databases to Peirce's reduction + thesis. *Logic Journal of the IGPL*, 32(5), 779–809. +- Koshkin, S. (2024b). Functional completeness and primitive positive decomposition of relations on + finite domains. *Logic Journal of the IGPL*, advance article jzae077. https://doi.org/10.1093/jigpal/jzae077 +- Mediano, P. A. M., Rosas, F. E., Luppi, A. I., Carhart-Harris, R. L., Bor, D., Seth, A. K., & + Barrett, A. B. (2025). Toward a unified taxonomy of information dynamics via Integrated Information + Decomposition. *Proceedings of the National Academy of Sciences*, 122(39), e2423297122. + +and in the text, "(Koshkin, 2024, 2025)" → "(Koshkin, 2024a, 2024b)"; "Koshkin, 2025, Theorems 2–4" +→ "Koshkin, 2024b, Theorems 2–4"; "Koshkin, 2025, Theorem 6" → "Koshkin, 2024b, Theorem 6". + +--- + +## E. Attribution and the debates as portrayed + +Depth of reading, so you can weigh each item. **Read in full:** Quine (1954); Hereth Correia & +Pöschel (2004, 2006); Koshkin (2024b, arXiv v1); Rosenblat & Stark (first page); Wolff's Simmel (the +table of contents and pp. 118–124 around the dyad passage). **Abstract only:** Kellogg et al. (2020); +Stark & Pais (2020); Cameron (2024); Rahman (2021); Rudin (2019); Vallas & Schor (2020); Schor et al. +(2020); Einav, Farronato & Levin (2016); Hall & Krueger (2018); Wood et al. (2019); Victor & Blackburn +(1987); Puranam, Raveendran & Knudsen (2012); Raveendran, Silvestri & Gulati (2020); Parasuraman & +Riley (1997); Green & Chen (2019); Lebovitz, Lifshitz-Assaf & Levina (2022); Koshkin (2024a). +**Database record only, not read:** Skitka, Mosier & Burdick (1999); Sundararajan (2016); every other +entry in Part D that is marked ✓ on its record. Where a proposal below rests on an abstract, read the +paper before the sentence goes into the Doc. + +**E1. The "rival camp" has no citation (§1).** "One camp sees totalizing triads that fuse workers, +clients, and software into an indivisible whole (Kellogg et al., 2020; Stark & Pais, 2020); a rival +camp sees high-speed market relays unbundling work into arms-length dyads." The second camp is real +and nameable. Einav, Farronato and Levin (2016, *Annual Review of Economics* 8, 615–635, +10.1146/annurev-economics-080315-015334) "view the primary function of these markets as making it easy +for buyers to find sellers and engage in convenient, trustworthy transactions" — the platform as +matching market. Hall and Krueger (2018, *ILR Review* 71(3), 705–732, 10.1177/0019793917717222) model +Uber drivers as flexible independent suppliers. Sundararajan (2016, *The Sharing Economy*, MIT Press) +calls it crowd-based capitalism. Vallas and Schor's review (2020, *Annual Review of Sociology* 46, +273–294, 10.1146/annurev-soc-121919-054857) names this image "entrepreneurial incubators" and sets it +against "digital cages", which is your first camp. `[DRAFTED by Claude]`: "…a rival camp sees +matching markets that relay buyers to sellers and leave the work itself to arm's-length contractors +(Einav, Farronato, & Levin, 2016; Hall & Krueger, 2018; Sundararajan, 2016) — the 'entrepreneurial +incubator' image in Vallas and Schor's (2020) review." + +**E2. Kellogg et al. do not describe a triad (§1).** Their abstract frames algorithmic control as +Edwards's "contested terrain" between employers who implement technologies and workers who resist, +through six mechanisms (restricting, recommending, recording, rating, replacing, rewarding). That is a +labor-process, employer–worker frame; customers enter only as raters. Stark and Pais (2020) do say what +you attribute: "In a triangular geometry, platform owners co-opt the behavior of providers and users, +enrolling them in the practices of algorithmic management without managerial authority having been +delegated to them." Keep Stark & Pais for the triad; cite Kellogg et al. for control, not for fusion. +(Stark and Pais also give you the contrastive line "actors in markets contract, hierarchies command, +and networks collaborate, platforms co-opt" — it may be worth quoting.) + +**E3. "Since Thompson (1967), scholars have treated joint influence and systemic wholeness as if they +were the same thing … overturns a sixty-year assumption" (§2).** The field has re-cut interdependence +repeatedly. Victor and Blackburn (1987, *AMR* 12(3), 486–498, 10.2307/258515) argued that Thompson's +conceptualization "fail[s] to satisfy basic requirements for empirical or practical investigations" +and rebuilt it on Kelley–Thibaut outcome structures. Wageman (1995) split task from outcome +interdependence. Puranam, Raveendran and Knudsen (2012, *AMR* 37(3), 419–440, 10.5465/amr.2010.0535) +introduced epistemic interdependence "to sharply distinguish interdependence between tasks and between +agents." Raveendran, Silvestri and Gulati (2020, *AMA* 14(2), 828–868, 10.5465/annals.2018.0015) sort +it into task, goal and knowledge interdependence. None of the four abstracts describes a partition +test of whether the coupled unit is decomposable, which is your point — I did not read the four papers +in full, so check before asserting it — but "treated as the same thing" is not what happened. `[DRAFTED by Claude]`: "Interdependence typologies since Thompson (1967) classify how tasks, +outcomes and knowledge couple (Victor & Blackburn, 1987; Wageman, 1995; Puranam, Raveendran, & +Knudsen, 2012; Raveendran, Silvestri, & Gulati, 2020); none supplies a test of whether the coupled +unit can be cut without loss. Running PyPhi over the Peirce probes shows that joint influence and +systemic wholeness are separate dimensions…" and drop "overturns a sixty-year assumption". + +**E4. "After a decade of fieldwork … scholars remain deadlocked" (§1).** No source says deadlock. Two +reviews document the disagreement you need: Vallas and Schor (2020) find four competing metaphors +(incubator, digital cage, accelerant of precarity, chameleon), each with limitations; Schor et al. +(2020, *Theory and Society* 49, 833–861, 10.1007/s11186-020-09408-y) find that both dominant +approaches — precarity and algorithmic control — "predict that workers will have relatively common +experiences," and the data show heterogeneity instead. `[DRAFTED by Claude]`: "…scholars still hold +competing images of what the platform is (Vallas & Schor, 2020; Schor et al., 2020): when an algorithm +mediates…" + +**E5. Simmel (§1, A.1).** Accurate. Wolff p. 123 carries both halves of your paraphrase (the dyad dies +with either member's secession; a group of three "continues to exist even in case one of the members +drops out"), and "super-individual" is his term on the same page. Add the page: (Simmel, 1950: 123). +"Play partners against each other" is *tertius gaudens* and *divide et impera*, Wolff pp. 154–169. + +**E6. Rudin (2019) as the source of the "post-hoc verification trap" / "Potemkin oversight" (A.2.3, +A.5).** Rudin's argument is that post-hoc explanations of black-box models are unreliable and that +high-stakes decisions should use inherently interpretable models. It says nothing about a human +reviewer rubber-stamping a system's recommendation. That phenomenon is automation bias: Parasuraman +and Riley (1997, *Human Factors* 39(2), 230–253, 10.1518/001872097778543886) and Skitka, Mosier and +Burdick (1999, *IJHCS* 51(5), 991–1006, 10.1006/ijhc.1999.0252) name it; Green and Chen (2019, *PACM +HCI* 3 CSCW, 1–24, 10.1145/3359152) study "algorithm-in-the-loop" decisions; and in this journal +Lebovitz, Lifshitz-Assaf and Levina (2022, *Org Sci* 33(1), 126–148, 10.1287/orsc.2021.1549) watched +radiologists either disengage from or defer to opaque AI tools. `[DRAFTED by Claude]`: "…formalizing +the rubber-stamp pattern that the automation-bias literature documents (Parasuraman & Riley, 1997; +Skitka, Mosier, & Burdick, 1999) and that Lebovitz, Lifshitz-Assaf, and Levina (2022) observed among +radiologists facing opaque AI." Keep Rudin only where the claim is about explanations of black boxes. + +**E7. The formal-logic claims (A.1, Appendix A.1).** Verified against full text: Quine's pairing +translation (p. 180); Hereth Correia & Pöschel 2006 Lemma 1 and Theorem 2; Koshkin's Theorems 2, 3, 4 +and 6 (arXiv version). The 2004 paper's Theorem 13 states the finite-domain version of the 2006 +result with the proof deferred, which is why "introduced with a restricted proof in Burch, 1991" and +the 2004/2006 pairing are right. Two wording points: "Peircean Algebraic Logic (introduced with a +restricted proof in Burch, 1991)" — Burch introduced PAL and proved the thesis under a restriction on +juxtaposition; the 2006 paper removes the restriction and reproves it; say that. And "Koshkin, 2024 for +infinite domains and projoins" — the 2024a abstract speaks of "natural joins", "ternarity" and the +finite/infinite split; I could not confirm the word "projoin" without the full text. + +**E8. "A frontier LLM … got every nontrivial variation backward" (§3); "standalone LLMs fail badly" +(§3); "LLMs hallucinate ungrounded rules and misguess multi-party partition math" (A.2.1).** The +evidence is one model, one stipulated case, two adversary predictions (both wrong), plus one drafter +run that matched the human encodings and one that declined to invent rules. That supports "the +model's own predictions about what its readings would compute were wrong both times"; it does not +support "every nontrivial variation" or a general failure claim. `[DRAFTED by Claude]`: "Given only +the case prose, the model found both design variants a human had encoded — and predicted both +verdicts backward: it expected driver pooling to stay a three-party triad (PyPhi: the drivers factor +out) and off-app repeat rides to collapse into a dyad (PyPhi: a bypass core of driver and rider)." + +**E9. PID / ΦID (A.3, App. A.3).** Correctly attributed. One nuance: Φᵣ is the ΦID-based revised +integrated information; the Doc's gloss "corrects whole-minus-sum Φ(WMS) for double-counting +redundancy" matches Mediano et al.'s framing. + +**E10. Daft & Lewin, March, Girotra et al., Gartenberg et al.** All as the CFP cites them. "Thirty-six +years later" (A.1) is right for 2026. + +--- + +## F. Prioritized fix list + +**Must fix before 1 November** +1. Replace the Table 3 outside-option rows and A.2.2's third bullet with the prototype's O1–O5 (C2). +2. Replace Table 5's Example 02, 03, 04 rows and A.2.3's "four worked cases" clause with the computed results (C2). +3. Correct Φ = 1.198 → 0.830 and Φ = 1.000 → "Φ = 0 (dyadic); core {P,R}" in Table 3, Table 4, A.2.2 and Part I §3 (C2, C3). +4. Remove "56 / 132 / 68" and "96 of 256"; use the census (24/256, 24/160, 0/96) and the Peirce probes (C3). +5. Fix the file paths in C1 and the twelve study labels in C4; drop `strategic_model` from `v0.1-stage1`; drop "V3 #6". +6. Replace the four unsourced Appendix D figures (R², 5.755 bits, 4/8, Wageman hybrid) with the studies' own numbers (C4). +7. Fix the reference list: Cameron, Koshkin 2025→2024b, HC&P 2004 venue, Albantakis and Mediano titles, Koshkin 2024 pages; add Stark & Pais, Rosenblat & Stark, Tononi (D). +8. Point every prototype reference at `irreducibility-pipeline/` inside the lab and name the lab tag (C6); then push the branch, open the PR into `contrib`, and cut the tag. +9. Replace the "[Anonymized …]" line with the author line. +10. Fix the workshop date in §4 and in this folder's README (27–28 February 2027, tentative, venue unstated). + +**Should fix** +11. §1: cite the rival camp (E1); move Kellogg et al. to the control claim (E2); replace "deadlocked" (E4). +12. §2: replace the "sixty-year assumption" sentence (E3); fix the "256 … proves … four regimes" sentence (C3). +13. §3: state the AI step at its actual size (B); soften "every nontrivial variation" (E8); decide "literally" (B). +14. A.2.3 / A.5: re-attribute the rubber-stamp trap (E6); add the Thompson caveat (C4). +15. A.1: "unanimous three-voter majority" → "three-voter majority"; "Broadcast Cascades" (§2) vs "Cyclic One-Input Relay" (Table 1) — one name. +16. Step 6 / App. B.1: `contingency.py` is the bypass test; outside options are the O-designs and `enricher_regime` (C1). +17. "proves" ×6 → "shows" / "computes"; "collapses a decade-long debate" → "turns … into one testable rule"; "pre-registered" ×3 → "fixed before computing" (B). +18. §5: one sentence of execution risks; one clause on ethics (A). +19. Add captions "Table 1 … Table 6" where the text cites them; fix "Section A.2.2 and Table 5" (Table 5 is in Appendix B). + +**Nice** +20. Compute the harness on itself and report it (B). +21. Trim the algorithmacy frame in §2's regime glosses; keep §1 and §5 (B). +22. One "Potemkin", or none (B). +23. "tabular and small-network MARL proxies" (C4); "Submission Tracks" → "Contribution types" (A). +24. Fix `wageman-ti-verdict`'s manifest or script so the full lab CI is green before reviewers run it (C7). + +--- + +## Appendix: how each number was produced + +``` +# prototype (from its own root; venv-4.0 carries the PyPhi pin) +python reproduce.py # 17/17, 2 m 17 s +python -m pytest -q tests # 19 passed +python -m irreducibility.analyze examples/01_gig_dispatch/encodings.json +python -m irreducibility.analyze examples/01_gig_dispatch/ai_draft_plus_adversary.json +python -m irreducibility.analyze examples/02_insurance_claim/encodings.json +python -m irreducibility.analyze examples/03_code_review_gate/encodings.json +python -m irreducibility.analyze examples/04_dealer_vs_clearinghouse/encodings.json +python -m studies.census; python -m studies.mediator_in_core; python -m studies.enricher_regime +python -m irreducibility.encode_check examples/01_gig_dispatch/ai_draft.json # ADMISSIBLE 2 +python -m irreducibility.encode_check examples/01_gig_dispatch/ai_draft_plus_adversary.json # ADMISSIBLE 4 +python -m irreducibility.encode_check examples/02_insurance_claim/ai_draft.json # REJECTED 9 + +# lab (from the lab root) +python ci/reproduce.py thinkers-peirce-h1-irreducibility thinkers-peirce-jd thinkers-peirce-jd-full \ + hitl-rubber-stamp graded-commit-verdict mixed-radix-mediator parity-radix-blindspot formal-informal-cut \ + wageman-ti-verdict thompson-verdict-bridge imputer-exact-phi topology-aware-imputer \ + matched-imputer-exact-phi marl-emergent-learn marl-deep-replicate pyphi-iit4-mv-m2-smoke \ + parity-law-n-gt8 ternary-pivotality # 17 PASS, wageman-ti-verdict FAIL +python ci/reproduce.py irreducibility-pipeline-reproduce # the new check + +# citations +curl -s -G https://api.crossref.org/works --data-urlencode "query.bibliographic=" --data-urlencode rows=2 +``` diff --git a/submissions/proposals/orgsci_ai_2026/gdoc_1fhM_v6_story_plus_addendum.md b/submissions/proposals/orgsci_ai_2026/gdoc_1fhM_v6_story_plus_addendum.md index a110e7cc..82e1aa2c 100644 --- a/submissions/proposals/orgsci_ai_2026/gdoc_1fhM_v6_story_plus_addendum.md +++ b/submissions/proposals/orgsci_ai_2026/gdoc_1fhM_v6_story_plus_addendum.md @@ -1,20 +1,27 @@ +# Beyond the Dyadic Straitjacket: Bringing Integrated Information Theory (IIT 4.0) and PyPhi to Organizational Coordination via a Self-Exemplifying Research Harness + +**Special Issue:** [*Organization Science* — AI-Enabled Frontiers in Organizational Science](https://pubsonline.informs.org/pb-assets/filesorsc/CFP_AI-Enabled%20Frontiers%20in%20Organizational%20Science-1785685920943.pdf): Reimagining What Can Be Known and How +**Contribution Types:** AI-Enabled Research Loops Under Human Direction; Critical, Diagnostic, and Boundary-Setting Work; Reusable Research Infrastructure +**Stage 1 Package:** Part I Stage 1 Research Proposal (Prospectus, Sections 1–5, 1,992 words) \+ Part II Technical Addendum & Verification Compendium \+ Open Research Harness ([algorithmacy-lab](https://github.com/rogerSuperBuilderAlpha/algorithmacy-lab)) +**Author:** Roger Hunt · PhD Candidate, Bentley University · rhunt@bentley.edu + # Part I: Stage 1 Research Proposal (Prospectus) -## 1. The Foundational Question: When Does a Triad Refuse to Reduce to Dyads? +## 1\. The Foundational Question: When Does a Triad Refuse to Reduce to Dyads? -What happens when a third party steps between two people who work together? Georg Simmel (1902/1950) argued that the jump from two actors to three is the most radical threshold in social life: a dyad vanishes if either member leaves, whereas a triad can outlive a departure, play partners against each other, or fuse three actors into a unit inexplicable by its pairs alone. Organization theory builds on that insight, from Caplow (1956) on coalitions and Thompson (1967) on interdependence to Burt (1992) on structural holes, Coleman (1988) on closure, Obstfeld (2005) on *tertius iungens*, and Kellogg, Valentine, and Christin (2020) on algorithmic control. +What happens when a third party steps between two people who work together? Georg Simmel (1902/1950: 123\) argued that the jump from two actors to three is the most radical threshold in social life: a dyad vanishes if either member leaves, whereas a triad can outlive a departure, play partners against each other, or fuse three actors into a unit inexplicable by its pairs alone. Organization theory builds on that insight, from Caplow (1956) on coalitions and Thompson (1967) on interdependence to Burt (1992) on structural holes, Coleman (1988) on closure, Obstfeld (2005) on *tertius iungens*, and Kellogg, Valentine, and Christin (2020) on algorithmic control. Historically, formal coordination ran on written text. Standard operating procedures and contracts coordinated work on paper. Navigating a bureaucracy required **literacy**: reading shared rules that sat in plain sight. Even when a manager stood between two workers, work operated as a chain of dyadic obligations—Worker A reported to the manager under one rule, and the manager instructed Worker B under another—so anyone could understand the workflow by reading each pairwise link in turn. Today, software platforms, automated dispatchers, rating engines, and continuous-integration gates sit in the middle of work (Cameron, 2024; Curchod, Patriotta, Cohen, & Neysen, 2020; Orlikowski & Scott, 2008; Rahman, 2021; Shestakofsky, 2017). Navigating these workplaces requires a different sensibility: **algorithmacy**. Unlike a static rulebook, an algorithmic mediator is an active, state-updating participant that watches both sides at once and conditions each human actor's next move on counterparts they may never meet. -Yet after a decade of fieldwork on algorithmic management, scholars remain deadlocked: when an algorithm mediates between two counterparts, does it create a genuinely irreducible triad or merely a fast broker stringing together two-party ties? One camp sees totalizing triads that fuse workers, clients, and software into an indivisible whole (Kellogg et al., 2020; Stark & Pais, 2020); a rival camp sees high-speed market relays unbundling work into arms-length dyads. +Yet after a decade of fieldwork on algorithmic management, \[DRAFTED by Claude\] scholars still hold competing images of what the platform is (Vallas & Schor, 2020; Schor et al., 2020): when an algorithm mediates between two counterparts, does it create a genuinely irreducible triad or merely a fast broker stringing together two-party ties? One camp sees totalizing triads that fuse workers, clients, and software into an indivisible whole (Stark & Pais, 2020); \[DRAFTED by Claude\] a rival camp sees matching markets that relay buyers to sellers (Einav, Farronato, & Levin, 2016; Hall & Krueger, 2018; Sundararajan, 2016). Organization science has not settled this debate because "triadic mediation," "reciprocal interdependence," and "systemic wholeness" have remained metaphors. Network analysis counts ties and brokerage paths, while regressions measure whether one actor's behavior correlates with another's. Neither can answer Simmel's causal question: can a three-party coordination arrangement be severed into pairwise channels without losing causal power, or does it act as an indivisible whole? -## 2. The Core Innovation: Bringing Integrated Information Theory (IIT 4.0) and PyPhi to Organizational Coordination +## 2\. The Core Innovation: Bringing Integrated Information Theory (IIT 4.0) and PyPhi to Organizational Coordination -To answer that question, we bring a mathematical framework from theoretical neuroscience into organization science: **Integrated Information Theory (IIT 4.0)** (Albantakis et al., 2023; Tononi, 2004) and its exact computational engine, **PyPhi** (Mayner et al., 2018). +To answer that question, we bring a mathematical framework from theoretical neuroscience into organization science: **Integrated Information Theory (IIT 4.0)** (Albantakis et al., 2023; Tononi, 2004\) and its exact computational engine, **PyPhi** (Mayner et al., 2018). Neuroscientists confronted the exact puzzle organization theorists face today: given interacting elements whose states update over time, when does a collection act as one integrated unit rather than smaller modules operating side by side? Correlation cannot tell. Two wall clocks tick in lockstep without forming one mechanism, and falling dominoes pass a signal from first to last through purely pairwise contact. @@ -24,269 +31,297 @@ Then comes the decisive move that makes PyPhi transformative for organization th The causal information lost across that weakest seam is **system integrated information (Φ)**. This yields an exact structural test: -• **When Φ = 0 across the weakest cut**, the three-party arrangement is causally reducible: no matter how entangled the prose sounds, the workflow factors into pairwise or unilateral links without losing causal information. -• **When Φ > 0 across the weakest cut**, even the gentlest partition breaks real causal structure: the three parties form an irreducible causal whole that cannot be recovered from its pairs. +• **When Φ \= 0 across the weakest cut**, the three-party arrangement is causally reducible: no matter how entangled the prose sounds, the workflow factors into pairwise or unilateral links without losing causal information. +• **When Φ \> 0 across the weakest cut**, even the gentlest partition breaks real causal structure: the three parties form an irreducible causal whole that cannot be recovered from its pairs. -Importing IIT 4.0 and PyPhi into organization science overturns a sixty-year assumption in our field. Since Thompson (1967), scholars have treated *joint influence* (whether two actors must combine inputs to determine a third actor's next step) and *systemic wholeness* (whether the group forms an indivisible unit) as if they were the same thing. Running PyPhi across all 256 possible three-party mediated coordination structures proves that joint influence and systemic wholeness are orthogonal dimensions, revealing four distinct coordination regimes that organizational prose routinely conflates (Technical Addendum, Section A.1 and Table 1): +\[DRAFTED by Claude\] Interdependence typologies since Thompson (1967) classify how tasks, outcomes and knowledge couple (Victor & Blackburn, 1987; Wageman, 1995; Puranam, Raveendran, & Knudsen, 2012; Raveendran, Silvestri, & Gulati, 2020); none tests whether the coupled unit can be cut without loss. \[DRAFTED by Claude\] The Peirce probes (89 one-input wirings, 30 two-input forms, each cut by PyPhi) show that *joint influence* (whether two actors must combine inputs to determine a third actor's next step) and *systemic wholeness* (whether the group forms an indivisible unit) come apart in both directions, which yields four coordination regimes that organizational prose routinely conflates (Technical Addendum, Section A.1, Table 1, and Appendix A.2): -• **Dyadic Relays (no joint determination, Φ = 0):** A mediator passes Partner A's input to Partner B down a one-way chain; PyPhi proves the workflow factors into pairwise links across its weakest seam, requiring only **literacy** (reading one's own direct rule). -• **Broadcast Cascades (no joint determination, Φ > 0):** No single actor combines two inputs at once, yet closed feedback loops bind all three into an indivisible cycle that cannot be cut without losing information. -• **False Dyads and Hidden Clearinghouses (joint determination, yet three-party Φ = 0):** One actor combines inputs from two counterparts, yet the three-party system splits across its weakest seam because one party is a passive sink or interchangeable pool around a two-party core. -• **Irreducible Triads (joint determination and Φ > 0):** The mediator fuses all three parties into a unit that resists every cut. Navigating it requires **algorithmacy**: no participant can steer outcomes by reading a pairwise contract, because causal power lives in the simultaneous state of all three actors. +• **Dyadic Relays (no joint determination, Φ \= 0):** A mediator passes Partner A's input to Partner B down a one-way chain; PyPhi shows the workflow factors into pairwise links across its weakest seam, requiring only **literacy** (reading one's own direct rule). +• **Broadcast Cascades (no joint determination, Φ \> 0):** No single actor combines two inputs at once, yet closed feedback loops bind all three into an indivisible cycle that cannot be cut without losing information. +• **False Dyads and Hidden Clearinghouses (joint determination, yet three-party Φ \= 0):** One actor combines inputs from two counterparts, yet the three-party system splits across its weakest seam because one party is a passive sink or interchangeable pool around a two-party core. +• **Irreducible Triads (joint determination and Φ \> 0):** The mediator fuses all three parties into a unit that resists every cut. Navigating it requires **algorithmacy**: no participant can steer outcomes by reading a pairwise contract, because causal power lives in the simultaneous state of all three actors. -## 3. Why and How We Use AI: A Self-Exemplifying Research Harness, Not "AI Doing Research" +## 3\. Why and How We Use AI: A Self-Exemplifying Research Harness, Not "AI Doing Research" -We do not use artificial intelligence to "do research" for us, nor do we treat Large Language Models as theoretical oracles. In fact, our preliminary laboratory tests prove that standalone LLMs fail badly when asked to judge organizational structure directly. Given ride-hail dispatch descriptions, a frontier LLM guessed from surface words ("platform," "pool") and got every nontrivial variation backward: calling driver pooling a triad when the platform-rider sub-circuit factored the pool out, and calling off-app repeat rides a dyadic collapse when direct peer-to-peer contact formed an integrated bypass core that turned platform mediation into a **Potemkin village** (Technical Addendum, Section A.2.2 and Table 5). +We do not use artificial intelligence to "do research" for us, nor do we treat Large Language Models as theoretical oracles. In fact, our preliminary laboratory tests show that a standalone LLM fails when asked to judge organizational structure directly. \[DRAFTED by Claude\] Given only the case prose, the model found both human-encoded design variants but predicted both verdicts backward: it expected driver pooling to stay a three-party triad (PyPhi: the drivers factor out) and off-app repeat rides to collapse into a dyad (PyPhi: a bypass core of driver and rider), a core that turned platform mediation into a **Potemkin village** (Technical Addendum, Section A.2.2 and Appendix B, Table 5). LLMs fail as structural judges because they match semantic patterns rather than computing combinatorial causal partitions. Conversely, while IIT 4.0 and PyPhi provide the exact mathematical engine organization theory needs, applying them to qualitative fieldwork previously hit a wall: hand-coding ethnographies into transition tables could neither scale nor survive a skeptic's objection that the analyst rigged the encoding. -Instead, we built a **collaborative, falsifiable research harness** (algorithmacy-lab) to execute and apply IIT 4.0 and PyPhi to organizational life (Technical Addendum, Section A.2.1 and Appendix B). Any researcher can fork our repository, engage the harness, ask an organizational question, and have their AI agents run the experimental workflow: translating field narratives into quote-anchored transition models, generating the strongest skeptical counter-encoding, executing exact PyPhi partition cuts and four falsification controls (actor removal, link severing, pooling, and peer-to-peer bypass), and contributing verified results back to the shared research program. +Instead, we built a **collaborative, falsifiable research harness** (algorithmacy-lab) to execute and apply IIT 4.0 and PyPhi to organizational life (Technical Addendum, Section A.2.1 and Appendix B). \[DRAFTED by Claude\] Any researcher can fork the lab, run its model-agnostic drafter and adversary prompts on a case, pass the result through the evidence gate, and compute. \[DRAFTED by Claude\] Three runs on stipulated cases are logged so far, all on one commercial model (Stage 2 risks in Section 5). In doing so, **our research architecture quite literally demonstrates the exact triadic coordination we are examining**. A lone scholar hand-coding a case, or prompting a chatbot in private, is a reducible dyad vulnerable to confirmation bias and hallucination. Inside our repository, the organizational scholar, the AI agents, and the deterministic PyPhi verification harness form an irreducible triad: the scholar supplies theoretical questions, competing AI agents translate field evidence and rival readings, and the PyPhi harness enforces exact partition laws and falsification gates that neither human bias nor AI fluency can bypass. -## 4. What the Harness Reveals and What We Will Do in Stage 2 (January–May 2027) +## 4\. What the Harness Reveals and What We Will Do in Stage 2 (January–May 2027\) Applying PyPhi through this harness has already established three findings for organization theory (Technical Addendum, Sections A.2–A.3 and Tables 3–6): -• **Turning interpretive deadlocks into exact empirical targets:** Running ride-hail dispatch accounts (Cameron, 2024; Rosenblat & Stark, 2016) through PyPhi collapses a decade-long debate into one observable rule (Technical Addendum, Table 3): simultaneous driver-rider-platform commitment yields an Irreducible Triad (Φ = 2.0 bits), whereas sequential offer passing yields a Dyadic Relay (Φ = 0.0 bits), pinpointing the exact field evidence needed to decide between them. -• **Mapping who holds power in an algorithmic triad:** Perturbing ride-hail dispatch and all 256 coordination structures reveals where leverage lives (Technical Addendum, Tables 3–4): mediators preserve triadic lock-in by blocking direct peer-to-peer ties between counterparts, while workers and clients escape lock-in by building outside options that preserve an independent state transition. -• **Extending PyPhi to multi-valued states and exposing correlation proxies:** Our custom multi-valued IIT 4.0 engine models multi-tiered action states (withholding, routine compliance, discretionary effort) and proves that standard correlation and mutual-information proxies miss over a third (96 of 256) of the irreducible triads that exact PyPhi catches (Technical Addendum, Appendices A–B). +• **Turning interpretive deadlocks into exact empirical targets:** Running ride-hail dispatch accounts (Cameron, 2024; Rosenblat & Stark, 2016\) through PyPhi turns a decade-long debate into one testable rule (Technical Addendum, Table 3): simultaneous driver-rider-platform commitment yields an Irreducible Triad (Φ \= 2.0 bits), whereas sequential offer passing yields a Dyadic Relay (Φ \= 0.0 bits), pinpointing the exact field evidence needed to decide between them. +• **Mapping who holds power in an algorithmic triad:** Perturbing ride-hail dispatch and all 256 coordination structures reveals where leverage lives (Technical Addendum, Tables 3–4): mediators preserve triadic lock-in by blocking direct peer-to-peer ties between counterparts, while workers and clients escape lock-in by building outside options that preserve an independent state transition. +• **Extending PyPhi to multi-valued states and exposing correlation proxies:** Our custom multi-valued IIT 4.0 engine models multi-tiered action states (withholding, routine compliance, discretionary effort) \[DRAFTED by Claude\] and shows that two popular time-series proxies barely beat chance on the 256-form census (rank-AUC 0.563 and 0.629), while exact PyPhi finds its 24 irreducible forms (Technical Addendum, Appendix A.3). -In Stage 2 (January–May 2027), we will use the harness to execute three workstreams (Technical Addendum, Section A.3 and Appendix C): (1) **a comparative re-analysis of 10 to 15 landmark ethnographies of algorithmic management**, paired with dual human field-coder validation on ride-hail dispatch and archival GitHub pull-request review gates; (2) **an actor-indexed strategic model of triadic lock-in and coalition escape**, testing when mediators fuse partners into a triad versus keeping them in dyadic silos; and (3) **an open-source release of the harness and command-line toolkit before the February 2027 Duke workshop**, enabling any organizational scholar to fork the repository and run exact PyPhi experiments on their own cases. +In Stage 2 (January–May 2027), we will use the harness to execute three workstreams (Technical Addendum, Section A.3 and Appendix C): (1) **a comparative re-analysis of 10 to 15 landmark ethnographies of algorithmic management**, paired with dual human field-coder validation on ride-hail dispatch and archival GitHub pull-request review gates; (2) **an actor-indexed strategic model of triadic lock-in and coalition escape**, testing when mediators fuse partners into a triad versus keeping them in dyadic silos; and (3) **an open-source release of the harness and command-line toolkit before the 27–28 February 2027 workshop (dates tentative)**, enabling any organizational scholar to fork the repository and run exact PyPhi experiments on their own cases. -## 5. Boundary Conditions, Key Risks, and How Organization Science Changes +## 5\. Boundary Conditions, Key Risks, and How Organization Science Changes Four boundary conditions govern this program, each stress-tested in our preliminary audits (Technical Addendum, Section A.4 and Table 6): -• **Interpretive ambiguity:** When field prose leaves a transition rule underspecified, a skeptical encoding can flip Φ; our harness reports the spread between primary and skeptical verdicts to pinpoint what field observation is missing. -• **Lock-in versus performance:** High Φ measures structural indivisibility, not efficiency or fairness; in our benchmarks, Φ is orthogonal to task payoff across both extractive platform traps and high-performing teams. -• **Boundary specification:** Omitting a fourth party or imputing ties via closure priors distorts partition cuts even when correlations look healthy, which is why the harness enforces actor-removal and boundary checks. +• **Interpretive ambiguity:** When field prose leaves a transition rule underspecified, a skeptical encoding can flip Φ; our harness reports the spread between primary and skeptical verdicts to pinpoint what field observation is missing. +• **Lock-in versus performance:** High Φ measures structural indivisibility, not efficiency or fairness; in our benchmarks, Φ is orthogonal to task payoff across both extractive platform traps and high-performing teams. +• **Boundary specification:** Omitting a fourth party or imputing ties via closure priors distorts partition cuts even when correlations look healthy, which is why the harness enforces actor-removal and boundary checks. • **Combinatorial scale:** Because PyPhi evaluates every partition, exact IIT 4.0 scales exponentially and targets governance nuclei of three to ten interacting roles. -When Daft and Lewin (1990) launched *Organization Science*, they urged scholars to break out of the "normal science straitjacket." By bringing Integrated Information Theory and PyPhi into organization theory—and wrapping them in an open, self-exemplifying research harness that any scholar and their AI agents can fork, interrogate, and extend—we give the field an exact instrument to measure when three actors become more than the sum of their dyadic parts, and when work crosses the threshold from **literacy** to **algorithmacy**. +\[DRAFTED by Claude\] Three risks govern Stage 2: fieldwork waits on IRB approval; encoding must hold on open-weight models, not only the commercial one we logged; and AI–human coder agreement (target Krippendorff's α ≥ 0.80 per rule) is unmeasured. \[DRAFTED by Claude\] Every verdict audits rule architectures, not individuals, and the lever matrix is symmetric (Technical Addendum, Section A.4). +When Daft and Lewin (1990) launched *Organization Science*, they urged scholars to break out of the "normal science straitjacket." By bringing Integrated Information Theory and PyPhi into organization theory—and wrapping them in an open, self-exemplifying research harness that any scholar and their AI agents can fork, interrogate, and extend—we give the field an exact instrument to measure when three actors become more than the sum of their dyadic parts, and when work crosses the threshold from **literacy** to **algorithmacy**. # Part II: Technical Addendum — Formal Mechanics, Worked Tables, and Verification Compendium ## Addendum Section A.1. Formal Representation, Boolean Transition Mechanics, and Regime Classification -In their inaugural editorial for *Organization Science*, Daft and Lewin (1990) urged organizational scholars to break out of the "normal science straitjacket." Thirty-six years later, generative AI threatens an inverted version of that trap: automating low-cost, incremental variations on familiar designs rather than opening scientific questions that were previously intractable (Gartenberg, Hasan, Murray, & Pierce, 2026; March, 1991; Girotra, Terwiesch, & Ulrich, 2010). +In their inaugural editorial for Organization Science, Daft and Lewin (1990) urged organizational scholars to break out of the "normal science straitjacket." Thirty-six years later, generative AI threatens an inverted version of that trap: automating low-cost, incremental variations on familiar designs rather than opening scientific questions that were previously intractable (Gartenberg, Hasan, Murray, & Pierce, 2026; March, 1991; Girotra, Terwiesch, & Ulrich, 2010). Our core contribution addresses a foundational measurement problem in organizational theory. Platforms, clearinghouses, and AI agents now sit at the center of workplace coordination (Kellogg, Valentine, & Christin, 2020; Rahman, 2021; Cameron, 2024; Curchod, Patriotta, Cohen, & Neysen, 2020; Anthony, Bechky, & Fayard, 2023; Orlikowski & Scott, 2008). Yet organizational science still lacks a reproducible way to test a basic structural claim: **when an intermediary sits between two parties, is the three-party arrangement genuinely triadic—held together only by all three parties acting in concert—or does it factor into pairwise dyads that merely pass through the middle?** -Nearly every major stream of organization theory stakes a claim on this distinction—Simmel (1902/1950) on *tertii* and super-individual wholes, Caplow (1956) on coalitions, Burt (1992) on structural holes, Obstfeld (2005) on *tertius iungens*, Granovetter (1973) on bridges, Coleman (1988) on closure, Ostrom (1990) on polycentric governance, Thompson (1967) on interdependence, and Wageman (1995) on hybrid tasks—without a common mathematical test to decide it on organizational evidence. Worse, when qualitative accounts of an arrangement disagree (for example, a platform dispatch manual describing joint matching versus a driver describing a one-way algorithmic dictate), researchers typically average two human coders into an inter-rater reliability score, burying the structural disagreement inside a consensus code. +Nearly every major stream of organization theory stakes a claim on this distinction—Simmel (1902/1950) on tertii and super-individual wholes, Caplow (1956) on coalitions, Burt (1992) on structural holes, Obstfeld (2005) on tertius iungens, Granovetter (1973) on bridges, Coleman (1988) on closure, Ostrom (1990) on polycentric governance, Thompson (1967) on interdependence, and Wageman (1995) on hybrid tasks—without a common mathematical test to decide it on organizational evidence. Worse, when qualitative accounts of an arrangement disagree (for example, a platform dispatch manual describing joint matching versus a driver describing a one-way algorithmic dictate), researchers typically average two human coders into an inter-rater reliability score, burying the structural disagreement inside a consensus code. ### How We Represent and Test an Organizational Triad -Consider a recurring organizational act involving three parties—for instance, a Driver (*D*), a Dispatch Platform (*P*), and a Rider (*R*). At each step, each party has a binary action state (`1` = commits/participates; `0` = withholds/waits) and a deterministic rule for its next state (*D*′, *P*′, *R*′) as a function of the current states of the parties (`AND` [∧], `OR` [∨], `NOT` [¬], `XOR` [⊕]): +Consider a recurring organizational act involving three parties—for instance, a Driver (D), a Dispatch Platform (P), and a Rider (R). At each step, each party has a binary action state (1 \= commits/participates; 0 \= withholds/waits) and a deterministic rule for its next state (D′, P′, R′) as a function of the current states of the parties (AND \[∧\], OR \[∨\], NOT \[¬\], XOR \[⊕\]): -* **A Relay / Conduit (*P*′ = *D*):** Suppose the platform simply relays the driver's state to the rider (*D*′ = *P*, *P*′ = *D*, *R*′ = *P*). Here the platform never combines both sides' states; the rider is a downstream receiver, and severing the rider from the loop leaves the driver–platform interaction intact. -* **A Joint-Commitment Clearinghouse (*P*′ = *D* ∧ *R*):** Now suppose the platform commits a dispatch *only when both* the driver is available *and* the rider has confirmed (*D*′ = *P*, *P*′ = *D* ∧ *R*, *R*′ = *P*). Here no pairwise slice explains what the platform does next; the transition depends irreducibly on the joint state of both counterparts. +* **A Relay / Conduit (P′ \= D):** Suppose the platform simply relays the driver's state to the rider (D′ \= P, P′ \= D, R′ \= P). Here the platform never combines both sides' states; the rider is a downstream receiver, and severing the rider from the loop leaves the driver–platform interaction intact. +* **A Joint-Commitment Clearinghouse (P′ \= D ∧ R):** Now suppose the platform commits a dispatch only when both the driver is available and the rider has confirmed (D′ \= P, P′ \= D ∧ R, R′ \= P). Here no pairwise slice explains what the platform does next; the transition depends irreducibly on the joint state of both counterparts. To test where any multi-party rule table falls, we compile the rules into a state-by-node Transition Probability Matrix (TPM) and compute exact **system integrated information Φ over the Minimum Information Partition (MIP)** in Integrated Information Theory 4.0 (Albantakis et al., 2023; Mayner et al., 2018). The MIP cuts the system into independent parts in every possible way, severs the causal links crossing the cut, and measures how much cause-and-effect information is lost under the least-destructive cut: -1. **Factorable / Dyadic (Φ(MIP) = 0):** If some cut loses zero causal information, the arrangement factors into simpler parts. -2. **Irreducible / Triadic (Φ(MIP) > 0):** If every cut loses causal information, the arrangement is dynamically irreducible, and IIT 4.0's **major complex** (`maximal_complex`) identifies the exact subset of parties that forms the irreducible core ({*D*, *P*, *R*} of size 3, or a two-party capture/bypass core {*P*, *R*}, {*D*, *P*}, or {*D*, *R*}). +1. **Factorable / Dyadic (Φ(MIP) \= 0):** If some cut loses zero causal information, the arrangement factors into simpler parts. +2. **Irreducible / Triadic (Φ(MIP) \> 0):** If every cut loses causal information, the arrangement is dynamically irreducible, and IIT 4.0's **major complex** (maximal\_complex) identifies the exact subset of parties that forms the irreducible core ({D, P, R} of size 3, or a two-party capture/bypass core {P, R}, {D, P}, or {D, R}). ### Two Foundational Guardrails (Algebraic Logic and Structural Regime Classification) -Our framework pairs exact Φ(MIP) with two theoretical guardrails (proved and benchmarked in Technical Appendix A): +Our framework pairs exact Φ(MIP) with two theoretical guardrails (stated and benchmarked in Technical Appendix A): + +* **Why Peirce vs. Quine Matters:** Peirce (1897/1933) argued that genuine triadic relations cannot be built from dyads alone, whereas Quine (1954) showed that any n-ary predicate can be rewritten as a single dyadic predicate F by expanding the domain with iterated Kuratowski ordered pairs. Modern universal algebra explains why both hold in their respective settings: in unrestricted primitive-positive clones \[F\]ₚₚ, the ternary diagonal Δ₃ is definable from binary equality via (x \= y) ∧ (y \= z) (Koshkin, 2024a, 2024b), whereas in Peircean Algebraic Logic without primitive teridentity (PAL ∖ {id₃}; Burch, 1991; Hereth Correia & Pöschel, 2004, 2006\) and in bond algebra over a fixed set of parties (Koshkin, 2024b), binary composition never creates a three-way junction. Because an empirical study fixes who the organizational parties are, irreducibility must be tested over that fixed party set. +* **Why Dynamical Wholeness (Φ(MIP) \> 0\) Must Be Paired with Mediator Regime (regime.py):** Our computational probes show that dynamical wholeness (Φ(MIP) \> 0\) and two-input joint determination cross in both directions: a cyclic three-party copy ring (A′ \= C, B′ \= A, C′ \= B) uses only one-input copy rules yet scores Φ(MIP) \= 2.0 because no cut can sever a closed ring without loss, whereas 11 of 30 two-input mediated forms (such as a three-voter majority triad) contain genuine two-input rules yet factor at Φ(MIP) \= 0\. Our pipeline therefore reports both Φ(MIP) with its major complex and the structural mediator regime (the code's dyadic, glossed here as PASSIVE or CONDUIT, and BOTTLENECK, CAPTURE, ENRICHER, BYPASSED), distinguishing cyclic one-input relays from genuine joint-commitment triads. +* **From Literacy to Algorithmacy:** This distinction grounds our construct of **algorithmacy**: whereas oracy, literacy, and numeracy suffice when technology acts as a passive dyadic conduit (Φ(MIP) \= 0), coordinating through an active algorithmic mediator that binds parties into an irreducible causal complex (Φ(MIP) \> 0\) requires reasoning about joint commitment rules, outside options, and partition fault lines. -* **Why Peirce vs. Quine Matters:** Peirce (1897/1933) argued that genuine triadic relations cannot be built from dyads alone, whereas Quine (1954) showed that any *n*-ary predicate can be rewritten as a single dyadic predicate *F* by expanding the domain with iterated Kuratowski ordered pairs. Modern universal algebra explains why both hold in their respective settings: in unrestricted primitive-positive clones [F]ₚₚ, the ternary diagonal Δ₃ is definable from binary equality via (*x* = *y*) ∧ (*y* = *z*) (Koshkin, 2024, 2025), whereas in Peircean Algebraic Logic without primitive teridentity (PAL ∖ {id₃}; Burch, 1991; Hereth Correia & Pöschel, 2004, 2006) and in bond algebra over a fixed set of parties (Koshkin, 2025), binary composition never creates a three-way junction. Because an empirical study fixes who the organizational parties are, irreducibility must be tested over that fixed party set. -* **Why Dynamical Wholeness (Φ(MIP) > 0) Must Be Paired with Mediator Regime (`regime.py`):** Our computational probes show that dynamical wholeness (Φ(MIP) > 0) and two-input joint determination cross in both directions: a cyclic three-party copy ring (*A*′ = *C*, *B*′ = *A*, *C*′ = *B*) uses only one-input copy rules yet scores Φ(MIP) = 2.0 because no cut can sever a closed ring without loss, whereas 11 of 30 two-input mediated forms (such as a unanimous three-voter majority triad) contain genuine two-input rules yet factor at Φ(MIP) = 0. Our pipeline therefore reports **both** Φ(MIP) with its major complex **and** the structural mediator regime (`PASSIVE`, `CONDUIT`, `BOTTLENECK`, `CAPTURE`, `ENRICHER`, `BYPASSED`), distinguishing cyclic one-input relays from genuine joint-commitment triads. -* **From Literacy to Algorithmacy:** This distinction grounds our construct of **algorithmacy**: whereas *oracy*, *literacy*, and *numeracy* suffice when technology acts as a passive dyadic conduit (Φ(MIP) = 0), coordinating through an active algorithmic mediator that binds parties into an irreducible causal complex (Φ(MIP) > 0) requires reasoning about joint commitment rules, outside options, and partition fault lines. +Table 1: Coordination regimes, rule architectures, and exact IIT 4.0 verdicts -| Coordination Regime (`regime.py`) | Rule Architecture & Input Structure | Exact IIT 4.0 Verdict & Major Complex | Mediator Role (`classify_mediator`) | Organizational Archetype & Required Competency | -| :--- | :--- | :--- | :--- | :--- | -| **Factored Dyadic Conduit** | Pairwise signals or passive pass-through (*P*′ = *D*) | **Dyadic:** Φ(MIP) = 0; partitions cleanly across party cut | `PASSIVE` or `CONDUIT` | Classical communication channel; **Literacy / Numeracy** | -| **Cyclic One-Input Relay** | Unbranched 1-input cycle (*A*′ = *C*, *B*′ = *A*, *C*′ = *B*) | **Dynamical Whole:** Φ(MIP) > 0, but max input arity = 1 (no 2-input rule) | `CONDUIT` (cyclic rotation without joint commit) | Sequential rotation / relay ring; **Extended Literacy** | -| **Asymmetric Capture Triad** | Mediator jointly commits on two parties; one party has an outside option | **Triadic Sub-Complex:** Φ(MIP) > 0; major complex binds {*P*, *R*} or {*D*, *P*} (size 2) | `CAPTURE` (mediator + non-exiting party) | Platform lock-in of captive side; **Strategic Algorithmacy** | -| **Irreducible Mediated Triad** | Mediator commits on joint state (*P*′ = *D* ∧ *R*) and parties read mediator | **Triadic Complex:** Φ(MIP) > 0; major complex binds all three parties {*D*, *P*, *R*} | `BOTTLENECK` (drops on removal) or `ENRICHER` | Active clearinghouse / protocol triad; **Full Algorithmacy** | +| Coordination Regime (`regime.py`) | Rule Architecture & Input Structure | Exact IIT 4.0 Verdict & Major Complex | Mediator Role (regime() in regime.py) | Organizational Archetype & Required Competency | +| :---- | :---- | :---- | :---- | :---- | +| **Factored Dyadic Conduit** | Pairwise signals or passive pass-through (*P*′ \= *D*) | **Dyadic:** Φ(MIP) \= 0; partitions cleanly across party cut | `dyadic (glossed PASSIVE or CONDUIT)` | Classical communication channel; **Literacy / Numeracy** | +| **Broadcast Cascade (Cyclic One-Input Relay)** | Unbranched 1-input cycle (*A*′ \= *C*, *B*′ \= *A*, *C*′ \= *B*) | **Dynamical Whole:** Φ(MIP) \> 0, but max input arity \= 1 (no 2-input rule) | `CONDUIT` (cyclic rotation without joint commit) | Sequential rotation / relay ring; **Extended Literacy** | +| **Asymmetric Capture Triad** | Mediator jointly commits on two parties; one party has an outside option | **Triadic Sub-Complex:** Φ(MIP) \> 0; major complex binds {*P*, *R*} or {*D*, *P*} (size 2\) | `CAPTURE` (mediator \+ non-exiting party) | Platform lock-in of captive side; **Strategic Algorithmacy** | +| **Irreducible Mediated Triad** | Mediator commits on joint state (*P*′ \= *D* ∧ *R*) and parties read mediator | **Triadic Complex:** Φ(MIP) \> 0; major complex binds all three parties {*D*, *P*, *R*} | `BOTTLENECK` (drops on removal) or `ENRICHER` | Active clearinghouse / protocol triad; **Full Algorithmacy** | -## Addendum Section A.2. Complete Six-Step Pipeline Mechanics and Worked Ride-Hail Dispatch Proof of Concept +## Addendum Section A.2. The Six-Step AI-and-PyPhi Pipeline and Proof of Concept -We have built, tested, and packaged a self-contained open-source prototype (`irreducibility-pipeline`, tag `v0.1-stage1`, which reproduces all 17 reference results and passes 19 automated test gates in two minutes via a single command), backed by our broader computational laboratory (`algorithmacy-lab`, containing 127 studies and 542 automated CI checks). +We have built, tested, and packaged a self-contained open-source prototype (the irreducibility-pipeline/ directory of algorithmacy-lab, https\://github.com/rogerSuperBuilderAlpha/algorithmacy-lab, lab tag orgsci-stage1; from a clone of the lab, python irreducibility-pipeline/reproduce.py reproduces all 17 reference results in about 2½ minutes and pytest \-q irreducibility-pipeline/tests passes 19 automated tests in 5 seconds; prototype paths below are relative to irreducibility-pipeline/), backed by our broader computational laboratory (algorithmacy-lab, containing 127 studies and 542 automated CI checks). ### A.2.1. AI-Enabled Research Loop Under Human Direction: The Six-Step Pipeline The central methodological challenge in applying exact causal measures to organizations is translating qualitative evidence (platform manuals, interviews, workflow logs) into formal transition rules without smuggling the researcher's preferred conclusion into the encoding. Asking an LLM to directly label a case "triadic" or "dyadic" fails because LLMs hallucinate ungrounded rules and misguess multi-party partition math. Instead, our **six-step AI-and-PyPhi pipeline** separates **structured qualitative reading** (done by two LLMs under a deterministic code gate) from **exact partition math** (done by PyPhi): -1. **Step 1 — Bound and Name (`protocol/`):** Fix one recurring organizational act, name the *n* parties (typically 3 to 5), and define each party's binary action state (`1` = commits; `0` = withholds). -2. **Step 2 — Encode via Drafter, Adversary, and Verbatim Gate (`encode/`):** An LLM **Drafter** (`PROMPT_drafter.md`) extracts every defensible Boolean encoding supported by the source text over party labels (`and` [∧], `or` [∨], `not` [¬], `xor` [⊕], `0`, `1`). Every rule must attach a **verbatim quote** from the source document, state whether the mediator *commits* on a joint condition, *conveys* one side's state, or *stores* inputs, and record a pre-registered prediction before computation. A second LLM **Adversary** (`PROMPT_adversary.md`) searches for rival encodings across three structural forces: commit versus convey, interchangeable pooled parties (`or` [∨]), and outside options. A deterministic gate (`encode_check.py`) rejects any encoding with a missing rule, a quote not found character-for-character in the source text, a missing mediator alternative, or a missing prediction before PyPhi can run. -3. **Step 3 — Compute (`irreducibility/core.py`):** Compiles each rule set into a 2ⁿ × *n* state-by-node TPM and connectivity matrix and calls PyPhi (`wmayner/pyphi`, commit `b78d0e342`) to compute exact Φ(MIP) and the major complex across all reachable states. -4. **Step 4 — Validate First (`irreducibility/validate.py`):** Before any empirical result can be reported, the solver must pass four mandatory control structures (`controls.py`, shown in Table 2). -5. **Step 5 — Report the Spread (`irreducibility/spread.py`):** Rather than collapsing rival readings into a single point estimate, the pipeline reports verdict agreement across all defensible encodings, the Φ gap (max Φ − min Φ), and the **exact single-rule flips** that reverse the verdict. -6. **Step 6 — Read the Structure (`irreducibility/regime.py`, `contingency.py`):** Compares the three-party core against the two-party bypass reduction (`reduce_mediator`) to classify the mediator (`PASSIVE`, `CONDUIT`, `BOTTLENECK`, `CAPTURE`, `ENRICHER`, `BYPASSED`) and sweeps outside-option exit scenarios. +1. **Step 1 — Bound and Name (protocol/):** Fix one recurring organizational act, name the n parties (typically 3 to 5), and define each party's binary action state (1 \= commits; 0 \= withholds). +2. **Step 2 — Encode via Drafter, Adversary, and Verbatim Gate (encode/):** An LLM Drafter (PROMPT\_drafter.md) extracts every defensible Boolean encoding supported by the source text over party labels (and \[∧\], or \[∨\], not \[¬\], xor \[⊕\], 0, 1). Every rule must attach a verbatim quote from the source document, state whether the mediator commits on a joint condition, conveys one side's state, or stores inputs, and record a prediction fixed before anything is computed. A second LLM Adversary (PROMPT\_adversary.md) searches for rival encodings across three structural forces: commit versus convey, interchangeable pooled parties (or \[∨\]), and outside options. A deterministic gate (encode\_check.py) rejects any encoding with a missing rule, a quote not found character-for-character in the source text, a missing mediator alternative, or a missing prediction before PyPhi can run. +3. **Step 3 — Compute (irreducibility/core.py):** Compiles each rule set into a 2ⁿ × n state-by-node TPM and connectivity matrix and calls PyPhi (wmayner/pyphi, commit b78d0e342) to compute exact Φ(MIP) and the major complex across all reachable states. +4. **Step 4 — Validate First (irreducibility/validate.py):** Before any empirical result can be reported, the solver must pass two mandatory controls and five reference forms (validate.py; Table 2 shows the two controls and two of the five reference forms). +5. **Step 5 — Report the Spread (irreducibility/spread.py):** Rather than collapsing rival readings into a single point estimate, the pipeline reports verdict agreement across all defensible encodings, the Φ gap (max Φ − min Φ), and the exact single-rule flips that reverse the verdict. +6. **Step 6 — Read the Structure (irreducibility/regime.py, contingency.py):** Compares the three-party core against the two-party bypass reduction (contingency\_test() and add\_bypass() in contingency.py, which return intrinsic, contingent, partial, or reducible) and classifies the mediator's position with regime() in regime.py (REGIMES: dyadic, glossed here as PASSIVE or CONDUIT, BYPASSED, CAPTURE, BOTTLENECK, ENRICHER; with lesion\_survives()), while classify\_rules() in core.py returns the verdict. Outside options are tested through the O₁–O₅ design encodings in examples/01\_gig\_dispatch/ and studies/enricher\_regime.py. + +Table 2: Instrument controls and reference forms run before any result (validate.py) -| Mandatory Control (`irreducibility/controls.py`) | Party Rules (*W*′, *S*′, *C*′) | Exact IIT 4.0 Verdict & Core | Exact Φ(MIP) | Structural Purpose in Pipeline | -| :--- | :--- | :--- | :--- | :--- | -| **1. Factoring Control** | *W*′ = *S*, *S*′ = *W*, *C*′ = *C* | **Dyadic** (factors cleanly) | Φ(MIP) = 0.000 | Verifies decoupled third party scores strictly zero | -| **2. Irreducible Control** | *W*′ = *S* ∨ *C*, *S*′ = *W* ∧ *C*, *C*′ = *W* ⊕ *S* | **Triadic** (core {*W*, *S*, *C*}) | Φ(MIP) = 0.830 | Verifies mixed AND/OR/XOR mechanism is irreducible | -| **3. Strict-Mediation Triad** | *W*′ = *S*, *S*′ = *W* ∧ *C*, *C*′ = *S* | **Triadic** (core {*W*, *S*, *C*}) | Φ(MIP) = 2.000 | Canonical conjunctive clearinghouse bottleneck | -| **4. Gig "False Dyad"** | *W*′ = ¬*S*, *S*′ = *W* ∧ *C*, *C*′ = *C* ∧ ¬*S* | **Triadic** (core {*W*, *S*, *C*}) | Φ(MIP) = 2.000 | Asymmetric dispatch triad that looks dyadic on surface | +| Control or Reference Form (irreducibility/validate.py) | Party Rules (*W*′, *S*′, *C*′) | Exact IIT 4.0 Verdict & Core | Exact Φ(MIP) | Structural Purpose in Pipeline | +| :---- | :---- | :---- | :---- | :---- | +| **1\. Factoring Control** | *W*′ \= *S*, *S*′ \= *W*, *C*′ \= *C* | **Dyadic** (factors cleanly) | Φ(MIP) \= 0.000 | Verifies decoupled third party scores strictly zero | +| **2\. Irreducible Control** | *W*′ \= *S* ∨ *C*, *S*′ \= *W* ∧ *C*, *C*′ \= *W* ⊕ *S* | **Triadic** (core {*W*, *S*, *C*}) | Φ(MIP) \= 0.830 | Verifies mixed AND/OR/XOR mechanism is irreducible | +| **3\. Strict-Mediation Triad (reference form)** | *W*′ \= *S*, *S*′ \= *W* ∧ *C*, *C*′ \= *S* | **Triadic** (core {*W*, *S*, *C*}) | Φ(MIP) \= 2.000 | Canonical conjunctive clearinghouse bottleneck | +| **4\. Gig "False Dyad" (reference form)** | *W*′ \= ¬*S*, *S*′ \= *W* ∧ *C*, *C*′ \= *C* ∧ ¬*S* | **Triadic** (core {*W*, *S*, *C*}) | Φ(MIP) \= 2.000 | Asymmetric dispatch triad that looks dyadic on surface | ### A.2.2. Complete Walk-Through and Blind AI Runs: Ride-Hail Dispatch -To see what the pipeline reveals that standard coding misses, consider Worked Example 01 (`examples/01_gig_dispatch/`, summarized in Table 3). The source dossier contains two conflicting accounts of ride-hail dispatch: the platform manual states that dispatch *"assigns a trip only when an eligible driver is available and a rider has confirmed the request,"* whereas an interviewed driver states, *"It's a suggestion, it follows what I do."* +To see what the pipeline reveals that standard coding misses, consider Worked Example 01 (examples/01\_gig\_dispatch/, summarized in Table 3). The source dossier contains two conflicting accounts of ride-hail dispatch: the platform manual states that dispatch "assigns a trip only when an eligible driver is available and a rider has confirmed the request," whereas an interviewed driver states, "It's a suggestion, it follows what I do." -* **Pinpointing the Exact Rule Carrying a Qualitative Dispute (*R*₁ vs. *R*₂):** Under the platform manual (*R*₁: *D*′ = *P*, *P*′ = *D* ∧ *R*, *R*′ = *P*), PyPhi returns Φ(MIP) = 2.000 with major complex {*D*, *P*, *R*}; removing the platform collapses coordination to Φ = 0, classifying the platform as a triadic `BOTTLENECK`. Under the driver's account (*R*₂), only the platform's rule changes (*P*′ = *D*), and the system factors completely (Φ(MIP) = 0.000, `CONDUIT`). Instead of averaging the two accounts, the pipeline isolates *P*′ as the single rule carrying the entire disagreement and specifies the observable test (whether dispatch ever commits when *D* = 1 and *R* = 0) that decides between them. -* **Pooling Interchangeable Workers (*D*₁) and Off-App Bypass (*D*₂):** When the platform pools two interchangeable drivers via `OR` (*D*₁: *P*′ = (*D*₁ ∨ *D*₂) ∧ *R*), neither individual driver remains necessary to the match: PyPhi factors both drivers out of the major complex, leaving only {*P*, *R*} bound (Φ(MIP) = 1.000). Conversely, if driver and rider establish a direct off-app tie (*D*₂: *D*′ = *P* ∨ *R*, *R*′ = *P* ∨ *D*), the major complex shifts to {*D*, *R*} (Φ(MIP) = 1.198) and the platform is classified as `BYPASSED`. -* **The Outside-Option Law (*O*₁–*O*₅ and 60/60 Random Trials):** Sweeping outside options (*E*(*D*), *E*(*R*)) reveals a sharp structural law that held across **60 of 60** randomized multi-party configurations: **a platform's irreducible core consists of itself plus whichever parties lack an outside option.** Giving the driver an outside option (*O*₂) shrinks the core to {*P*, *R*} (`CAPTURE` of the rider); giving the rider an outside option (*O*₃) shrinks the core to {*D*, *P*} (`CAPTURE` of the driver); giving both sides outside options (*O*₄) dissolves lock-in to Φ(MIP) = 0. +* **Pinpointing the Exact Rule Carrying a Qualitative Dispute (R₁ vs. R₂):** Under the platform manual (R₁: D′ \= P, P′ \= D ∧ R, R′ \= P), PyPhi returns Φ(MIP) \= 2.000 with major complex {D, P, R}; removing the platform collapses coordination to Φ \= 0, classifying the platform as a triadic BOTTLENECK. Under the driver's account (R₂), only the platform's rule changes (P′ \= D), and the system factors completely (Φ(MIP) \= 0.000; the code prints dyadic, glossed here as CONDUIT). Instead of averaging the two accounts, the pipeline isolates P′ as the single rule carrying the entire disagreement and specifies the observable test (whether dispatch ever commits when D \= 1 and R \= 0\) that decides between them. +* **Pooling Interchangeable Workers (D₁) and Off-App Bypass (D₂):** When the platform pools two interchangeable drivers via OR (D₁: P′ \= (D₁ ∨ D₂) ∧ R), neither individual driver remains necessary to the match: PyPhi factors both drivers out of the major complex, leaving {P, R} as the major complex while the system as a whole scores Φ(MIP) \= 0.000 (dyadic). Conversely, if driver and rider establish a direct off-app tie (D₂: D′ \= P ∨ R, R′ \= P ∨ D), the major complex shifts to {D, R} (Φ(MIP) \= 0.830) and the platform is classified as BYPASSED. +* **The Outside-Option Law (O₁–O₅ and 60/60 Random Trials):** Sweeping outside options (E(D), E(R)) reveals a sharp structural law that held across 60 of 60 randomized multi-party configurations: **a platform's irreducible core consists of itself plus whichever parties lack an outside option.** \[DRAFTED by Claude\] Giving only the rider an outside option (O₃) shrinks the core to the captive driver and the platform; giving only the driver one (O₄) shrinks it to the platform and the captive rider; giving both (O₅) removes the platform from the core and leaves the driver and rider bound to each other — the platform is bypassed, not dissolved. + +Table 3: Gig-dispatch encodings, outside-option designs, and exact Φ(MIP) verdicts | Encoding ID & Reading (`examples/01_gig_dispatch/`) | Formal Transition Rules (*D*′, *P*′, *R*′) | Exact Φ(MIP) | Major Complex (Core) | Structural Verdict & Mediator Regime | -| :--- | :--- | :--- | :--- | :--- | -| **R₁: Platform Manual** (Joint matching) | *D*′ = *P*, *P*′ = *D* ∧ *R*, *R*′ = *P* | Φ(MIP) = 2.000 | {*D*, *P*, *R*} (size 3) | **Triadic `BOTTLENECK`** (bypass collapses to Φ = 0) | -| **R₂: Driver Experience** (Conduit / dictate) | *D*′ = *P*, *P*′ = *D*, *R*′ = *P* | Φ(MIP) = 0.000 | {*D*, *P*} (dyadic) | **Dyadic `CONDUIT`** (single rule *P*′ flips verdict) | -| **D₁: Driver Pool** (2 interchangeable drivers) | *D*₁′ = *P*, *D*₂′ = *P*, *P*′ = (*D*₁ ∨ *D*₂) ∧ *R*, *R*′ = *P* | Φ(MIP) = 1.000 | {*P*, *R*} (size 2) | **Factored on Drivers** (individual *D*ᵢ excluded from core) | -| **D₂: Direct-Tie Bypass** (Off-app rider–driver tie) | *D*′ = *P* ∨ *R*, *P*′ = *D* ∧ *R*, *R*′ = *P* ∨ *D* | Φ(MIP) = 1.198 | {*D*, *R*} (size 2) | **`BYPASSED`** (direct tie binds {*D*, *R*} without *P*) | -| **O₁: No Outside Options** (Both captive) | *D*′ = *P*, *P*′ = *D* ∧ *R*, *R*′ = *P* | Φ(MIP) = 2.000 | {*D*, *P*, *R*} (size 3) | **Full Triadic Core** (neither party can exit) | -| **O₂: Driver Outside Option** (*E*(*D*) = 1) | *D*′ = *P* ∨ *E*(*D*), *P*′ = *D* ∧ *R*, *R*′ = *P* | Φ(MIP) = 2.000 | {*P*, *R*} (size 2) | **`CAPTURE` of Rider** (exiting driver leaves core) | -| **O₃: Rider Outside Option** (*E*(*R*) = 1) | *D*′ = *P*, *P*′ = *D* ∧ *R*, *R*′ = *P* ∨ *E*(*R*) | Φ(MIP) = 2.000 | {*D*, *P*} (size 2) | **`CAPTURE` of Driver** (exiting rider leaves core) | -| **O₄: Both Have Outside Options** | *D*′ = *P* ∨ *E*(*D*), *P*′ = *D* ∧ *R*, *R*′ = *P* ∨ *E*(*R*) | Φ(MIP) = 0.000 | ∅ (fully factored) | **Complete Dissolution** (platform loses all lock-in) | -| **O₅: Platform Substitute** (Multi-homing) | *D*′ = *P*₁ ∨ *P*₂, *P*₁′ = *D* ∧ *R*, *R*′ = *P*₁ ∨ *P*₂ | Φ(MIP) = 1.000 | {*D*, *R*} (size 2) | **Mediator Replaced** (competing platforms factor out) | +| :---- | :---- | :---- | :---- | :---- | +| **R₁: Platform Manual** (Joint matching) | *D*′ \= *P*, *P*′ \= *D* ∧ *R*, *R*′ \= *P* | Φ(MIP) \= 2.000 | {*D*, *P*, *R*} (size 3\) | **Triadic `BOTTLENECK`** (bypass collapses to Φ \= 0\) | +| **R₂: Driver Experience** (Conduit / dictate) | *D*′ \= *P*, *P*′ \= *D*, *R*′ \= *P* | Φ(MIP) \= 0.000 | {*D*, *P*} (dyadic) | **Dyadic `CONDUIT`** (the code prints dyadic; CONDUIT is our gloss; single rule P′ flips verdict) | +| **D₁: Driver Pool** (rival encoding C; 2 interchangeable drivers) | *D*₁′ \= *P*, *D*₂′ \= *P*, *P*′ \= (*D*₁ ∨ *D*₂) ∧ *R*, *R*′ \= *P* | Φ(MIP) \= 0.000 (dyadic) | {*P*, *R*} (major complex) | **Factored on Drivers** (individual Dᵢ outside the major complex; system Φ \= 0, dyadic) | +| **D₂: Direct-Tie Bypass** (design O₅; off-app rider–driver tie) | *D*′ \= *P* ∨ *R*, *P*′ \= *D* ∧ *R*, *R*′ \= *P* ∨ *D* | Φ(MIP) \= 0.830 | {*D*, *R*} (size 2\) | **`BYPASSED`** (direct tie binds {*D*, *R*} without *P*) | +| **O₁: No Outside Options** (Both captive) | *D*′ \= *P*, *P*′ \= *D* ∧ *R*, *R*′ \= *P* | Φ(MIP) \= 2.000 | {*D*, *P*, *R*} (size 3\) | **BOTTLENECK** (neither party can exit) | +| **O₂: Complementary Direct Tie** (repeat trips need app and contact) | *D′ \= P ∧ R, P′ \= D ∧ R, R′ \= P ∧ D* | Φ(MIP) \= 6.000 | {D, *P*, *R*} (size 3\) | **`ENRICHER (all three parties stay in the core)`** | +| **O₃: Captive Driver, Mobile Rider** | *D′ \= P, P′ \= D ∧ R, R′ \= P ∨ D* | Φ(MIP) \= 0.415 | {*D*, *P*} (size 2\) | **`CAPTURE` of Driver** (exiting rider leaves core) | +| **O₄: Mobile Driver, Captive Rider** | *D′ \= P ∨ R, P′ \= D ∧ R, R′ \= P* | Φ(MIP) \= 0.415 | {P, R} (size 2\) | **CAPTURE of Rider (exiting driver leaves core)** | +| **O₅: Both Mobile** (substitute direct tie) | *D′ \= P ∨ R, P′ \= D ∧ R, R′ \= P ∨ D* | Φ(MIP) \= 0.830 | {*D*, *R*} (size 2\) | **BYPASSED (platform leaves the core; parties stay bound)** | ### Logged Blind AI Runs, Adversarial Coding, and Proxy Benchmarks Three completed empirical and computational benchmarks in our Stage 1 package demonstrate why both parts of the AI-and-PyPhi loop are necessary (full logs in Technical Appendix B): -1. **Blind LLM Runs Refuted by Exact Computation (`encode/runs/`):** In logged blind runs (Claude Sonnet 5.5, October 2026, given only raw source text), the Drafter reproduced both human rival encodings of gig dispatch with verbatim quotes. The Adversary then discovered the driver-pool encoding (*D*₁) and the direct-tie bypass encoding (*D*₂)—and **PyPhi refuted both of the LLM's own intuitive predictions** (the LLM predicted the driver pool would stay a three-party triad, whereas PyPhi showed the drivers factor out of the core; the LLM predicted the direct tie would factor, whereas PyPhi showed it forms a bypass triad {*D*, *R*}). On a second case (insurance-claim routing), the source text left four design variants underspecified; the Drafter refused to invent unquoted rules and `encode_check.py` properly rejected the file (9 errors). -2. **Adversarial Coding Across 101 Contested Accounts (`studies/adversarial_coding/`):** Across 101 contested organizational descriptions, an evidence-constrained adversary flipped the single-encoding point verdict on **101 of 101** accounts, whereas standard two-coder agreement bracketed the adversarial reading in only **22 of 101**. -3. **Failure of Standard Time-Series Proxies (`studies/proxies/`):** Across all 256 three-party structures, two popular observational time-series proxies—ΦID synergistic information Φᵣ (Mediano et al., 2025; Williams & Beer, 2010) and whole-minus-sum Φ(WMS)—separated dyadic from triadic structures at rank-AUC **0.563** and **0.629** (barely above 0.50 chance), confirming that passive time-series correlations cannot substitute for rule-level Φ(MIP). +1. **Blind LLM Runs Refuted by Exact Computation (examples/01\_gig\_dispatch/ai\_draft.json, ai\_draft\_plus\_adversary.json, ai\_adversary\_raw.json; examples/02\_insurance\_claim/ai\_draft.json):** In logged blind runs (Claude Sonnet 5.5, October 2026, given only raw source text), the Drafter reproduced both human rival encodings of gig dispatch with verbatim quotes. The Adversary then discovered the driver-pool encoding (D₁) and the direct-tie bypass encoding (D₂)—and **PyPhi refuted both of the LLM's own intuitive predictions** (the LLM predicted the driver pool would stay a three-party triad, whereas PyPhi showed the drivers factor out of the core; the LLM predicted the direct tie would factor, whereas PyPhi showed it forms a bypass triad {D, R}). On a second case (insurance-claim routing), the source text left four design variants underspecified; the Drafter left the rules of four of the five designs unwritten and encode\_check.py rejected the file (9 problems in 5 encodings: 8 missing party rules, 1 missing mediator alternative). +2. **Adversarial Coding Across 101 Contested Accounts (studies/adversarial\_coding.py):** Across 101 contested organizational descriptions, an evidence-constrained adversary flipped the single-encoding point verdict on 101 of 101 accounts, whereas standard two-coder agreement bracketed the adversarial reading in only 22 of 101\. +3. **Failure of Standard Time-Series Proxies (studies/proxy\_run.py, studies/proxy\_bridge.py, studies/phiid\_measure.py):** Across the 256 strict-mediation forms of the census, two popular observational time-series proxies—ΦID synergistic information Φᵣ (Mediano et al., 2025; Williams & Beer, 2010\) and whole-minus-sum Φ(WMS)—separated dyadic from triadic structures at rank-AUC 0.563 and 0.629 (barely above 0.50 chance), confirming that passive time-series correlations cannot substitute for rule-level Φ(MIP). ### A.2.3. Broader Laboratory Extensions (Cataloged in Appendix D) -Beyond the four worked cases in `irreducibility-pipeline` (gig dispatch, insurance-claim routing, software code-review gates, and dealer vs. clearinghouse), our laboratory (`algorithmacy-lab`) has already built: (a) a custom **multi-valued IIT 4.0 solver** (`third_party/pyphi_iit4_mv`) for graded ternary and mixed-radix state spaces; (b) **construct-validity bridges** showing that Thompson's (1967) interdependence hierarchy collapses at its top step (pooled scores Φ = 0, but sequential and reciprocal both score Φ = 2.0) and that Wageman's (1995) hybrid team designs factor cleanly; and (c) **human-in-the-loop oversight diagnostics** proving that "rubber-stamping" an AI agent's recommendations leaves the human reviewer outside the major complex while the automated loop stays integrated at Φ = 2.0, formalizing the post-hoc verification trap identified by Rudin (2019). +Beyond the four worked cases in irreducibility-pipeline/ (\[DRAFTED by Claude\] gig dispatch, a triadic BOTTLENECK at Φ \= 2.000 under the platform manual; insurance-claim routing, five designs on which two of five naive predictions held; software code-review gates, where the CI gate is BYPASSED at Φ \= 1.000 when maintainers wait for CI and joins the core as an ENRICHER at Φ \= 2.000 when they approve on the diff alone; and dealer vs. clearinghouse, both triadic at Φ \= 2.000, the dealer's place contingent on a ban on direct sales and the clearinghouse's intrinsic), our laboratory (algorithmacy-lab) has already built: (a) a custom **multi-valued IIT 4.0 solver** (third\_party/pyphi\_iit4\_mv) for graded ternary and mixed-radix state spaces; (b) **construct-validity bridges** showing that Thompson's (1967) interdependence hierarchy collapses at its top step (pooled scores Φ \= 0, but sequential and reciprocal both score Φ \= 2.0) on canonical encodings, while alternate encodings flip the verdict (pooled all-required → triadic; sequential acyclic hand-off → dyadic; verdict PARTIAL\_ALIGNMENT, alignment 0.429), and that a Wageman-style (1995) interdependence index predicts the dyadic/triadic verdict (AUC \= 1.000 on the designed panel at W ≥ 0.472) but not Φ magnitude (XOR and AND share W at Φ \= 0.5 vs. 2.0); and (c) **human-in-the-loop oversight diagnostics** showing that "rubber-stamping" an AI agent's recommendations leaves the human reviewer outside the major complex while the automated loop stays integrated at Φ \= 2.0, \[DRAFTED by Claude\] formalizing the rubber-stamp pattern that the automation-bias literature documents (Parasuraman & Riley, 1997; Skitka, Mosier, & Burdick, 1999\) and that Lebovitz, Lifshitz-Assaf, and Levina (2022) observed among radiologists facing opaque AI. -## Addendum Section A.3. Extended Stage 2 Technical Specifications and Lever Architecture +## Addendum Section A.3. Detailed Stage 2 Technical Protocols and Strategic Lever Matrix (January–May 2027\) If invited to Stage 2, we will execute three focused workstreams over the four-month revision window (detailed in Technical Appendix C): -1. **Harden and Release the Open-Source `irreducibility` Package (January–February 2027):** We will package the pipeline as a single installable command-line tool and Python library (`irreducibility init`, `encode`, `check`, `run`) supporting both Anthropic and open-weight LLM endpoints, enforcing `encode_check.py` automatically, and integrating our multi-valued IIT 4.0 engine (`pyphi_iit4_mv`) so researchers can test ternary and mixed-radix organizational rules out of the box. -2. **Complete the Actor-Indexed Strategic Model of Triadic Levers (February–March 2027):** Exhaustive enumeration of all 256 three-party Boolean structures (`studies/strategic_model/`) partitions the space into **56** dyadic structures, **132** cycle-supported triads, and **68** mediated triads. We will formalize the actor-indexed strategic lever matrix (Table 4) that computes, for each party (Mediator *M*, Party *A*, Party *B*) and each single-rule edit, how that move creates, captures, bypasses, or dissolves an irreducible triad. -3. **Comparative Empirical Application Across 10–15 Published Platform Cases & Field Protocol (March–May 2027):** We will apply the pipeline to 10–15 landmark published platform and algorithmic-management studies (including Rahman, 2021; Cameron, 2024; Curchod et al., 2020; Kellogg et al., 2020), encoding every case directly from its published text to report the full encoding spread and the deciding empirical rule. In parallel, once IRB approval is completed, we will field our pre-built ride-hail dispatch interview protocol (`protocol/`) and GitHub code-review gate study (`examples/03_code_review_gate/`). +1. **Harden and Release the Open-Source irreducibility Package (January–February 2027):** We will package the pipeline as a single installable command-line tool and Python library (irreducibility init, encode, check, run) supporting both Anthropic and open-weight LLM endpoints, enforcing encode\_check.py automatically, and integrating our multi-valued IIT 4.0 engine (pyphi\_iit4\_mv) so researchers can test ternary and mixed-radix organizational rules out of the box. +2. **Complete the Actor-Indexed Strategic Model of Triadic Levers (February–March 2027):** \[DRAFTED by Claude\] Exhaustive enumeration of the 256 strict-mediation three-party forms (4 worker rules × 16 mediator rules × 4 counterpart rules; studies/census.py) finds 24 irreducible and 232 factorable, with a mediator that reads both parties necessary but not sufficient (24/160 vs 0/96). We will formalize the actor-indexed strategic lever matrix (Table 4\) that computes, for each party (Mediator M, Party A, Party B) and each single-rule edit, how that move creates, captures, bypasses, or dissolves an irreducible triad. +3. **Comparative Empirical Application Across 10–15 Published Platform Cases & Field Protocol (March–May 2027):** We will apply the pipeline to 10–15 landmark published platform and algorithmic-management studies (including Rahman, 2021; Cameron, 2024; Curchod et al., 2020; Kellogg et al., 2020), encoding every case directly from its published text to report the full encoding spread and the deciding empirical rule. In parallel, once IRB approval is completed, we will field our pre-built ride-hail dispatch interview protocol (protocol/) and GitHub code-review gate study (irreducibility-pipeline/examples/03\_code\_review\_gate/). + +Table 4: Actor-indexed strategic lever matrix -| Focal Actor (Row) | Strategic Lever 1: Commit vs. Convey (Mediator Rule *M*′) | Strategic Lever 2: Pool Counterparts via `OR` (∨) | Strategic Lever 3: Add Outside Option (*E*ᵢ = 1) | Strategic Lever 4: Build Direct Counterpart Tie (*A* ↔ *B*) | -| :--- | :--- | :--- | :--- | :--- | -| **Mediator / Platform (*M*)** | **Switch Convey → Joint Commit** (*M*′ = *A* ∧ *B*): Creates `BOTTLENECK` triad (Φ: 0.0 → 2.0, core {*A*, *M*, *B*}) | **Pool Replaceable Side *A*** (*M*′ = (*A*₁ ∨ *A*₂) ∧ *B*): Expels *A*ᵢ from core; locks in {*M*, *B*} (Φ = 1.0) | **Block Counterpart Exit** (*E*(*A*) = *E*(*B*) = 0): Preserves full 3-party lock-in across all 60/60 random trials | **Prohibit Off-Platform Ties** (anti-disintermediation): Prevents bypass of *M* | -| **Party *A* (e.g., Worker / Driver)** | **Treat Prompt as Advisory** (*A*′ = self or convey): Dissolves `BOTTLENECK` to Φ = 0.0 if *M* follows *A* | **Form Worker Coalition / Union**: Restores collective input parity against one-sided pooling | **Secure Outside Option** (*A*′ = *M* ∨ *E*(*A*)): Frees *A* from major complex; shifts core to {*M*, *B*} (`CAPTURE` on *B* only) | **Establish Direct Tie to *B*** (*A*′ = *M* ∨ *B*): Bypasses *M*, shifting core to {*A*, *B*} (Φ = 1.198, `BYPASSED`) | -| **Party *B* (e.g., Client / Rider)** | **Require Joint Confirmation** (*M*′ = *A* ∧ *B*): Binds *B* into mediated clearinghouse if no exit exists | **Multi-Home Across Mediators** (*O*₅, *B*′ = *M*₁ ∨ *M*₂): Factors individual mediator out of core | **Exercise Outside Option** (*B*′ = *M* ∨ *E*(*B*)): Frees *B* from major complex (or dissolves triad to Φ = 0 if *A* also exits) | **Partner Directly with *A*** (*B*′ = *M* ∨ *A*): Eliminates mediator bottleneck via bilateral contract | +| Focal Actor (Row) | Strategic Lever 1: Commit vs. Convey (Mediator Rule *M*′) | Strategic Lever 2: Pool Counterparts via `OR` (∨) | Strategic Lever 3: Add Outside Option (*E*ᵢ \= 1\) | Strategic Lever 4: Build Direct Counterpart Tie (*A* ↔ *B*) | +| :---- | :---- | :---- | :---- | :---- | +| **Mediator / Platform (*M*)** | **Switch Convey → Joint Commit** (*M*′ \= *A* ∧ *B*): Creates `BOTTLENECK` triad (Φ: 0.0 → 2.0, core {*A*, *M*, *B*}) | **Pool Replaceable Side *A*** (*M*′ \= (*A*₁ ∨ *A*₂) ∧ *B*): Expels *A*ᵢ from core; leaves {M, B} as the major complex while the system scores Φ \= 0.000 (dyadic) | **Block Counterpart Exit** (*E*(*A*) \= *E*(*B*) \= 0): Preserves full 3-party lock-in across all 60/60 random trials | **Prohibit Off-Platform Ties** (anti-disintermediation): Prevents bypass of *M* | +| **Party *A* (e.g., Worker / Driver)** | **Treat Prompt as Advisory** (*A*′ \= self or convey): Dissolves `BOTTLENECK` to Φ \= 0.0 if *M* follows *A* | **Form Worker Coalition / Union**: Restores collective input parity against one-sided pooling (worker\_union\_scale, V2 \#31, UNION\_MIRRORS\_COAL: a union scales like a counterpart coalition) | **Secure Outside Option** (*A*′ \= *M* ∨ *E*(*A*)): Frees *A* from major complex; shifts core to {*M*, *B*} (`CAPTURE` on *B* only) | **Establish Direct Tie to *B*** (A′ \= M ∨ B): Bypasses *M*, shifting core to {*A*, *B*} (Φ \= 0.830, `BYPASSED`) | +| **Party *B* (e.g., Client / Rider)** | **Require Joint Confirmation** (*M*′ \= *A* ∧ *B*): Binds *B* into mediated clearinghouse if no exit exists | **Multi-Home Across Mediators** (B′ \= *M*₁ ∨ *M*₂) (rival\_platforms, V2 \#32): \[DRAFTED by Claude\] RIVAL\_ENCODING, an equal-Φ rivalry in which each reachable state selects one mediator triad with B; competing mediators do not factor out | **Exercise Outside Option** (*B*′ \= *M* ∨ *E*(*B*)): Frees *B* from major complex (if A also exits, M is BYPASSED and {A, B} stay bound at Φ \= 0.830) | **Partner Directly with *A*** (*B*′ \= *M* ∨ *A*): Eliminates mediator bottleneck via bilateral contract | -## Addendum Section A.4. Extended Technical Risk Audits and Boundary Protocols +## Addendum Section A.4. Quantitative Boundary Audits, Imputation Controls, and Scaling Benchmarks -Because our laboratory commits pre-registered hypotheses before running experiments and keeps refuted predictions in CI, we can state the exact boundary conditions and risks of our approach: +We state the exact boundary conditions and risks of our approach: -1. **Encoding Sensitivity on Contested Qualitative Evidence:** Because an evidence-constrained adversary can flip a single-encoding verdict on 101 of 101 contested accounts, any pipeline that outputs a single LLM encoding would create false precision. We mitigate this by forbidding single-encoding claims: `spread.py` always reports the full verdict spread across all verbatim-grounded encodings and identifies the exact empirical rule that settles the disagreement. -2. **Structural Irreducibility (Φ > 0) Does Not Mean Superior Task Performance:** Our own pre-registered multi-agent reinforcement learning (MARL) falsifications refuted the hypothesis that Φ(MIP) > 0 predicts task performance or faster learning (yielded near-chance rank-AUC of **0.485–0.555** across tabular and neural policies). High Φ(MIP) measures **causal non-factorability and lock-in**, which can reflect an inefficient `BOTTLENECK` or asymmetric `CAPTURE` rather than normative efficiency. Our empirical hypotheses therefore test structural lock-in, bypass contingency, and oversight exclusion—never equating Φ with welfare or performance. -3. **Unobserved Parties and Off-Channel Interactions:** Field records can miss off-platform ties. While generic network priors can restore cheap mutual-information screens (AUC 0.944), our stress tests under **exact Φ(MIP)** show that when a party is hidden, ring-prior imputation drops to AUC **0.806** (and omission to **0.750**). Imputation cannot substitute for observing all interacting parties; accordingly, `protocol/` enforces explicit node-completeness and off-channel checks before computing exact Φ. -4. **Combinatorial Scale and Solver Preset Pinning:** Exact IIT 4.0 MIP evaluation scales to roughly *n* = 10 binary nodes; we therefore bound analysis to local governance nuclei of 3 to 5 interacting parties. We also pin our solver to IIT 4.0's 2023 formulation (`b78d0e342`), as upstream PyPhi 2.0's `iit4_2026` preset returns φₛ = 0 on deterministic systems at zero noise (ε = 0). -5. **Ethics and Dual-Use Symmetry:** All verdicts evaluate institutional rule architectures rather than individuals, and fieldwork proceeds under IRB oversight. The strategic lever matrix (Table 4) is symmetric: the same calculation that reveals how a platform achieves `CAPTURE` reveals to workers and regulators which outside option or coalition dissolves it. +1. **Encoding Sensitivity on Contested Qualitative Evidence:** Because an evidence-constrained adversary can flip a single-encoding verdict on 101 of 101 contested accounts, any pipeline that outputs a single LLM encoding would create false precision. We mitigate this by forbidding single-encoding claims: spread.py always reports the full verdict spread across all verbatim-grounded encodings and identifies the exact empirical rule that settles the disagreement. +2. **Structural Irreducibility (Φ \> 0\) Does Not Mean Superior Task Performance:** Our own falsifications on tabular and small-network MARL proxies, with hypotheses fixed before computing, refuted the hypothesis that Φ(MIP) \> 0 predicts task performance or faster learning (yielded near-chance rank-AUC of 0.485–0.555 across tabular and neural policies). High Φ(MIP) measures **causal non-factorability and lock-in**, which can reflect an inefficient BOTTLENECK or asymmetric CAPTURE rather than normative efficiency. Our empirical hypotheses therefore test structural lock-in, bypass contingency, and oversight exclusion—never equating Φ with welfare or performance. +3. **Unobserved Parties and Off-Channel Interactions:** Field records can miss off-platform ties. While generic network priors can restore cheap mutual-information screens (AUC 0.944), our stress tests under exact Φ(MIP) show that when a party is hidden, ring-prior imputation drops to AUC 0.806 (and omission to 0.750). Imputation cannot substitute for observing all interacting parties; accordingly, protocol/ enforces explicit node-completeness and off-channel checks before computing exact Φ. +4. **Combinatorial Scale and Solver Preset Pinning:** Exact IIT 4.0 MIP evaluation scales to roughly n \= 10 binary nodes; we therefore bound analysis to local governance nuclei of 3 to 5 interacting parties. We also pin our solver to IIT 4.0's 2023 formulation (b78d0e342), as upstream PyPhi 2.0's iit4\_2026 preset returns φₛ \= 0 on deterministic systems at zero noise (ε \= 0). +5. **Ethics and Dual-Use Symmetry:** All verdicts evaluate institutional rule architectures rather than individuals, and fieldwork proceeds under IRB oversight. The strategic lever matrix (Table 4\) is symmetric: the same calculation that reveals how a platform achieves CAPTURE reveals to workers and regulators which outside option or coalition dissolves it. -## Addendum Section A.5. Extended Theoretical Implications for Interdependence and Governance +## Addendum Section A.5. Extended Theoretical Implications for Interdependence and Oversight If successful, this work changes organizational research in three ways: -* **From Metaphor to Falsifiable Structural Measurement:** Claims that a platform, clearinghouse, or AI agent creates an "irreducible triad" become computed, replicable, and contestable. Studies publish explicit rule tables tied to verbatim evidence, and any reader can rerun PyPhi under a rival reading to see whether the verdict holds or flips. -* **Auditing Human-in-the-Loop Governance and Classic Typologies:** Classic interdependence typologies can be tested against an exact partition standard—revealing, for example, that Thompson's (1967) sequential and reciprocal interdependence share identical triadic integration (Φ = 2.0)—and organizational AI deployments can be audited for "Potemkin" oversight where human reviewers are structurally excluded from the Φ > 0 causal complex (Rudin, 2019). +* **From Metaphor to Falsifiable Structural Measurement:** Claims that a platform, clearinghouse, or AI agent creates an "irreducible triad" become computed, replicable, and contestable. Studies publish explicit rule tables tied to verbatim evidence, and any reader can rerun PyPhi under a rival reading to see whether the verdict holds or flips. +* **Auditing Human-in-the-Loop Governance and Classic Typologies:** Classic interdependence typologies can be tested against an exact partition standard—revealing, for example, that Thompson's (1967) sequential and reciprocal interdependence share identical triadic integration (Φ \= 2.0) on canonical encodings, although alternate encodings flip the verdict (PARTIAL\_ALIGNMENT, alignment 0.429)—and organizational AI deployments can be audited for "Potemkin" oversight where human reviewers are structurally excluded from the Φ \> 0 causal complex (Parasuraman & Riley, 1997; Lebovitz, Lifshitz-Assaf, & Levina, 2022). * **A Formal Calculus of Coordinative Strategy:** Answering Daft and Lewin (1990), combining adversarial AI reading with exact partition math equips organizational scholars with a rigorous calculus of how commitment rules, pooling, and outside options govern power in algorithmic organizations. # References -* Albantakis, L., Barbosa, L., Findlay, G., Grasso, M., Haun, A. M., Marshall, W., Mayner, W. G. P., Zaeemzadeh, A., Boly, M., Juel, B. E., Sasai, S., Fujii, K., David, I., Hendren, J., True, J. P., & Tononi, G. (2023). Integrated information theory (IIT) 4.0: Formulating the properties of phenomenal existence in physical systems. *PLoS Computational Biology*, 19(10), e1011465. -* Anthony, C., Bechky, B. A., & Fayard, A.-L. (2023). "Collaborating" with AI: Taking a system view to explore the future of work. *Organization Science*, 34(5), 1672–1694. -* Burch, R. W. (1991). *A Peircean Reduction Thesis: The Foundations of Topological Logic*. Texas Tech University Press. -* Burt, R. S. (1992). *Structural Holes: The Social Structure of Competition*. Harvard University Press. -* Cameron, L. D. (2024). The making of crystal-clear calls: Algorithmic management and the standardization of service work. *Administrative Science Quarterly*, 69(1), 1–42. -* Caplow, T. (1956). A theory of coalitions in the triad. *American Sociological Review*, 21(4), 489–493. -* Coleman, J. S. (1988). Social capital in the creation of human capital. *American Journal of Sociology*, 94(Suppl.), S95–S120. -* Curchod, C., Patriotta, G., Cohen, L., & Neysen, N. (2020). Working for an algorithm: Power asymmetries and agency in online work settings. *Administrative Science Quarterly*, 65(3), 644–676. -* Daft, R. L., & Lewin, A. Y. (1990). Can organization studies begin to break out of the normal science straitjacket? An editorial essay. *Organization Science*, 1(1), 1–9. -* Gartenberg, C., Hasan, S., Murray, A., & Pierce, L. (2026). More versus better: Artificial intelligence, incentives, and the emerging crisis in peer review. *Organization Science*, 37(3), 795–812. -* Girotra, K., Terwiesch, C., & Ulrich, K. T. (2010). Idea generation and the quality of the best idea. *Management Science*, 56(4), 591–605. -* Granovetter, M. S. (1973). The strength of weak ties. *American Journal of Sociology*, 78(6), 1360–1380. -* Hereth Correia, J., & Pöschel, R. (2004). The power of Peircean algebraic logic. In *Conceptual Structures at Work: 12th International Conference on Conceptual Structures, ICCS 2004* (LNCS Vol. 3127, pp. 337–350). Springer. -* Hereth Correia, J., & Pöschel, R. (2006). The teridentity and Peircean algebraic logic. In *Conceptual Structures: Inspiration and Application, ICCS 2006* (LNAI Vol. 4068, pp. 229–246). Springer. -* Kellogg, K. C., Valentine, M. A., & Christin, A. (2020). Algorithms at work: The new contested terrain of control. *Academy of Management Annals*, 14(1), 366–410. -* Koshkin, S. (2024). Logical reduction of relations: From relational databases to Peirce's reduction thesis. *Logic Journal of the IGPL*, 32(5), 779–813. -* Koshkin, S. (2025). Logical reduction of finite relations and granular computing. *International Journal of Approximate Reasoning*, 186, 109523. -* March, J. G. (1991). Exploration and exploitation in organizational learning. *Organization Science*, 2(1), 71–87. -* Mayner, W. G. P., Marshall, W., Albantakis, L., Findlay, G., Marchman, R., & Tononi, G. (2018). PyPhi: A toolbox for integrated information theory. *PLoS Computational Biology*, 14(7), e1006343. -* Mediano, P. A. M., Rosas, F. E., Luppi, A. I., Carhart-Harris, R. L., Bor, D., Seth, A. K., & Barrett, A. B. (2025). Toward an extended taxonomy of information dynamics via Integrated Information Decomposition. *Proceedings of the National Academy of Sciences*, 122(39), e2423297122. -* Obstfeld, D. (2005). Social networks, the *tertius iungens* orientation, and involvement in innovation. *Administrative Science Quarterly*, 50(1), 100–130. -* Orlikowski, W. J., & Scott, S. V. (2008). Sociomateriality: Challenging the separation of technology, work and organization. *Academy of Management Annals*, 2(1), 433–474. -* Ostrom, E. (1990). *Governing the Commons: The Evolution of Institutions for Collective Action*. Cambridge University Press. -* Peirce, C. S. (1933). The logic of relatives (1897). In C. Hartshorne & P. Weiss (Eds.), *Collected Papers of Charles Sanders Peirce* (Vol. 3, §§3.456–3.552). Harvard University Press. -* Quine, W. V. O. (1954). Reduction to a dyadic predicate. *Journal of Symbolic Logic*, 19(3), 180–182. -* Rahman, H. A. (2021). The invisible cage: Workers' reactivity to opaque algorithmic evaluations. *Administrative Science Quarterly*, 66(4), 945–988. -* Rudin, C. (2019). Stop explaining black box machine learning models for high stakes decisions and use interpretable models instead. *Nature Machine Intelligence*, 1(5), 206–215. -* Simmel, G. (1950). Quantitative aspects of the group (1902). In K. H. Wolff (Trans. & Ed.), *The Sociology of Georg Simmel* (pp. 87–177). Free Press. -* Thompson, J. D. (1967). *Organizations in Action: Social Science Bases of Administrative Theory*. McGraw-Hill. -* Wageman, R. (1995). Interdependence and group effectiveness. *Administrative Science Quarterly*, 40(1), 145–180. +* Albantakis, L., Barbosa, L., Findlay, G., Grasso, M., Haun, A. M., Marshall, W., Mayner, W. G. P., Zaeemzadeh, A., Boly, M., Juel, B. E., Sasai, S., Fujii, K., David, I., Hendren, J., Lang, J. P., & Tononi, G. (2023). Integrated information theory (IIT) 4.0: Formulating the properties of phenomenal existence in physical terms. *PLoS Computational Biology*, 19(10), e1011465. +* Anthony, C., Bechky, B. A., & Fayard, A.-L. (2023). "Collaborating" with AI: Taking a system view to explore the future of work. *Organization Science*, 34(5), 1672–1694. +* Burch, R. W. (1991). *A Peircean Reduction Thesis: The Foundations of Topological Logic*. Texas Tech University Press. +* Burt, R. S. (1992). *Structural Holes: The Social Structure of Competition*. Harvard University Press. +* Cameron, L. D. (2024). The making of the “good bad” job: How algorithmic management manufactures consent through constant and confined choices. *Administrative Science Quarterly*, 69(2), 458–514. +* Caplow, T. (1956). A theory of coalitions in the triad. *American Sociological Review*, 21(4), 489–493. +* Coleman, J. S. (1988). Social capital in the creation of human capital. *American Journal of Sociology*, 94(Suppl.), S95–S120. +* Curchod, C., Patriotta, G., Cohen, L., & Neysen, N. (2020). Working for an algorithm: Power asymmetries and agency in online work settings. *Administrative Science Quarterly*, 65(3), 644–676. +* Daft, R. L., & Lewin, A. Y. (1990). Can organization studies begin to break out of the normal science straitjacket? An editorial essay. *Organization Science*, 1(1), 1–9. +* Einav, L., Farronato, C., & Levin, J. (2016). Peer-to-peer markets. *Annual Review of Economics*, 8, 615–635. +* Gartenberg, C., Hasan, S., Murray, A., & Pierce, L. (2026). More versus better: Artificial intelligence, incentives, and the emerging crisis in peer review. *Organization Science*, 37(3), 795–812. +* Girotra, K., Terwiesch, C., & Ulrich, K. T. (2010). Idea generation and the quality of the best idea. *Management Science*, 56(4), 591–605. +* Granovetter, M. S. (1973). The strength of weak ties. *American Journal of Sociology*, 78(6), 1360–1380. +* Hall, J. V., & Krueger, A. B. (2018). An analysis of the labor market for Uber's driver-partners in the United States. *ILR Review*, 71(3), 705–732. +* Hereth Correia, J., & Pöschel, R. (2004). The power of Peircean algebraic logic (PAL). In *Conceptual Structures at Work: 12th International Conference on Conceptual Structures, ICCS 2004* (LNCS Vol. 3127, pp. 337–351). Springer. +* Hereth Correia, J., & Pöschel, R. (2006). The teridentity and Peircean algebraic logic. In *Conceptual Structures: Inspiration and Application, ICCS 2006* (LNAI Vol. 4068, pp. 229–246). Springer. +* Kellogg, K. C., Valentine, M. A., & Christin, A. (2020). Algorithms at work: The new contested terrain of control. *Academy of Management Annals*, 14(1), 366–410. +* Koshkin, S. (2024a). Logical reduction of relations: From relational databases to Peirce's reduction thesis. *Logic Journal of the IGPL*, 32(5), 779–809. +* Koshkin, S. (2024b). Functional completeness and primitive positive decomposition of relations on finite domains. *Logic Journal of the IGPL*. Advance online publication. https\://doi.org/10.1093/jigpal/jzae077 +* Lebovitz, S., Lifshitz-Assaf, H., & Levina, N. (2022). To engage or not to engage with AI for critical judgments: How professionals deal with opacity when using AI for medical diagnosis. *Organization Science*, 33(1), 126–148. +* March, J. G. (1991). Exploration and exploitation in organizational learning. *Organization Science*, 2(1), 71–87. +* Mayner, W. G. P., Marshall, W., Albantakis, L., Findlay, G., Marchman, R., & Tononi, G. (2018). PyPhi: A toolbox for integrated information theory. *PLoS Computational Biology*, 14(7), e1006343. +* Mediano, P. A. M., Rosas, F. E., Luppi, A. I., Carhart-Harris, R. L., Bor, D., Seth, A. K., & Barrett, A. B. (2025). Toward a unified taxonomy of information dynamics via Integrated Information Decomposition. *Proceedings of the National Academy of Sciences*, 122(39), e2423297122. +* Obstfeld, D. (2005). Social networks, the *tertius iungens* orientation, and involvement in innovation. *Administrative Science Quarterly*, 50(1), 100–130. +* Orlikowski, W. J., & Scott, S. V. (2008). Sociomateriality: Challenging the separation of technology, work and organization. *Academy of Management Annals*, 2(1), 433–474. +* Ostrom, E. (1990). *Governing the Commons: The Evolution of Institutions for Collective Action*. Cambridge University Press. +* Parasuraman, R., & Riley, V. (1997). Humans and automation: Use, misuse, disuse, abuse. *Human Factors*, 39(2), 230–253. +* Peirce, C. S. (1933). The logic of relatives (1897). In C. Hartshorne & P. Weiss (Eds.), *Collected Papers of Charles Sanders Peirce* (Vol. 3, §§3.456–3.552). Harvard University Press. +* Puranam, P., Raveendran, M., & Knudsen, T. (2012). Organization design: The epistemic interdependence perspective. *Academy of Management Review,* 37(3), 419–440. +* Quine, W. V. O. (1954). Reduction to a dyadic predicate. *Journal of Symbolic Logic*, 19(3), 180–182. +* Rahman, H. A. (2021). The invisible cage: Workers' reactivity to opaque algorithmic evaluations. *Administrative Science Quarterly*, 66(4), 945–988. +* Raveendran, M., Silvestri, L., & Gulati, R. (2020). The role of interdependence in the micro-foundations of organization design: Task, goal, and knowledge interdependence. *Academy of Management Annals,* 14(2), 828–868. +* Rosenblat, A., & Stark, L. (2016). Algorithmic labor and information asymmetries: A case study of Uber's drivers. *International Journal of Communication*, 10, 3758–3784. +* Schor, J. B., Attwood-Charles, W., Cansoy, M., Ladegaard, I., & Wengronowitz, R. (2020). Dependence and precarity in the platform economy. *Theory and Society*, 49(5–6), 833–861. +* Shestakofsky, B. (2017). Working algorithms: Software automation and the future of work. *Work and Occupations*, 44(4), 376–423. +* Simmel, G. (1902/1950). Quantitative aspects of the group (1902/1908). In K. H. Wolff (Trans. & Ed.), *The Sociology of Georg Simmel* (pp. 87–177). Free Press. +* Skitka, L. J., Mosier, K. L., & Burdick, M. (1999). Does automation bias decision-making? *International Journal of Human-Computer Studies*, 51(5), 991–1006. +* Stark, D., & Pais, I. (2020). Algorithmic management in the platform economy. *Sociologica*, 14(3), 47–72. +* Sundararajan, A. (2016). *The Sharing Economy: The End of Employment and the Rise of Crowd-Based Capitalism*. MIT Press. +* Thompson, J. D. (1967). *Organizations in Action: Social Science Bases of Administrative Theory*. McGraw-Hill. +* Tononi, G. (2004). An information integration theory of consciousness. *BMC Neuroscience*, 5, 42\. +* Vallas, S., & Schor, J. B. (2020). What do platforms do? Understanding the gig economy. *Annual Review of Sociology*, 46, 273–294. +* Victor, B., & Blackburn, R. S. (1987). Interdependence: An alternative conceptualization. *Academy of Management Review,* 12(3), 486–498. +* Wageman, R. (1995). Interdependence and group effectiveness. *Administrative Science Quarterly*, 40(1), 145–180. * Williams, P. L., & Beer, R. D. (2010). Nonnegative decomposition of multivariate information. *arXiv:1004.2515*. -# Technical Appendix (Stage 1 Supplement) +# Addendum Appendices A–D: Formal Proofs, Engine Specifications, and CI Verdicts ## Appendix A: Algebraic Irreducibility, IIT 4.0 Wholeness, and Proxy Benchmarks ### A.1. Peircean Algebraic Logic (PAL), Bond Algebra, and Quine's Pairing Translation -Quine (1954, p. 180) translated any interpreted *n*-ary theory into a single dyadic predicate letter *F* by encoding tuples via iterated Kuratowski ordered pairs {{*x*}, {*x*, *y*}} over a universe closed under pairing. In standard primitive-positive relational clones [F]ₚₚ, variable identification is unrestricted, so the ternary diagonal Δ₃ = {(*x*, *x*, *x*) ∈ *X*³ : *x* ∈ *X*} is trivially generated from binary equality via (*x* = *y*) ∧ (*y* = *z*), and on finite domains with |*X*| ≥ 3 every *n*-ary relation reduces to binary relations under primitive-positive operations, whereas on Boolean domains ¬*I*₃ is primitive-positive irreducible to binaries (Koshkin, 2025, Theorems 2–4; see Koshkin, 2024 for infinite domains and projoins). In **Peircean Algebraic Logic** (introduced with a restricted proof in Burch, 1991), removing primitive teridentity (PAL ∖ {id₃}) caps every connected set of argument places generated from unary and binary relations at size ≤ 2, so id₃ cannot be generated over any fixed domain |*X*| ≥ 2 (Hereth Correia & Pöschel, 2004; Hereth Correia & Pöschel, 2006, Lemma 1 and Theorem 2). Likewise, in tabular **bond algebra** where composition quantifies out shared places, teridentity is bond-irreducible on any domain with |*X*| ≥ 2 (Koshkin, 2025, Theorem 6). +Quine (1954, p. 180\) translated any interpreted *n*\-ary theory into a single dyadic predicate letter *F* by encoding tuples via iterated Kuratowski ordered pairs {{*x*}, {*x*, *y*}} over a universe closed under pairing. In standard primitive-positive relational clones \[F\]ₚₚ, variable identification is unrestricted, so the ternary diagonal Δ₃ \= {(*x*, *x*, *x*) ∈ *X*³ : *x* ∈ *X*} is trivially generated from binary equality via (*x* \= *y*) ∧ (*y* \= *z*), and on finite domains with \|*X*\| ≥ 3 every *n*\-ary relation reduces to binary relations under primitive-positive operations, whereas on Boolean domains ¬*I*₃ is primitive-positive irreducible to binaries (Koshkin, 2024b, Theorems 2–4; see Koshkin, 2024a for infinite domains and for natural joins and projections). In **Peircean Algebraic Logic** (introduced by Burch, 1991, who proved the reduction thesis under a restriction on juxtaposition that Hereth Correia & Pöschel, 2004, 2006, removed), removing primitive teridentity (PAL ∖ {id₃}) caps every connected set of argument places generated from unary and binary relations at size ≤ 2, so id₃ cannot be generated over any fixed domain \|*X*\| ≥ 2 (Hereth Correia & Pöschel, 2004; Hereth Correia & Pöschel, 2006, Lemma 1 and Theorem 2). Likewise, in tabular **bond algebra** where composition quantifies out shared places, teridentity is bond-irreducible on any domain with \|*X*\| ≥ 2 (Koshkin, 2024b, Theorem 6). ### A.2. What the Classifier Computes vs. What the Peirce Probes Test -In `irreducibility/core.py` (and `org_frontier/classifier/`), a structure is classified as `triadic` iff system integrated information over the Minimum Information Partition (Albantakis et al., 2023) satisfies Φ(MIP) > 10⁻⁹ in at least one reachable state, and `pyphi.new_big_phi.maximal_complex` identifies the major complex (which may bind all three parties {*D*, *P*, *R*} under `BOTTLENECK`/`ENRICHER`, two parties {*D*, *P*} or {*P*, *R*} under `CAPTURE`, or {*D*, *R*} under `BYPASSED`). Separately, our Peirce probes (`org_frontier/thinkers/peirce/probe_peirce_joint_determination.py`; CI checks `thinkers-peirce-h1-irreducibility`, `thinkers-peirce-jd`, and `thinkers-peirce-jd-full`) test how systemic wholeness (Φ(MIP) > 0) relates to two-input joint determination (a node whose rule depends non-trivially on two counterparts), showing that the two properties cross in both directions: +In `irreducibility/core.py` (and `org_frontier/classifier/`), a structure is classified as `triadic` iff system integrated information over the Minimum Information Partition (Albantakis et al., 2023\) satisfies Φ(MIP) \> 10⁻⁹ in at least one reachable state, and `pyphi.new_big_phi.maximal_complex` identifies the major complex (which may bind all three parties {*D*, *P*, *R*} under `BOTTLENECK`/`ENRICHER`, two parties {*D*, *P*} or {*P*, *R*} under `CAPTURE`, or {*D*, *R*} under `BYPASSED`). Separately, our Peirce probes (`org_frontier/thinkers/peirce/probe_peirce_joint_determination.py`; CI checks `thinkers-peirce-h1-irreducibility`, `thinkers-peirce-jd`, and `thinkers-peirce-jd-full`) test how systemic wholeness (Φ(MIP) \> 0\) relates to two-input joint determination (a node whose rule depends non-trivially on two counterparts), showing that the two properties cross in both directions: -* **Wholeness without Joint Determination:** Across all 89 four-node one-input copy wirings, 66 reach genuine effect-side adicity 3 and 12 reach adicity 4 (while cause-side adicity never exceeds 2); among the 11 unbranched wirings (max adicity 2), 8 of 89 have Φ(MIP) > 0 (and the 3-node copy ring *A*′ = *C*, *B*′ = *A*, *C*′ = *B* scores Φ(MIP) = 2.0 with core {*A*, *B*, *C*}). Under `core.py`, these cyclic copy rings read as `triadic` wholes even though no rule has two inputs. -* **Joint Determination without Wholeness:** Across the 30 two-input mediated forms in `thinkers-peirce-jd-full`, 5 exhibit joint determination inside a whole, 11 have genuine two-input joint determination yet factor at Φ(MIP) = 0, and 1 has no joint determination (and in `thinkers-peirce-jd`, the 3-voter majority triad at state (1, 1, 1) scores Φ(MIP) = 0 with 4 partition ties). That is why Step 6 (`regime.py`) combines Φ(MIP), the major complex, and the bypass reduction rather than equating Φ(MIP) > 0 with a single algebraic property. +* **Wholeness without Joint Determination:** Across all 89 four-node one-input copy wirings, 66 reach genuine effect-side adicity 3 and 12 reach adicity 4 (while cause-side adicity never exceeds 2); among the 11 unbranched wirings (max adicity 2), 8 of 89 have Φ(MIP) \> 0 (and the 3-node copy ring *A*′ \= *C*, *B*′ \= *A*, *C*′ \= *B* scores Φ(MIP) \= 2.0 with core {*A*, *B*, *C*}). Under `core.py`, these cyclic copy rings read as `triadic` wholes even though no rule has two inputs. +* **Joint Determination without Wholeness:** Across the 30 two-input mediated forms in `thinkers-peirce-jd-full`, 5 exhibit joint determination inside a whole, 11 have genuine two-input joint determination yet factor at Φ(MIP) \= 0, and 1 has no joint determination (and in `thinkers-peirce-jd`, the 3-voter majority triad at state (1, 1, 1\) scores Φ(MIP) \= 0 with 4 partition ties). That is why Step 6 (`regime.py`) combines Φ(MIP), the major complex, and the bypass reduction rather than equating Φ(MIP) \> 0 with a single algebraic property. ### A.3. Why Time-Series Information Decomposition (PID / ΦID) Cannot Replace Exact Φ(MIP) -Partial Information Decomposition (Williams & Beer, 2010) and Integrated Information Decomposition (ΦID; Mediano et al., 2025) decompose multivariate time-series information, and the ΦID-based measure Φᵣ corrects whole-minus-sum integrated information Φ(WMS) for double-counting redundancy. We tested these proxies in two separate benchmarks: +Partial Information Decomposition (Williams & Beer, 2010\) and Integrated Information Decomposition (ΦID; Mediano et al., 2025\) decompose multivariate time-series information, and the ΦID-based measure Φᵣ corrects whole-minus-sum integrated information Φ(WMS) for double-counting redundancy. We tested these proxies in two separate benchmarks: -* In our prototype's `studies/proxies` check across the 256 three-party structures, simulated-trajectory ΦID Φᵣ and whole-minus-sum Φ(WMS) separate dyadic from triadic structures at rank-AUC **0.563** and **0.629**. -* In `foundations/phiid_vs_phi/FINDINGS.md`, exact-TPM Φ(WMS) correlates with exact Φ(MIP) at Spearman ρ = **0.283** (AUC = **0.669**), while finite time-series ΦID Φᵣ (CCS) correlates at Spearman ρ = **0.124** (AUC = **0.560**). +* In our prototype's `proxies check (studies/proxy_run.py, studies/proxy_bridge.py, studies/phiid_measure.py) across the 256 strict-mediation census forms,` simulated-trajectory ΦID Φᵣ and whole-minus-sum Φ(WMS) separate dyadic from triadic structures at rank-AUC **0.563** and **0.629**. +* In `foundations/phiid_vs_phi/FINDINGS.md`, exact-TPM Φ(WMS) correlates with exact Φ(MIP) at Spearman ρ \= **0.283** (AUC \= **0.669**), while finite time-series ΦID Φᵣ (CCS) correlates at Spearman ρ \= **0.124** (AUC \= **0.560**). -Furthermore, our canonical Φ(MIP) = 2.0 strict-mediation control (*D*′ = *P*, *P*′ = *D* ∧ *R*, *R*′ = *P*) uses a conjunctive `AND` (∧) rule, whereas pure `XOR` (⊕) parity triads exhibit the **parity blindspot** (`#4`, `BLINDSPOT_SURVIVES_RADIX`), scoring Φ = 0.5 at *n* = 3 and decaying as Φ = 2²⁻ⁿ through *n* = 10. +Furthermore, our canonical Φ(MIP) \= 2.0 strict-mediation control (*D*′ \= *P*, *P*′ \= *D* ∧ *R*, *R*′ \= *P*) uses a conjunctive `AND` (∧) rule, whereas pure `XOR` (⊕) parity triads exhibit the **parity blindspot**, scoring Φ \= 0.5 at n \= 3 and decaying as Φ \= 2²⁻ⁿ through n \= 10 (parity\_law\_n\_gt6 and parity\_law\_n\_gt8: LAW\_HOLDS\_NGT6, LAW\_HOLDS\_NGT8), while balanced commits S′ \= (W \+ C) mod k keep a flat Φ ≈ 0.5 band at k \= 2, 3, 4 (parity\_radix\_blindspot, V2 \#4: BLINDSPOT\_SURVIVES\_RADIX). ## Appendix B: The Six-Step Pipeline and Multi-Valued Engine Architecture ### B.1. The Six-Step AI-and-PyPhi Pipeline (`irreducibility/` & `encode/`) -* **Step 1 — Bound and Name (`protocol/`):** Fixes one recurring organizational act, names the *n* parties as uppercase identifiers, and defines binary participation states (0/1). -* **Step 2 — Encode via Drafter, Adversary, and Gate (`encode/SCHEMA.json`, `PROMPT_drafter.md`, `PROMPT_adversary.md`, `irreducibility/encode_check.py`):** Rules are deterministic Boolean expressions over party labels (`and` [∧], `or` [∨], `not` [¬], `xor` [⊕], `0`, `1`); `rules.py` rejects any other syntax so encodings cannot execute code. The Drafter writes rival and design encodings with verbatim source quotes, mediator alternatives (commit, convey, store), and fixed predictions; the Adversary tests commit-vs-convey, pooling via `or` (∨), and outside options; `encode_check.py` rejects any missing rule, non-verbatim quote, missing alternative, or missing prediction without computing Φ. -* **Step 3 — Compute (`irreducibility/core.py`):** `tpm_from_rules` builds the 2ⁿ × *n* little-endian state-by-node TPM; `cm_from_rules` builds the connectivity matrix via flip test; `pyphi.new_big_phi.sia` and `maximal_complex` evaluate Φ(MIP) and the major complex across reachable states (pinned to `wmayner/pyphi` commit `b78d0e342` on Python 3.10–3.12). -* **Step 4 — Validate First (`irreducibility/validate.py`):** Enforces the four mandatory controls (`irreducibility/controls.py`: factoring Φ = 0.000, irreducible Φ = 0.830, strict-mediation Φ = 2.000, and gig false-dyad Φ = 2.000; see Section 2.1 Table) before any script reports results. -* **Step 5 — Report the Spread (`irreducibility/spread.py`, `analyze.py`):** Computes verdict agreement, Φ gap, per-party rule agreement, and exact single-rule flips across rival encodings. -* **Step 6 — Read the Structure (`irreducibility/regime.py`, `contingency.py`):** Classifies the mediator via `classify_mediator` (`PASSIVE`, `CONDUIT`, `BOTTLENECK`, `CAPTURE`, `ENRICHER`, `BYPASSED`) and tests outside-option scenarios (*O*₁–*O*₅). Four worked examples and logged blind Claude Sonnet 5.5 runs are summarized in Table 5 below. - -| Worked Case / Logged AI Run (`examples/` & `encode/runs/`) | Organizational Setting & Parties | Encodings & Gate Status (`encode_check.py`) | Key Structural Verdict, Φ(MIP) Spread, and AI Prediction Audit | -| :--- | :--- | :--- | :--- | -| **Example 01: Gig Dispatch** (`examples/01_gig_dispatch/`) | Driver (*D*), Platform (*P*), Rider (*R*) + outside options (*O*₁–*O*₅) | 2 rival (*R*₁, *R*₂), 2 design (*D*₁, *D*₂), 5 exit (*O*₁–*O*₅); **PASS** | Platform manual *R*₁ = **Triadic `BOTTLENECK`** (Φ = 2.0, core {*D*, *P*, *R*}); Driver account *R*₂ = **Dyadic `CONDUIT`** (Φ = 0.0); single rule *P*′ decides | -| **Example 02: Insurance Claim** (`examples/02_insurance_claim/`) | Claimant (*C*), Intake Portal (*M*), Adjuster (*A*) | 2 rival readings + 4 underspecified designs in blind AI run | Human complete file passes; in blind AI run (`02_insurance_claim_drafter.json`), Drafter refused to invent 4 ungrounded rules and `encode_check.py` **REJECTED** (9 problems) | -| **Example 03: Code-Review Gate** (`examples/03_code_review_gate/`) | Author (*A*), CI / Merge Bot (*G*), Reviewer (*R*) | Branch-protection gate vs. rubber-stamp approval; **PASS** | Required review gate (*G*′ = *A* ∧ *R*) yields **Triadic `BOTTLENECK`** (Φ = 2.0, core {*A*, *G*, *R*}); rubber-stamp excludes *R* from major complex (`#39 HUMAN_COMMIT_READ`) | -| **Example 04: Dealer vs. Clearinghouse** (`examples/04_dealer_vs_clearinghouse/`) | Buyer (*B*), Intermediary (*M*), Seller (*S*) | Bilateral dealer relay vs. multilateral net clearinghouse; **PASS** | Sequential dealer inventory relay factors (**Dyadic**, Φ = 0.0); simultaneous net clearinghouse binds {*B*, *M*, *S*} (**Triadic**, Φ = 2.0) | -| **Logged Run 1: Drafter on 01** (`01_gig_dispatch_drafter.json`) | Blind Claude Sonnet 5.5 run on `SOURCE.md` only | 2 rival encodings with verbatim quotes; **PASS** (0 errors) | Reproduced both human rival encodings (*R*₁ Φ = 2.0; *R*₂ Φ = 0.0) and matched both pre-registered predictions | -| **Logged Run 2: Adversary on 01** (`01_gig_dispatch_adversary.json`) | Blind Claude Sonnet 5.5 adversarial search on `01` | Discovered Driver Pool (*D*₁) and Direct Tie (*D*₂); **PASS** | **PyPhi refuted both LLM predictions:** LLM predicted *D*₁ would stay 3-party triadic (actual: *D*ᵢ factored out, core {*P*, *R*}) and *D*₂ would factor (actual: triadic core {*D*, *R*}, *P* `BYPASSED`) | +* **Step 1 — Bound and Name (`protocol/`):** Fixes one recurring organizational act, names the *n* parties as uppercase identifiers, and defines binary participation states (0/1). +* **Step 2 — Encode via Drafter, Adversary, and Gate (`encode/SCHEMA.json`, `PROMPT_drafter.md`, `PROMPT_adversary.md`, `irreducibility/encode_check.py`):** Rules are deterministic Boolean expressions over party labels (`and` \[∧\], `or` \[∨\], `not` \[¬\], `xor` \[⊕\], `0`, `1`); `rules.py` rejects any other syntax so encodings cannot execute code. The Drafter writes rival and design encodings with verbatim source quotes, mediator alternatives (commit, convey, store), and fixed predictions; the Adversary tests commit-vs-convey, pooling via `or` (∨), and outside options; `encode_check.py` rejects any missing rule, non-verbatim quote, missing alternative, or missing prediction without computing Φ. +* **Step 3 — Compute (`irreducibility/core.py`):** `tpm_from_rules` builds the 2ⁿ × *n* little-endian state-by-node TPM; `cm_from_rules` builds the connectivity matrix via flip test; `pyphi.new_big_phi.sia` and `maximal_complex` evaluate Φ(MIP) and the major complex across reachable states (pinned to `wmayner/pyphi` commit `b78d0e342` on Python 3.10–3.12). +* **Step 4 — Validate First (`irreducibility/validate.py`):** Runs two controls (factoring Φ \= 0.000; irreducible Φ \= 0.830) and five reference forms (strict mediation Φ \= 2.000; chat dyad, dyadic gig model, and broken-liveness feedback, each Φ \= 0.000; gig false dyad Φ \= 2.000) before any script reports results; Table 2 shows the two controls and two of the five forms. +* **Step 5 — Report the Spread (`irreducibility/spread.py`, `analyze.py`):** Computes verdict agreement, Φ gap, per-party rule agreement, and exact single-rule flips across rival encodings. +* **Step 6 — Read the Structure (`irreducibility/regime.py`, `contingency.py`):** Reads the mediator's position with regime() in regime.py (REGIMES: dyadic, BYPASSED, CAPTURE, BOTTLENECK, ENRICHER, with lesion\_survives(); PASSIVE and CONDUIT are our glosses of dyadic), runs the bypass test with contingency\_test() and add\_bypass() in contingency.py (intrinsic, contingent, partial, or reducible), and takes the verdict from classify\_rules() in core.py; outside options are the O₁–O₅ design encodings in examples/01\_gig\_dispatch/ and the battery in studies/enricher\_regime.py. Four worked examples and logged blind Claude Sonnet 5.5 runs are summarized in Table 5 below. + +Table 5: Worked examples and logged AI runs in irreducibility-pipeline/ + +| Worked Case / Logged AI Run (`examples/` in irreducibility-pipeline/) | Organizational Setting & Parties | Encodings & Gate Status (`encode_check.py`) | Key Structural Verdict, Φ(MIP) Spread, and AI Prediction Audit | +| :---- | :---- | :---- | :---- | +| **Example 01: Gig Dispatch** (`examples/01_gig_dispatch/`) | Driver (*D*), Platform (*P*), Rider (*R*) (D₁, D₂ in rival encoding C) | 3 rival (A \= R₁, B \= R₂, C \= D₁) \+ 5 design (O₁–O₅, with O₅ \= D₂) \= 8 admissible encodings; **PASS** | Platform manual *R*₁ \= **Triadic `BOTTLENECK`** (Φ \= 2.0, core {*D*, *P*, *R*}); Driver account *R*₂ \= **Dyadic `CONDUIT`** (Φ \= 0.0); single rule P′ decides (A→B flip: P′ \= D ∧ R becomes P′ \= D) | +| **Example 02: Insurance Claim** (`examples/02_insurance_claim/`) | Claimant (*C*), auto-adjudication engine (E, mediator), human adjuster (A) | 5 design encodings, no rival pair (pipe, gated, loop, loop\_nolearn, frozen); PASS | pipe triadic Φ \= 2.000, {C, E, A}, BOTTLENECK (prediction held); gated Φ \= 0.415, {C, E}, CAPTURE (failed); loop Φ \= 1.000, {E, A}, CAPTURE (failed); loop\_nolearn Φ \= 2.000, {C, A}, BYPASSED (failed); frozen dyadic Φ \= 0.000 (held): 2 of 5 naive predictions held. Logged AI run (examples/02\_insurance\_claim/ai\_draft.json): the Drafter left 4 of 5 designs' rules unwritten and encode\_check.py REJECTED the file (9 problems in 5 encodings: 8 missing party rules, 1 missing mediator alternative) | +| **Example 03: Code-Review Gate** (`examples/03_code_review_gate/`) | Author (*A*), CI gate (G, mediator), Maintainer (M) | 2 rival encodings: gated (A′ \= G ∧ M, G′ \= A, M′ \= A ∧ G) vs. diff\_only (M′ \= A); **PASS** | \[DRAFTED by Claude\] Required review gate (gated): when maintainers wait for CI the gate is bypassed — the author and maintainer form the core at Φ \= 1.0 and the gate sits outside it; approving on the diff alone (diff\_only) brings the gate into a three-party core at Φ \= 2.0 as an enricher. Both naive predictions failed; the field-mock M4 reads the same (BYPASSED). | +| **Example 04: Dealer vs. Clearinghouse** (`examples/04_dealer_vs_clearinghouse/`) | Upstream party (U), Intermediary (I, mediator), Downstream party (V) | 2 encodings: dealer (U′ \= V, I′ \= U, V′ \= I; a ban on direct sales) vs. clearinghouse (I′ \= U ∧ V); **PASS** | Both triadic BOTTLENECK at Φ \= 2.000, core {U, I, V}; the contrast is contingency: dealer is contingent (opening the bypass loses Φ \= 2.000; core → {U, V}), clearinghouse is intrinsic (bypass loses 0.000; core → {U, I}) | +| **Logged Run 1: Drafter on 01** (examples/01\_gig\_dispatch/ai\_draft.json) | Blind Claude Sonnet 5.5 run on `prose.md` only | 2 rival encodings with verbatim quotes; **PASS** (0 errors) | Reproduced both human rival encodings (*R*₁ Φ \= 2.0; *R*₂ Φ \= 0.0) and matched both predictions fixed before computing | +| **Logged Run 2: Adversary on 01** (examples/01\_gig\_dispatch/ai\_draft\_plus\_adversary.json; raw output ai\_adversary\_raw.json) | Blind Claude Sonnet 5.5 adversarial search on `01` | 4 admissible encodings; added driver\_pool (D₁) and direct\_contact\_substitute (D₂); **PASS** | **PyPhi refuted both LLM predictions:** LLM predicted *D*₁ would stay 3-party triadic (actual: dyadic, Φ \= 0.000, major complex {P, R}) and *D*₂ would factor (actual: triadic core {D, R}, P BYPASSED, Φ \= 0.830) | ### B.2. Custom Multi-Valued IIT 4.0 Engine (`third_party/pyphi_iit4_mv`) & CI Gate -* **Milestone 1 (SBS `ExplicitTPM`) & Milestone 2 (Multi-Valued IIT 4.0 Solver):** Extends the binary-only `wmayner/pyphi` commit `b78d0e342` baseline to mixed-radix state spaces (*O*₁ × *O*₂ × … × *O*ₙ) without binary dummy-node inflation, yielding φₛ = 3.169925 (2 log₂ 3 bits) on its 2-node ternary control in `smoke_m2.py`—the same 2 log₂ 3 value that upstream PyPhi 2.0 (commit `134a8f31`) returns on the ternary conjunctive triad at (2, 2, 2) under `pyphi.iit4_2023` at ε = 0. -* **Continuous Integration Harness (`reproduce-the-numbers`):** Verifies all 542 automated checks in `ci/reproduce.json` across 127 studies in `org_frontier/studies/`, 135 probes, and 9 `foundations/` studies, alongside the 19 test gates and 17 reference results in `irreducibility-pipeline`. +* **Milestone 1 (SBS `ExplicitTPM`) & Milestone 2 (Multi-Valued IIT 4.0 Solver):** Extends the binary-only `wmayner/pyphi` commit `b78d0e342` baseline to mixed-radix state spaces (*O*₁ × *O*₂ × … × *O*ₙ) without binary dummy-node inflation, yielding φₛ \= 3.169925 (2 log₂ 3 bits) on its 2-node ternary control in `smoke_m2.py`—the same 2 log₂ 3 value that upstream PyPhi 2.0 (commit `134a8f31`) returns on the ternary conjunctive triad at (2, 2, 2\) under `pyphi.iit4_2023` at ε \= 0\. +* **Continuous Integration Harness (`reproduce-the-numbers`):** Verifies all 542 automated checks in `ci/reproduce.json` across 127 studies in `org_frontier/studies/`, 135 probes, and 9 `foundations/` studies, alongside the 19 test gates and 17 reference results in the irreducibility-pipeline/ directory of algorithmacy-lab (lab tag orgsci-stage1). ## Appendix C: Stage 2 Empirical Validation & Strategic Model Specifications -1. **Software Packaging:** `pip install irreducibility` CLI supporting Anthropic and local open-weight models, enforcing `encode_check.py` before computation, and exposing `pyphi_iit4_mv` for ternary/mixed-radix rules. -2. **Actor-Indexed Strategic Model (`studies/strategic_model/`):** A single strategic matrix (Section 3, Table 4) indexes the three parties as rows (Mediator *M*, Party *A*, Party *B*) and the rule edits as columns (commit vs. convey, pooling via `or` [∨], outside options *E*ᵢ, and direct counterpart ties *A* ↔ *B*), reporting exact ΔΦ(MIP) and major-complex transitions across all 256 three-party structures (56 dyadic, 132 cycle-supported, 68 mediated triads). +1. **Software Packaging:** `pip install irreducibility` CLI supporting Anthropic and local open-weight models, enforcing `encode_check.py` before computation, and exposing `pyphi_iit4_mv` for ternary/mixed-radix rules. +2. **Actor-Indexed Strategic Model (Stage 2 work; not yet in the repository):** A single strategic matrix (Section A.3, Table 4\) indexes the three parties as rows (Mediator *M*, Party *A*, Party *B*) and the rule edits as columns (commit vs. convey, pooling via `or` \[∨\], outside options *E*ᵢ, and direct counterpart ties *A* ↔ *B*), reporting exact ΔΦ(MIP) and major-complex transitions across the 256 strict-mediation three-party forms. \[DRAFTED by Claude\] Exhaustive enumeration of the 256 strict-mediation three-party forms (4 worker rules × 16 mediator rules × 4 counterpart rules) finds 24 irreducible and 232 factorable, with a mediator that reads both parties necessary but not sufficient (24/160 vs 0/96). 3. **Multi-Arm Empirical Validation:** Encodes 10–15 published platform and algorithmic-management cases from their own text (reporting all defensible encodings and the deciding empirical detail), fields the gig-dispatch interview packet (`protocol/`) and software code-review protocol (`org_frontier/field/`) once IRB approval is in hand, and pairs rule-level Φ(MIP) encodings with repository CRQA coupling metrics (`org_frontier/recurrence/`) and the psychometric algorithmacy scale (`org_frontier/survey/`). ## Appendix D: Summary of Completed Laboratory Arcs & Verified CI Verdicts +Table 6: Completed laboratory arcs and verified CI verdicts + | Research Arc | Study & Probe IDs in Repo | Core Organizational & Methodological Question | Verified CI Verdict(s) (`ci/reproduce.json`) | -| :--- | :--- | :--- | :--- | -| **Six-Step Pipeline, Adversarial Coding & Proxies** | `irreducibility-pipeline` (`v0.1-stage1`): `examples/01–04`, `adversarial_coding`, `proxies`, `strategic_model` | How do we translate qualitative text into exact IIT 4.0 tests without hiding encoding choices? | **17/17** reference results & **19/19** test gates pass; **101/101** adversarial flips; proxies rank-AUC **0.563** (Φᵣ) & **0.629** (Φ(WMS)); **60/60** exit trials retain non-exiting core. | -| **Multi-Valued IIT 4.0 & Graded Resolution** | V2 `#1–#4` (`ternary_conjunctive_mediator`, `graded_commitment_sweep`, `mixed_radix_asymmetric`, `multivalued_xor_blindspot`) | Does organizational irreducibility survive graded (*k* ≥ 3) and mixed-radix state spaces? | `TWO_CONDITION_STATE_DEPENDENT`, `SHARP_CLASS_GRADED_PATH` (*R*² = 0.992), `EXTRA_RESOLUTION_TO_PHI` (3 bits → 5.755 bits), `BLINDSPOT_SURVIVES_RADIX` (parity Φ = 2²⁻ⁿ). | -| **Classic Org Theory Bridges** | V2 `#43`, `#44`, `#46` (`thompson_verdict_bridge`, `wageman_ti_verdict`, `formal_informal_cut`) | Do classic interdependence typologies align with exact causal irreducibility? | `PARTIAL_ALIGNMENT` (Thompson pooled Φ = 0; sequential & reciprocal both Φ = 2.0), `WAGEMAN_PREDICTS_VERDICT`, `CUTS_ACROSS` (4/8 formal vs. shadow diverge). | -| **16-Thinker Triad Catalog** | CI checks `#001–#082` (`org_frontier/thinkers/`: Peirce, Simmel, Caplow, Burt, Granovetter, Coleman, Ostrom, Blau, etc.) | Which canonical sociological triad mechanisms are causally irreducible vs. factorable? | **82 automated probes** across **16 thinkers**; `thinkers-peirce-h1-irreducibility` (8/89 1-input wirings Φ > 0), `thinkers-peirce-jd-full` (11/30 2-input forms Φ = 0). | -| **Topology & Scaling Laws** | V3 `#1`, `#5`, `#10`; V4 `#9` (`dual_mediator_template_census`, `ring_of_hubs`, `parity_law_n_gt6`, `parity_law_n_gt8`) | Do modular organizational hubs or dual mediators fuse into macro-triads at scale? | `FACTORS_INTO_FIVE` (V3 `#1`), `FACTORS_NO_COMBINE` (V3 `#5`: hubs factor along bridge cuts), `LAW_HOLDS_NGT6` (*n* = 7, 8), `LAW_HOLDS_NGT8` (*n* = 9, 10). | -| **Partial Observation & Imputation** | V2 `#24`; V3 `#15`; V4 `#4`, `#5` (`partial_observation_screen`, `topology_aware_imputer`, `imputer_exact_phi`, `prior_matched_vs_mismatched`) | How do hidden nodes and priors affect cheap MI screens vs. exact Φ(MIP)? | `HIDDEN_COLLAPSE_INTERMITTENT_CLIFF` (V2 `#24`), `IMPUTER_RESTORES_AUC` (V3 `#15` on MI: 0.944), `COPY_RESTORES_RING_FAILS` (V4 `#4` on exact Φ: ring 0.806 vs. copy-W 0.896), `MATCHED_RETAINS_COPY_RANKS` (V4 `#5`). | -| **Platform Political Economy** | V2 `#29`, `#31`, `#32`, `#35` (`dual_principals`, `union_vs_coalition`, `multihoming_bypass`, `Substitute_degradation`) | How do dual principals, worker unions, multi-homing, and outside options reshape lock-in? | `CONFLICT_ENCODING`, `UNION_MIRRORS_COAL` (worker union mirrors coalition lever), `RIVAL_ENCODING`, `DROP_AT_FIRST_SUBST` (first outside option breaks lock-in). | -| **AI Workflows, Oversight & MARL Falsifications** | V2 `#37`, `#39`, `#40`, `#41`; V3 `#6`; probes 98, 107 (`agent_protocol_triad`, `hitl_oversight`, `ai_labor_displacement`, `marl_emergent_triads`, `marl_deep_replicate`) | When do AI agents form genuine triads, when is human oversight excluded, and does Φ > 0 predict MARL task success? | `PROTOCOL_IS_COMMIT` (`#37`), `HUMAN_COMMIT_READ` (`#39`: rubber-stamp leaves human outside Φ = 2.0 core), `SHARP_FULL_DISPLACE` (`#40`), `EMERGENT_NULL` & `NULL_SURVIVES` (AUC 0.485–0.555). | +| :---- | :---- | :---- | :---- | +| **Six-Step Pipeline, Adversarial Coding & Proxies** | `irreducibility-pipeline/ in algorithmacy-lab (lab tag orgsci-stage1): examples/01–04, studies/adversarial_coding.py, studies/proxy_run.py, proxy_bridge.py, phiid_measure.py` | How do we translate qualitative text into exact IIT 4.0 tests without hiding encoding choices? | **17/17** reference results & **19/19** test gates pass; **101/101** adversarial flips; proxies rank-AUC **0.563** (Φᵣ) & **0.629** (Φ(WMS)); **60/60** exit trials retain non-exiting core. | +| **Multi-Valued IIT 4.0 & Graded Resolution** | V2 `#1–#4` (`ternary_pivotality`, `graded_commit_verdict`, `mixed_radix_mediator`, `parity_radix_blindspot`) | Does organizational irreducibility survive graded (*k* ≥ 3\) and mixed-radix state spaces? | `TWO_CONDITION_STATE_DEPENDENT`, `SHARP_CLASS_GRADED_PATH` (on diagonal (L,L,L): L \= 0 NULL, L \= 1 DYADIC (Φ \= 0.390, {W,S}), L \= 2 TRIADIC (Φ \= 3.170, {W,S,C})), `EXTRA_RESOLUTION_TO_PHI` (ternary mediator on (1,S,1) sweep: Φ \= 1.170 / 0.500 / 2.000 (full form), core stays {W,S,C}), `BLINDSPOT_SURVIVES_RADIX` (balanced commits S′ \= (W \+ C) mod k keep a flat Φ ≈ 0.5 band at k \= 2, 3, 4). | +| **Classic Org Theory Bridges** | V2 `#43`, `#44`, `#46` (`thompson_verdict_bridge`, `wageman_ti_verdict`, `formal_informal_cut`) | Do classic interdependence typologies align with exact causal irreducibility? | `PARTIAL_ALIGNMENT` (Thompson pooled Φ \= 0; sequential & reciprocal both Φ \= 2.0), `WAGEMAN_PREDICTS_VERDICT (AUC = 1.000 on the designed panel at W ≥ 0.472; does not predict Φ magnitude: XOR and AND share W at Φ = 0.5 vs. 2.0), CUTS_ACROSS` (4/6 forms mismatch H1; alignment 0.333). | +| **16-Thinker Triad Catalog** | 82 thinkers-\* CI checks across 16 thinkers (`org_frontier/thinkers/`: Peirce, Simmel, Caplow, Burt, Granovetter, Coleman, Ostrom, Blau, etc.) | Which canonical sociological triad mechanisms are causally irreducible vs. factorable? | **82 automated probes** across **16 thinkers**; `thinkers-peirce-h1-irreducibility` (8/89 1-input wirings Φ \> 0), `thinkers-peirce-jd-full` (11/30 2-input forms Φ \= 0). | +| **Topology & Scaling Laws** | V3 `#1`, `#5`, `#10`; V4 `#9` (`dual_mediator_template_census`, `ring_of_hubs`, `parity_law_n_gt6`, `parity_law_n_gt8`) | Do modular organizational hubs or dual mediators fuse into macro-triads at scale? | `FACTORS_INTO_FIVE` (V3 `#1`), `FACTORS_NO_COMBINE` (V3 `#5`: hubs factor along bridge cuts), `LAW_HOLDS_NGT6` (*n* \= 7, 8), `LAW_HOLDS_NGT8 (n = 9, 10); together these carry the parity law Φ = 2²⁻ⁿ.` | +| **Partial Observation & Imputation** | V2 `#24`; V3 `#15`; V4 `#4`, `#5` (`partial_observation_screen`, `topology_aware_imputer`, `imputer_exact_phi`, `matched_imputer_exact_phi`) | How do hidden nodes and priors affect cheap MI screens vs. exact Φ(MIP)? | `HIDDEN_COLLAPSE_INTERMITTENT_CLIFF` (V2 `#24`), `IMPUTER_RESTORES_AUC` (V3 `#15` on MI: 0.944), `COPY_RESTORES_RING_FAILS` (V4 `#4` on exact Φ: ring 0.806 vs. copy-W 0.896), `MATCHED_RETAINS_COPY_RANKS` (V4 `#5`). | +| **Platform Political Economy** | V2 `#29`, `#31`, `#32`, `#35` (`dual_principal_conflict`, `worker_union_scale`, `rival_platforms`, `gig_substitution`) | How do dual principals, worker unions, multi-homing, and outside options reshape lock-in? | `CONFLICT_ENCODING`, `UNION_MIRRORS_COAL` (worker union mirrors coalition lever), `RIVAL_ENCODING`, `DROP_AT_FIRST_SUBST` (first outside option breaks lock-in). | +| **AI Workflows, Oversight & MARL Falsifications** | V2 `#37`, `#39`, `#40`, `#41`; probes 98, 107 (`agent_protocol_triad`, `hitl_rubber_stamp`, `ai_fidelity_displace`, `marl_emergent_learn`, `marl_deep_replicate`) | When do AI agents form genuine triads, when is human oversight excluded, and does Φ \> 0 predict MARL task success? | `PROTOCOL_IS_COMMIT` (`#37`), `HUMAN_COMMIT_READ` (`#39`: rubber-stamp leaves human outside Φ \= 2.0 core), `SHARP_FULL_DISPLACE` (`#40`), `EMERGENT_NULL` & `NULL_SURVIVES` (AUC 0.485–0.555). | +