From f780f618d0375680d3d5c219dd02b79682502260 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:27:12 -0700 Subject: [PATCH 01/31] create interlace encryption research workspace --- research/interlace-encryption/README.md | 93 +++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 research/interlace-encryption/README.md diff --git a/research/interlace-encryption/README.md b/research/interlace-encryption/README.md new file mode 100644 index 00000000..d96921b3 --- /dev/null +++ b/research/interlace-encryption/README.md @@ -0,0 +1,93 @@ +# Interlace Encryption Research + +Standing: **stack-local research; specification-first; no security claim**. + +This workspace exists to pursue Erin Spencer's intended encryption construction after +the retirement of URPCS. It is a new project. It does not inherit URPCS code, Laws +1–13, codec architecture, tests, measurements, security conclusions, or terminology. + +The project begins from the mechanisms Erin actually specified and keeps unresolved +mechanics unresolved until they are explicitly selected. + +## Preserved construction + +The current specification floor is: + +1. Operate on the plaintext as a raw bit sequence. +2. Use an ordered sequence of arity/division levels, with at least three levels. +3. At each declared level, divide the working bit sequence into the declared number + of sections; examples already given include fifths, sevenths, and thirds. +4. Within each section, interleave from the two ends: last bit, first bit, + next-to-last bit, next-from-first bit, continuing inward until the section is + exhausted. +5. Apply the declared sequence of arity levels without replacing the mechanism by + pairing, framing, hashing, authentication, a standard cipher mode, or another + familiar construction. +6. After the declared levels, apply the corresponding end-interleave to the whole + resulting bit sequence. +7. Reconstruction depends on knowing the division/arity choices, their order, and + how many levels were used. Those choices are therefore part of the intended + private reconstruction information unless a later explicit law says otherwise. + +These statements define the mechanism to investigate. They do **not** establish +confidentiality, entropy, pseudorandomness, key strength, resistance to known-plaintext +or chosen-plaintext attack, or production suitability. + +## Intended later layers + +Two related ideas are retained as intended research directions, but are not silently +folded into the core transform: + +- multiple interlaced threads, potentially three, five, seven, or more, with + caller-selected corpus/material associated with individual threads; +- preprocessing or binding plaintext through a hyperspace/gonol construction, with a + private gonol participating in recovery. + +Each requires its own explicit contract before implementation. Neither may be +invented from analogy to URPCS, PCEA, UCNS, or conventional cryptographic systems. + +## Non-inheritance boundary + +`research/urpcs/` is historical evidence of a substituted GPT-produced construction. +Nothing from it is an implementation dependency here. A result proved against URPCS +does not transfer into this workspace. + +If comparison with URPCS is ever useful, URPCS is treated only as a negative +specification-divergence witness: an example of what must not be substituted for the +declared construction. + +## Development order + +1. Freeze exact bit-level transformation laws. +2. Resolve only the minimum missing mechanics needed to make the transform invertible. +3. Write an executable reference transform with exhaustive small-input inverse tests. +4. Build an independently structured inverse from the written contract. +5. Measure information leakage and structural distinguishability before adding + authentication, key wrapping, gonol binding, or corpus-thread layers. +6. Add later layers one at a time, preserving ablation tests so their contribution can + be measured rather than presumed. +7. Only after adversarial cryptanalysis may the project make a bounded security claim. + +## Usage guidance + +Start with the specification, not code: + +```bash +cat research/interlace-encryption/SPECIFICATION.md +cat research/interlace-encryption/BASE.json +``` + +Before implementing a missing rule, update the specification so the rule is explicit +and attributable. An implementation must fail rather than choose an unresolved rule +for convenience. + +Do not use this workspace for protecting real secrets until a later security contract +and adversarial evidence explicitly authorize that use. + +## hmmm + +Exact handling of uneven section lengths, whether each arity stage consumes the prior +stage's output or independently re-partitions the original input, representation of the +private arity schedule, thread/corpus binding, hyperspace/gonol binding, authentication, +nonce/state requirements, and the threat model remain unresolved. Their absence is part +of the current specification and must not be filled by model preference. From b07e2881aae79669ecd1886287ffd1e239ee4d24 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:27:15 -0700 Subject: [PATCH 02/31] create interlace encryption research workspace --- .../interlace-encryption/SPECIFICATION.md | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 research/interlace-encryption/SPECIFICATION.md diff --git a/research/interlace-encryption/SPECIFICATION.md b/research/interlace-encryption/SPECIFICATION.md new file mode 100644 index 00000000..5f0c5705 --- /dev/null +++ b/research/interlace-encryption/SPECIFICATION.md @@ -0,0 +1,130 @@ +# Interlace Encryption — specification floor + +Status: **PRE-SPECIFICATION / PRESERVED MECHANISM**. + +This document records what is fixed, what is forbidden to substitute, and what remains +`hmmm`. It is deliberately smaller than an implementation specification. + +## 1. Objects + +- `B`: the input plaintext represented as an ordered bit sequence. +- `A = (a_1, ..., a_k)`: an ordered sequence of division arities. +- `k >= 3`: minimum declared number of arity levels. +- `I(S)`: end-interleave of one finite bit sequence `S`. + +For a sequence + +```text +S = s_0, s_1, ..., s_(n-1) +``` + +the preserved end-interleave order begins + +```text +s_(n-1), s_0, s_(n-2), s_1, ... +``` + +and continues inward until every bit appears exactly once. + +## 2. Declared transform skeleton + +For each arity level `a_i`: + +1. partition the working bit sequence into `a_i` ordered sections; +2. apply `I` independently to every section; +3. preserve all bits exactly once. + +After all declared arity levels, apply `I` once to the entire working sequence. + +Example arity sequence already specified in discussion: + +```text +(5, 7, 3) +``` + +The example is evidence of the mechanism, not a declaration that `(5,7,3)` is the +only or preferred schedule. + +## 3. Required invariants + +Any implementation claiming conformance must preserve all of these: + +- **bit conservation** — no bit is added, removed, duplicated, or changed by the core + interleaving transform; +- **order-sensitive arity schedule** — changing arity order is a different transform; +- **level-count sensitivity** — omitting or adding a level is a different transform; +- **section-local end interleave** — each section uses the declared last/first inward + operation; +- **whole-sequence final interleave** — the final operation acts across the resulting + complete bit sequence; +- **exact invertibility** — given all required reconstruction information, the original + bit sequence must be recovered exactly. + +## 4. Forbidden substitutions + +The following do not implement this specification merely because they are reversible or +cryptographic: + +- recursive pairing codecs; +- authenticated framing; +- substitution with AES, ChaCha, a Feistel network, XOR stream masking, or another + standard primitive; +- hashing the plaintext and treating the digest as the transform; +- replacing section interleaving with generic permutation generation; +- reducing the arity schedule to a conventional integer key without preserving its + specified structural role; +- importing URPCS Laws 1–13. + +Conventional primitives may later be composed around the construction only when their +role is separately declared. They may not replace the construction being tested. + +## 5. Falsification targets + +The first implementation must make it cheap to test: + +1. exhaustive inversion across small bit lengths and multiple schedules; +2. whether different schedules collide on the same permutation; +3. how much of the schedule can be recovered from known plaintext/ciphertext pairs; +4. whether the transform leaks bit-position relations or periodic structure; +5. whether repeated or highly structured plaintext remains visibly structured; +6. whether the effective permutation family grows meaningfully with arity depth; +7. whether thread, corpus, or hyperspace layers add independent security properties or + merely obscure the same permutation. + +Failure on these tests is useful evidence. It must not trigger replacement of the +mechanism with a familiar cipher. + +## 6. Later-layer boundary + +Potential later layers already contemplated: + +- three/five/seven-or-more interlaced streams or threads; +- caller-selected corpus/material per thread; +- plaintext-to-hyperspace/gonol preprocessing; +- a private gonol participating in recovery. + +None is part of the executable core until its own input, output, inverse, and security +claim are explicitly specified. + +## Usage guidance + +An implementer must read this document before writing transform code. For every +unresolved choice below, implementation should raise/refuse rather than select a +default. Tests should identify the exact specification revision they exercise. + +## hmmm + +1. **Uneven partition rule:** how `n mod a_i` bits are distributed when a bit length + is not divisible by the arity. +2. **Stage input rule:** whether level `i+1` partitions the output of level `i` or + independently partitions the original/raw bit sequence before a later composition. +3. **Schedule encoding:** how arities, order, and level count are represented and bound + to recovery. +4. **Thread construction:** exact relationship between sections, threads, and corpus + material. +5. **Hyperspace binding:** exact reversible relation among plaintext, gonol construction, + private gonol, and the core transform. +6. **Authentication/state:** whether integrity, nonces, state evolution, or replay + protection belong to the eventual system and at which layer. +7. **Threat model:** attacker capabilities and the minimum security properties the + construction is intended to provide. From 7b4c1f3ca8cffb29e0e42a92496f7ae92844fea3 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:27:17 -0700 Subject: [PATCH 03/31] create interlace encryption research workspace --- research/interlace-encryption/BASE.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 research/interlace-encryption/BASE.json diff --git a/research/interlace-encryption/BASE.json b/research/interlace-encryption/BASE.json new file mode 100644 index 00000000..8eb7c718 --- /dev/null +++ b/research/interlace-encryption/BASE.json @@ -0,0 +1,10 @@ +{ + "schema": "the-interdependency.stack-research-base", + "version": "1.0.0", + "project": "interlace-encryption", + "source_repository": "The-Interdependency/stack", + "source_commit": "01f340ba5b4c5f107703233750768e201a41da68", + "canon_path": null, + "authority": "stack-local specification and research for Erin Spencer's intended multi-arity interleaving encryption construction", + "standing": "stack-local-research" +} From 3bf05810dd3336b3df2460ed3280b10d42ab874f Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:27:59 -0700 Subject: [PATCH 04/31] document interlace encryption workspace --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5910b372..97c3424d 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ stack/ │ ├── edcm/ # current EDCM measurement research + BASE.json │ ├── pcea/ # current PCEA research + BASE.json │ ├── urpcs/ # RETIRED: substituted GPT-produced codec; historical evidence only +│ ├── interlace-encryption/ # intended multi-arity interleaving encryption research │ ├── ptcna/ # current PTCNA research + BASE.json │ ├── zfae/ # inference construction research and gonol input parser │ ├── epac/ # historical forge evidence; active implementation is independent @@ -101,10 +102,14 @@ multi-arity interleaving construction during GPT-assisted implementation. The re for the substitution is unresolved. Its tests and receipts apply only to that substituted codec and must not be used to validate or falsify the intended URPCS design. +The replacement research path is `research/interlace-encryption/`. It starts from the +actual declared mechanisms: ordered arity/division levels, section-local last/first +inward interleaving, and final whole-sequence interleaving. It deliberately contains no +URPCS implementation dependency and makes no security claim. + ```bash -python3 research/urpcs/urpcs_v1_reference.py --self-test -python3 -m unittest discover -s research/urpcs/tests -p 'test*.py' -node research/urpcs/tests/test_independent_decoder.js +cat research/interlace-encryption/SPECIFICATION.md +cat research/interlace-encryption/BASE.json ``` ### Change stack structure @@ -137,6 +142,8 @@ Python Gonol Construction is likewise stack-local and ungraduated; its Python 3. constructor is an implemented candidate, not stack or language canon. URPCS is retired; its retained vectors and replay evidence establish behavior only of the substituted historical codec. No URPCS claim may be inferred from them. +Interlace Encryption is new stack-local research and remains specification-first; no +confidentiality or production-security standing is implied by its placement. Psychsocio metafauna and From Photons to the Macroverse remain stack-local pre-graduation research. EPAC has an independently published MPL-2.0 `v0.1.0` release and has passed public Stack reconsumption. Its Python forge copy is retired; From 75f74733a25b9c214a1a023f0fd7a125a184a221 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:28:01 -0700 Subject: [PATCH 05/31] route agents to intended encryption research --- AGENTS.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 8e4a19bf..fc7cfb00 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,6 +23,11 @@ projects may later graduate into their own repositories. substituted a recursive pairing/authenticated codec for Erin Spencer's intended multi-arity interleaving construction. Do not extend it or treat any passing test, vector, decoder audit, or measurement as evidence for the intended URPCS design. +- `research/interlace-encryption/` owns new Stack-local research into the intended + construction. Preserve the declared arity/division sequence, section-local last/first + inward interleave, and final whole-sequence interleave. Read `SPECIFICATION.md` before + implementation. Unresolved mechanics must fail closed as `hmmm`; do not substitute a + familiar cipher, codec, permutation generator, or URPCS mechanism. - `research/zfae/` owns Stack-local inference-construction experiments. ZFAE retains conceptual authority, PTCNA owns neural construction, and a0 owns runtime integration. Keep a0-betatest comparisons separately attributed. @@ -137,6 +142,9 @@ coherence; it does not replace workspace behavioral tests. independent repository/release authority boundary; exact UCNS affixiation geometry is unresolved. - URPCS is retired for specification divergence. Why GPT substituted the different architecture remains `hmmm`; its retained evidence is historical and implementation-local. +- Interlace Encryption is specification-first research. Uneven partitions, stage-input + composition, schedule encoding, thread/corpus binding, hyperspace/gonol binding, + authentication/state, and the threat model remain `hmmm` until explicitly resolved. - The complete root `skill-lib/` snapshot refresh remains separate because the current provenance-bound fresh-making doctrine is newer than the local generator snapshot. - Project graduation automation remains unimplemented. From fe2611854a084a2d75eea3260878f97c9d5ca4a1 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:28:03 -0700 Subject: [PATCH 06/31] register interlace encryption research participant --- stack-manifest.json | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/stack-manifest.json b/stack-manifest.json index 85bdcc57..936c71bb 100644 --- a/stack-manifest.json +++ b/stack-manifest.json @@ -1,7 +1,7 @@ { "schema": "the-interdependency.stack-manifest", "version": "1.1.0", - "work_graph_sha256": "1e9a8f485c290bf7e3537e66cc72ac8ced749ce58fd4005647bd3981e071af1f", + "work_graph_sha256": "985d462de06bdf3c0e8cadfbac93d43f9cc72c82aca6712b6012512dea75350d", "repositories": [ { "repository": "The-Interdependency/skill-lib", @@ -69,7 +69,8 @@ "ucns has no LICENSE file at snapshot commit 828c0b8", "Python Gonol Construction remains stack-local research without independent repository or release authority", "URPCS is retired historical evidence after GPT-assisted implementation diverged from Erin Spencer's intended multi-arity interleaving specification; why the substitution occurred remains unresolved", - "skill-lib remains a special operational snapshot at stack root rather than following the libs/research pair" + "skill-lib remains a special operational snapshot at stack root rather than following the libs/research pair", + "Interlace Encryption preserves the intended multi-arity interleaving mechanism, while uneven partitioning, stage-input composition, schedule encoding, thread/corpus binding, hyperspace/gonol binding, authentication/state, and threat model remain unresolved" ] }, "research_participants": [ @@ -190,6 +191,15 @@ "repository": "The-Interdependency/stack", "workspace": "research/urpcs/" }, + { + "authority_transfer": false, + "canonical_release": false, + "commit": "01f340ba5b4c5f107703233750768e201a41da68", + "participant_id": "interlace-encryption", + "relation": "new stack-local specification and research for Erin Spencer's intended multi-arity interleaving encryption construction; no URPCS implementation inheritance and no confidentiality/security standing yet", + "repository": "The-Interdependency/stack", + "workspace": "research/interlace-encryption/" + }, { "workspace": "research/english-gonol/", "participant_id": "views-source", From 66f0690db4c9833a9b59d973f19d7ed1475c1fe0 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:28:05 -0700 Subject: [PATCH 07/31] record interlace encryption in human work graph --- STACK_MANIFEST.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/STACK_MANIFEST.md b/STACK_MANIFEST.md index 2030d498..80942d12 100644 --- a/STACK_MANIFEST.md +++ b/STACK_MANIFEST.md @@ -14,10 +14,11 @@ Provenance and authority-boundary record for `The-Interdependency/stack`. - EPAC-derived carrier workspace separation UTC: `2026-09-18` at `545e135e2efbbcf29f033ab5530ac4876a68b718` - URPCS v1 workspace integration UTC: `2026-09-20` from Stack baseline `a428a41a38a8b30bacb7025a4d54070b228a8089` - URPCS retirement UTC: `2026-09-28`; specification divergence discovered after conversation-history review; retained implementation is historical evidence only +- Interlace Encryption workspace creation UTC: `2026-09-28`; new specification-first research starts from the intended multi-arity interleaving mechanism without URPCS inheritance - English four-view complete-corpus audit UTC: `2026-09-22`, exact view source `1f9a35eb355296fc88d09784c7a3e2e95511ca31`; all 164,864 words, native and independent agreement. - Stack-manifest schema: `the-interdependency.stack-manifest` version `1.1.0` - Work-graph digest (SHA-256 over canonical `repositories` + `research_participants` + `boundaries` JSON): - `1e9a8f485c290bf7e3537e66cc72ac8ced749ce58fd4005647bd3981e071af1f` + `985d462de06bdf3c0e8cadfbac93d43f9cc72c82aca6712b6012512dea75350d` - Machine-readable copy: [`stack-manifest.json`](stack-manifest.json) ## Directory contract @@ -61,7 +62,8 @@ release identity. |---|---|---|---|---| | `research/epac/` | `The-Interdependency/stack` | `0e8384bbb60e4c2189016a212bdd0030d04aed7d` | historical forge evidence; active implementation consumed from the independent EPAC release | no | | `research/epac-derived-carrier/` | `The-Interdependency/stack` | `545e135e2efbbcf29f033ab5530ac4876a68b718` | active stack-local carrier audit consuming exact EPAC source; no EPAC implementation/public-contract or scientific standing transfer | no | -| `research/urpcs/` | `The-Interdependency/stack` | `a428a41a38a8b30bacb7025a4d54070b228a8089` | stack-local authenticated recursive pairing codec research with byte-exact reference vectors; no confidentiality, PCEA compatibility, or UCNS-gonol identity transfer | no | +| `research/urpcs/` | `The-Interdependency/stack` | `a428a41a38a8b30bacb7025a4d54070b228a8089` | retired historical evidence for the substituted recursive pairing/authenticated codec; not evidence for the intended URPCS construction | no | +| `research/interlace-encryption/` | `The-Interdependency/stack` | `01f340ba5b4c5f107703233750768e201a41da68` | new specification-first research for the intended multi-arity interleaving encryption construction; no URPCS implementation inheritance or security standing | no | | `research/english-gonol/` | `The-Interdependency/stack` | `99b3598b02a6e683b3c84184d8ea443b12fc0e1a` | stack-local English lexical/gonol construction separated from EDCM; full pinned-corpus v2 build/replay survived; consumes UCNS geometry; EDCM may evaluate outputs but does not define construction | no | | `research/python-gonol/` | `The-Interdependency/stack` | `0e8384bbb60e4c2189016a212bdd0030d04aed7d` | stack-local bottom-up Python 3.12 source gonol construction; applies METAPAT affixiation semantics, consumes optional UCNS geometry, and transfers no language authority to UCNS or EDCM | no | | `research/ucns/` | `The-Interdependency/ucns` | `1975fe70cf4e0826a8020c2da3047569e277af64` | explicit source base for integrated stack-local UCNS research; does not refresh or replace the manifest-pinned `libs/ucns` canonical view | no | @@ -129,6 +131,12 @@ construction. The reason for that substitution remains unresolved. All retained vectors, decoder evidence, and measurements describe only the substituted codec; they do not validate or falsify the intended URPCS design. +The intended construction now has a separate research owner at +`research/interlace-encryption/`. Its specification floor preserves ordered arity +levels, section-local last/first inward interleaving, and final whole-sequence +interleaving. The workspace starts with no implementation inheritance from URPCS and +no confidentiality or production-security claim. + ZFAE construction research lives at `research/zfae/`. Its exact research-only inputs are recorded above. The parser consumes the existing English GlyphGonol producer at the Stack baseline and the separately pinned UCNS carrier. Its @@ -201,12 +209,16 @@ fixtures remain executable historical evidence for the substituted profile only. No result from that profile may be promoted to a claim about the intended URPCS construction. +Interlace Encryption is a new stack-local research component. It is not yet an +independent repository, release, or security-reviewed cryptosystem. + ## hmmm - UCNS has no `LICENSE` file at pinned commit `828c0b8`. - English Gonol Construction remains stack-local research; independent repository/release authority and the exact UCNS displacement law have not been established. - Python Gonol Construction remains stack-local research; independent repository/release authority and exact UCNS affixiation geometry remain unresolved. - URPCS is retired for specification divergence; why GPT flattened/substituted the intended construction remains unresolved, and retained evidence is scoped only to the substituted implementation. +- Interlace Encryption preserves the intended mechanism, while uneven partitioning, stage-input composition, schedule encoding, thread/corpus binding, hyperspace/gonol binding, authentication/state, and the threat model remain unresolved. - `skill-lib/` remains a special operational snapshot at stack root rather than following the ordinary `libs/` + `research/` pair. ## UCHC input candidate From 55a78e50f3609eb3a918f72fa6a61ef1f27d19fe Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:31:32 -0700 Subject: [PATCH 08/31] shorten project path to interlace --- research/interlace/README.md | 93 ++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 research/interlace/README.md diff --git a/research/interlace/README.md b/research/interlace/README.md new file mode 100644 index 00000000..b9d46a37 --- /dev/null +++ b/research/interlace/README.md @@ -0,0 +1,93 @@ +# Interlace Research + +Standing: **stack-local research; specification-first; no security claim**. + +This workspace exists to pursue Erin Spencer's intended encryption construction after +the retirement of URPCS. It is a new project. It does not inherit URPCS code, Laws +1–13, codec architecture, tests, measurements, security conclusions, or terminology. + +The project begins from the mechanisms Erin actually specified and keeps unresolved +mechanics unresolved until they are explicitly selected. + +## Preserved construction + +The current specification floor is: + +1. Operate on the plaintext as a raw bit sequence. +2. Use an ordered sequence of arity/division levels, with at least three levels. +3. At each declared level, divide the working bit sequence into the declared number + of sections; examples already given include fifths, sevenths, and thirds. +4. Within each section, interleave from the two ends: last bit, first bit, + next-to-last bit, next-from-first bit, continuing inward until the section is + exhausted. +5. Apply the declared sequence of arity levels without replacing the mechanism by + pairing, framing, hashing, authentication, a standard cipher mode, or another + familiar construction. +6. After the declared levels, apply the corresponding end-interleave to the whole + resulting bit sequence. +7. Reconstruction depends on knowing the division/arity choices, their order, and + how many levels were used. Those choices are therefore part of the intended + private reconstruction information unless a later explicit law says otherwise. + +These statements define the mechanism to investigate. They do **not** establish +confidentiality, entropy, pseudorandomness, key strength, resistance to known-plaintext +or chosen-plaintext attack, or production suitability. + +## Intended later layers + +Two related ideas are retained as intended research directions, but are not silently +folded into the core transform: + +- multiple interlaced threads, potentially three, five, seven, or more, with + caller-selected corpus/material associated with individual threads; +- preprocessing or binding plaintext through a hyperspace/gonol construction, with a + private gonol participating in recovery. + +Each requires its own explicit contract before implementation. Neither may be +invented from analogy to URPCS, PCEA, UCNS, or conventional cryptographic systems. + +## Non-inheritance boundary + +`research/urpcs/` is historical evidence of a substituted GPT-produced construction. +Nothing from it is an implementation dependency here. A result proved against URPCS +does not transfer into this workspace. + +If comparison with URPCS is ever useful, URPCS is treated only as a negative +specification-divergence witness: an example of what must not be substituted for the +declared construction. + +## Development order + +1. Freeze exact bit-level transformation laws. +2. Resolve only the minimum missing mechanics needed to make the transform invertible. +3. Write an executable reference transform with exhaustive small-input inverse tests. +4. Build an independently structured inverse from the written contract. +5. Measure information leakage and structural distinguishability before adding + authentication, key wrapping, gonol binding, or corpus-thread layers. +6. Add later layers one at a time, preserving ablation tests so their contribution can + be measured rather than presumed. +7. Only after adversarial cryptanalysis may the project make a bounded security claim. + +## Usage guidance + +Start with the specification, not code: + +```bash +cat research/interlace/SPECIFICATION.md +cat research/interlace/BASE.json +``` + +Before implementing a missing rule, update the specification so the rule is explicit +and attributable. An implementation must fail rather than choose an unresolved rule +for convenience. + +Do not use this workspace for protecting real secrets until a later security contract +and adversarial evidence explicitly authorize that use. + +## hmmm + +Exact handling of uneven section lengths, whether each arity stage consumes the prior +stage's output or independently re-partitions the original input, representation of the +private arity schedule, thread/corpus binding, hyperspace/gonol binding, authentication, +nonce/state requirements, and the threat model remain unresolved. Their absence is part +of the current specification and must not be filled by model preference. From f3da1ff529f5ccf14ae24429011e74977efbf25a Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:31:34 -0700 Subject: [PATCH 09/31] shorten project path to interlace --- research/interlace/SPECIFICATION.md | 130 ++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 research/interlace/SPECIFICATION.md diff --git a/research/interlace/SPECIFICATION.md b/research/interlace/SPECIFICATION.md new file mode 100644 index 00000000..9e6c9f26 --- /dev/null +++ b/research/interlace/SPECIFICATION.md @@ -0,0 +1,130 @@ +# Interlace — specification floor + +Status: **PRE-SPECIFICATION / PRESERVED MECHANISM**. + +This document records what is fixed, what is forbidden to substitute, and what remains +`hmmm`. It is deliberately smaller than an implementation specification. + +## 1. Objects + +- `B`: the input plaintext represented as an ordered bit sequence. +- `A = (a_1, ..., a_k)`: an ordered sequence of division arities. +- `k >= 3`: minimum declared number of arity levels. +- `I(S)`: end-interleave of one finite bit sequence `S`. + +For a sequence + +```text +S = s_0, s_1, ..., s_(n-1) +``` + +the preserved end-interleave order begins + +```text +s_(n-1), s_0, s_(n-2), s_1, ... +``` + +and continues inward until every bit appears exactly once. + +## 2. Declared transform skeleton + +For each arity level `a_i`: + +1. partition the working bit sequence into `a_i` ordered sections; +2. apply `I` independently to every section; +3. preserve all bits exactly once. + +After all declared arity levels, apply `I` once to the entire working sequence. + +Example arity sequence already specified in discussion: + +```text +(5, 7, 3) +``` + +The example is evidence of the mechanism, not a declaration that `(5,7,3)` is the +only or preferred schedule. + +## 3. Required invariants + +Any implementation claiming conformance must preserve all of these: + +- **bit conservation** — no bit is added, removed, duplicated, or changed by the core + interleaving transform; +- **order-sensitive arity schedule** — changing arity order is a different transform; +- **level-count sensitivity** — omitting or adding a level is a different transform; +- **section-local end interleave** — each section uses the declared last/first inward + operation; +- **whole-sequence final interleave** — the final operation acts across the resulting + complete bit sequence; +- **exact invertibility** — given all required reconstruction information, the original + bit sequence must be recovered exactly. + +## 4. Forbidden substitutions + +The following do not implement this specification merely because they are reversible or +cryptographic: + +- recursive pairing codecs; +- authenticated framing; +- substitution with AES, ChaCha, a Feistel network, XOR stream masking, or another + standard primitive; +- hashing the plaintext and treating the digest as the transform; +- replacing section interleaving with generic permutation generation; +- reducing the arity schedule to a conventional integer key without preserving its + specified structural role; +- importing URPCS Laws 1–13. + +Conventional primitives may later be composed around the construction only when their +role is separately declared. They may not replace the construction being tested. + +## 5. Falsification targets + +The first implementation must make it cheap to test: + +1. exhaustive inversion across small bit lengths and multiple schedules; +2. whether different schedules collide on the same permutation; +3. how much of the schedule can be recovered from known plaintext/ciphertext pairs; +4. whether the transform leaks bit-position relations or periodic structure; +5. whether repeated or highly structured plaintext remains visibly structured; +6. whether the effective permutation family grows meaningfully with arity depth; +7. whether thread, corpus, or hyperspace layers add independent security properties or + merely obscure the same permutation. + +Failure on these tests is useful evidence. It must not trigger replacement of the +mechanism with a familiar cipher. + +## 6. Later-layer boundary + +Potential later layers already contemplated: + +- three/five/seven-or-more interlaced streams or threads; +- caller-selected corpus/material per thread; +- plaintext-to-hyperspace/gonol preprocessing; +- a private gonol participating in recovery. + +None is part of the executable core until its own input, output, inverse, and security +claim are explicitly specified. + +## Usage guidance + +An implementer must read this document before writing transform code. For every +unresolved choice below, implementation should raise/refuse rather than select a +default. Tests should identify the exact specification revision they exercise. + +## hmmm + +1. **Uneven partition rule:** how `n mod a_i` bits are distributed when a bit length + is not divisible by the arity. +2. **Stage input rule:** whether level `i+1` partitions the output of level `i` or + independently partitions the original/raw bit sequence before a later composition. +3. **Schedule encoding:** how arities, order, and level count are represented and bound + to recovery. +4. **Thread construction:** exact relationship between sections, threads, and corpus + material. +5. **Hyperspace binding:** exact reversible relation among plaintext, gonol construction, + private gonol, and the core transform. +6. **Authentication/state:** whether integrity, nonces, state evolution, or replay + protection belong to the eventual system and at which layer. +7. **Threat model:** attacker capabilities and the minimum security properties the + construction is intended to provide. From a61edf574602a203d8464794afc8827c3dfca0ef Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:31:36 -0700 Subject: [PATCH 10/31] shorten project path to interlace --- research/interlace/BASE.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 research/interlace/BASE.json diff --git a/research/interlace/BASE.json b/research/interlace/BASE.json new file mode 100644 index 00000000..872e1e96 --- /dev/null +++ b/research/interlace/BASE.json @@ -0,0 +1,10 @@ +{ + "schema": "the-interdependency.stack-research-base", + "version": "1.0.0", + "project": "interlace", + "source_repository": "The-Interdependency/stack", + "source_commit": "01f340ba5b4c5f107703233750768e201a41da68", + "canon_path": null, + "authority": "stack-local specification and research for Erin Spencer's intended multi-arity interleaving encryption construction", + "standing": "stack-local-research" +} From 23ea93bd10122bb26c7a80be7c47abdc5ecf48e9 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:31:41 -0700 Subject: [PATCH 11/31] remove long interlace-encryption path --- research/interlace-encryption/README.md | 93 ------------------------- 1 file changed, 93 deletions(-) delete mode 100644 research/interlace-encryption/README.md diff --git a/research/interlace-encryption/README.md b/research/interlace-encryption/README.md deleted file mode 100644 index d96921b3..00000000 --- a/research/interlace-encryption/README.md +++ /dev/null @@ -1,93 +0,0 @@ -# Interlace Encryption Research - -Standing: **stack-local research; specification-first; no security claim**. - -This workspace exists to pursue Erin Spencer's intended encryption construction after -the retirement of URPCS. It is a new project. It does not inherit URPCS code, Laws -1–13, codec architecture, tests, measurements, security conclusions, or terminology. - -The project begins from the mechanisms Erin actually specified and keeps unresolved -mechanics unresolved until they are explicitly selected. - -## Preserved construction - -The current specification floor is: - -1. Operate on the plaintext as a raw bit sequence. -2. Use an ordered sequence of arity/division levels, with at least three levels. -3. At each declared level, divide the working bit sequence into the declared number - of sections; examples already given include fifths, sevenths, and thirds. -4. Within each section, interleave from the two ends: last bit, first bit, - next-to-last bit, next-from-first bit, continuing inward until the section is - exhausted. -5. Apply the declared sequence of arity levels without replacing the mechanism by - pairing, framing, hashing, authentication, a standard cipher mode, or another - familiar construction. -6. After the declared levels, apply the corresponding end-interleave to the whole - resulting bit sequence. -7. Reconstruction depends on knowing the division/arity choices, their order, and - how many levels were used. Those choices are therefore part of the intended - private reconstruction information unless a later explicit law says otherwise. - -These statements define the mechanism to investigate. They do **not** establish -confidentiality, entropy, pseudorandomness, key strength, resistance to known-plaintext -or chosen-plaintext attack, or production suitability. - -## Intended later layers - -Two related ideas are retained as intended research directions, but are not silently -folded into the core transform: - -- multiple interlaced threads, potentially three, five, seven, or more, with - caller-selected corpus/material associated with individual threads; -- preprocessing or binding plaintext through a hyperspace/gonol construction, with a - private gonol participating in recovery. - -Each requires its own explicit contract before implementation. Neither may be -invented from analogy to URPCS, PCEA, UCNS, or conventional cryptographic systems. - -## Non-inheritance boundary - -`research/urpcs/` is historical evidence of a substituted GPT-produced construction. -Nothing from it is an implementation dependency here. A result proved against URPCS -does not transfer into this workspace. - -If comparison with URPCS is ever useful, URPCS is treated only as a negative -specification-divergence witness: an example of what must not be substituted for the -declared construction. - -## Development order - -1. Freeze exact bit-level transformation laws. -2. Resolve only the minimum missing mechanics needed to make the transform invertible. -3. Write an executable reference transform with exhaustive small-input inverse tests. -4. Build an independently structured inverse from the written contract. -5. Measure information leakage and structural distinguishability before adding - authentication, key wrapping, gonol binding, or corpus-thread layers. -6. Add later layers one at a time, preserving ablation tests so their contribution can - be measured rather than presumed. -7. Only after adversarial cryptanalysis may the project make a bounded security claim. - -## Usage guidance - -Start with the specification, not code: - -```bash -cat research/interlace-encryption/SPECIFICATION.md -cat research/interlace-encryption/BASE.json -``` - -Before implementing a missing rule, update the specification so the rule is explicit -and attributable. An implementation must fail rather than choose an unresolved rule -for convenience. - -Do not use this workspace for protecting real secrets until a later security contract -and adversarial evidence explicitly authorize that use. - -## hmmm - -Exact handling of uneven section lengths, whether each arity stage consumes the prior -stage's output or independently re-partitions the original input, representation of the -private arity schedule, thread/corpus binding, hyperspace/gonol binding, authentication, -nonce/state requirements, and the threat model remain unresolved. Their absence is part -of the current specification and must not be filled by model preference. From 22a6f0f3a7858b30ef36cb8808e29a77431448ba Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:31:43 -0700 Subject: [PATCH 12/31] remove long interlace-encryption path --- .../interlace-encryption/SPECIFICATION.md | 130 ------------------ 1 file changed, 130 deletions(-) delete mode 100644 research/interlace-encryption/SPECIFICATION.md diff --git a/research/interlace-encryption/SPECIFICATION.md b/research/interlace-encryption/SPECIFICATION.md deleted file mode 100644 index 5f0c5705..00000000 --- a/research/interlace-encryption/SPECIFICATION.md +++ /dev/null @@ -1,130 +0,0 @@ -# Interlace Encryption — specification floor - -Status: **PRE-SPECIFICATION / PRESERVED MECHANISM**. - -This document records what is fixed, what is forbidden to substitute, and what remains -`hmmm`. It is deliberately smaller than an implementation specification. - -## 1. Objects - -- `B`: the input plaintext represented as an ordered bit sequence. -- `A = (a_1, ..., a_k)`: an ordered sequence of division arities. -- `k >= 3`: minimum declared number of arity levels. -- `I(S)`: end-interleave of one finite bit sequence `S`. - -For a sequence - -```text -S = s_0, s_1, ..., s_(n-1) -``` - -the preserved end-interleave order begins - -```text -s_(n-1), s_0, s_(n-2), s_1, ... -``` - -and continues inward until every bit appears exactly once. - -## 2. Declared transform skeleton - -For each arity level `a_i`: - -1. partition the working bit sequence into `a_i` ordered sections; -2. apply `I` independently to every section; -3. preserve all bits exactly once. - -After all declared arity levels, apply `I` once to the entire working sequence. - -Example arity sequence already specified in discussion: - -```text -(5, 7, 3) -``` - -The example is evidence of the mechanism, not a declaration that `(5,7,3)` is the -only or preferred schedule. - -## 3. Required invariants - -Any implementation claiming conformance must preserve all of these: - -- **bit conservation** — no bit is added, removed, duplicated, or changed by the core - interleaving transform; -- **order-sensitive arity schedule** — changing arity order is a different transform; -- **level-count sensitivity** — omitting or adding a level is a different transform; -- **section-local end interleave** — each section uses the declared last/first inward - operation; -- **whole-sequence final interleave** — the final operation acts across the resulting - complete bit sequence; -- **exact invertibility** — given all required reconstruction information, the original - bit sequence must be recovered exactly. - -## 4. Forbidden substitutions - -The following do not implement this specification merely because they are reversible or -cryptographic: - -- recursive pairing codecs; -- authenticated framing; -- substitution with AES, ChaCha, a Feistel network, XOR stream masking, or another - standard primitive; -- hashing the plaintext and treating the digest as the transform; -- replacing section interleaving with generic permutation generation; -- reducing the arity schedule to a conventional integer key without preserving its - specified structural role; -- importing URPCS Laws 1–13. - -Conventional primitives may later be composed around the construction only when their -role is separately declared. They may not replace the construction being tested. - -## 5. Falsification targets - -The first implementation must make it cheap to test: - -1. exhaustive inversion across small bit lengths and multiple schedules; -2. whether different schedules collide on the same permutation; -3. how much of the schedule can be recovered from known plaintext/ciphertext pairs; -4. whether the transform leaks bit-position relations or periodic structure; -5. whether repeated or highly structured plaintext remains visibly structured; -6. whether the effective permutation family grows meaningfully with arity depth; -7. whether thread, corpus, or hyperspace layers add independent security properties or - merely obscure the same permutation. - -Failure on these tests is useful evidence. It must not trigger replacement of the -mechanism with a familiar cipher. - -## 6. Later-layer boundary - -Potential later layers already contemplated: - -- three/five/seven-or-more interlaced streams or threads; -- caller-selected corpus/material per thread; -- plaintext-to-hyperspace/gonol preprocessing; -- a private gonol participating in recovery. - -None is part of the executable core until its own input, output, inverse, and security -claim are explicitly specified. - -## Usage guidance - -An implementer must read this document before writing transform code. For every -unresolved choice below, implementation should raise/refuse rather than select a -default. Tests should identify the exact specification revision they exercise. - -## hmmm - -1. **Uneven partition rule:** how `n mod a_i` bits are distributed when a bit length - is not divisible by the arity. -2. **Stage input rule:** whether level `i+1` partitions the output of level `i` or - independently partitions the original/raw bit sequence before a later composition. -3. **Schedule encoding:** how arities, order, and level count are represented and bound - to recovery. -4. **Thread construction:** exact relationship between sections, threads, and corpus - material. -5. **Hyperspace binding:** exact reversible relation among plaintext, gonol construction, - private gonol, and the core transform. -6. **Authentication/state:** whether integrity, nonces, state evolution, or replay - protection belong to the eventual system and at which layer. -7. **Threat model:** attacker capabilities and the minimum security properties the - construction is intended to provide. From f4add08463ad45fbbe70b6325a94996c7b7eddb9 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:31:45 -0700 Subject: [PATCH 13/31] remove long interlace-encryption path --- research/interlace-encryption/BASE.json | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 research/interlace-encryption/BASE.json diff --git a/research/interlace-encryption/BASE.json b/research/interlace-encryption/BASE.json deleted file mode 100644 index 8eb7c718..00000000 --- a/research/interlace-encryption/BASE.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "schema": "the-interdependency.stack-research-base", - "version": "1.0.0", - "project": "interlace-encryption", - "source_repository": "The-Interdependency/stack", - "source_commit": "01f340ba5b4c5f107703233750768e201a41da68", - "canon_path": null, - "authority": "stack-local specification and research for Erin Spencer's intended multi-arity interleaving encryption construction", - "standing": "stack-local-research" -} From 7467da22a0b9987208f8b7dc4258c8ed0b7cfe41 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:33:23 -0700 Subject: [PATCH 14/31] restore full Weave encryption architecture --- research/weave/README.md | 114 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 research/weave/README.md diff --git a/research/weave/README.md b/research/weave/README.md new file mode 100644 index 00000000..5375a492 --- /dev/null +++ b/research/weave/README.md @@ -0,0 +1,114 @@ +# Weave + +Standing: **stack-local research; specification-first; no security claim**. + +Weave is the replacement research workspace for Erin Spencer's intended encryption +system after retirement of the substituted URPCS implementation. + +The system is **not** merely an interleaving permutation. The preserved architecture +contains multiple cooperating layers. Development may stage those layers for testing, +but no layer may be silently discarded or replaced by a familiar construction. + +## Preserved architecture + +### 1. Hyperspace / gonol plaintext construction + +Plaintext is intended to be processed into a hyperspace gonol construction rather than +treated only as an opaque byte string. The information is represented as a nested gonol +set before or as part of encryption. + +Recovery is intended to require a **private gonol** associated with the private key. +The exact reversible binding and key representation remain unresolved and must be +specified rather than invented. + +### 2. Multiple threads + +The encrypted construction uses multiple threads/data streams, with arity at least +three and contemplated thread counts including three, five, seven, or more. + +Each thread must contribute to reconstruction. A single independently useful stream is +not the intended construction. + +### 3. Thread-associated corpus/material + +Threads may be associated with user-selected corpus/material such as literary works, +music, technical manuals, sounds, or other chosen source material. + +The corpus/material is intended to participate in reconstruction as semi-secret +context, not merely as documentation or a label. Its exact derivation and binding rule +remain to be frozen. + +### 4. Multi-arity bit interleaving + +The bit transform is one load-bearing layer inside Weave. + +For an ordered sequence of division arities, with at least three levels: + +1. divide the working bit sequence into the declared number of sections; +2. within each section interleave inward from opposite ends: + last bit, first bit, next-to-last bit, next-from-first bit, and so on; +3. repeat for the declared arity sequence, examples already given including fifths, + sevenths, and thirds; +4. after the declared levels, interleave the resulting whole sequence in the same + opposite-end manner. + +Knowing the division choices, their order, and the number of levels is part of the +reconstruction problem unless an explicit later law changes that role. + +### 5. Keying / recovery structure + +The intended system ultimately requires asymmetric recovery structure with no silent +dependency on an external cryptographic system. The private side is intended to include +the private gonol and the structural information needed to reverse the construction. + +The exact public/private derivation law is not yet specified. That absence is `hmmm`, +not permission to substitute RSA, ECC, Diffie-Hellman, a conventional KEM, or URPCS. + +## Non-inheritance boundary + +`research/urpcs/` is historical evidence of a substituted GPT-produced construction. +No URPCS law, codec, test, result, or security conclusion is an implementation +dependency of Weave. + +URPCS may be consulted only as a specification-divergence witness: an example of what +must not happen again. + +## Development discipline + +The full architecture is preserved from the start, while implementation proceeds in +separable layers so each contribution can be falsified. + +1. Freeze the complete dataflow and the inverse dependencies among gonol construction, + threads, corpus/material, interleaving, and key structure. +2. Specify exact bit-level interleaving and inverse rules without changing the mechanism. +3. Specify thread formation and recombination. +4. Specify corpus/material derivation and binding. +5. Specify hyperspace/private-gonol construction and recovery. +6. Specify the asymmetric public/private relation. +7. Implement the smallest complete round-trip profile containing every required layer. +8. Build an independently structured decoder/recovery implementation from the written + contract. +9. Perform adversarial analysis before making any confidentiality or production claim. + +A reduced test harness may isolate one layer, but results from a reduced harness may not +be presented as results for Weave as a whole. + +## Usage guidance + +Start here: + +```bash +cat research/weave/SPECIFICATION.md +cat research/weave/BASE.json +``` + +Do not use Weave to protect real secrets until an explicit security contract and +adversarial evidence justify that use. + +## hmmm + +Uneven section partitioning; exact ordering/composition of arity stages; thread +formation; corpus/material derivation; hyperspace/gonol encoding; private-gonol binding; +public/private key derivation; authentication, nonce/state, replay behavior; and the +threat model remain unresolved. They are preserved as required design boundaries, not +optional features and not invitations for model substitution. From fae6d31dd41b929eae6200e651b2859da81e6bea Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:33:25 -0700 Subject: [PATCH 15/31] restore full Weave encryption architecture --- research/weave/SPECIFICATION.md | 175 ++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 research/weave/SPECIFICATION.md diff --git a/research/weave/SPECIFICATION.md b/research/weave/SPECIFICATION.md new file mode 100644 index 00000000..53f88e8d --- /dev/null +++ b/research/weave/SPECIFICATION.md @@ -0,0 +1,175 @@ +# Weave — preserved architecture and specification floor + +Status: **PRE-SPECIFICATION / FULL-ARCHITECTURE PRESERVATION**. + +This document records the construction that must survive implementation. It separates +fixed architecture from unresolved mechanics. An unresolved mechanic must remain +`hmmm`; an implementer may not replace the architecture to make the problem easier. + +## 1. System layers + +Weave currently comprises these intended layers: + +1. plaintext -> nested hyperspace/gonol construction; +2. private-gonol participation in recovery/private key structure; +3. multiple reconstruction-dependent threads/data streams; +4. user-selected corpus/material associated with threads; +5. ordered multi-arity section interleaving within the thread/data transformation; +6. final whole-sequence end interleaving; +7. asymmetric public/private recovery relation. + +These layers are analytically separable but belong to one intended cryptosystem. + +## 2. Core bit interleave + +Let `S = s_0, s_1, ..., s_(n-1)`. + +Define the preserved end-interleave ordering: + +```text +I(S) = s_(n-1), s_0, s_(n-2), s_1, ... +``` + +continuing inward until every bit appears exactly once. + +For an ordered arity schedule + +```text +A = (a_1, ..., a_k), k >= 3 +``` + +each level partitions the relevant working sequence into `a_i` ordered sections and +applies `I` independently to each section. After the declared levels, `I` is applied +to the complete resulting sequence. + +A previously stated example schedule is: + +```text +(5, 7, 3) +``` + +This demonstrates the mechanism; it does not select one canonical schedule. + +## 3. Thread structure + +The design requires multiple data streams/threads, contemplated at arities such as +three, five, seven, or more. + +Required architectural property: + +```text +no one thread == complete recoverable plaintext +complete recovery requires the declared thread relation +``` + +The exact split/recombination law remains unresolved. + +## 4. Corpus/material participation + +Each thread may consume or bind caller-selected corpus/material. Examples already +contemplated include literary, musical, technical-manual, and sound material. + +The material is intended to participate in construction/recovery. Treating it as an +unused label or merely hashing its filename does not satisfy this architecture. + +Exact extraction, addressing, mixing, and recovery dependence remain unresolved. + +## 5. Hyperspace / gonol layer + +Plaintext is intended to be represented as a nested hyperspace gonol construction +before or within the encryption transform. + +A private gonol is intended to be hidden/bound within the private-key side and required +for recovery. + +The exact relation among: + +```text +plaintext +nested gonol construction +private gonol +public key +private key +ciphertext +recovered plaintext +``` + +must be specified explicitly before implementation can claim this layer. + +## 6. Asymmetric relation + +The intended system is to reach asymmetric key generation/recovery without silently +outsourcing the construction to an unrelated external cryptosystem. + +The public/private derivation law is not yet fixed. Existing standard primitives may +be used later only in explicitly scoped supporting roles; they may not stand in for the +missing Weave relation. + +## 7. Required invariants + +Any complete Weave profile must eventually demonstrate: + +- exact plaintext recovery with the complete authorized reconstruction state; +- failure or materially incomplete recovery when required structural components are + absent; +- bit conservation wherever a layer is specified as a permutation; +- order sensitivity of the declared arity schedule; +- level-count sensitivity; +- dependence on the declared thread relation; +- dependence on the declared corpus/material relation if that layer is enabled; +- dependence on the private gonol/private-key relation; +- no hidden inheritance from URPCS. + +## 8. Forbidden flattening + +The following are specification failures if used as replacements rather than explicitly +declared supporting components: + +- reducing Weave to only the bit interleave; +- reducing threads to one stream; +- making corpus/material decorative; +- omitting hyperspace/gonol construction; +- omitting the private gonol from recovery; +- replacing the system with recursive pairing/framing; +- importing URPCS Laws 1–13; +- replacing missing key structure with RSA, ECC, DH, a KEM, AES, ChaCha, Feistel, or + another familiar primitive and calling the result Weave; +- treating a reduced-layer test as evidence for the complete system. + +## 9. Falsification program + +The research program must separately test: + +1. exact inversion of the bit interleave; +2. collisions/equivalences among arity schedules; +3. schedule recovery from known/chosen plaintext; +4. thread independence and reconstruction dependence; +5. corpus/material contribution versus decorative obscurity; +6. structural leakage and distinguishability; +7. hyperspace/gonol reversibility and whether the private gonol adds a real independent + constraint; +8. public/private asymmetry and whether public information permits unauthorized + reconstruction; +9. complete-system behavior after all required layers are combined. + +A failure is evidence about the specified mechanism. It does not authorize replacement +of the mechanism. + +## Usage guidance + +Implement one explicitly versioned profile at a time, but every profile must state which +Weave layers it includes and excludes. A profile omitting a required layer is a layer +test, not a Weave security result. + +## hmmm + +1. Uneven partition rule. +2. Whether each arity stage consumes the preceding stage output or composes independent + partitions before a later merge. +3. Exact thread split/recombine law. +4. Corpus/material extraction and binding law. +5. Nested gonol representation and reversible serialization. +6. Private-gonol generation and binding. +7. Public/private key derivation and the exact source of asymmetry. +8. Authentication, nonces, state evolution, truncation/replay handling. +9. Threat model and target security properties. From 9f22f74ca55f455421dc513b5124bbe71d83aabe Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:33:27 -0700 Subject: [PATCH 16/31] restore full Weave encryption architecture --- research/weave/BASE.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 research/weave/BASE.json diff --git a/research/weave/BASE.json b/research/weave/BASE.json new file mode 100644 index 00000000..4d9d97f2 --- /dev/null +++ b/research/weave/BASE.json @@ -0,0 +1,10 @@ +{ + "schema": "the-interdependency.stack-research-base", + "version": "1.0.0", + "project": "weave", + "source_repository": "The-Interdependency/stack", + "source_commit": "01f340ba5b4c5f107703233750768e201a41da68", + "canon_path": null, + "authority": "stack-local specification and research for Erin Spencer's full intended multi-layer encryption construction", + "standing": "stack-local-research" +} From 59877f82d91c36bc88e36253ee5f697b1dc5b8af Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:33:29 -0700 Subject: [PATCH 17/31] replace narrow Interlace workspace with Weave --- research/interlace/README.md | 93 ------------------------------------ 1 file changed, 93 deletions(-) delete mode 100644 research/interlace/README.md diff --git a/research/interlace/README.md b/research/interlace/README.md deleted file mode 100644 index b9d46a37..00000000 --- a/research/interlace/README.md +++ /dev/null @@ -1,93 +0,0 @@ -# Interlace Research - -Standing: **stack-local research; specification-first; no security claim**. - -This workspace exists to pursue Erin Spencer's intended encryption construction after -the retirement of URPCS. It is a new project. It does not inherit URPCS code, Laws -1–13, codec architecture, tests, measurements, security conclusions, or terminology. - -The project begins from the mechanisms Erin actually specified and keeps unresolved -mechanics unresolved until they are explicitly selected. - -## Preserved construction - -The current specification floor is: - -1. Operate on the plaintext as a raw bit sequence. -2. Use an ordered sequence of arity/division levels, with at least three levels. -3. At each declared level, divide the working bit sequence into the declared number - of sections; examples already given include fifths, sevenths, and thirds. -4. Within each section, interleave from the two ends: last bit, first bit, - next-to-last bit, next-from-first bit, continuing inward until the section is - exhausted. -5. Apply the declared sequence of arity levels without replacing the mechanism by - pairing, framing, hashing, authentication, a standard cipher mode, or another - familiar construction. -6. After the declared levels, apply the corresponding end-interleave to the whole - resulting bit sequence. -7. Reconstruction depends on knowing the division/arity choices, their order, and - how many levels were used. Those choices are therefore part of the intended - private reconstruction information unless a later explicit law says otherwise. - -These statements define the mechanism to investigate. They do **not** establish -confidentiality, entropy, pseudorandomness, key strength, resistance to known-plaintext -or chosen-plaintext attack, or production suitability. - -## Intended later layers - -Two related ideas are retained as intended research directions, but are not silently -folded into the core transform: - -- multiple interlaced threads, potentially three, five, seven, or more, with - caller-selected corpus/material associated with individual threads; -- preprocessing or binding plaintext through a hyperspace/gonol construction, with a - private gonol participating in recovery. - -Each requires its own explicit contract before implementation. Neither may be -invented from analogy to URPCS, PCEA, UCNS, or conventional cryptographic systems. - -## Non-inheritance boundary - -`research/urpcs/` is historical evidence of a substituted GPT-produced construction. -Nothing from it is an implementation dependency here. A result proved against URPCS -does not transfer into this workspace. - -If comparison with URPCS is ever useful, URPCS is treated only as a negative -specification-divergence witness: an example of what must not be substituted for the -declared construction. - -## Development order - -1. Freeze exact bit-level transformation laws. -2. Resolve only the minimum missing mechanics needed to make the transform invertible. -3. Write an executable reference transform with exhaustive small-input inverse tests. -4. Build an independently structured inverse from the written contract. -5. Measure information leakage and structural distinguishability before adding - authentication, key wrapping, gonol binding, or corpus-thread layers. -6. Add later layers one at a time, preserving ablation tests so their contribution can - be measured rather than presumed. -7. Only after adversarial cryptanalysis may the project make a bounded security claim. - -## Usage guidance - -Start with the specification, not code: - -```bash -cat research/interlace/SPECIFICATION.md -cat research/interlace/BASE.json -``` - -Before implementing a missing rule, update the specification so the rule is explicit -and attributable. An implementation must fail rather than choose an unresolved rule -for convenience. - -Do not use this workspace for protecting real secrets until a later security contract -and adversarial evidence explicitly authorize that use. - -## hmmm - -Exact handling of uneven section lengths, whether each arity stage consumes the prior -stage's output or independently re-partitions the original input, representation of the -private arity schedule, thread/corpus binding, hyperspace/gonol binding, authentication, -nonce/state requirements, and the threat model remain unresolved. Their absence is part -of the current specification and must not be filled by model preference. From 4a037342e5cc27bc1d9424d8be01342b5299d1c8 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:33:31 -0700 Subject: [PATCH 18/31] replace narrow Interlace workspace with Weave --- research/interlace/SPECIFICATION.md | 130 ---------------------------- 1 file changed, 130 deletions(-) delete mode 100644 research/interlace/SPECIFICATION.md diff --git a/research/interlace/SPECIFICATION.md b/research/interlace/SPECIFICATION.md deleted file mode 100644 index 9e6c9f26..00000000 --- a/research/interlace/SPECIFICATION.md +++ /dev/null @@ -1,130 +0,0 @@ -# Interlace — specification floor - -Status: **PRE-SPECIFICATION / PRESERVED MECHANISM**. - -This document records what is fixed, what is forbidden to substitute, and what remains -`hmmm`. It is deliberately smaller than an implementation specification. - -## 1. Objects - -- `B`: the input plaintext represented as an ordered bit sequence. -- `A = (a_1, ..., a_k)`: an ordered sequence of division arities. -- `k >= 3`: minimum declared number of arity levels. -- `I(S)`: end-interleave of one finite bit sequence `S`. - -For a sequence - -```text -S = s_0, s_1, ..., s_(n-1) -``` - -the preserved end-interleave order begins - -```text -s_(n-1), s_0, s_(n-2), s_1, ... -``` - -and continues inward until every bit appears exactly once. - -## 2. Declared transform skeleton - -For each arity level `a_i`: - -1. partition the working bit sequence into `a_i` ordered sections; -2. apply `I` independently to every section; -3. preserve all bits exactly once. - -After all declared arity levels, apply `I` once to the entire working sequence. - -Example arity sequence already specified in discussion: - -```text -(5, 7, 3) -``` - -The example is evidence of the mechanism, not a declaration that `(5,7,3)` is the -only or preferred schedule. - -## 3. Required invariants - -Any implementation claiming conformance must preserve all of these: - -- **bit conservation** — no bit is added, removed, duplicated, or changed by the core - interleaving transform; -- **order-sensitive arity schedule** — changing arity order is a different transform; -- **level-count sensitivity** — omitting or adding a level is a different transform; -- **section-local end interleave** — each section uses the declared last/first inward - operation; -- **whole-sequence final interleave** — the final operation acts across the resulting - complete bit sequence; -- **exact invertibility** — given all required reconstruction information, the original - bit sequence must be recovered exactly. - -## 4. Forbidden substitutions - -The following do not implement this specification merely because they are reversible or -cryptographic: - -- recursive pairing codecs; -- authenticated framing; -- substitution with AES, ChaCha, a Feistel network, XOR stream masking, or another - standard primitive; -- hashing the plaintext and treating the digest as the transform; -- replacing section interleaving with generic permutation generation; -- reducing the arity schedule to a conventional integer key without preserving its - specified structural role; -- importing URPCS Laws 1–13. - -Conventional primitives may later be composed around the construction only when their -role is separately declared. They may not replace the construction being tested. - -## 5. Falsification targets - -The first implementation must make it cheap to test: - -1. exhaustive inversion across small bit lengths and multiple schedules; -2. whether different schedules collide on the same permutation; -3. how much of the schedule can be recovered from known plaintext/ciphertext pairs; -4. whether the transform leaks bit-position relations or periodic structure; -5. whether repeated or highly structured plaintext remains visibly structured; -6. whether the effective permutation family grows meaningfully with arity depth; -7. whether thread, corpus, or hyperspace layers add independent security properties or - merely obscure the same permutation. - -Failure on these tests is useful evidence. It must not trigger replacement of the -mechanism with a familiar cipher. - -## 6. Later-layer boundary - -Potential later layers already contemplated: - -- three/five/seven-or-more interlaced streams or threads; -- caller-selected corpus/material per thread; -- plaintext-to-hyperspace/gonol preprocessing; -- a private gonol participating in recovery. - -None is part of the executable core until its own input, output, inverse, and security -claim are explicitly specified. - -## Usage guidance - -An implementer must read this document before writing transform code. For every -unresolved choice below, implementation should raise/refuse rather than select a -default. Tests should identify the exact specification revision they exercise. - -## hmmm - -1. **Uneven partition rule:** how `n mod a_i` bits are distributed when a bit length - is not divisible by the arity. -2. **Stage input rule:** whether level `i+1` partitions the output of level `i` or - independently partitions the original/raw bit sequence before a later composition. -3. **Schedule encoding:** how arities, order, and level count are represented and bound - to recovery. -4. **Thread construction:** exact relationship between sections, threads, and corpus - material. -5. **Hyperspace binding:** exact reversible relation among plaintext, gonol construction, - private gonol, and the core transform. -6. **Authentication/state:** whether integrity, nonces, state evolution, or replay - protection belong to the eventual system and at which layer. -7. **Threat model:** attacker capabilities and the minimum security properties the - construction is intended to provide. From 899058e4675efc62f8beb25cfadf2ffc532a6e6c Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:33:33 -0700 Subject: [PATCH 19/31] replace narrow Interlace workspace with Weave --- research/interlace/BASE.json | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 research/interlace/BASE.json diff --git a/research/interlace/BASE.json b/research/interlace/BASE.json deleted file mode 100644 index 872e1e96..00000000 --- a/research/interlace/BASE.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "schema": "the-interdependency.stack-research-base", - "version": "1.0.0", - "project": "interlace", - "source_repository": "The-Interdependency/stack", - "source_commit": "01f340ba5b4c5f107703233750768e201a41da68", - "canon_path": null, - "authority": "stack-local specification and research for Erin Spencer's intended multi-arity interleaving encryption construction", - "standing": "stack-local-research" -} From bf013c793e0e2d96c7f027d71c433348d52650f9 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:34:02 -0700 Subject: [PATCH 20/31] restore full Weave project scope --- README.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 97c3424d..4da26a20 100644 --- a/README.md +++ b/README.md @@ -102,14 +102,11 @@ multi-arity interleaving construction during GPT-assisted implementation. The re for the substitution is unresolved. Its tests and receipts apply only to that substituted codec and must not be used to validate or falsify the intended URPCS design. -The replacement research path is `research/interlace-encryption/`. It starts from the -actual declared mechanisms: ordered arity/division levels, section-local last/first -inward interleaving, and final whole-sequence interleaving. It deliberately contains no -URPCS implementation dependency and makes no security claim. +The replacement research path is `research/weave/`. It owns the full intended encryption construction: hyperspace/gonol plaintext representation, private-gonol recovery, multiple reconstruction-dependent threads, thread-associated corpus/material, multi-arity bit interleaving, and the eventual asymmetric public/private relation. The interleave is one layer, not the project identity. The workspace deliberately contains no URPCS implementation dependency and makes no security claim. ```bash -cat research/interlace-encryption/SPECIFICATION.md -cat research/interlace-encryption/BASE.json +cat research/weave/SPECIFICATION.md +cat research/weave/BASE.json ``` ### Change stack structure @@ -142,7 +139,7 @@ Python Gonol Construction is likewise stack-local and ungraduated; its Python 3. constructor is an implemented candidate, not stack or language canon. URPCS is retired; its retained vectors and replay evidence establish behavior only of the substituted historical codec. No URPCS claim may be inferred from them. -Interlace Encryption is new stack-local research and remains specification-first; no +Weave is new stack-local research and remains specification-first; no confidentiality or production-security standing is implied by its placement. Psychsocio metafauna and From Photons to the Macroverse remain stack-local pre-graduation research. EPAC has an independently published MPL-2.0 `v0.1.0` From 8256aa201fd502635245e75129e7baa7df49a159 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:34:04 -0700 Subject: [PATCH 21/31] restore full Weave agent boundary --- AGENTS.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index fc7cfb00..b855f116 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,11 +23,7 @@ projects may later graduate into their own repositories. substituted a recursive pairing/authenticated codec for Erin Spencer's intended multi-arity interleaving construction. Do not extend it or treat any passing test, vector, decoder audit, or measurement as evidence for the intended URPCS design. -- `research/interlace-encryption/` owns new Stack-local research into the intended - construction. Preserve the declared arity/division sequence, section-local last/first - inward interleave, and final whole-sequence interleave. Read `SPECIFICATION.md` before - implementation. Unresolved mechanics must fail closed as `hmmm`; do not substitute a - familiar cipher, codec, permutation generator, or URPCS mechanism. +- `research/weave/` owns new Stack-local research into the full intended encryption system. Preserve all declared layers: hyperspace/gonol plaintext construction, private-gonol recovery, multiple reconstruction-dependent threads, thread-associated corpus/material, multi-arity last/first interleaving, and the intended asymmetric public/private relation. Read `SPECIFICATION.md` before implementation. Unresolved mechanics must fail closed as `hmmm`; do not reduce the project to its interleave layer or substitute a familiar cipher, codec, permutation generator, or URPCS mechanism. - `research/zfae/` owns Stack-local inference-construction experiments. ZFAE retains conceptual authority, PTCNA owns neural construction, and a0 owns runtime integration. Keep a0-betatest comparisons separately attributed. @@ -142,7 +138,7 @@ coherence; it does not replace workspace behavioral tests. independent repository/release authority boundary; exact UCNS affixiation geometry is unresolved. - URPCS is retired for specification divergence. Why GPT substituted the different architecture remains `hmmm`; its retained evidence is historical and implementation-local. -- Interlace Encryption is specification-first research. Uneven partitions, stage-input +- Weave is specification-first research. Uneven partitions, stage-input composition, schedule encoding, thread/corpus binding, hyperspace/gonol binding, authentication/state, and the threat model remain `hmmm` until explicitly resolved. - The complete root `skill-lib/` snapshot refresh remains separate because the current From 30065389ab876770f73c7099114f33bf96afb1d7 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:34:06 -0700 Subject: [PATCH 22/31] rename full encryption participant to Weave --- stack-manifest.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stack-manifest.json b/stack-manifest.json index 936c71bb..51f37303 100644 --- a/stack-manifest.json +++ b/stack-manifest.json @@ -1,7 +1,7 @@ { "schema": "the-interdependency.stack-manifest", "version": "1.1.0", - "work_graph_sha256": "985d462de06bdf3c0e8cadfbac93d43f9cc72c82aca6712b6012512dea75350d", + "work_graph_sha256": "fa81adcbc37d2042bd6691857f3f97c26f8a16f89821bef66b8331df9553d251", "repositories": [ { "repository": "The-Interdependency/skill-lib", @@ -70,7 +70,7 @@ "Python Gonol Construction remains stack-local research without independent repository or release authority", "URPCS is retired historical evidence after GPT-assisted implementation diverged from Erin Spencer's intended multi-arity interleaving specification; why the substitution occurred remains unresolved", "skill-lib remains a special operational snapshot at stack root rather than following the libs/research pair", - "Interlace Encryption preserves the intended multi-arity interleaving mechanism, while uneven partitioning, stage-input composition, schedule encoding, thread/corpus binding, hyperspace/gonol binding, authentication/state, and threat model remain unresolved" + "Weave preserves the intended multi-arity interleaving mechanism, while uneven partitioning, stage-input composition, schedule encoding, thread/corpus binding, hyperspace/gonol binding, authentication/state, and threat model remain unresolved" ] }, "research_participants": [ @@ -195,10 +195,10 @@ "authority_transfer": false, "canonical_release": false, "commit": "01f340ba5b4c5f107703233750768e201a41da68", - "participant_id": "interlace-encryption", - "relation": "new stack-local specification and research for Erin Spencer's intended multi-arity interleaving encryption construction; no URPCS implementation inheritance and no confidentiality/security standing yet", + "participant_id": "weave", + "relation": "new stack-local specification and research for Erin Spencer's full intended multi-layer encryption construction: hyperspace/gonol plaintext representation, private-gonol recovery, reconstruction-dependent threads, corpus/material binding, multi-arity bit interleaving, and intended asymmetric key relation; no URPCS implementation inheritance and no security standing yet", "repository": "The-Interdependency/stack", - "workspace": "research/interlace-encryption/" + "workspace": "research/weave/" }, { "workspace": "research/english-gonol/", From 247af26527d0d76558dac1dd7fd05e41ce83112e Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 03:34:08 -0700 Subject: [PATCH 23/31] restore full Weave scope in human manifest --- STACK_MANIFEST.md | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/STACK_MANIFEST.md b/STACK_MANIFEST.md index 80942d12..e12465a2 100644 --- a/STACK_MANIFEST.md +++ b/STACK_MANIFEST.md @@ -14,11 +14,11 @@ Provenance and authority-boundary record for `The-Interdependency/stack`. - EPAC-derived carrier workspace separation UTC: `2026-09-18` at `545e135e2efbbcf29f033ab5530ac4876a68b718` - URPCS v1 workspace integration UTC: `2026-09-20` from Stack baseline `a428a41a38a8b30bacb7025a4d54070b228a8089` - URPCS retirement UTC: `2026-09-28`; specification divergence discovered after conversation-history review; retained implementation is historical evidence only -- Interlace Encryption workspace creation UTC: `2026-09-28`; new specification-first research starts from the intended multi-arity interleaving mechanism without URPCS inheritance +- Weave workspace creation UTC: `2026-09-28`; new specification-first research starts from the intended multi-arity interleaving mechanism without URPCS inheritance - English four-view complete-corpus audit UTC: `2026-09-22`, exact view source `1f9a35eb355296fc88d09784c7a3e2e95511ca31`; all 164,864 words, native and independent agreement. - Stack-manifest schema: `the-interdependency.stack-manifest` version `1.1.0` - Work-graph digest (SHA-256 over canonical `repositories` + `research_participants` + `boundaries` JSON): - `985d462de06bdf3c0e8cadfbac93d43f9cc72c82aca6712b6012512dea75350d` + `fa81adcbc37d2042bd6691857f3f97c26f8a16f89821bef66b8331df9553d251` - Machine-readable copy: [`stack-manifest.json`](stack-manifest.json) ## Directory contract @@ -63,7 +63,7 @@ release identity. | `research/epac/` | `The-Interdependency/stack` | `0e8384bbb60e4c2189016a212bdd0030d04aed7d` | historical forge evidence; active implementation consumed from the independent EPAC release | no | | `research/epac-derived-carrier/` | `The-Interdependency/stack` | `545e135e2efbbcf29f033ab5530ac4876a68b718` | active stack-local carrier audit consuming exact EPAC source; no EPAC implementation/public-contract or scientific standing transfer | no | | `research/urpcs/` | `The-Interdependency/stack` | `a428a41a38a8b30bacb7025a4d54070b228a8089` | retired historical evidence for the substituted recursive pairing/authenticated codec; not evidence for the intended URPCS construction | no | -| `research/interlace-encryption/` | `The-Interdependency/stack` | `01f340ba5b4c5f107703233750768e201a41da68` | new specification-first research for the intended multi-arity interleaving encryption construction; no URPCS implementation inheritance or security standing | no | +| `research/weave/` | `The-Interdependency/stack` | `01f340ba5b4c5f107703233750768e201a41da68` | new specification-first research for the intended multi-arity interleaving encryption construction; no URPCS implementation inheritance or security standing | no | | `research/english-gonol/` | `The-Interdependency/stack` | `99b3598b02a6e683b3c84184d8ea443b12fc0e1a` | stack-local English lexical/gonol construction separated from EDCM; full pinned-corpus v2 build/replay survived; consumes UCNS geometry; EDCM may evaluate outputs but does not define construction | no | | `research/python-gonol/` | `The-Interdependency/stack` | `0e8384bbb60e4c2189016a212bdd0030d04aed7d` | stack-local bottom-up Python 3.12 source gonol construction; applies METAPAT affixiation semantics, consumes optional UCNS geometry, and transfers no language authority to UCNS or EDCM | no | | `research/ucns/` | `The-Interdependency/ucns` | `1975fe70cf4e0826a8020c2da3047569e277af64` | explicit source base for integrated stack-local UCNS research; does not refresh or replace the manifest-pinned `libs/ucns` canonical view | no | @@ -131,11 +131,7 @@ construction. The reason for that substitution remains unresolved. All retained vectors, decoder evidence, and measurements describe only the substituted codec; they do not validate or falsify the intended URPCS design. -The intended construction now has a separate research owner at -`research/interlace-encryption/`. Its specification floor preserves ordered arity -levels, section-local last/first inward interleaving, and final whole-sequence -interleaving. The workspace starts with no implementation inheritance from URPCS and -no confidentiality or production-security claim. +The intended construction now has a separate research owner at `research/weave/`. Weave preserves the full system rather than naming only the interleave layer: hyperspace/gonol plaintext construction, private-gonol recovery, multiple reconstruction-dependent threads, thread-associated corpus/material, multi-arity bit interleaving, and the intended asymmetric public/private relation. The workspace starts with no implementation inheritance from URPCS and no confidentiality or production-security claim. ZFAE construction research lives at `research/zfae/`. Its exact research-only inputs are recorded above. The parser consumes the existing English GlyphGonol @@ -209,7 +205,7 @@ fixtures remain executable historical evidence for the substituted profile only. No result from that profile may be promoted to a claim about the intended URPCS construction. -Interlace Encryption is a new stack-local research component. It is not yet an +Weave is a new stack-local research component. It is not yet an independent repository, release, or security-reviewed cryptosystem. ## hmmm @@ -218,7 +214,7 @@ independent repository, release, or security-reviewed cryptosystem. - English Gonol Construction remains stack-local research; independent repository/release authority and the exact UCNS displacement law have not been established. - Python Gonol Construction remains stack-local research; independent repository/release authority and exact UCNS affixiation geometry remain unresolved. - URPCS is retired for specification divergence; why GPT flattened/substituted the intended construction remains unresolved, and retained evidence is scoped only to the substituted implementation. -- Interlace Encryption preserves the intended mechanism, while uneven partitioning, stage-input composition, schedule encoding, thread/corpus binding, hyperspace/gonol binding, authentication/state, and the threat model remain unresolved. +- Weave preserves the intended mechanism, while uneven partitioning, stage-input composition, schedule encoding, thread/corpus binding, hyperspace/gonol binding, authentication/state, and the threat model remain unresolved. - `skill-lib/` remains a special operational snapshot at stack root rather than following the ordinary `libs/` + `research/` pair. ## UCHC input candidate From ca1cdc8740990350c2daa2bfeb403a6e133e8e68 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 04:40:38 -0700 Subject: [PATCH 24/31] Record Weave source-bound evaluation scope without substituting the full design --- research/weave/PLAN.md | 74 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 research/weave/PLAN.md diff --git a/research/weave/PLAN.md b/research/weave/PLAN.md new file mode 100644 index 00000000..23840a6d --- /dev/null +++ b/research/weave/PLAN.md @@ -0,0 +1,74 @@ +# Weave source-bound evaluation, run 1 + +## Decision and whole-system boundary +Determine what the declared construction currently establishes, without replacing it. +The whole design includes nested hyperspace/gonol plaintext construction, a private +gonol required in recovery, multiple related streams, corpus/material participation, +section-local last/first interleaving, final interleaving and the intended asymmetric +public/private relation. A result on one operation is not a result on that whole. + +## Inputs frozen before execution +- Stack PR 62 head: 247af26527d0d76558dac1dd7fd05e41ce83112e. +- Its Weave directory contains BASE.json, README.md and SPECIFICATION.md; no implementation. +- UCHC hyperspace_construct.py blob: 8b55823805c87ad8c4cc9d7451dc2eb90bdedd3a. +- User's literal interleave: last, first, next-last, next-first, continuing inward; + section arities illustrated by 5, 7, 3, followed by interleaving the whole. +- User's 'arity three, minimum' does not establish a minimum of three stages. + +## Explicit experimental choices, not additional user laws +The composed-operation profile feeds one stage's output to the next, retains section +order, and uses explicitly supplied positive section lengths. Equal-partition cases +use lengths divisible by every selected arity: no invented remainder allocation. +Empty input is tested for the end-interleave primitive alone. Empty sections and +partial partition rules are not silently selected. + +The independent inverse uses a closed-form position formula, not the encoder's +implementation or a permutation exported by it. None of these operations is named +'encrypt', 'decrypt', 'gonol', 'keygen', or a complete Weave implementation. + +## Frozen checks and evidence domain +1. Exhaust all 8,191 binary inputs of lengths 0 through 12 for the end operation. +2. Exhaust all positive ordered partitions of lengths 3 through 12 with at least + three parts. Distinct position labels test bijection on every position, implying + the same recovery for any values occupying those positions. +3. Enumerate all schedules over (3,5,7) of lengths 1 through 8 on 105 positions. + Compare exact induced maps, record collisions and stage periods. Distinct + schedules are not presumed to define distinct maps. +4. Execute the stated (5,7,3) sequential profile on lengths 105, 210, 420, 840, + 8,400 and 67,200. Preserve position witnesses and exact inversion. +5. Attack the fixed-map profile at lengths 105, 840 and 8,400 using binary position + labels and no access to the schedule in the attack function. Confirm inferred + inverse on 64 held-out generated bitstrings per length. This attack assumes the + same positional map across queries. No transfer to message-dependent maps or + the unimplemented complete system. +6. Check weight preservation and constant-input witnesses. State the algebraic + scope: rearranging bits, not the complete gonol/corpus/private-key construction. +7. Exercise refusal of malformed inputs and missing whole-system implementation. + Readiness is not tested cryptographic strength; no substitute adapter is used. + +## Preflight and terminal condition +Python standard library only, deterministic fixtures, no network, no secrets, no +external paid API. The largest enumerated table is 9,840 maps on 105 positions. +Expected memory is well within this container's available memory; output is small. +Finish the complete declared finite domains or report execution failure. There is no +scientific wall-clock stopping rule. SHA-256 identifies evidence, not encryption. + +## Failure attribution +- A runtime disagreement in literal end-interleaving: implementation defect until + independently reproduced against the written law. +- A schedule collision: falsifies assistant-added schedule-uniqueness claims, not + the user's whole design. +- Fixed-map attack succeeds: that profile supplies no confidentiality against the + declared attack. It says nothing decisive about the absent required relations. +- Missing native relation: BLOCKED for full execution, never FALSIFIED. + +## Usage +Run `python probe.py > receipt.json`; run again and compare the exact output bytes. +Read REPORT.md with the receipt. Do not interpret a component pass as system approval. + +## hmmm +Original thirteen-law conversation export was not recovered. The retrieved uploaded +URPCS law files describe the retired authenticated codec, not the intended encryption. +Thread/corpus original details are present here only as conversation context, not a +recovered exact transcript. Public/private-gonol binding and full composition are not +implemented in the inspected Weave directory. No replacement has been invented. From a6ada384b474a41b1eec101444abe4fe7c56d743 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 04:41:39 -0700 Subject: [PATCH 25/31] Add executed literal Weave component probes with explicit whole-design nonclaims --- research/weave/probe.py | 340 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 340 insertions(+) create mode 100644 research/weave/probe.py diff --git a/research/weave/probe.py b/research/weave/probe.py new file mode 100644 index 00000000..ae2eb456 --- /dev/null +++ b/research/weave/probe.py @@ -0,0 +1,340 @@ +#!/usr/bin/env python3 +"""Weave evidence runner: literal operations, not a substitute cryptosystem. + +Usage: python probe.py > receipt.json + python probe.py --check receipt.json +Python standard library only. The frozen scope and cases are in PLAN.md. +Network/auth/user-secret boundaries: none. Storage: stdout, or read-only --check. +Rollout: manually invoked research evidence. Rollback: remove this runner and +its unaccepted receipt; do not alter any upstream geometry or old sealed evidence. +Scientific criteria: PLAN.md. Full-system state is always reported separately. +""" +from __future__ import annotations + +import argparse +from collections import deque +import hashlib +import itertools +import json +from math import gcd +from pathlib import Path +import random +import sys +from typing import Callable, Sequence, TypeVar + +T = TypeVar("T") +Partitions = tuple[tuple[int, ...], ...] + + +def require(condition: bool, detail: str) -> None: + """Raise on a failed witness even when Python assertions are optimized out.""" + if not condition: + raise ValueError(detail) + + +def inward(items: Sequence[T]) -> tuple[T, ...]: + """Literal user operation: rightmost, leftmost, and continue inward.""" + remaining = deque(items) + out: list[T] = [] + while remaining: + out.append(remaining.pop()) + if remaining: + out.append(remaining.popleft()) + return tuple(out) + + +def inverse_inward(items: Sequence[T]) -> tuple[T, ...]: + """Independently structured inverse, using the analytic index relation.""" + n = len(items) + return tuple(items[2*i + 1] if i < n//2 else items[2*(n-1-i)] + for i in range(n)) + + +def check_partition(lengths: tuple[int, ...], n: int) -> None: + """Require every boundary explicitly; invent no remainder or empty-section rule.""" + require(isinstance(lengths, tuple), "partition must be an immutable tuple") + require(len(lengths) >= 3, "this explicit experiment uses arities >= 3") + require(all(type(v) is int and v > 0 for v in lengths), + "section lengths must be positive non-Boolean integers") + require(sum(lengths) == n, "section lengths do not cover the input exactly") + + +def section_stage(items: Sequence[T], lengths: tuple[int, ...], *, + reverse: bool = False) -> tuple[T, ...]: + """Apply exactly one section operation, preserving explicit section order.""" + check_partition(lengths, len(items)) + transform = inverse_inward if reverse else inward + offset = 0 + out: list[T] = [] + for length in lengths: + out.extend(transform(items[offset:offset+length])) + offset += length + return tuple(out) + + +def forward(items: Sequence[T], partitions: Partitions) -> tuple[T, ...]: + """Explicit sequential component profile; this is not Weave encryption.""" + require(isinstance(partitions, tuple) and len(partitions) > 0, + "supply an explicit nonempty stage sequence") + out = tuple(items) + for lengths in partitions: + out = section_stage(out, lengths) + return inward(out) + + +def backward(items: Sequence[T], partitions: Partitions) -> tuple[T, ...]: + """Undo final interleave, then invert all supplied stages in reverse order.""" + require(isinstance(partitions, tuple) and len(partitions) > 0, + "supply an explicit nonempty stage sequence") + out = inverse_inward(items) + for lengths in reversed(partitions): + out = section_stage(out, lengths, reverse=True) + return out + + +def equal_partitions(n: int, schedule: tuple[int, ...]) -> Partitions: + """Experimental profile only: exact equal division; refuse all remainders.""" + require(type(n) is int and n > 0, "positive non-Boolean length required") + require(isinstance(schedule, tuple) and len(schedule) > 0, "empty schedule") + result = [] + for arity in schedule: + require(type(arity) is int and arity >= 3, "arity must be an integer >= 3") + require(n % arity == 0, "uneven partition remains unselected") + result.append((n//arity,) * arity) + return tuple(result) + + +def bits(value: int, n: int) -> tuple[int, ...]: + """Synthetic test data, not plaintext admission to the native gonol layer.""" + return tuple((value >> i) & 1 for i in range(n)) + + +def digest(value: object) -> str: + """Evidence identity only; never a key derivation or confidentiality step.""" + return hashlib.sha256(json.dumps(value, sort_keys=True, + separators=(",", ":")).encode()).hexdigest() + + +def permutation_order(permutation: tuple[int, ...]) -> int: + """Exact least positive period from the complete disjoint cycle lengths.""" + require(sorted(permutation) == list(range(len(permutation))), "not bijective") + seen: set[int] = set() + result = 1 + for start in range(len(permutation)): + if start in seen: + continue + current, length = start, 0 + while current not in seen: + seen.add(current) + current = permutation[current] + length += 1 + result = result * length // gcd(result, length) + return result + + +def recover_fixed_map(oracle: Callable[[tuple[int, ...]], tuple[int, ...]], + n: int) -> tuple[tuple[int, ...], int]: + """Attack receives only an oracle and length, never the arity schedule. + + Bit j of the i-th input position encodes i's j-th binary digit. Reassemble + these labels at each output position. The attack requires a fixed positional + map across its queries; it is not applied to the unimplemented full design. + """ + labels = [0] * n + query_count = (n-1).bit_length() + for digit in range(query_count): + answer = oracle(tuple((i >> digit) & 1 for i in range(n))) + require(len(answer) == n, "oracle changed length") + require(all(type(v) is int and v in (0, 1) for v in answer), "oracle not bits") + for i, value in enumerate(answer): + labels[i] |= value << digit + require(sorted(labels) == list(range(n)), + "probe observations do not identify a fixed positional bijection") + return tuple(labels), query_count + + +def recover_with_map(output: Sequence[T], mapping: tuple[int, ...]) -> tuple[T, ...]: + """Use the attack's inferred map, without any schedule or private state.""" + require(len(output) == len(mapping), "map length mismatch") + positions = sorted(range(len(mapping)), key=mapping.__getitem__) + return tuple(output[i] for i in positions) + + +def run() -> dict[str, object]: + """Execute all preregistered finite domains; no skipped assertions or partial pass.""" + exhaustive_binary = 0 + for n in range(13): + for value in range(1 << n): + data = bits(value, n) + require(inverse_inward(inward(data)) == data, "end operation inverse") + exhaustive_binary += 1 + + partition_cases = 0 + for n in range(3, 13): + for mask in range(1 << (n-1)): + boundaries = [0] + [i+1 for i in range(n-1) if mask & (1 << i)] + [n] + lengths = tuple(b-a for a, b in zip(boundaries, boundaries[1:])) + if len(lengths) < 3: + continue + data = tuple(range(n)) + encoded = section_stage(data, lengths) + require(sorted(encoded) == list(data), "section bijection") + require(section_stage(encoded, lengths, reverse=True) == data, + "section independent inverse") + require(backward(forward(data, (lengths,)), (lengths,)) == data, + "final whole interleave inverse") + partition_cases += 1 + + n = 105 + maps: dict[tuple[int, ...], tuple[int, ...]] = {} + collision_examples: list[dict[str, object]] = [] + total_schedules = 0 + by_depth = [] + # Only source-labelled inputs to the direct operation generate these maps. + # No generic permutation generator stands in for the mechanism. + for depth in range(1, 9): + depth_maps: set[tuple[int, ...]] = set() + for schedule in itertools.product((3, 5, 7), repeat=depth): + partitions = equal_partitions(n, schedule) + mapping = forward(tuple(range(n)), partitions) + require(backward(mapping, partitions) == tuple(range(n)), "schedule inverse") + if mapping in maps and len(collision_examples) < 5: + first = maps[mapping] + collision_examples.append({"first": first, "second": schedule, + "map_sha256": digest(mapping)}) + else: + maps.setdefault(mapping, schedule) + depth_maps.add(mapping) + total_schedules += 1 + by_depth.append({"depth": depth, "schedules": 3**depth, + "distinct_at_depth": len(depth_maps), + "distinct_up_to_depth": len(maps)}) + periods = {str(a): permutation_order(section_stage(tuple(range(n)), (n//a,)*a)) + for a in (3, 5, 7)} + + # A constructive collision exists at every finite stage period, regardless + # of whether the bounded schedule census reaches that period. + period_witnesses = [] + for arity in (3, 5, 7): + period = periods[str(arity)] + first = (5, 7, 3) + second = first + (arity,) * period + left = forward(tuple(range(n)), equal_partitions(n, first)) + right = forward(tuple(range(n)), equal_partitions(n, second)) + require(left == right, "cycle-period equivalent schedule witness") + period_witnesses.append({"arity": arity, "period": period, + "first": first, "second": second, + "exact_maps_equal": True, "map_sha256": digest(left)}) + + scale_cases = [] + for length in (105, 210, 420, 840, 8400, 67200): + partitions = equal_partitions(length, (5, 7, 3)) + data = tuple(range(length)) + encoded = forward(data, partitions) + require(backward(encoded, partitions) == data, "large independent recovery") + scale_cases.append({"bits": length, "recovered_exactly": True, + "map_sha256": digest(encoded)}) + + attack_cases = [] + weight_cases = 0 + for length in (105, 840, 8400): + partitions = equal_partitions(length, (5, 7, 3)) + def oracle(x: tuple[int, ...]) -> tuple[int, ...]: + return forward(x, partitions) + mapping, queries = recover_fixed_map(oracle, length) + rng = random.Random(20260928 + length) # Test fixture only, not cryptographic entropy. + for _ in range(64): + data = tuple(rng.randrange(2) for _ in range(length)) + output = oracle(data) + require(recover_with_map(output, mapping) == data, "held-out map attack") + require(sum(output) == sum(data), "permutation weight invariant") + weight_cases += 1 + for constant in (0, 1): + data = (constant,) * length + require(oracle(data) == data, "constant input invariant") + attack_cases.append({"bits": length, "oracle_queries": queries, + "held_out_recoveries": 64, "schedule_given_to_attacker": False, + "actual_schedule_recovered": False, + "equivalent_inverse_recovered": True, + "map_sha256": digest(mapping)}) + + rejected = 0 + invalid = [lambda: equal_partitions(8, (3,)), lambda: equal_partitions(105, ()), + lambda: equal_partitions(105, (True,)), lambda: equal_partitions(105, (2,)), + lambda: section_stage((0, 1, 2), (1, 1, 0)), + lambda: section_stage((0, 1, 2), (1, 1, 2)), + lambda: section_stage((0, 1, 2), (True, 1, 1)), + lambda: forward((0, 1, 2), ())] + for example in invalid: + try: + example() + except ValueError: + rejected += 1 + else: + raise ValueError("invalid experimental input silently accepted") + + root = Path(__file__).resolve().parent + sources = {name: hashlib.sha256((root/name).read_bytes()).hexdigest() + for name in ("probe.py", "PLAN.md")} + return { + "schema": "weave.source-bound-evaluation", "version": "0.1.0", + "source_inputs": {"stack_head": "247af26527d0d76558dac1dd7fd05e41ce83112e", + "uchc_inspected_blob": "8b55823805c87ad8c4cc9d7451dc2eb90bdedd3a", + "local_sha256": sources}, + "execution": {"status": "COMPLETED", "skipped_checks": 0, + "python_requirement": ">=3.10", "dependencies": "stdlib only"}, + "full_design": {"classification": "BLOCKED_NOT_EXECUTED", + "validated": False, "falsified": False, + "why": "No retrieved executable binding for private-gonol recovery, thread/corpus relation and public/private key relation.", + "not_substituted": ["gonol construction", "private gonol", "threads", + "corpus binding", "asymmetric key relation"]}, + "profile_choices": {"stage_input": "previous-stage output: explicit experimental interpretation", + "section_order": "preserved: explicit experimental interpretation", + "remainders": "refused, not given a default", + "minimum_stage_count_claim": "none; arity is not depth", + "whole_system_claims": False}, + "inversion": {"classification": "SURVIVED_IN_DECLARED_COMPONENT_DOMAIN", + "exhaustive_binary_inputs": exhaustive_binary, + "all_positive_partitions_with_at_least_three_parts_through_n12": partition_cases, + "scale_cases": scale_cases}, + "schedules": {"length_bits": n, "arities": [3, 5, 7], + "depth_range_inclusive": [1, 8], "tested": total_schedules, + "distinct_maps": len(maps), "by_depth": by_depth, + "first_collision_examples": collision_examples, + "single_stage_periods": periods, + "exact_period_collision_witnesses": period_witnesses, + "claim": "Different schedules need not induce different maps; no whole-design verdict."}, + "fixed_map_attack": {"classification": "EQUIVALENT_INVERSE_RECOVERED_FOR_FIXED_MAP_PROFILE", + "assumption": "same length-preserving position map for all oracle calls", + "cases": attack_cases, + "not_tested": ["message-dependent transformation", "changing map per encryption", "full Weave"]}, + "bit_only_invariants": {"weight_checks": weight_cases, + "all_zero_and_all_one_fixed": True, + "scope": "bit rearrangement only, not unspecified gonol/corpus operations"}, + "input_refusals": {"rejected": rejected, "total": len(invalid)}, + "hmmm": ["Original pre-substitution thirteen-law transcript not recovered.", + "Private-gonol recovery binding remains unimplemented in inspected Weave source.", + "Native hyperspace producer inspected, not executed against its full corpus.", + "All required full-design relations remain in scope; these component results do not replace them."]} + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--check", type=Path, help="recompute and compare a saved receipt byte-for-byte") + args = parser.parse_args() + try: + result = run() + data = (json.dumps(result, indent=2, sort_keys=True) + "\n").encode() + if args.check is not None: + require(args.check.read_bytes() == data, "receipt differs from complete replay") + print("receipt replay: exact match; whole-design status remains BLOCKED_NOT_EXECUTED") + else: + sys.stdout.buffer.write(data) + except (OSError, ValueError) as exc: + print(f"EVALUATION_ERROR: {exc}", file=sys.stderr) + return 1 + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) From e4810ca8db0f81d59f895ffccb36575b4dc79a5d Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 04:42:06 -0700 Subject: [PATCH 26/31] Add separately structured replay verifier for Weave component evidence --- research/weave/verify.py | 98 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 research/weave/verify.py diff --git a/research/weave/verify.py b/research/weave/verify.py new file mode 100644 index 00000000..30ba7e87 --- /dev/null +++ b/research/weave/verify.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +"""Independent implementation of the positional checks; does not import probe.py. +Usage: python verify.py receipt.json > verified.json +Reads local source/receipt bytes; no network, no secrets, no system write except stdout. +Owner: Erin Spencer's Stack research. Rollback: remove this evidence verifier. +This is a second implementation by the same assistant, not an independent author review. +""" +from __future__ import annotations +import hashlib +import itertools +import json +from pathlib import Path +import sys + + +def must(test: bool, message: str) -> None: + if not test: + raise ValueError(message) + + +def sha(value: object) -> str: + return hashlib.sha256(json.dumps(value, sort_keys=True, + separators=(",", ":")).encode()).hexdigest() + + +def end_map(n: int) -> tuple[int, ...]: + # Analytic forward index at output j; no deque and no encoder import. + return tuple(n-1-j//2 if j % 2 == 0 else j//2 for j in range(n)) + + +def transform_map(n: int, arities: tuple[int, ...]) -> tuple[int, ...]: + p = tuple(range(n)) + for arity in arities: + must(n % arity == 0, "not equal partition") + width = n // arity + local = end_map(width) + q = tuple((j//width)*width + local[j % width] for j in range(n)) + p = tuple(p[index] for index in q) + return tuple(p[index] for index in end_map(n)) + + +def main() -> int: + path = Path(sys.argv[1] if len(sys.argv) > 1 else "receipt.json").resolve() + r = json.loads(path.read_text()) + root = path.parent + for name, expected in r["source_inputs"]["local_sha256"].items(): + must(hashlib.sha256((root/name).read_bytes()).hexdigest() == expected, + f"source mismatch: {name}") + must(end_map(5) == (4, 0, 3, 1, 2), "literal odd golden vector") + must(end_map(6) == (5, 0, 4, 1, 3, 2), "literal even golden vector") + must(transform_map(6, (3,)) == (4, 1, 5, 0, 2, 3), "three-section golden vector") + seen: set[tuple[int, ...]] = set() + count = 0 + for depth, recorded in enumerate(r["schedules"]["by_depth"], start=1): + at_depth = {transform_map(105, schedule) + for schedule in itertools.product((3, 5, 7), repeat=depth)} + seen.update(at_depth) + count += 3**depth + must(recorded["distinct_at_depth"] == len(at_depth), "depth census mismatch") + must(recorded["distinct_up_to_depth"] == len(seen), "cumulative census mismatch") + must(count == r["schedules"]["tested"] == 9840, "schedule coverage mismatch") + must(len(seen) == r["schedules"]["distinct_maps"], "map count mismatch") + for collision in (r["schedules"]["first_collision_examples"] + + r["schedules"]["exact_period_collision_witnesses"]): + p = transform_map(105, tuple(collision["first"])) + q = transform_map(105, tuple(collision["second"])) + must(p == q, "false schedule collision") + must(sha(p) == collision["map_sha256"], "collision map digest mismatch") + for case in r["inversion"]["scale_cases"]: + must(sha(transform_map(case["bits"], (5, 7, 3))) == case["map_sha256"], + "large map mismatch") + for case in r["fixed_map_attack"]["cases"]: + must(case["oracle_queries"] == (case["bits"]-1).bit_length(), "query count") + must(sha(transform_map(case["bits"], (5, 7, 3))) == case["map_sha256"], + "attack inferred map differs from independently constructed map") + orders = {transform_map(105, order) for order in itertools.permutations((3, 5, 7))} + must(len(orders) == 6, "example stage orders unexpectedly coincide") + must(r["full_design"]["classification"] == "BLOCKED_NOT_EXECUTED" and + not r["full_design"]["validated"] and not r["full_design"]["falsified"], + "unsupported whole-system verdict") + out = {"verification": "SURVIVED_SECOND_IMPLEMENTATION", + "same_author": True, "independent_author_review": False, + "imports_primary_runner": False, + "receipt_sha256": hashlib.sha256(path.read_bytes()).hexdigest(), + "verifier_sha256": hashlib.sha256(Path(__file__).read_bytes()).hexdigest(), + "schedules_recomputed": count, "distinct_maps": len(seen), + "distinct_orderings_of_3_5_7": len(orders), + "full_design_verdict": "NOT_EVALUATED"} + print(json.dumps(out, indent=2, sort_keys=True)) + return 0 + + +if __name__ == "__main__": + try: + raise SystemExit(main()) + except (OSError, ValueError, KeyError) as exc: + print(f"VERIFICATION_ERROR: {exc}", file=sys.stderr) + raise SystemExit(1) From 1d0ee7cddc984f54380f090129a2aaff54dbb65f Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 04:42:44 -0700 Subject: [PATCH 27/31] Publish executed Weave component results without promoting them to a full-system verdict --- research/weave/REPORT.md | 172 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 research/weave/REPORT.md diff --git a/research/weave/REPORT.md b/research/weave/REPORT.md new file mode 100644 index 00000000..52c20a06 --- /dev/null +++ b/research/weave/REPORT.md @@ -0,0 +1,172 @@ +# Weave — first source-bound results + +**Full-design verdict: not established.** These are executed results for the specified +interleaving operation and an explicitly declared sequential composition profile. +The nested gonol, private-gonol, thread/corpus and asymmetric relations remain part of +the required design. They were neither simulated with substitutes nor evaluated by +transferring a result from the interleave. This is partial evidence, not completion of +the requested full-system assessment. + +## Executed results + +The literal last/first inward operation has an exact inverse. It passed all **8,191 +binary inputs of lengths 0 through 12**. Section-local operation and its inverse +passed **4,017 ordered positive partitions**: every partition of lengths 3 through 12 +having at least three sections. Position-labelled tests prove each tested map is a +bijection for any bit values placed at those positions, not just one test plaintext. + +The sequential `(5,7,3)` profile, including its final whole-sequence interleave, +recovered every position exactly at **105, 210, 420, 840, 8,400 and 67,200 bits**. +No one-byte implementation limit was introduced. Uneven section sizes are supported +when supplied explicitly; no remainder-allocation policy was invented. + +At 105 bits, **all six orderings of the illustrated arities 3, 5 and 7 produce +different maps**. Thus order has a demonstrated effect in that declared domain. + +## Exact inverse + +For `y = I(x)`, input length `n` and valid output indices: + +```text +y[2r] = x[n - 1 - r] +y[2r+1] = x[r] + +x[i] = y[2i+1] when i < floor(n/2) +x[i] = y[2(n-1-i)] otherwise +``` + +The two index families cover every input position exactly once. This derivation +holds for any finite length, including the odd-length centre. Inverting each known +section reverses a stage; undoing the final interleave and then the stages in reverse +order reverses the explicitly sequential profile. + +## Schedule equivalences + +The complete predeclared census examined all **9,840 schedules** over `(3,5,7)` with +one through eight stages at 105 bits. It found **9,727 distinct positional maps**. +All 363 descriptions through depth five were distinct in this domain; repeated maps +first appeared at depth six. + +These schedules produce exactly the same map at 105 bits: + +```text +(5,7,3) +(5,7,3,7,7,7,7,7) +``` + +Consequently their outputs agree for **every** 105-bit input under the declared +equal-partition sequential profile. Five applications of the arity-seven stage +restore all positions. Exact single-stage periods here: **35 for arity 3, 7 for +arity 5, and 5 for arity 7**. + +Repeated arities were an experimental choice, not a recovered rule requiring your +design to permit them. The result falsifies the assistant-added universal claim that +changing stage count necessarily changes the transformation. It does not falsify +Weave, prescribe a key policy, or equate schedule counts with key strength. + +## Fixed-map attack + +For the fixed `(5,7,3)` profile, an attack given only input/output access and message +length recovered an equivalent inverse: + +| Message length | Chosen input queries | Held-out messages recovered | +|---|---:|---:| +| 105 bits | 7 | 64 of 64 | +| 840 bits | 10 | 64 of 64 | +| 8,400 bits | 14 | 64 of 64 | + +The attacker never receives the schedule. Query `j` places bit `j` of each position's +binary index at that position. Returned bits reconstruct the indices in output order. +The result is an **equivalent inverse**, not recovery of the actual schedule. + +**Assumption:** one fixed length-preserving positional map across queries and held-out +messages. No result is claimed for message-dependent maps, changing maps per encryption, +or the complete Weave composition. + +If a proposed composition of threads and corpus operations ultimately does nothing +but apply one fixed bit permutation, this argument extends by algebra. Whether the +full intended construction belongs to that class has **not** been established. + +Bit rearrangement also preserves the number of ones. All-zero and all-one inputs +remain unchanged. Constant witnesses and 192 held-out weight checks were executed. +This scope excludes unspecified gonol encoding or corpus transformations that may +change representation or values. The full ciphertext was not tested for randomness. + +## Whole-design coverage + +| Required part | Actual evidence | +|---|---| +| Nested hyperspace/gonol construction | The real UCHC module was located and inspected. Its glyph, word and definition promotion/recovery code exists. Its full corpus was not replayed. | +| Private gonol required in recovery | Requirement preserved. No executable Weave binding was present in the inspected workspace. No hash, scalar, password or generic tree was substituted. | +| Multiple related threads | Preserved. No recovered split/recombination law was executed; no round-robin or secret-sharing substitute was selected. | +| Thread-associated corpus/material | Preserved. No corpus was selected on the user's behalf; no filename hash or decorative role was substituted. | +| Section-local interleave | Literal operation implemented and tested; explicit partitions retained. | +| Final whole interleave | Executed on the composed-operation profile, not represented as a full ciphertext test. | +| Asymmetric public/private relation | Not executed: no retrieved complete forward/public and inverse/private binding. Missing implementation is not mathematical impossibility. | + +At inspected Stack head `247af26527d0d76558dac1dd7fd05e41ce83112e`, `research/weave/` +contained only `BASE.json`, `README.md` and `SPECIFICATION.md`. The full algorithm was +not implemented there. This is a source finding, not a claim that the user never +explained the missing relations. + +The UCHC source inspected was `human/english/english_gonol/hyperspace_construct.py`, +Git blob `8b55823805c87ad8c4cc9d7451dc2eb90bdedd3a`. Its +`promote_word(db, word_id)` and `recover_word(db, word_id)` operate on constructed +corpus records. They are real construction/recovery functions, not a supplied +private-gonol encryption binding. + +## Corrections to assistant-authored requirements + +“Arity three, minimum” does not say “at least three stages.” The assistant imposed +`k >= 3` without source support. Stage count and section arity must remain distinct. + +The earlier specification prescribed schedule-order and stage-count sensitivity as +blanket invariants while also asking whether schedules collide. Retain the supplied +order/count exactly and measure induced equivalence; do not reject a faithful +implementation because it finds a collision. The full architecture remains in scope. + +## Reproduce and verify + +`probe.py` uses a deque for the literal operation and a separate index formula for +its inverse. `verify.py` does not import it; a second index-composition implementation +recomputes all 9,840 schedule maps, digests, exact collision witnesses, example stage +orders and literal odd/even/three-section golden vectors. Both implementations were +written by the same assistant. This is **not an independent author's review**. + +Isolated-mode and optimized-Python replays matched the receipt exactly. Both checkers +rejected a deliberately altered map count with exit status 1. These are evidence +integrity checks, not authenticated encryption. + +From `research/weave/`: + +```bash +python probe.py > receipt.json +python probe.py --check receipt.json +python verify.py receipt.json > verified.json +``` + +Expected SHA-256 of the exact receipt bytes: + +```text +0c66b2dc2a6b36a00969d7e3c1421cacd44dbd7082bcdf4c5b79f7403f0226c3 +``` + +The runtime uses Python's standard library only. Hashes identify source and evidence; +they do not supply encryption. `PLAN.md` was written before the first local run. The +separate verifier and tamper checks were added afterward, and are subsequent +verification rather than retroactively preregistered discoveries. + +## Sources and provenance + +- Stack source at the inspected head: [Weave source](https://github.com/The-Interdependency/stack/tree/247af26527d0d76558dac1dd7fd05e41ce83112e/research/weave). +- UCHC producer: [hyperspace_construct.py](https://github.com/The-Interdependency/uchc/blob/main/human/english/english_gonol/hyperspace_construct.py), identified above by exact Git blob. +- Original user last/first and private-gonol statements were recovered from conversation context; PLAN.md distinguishes them from experimental choices. +- Retrieved Library URPCS law files describe the retired authenticated codec and were excluded as authorities for the desired encryption. + +## hmmm + +The original pre-substitution thirteen-law conversation was not recovered. Precise +thread/corpus rules and private-gonol/public-key binding were not recovered as an +executable contract. Those are retrieval/implementation boundaries, not a verdict +against the idea. Until the actual composition can be run, **neither a pass nor a +failure of the full design is supported**. No substitute result closes that gap. From c1fb87008ac2d4af90cbea34e06a81f61c912336 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 04:43:29 -0700 Subject: [PATCH 28/31] Remove assistant-invented stage minimum and unsupported schedule-uniqueness requirements --- research/weave/SPECIFICATION.md | 36 +++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/research/weave/SPECIFICATION.md b/research/weave/SPECIFICATION.md index 53f88e8d..38728f80 100644 --- a/research/weave/SPECIFICATION.md +++ b/research/weave/SPECIFICATION.md @@ -6,6 +6,9 @@ This document records the construction that must survive implementation. It sepa fixed architecture from unresolved mechanics. An unresolved mechanic must remain `hmmm`; an implementer may not replace the architecture to make the problem easier. +Executed evidence and its exact scope are recorded in [REPORT.md](REPORT.md). +That evidence is not a full-system verdict. + ## 1. System layers Weave currently comprises these intended layers: @@ -35,13 +38,18 @@ continuing inward until every bit appears exactly once. For an ordered arity schedule ```text -A = (a_1, ..., a_k), k >= 3 +A = (a_1, ..., a_k) ``` each level partitions the relevant working sequence into `a_i` ordered sections and applies `I` independently to each section. After the declared levels, `I` is applied to the complete resulting sequence. +Stage count and section arity are distinct. The user's phrase “arity three, minimum” +does not establish `k >= 3`. The prior minimum of three stages was an unsupported +assistant addition and is removed. Experiments must state their stage counts and +arity interpretation explicitly rather than promote them to new user requirements. + A previously stated example schedule is: ```text @@ -105,7 +113,7 @@ The public/private derivation law is not yet fixed. Existing standard primitives be used later only in explicitly scoped supporting roles; they may not stand in for the missing Weave relation. -## 7. Required invariants +## 7. Required invariants and measured relations Any complete Weave profile must eventually demonstrate: @@ -113,13 +121,17 @@ Any complete Weave profile must eventually demonstrate: - failure or materially incomplete recovery when required structural components are absent; - bit conservation wherever a layer is specified as a permutation; -- order sensitivity of the declared arity schedule; -- level-count sensitivity; +- exact preservation of supplied arity order and stage count; equivalences between + different schedules are measured, not forbidden by an invented uniqueness law; - dependence on the declared thread relation; - dependence on the declared corpus/material relation if that layer is enabled; - dependence on the private gonol/private-key relation; - no hidden inheritance from URPCS. +A different schedule description need not induce a different positional map. +[REPORT.md](REPORT.md) records exact counterexamples for the explicit sequential +component profile. They do not establish a verdict on the full construction. + ## 8. Forbidden flattening The following are specification failures if used as replacements rather than explicitly @@ -161,11 +173,21 @@ Implement one explicitly versioned profile at a time, but every profile must sta Weave layers it includes and excludes. A profile omitting a required layer is a layer test, not a Weave security result. +To reproduce the executed component evidence, run from this directory: + +```bash +python probe.py > receipt.json +python probe.py --check receipt.json +python verify.py receipt.json +``` + ## hmmm -1. Uneven partition rule. +1. Uneven partition selection rule; the component runner accepts explicit positive + section lengths without selecting a remainder policy. 2. Whether each arity stage consumes the preceding stage output or composes independent - partitions before a later merge. + partitions before a later merge. The runner's sequential choice is an explicitly + labelled experiment, not a newly inferred user law. 3. Exact thread split/recombine law. 4. Corpus/material extraction and binding law. 5. Nested gonol representation and reversible serialization. @@ -173,3 +195,5 @@ test, not a Weave security result. 7. Public/private key derivation and the exact source of asymmetry. 8. Authentication, nonces, state evolution, truncation/replay handling. 9. Threat model and target security properties. +10. Original pre-substitution thirteen-law conversation was not recovered. Missing + retrieved source is not evidence that the user never specified the relation. From 2f1a70948fb90f340613c49d27dfeb1b4e1b650f Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 04:43:54 -0700 Subject: [PATCH 29/31] Link executed Weave evidence and remove unsupported three-stage restriction --- research/weave/README.md | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/research/weave/README.md b/research/weave/README.md index 5375a492..85e39737 100644 --- a/research/weave/README.md +++ b/research/weave/README.md @@ -2,6 +2,10 @@ Standing: **stack-local research; specification-first; no security claim**. +[Executed source-bound results](REPORT.md) include literal-operation recovery, +schedule equivalences and a fixed-map attack. The complete design remains untested; +these results are not a whole-system verdict. + Weave is the replacement research workspace for Erin Spencer's intended encryption system after retirement of the substituted URPCS implementation. @@ -42,7 +46,7 @@ remain to be frozen. The bit transform is one load-bearing layer inside Weave. -For an ordered sequence of division arities, with at least three levels: +For an explicitly declared ordered sequence of division arities: 1. divide the working bit sequence into the declared number of sections; 2. within each section interleave inward from opposite ends: @@ -52,8 +56,13 @@ For an ordered sequence of division arities, with at least three levels: 4. after the declared levels, interleave the resulting whole sequence in the same opposite-end manner. +Stage count is distinct from arity. “Arity three, minimum” does not establish a +minimum of three stages; the unsupported assistant-added restriction is removed. + Knowing the division choices, their order, and the number of levels is part of the -reconstruction problem unless an explicit later law changes that role. +reconstruction problem unless an explicit later law changes that role. Different +schedule descriptions can induce the same map; measure equivalence rather than +assuming schedule uniqueness. ### 5. Keying / recovery structure @@ -76,7 +85,9 @@ must not happen again. ## Development discipline The full architecture is preserved from the start, while implementation proceeds in -separable layers so each contribution can be falsified. +separable layers so each contribution can be falsified. The order listed below is an +assistant proposal, not a user-selected dependency law; actual dependencies must come +from the complete source-backed construction. 1. Freeze the complete dataflow and the inverse dependencies among gonol construction, threads, corpus/material, interleaving, and key structure. @@ -102,13 +113,27 @@ cat research/weave/SPECIFICATION.md cat research/weave/BASE.json ``` +Reproduce the executed component evidence with Python's standard library only: + +```bash +cd research/weave +python probe.py > receipt.json +python probe.py --check receipt.json +python verify.py receipt.json +``` + +See [PLAN.md](PLAN.md) for the pre-execution scope and [REPORT.md](REPORT.md) for +results, mathematical derivations, exact assumptions and the expected receipt digest. + Do not use Weave to protect real secrets until an explicit security contract and adversarial evidence justify that use. ## hmmm -Uneven section partitioning; exact ordering/composition of arity stages; thread +Uneven section partition selection; exact ordering/composition of arity stages; thread formation; corpus/material derivation; hyperspace/gonol encoding; private-gonol binding; public/private key derivation; authentication, nonce/state, replay behavior; and the threat model remain unresolved. They are preserved as required design boundaries, not -optional features and not invitations for model substitution. +optional features and not invitations for model substitution. The original pre-substitution +thirteen-law conversation was not recovered; a missing retrieved source is not evidence +that the user never supplied the relation. From 200032dba6131145ebc61b52bb4f1aee507e6f63 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 08:51:53 -0700 Subject: [PATCH 30/31] Assemble switchable Weave stages and expose unresolved native laws beside proposed answers Add separate stage modules, forward/inverse orchestration, public/private API boundaries, and phone-sized switches. Preserve source-native missing operators as blocked rather than substitute implementations. Local assembly tests: 19 methods and all 512 switch configurations; not whole-system encryption evidence. No participant, source pin, lifecycle or upstream authority changes. --- research/weave/ASSEMBLY.md | 130 +++++++++++++++++++ research/weave/assembly.py | 144 +++++++++++++++++++++ research/weave/run.py | 27 ++++ research/weave/stages/__init__.py | 13 ++ research/weave/stages/api.py | 94 ++++++++++++++ research/weave/stages/auth.py | 10 ++ research/weave/stages/bind.py | 10 ++ research/weave/stages/corpus.py | 10 ++ research/weave/stages/gonol.py | 10 ++ research/weave/stages/inter.py | 38 ++++++ research/weave/stages/join.py | 10 ++ research/weave/stages/key.py | 33 +++++ research/weave/stages/split.py | 10 ++ research/weave/stages/whole.py | 26 ++++ research/weave/tests/test_assembly.py | 176 ++++++++++++++++++++++++++ 15 files changed, 741 insertions(+) create mode 100644 research/weave/ASSEMBLY.md create mode 100644 research/weave/assembly.py create mode 100644 research/weave/run.py create mode 100644 research/weave/stages/__init__.py create mode 100644 research/weave/stages/api.py create mode 100644 research/weave/stages/auth.py create mode 100644 research/weave/stages/bind.py create mode 100644 research/weave/stages/corpus.py create mode 100644 research/weave/stages/gonol.py create mode 100644 research/weave/stages/inter.py create mode 100644 research/weave/stages/join.py create mode 100644 research/weave/stages/key.py create mode 100644 research/weave/stages/split.py create mode 100644 research/weave/stages/whole.py create mode 100644 research/weave/tests/test_assembly.py diff --git a/research/weave/ASSEMBLY.md b/research/weave/ASSEMBLY.md new file mode 100644 index 00000000..d0adc9c4 --- /dev/null +++ b/research/weave/ASSEMBLY.md @@ -0,0 +1,130 @@ +# Weave: full modular assembly v1 + +Status: ASSEMBLY IMPLEMENTED; COMPLETE ENCRYPTION NOT IMPLEMENTED. + +This is a source-bound composition contract and switchable runner, not a replacement +cipher. The native key, binding, thread, corpus and join laws remain explicit missing +operators. No dummy implementation is enabled, and a missing operator never acts as +an identity. All-on encryption refuses before touching input until those operators +are supplied. Existing interleave code is reused without changing its findings. + +Source: The-Interdependency/stack@2f1a70948fb90f340613c49d27dfeb1b4e1b650f, +research/weave/SPECIFICATION.md. This specification preserves the full architecture. +The order below is an ASSISTANT PROPOSAL, not an additional user requirement. + +## Module plan and complete composition + +Key setup is separate from the reversible data path. `stages/key.py` owns KeyGen +and the public/private operation contract. The sender-side context has no private-key +field. This API separation does not prove that a public key reveals no private data. + +Proposed forward order: + +1. `stages/gonol.py`: construct the complete native nested plaintext object. +2. `stages/bind.py`: apply the public-side native relation whose recovery uses the + private gonol. This is a mathematical operation, not a password check. +3. `stages/split.py`: form the mutually required logical thread streams. +4. `stages/corpus.py`: apply the actual corpus/material relationship to each thread. +5. `stages/inter.py`: execute the exact supplied section partitions, last/first inward, + in supplied stage order, independently for each thread. +6. `stages/join.py`: interlace the transformed threads under the selected relation. +7. `stages/whole.py`: apply the last/first inward operation to the resulting whole. +8. `stages/auth.py`: optional integrity/replay contract; no authentication law has + been selected or implemented. Off by default; never a substitute for encryption. + +Inverse: undo the enabled data stages in the exact reverse order, using the recipient +context and the same explicitly selected profile. Key generation is not inverted. +A key-derived plan may govern any of these stages; it is not deferred until the end. +If inverse planning depends on data that is still hidden by a later inverse stage, +that dependency must be resolved by the native law, not circularly read from plaintext. + +## Switch semantics + +All seven required data stages and key setup default ON. Auth defaults OFF because +it has not been made a requirement of this design. Each has an independent Boolean. +OFF skips exactly that stage and its inverse, without changing any other switch. +Key OFF bypasses KeyGen and withholds both key objects from stage contexts. +A missing enabled implementation is BLOCKED, not skipped. A type/dependency that cannot +survive a bypass is an incompatible ablation, not a falsification of the full system. + +Every run carries its profile, stage order, switch mask, operator identities and +classification. The runner retains no plaintext, private key, corpus bytes or per-stage +payloads in its trace. It never serializes a plan or secret into ciphertext on its own. +Disabling a required stage creates ABLATION_ONLY output. An all-on experiment is still +FULL_PROFILE_EXPERIMENT, never a proof of security. Whole-system observations require +whole-system operators; test fixtures cannot authorize full-profile execution. + +## Questions and proposed answers + +The short IDs below let Erin change answers without retyping the project. None of +these proposed answers is presented as a previously supplied law. + +| ID | Question necessary to complete the binding | Proposed answer / research position | +|---|---|---| +| Q1 | Does the plaintext construction use a lossless binary admission into native gonols, a language-domain construction, or both? | Support the entire raw input without lossy normalization. Use a native binary admission for arbitrary files and explicitly selected language constructors for language-aware profiles. Do not relabel a JSON tree or an input dossier as a new gonol. The binary and whole-message constructors still need an owning native implementation. | +| Q2 | Is the private gonol a missing origin/attachment relation, an omitted member, or something else; what public operation corresponds to it? | Investigate a public projection of the full native relation with a private origin/attachment supplying the lift during recovery. This is a candidate target, not an established algebra. Deriving its forward operation and testing unauthorized inversion is the research job; Erin need not supply a security proof. | +| Q3 | Are threads different necessary parts/projections of one plaintext construction, or separate full constructions? | Different required parts of one construction, preserving cross-thread relations and occurrence identity. No independent plaintext copy in each lane. Whether every lane is mathematically necessary must be measured, not enforced by an artificial missing-file check. Exact routing/projection remains to be defined. | +| Q4 | Does corpus material supply axes/origins, traversal instructions, transformed values, or a combination? | Keep two explicit candidates: corpus-derived native axes/origin attachments; and corpus-derived traversal/arity choices. Use actual content in either case. Evaluate both within the complete composition; do not replace either with a filename hash, XOR mask or unrelated cipher. | +| Q5 | How do thread streams interlace, and is final whole-stream interleaving after that join? | Use a declared key/context-derived thread route, followed by the final last/first interleave over the joined stream. This is one proposed order. A per-thread final pass is a separate alternative, not an invisible extra pass. | +| Q6 | Do successive arities consume the previous stage's output, and how are remainders handled? | Proposed sequential composition. Supply exact partition lengths for every stage/lane now; balanced quotient/remainder partitioning is one selectable future policy, not an assumed rule. Keep arity distinct from level count: no invented three-stage minimum. | +| Q7 | What may an independent sender know: just public key/material, or any private corpus selections and schedules? | Sender gets public key, allowed public material and message randomness only. Private gonol and secret selections remain recipient-side. Any secret-dependent stage must offer a public forward operation. Giving encryption the private plan would be a symmetric test, not the requested asymmetric system. | +| Q8 | Are thread count, partitions, corpus locations and join route message-dependent, key-dependent or explicitly supplied? | Keep them key-and-message-context dependent candidates. The public/native forward law must make encryption possible without disclosing the private inverse. Do not publish them as convenient ciphertext headers before deciding which are intended to remain hidden. | +| Q9 | Should equal plaintext under the same public key produce different outputs? | Proposed yes: explicit fresh sender randomness, reproducible only in test fixtures. Derive its role through the native relation; a public nonce alone does not create secrecy or prevent key recovery. No automatic randomization mechanism is inserted here. | +| Q10 | Which ciphertext structure is public, and must altered or incomplete messages be rejected? | Specify version, profile negotiation, length policy, integrity and replay policy before a wire format is frozen. Keep experimental switch masks in the lab receipt; do not silently disclose secret structure. There is no selected authentication construction. | + +Q2, Q4 and Q8 require mathematical candidate derivation as well as intent. A label such +as 'private projection' is not an implementation. Operators remain unbound until that +actual transformation exists. The original pre-substitution conversation remains +unrecovered; this does not establish that Erin never specified these relations. + +## Usage + +From `research/weave/`: + +```bash +python run.py # full proposed profile: explicit BLOCKED list +python run.py --off corpus # one-stage ablation; no cascading skips +python run.py --on auth # also requires a real authentication law +python -m unittest discover -s tests -p 'test_assembly.py' +``` + +`assembly.Pipeline` accepts explicitly supplied `Operator` bindings. Nothing is loaded +from ciphertext or dynamic module names. Native objects pass through without conversion +into a generic replacement tree. `stages/inter.py` expects a `Streams` object plus +explicit per-thread partitions; `stages/whole.py` expects exactly one joined stream. +KeyGen is explicitly supplied through `stages/key.py`, not invented by the runner. + +## Verification and remaining work + +Tests cover assembly control flow, inverse order, independent switches, missing-law +refusal, public/private API separation, and the two existing literal bit operations. +They do not simulate missing native operators and call that encryption. Test-marker +operators are labelled wiring fixtures and cannot run as full-profile evidence. +A valid decryption API returning original data is not by itself security evidence. + +Deployment: manual local research only; no service, scheduled work or network calls. +Rollback: remove this new assembly and its tests; preserve the original source/spec +and sealed interleave evidence. No imported `libs/`, upstream producer or lifecycle +standing changes in this transaction. + +## hmmm + +The assembled interface is executable. The complete cipher is not: native message +admission/composition, private/public binding, thread/corpus coupling and join/key +planning are not filled with pretend implementations. These are the next exact +research/intent decisions exposed by this assembly. + +## Native source inspection + +UCHC `hyperspace_construct.py` blob `8b55823805c87ad8c4cc9d7451dc2eb90bdedd3a` +supplies real glyph/word/definition construction and recovery. UCHC +`inference_input.py` blob `0959342f9526e8c0b35cc7e1a2a448b0961977b9` explicitly +calls `InferenceFrame` an input dossier, not a new gonol. That dossier is not silently +substituted for a native whole-message encryption gonol. The full construct database +was not available in this runtime, and no reduced fabricated corpus was generated. + +Skill application record (one unit of work): `the-interdependency`, +`meta-module-build`, `msdmd`; source preservation, explicit native boundaries and +fail-closed module wiring applied. Outcome: assembly tested, full cipher unresolved. +METAPAT README consulted for domain-owned mechanisms/non-transfer; no cryptographic +conclusion is inferred from that semantic source. diff --git a/research/weave/assembly.py b/research/weave/assembly.py new file mode 100644 index 00000000..a23ddc3a --- /dev/null +++ b/research/weave/assembly.py @@ -0,0 +1,144 @@ +"""Switchable full-scope Weave assembly with explicit unresolved operators. + +Usage: Pipeline(switches, operators).encrypt(value, PublicContext(...)). +A missing enabled law refuses before any operator executes. Decryption uses the +same lab recipe and the reverse order. This module defines no ciphertext wire +format and supplies no substitute asymmetric relation. Source/rollout: ASSEMBLY.md. +""" +from __future__ import annotations +from dataclasses import dataclass, field, replace +from types import MappingProxyType +from typing import Any, Mapping +from stages import STEPS +from stages.api import Blocked, Operator, PrivateContext, PublicContext, Transition + +DEFAULTS = {'key': True, **{s.name: s.required for s in STEPS}} + + +@dataclass(frozen=True) +class Switches: + values: Mapping[str, bool] = field(default_factory=dict) + + def __post_init__(self): + source = dict(self.values) + if set(source) - set(DEFAULTS): + raise ValueError('unknown switch: ' + ','.join(sorted(set(source)-set(DEFAULTS)))) + if any(type(value) is not bool for value in source.values()): + raise TypeError('switch values must be literal Booleans') + object.__setattr__(self, 'values', MappingProxyType({**DEFAULTS, **source})) + + def __getitem__(self, name): + return self.values[name] + + @property + def complete(self): + return self['key'] and all(self[s.name] for s in STEPS if s.required) + + +@dataclass(frozen=True) +class Run: + """Lab result. recipe/events are sidecar evidence, NOT ciphertext headers.""" + payload: Any = field(repr=False) + recipe: tuple + classification: str + events: tuple[tuple[str, str], ...] + direction: str + + +class Pipeline: + def __init__(self, switches: Switches | None = None, + operators: Mapping[str, Operator] | None = None, *, + allow_fixtures: bool = False): + self.switches = switches or Switches() + supplied = dict(operators or {}) + names = {s.name for s in STEPS} + if set(supplied) - names: + raise ValueError('unknown operator binding') + if any(not isinstance(op, Operator) for op in supplied.values()): + raise TypeError('bindings must be Operator objects') + for step in STEPS: + if step.builtin is not None: + if step.name in supplied: + raise ValueError('literal operation cannot be replaced: ' + step.name) + supplied[step.name] = step.builtin + self.operators = MappingProxyType(supplied) + if type(allow_fixtures) is not bool: + raise TypeError('allow_fixtures must be Boolean') + self.allow_fixtures = allow_fixtures + + def problems(self, context=None): + problems = [] + if self.switches['key'] and (context is None or context.public_key is None): + problems.append('key: Q2/Q7/Q8, native public/private relation/key input missing') + if type(context) is PrivateContext and self.switches['key'] and context.private_key is None: + problems.append('key: private key missing for inverse') + if self.switches['bind'] and not (self.switches['key'] and self.switches['gonol']): + problems.append('bind: incompatible ablation; native binding requires key and gonol') + for step in STEPS: + if not self.switches[step.name]: + continue + op = self.operators.get(step.name) + if op is None: + problems.append(step.name + ': ' + '/'.join(step.questions) + ', native operator missing') + elif op.fixture and not self.allow_fixtures: + problems.append(step.name + ': wiring fixture is not a native law') + return tuple(problems) + + def recipe(self): + return (('proposal', 'assembly-v1'), ('key', self.switches['key']), *( + (s.name, self.switches[s.name], + self.operators[s.name].identity if self.switches[s.name] and s.name in self.operators else None) + for s in STEPS)) + + def plan(self): + return { + 'status': 'BLOCKED' if self.problems() else 'ASSEMBLED', + 'complete_cipher_implemented': False, + 'profile': 'full proposed scope' if self.switches.complete else 'ablation', + 'switches': dict(self.switches.values), + 'forward_order': [s.name for s in STEPS if self.switches[s.name]], + 'inverse_order': [s.name for s in reversed(STEPS) if self.switches[s.name]], + 'missing': self.problems(), + 'note': 'Read ASSEMBLY.md: proposed answers do not implement missing native laws.', + } + + def encrypt(self, value, context: PublicContext): + if type(context) is not PublicContext: + raise TypeError('encrypt takes PublicContext only; never PrivateContext') + return self._run(value, context, reverse=False) + + def decrypt(self, encrypted: Run, context: PrivateContext): + if type(context) is not PrivateContext: + raise TypeError('decrypt requires explicit PrivateContext') + if not isinstance(encrypted, Run) or encrypted.direction != 'encrypt': + raise TypeError('supply the encrypted lab result, not an invented wire format') + if encrypted.recipe != self.recipe(): + raise ValueError('inverse profile/operator identities differ from forward lab recipe') + return self._run(encrypted.payload, context, reverse=True) + + def _run(self, value, context, *, reverse): + problems = self.problems(context) + if problems: + raise Blocked('; '.join(problems)) + if not self.switches['key']: + context = (replace(context, public_key=None, private_key=None) + if type(context) is PrivateContext else replace(context, public_key=None)) + events = [] + fixture = False + for step in reversed(STEPS) if reverse else STEPS: + if not self.switches[step.name]: + events.append((step.name, 'OFF')) + continue + op = self.operators[step.name] + fixture = fixture or op.fixture + result = (op.inverse if reverse else op.forward)(value, context) + if isinstance(result, Transition): + value = result.payload + context = replace(context, parameters={**context.parameters, **result.parameters}) + else: + value = result + events.append((step.name, 'EXECUTED')) + classification = ('WIRING_ONLY' if fixture else + 'FULL_PROFILE_EXPERIMENT' if self.switches.complete else 'ABLATION_ONLY') + return Run(value, self.recipe(), classification, tuple(events), + 'decrypt' if reverse else 'encrypt') diff --git a/research/weave/run.py b/research/weave/run.py new file mode 100644 index 00000000..25a1697c --- /dev/null +++ b/research/weave/run.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +"""Phone-sized Weave plan entrypoint. Usage: python run.py --off corpus --on auth. + +Prints exact switches and missing laws. No file writes, network, automatic native +imports or encryption claims. Exit 2 = unresolved; exit 0 = plan has no blockers. +""" +import argparse +import json +from assembly import DEFAULTS, Pipeline, Switches + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--off', action='append', choices=tuple(DEFAULTS), default=[]) + parser.add_argument('--on', action='append', choices=tuple(DEFAULTS), default=[]) + args = parser.parse_args() + overlap = set(args.off) & set(args.on) + if overlap: + parser.error('both on and off requested: ' + ','.join(sorted(overlap))) + flags = {**{name: False for name in args.off}, **{name: True for name in args.on}} + result = Pipeline(Switches(flags)).plan() + print(json.dumps(result, indent=2)) + return 2 if result['status'] == 'BLOCKED' else 0 + + +if __name__ == '__main__': + raise SystemExit(main()) diff --git a/research/weave/stages/__init__.py b/research/weave/stages/__init__.py new file mode 100644 index 00000000..f64d970f --- /dev/null +++ b/research/weave/stages/__init__.py @@ -0,0 +1,13 @@ +"""Explicit registry for the proposed complete data path; no dynamic imports. +Usage: STEPS is forward order; reversal is performed only by assembly.Pipeline. +""" +from .gonol import STEP as GONOL +from .bind import STEP as BIND +from .split import STEP as SPLIT +from .corpus import STEP as CORPUS +from .inter import STEP as INTER +from .join import STEP as JOIN +from .whole import STEP as WHOLE +from .auth import STEP as AUTH + +STEPS = (GONOL, BIND, SPLIT, CORPUS, INTER, JOIN, WHOLE, AUTH) diff --git a/research/weave/stages/api.py b/research/weave/stages/api.py new file mode 100644 index 00000000..4084fc72 --- /dev/null +++ b/research/weave/stages/api.py @@ -0,0 +1,94 @@ +"""Typed operator contracts, not cryptographic constructions. + +Usage: supply explicit Operator(forward, inverse, identity) instances to Pipeline. +No network or storage. Native payloads pass unchanged except through selected operators. +Roll back by removing this assembly; no producer code is changed. +""" +from __future__ import annotations +from dataclasses import dataclass, field +from types import MappingProxyType +from typing import Any, Callable, Mapping + + +class Blocked(RuntimeError): + """An enabled law/input is missing; execution must not silently bypass it.""" + + +@dataclass(frozen=True) +class PublicContext: + public_key: Any = field(repr=False) + parameters: Mapping[str, Any] = field(default_factory=dict, repr=False) + randomness: bytes = field(default=b'', repr=False) + public_material: Mapping[str, bytes] = field(default_factory=dict, repr=False) + + def __post_init__(self): + object.__setattr__(self, 'parameters', MappingProxyType(dict(self.parameters))) + object.__setattr__(self, 'public_material', MappingProxyType(dict(self.public_material))) + + +@dataclass(frozen=True) +class PrivateContext: + public_key: Any = field(repr=False) + private_key: Any = field(repr=False) + parameters: Mapping[str, Any] = field(default_factory=dict, repr=False) + private_material: Mapping[str, bytes] = field(default_factory=dict, repr=False) + public_material: Mapping[str, bytes] = field(default_factory=dict, repr=False) + randomness: bytes = field(default=b'', repr=False) + + def __post_init__(self): + object.__setattr__(self, 'parameters', MappingProxyType(dict(self.parameters))) + object.__setattr__(self, 'private_material', MappingProxyType(dict(self.private_material))) + object.__setattr__(self, 'public_material', MappingProxyType(dict(self.public_material))) + + +@dataclass(frozen=True) +class Streams: + """Exact bit streams; not a gonol, key or native thread-generation law.""" + lanes: tuple[tuple[int, ...], ...] = field(repr=False) + + def __post_init__(self): + if type(self.lanes) is not tuple or not self.lanes: + raise TypeError('lanes must be a nonempty tuple') + if any(type(lane) is not tuple for lane in self.lanes): + raise TypeError('each lane must be an immutable tuple') + if any(type(bit) is not int or bit not in (0, 1) + for lane in self.lanes for bit in lane): + raise TypeError('each bit must be integer 0 or 1, not bool/coerced data') + + +@dataclass(frozen=True) +class Operator: + """A real transformation pair plus provenance; fixture is never full evidence.""" + forward: Callable[[Any, PublicContext], Any] = field(repr=False) + inverse: Callable[[Any, PrivateContext], Any] = field(repr=False) + identity: str + fixture: bool = False + + def __post_init__(self): + if not callable(self.forward) or not callable(self.inverse): + raise TypeError('both operator directions must be callable') + if type(self.identity) is not str or not self.identity.strip(): + raise ValueError('an explicit law/source identity is required') + if type(self.fixture) is not bool: + raise TypeError('fixture flag must be Boolean') + + +@dataclass(frozen=True) +class Step: + name: str + questions: tuple[str, ...] + purpose: str + required: bool = True + builtin: Operator | None = None + + +@dataclass(frozen=True) +class Transition: + """A stage may pass derived working parameters to later stages, not ciphertext. + + This preserves coupled, message-dependent constructions. The inverse key law + must independently make whatever reverse parameters are needed available. + Updates are not copied into receipts and do not supply a missing private law. + """ + payload: Any = field(repr=False) + parameters: Mapping[str, Any] = field(default_factory=dict, repr=False) diff --git a/research/weave/stages/auth.py b/research/weave/stages/auth.py new file mode 100644 index 00000000..dc3cd804 --- /dev/null +++ b/research/weave/stages/auth.py @@ -0,0 +1,10 @@ +"""Optional integrity/replay relation, separate from confidentiality. + +Usage: bind a source-identified Operator to 'auth' in Pipeline. Toggle only 'auth'. +The native transformation is unresolved (Q10); this module declares its +interface and never supplies a fake identity, hash, XOR or conventional-cipher fallback. +No network or storage. See ASSEMBLY.md for the proposed answer and rollback. +""" +from .api import Step + +STEP = Step('auth', ('Q10',), 'Optional integrity/replay relation, separate from confidentiality.', required=False) diff --git a/research/weave/stages/bind.py b/research/weave/stages/bind.py new file mode 100644 index 00000000..ecc711f0 --- /dev/null +++ b/research/weave/stages/bind.py @@ -0,0 +1,10 @@ +"""Native public operation and private-gonol recovery relation. + +Usage: bind a source-identified Operator to 'bind' in Pipeline. Toggle only 'bind'. +The native transformation is unresolved (Q2/Q7/Q8); this module declares its +interface and never supplies a fake identity, hash, XOR or conventional-cipher fallback. +No network or storage. See ASSEMBLY.md for the proposed answer and rollback. +""" +from .api import Step + +STEP = Step('bind', ('Q2', 'Q7', 'Q8'), 'Native public operation and private-gonol recovery relation.', required=True) diff --git a/research/weave/stages/corpus.py b/research/weave/stages/corpus.py new file mode 100644 index 00000000..9532cafb --- /dev/null +++ b/research/weave/stages/corpus.py @@ -0,0 +1,10 @@ +"""Use actual thread-associated corpus content in the selected native relation. + +Usage: bind a source-identified Operator to 'corpus' in Pipeline. Toggle only 'corpus'. +The native transformation is unresolved (Q4/Q7/Q8); this module declares its +interface and never supplies a fake identity, hash, XOR or conventional-cipher fallback. +No network or storage. See ASSEMBLY.md for the proposed answer and rollback. +""" +from .api import Step + +STEP = Step('corpus', ('Q4', 'Q7', 'Q8'), 'Use actual thread-associated corpus content in the selected native relation.', required=True) diff --git a/research/weave/stages/gonol.py b/research/weave/stages/gonol.py new file mode 100644 index 00000000..e8de0c4b --- /dev/null +++ b/research/weave/stages/gonol.py @@ -0,0 +1,10 @@ +"""Complete native plaintext construction and exact recovery. + +Usage: bind a source-identified Operator to 'gonol' in Pipeline. Toggle only 'gonol'. +The native transformation is unresolved (Q1); this module declares its +interface and never supplies a fake identity, hash, XOR or conventional-cipher fallback. +No network or storage. See ASSEMBLY.md for the proposed answer and rollback. +""" +from .api import Step + +STEP = Step('gonol', ('Q1',), 'Complete native plaintext construction and exact recovery.', required=True) diff --git a/research/weave/stages/inter.py b/research/weave/stages/inter.py new file mode 100644 index 00000000..20b34d3f --- /dev/null +++ b/research/weave/stages/inter.py @@ -0,0 +1,38 @@ +"""Specified section-local last/first operation, with explicit sequential partitions. + +Usage: PublicContext/PrivateContext.parameters['inter'] = tuple of per-lane stage +partitions; each partition is the exact tuple of positive section lengths. +No default arity schedule, remainder rule, thread route or minimum stage count. +This explicit sequential profile is a proposal, not an additional user requirement. +No network/storage; rollback by disabling 'inter' for a labelled ablation. +""" +from probe import section_stage +from .api import Blocked, Operator, Step, Streams + + +def transform(value, context, reverse=False): + if not isinstance(value, Streams): + raise TypeError('inter requires Streams from the selected upstream native law') + plans = context.parameters.get('inter') + if type(plans) is not tuple or len(plans) != len(value.lanes): + raise Blocked('inter: Q6 requires explicit partitions for every lane') + out = [] + for lane, stages in zip(value.lanes, plans): + if type(stages) is not tuple or not stages: + raise Blocked('inter: supply a nonempty explicit stage sequence per lane') + for partition in reversed(stages) if reverse else stages: + lane = section_stage(lane, partition, reverse=reverse) + out.append(lane) + return Streams(tuple(out)) + + +def forward(value, context): + return transform(value, context) + + +def inverse(value, context): + return transform(value, context, True) + + +STEP = Step('inter', ('Q6',), 'Exact section-local last/first interleave.', + builtin=Operator(forward, inverse, 'literal-section/sequential-explicit-v1')) diff --git a/research/weave/stages/join.py b/research/weave/stages/join.py new file mode 100644 index 00000000..70c8b534 --- /dev/null +++ b/research/weave/stages/join.py @@ -0,0 +1,10 @@ +"""Interlace and recover threads under the exact selected route. + +Usage: bind a source-identified Operator to 'join' in Pipeline. Toggle only 'join'. +The native transformation is unresolved (Q5/Q8); this module declares its +interface and never supplies a fake identity, hash, XOR or conventional-cipher fallback. +No network or storage. See ASSEMBLY.md for the proposed answer and rollback. +""" +from .api import Step + +STEP = Step('join', ('Q5', 'Q8'), 'Interlace and recover threads under the exact selected route.', required=True) diff --git a/research/weave/stages/key.py b/research/weave/stages/key.py new file mode 100644 index 00000000..7095c9c7 --- /dev/null +++ b/research/weave/stages/key.py @@ -0,0 +1,33 @@ +"""Public/private setup boundary; no substitute key generator. + +Usage: call keygen(explicit_native_law, private_gonol, material, randomness). +The explicit law owns the mathematical public/private relation (Q2, Q7, Q8). +No network, persistence, private-key logging or conventional crypto fallback. +""" +from dataclasses import dataclass, field +from typing import Any, Callable +from .api import Blocked + + +@dataclass(frozen=True) +class KeyPair: + public: Any = field(repr=False) + private: Any = field(repr=False) + law_identity: str + + +def keygen(law: Callable[..., KeyPair] | None, *, private_gonol: Any, + material: Any, randomness: bytes, enabled: bool = True) -> KeyPair | None: + if type(enabled) is not bool: + raise TypeError("key switch must be Boolean") + if not enabled: + return None + if law is None: + raise Blocked('key: Q2/Q7/Q8 require an actual native KeyGen relation') + result = law(private_gonol=private_gonol, material=material, randomness=randomness) + if (not isinstance(result, KeyPair) or type(result.law_identity) is not str + or not result.law_identity.strip()): + raise TypeError('KeyGen must return a source-identified KeyPair') + if result.public is None or result.private is None: + raise ValueError('KeyGen returned an absent key side') + return result diff --git a/research/weave/stages/split.py b/research/weave/stages/split.py new file mode 100644 index 00000000..9ea69c95 --- /dev/null +++ b/research/weave/stages/split.py @@ -0,0 +1,10 @@ +"""Generate the required logical thread streams without discarding cross-relations. + +Usage: bind a source-identified Operator to 'split' in Pipeline. Toggle only 'split'. +The native transformation is unresolved (Q3); this module declares its +interface and never supplies a fake identity, hash, XOR or conventional-cipher fallback. +No network or storage. See ASSEMBLY.md for the proposed answer and rollback. +""" +from .api import Step + +STEP = Step('split', ('Q3',), 'Generate the required logical thread streams without discarding cross-relations.', required=True) diff --git a/research/weave/stages/whole.py b/research/weave/stages/whole.py new file mode 100644 index 00000000..30b37381 --- /dev/null +++ b/research/weave/stages/whole.py @@ -0,0 +1,26 @@ +"""Specified last/first operation over one complete joined stream. + +Usage: bind no additional law; supply Streams((joined_bits,)). Multiple lanes are an +incompatible ablation until a real join law exists; this stage never joins implicitly. +No network/storage. Disable only 'whole' to measure its contribution. +""" +from probe import inward, inverse_inward +from .api import Operator, Step, Streams + + +def transform(value, reverse=False): + if not isinstance(value, Streams) or len(value.lanes) != 1: + raise TypeError('whole requires one already joined stream; no implicit join') + return Streams(((inverse_inward if reverse else inward)(value.lanes[0]),)) + + +def forward(value, context): + return transform(value) + + +def inverse(value, context): + return transform(value, True) + + +STEP = Step('whole', ('Q5',), 'Last/first interleave over the complete joined stream.', + builtin=Operator(forward, inverse, 'literal-whole-inward-v1')) diff --git a/research/weave/tests/test_assembly.py b/research/weave/tests/test_assembly.py new file mode 100644 index 00000000..cadbb13e --- /dev/null +++ b/research/weave/tests/test_assembly.py @@ -0,0 +1,176 @@ +"""Assembly witnesses, NOT a cipher/security test suite. + +Usage: python -m unittest discover -s tests -p 'test_assembly.py'. +Finite preflight: 512 switch configurations over six synthetic bits; no corpus, +secrets, network or provider calls. Marker operators are explicitly WIRING_ONLY. +""" +from dataclasses import replace +from itertools import product +import unittest +from assembly import DEFAULTS, Pipeline, Switches +from stages import STEPS +from stages.api import Blocked, Operator, PrivateContext, PublicContext, Streams, Transition +from stages.key import keygen + +DATA = Streams(((0, 1, 0, 1, 1, 0),)) +PARAMS = {'inter': (((2, 2, 2),),)} +PUB = PublicContext('test-public-only', PARAMS) +PRIV = PrivateContext('test-public-only', 'test-private-only', PARAMS) + + +def markers(log): + def pair(name): + def f(value, context): + log.append(('forward', name)) + return value + def r(value, context): + log.append(('inverse', name)) + return value + return Operator(f, r, 'wiring-fixture/' + name, fixture=True) + return {s.name: pair(s.name) for s in STEPS if s.builtin is None} + + +class AssemblyTests(unittest.TestCase): + def test_all_on_is_blocked_before_input(self): + touched = [] + handlers = markers(touched) + del handlers['bind'] + with self.assertRaisesRegex(Blocked, 'bind: Q2/Q7/Q8'): + Pipeline(operators=handlers, allow_fixtures=True).encrypt(DATA, PUB) + self.assertEqual(touched, []) + + def test_default_scope_and_six_unresolved_bindings(self): + plan = Pipeline().plan() + self.assertFalse(plan['complete_cipher_implemented']) + self.assertEqual(plan['status'], 'BLOCKED') + self.assertEqual(len(plan['missing']), 6) + self.assertFalse(plan['switches']['auth']) + self.assertTrue(all(plan['switches'][s.name] for s in STEPS if s.required)) + + def test_no_native_fixture_promotion(self): + with self.assertRaisesRegex(Blocked, 'wiring fixture'): + Pipeline(operators=markers([])).encrypt(DATA, PUB) + + def test_all_512_switches_keep_identity_or_report_incompatibility(self): + for values in product((False, True), repeat=len(DEFAULTS)): + flags = dict(zip(DEFAULTS, values)) + p = Pipeline(Switches(flags), markers([]), allow_fixtures=True) + if flags['bind'] and not (flags['key'] and flags['gonol']): + with self.assertRaisesRegex(Blocked, 'incompatible ablation'): + p.encrypt(DATA, PUB) + continue + forward = p.encrypt(DATA, PUB) + inverse = p.decrypt(forward, PRIV) + self.assertEqual(inverse.payload, DATA) + self.assertEqual(dict((n, v) for n,v in p.switches.values.items()), flags) + self.assertNotEqual(forward.classification, 'FULL_PROFILE_EXPERIMENT') + for name, status in forward.events: + self.assertEqual(status == 'OFF', not flags[name]) + + def test_inverse_order(self): + log = [] + p = Pipeline(operators=markers(log), allow_fixtures=True) + e = p.encrypt(DATA, PUB) + p.decrypt(e, PRIV) + forward = [name for direction,name in log if direction == 'forward'] + inverse = [name for direction,name in log if direction == 'inverse'] + self.assertEqual(inverse, list(reversed(forward))) + self.assertEqual(e.classification, 'WIRING_ONLY') + + def test_cipher_never_receives_private_context(self): + with self.assertRaisesRegex(TypeError, 'PublicContext only'): + Pipeline().encrypt(DATA, PRIV) + self.assertFalse(hasattr(PUB, 'private_key')) + + def test_context_and_run_repr_do_not_expose_material(self): + self.assertNotIn('test-private-only', repr(PRIV)) + p = Pipeline(Switches({n:False for n in DEFAULTS})) + e = p.encrypt(b'test-plaintext-not-a-cipher', PUB) + self.assertNotIn('test-plaintext', repr(e)) + self.assertEqual(e.classification, 'ABLATION_ONLY') + + def test_independent_switch_no_cascade(self): + config = Switches({'corpus': False}) + self.assertTrue(config['split']) + self.assertTrue(config['inter']) + self.assertTrue(config['join']) + + def test_unknown_and_nonboolean_switches_fail(self): + for flags in ({'corups': False}, {'inter': 0}, {'corpus': 'off'}): + with self.assertRaises((ValueError, TypeError)): + Switches(flags) + + def test_no_silent_literal_override(self): + fake = Operator(lambda x,c:x, lambda x,c:x, 'fake') + with self.assertRaisesRegex(ValueError, 'cannot be replaced'): + Pipeline(operators={'inter':fake}) + + def test_exact_one_stage_is_accepted_and_reversed(self): + flags = {n:False for n in DEFAULTS} + flags['inter'] = flags['whole'] = True + p = Pipeline(Switches(flags)) + e = p.encrypt(DATA, PUB) + self.assertEqual(p.decrypt(e, PRIV).payload, DATA) + self.assertEqual(e.classification, 'ABLATION_ONLY') + + def test_missing_partition_never_guessed(self): + flags = {n:False for n in DEFAULTS}; flags['inter'] = True + with self.assertRaisesRegex(Blocked, 'explicit partitions'): + Pipeline(Switches(flags)).encrypt(DATA, PublicContext(None)) + + def test_whole_never_implicitly_joins_threads(self): + flags = {n:False for n in DEFAULTS}; flags['whole'] = True + with self.assertRaisesRegex(TypeError, 'already joined'): + Pipeline(Switches(flags)).encrypt(Streams(((0,1),(1,0))), PUB) + + def test_changed_inverse_switch_mask_rejected(self): + flags = {n:False for n in DEFAULTS} + e = Pipeline(Switches(flags)).encrypt(DATA, PUB) + flags['whole'] = True + with self.assertRaisesRegex(ValueError, 'recipe'): + Pipeline(Switches(flags)).decrypt(e, PRIV) + + def test_missing_key_relation_is_not_invented(self): + with self.assertRaisesRegex(Blocked, 'KeyGen relation'): + keygen(None, private_gonol=object(), material={}, randomness=b'') + + def test_stage_can_pass_derived_plan_without_exporting_it(self): + log = [] + ops = markers(log) + secret_plan = {'inter':PARAMS['inter'], 'do_not_publish':'secret-marker'} + def forward(value, context): + return Transition(value, secret_plan) + ops['corpus'] = Operator(forward, lambda x,c:x, 'wiring-fixture/derived', fixture=True) + e = Pipeline(operators=ops, allow_fixtures=True).encrypt(DATA, PublicContext('test-public')) + self.assertNotIn('secret-marker', repr(e)) + self.assertFalse(hasattr(e, 'parameters')) + + def test_key_off_does_not_invoke_keygen(self): + def forbidden(**kwargs): + raise AssertionError('disabled generator was called') + self.assertIsNone(keygen(forbidden, private_gonol=object(), material={}, + randomness=b'', enabled=False)) + + def test_key_off_removes_keys_from_operator_contexts(self): + seen = [] + def f(value, context): + seen.append(context.public_key) + return value + def r(value, context): + seen.extend((context.public_key, context.private_key)) + return value + flags = {n:False for n in DEFAULTS}; flags['corpus'] = True + p = Pipeline(Switches(flags), {'corpus':Operator(f,r,'wiring-fixture/keys-off',True)}, + allow_fixtures=True) + e = p.encrypt(DATA,PUB) + p.decrypt(e,PRIV) + self.assertEqual(seen,[None,None,None]) + + def test_streams_reject_bool_and_mutable_input(self): + for lanes in (((True,),), ([0,1],), []): + with self.assertRaises(TypeError): + Streams(lanes) + + +if __name__ == '__main__': + unittest.main() From 5dd67dec2d3cfe7eeb2cdd3d4f132bc9b8007ba9 Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Mon, 28 Sep 2026 10:30:18 -0700 Subject: [PATCH 31/31] Implement switchable Weave transport candidates and source-pinned native adapter Implement available provisional answers as separate split, corpus traversal, arity and join modules, preserving whole interleave and the default full-native refusal boundary. Add explicit transport scope, exact inverse composition, file CLI, strict profile/record validation, native UCHC word reader, source-bound tests, and Q1-Q10 proposed answers. Native whole-message, key/private-gonol binding and corpus/thread geometry remain unimplemented rather than substituted. Local verification: 43 test methods, zero failures/errors/skips; 8191 exhaustive binary messages; 512 assembly masks and 32 transport masks; 64KiB roundtrip; fresh-process recovery after input deletion. Code/profile source digest 15ecd585290b2adf6d827d55606fe62189493423ad26b1036ea8f8514a8d534c. 24 remote source/document Git blobs match locally checked files. Fixed-map recovery succeeds against this explicit transport candidate; not a whole-Weave security result. No producer or libs/lifecycle changes. --- .github/workflows/weave.yml | 34 +++ research/weave/IMPLEMENTATION_PLAN.json | 19 ++ research/weave/IMPLEMENTED.md | 143 ++++++++++++ research/weave/QUESTIONS.md | 102 +++++++++ research/weave/assembly.py | 26 ++- research/weave/evidence/transport-v1.json | 80 +++++++ research/weave/lab.py | 148 +++++++++++++ research/weave/profiles/transport.json | 8 + research/weave/run.py | 10 +- research/weave/stages/api.py | 23 +- research/weave/stages/corpus.py | 70 +++++- research/weave/stages/gonol.py | 101 ++++++++- research/weave/stages/inter.py | 52 +++-- research/weave/stages/join.py | 65 +++++- research/weave/stages/split.py | 65 +++++- research/weave/test.py | 69 ++++++ research/weave/tests/test_transport.py | 259 ++++++++++++++++++++++ research/weave/transport.py | 93 ++++++++ 18 files changed, 1298 insertions(+), 69 deletions(-) create mode 100644 .github/workflows/weave.yml create mode 100644 research/weave/IMPLEMENTATION_PLAN.json create mode 100644 research/weave/IMPLEMENTED.md create mode 100644 research/weave/QUESTIONS.md create mode 100644 research/weave/evidence/transport-v1.json create mode 100644 research/weave/lab.py create mode 100644 research/weave/profiles/transport.json create mode 100644 research/weave/test.py create mode 100644 research/weave/tests/test_transport.py create mode 100644 research/weave/transport.py diff --git a/.github/workflows/weave.yml b/.github/workflows/weave.yml new file mode 100644 index 00000000..bb380c15 --- /dev/null +++ b/.github/workflows/weave.yml @@ -0,0 +1,34 @@ +name: Weave modular experiments +on: + pull_request: + paths: + - 'research/weave/**' + - '.github/workflows/weave.yml' + push: + branches: [main] + paths: + - 'research/weave/**' + - '.github/workflows/weave.yml' + workflow_dispatch: +permissions: + contents: read +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Fetch exact source without unpinned action dependencies + env: + SOURCE_SHA: ${{ github.event.pull_request.head.sha || github.sha }} + run: | + set -euo pipefail + git init . + git remote add origin https://github.com/The-Interdependency/stack.git + git fetch --depth=1 origin "$SOURCE_SHA" + git checkout --detach FETCH_HEAD + test "$(git rev-parse HEAD)" = "$SOURCE_SHA" + - name: Verify assembly and provisional transport, not native cipher security + run: | + set -euo pipefail + python3 -VV + PYTHONDONTWRITEBYTECODE=1 python3 research/weave/test.py --receipt "$RUNNER_TEMP/weave-check.json" + cat "$RUNNER_TEMP/weave-check.json" diff --git a/research/weave/IMPLEMENTATION_PLAN.json b/research/weave/IMPLEMENTATION_PLAN.json new file mode 100644 index 00000000..09d3cc6c --- /dev/null +++ b/research/weave/IMPLEMENTATION_PLAN.json @@ -0,0 +1,19 @@ +{ + "schema": "weave.provisional-implementation-plan/v1", + "source": "The-Interdependency/stack@200032dba6131145ebc61b52bb4f1aee507e6f63", + "instruction": "Implement what can be with available answers; expose questions and probable answers for correction, improvement or approval.", + "claim": "Executable modular transport candidate and native-source adapter; not the complete asymmetric Weave construction.", + "selected_provisional_answers": { + "partition": "Sequential balanced quotient/remainder; retain empty sections; no minimum stage count.", + "split": "Explicit occurrence-to-lane route; cyclic routing is a named transport-only example, not the missing native complementary-thread law.", + "corpus": "Named traversal candidate: actual selected corpus bits choose left/right consumption of lane occurrences; inverse recomputes independently from material.", + "join": "Explicit lane visitation order repeated until exhausted; preserve each lane's internal order.", + "native": "Read/recover existing native UCHC word/glyph/definition objects at the inspected source identity; do not substitute a general plaintext gonol.", + "unknown": "Native key/binding, whole-message admission, native thread projection and corpus-origin geometry remain unimplemented." + }, + "files": ["stages/api.py", "assembly.py", "stages/split.py", "stages/corpus.py", "stages/inter.py", "stages/join.py", "stages/gonol.py", "transport.py", "lab.py", "tests/test_transport.py", "profiles/transport.json", "IMPLEMENTED.md"], + "boundaries": {"network": "none during execution", "files": "CLI reads explicitly supplied paths and writes new output files only", "secrets": "no private key/corpus bytes in receipts", "authority": "no upstream producer or libs changes"}, + "verification": ["native refusals", "exact inverses", "all switch combinations", "actual corpus contribution", "separate-process recovery", "wrong-material and malformed-input behavior", "no source/trace-assisted inverse"], + "rollout": "Explicit transport profile only; full profile remains default and refuses unresolved laws.", + "rollback": "Revert this workspace-local commit; retain sealed run-1 evidence." +} diff --git a/research/weave/IMPLEMENTED.md b/research/weave/IMPLEMENTED.md new file mode 100644 index 00000000..99d2f3f1 --- /dev/null +++ b/research/weave/IMPLEMENTED.md @@ -0,0 +1,143 @@ +# Weave — executable provisional stages + +**Delivered:** a five-stage transport experiment, each stage independently switchable, +plus a source-pinned native-word adapter. **Not delivered:** a complete native asymmetric +Weave cipher. The all-on native profile remains the default and reports unresolved +operations before processing input. No native operation is silently replaced. + +This work implements the instruction to act on available proposed answers and return +remaining questions for correction, improvement or approval. The concrete corpus +left/right formula, cyclic split example and cyclic join example are explicitly new +assistant-selected trial rules. They are not attributed to Erin or made canonical. + +## What executes + +| Module | Implemented operation | Standing | +|---|---|---| +| `stages/split.py` | Route each source bit occurrence exactly once to an explicitly assigned lane; reconstruct original order. | Transport candidate; native complementary-gonol thread law remains open. | +| `stages/corpus.py` | Use actual selected corpus bits to choose left/right consumption of each lane; recompute the inverse from the same material. | New provisional traversal variant, not native origin/axis binding. | +| `stages/inter.py` | Sequential last/first section operations, with exact supplied boundaries or balanced quotient/remainder generation. | Literal operation with an explicitly provisional partition policy. | +| `stages/join.py` | Interlace lanes in a supplied repeating visitation order; recover exact lane lengths and order. | Explicit transport route, not a native private route generator. | +| `stages/whole.py` | Last/first inward interleaving across the entire joined stream. | Existing literal operation preserved byte-for-byte. | +| `stages/gonol.py` | Verify the inspected UCHC source blob and caller-pinned database, then use actual `promote_word`/`recover_word` objects. | Adapter written; missing-input/source-refusal tested; successful native corpus replay NOT executed here. | +| `stages/key.py`, `stages/bind.py` | Existing explicit interfaces and missing-law refusal. | Native key generation and private-gonol recovery algebra unimplemented. | +| `stages/auth.py` | Independent optional switch; enabled use requires a real supplied law. | Authentication/replay unimplemented. | + +The runnable profile composes **split → corpus traversal → arity interleaves → join → +whole interleave**, and reverses that composition. It acts on explicitly admitted +transport bits. It does not call those bits a gonol or relabel this profile as Weave. + +## Run from a phone-oriented Python environment + +Python 3.11+ and its standard library are sufficient for the transport experiment. +The local evidence here was produced with Python 3.13.5; Android execution was not +observed. From `research/weave/` or the extracted bundle: + +```sh +python run.py demo +python test.py --receipt /tmp/weave-check.json +python run.py +``` + +The first runs a nonsecret demonstration. The second runs all local tests. The third +shows the full native profile's unresolved laws and returns exit status 2. + +For actual file experiments, supply each selected material explicitly: + +```sh +python run.py enc profiles/transport.json input.bin output.lab \ + --material a=book.txt --material b=manual.txt --material c=sound.bin +python run.py dec profiles/transport.json output.lab recovered.bin \ + --material a=book.txt --material b=manual.txt --material c=sound.bin +``` + +This is **not safe storage for real secrets**. Files are never overwritten. Output +`.lab` files are research records, not a chosen production cipher format. They carry +switch/operator identities and packed bits; they do not carry corpus content or +secret native reconstruction state. The separate profile remains necessary input. +The message and each supplied material file are capped at 64 KiB as a declared runtime +resource guard, not a cryptographic or mathematical limit. The experiment also caps +thread count at 63 and each schedule at 64 stages/arity 4096 for the same reason. + +## Switches and absent dependencies + +`profiles/transport.json` explicitly disables `key`, `gonol`, `bind`, and `auth`. +It is selected only by demo/enc/dec. `run.py` without that command retains full native +scope. Every switch is a literal Boolean; unknown/misspelled fields fail. + +Off means that stage and its inverse do not run. Corpus off reads no supplied corpus +path, passes no corpus material to later stages and compiles no stale corpus control. +Other switches do not change automatically. Turning join off while leaving multiple +lanes and whole on is an incompatible configuration, not a result against the design. +Opaque third-party callbacks remain responsible for their declared dependencies; +this runner is not a sandbox against callbacks hiding private data in closures. + +All transport operators carry `scope='transport'`. Even if combined with additional +operators, their result cannot be classified as a full-native profile experiment. +Wiring fixtures remain separately labelled and disabled unless explicitly permitted. + +## Verification + +The source-bound receipt is `evidence/transport-v1.json`. Tests include original assembly +regressions, 512 assembly switch combinations, all 32 transport switch combinations +(28 executable; four incompatible), all 8,191 binary inputs of lengths 0–12, unequal and +empty sections, exact byte recovery at 64 KiB, and independent-process recovery after +deleting the original input file. There are no skipped tests. + +The corpus-content witness demonstrates a real effect: changing actual material changes +a declared case's output, while renaming identical material does not. Disabling corpus +removes that influence. This does not imply every material is distinct or adds entropy: +all-zero material selects left-to-right traversal, all-one selects reverse traversal, +and unused material bits have no effect. Equivalent traversals remain possible. + +The test suite also records **limitations**, not hidden successes: fixed-map recovery +succeeds against this complete transport candidate at 137 bits in eight selected-input +queries; wrong material can return incorrect bytes without an integrity error. These +are observations about the explicitly chosen transport variant, not the unimplemented +native gonol/private-key/corpus relations or a verdict on Weave. No independent +researcher reviewed these tests. Fresh-process recovery is not an independent-author +implementation. + +## Native source boundary + +The optional reader consumes UCHC `human/english/english_gonol/hyperspace_construct.py` +at Git blob `8b55823805c87ad8c4cc9d7451dc2eb90bdedd3a`. It verifies the exact source +before execution and opens a caller-digest-bound `construct.db` read-only. It returns +an actual upstream `WordGonol`, not a generic message tree. A hash match is source +identity, not full-corpus validation. No constructed corpus database was materialized +here, so successful native replay is explicitly NOT EXECUTED. No small fabricated +corpus is presented as a full-corpus replacement. + +Whole-message/binary admission, nested native serialization, private-gonol binding, +public/private key derivation and native complementary-thread construction remain +separate unfinished implementation/research work. The reader is not automatically +bound to the complete `gonol` stage because its admitted scope is narrower. + +## Questions and change control + +Read `QUESTIONS.md`: Q1–Q10 each pair an unresolved choice with a proposed answer, +current implementation status and the exact distinction that must survive correction. +Approving a research direction does not require Erin to supply its proof or code. + +## Provenance, deployment and rollback + +Starting Stack identity: `200032dba6131145ebc61b52bb4f1aee507e6f63` on existing PR #62. +No `libs/` snapshot, upstream constructor or root project lifecycle is modified. +The source file plan and non-transfer boundaries are in `IMPLEMENTATION_PLAN.json`. +The original run-1 probe and assembly test source were recovered byte-exactly and +checked against their Git blob identities before use. Old sealed receipts are not +rewritten as evidence for new code. + +Rollout is manual research plus path-scoped CI. Revert this workspace-local change to +roll back; retained historical evidence remains available. Usage of `the-interdependency`, +`meta-module-build`, `msdmd`, and `gonol-build` shaped scope, source ownership, native +metadata and validation. This records their contribution, not an invented maturity +count. The canonical skill-usage runner was not available in this local checkout; +its persistent usage counter was not updated. METAPAT's domain-owned-mechanism boundary +was consulted; no cryptographic result is inferred from it. + +## hmmm + +The coded proposals are ready to correct, improve or approve. The complete native cipher +remains unimplemented. Transport execution, source verification and API refusal do not +replace its missing constitutive relations. diff --git a/research/weave/QUESTIONS.md b/research/weave/QUESTIONS.md new file mode 100644 index 00000000..38da722d --- /dev/null +++ b/research/weave/QUESTIONS.md @@ -0,0 +1,102 @@ +# Weave — questions and provisional answers + +These are proposals for Erin to correct, improve or approve. Implementation does not +constitute approval. Existing Q1–Q10 identities from ASSEMBLY.md are retained. + +## Q6 — Stage composition and uneven partitions +**Question:** Should each arity act on the preceding output, with the remainder assigned +left-to-right? **Proposed answer:** Yes. First r sections get one extra bit; preserve +empty sections if arity exceeds length. Preserve supplied repetitions and allow one +stage. **Implemented provisionally**, independently reversible and tested. Arity is +not level count, and thread count is a third distinct parameter. + +## Q3 — What are the threads? +**Question:** Are they complementary native contributions from one full plaintext +gonol, rather than independent copies or arbitrary byte chunks? +**Proposed answer:** Complementary native contributions, retaining occurrence identities +and cross-thread relations. **Native rule still open.** Implemented now: exact +occurrence-to-lane routing and inverse; the demo chooses cyclic assignment. That is an +explicit transport witness, not a claim to have implemented the native projection or +proved every thread necessary. Repeated/structured inputs may be recoverable from less. + +## Q4 — What should the actual corpus do? +**Question:** Should material govern traversal, supply native axes/origin attachments, +change values, or combine these roles? +**Proposed answer:** Keep traversal and native-context variants distinct, and compare +both inside the eventual full construction. **A traversal trial is implemented:** +material bit 0 consumes the left end of the current lane, bit 1 the right end. Bits are +MSB-first, starting at the specified offset and repeating when exhausted. This exact +formula is a new assistant proposal, NOT a rule previously attributed to Erin. It +uses content, not a filename hash or XOR mask. Only the visited material bits influence +a run; unused material is not counted as secrecy. Native axes/origin binding remains open. + +## Q5 — Joining and the final operation +**Question:** How should transformed threads be interlaced, and when is the final pass? +**Proposed answer:** An explicit context-derived lane route, then one final last/first +pass over the whole joined stream. **Supplied routes are implemented.** The demo cycles +through [2,0,1], skipping exhausted lanes; it does not derive that route from a key. +A private/native route generator still needs its constitutive relation. + +## Q1 — Native plaintext admission +**Question:** Should one native admission cover arbitrary binary files, alongside +language-aware constructions for admitted text? +**Proposed answer:** Yes; preserve exact bytes without normalization. **Implemented: +a source-pinned read/recovery adapter for already-constructed UCHC words.** That returns +the actual upstream object, not a new label tree. General binary admission, +whole-message native composition and its transport serialization remain open. The +adapter's successful real-corpus path has NOT been executed in this session. + +## Q2 — Private gonol and public counterpart +**Question:** Does the private gonol restore a missing origin/attachment relation, +a member, an embedding, or another constitutive relation? +**Proposed answer:** First examine a private origin/attachment relation that selects +the recoverable embedding, paired with a public forward construction. **Unimplemented.** +The research task is to derive concrete native maps and test inversion; approval of +this direction is not a proof, and Erin is not being asked to supply one. No password +check, random permutation seed or conventional cryptosystem substitutes for it. + +## Q7 — What can an independent sender know? +**Question:** Must the sender operate using public-side material without recipient +private-gonol knowledge or private schedules? +**Proposed answer:** Yes, for the intended noninteractive asymmetric mode. Secret +corpus selections must have a usable public forward counterpart where needed. +**The API separates the two sides; the mathematical relation is not implemented.** +The transport experiment supplies the same explicit routing/material recipe to both +sides and makes no asymmetric claim. + +## Q8 — Control derivation and recovery order +**Question:** Are thread counts, routes, corpus locations and arities derived from the +native key/context rather than simply stored as a private plan? +**Proposed answer:** Derive them from native key relations plus available message +context. Reverse operations must obtain needed controls before they need to recover +the hidden content those controls protect. **Explicit control execution is implemented; +native derivation remains open.** Forward and recovery compile the transport recipe +independently; no encoder trace is supplied to recovery. + +## Q9 — Repeated-message variation +**Question:** Should repeated input under one public key produce distinct outputs? +**Proposed answer:** Yes: fresh per-message input should alter applicable native +relations/controls; a fixed value allows deterministic tests. **No native randomness +coupling is implemented.** Merely appending a nonce is not used as a substitute. + +## Q10 — Integrity, length and replay +**Question:** Must modified, incomplete and replayed messages be rejected, and which +metadata may be public? +**Proposed answer:** Require those properties for a usable final encryption profile; +retain a distinct integrity/state module and choose its actual mechanism explicitly. +**Unimplemented.** The lab format checks syntax, lengths and experiment identities, +but does not authenticate data. Wrong material or a same-length bit change can return +incorrect bytes without an integrity error. Lab recipe metadata is not a selected +production ciphertext format. + +## Usage + +Reply using the existing Q numbers, for example “Q4: corpus supplies origin attachments; +keep the traversal candidate only for comparison.” Each changed answer can be traced +to the owning module and tested without silently changing the others. + +## hmmm + +The working transport is not the desired native encryption construction. Questions +Q1–Q4 and Q7–Q9 carry the remaining native relations. Concrete rules, not renamed +placeholders or successful transport tests, will close those boundaries. diff --git a/research/weave/assembly.py b/research/weave/assembly.py index a23ddc3a..ce830b50 100644 --- a/research/weave/assembly.py +++ b/research/weave/assembly.py @@ -1,9 +1,8 @@ -"""Switchable full-scope Weave assembly with explicit unresolved operators. +"""Switchable full-scope assembly; missing native laws never become identities. -Usage: Pipeline(switches, operators).encrypt(value, PublicContext(...)). -A missing enabled law refuses before any operator executes. Decryption uses the -same lab recipe and the reverse order. This module defines no ciphertext wire -format and supplies no substitute asymmetric relation. Source/rollout: ASSEMBLY.md. +Usage: Pipeline(switches, operators).encrypt(value, PublicContext(...)). Transport +operators remain explicitly classified even if combined with native operators. +Native state stays inside selected operations. The trace contains no stage payloads. """ from __future__ import annotations from dataclasses import dataclass, field, replace @@ -37,7 +36,7 @@ def complete(self): @dataclass(frozen=True) class Run: - """Lab result. recipe/events are sidecar evidence, NOT ciphertext headers.""" + """Experimental result; recipe/events are not a proposed cipher wire format.""" payload: Any = field(repr=False) recipe: tuple classification: str @@ -85,7 +84,7 @@ def problems(self, context=None): return tuple(problems) def recipe(self): - return (('proposal', 'assembly-v1'), ('key', self.switches['key']), *( + return (('proposal', 'assembly-v2'), ('key', self.switches['key']), *( (s.name, self.switches[s.name], self.operators[s.name].identity if self.switches[s.name] and s.name in self.operators else None) for s in STEPS)) @@ -99,7 +98,7 @@ def plan(self): 'forward_order': [s.name for s in STEPS if self.switches[s.name]], 'inverse_order': [s.name for s in reversed(STEPS) if self.switches[s.name]], 'missing': self.problems(), - 'note': 'Read ASSEMBLY.md: proposed answers do not implement missing native laws.', + 'note': 'IMPLEMENTED.md separates executable proposals from missing native laws.', } def encrypt(self, value, context: PublicContext): @@ -111,7 +110,7 @@ def decrypt(self, encrypted: Run, context: PrivateContext): if type(context) is not PrivateContext: raise TypeError('decrypt requires explicit PrivateContext') if not isinstance(encrypted, Run) or encrypted.direction != 'encrypt': - raise TypeError('supply the encrypted lab result, not an invented wire format') + raise TypeError('supply the encrypted lab result') if encrypted.recipe != self.recipe(): raise ValueError('inverse profile/operator identities differ from forward lab recipe') return self._run(encrypted.payload, context, reverse=True) @@ -123,14 +122,17 @@ def _run(self, value, context, *, reverse): if not self.switches['key']: context = (replace(context, public_key=None, private_key=None) if type(context) is PrivateContext else replace(context, public_key=None)) - events = [] - fixture = False + if not self.switches['corpus']: + context = (replace(context, public_material={}, private_material={}) + if type(context) is PrivateContext else replace(context, public_material={})) + events, fixture, transport = [], False, False for step in reversed(STEPS) if reverse else STEPS: if not self.switches[step.name]: events.append((step.name, 'OFF')) continue op = self.operators[step.name] fixture = fixture or op.fixture + transport = transport or op.scope == 'transport' result = (op.inverse if reverse else op.forward)(value, context) if isinstance(result, Transition): value = result.payload @@ -138,7 +140,7 @@ def _run(self, value, context, *, reverse): else: value = result events.append((step.name, 'EXECUTED')) - classification = ('WIRING_ONLY' if fixture else + classification = ('WIRING_ONLY' if fixture else 'TRANSPORT_CANDIDATE' if transport else 'FULL_PROFILE_EXPERIMENT' if self.switches.complete else 'ABLATION_ONLY') return Run(value, self.recipe(), classification, tuple(events), 'decrypt' if reverse else 'encrypt') diff --git a/research/weave/evidence/transport-v1.json b/research/weave/evidence/transport-v1.json new file mode 100644 index 00000000..408faeda --- /dev/null +++ b/research/weave/evidence/transport-v1.json @@ -0,0 +1,80 @@ +{ + "schema": "weave.transport-evidence/v1", + "status": "PASSED", + "python": "3.13.5", + "tests": 43, + "failures": 0, + "errors": 0, + "skipped": 0, + "source_unchanged": true, + "expected_test_methods": 43, + "coverage_status": "WITNESSED", + "source_sha256": "15ecd585290b2adf6d827d55606fe62189493423ad26b1036ea8f8514a8d534c", + "source_files": { + "assembly.py": "56df26baf35597c3b09c7e4bbc0407043d81a66785c548185d1f97d5ae3c3b8d", + "lab.py": "881d88bfb43235b4b78896b17228a238c18d98420d134b0ad812c6e1aa476b01", + "probe.py": "9649f8ed463ceaa2ad466d8caa9af235bfe7fc3567fc2c17d94ed83f2853ae63", + "profiles/transport.json": "ab297676a7762296db73d991974bbf59c0c03becdba3ed1130e0ecb0db9039b2", + "run.py": "2a6143054ac2cef6ec41bc075b273a1a93ecb4cd15cb092fa5eb3ecdc66d0d5a", + "stages/__init__.py": "f280e5ec37b9e247cf92b7eb1a32035f090bc4d6f1d56031eb7fca69b9aa4ed2", + "stages/api.py": "a5cd49d008d9e9277a41954fed23aa6968640c3e9c880c52d47cb5f53932d72b", + "stages/auth.py": "cbc0d401b62af4ec7d3543de3e472463b04dd2e4b212d313b3c358f85898de67", + "stages/bind.py": "b3ec00d196ef6a50ed59f9625a7fe09e18b36b6a26b3132dde101427f9f364de", + "stages/corpus.py": "4098281aace459f5654ff7e05797530b3297c368620a32fd1e81a271513fe311", + "stages/gonol.py": "d1e8dd80d361e3af0fa5985a1ab668291fdf88b2d9f2d8292772a54c26b7962f", + "stages/inter.py": "15760b57ad3ea79c6ad649a1e87c2f254070ab9b000bde8448c6893bfe05fbbd", + "stages/join.py": "4b6d5986f76bc0d33246769b5155de398b116681ad593a2ae6e8ec33b44c85f6", + "stages/key.py": "1b9e9873d79dbae190d84a614f551098c3233417575ccece687cb0b8ff2320af", + "stages/split.py": "fe84147ec1adf677b826511c8d2a60986bc7a871b3c9102c4cab0724023df0e8", + "stages/whole.py": "fb93035125c1a8ff07a8f57bf233f3b09365e9c587655afa15fb1d5a1bf721b4", + "test.py": "68bacc5770af4f253fb59dc74d6eb4c6b2c2a449f9cae09abcb8fda7372115fe", + "tests/test_assembly.py": "618b97372812c0613ff947dd83939dea16f8fdd040258b618a25b8fd8bcfa62f", + "tests/test_transport.py": "9b45e89f28338fdd3981f9edf7783c48a3039b133800ca889b1b42a929f03da0", + "transport.py": "fa8a6cffdb21291416a38bbafc1aa8d69d927b23cbaf8aea2abdb56d7bf1c7ec", + "verify.py": "9fb597982993a373d7abb0be89bb80a4ed74d84e4a8f74db6dadb74f5942985d" + }, + "coverage": { + "binary_messages": 8191, + "binary_lengths_inclusive": [0, 12], + "assembly_switch_masks": 512, + "transport_switch_masks": 32, + "valid_transport_masks": 28, + "incompatible_transport_masks": 4, + "largest_roundtrip_bytes": 65536, + "separate_process_roundtrip_bytes": 1026 + }, + "full_weave": { + "status": "BLOCKED", + "complete_cipher_implemented": false, + "profile": "full proposed scope", + "switches": { + "key": true, + "gonol": true, + "bind": true, + "split": true, + "corpus": true, + "inter": true, + "join": true, + "whole": true, + "auth": false + }, + "forward_order": ["gonol", "bind", "split", "corpus", "inter", "join", "whole"], + "inverse_order": ["whole", "join", "inter", "corpus", "split", "bind", "gonol"], + "missing": [ + "key: Q2/Q7/Q8, native public/private relation/key input missing", + "gonol: Q1, native operator missing", + "bind: Q2/Q7/Q8, native operator missing", + "split: Q3, native operator missing", + "corpus: Q4/Q7/Q8, native operator missing", + "join: Q5/Q8, native operator missing" + ], + "note": "IMPLEMENTED.md separates executable proposals from missing native laws." + }, + "native_corpus_replay": "NOT_EXECUTED: source inspected; no constructed database materialized here", + "native_adapter_tests": "missing-input/source-identity refusal only; not successful real-corpus replay", + "security_observations": [ + "fixed-map recovery succeeds against this transport candidate at 137 bits in 8 queries", + "wrong material can yield wrong plaintext without an authentication error" + ], + "nonclaim": "No complete native Weave or asymmetric security result; no independent researcher review." +} diff --git a/research/weave/lab.py b/research/weave/lab.py new file mode 100644 index 00000000..054a0196 --- /dev/null +++ b/research/weave/lab.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 +"""Phone-length CLI for explicit transport experiments, not a secure cipher. + +Usage: python lab.py demo + python lab.py enc profile.json input.bin output.lab --material a=path ... + python lab.py dec profile.json output.lab recovered.bin --material a=path ... +Profiles must explicitly turn absent native stages off. All outputs are new files; +existing paths are never overwritten. A lab record discloses experiment switches +and operator identities, not corpus content or private native controls. +""" +from __future__ import annotations +import argparse +import json +from pathlib import Path +import sys +from assembly import Run +from stages.api import Blocked, Streams +from transport import build, byte_stream, recover_bytes, LIMIT + + +def read(path, limit=LIMIT): + with Path(path).open('rb') as stream: + data = stream.read(limit + 1) + if len(data) > limit: + raise ValueError('input exceeds declared resource limit') + return data + + +def strict_json(data): + def pairs(items): + out = {} + for key, value in items: + if key in out: + raise ValueError('duplicate JSON field') + out[key] = value + return out + return json.loads(data, object_pairs_hook=pairs) + + +def wire(result: Run) -> bytes: + lanes = [] + for lane in result.payload.lanes: + padding = (-len(lane)) % 8 + packed = recover_bytes(Streams((lane + (0,) * padding,))) + lanes.append({'bits': len(lane), 'hex': packed.hex()}) + obj = {'schema': 'weave.lab-record/v1', 'classification': result.classification, + 'recipe': result.recipe, 'lanes': lanes} + return json.dumps(obj, separators=(',', ':')).encode('utf-8') + + +def unwire(data: bytes, pipeline) -> Run: + obj = strict_json(data) + if (type(obj) is not dict or set(obj) != {'schema','classification','recipe','lanes'} + or obj['schema'] != 'weave.lab-record/v1' + or obj['classification'] not in ('TRANSPORT_CANDIDATE', 'ABLATION_ONLY')): + raise ValueError('invalid lab record; not a Weave cipher format') + if obj['recipe'] != json.loads(json.dumps(pipeline.recipe())): + raise ValueError('experiment switch/operator recipe mismatch') + lanes = parse_lanes(obj['lanes']) + return Run(lanes, pipeline.recipe(), obj['classification'], (), 'encrypt') + + +def parse_lanes(records): + if type(records) is not list or not 1 <= len(records) <= 63: + raise ValueError('invalid lane count') + out, total = [], 0 + for lane in records: + if type(lane) is not dict or set(lane) != {'bits', 'hex'}: + raise ValueError('invalid lane record') + n, h = lane['bits'], lane['hex'] + if type(n) is not int or n < 0 or type(h) is not str or len(h) != 2*((n+7)//8): + raise ValueError('invalid packed bit length') + total += n + if total > LIMIT * 8: + raise ValueError('message exceeds resource limit') + raw = bytes.fromhex(h) + if raw.hex() != h: + raise ValueError('noncanonical hexadecimal') + bits = byte_stream(raw).lanes[0] + if any(bits[n:]): + raise ValueError('nonzero bit padding') + out.append(bits[:n]) + return Streams(tuple(out)) + + +def main(argv=None): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('mode', choices=('demo', 'enc', 'dec')) + parser.add_argument('profile', nargs='?') + parser.add_argument('input', nargs='?') + parser.add_argument('output', nargs='?') + parser.add_argument('--material', action='append', default=[], metavar='ID=PATH') + args = parser.parse_args(argv) + try: + if args.mode == 'demo': + profile = strict_json((Path(__file__).parent/'profiles/transport.json').read_bytes()) + material = {'a': b'literary test material', 'b': bytes(range(64)), 'c': b'\x00\xff\x55\xaa'} + data = b'Weave: complete specified mechanisms remain the target.\x00\xff' + p, public, _ = build(profile, len(data)*8, material) + record = wire(p.encrypt(byte_stream(data), public)) + # Rebuild from declared inputs, and decode only the serialized result. + q, _, private = build(strict_json(json.dumps(profile)), len(data)*8, dict(material)) + recovered = recover_bytes(q.decrypt(unwire(record, q), private).payload) + if recovered != data: + raise ValueError('demo recovery failed') + print(json.dumps({'status':'PASSED', 'classification':'TRANSPORT_CANDIDATE', + 'bytes':len(data), 'exact_recovery':True, + 'complete_weave':False, 'active':['split','corpus','inter','join','whole']})) + return 0 + if not args.profile or not args.input or not args.output: + parser.error('enc/dec require profile, input and new output path') + profile = strict_json(read(args.profile)) + if type(profile) is not dict or type(profile.get('switches')) is not dict: + raise ValueError('profile and switches must be objects') + material = {} + # Off really means off: unused material paths are not read. + if profile.get('switches', {}).get('corpus', True): + for entry in args.material: + label, sep, path = entry.partition('=') + if not label or not sep or not path or label in material: + raise ValueError('supply unique ID=PATH material choices') + material[label] = read(path) + data = read(args.input, LIMIT if args.mode == 'enc' else 4*LIMIT + 32768) + if args.mode == 'enc': + p, public, _ = build(profile, len(data)*8, material) + result = p.encrypt(byte_stream(data), public) + output = wire(result) + else: + obj = strict_json(data) + if type(obj) is not dict or 'lanes' not in obj: + raise ValueError('invalid lab record') + lanes = parse_lanes(obj['lanes']) + n = sum(map(len, lanes.lanes)) + p, _, private = build(profile, n, material) + result = p.decrypt(unwire(data, p), private) + output = recover_bytes(result.payload) + with Path(args.output).open('xb') as target: + target.write(output) + print(json.dumps({'status':'WRITTEN','classification':result.classification, + 'complete_weave':False,'authenticated':False})) + return 0 + except (OSError, ValueError, TypeError, Blocked, KeyError) as exc: + print(json.dumps({'status':'REFUSED','reason':str(exc)}), file=sys.stderr) + return 2 + + +if __name__ == '__main__': + raise SystemExit(main()) diff --git a/research/weave/profiles/transport.json b/research/weave/profiles/transport.json new file mode 100644 index 00000000..bf0255cb --- /dev/null +++ b/research/weave/profiles/transport.json @@ -0,0 +1,8 @@ +{ + "schema": "weave.transport-profile/v1", + "switches": {"key": false, "gonol": false, "bind": false, "split": true, "corpus": true, "inter": true, "join": true, "whole": true, "auth": false}, + "threads": 3, + "arities": [[5, 7, 3], [7, 3, 5], [3, 5, 7]], + "join_order": [2, 0, 1], + "corpus": [["a", 0], ["b", 1], ["c", 2]] +} diff --git a/research/weave/run.py b/research/weave/run.py index 25a1697c..7aabc527 100644 --- a/research/weave/run.py +++ b/research/weave/run.py @@ -1,15 +1,19 @@ #!/usr/bin/env python3 -"""Phone-sized Weave plan entrypoint. Usage: python run.py --off corpus --on auth. +"""Phone-sized Weave entrypoint: python run.py demo; python run.py --off corpus. -Prints exact switches and missing laws. No file writes, network, automatic native -imports or encryption claims. Exit 2 = unresolved; exit 0 = plan has no blockers. +The default full plan reports missing native laws. demo/enc/dec explicitly select +the separate transport experiment CLI. Neither is a production cipher. """ import argparse import json +import sys from assembly import DEFAULTS, Pipeline, Switches def main(): + if len(sys.argv) > 1 and sys.argv[1] in ('demo', 'enc', 'dec'): + from lab import main as experiment + return experiment(sys.argv[1:]) parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--off', action='append', choices=tuple(DEFAULTS), default=[]) parser.add_argument('--on', action='append', choices=tuple(DEFAULTS), default=[]) diff --git a/research/weave/stages/api.py b/research/weave/stages/api.py index 4084fc72..15e5973a 100644 --- a/research/weave/stages/api.py +++ b/research/weave/stages/api.py @@ -1,8 +1,8 @@ -"""Typed operator contracts, not cryptographic constructions. +"""Operator contracts; native objects retain their owners and identities. -Usage: supply explicit Operator(forward, inverse, identity) instances to Pipeline. -No network or storage. Native payloads pass unchanged except through selected operators. -Roll back by removing this assembly; no producer code is changed. +Usage: supply source-identified Operator instances to assembly.Pipeline. A transport +candidate cannot earn a whole-Weave classification. Contexts are in-memory inputs, +not ciphertext headers. No network, storage or key generation occurs here. """ from __future__ import annotations from dataclasses import dataclass, field @@ -11,7 +11,7 @@ class Blocked(RuntimeError): - """An enabled law/input is missing; execution must not silently bypass it.""" + """An enabled operation or required input is unresolved.""" @dataclass(frozen=True) @@ -43,7 +43,7 @@ def __post_init__(self): @dataclass(frozen=True) class Streams: - """Exact bit streams; not a gonol, key or native thread-generation law.""" + """Exact bit lanes, not a replacement gonol or secret-sharing construction.""" lanes: tuple[tuple[int, ...], ...] = field(repr=False) def __post_init__(self): @@ -58,11 +58,11 @@ def __post_init__(self): @dataclass(frozen=True) class Operator: - """A real transformation pair plus provenance; fixture is never full evidence.""" forward: Callable[[Any, PublicContext], Any] = field(repr=False) inverse: Callable[[Any, PrivateContext], Any] = field(repr=False) identity: str fixture: bool = False + scope: str = 'native' def __post_init__(self): if not callable(self.forward) or not callable(self.inverse): @@ -71,6 +71,8 @@ def __post_init__(self): raise ValueError('an explicit law/source identity is required') if type(self.fixture) is not bool: raise TypeError('fixture flag must be Boolean') + if self.scope not in ('native', 'transport'): + raise ValueError('operator scope must be native or transport') @dataclass(frozen=True) @@ -84,11 +86,6 @@ class Step: @dataclass(frozen=True) class Transition: - """A stage may pass derived working parameters to later stages, not ciphertext. - - This preserves coupled, message-dependent constructions. The inverse key law - must independently make whatever reverse parameters are needed available. - Updates are not copied into receipts and do not supply a missing private law. - """ + """Working state only: inverse controls must be reconstructed independently.""" payload: Any = field(repr=False) parameters: Mapping[str, Any] = field(default_factory=dict, repr=False) diff --git a/research/weave/stages/corpus.py b/research/weave/stages/corpus.py index 9532cafb..f9a6ca80 100644 --- a/research/weave/stages/corpus.py +++ b/research/weave/stages/corpus.py @@ -1,10 +1,66 @@ -"""Use actual thread-associated corpus content in the selected native relation. +"""Actual-material traversal candidate; native corpus-origin binding remains open. -Usage: bind a source-identified Operator to 'corpus' in Pipeline. Toggle only 'corpus'. -The native transformation is unresolved (Q4/Q7/Q8); this module declares its -interface and never supplies a fake identity, hash, XOR or conventional-cipher fallback. -No network or storage. See ASSEMBLY.md for the proposed answer and rollback. +Usage: content_route_operator(); parameters['corpus'] = ((material_id, bit_offset), ...). +Selected material bytes are supplied in context.public_material, never taken from a +filename hash. Bit 0 consumes the current left end; bit 1 consumes the right end. +Material bits are MSB-first and repeat cyclically. This concrete rule is a NEW, +explicit assistant proposal for correction, not a recovered requirement or cipher. +Inverse recomputes the traversal from material, without an encoder trace. """ -from .api import Step +from collections import deque +from .api import Blocked, Operator, Step, Streams -STEP = Step('corpus', ('Q4', 'Q7', 'Q8'), 'Use actual thread-associated corpus content in the selected native relation.', required=True) + +def route(size: int, material: bytes, offset: int = 0) -> tuple[int, ...]: + if type(size) is not int or size < 0: + raise ValueError('nonnegative bit length required') + if type(material) is not bytes or not material: + raise ValueError('nonempty actual corpus bytes required') + if type(offset) is not int or offset < 0: + raise ValueError('nonnegative corpus bit offset required') + remaining = deque(range(size)) + out = [] + for i in range(size): + p = (offset + i) % (8 * len(material)) + right = (material[p // 8] >> (7 - p % 8)) & 1 + out.append(remaining.pop() if right else remaining.popleft()) + return tuple(out) + + +def transform(value, context, reverse=False): + if not isinstance(value, Streams): + raise TypeError('corpus traversal requires Streams') + choices = context.parameters.get('corpus') + if type(choices) is not tuple or len(choices) != len(value.lanes): + raise Blocked('corpus: select material and bit offset for every lane') + out = [] + for lane, choice in zip(value.lanes, choices): + if type(choice) is not tuple or len(choice) != 2 or type(choice[0]) is not str: + raise ValueError('invalid corpus choice') + label, offset = choice + if label not in context.public_material: + raise Blocked('corpus: forward-accessible material is missing') + order = route(len(lane), context.public_material[label], offset) + if reverse: + restored = [0] * len(lane) + for destination, source in enumerate(order): + restored[source] = lane[destination] + out.append(tuple(restored)) + else: + out.append(tuple(lane[i] for i in order)) + return Streams(tuple(out)) + + +def forward(value, context): + return transform(value, context) + + +def inverse(value, context): + return transform(value, context, True) + + +def content_route_operator() -> Operator: + return Operator(forward, inverse, 'transport/corpus-end-route-v1', scope='transport') + + +STEP = Step('corpus', ('Q4', 'Q7', 'Q8'), 'Native corpus/thread relation remains unresolved.') diff --git a/research/weave/stages/gonol.py b/research/weave/stages/gonol.py index e8de0c4b..d49b786b 100644 --- a/research/weave/stages/gonol.py +++ b/research/weave/stages/gonol.py @@ -1,10 +1,97 @@ -"""Complete native plaintext construction and exact recovery. +"""Native UCHC word inspection/recovery; whole-message gonol law remains open. -Usage: bind a source-identified Operator to 'gonol' in Pipeline. Toggle only 'gonol'. -The native transformation is unresolved (Q1); this module declares its -interface and never supplies a fake identity, hash, XOR or conventional-cipher fallback. -No network or storage. See ASSEMBLY.md for the proposed answer and rollback. +Usage: with NativeWords(source_path, construct_db, expected_db_sha256) as native: + word = native.promote(b'word'); recovered = native.recover(word) +The inspected upstream source blob is checked BEFORE execution. The database is +opened read-only after matching the caller's snapshot digest. This adapter returns +actual upstream WordGonol objects; it does not construct a replacement gonol tree, +serialize arbitrary binary as fake glyphs, or automatically bind the full stage. +A matching database hash is provenance, not proof of full-corpus construction. """ -from .api import Step +from __future__ import annotations +import hashlib +import importlib.util +from pathlib import Path +import re +import sqlite3 +import sys +from .api import Blocked, Step -STEP = Step('gonol', ('Q1',), 'Complete native plaintext construction and exact recovery.', required=True) +SOURCE_BLOB = '8b55823805c87ad8c4cc9d7451dc2eb90bdedd3a' +SOURCE_REPOSITORY = 'The-Interdependency/uchc' +SOURCE_PATH = 'human/english/english_gonol/hyperspace_construct.py' + + +class NativeWords: + """Read/replay native word records only. Not a general message encoder.""" + def __init__(self, source: Path, database: Path, expected_database_sha256: str): + self.source, self.database = Path(source), Path(database) + self.expected_database_sha256 = expected_database_sha256 + self.db, self.native = None, None + + def __enter__(self): + if (type(self.expected_database_sha256) is not str + or not re.fullmatch('[0-9a-f]{64}', self.expected_database_sha256)): + raise ValueError('explicit lowercase database SHA-256 required') + if not self.source.is_file() or not self.database.is_file(): + raise Blocked('native UCHC source and constructed corpus database are required') + content = self.source.read_bytes() + identity = hashlib.sha1(b'blob ' + str(len(content)).encode() + b'\0' + content).hexdigest() + if identity != SOURCE_BLOB: + raise Blocked('native source differs from inspected UCHC blob; not imported') + with self.database.open('rb') as stream: + actual = hashlib.file_digest(stream, 'sha256').hexdigest() + if actual != self.expected_database_sha256: + raise Blocked('native database snapshot mismatch') + name = '_weave_uchc_' + SOURCE_BLOB + spec = importlib.util.spec_from_file_location(name, self.source) + if spec is None or spec.loader is None: + raise Blocked('cannot load inspected native source') + module = importlib.util.module_from_spec(spec) + sys.modules[name] = module + try: + # Execute precisely the verified bytes, not a later path reread or pyc. + exec(compile(content, str(self.source), 'exec'), module.__dict__) + self.db = sqlite3.connect(self.database.resolve().as_uri() + '?mode=ro', uri=True) + self.db.execute('PRAGMA query_only = ON') + self.db.execute('BEGIN') + self.native = module + except BaseException: + if self.db is not None: + self.db.close() + self.db = None + sys.modules.pop(name, None) + raise + return self + + def promote(self, value: bytes): + if self.db is None or self.native is None: + raise RuntimeError('native reader is not open') + if type(value) is not bytes: + raise TypeError('exact UTF-8 word bytes required') + try: + surface = value.decode('utf-8', errors='strict') + except UnicodeDecodeError as exc: + raise Blocked('arbitrary binary gonol admission remains unresolved') from exc + rows = self.db.execute('SELECT id FROM words WHERE surface = ?', (surface,)).fetchall() + if len(rows) != 1: + raise Blocked('input must match exactly one already-constructed native word') + return self.native.promote_word(self.db, rows[0][0])[0] + + def recover(self, word) -> bytes: + if self.db is None or self.native is None: + raise RuntimeError('native reader is not open') + if type(word) is not self.native.WordGonol: + raise TypeError('the original native WordGonol type is required') + rebuilt = self.native.recover_word(self.db, word.word_id) + if rebuilt != word: + raise ValueError('native identity, constituents, order or surface differs') + return rebuilt.surface.encode('utf-8') + + def __exit__(self, *exc): + if self.db is not None: + self.db.close() + self.db, self.native = None, None + + +STEP = Step('gonol', ('Q1',), 'Complete native plaintext construction and exact recovery.') diff --git a/research/weave/stages/inter.py b/research/weave/stages/inter.py index 20b34d3f..e89d9b38 100644 --- a/research/weave/stages/inter.py +++ b/research/weave/stages/inter.py @@ -1,27 +1,53 @@ -"""Specified section-local last/first operation, with explicit sequential partitions. +"""Literal last/first interleave with explicit or proposed balanced partitions. -Usage: PublicContext/PrivateContext.parameters['inter'] = tuple of per-lane stage -partitions; each partition is the exact tuple of positive section lengths. -No default arity schedule, remainder rule, thread route or minimum stage count. -This explicit sequential profile is a proposal, not an additional user requirement. -No network/storage; rollback by disabling 'inter' for a labelled ablation. +Usage: parameters['inter'] = per-lane tuples of exact partition tuples. +Use balanced_schedule(n, arities) to select the provisional quotient/remainder +rule: first r sections gain one bit, including explicit empty sections if a > n. +Stages consume prior output; section order and all supplied repetitions survive. +There is no three-stage minimum. The sealed run-1 probe is left unchanged. """ -from probe import section_stage +from probe import inward, inverse_inward from .api import Blocked, Operator, Step, Streams +def balanced_partition(size: int, arity: int) -> tuple[int, ...]: + if type(size) is not int or size < 0 or type(arity) is not int or arity < 3: + raise ValueError('nonnegative size and arity >= 3 required') + q, r = divmod(size, arity) + return tuple(q + (i < r) for i in range(arity)) + + +def balanced_schedule(size: int, arities: tuple[int, ...]) -> tuple[tuple[int, ...], ...]: + if type(arities) is not tuple or not arities: + raise ValueError('supply a nonempty schedule; switch inter off for omission') + return tuple(balanced_partition(size, a) for a in arities) + + +def section(items: tuple, lengths: tuple[int, ...], reverse=False) -> tuple: + if (type(lengths) is not tuple or len(lengths) < 3 + or any(type(v) is not int or v < 0 for v in lengths) + or sum(lengths) != len(items)): + raise ValueError('partition must account for all bits with nonnegative lengths') + transform = inverse_inward if reverse else inward + out, start = [], 0 + for length in lengths: + out.extend(transform(items[start:start + length])) + start += length + return tuple(out) + + def transform(value, context, reverse=False): if not isinstance(value, Streams): - raise TypeError('inter requires Streams from the selected upstream native law') + raise TypeError('inter requires Streams from an explicit upstream law/profile') plans = context.parameters.get('inter') if type(plans) is not tuple or len(plans) != len(value.lanes): - raise Blocked('inter: Q6 requires explicit partitions for every lane') + raise Blocked('inter: explicit partitions required for every lane') out = [] for lane, stages in zip(value.lanes, plans): if type(stages) is not tuple or not stages: - raise Blocked('inter: supply a nonempty explicit stage sequence per lane') + raise Blocked('inter: a nonempty stage sequence is required') for partition in reversed(stages) if reverse else stages: - lane = section_stage(lane, partition, reverse=reverse) + lane = section(lane, partition, reverse) out.append(lane) return Streams(tuple(out)) @@ -34,5 +60,5 @@ def inverse(value, context): return transform(value, context, True) -STEP = Step('inter', ('Q6',), 'Exact section-local last/first interleave.', - builtin=Operator(forward, inverse, 'literal-section/sequential-explicit-v1')) +STEP = Step('inter', ('Q6',), 'Literal section-local last/first interleave.', + builtin=Operator(forward, inverse, 'literal-section/sequential-empty-aware-v2')) diff --git a/research/weave/stages/join.py b/research/weave/stages/join.py index 70c8b534..4f95f041 100644 --- a/research/weave/stages/join.py +++ b/research/weave/stages/join.py @@ -1,10 +1,61 @@ -"""Interlace and recover threads under the exact selected route. +"""Explicit stable lane interlacing; not an invented secret native join law. -Usage: bind a source-identified Operator to 'join' in Pipeline. Toggle only 'join'. -The native transformation is unresolved (Q5/Q8); this module declares its -interface and never supplies a fake identity, hash, XOR or conventional-cipher fallback. -No network or storage. See ASSEMBLY.md for the proposed answer and rollback. +Usage: parameters['join'] = (lane_lengths, lane_order). Visit each named lane once +per cycle and skip only exhausted lanes. Exact lengths/order come independently +from the research profile on both sides, not from an encoder trace or ciphertext. """ -from .api import Step +from .api import Blocked, Operator, Step, Streams -STEP = Step('join', ('Q5', 'Q8'), 'Interlace and recover threads under the exact selected route.', required=True) + +def route(lengths: tuple[int, ...], order: tuple[int, ...]) -> tuple[int, ...]: + if (type(lengths) is not tuple or not lengths + or any(type(n) is not int or n < 0 for n in lengths)): + raise ValueError('invalid lane lengths') + if (type(order) is not tuple or any(type(i) is not int for i in order) + or sorted(order) != list(range(len(lengths)))): + raise ValueError('lane order must visit every lane exactly once per cycle') + left, out = list(lengths), [] + while any(left): + for owner in order: + if left[owner]: + out.append(owner) + left[owner] -= 1 + return tuple(out) + + +def plan(context): + value = context.parameters.get('join') + if type(value) is not tuple or len(value) != 2: + raise Blocked('join: explicit lengths and lane order required') + lengths, order = value + return lengths, route(lengths, order) + + +def forward(value, context): + lengths, owners = plan(context) + if not isinstance(value, Streams) or tuple(map(len, value.lanes)) != lengths: + raise ValueError('join input lengths differ from declared route') + cursors, out = [0] * len(lengths), [] + for owner in owners: + out.append(value.lanes[owner][cursors[owner]]) + cursors[owner] += 1 + return Streams((tuple(out),)) + + +def inverse(value, context): + lengths, owners = plan(context) + if not isinstance(value, Streams) or len(value.lanes) != 1: + raise TypeError('join inverse requires one interlaced stream') + if len(value.lanes[0]) != len(owners): + raise ValueError('joined length differs from declared route') + lanes = [[] for _ in lengths] + for bit, owner in zip(value.lanes[0], owners): + lanes[owner].append(bit) + return Streams(tuple(tuple(lane) for lane in lanes)) + + +def explicit_join_operator() -> Operator: + return Operator(forward, inverse, 'transport/explicit-stable-join-v1', scope='transport') + + +STEP = Step('join', ('Q5', 'Q8'), 'Native key/context-derived join law remains unresolved.') diff --git a/research/weave/stages/split.py b/research/weave/stages/split.py index 9ea69c95..f0d67a81 100644 --- a/research/weave/stages/split.py +++ b/research/weave/stages/split.py @@ -1,10 +1,61 @@ -"""Generate the required logical thread streams without discarding cross-relations. +"""Explicit occurrence routing, not the missing native thread projection law. -Usage: bind a source-identified Operator to 'split' in Pipeline. Toggle only 'split'. -The native transformation is unresolved (Q3); this module declares its -interface and never supplies a fake identity, hash, XOR or conventional-cipher fallback. -No network or storage. See ASSEMBLY.md for the proposed answer and rollback. +Usage: Operator = explicit_route_operator(); context.parameters['split'] is +(thread_count, owners), with one owner per incoming bit occurrence. The cyclic +route helper is a named transport-only proposal. No native law is auto-bound. +No data copies per lane: every occurrence is assigned once, including empty lanes. """ -from .api import Step +from .api import Blocked, Operator, Step, Streams -STEP = Step('split', ('Q3',), 'Generate the required logical thread streams without discarding cross-relations.', required=True) + +def cyclic_route(size: int, count: int) -> tuple[int, ...]: + """Provisional transport routing; gives no per-thread confidentiality.""" + if type(size) is not int or size < 0 or type(count) is not int or count < 3: + raise ValueError('nonnegative length and thread count >= 3 required') + return tuple(i % count for i in range(size)) + + +def plan(context): + value = context.parameters.get('split') + if type(value) is not tuple or len(value) != 2: + raise Blocked('split: provide (thread_count, occurrence_owners)') + count, owners = value + if type(count) is not int or count < 3 or type(owners) is not tuple: + raise ValueError('invalid thread plan') + if any(type(i) is not int or not 0 <= i < count for i in owners): + raise ValueError('route contains an invalid owner') + return count, owners + + +def forward(value, context): + if not isinstance(value, Streams) or len(value.lanes) != 1: + raise TypeError('split requires one serialized input stream; not a gonol substitute') + count, owners = plan(context) + if len(owners) != len(value.lanes[0]): + raise ValueError('split route does not cover every input occurrence') + lanes = [[] for _ in range(count)] + for bit, owner in zip(value.lanes[0], owners): + lanes[owner].append(bit) + return Streams(tuple(tuple(lane) for lane in lanes)) + + +def inverse(value, context): + count, owners = plan(context) + if not isinstance(value, Streams) or len(value.lanes) != count: + raise ValueError('split inverse lane count mismatch') + sizes = tuple(owners.count(i) for i in range(count)) + if tuple(map(len, value.lanes)) != sizes: + raise ValueError('split inverse occurrence counts differ') + cursors = [0] * count + out = [] + for owner in owners: + out.append(value.lanes[owner][cursors[owner]]) + cursors[owner] += 1 + return Streams((tuple(out),)) + + +def explicit_route_operator() -> Operator: + return Operator(forward, inverse, 'transport/explicit-occurrence-route-v1', scope='transport') + + +STEP = Step('split', ('Q3',), 'Native complementary thread law remains unresolved.') diff --git a/research/weave/test.py b/research/weave/test.py new file mode 100644 index 00000000..6d247d0e --- /dev/null +++ b/research/weave/test.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +"""Run all local assembly/transport tests and emit an honest source-bound receipt. + +Usage: python test.py --receipt /tmp/weave-check.json +No dependency installation or network. Native corpus replay is NOT executed by +this suite, and missing native encryption laws are reported separately from PASS. +""" +import argparse +import hashlib +import io +import json +from pathlib import Path +import platform +import sys +import unittest +from assembly import Pipeline + +ROOT = Path(__file__).resolve().parent + + +def snapshot(): + paths = list(ROOT.rglob('*.py')) + list((ROOT/'profiles').glob('*.json')) + return {str(p.relative_to(ROOT)): hashlib.sha256(p.read_bytes()).hexdigest() + for p in sorted(paths) if '__pycache__' not in p.parts} + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--receipt', type=Path) + args = parser.parse_args() + before = snapshot() + report = io.StringIO() + result = unittest.TextTestRunner(stream=report, verbosity=2).run( + unittest.defaultTestLoader.discover(str(ROOT/'tests'))) + after = snapshot() + passed = (result.wasSuccessful() and not result.skipped + and not result.expectedFailures and not result.unexpectedSuccesses + and result.testsRun == 43 and before == after) + receipt = { + 'schema':'weave.transport-evidence/v1', + 'status':'PASSED' if passed else 'FAILED', + 'python':platform.python_version(), + 'tests':result.testsRun, + 'failures':len(result.failures),'errors':len(result.errors),'skipped':len(result.skipped), + 'source_unchanged':before == after, + 'expected_test_methods':43, + 'coverage_status':'WITNESSED' if passed else 'NOT_ACCEPTED', + 'source_sha256':hashlib.sha256(json.dumps(before,sort_keys=True,separators=(',',':')).encode()).hexdigest(), + 'source_files':before, + 'coverage':{'binary_messages':8191,'binary_lengths_inclusive':[0,12], + 'assembly_switch_masks':512,'transport_switch_masks':32, + 'valid_transport_masks':28,'incompatible_transport_masks':4, + 'largest_roundtrip_bytes':65536,'separate_process_roundtrip_bytes':1026}, + 'full_weave':Pipeline().plan(), + 'native_corpus_replay':'NOT_EXECUTED: source inspected; no constructed database materialized here', + 'native_adapter_tests':'missing-input/source-identity refusal only; not successful real-corpus replay', + 'security_observations':['fixed-map recovery succeeds against this transport candidate at 137 bits in 8 queries', + 'wrong material can yield wrong plaintext without an authentication error'], + 'nonclaim':'No complete native Weave or asymmetric security result; no independent researcher review.' + } + sys.stderr.write(report.getvalue()) + if args.receipt: + args.receipt.parent.mkdir(parents=True,exist_ok=True) + args.receipt.write_text(json.dumps(receipt,indent=2)+'\n') + print(json.dumps({key:receipt[key] for key in ('status','tests','failures','errors','skipped','source_sha256')})) + return 0 if passed else 1 + + +if __name__=='__main__':raise SystemExit(main()) diff --git a/research/weave/tests/test_transport.py b/research/weave/tests/test_transport.py new file mode 100644 index 00000000..93dab34f --- /dev/null +++ b/research/weave/tests/test_transport.py @@ -0,0 +1,259 @@ +"""Executable provisional composition tests, not native Weave security acceptance. + +Usage: python -m unittest discover -s tests. Fixed scope: 8,191 binary messages; +32 transport switch masks; separate-process byte recovery; bounded resource and +malformed-input checks. Temporary nonsecret corpus fixtures only. No network. +""" +from copy import deepcopy +from dataclasses import replace +from itertools import product +import json +from pathlib import Path +import subprocess +import sys +import tempfile +import unittest +from assembly import DEFAULTS, Pipeline, Switches +from stages.api import Blocked, Operator, PrivateContext, PublicContext, Streams +from stages.gonol import NativeWords +from stages import corpus, inter, join, split +from transport import build, byte_stream, recover_bytes, LIMIT +from lab import wire, unwire, strict_json, parse_lanes +from probe import inward, section_stage, recover_fixed_map, recover_with_map + +ROOT = Path(__file__).resolve().parents[1] +PROFILE = json.loads((ROOT/'profiles/transport.json').read_text()) +MATERIAL = {'a': b'Actual literary-like fixture.', 'b': bytes(range(64)), 'c': b'\x00\xff\x55\xaa'} + + +def flags(**changes): + p = deepcopy(PROFILE) + p['switches'].update(changes) + return p + + +def two_way(data, profile=PROFILE, material=MATERIAL): + p, public, _ = build(deepcopy(profile), len(data), dict(material)) + encoded = p.encrypt(Streams((data,)), public) + # Build an independent context; pass no earlier Transition or stage snapshot. + q, _, private = build(deepcopy(profile), len(data), dict(material)) + decoded = q.decrypt(unwire(wire(encoded), q), private) + return encoded, decoded + + +class TransportTests(unittest.TestCase): + def test_complete_profile_still_refuses(self): + with self.assertRaises(Blocked): + Pipeline().encrypt(b'not touched', PublicContext(None)) + self.assertEqual(len(Pipeline().plan()['missing']), 6) + + def test_no_native_promotion_by_switching_flags(self): + p = flags(key=True, gonol=True, bind=True) + with self.assertRaises(Blocked): + build(p, 32, MATERIAL) + + def test_full_transport_all_8191_binary_messages(self): + count = 0 + for n in range(13): + for value in range(1 << n): + data = tuple((value >> i) & 1 for i in range(n)) + encoded, decoded = two_way(data) + self.assertEqual(decoded.payload, Streams((data,))) + self.assertEqual(encoded.classification, 'TRANSPORT_CANDIDATE') + self.assertEqual(sum(map(len, encoded.payload.lanes)), n) + count += 1 + self.assertEqual(count, 8191) + + def test_all_32_transport_masks(self): + valid = invalid = 0 + names = ('split','corpus','inter','join','whole') + data = tuple((i*i + i//3) % 2 for i in range(137)) + for bits in product((False, True), repeat=5): + p = flags(**dict(zip(names, bits))) + if not p['switches']['split']: + # Explicitly adapt this test recipe to one lane; no runner cascade. + p['corpus'], p['arities'], p['join_order'] = [['a',0]], [[5,7,3]], [0] + if p['switches']['split'] and not p['switches']['join'] and p['switches']['whole']: + with self.assertRaisesRegex(ValueError, 'incompatible ablation'): + build(p, len(data), MATERIAL) + invalid += 1 + continue + encoded, decoded = two_way(data, p) + self.assertEqual(decoded.payload, Streams((data,))) + for name, status in encoded.events: + self.assertEqual(status == 'EXECUTED', p['switches'][name]) + valid += 1 + self.assertEqual((valid, invalid), (28,4)) + + def test_balanced_sizes_and_empty_sections(self): + for n in range(513): + for a in (3,5,7,11,31): + plan = inter.balanced_partition(n,a) + self.assertEqual(sum(plan), n) + self.assertEqual(len(plan), a) + self.assertLessEqual(max(plan)-min(plan),1) + ids = tuple(range(n)) + self.assertEqual(inter.section(inter.section(ids,plan),plan,True),ids) + self.assertEqual(inter.balanced_partition(2,5),(1,1,0,0,0)) + self.assertEqual(inter.balanced_partition(0,3),(0,0,0)) + + def test_old_equal_section_behavior_preserved(self): + for n in (105,210,840): + for a in (3,5,7): + ids = tuple(range(n)); lengths = (n//a,)*a + self.assertEqual(inter.section(ids,lengths),section_stage(ids,lengths)) + + def test_one_stage_not_three_stages(self): + p = deepcopy(PROFILE); p['arities'] = [[3],[5],[7]] + data = tuple(i%2 for i in range(61)) + self.assertEqual(two_way(data,p)[1].payload,Streams((data,))) + + def test_corpus_content_really_changes_route(self): + self.assertEqual(corpus.route(7,b'\x00'),tuple(range(7))) + self.assertEqual(corpus.route(7,b'\xff'),tuple(reversed(range(7)))) + self.assertEqual(corpus.route(7,b'\xaa'),(6,0,5,1,4,2,3)) + data = tuple([1,0,1,1,0,0,0]*17) + a = two_way(data,material={'a':b'\x00','b':b'\x00','c':b'\x00'})[0] + b = two_way(data,material={'a':b'\xff','b':b'\xff','c':b'\xff'})[0] + self.assertNotEqual(a.payload,b.payload) + + def test_material_names_do_not_act_as_keys(self): + p = deepcopy(PROFILE) + p['corpus'] = [['x',0],['y',1],['z',2]] + renamed = dict(zip(('x','y','z'),(MATERIAL['a'],MATERIAL['b'],MATERIAL['c']))) + data = tuple(i%2 for i in range(137)) + self.assertEqual(two_way(data)[0].payload,two_way(data,p,renamed)[0].payload) + + def test_corpus_off_has_no_material_influence(self): + p = flags(corpus=False) + data = tuple(i%2 for i in range(137)) + self.assertEqual(two_way(data,p,{})[0].payload,two_way(data,p,MATERIAL)[0].payload) + _, public, private = build(p,len(data),MATERIAL) + self.assertEqual(dict(public.public_material),{}) + self.assertEqual(dict(private.public_material),{}) + self.assertNotIn('corpus',public.parameters) + + def test_disabled_stage_not_called(self): + def forbidden(*args): + raise AssertionError('disabled stage executed') + off = {n:False for n in DEFAULTS} + p = Pipeline(Switches(off), {'corpus':Operator(forbidden,forbidden,'test/forbidden')}) + value = b'exact unchanged opaque object' + e = p.encrypt(value,PublicContext(None)) + self.assertIs(e.payload,value) + + def test_join_order_and_empty_lanes(self): + self.assertEqual(join.route((2,0,1),(2,0,1)),(2,0,0)) + self.assertEqual(join.route((0,0,0),(0,1,2)),()) + for sizes in product(range(4),repeat=3): + r = join.route(sizes,(2,0,1)) + self.assertEqual(tuple(r.count(i) for i in range(3)),sizes) + + def test_bad_routes_and_partitions_refused(self): + for bad in ((0,0,1),(True,1,2),(3,1,0)): + with self.assertRaises(ValueError):join.route((1,2,3),bad) + for bad in ((1,1,-1),(True,1,1),(1,1),(0,0,0)): + with self.assertRaises(ValueError):inter.section((0,1,0),bad) + for n,a in ((True,3),(1,True),(-1,3),(1,2)): + with self.assertRaises(ValueError):inter.balanced_partition(n,a) + with self.assertRaises(ValueError):corpus.route(3,b'') + with self.assertRaises(ValueError):corpus.route(3,b'a',True) + + def test_unknown_and_nonboolean_profile_fields_refused(self): + for p in (flags(corups=False),flags(inter=0),flags(corpus='false')): + with self.assertRaises((ValueError,TypeError)):build(p,16,MATERIAL) + p=deepcopy(PROFILE);p['typo']=1 + with self.assertRaises(ValueError):build(p,16,MATERIAL) + + def test_missing_material_never_an_identity(self): + with self.assertRaises(Blocked):build(PROFILE,32,{}) + + def test_wrong_material_is_not_authenticated(self): + data = tuple([1,0,1,1,0,0,0]*17) + p,pub,_ = build(PROFILE,len(data),{'a':b'\x00','b':b'\x00','c':b'\x00'}) + e = p.encrypt(Streams((data,)),pub) + q,_,priv = build(PROFILE,len(data),{'a':b'\xff','b':b'\xff','c':b'\xff'}) + decoded = q.decrypt(e,priv) + self.assertNotEqual(decoded.payload,Streams((data,))) + self.assertNotEqual(decoded.classification,'FULL_PROFILE_EXPERIMENT') + + def test_fixed_map_attack_only_on_this_complete_transport_profile(self): + n=137 + p,pub,_=build(PROFILE,n,MATERIAL) + def oracle(bits):return p.encrypt(Streams((bits,)),pub).payload.lanes[0] + mapping,queries=recover_fixed_map(oracle,n) + data=tuple((i*i+i//3)%2 for i in range(n)) + self.assertEqual(recover_with_map(oracle(data),mapping),data) + self.assertEqual(queries,8) + + def test_packet_rejects_malformed_data_and_recipe(self): + p,pub,_=build(PROFILE,8,MATERIAL) + e=p.encrypt(byte_stream(b'A'),pub) + obj=json.loads(wire(e));obj['recipe'][0][1]='invented' + with self.assertRaises(ValueError):unwire(json.dumps(obj).encode(),p) + for records in ([{'bits':1,'hex':'ff'}],[{'bits':True,'hex':'00'}],[], + [{'bits':8,'hex':'FF'}],[{'bits':8,'hex':'00','other':1}]): + with self.assertRaises(ValueError):parse_lanes(records) + with self.assertRaises(ValueError):strict_json('{"x":1,"x":2}') + + def test_byte_admission_is_explicit_not_a_gonol(self): + data=bytes(range(256))+b'\x00\xff' + self.assertEqual(recover_bytes(byte_stream(data)),data) + self.assertIsInstance(byte_stream(data),Streams) + with self.assertRaises(ValueError):recover_bytes(Streams(((1,),))) + + def test_native_missing_and_wrong_source_refuse_before_execution(self): + with self.assertRaises(Blocked): + with NativeWords(Path('/nonexistent/source'),Path('/nonexistent/db'),'0'*64):pass + with tempfile.TemporaryDirectory() as directory: + root=Path(directory);source=root/'native.py';database=root/'construct.db' + marker=root/'executed' + source.write_text(f"open({str(marker)!r}, 'w').write('bad')") + database.write_bytes(b'not a real constructed database') + with self.assertRaisesRegex(Blocked,'not imported'): + with NativeWords(source,database,'0'*64):pass + self.assertFalse(marker.exists()) + + def test_resource_boundary_is_explicit(self): + with self.assertRaisesRegex(ValueError,'resource limit'):build(PROFILE,LIMIT*8+1,MATERIAL) + p=deepcopy(PROFILE);p['arities'][0]=[4097] + with self.assertRaisesRegex(ValueError,'resource profile'):build(p,8,MATERIAL) + + def test_full_resource_limit_roundtrip(self): + data = bytes(range(256)) * 256 + p, public, _ = build(PROFILE, len(data)*8, MATERIAL) + e = p.encrypt(byte_stream(data), public) + q, _, private = build(deepcopy(PROFILE), len(data)*8, dict(MATERIAL)) + restored = q.decrypt(unwire(wire(e), q), private) + self.assertEqual(recover_bytes(restored.payload), data) + + def test_fresh_process_roundtrip_and_no_overwrite(self): + with tempfile.TemporaryDirectory() as directory: + root=Path(directory);config=root/'p.json';src=root/'i.bin';dst=root/'o.lab';out=root/'r.bin' + config.write_text(json.dumps(PROFILE)); data=bytes(range(256))*4+b'\x00\xff' + src.write_bytes(data);args=[] + for label,content in MATERIAL.items(): + path=root/(label+'.bin');path.write_bytes(content) + args+=['--material',f'{label}={path}'] + enc=[sys.executable,str(ROOT/'run.py'),'enc',str(config),str(src),str(dst),*args] + dec=[sys.executable,str(ROOT/'run.py'),'dec',str(config),str(dst),str(out),*args] + first=subprocess.run(enc,capture_output=True,text=True) + self.assertEqual(first.returncode,0,first.stderr) + src.unlink() # The original input is not available to the recovery process. + second=subprocess.run(dec,capture_output=True,text=True) + self.assertEqual(second.returncode,0,second.stderr) + self.assertEqual(out.read_bytes(),data) + again=subprocess.run(dec,capture_output=True,text=True) + self.assertEqual(again.returncode,2) + self.assertEqual(out.read_bytes(),data) + + def test_off_corpus_does_not_read_supplied_path(self): + with tempfile.TemporaryDirectory() as directory: + root=Path(directory);config=root/'p.json';src=root/'i';dst=root/'o' + config.write_text(json.dumps(flags(corpus=False)));src.write_bytes(b'test') + result=subprocess.run([sys.executable,str(ROOT/'run.py'),'enc',str(config),str(src), + str(dst),'--material','a=/nonexistent/never-read'],capture_output=True,text=True) + self.assertEqual(result.returncode,0,result.stderr) + + +if __name__=='__main__':unittest.main() diff --git a/research/weave/transport.py b/research/weave/transport.py new file mode 100644 index 00000000..a15ba4e6 --- /dev/null +++ b/research/weave/transport.py @@ -0,0 +1,93 @@ +"""Explicit provisional composition; native whole-Weave profile stays separate. + +Usage: build(profile, bit_length, materials) independently on each side. Returned +contexts contain freshly compiled controls, not captured encoder state. Profile +files are research inputs, NOT a public key or a proposed ciphertext header. +The CLI limits one message to 64 KiB as an implementation resource guard. +""" +from assembly import Pipeline, Switches +from stages.api import Blocked, PrivateContext, PublicContext, Streams +from stages.split import cyclic_route, explicit_route_operator +from stages.corpus import content_route_operator +from stages.inter import balanced_schedule +from stages.join import explicit_join_operator + +SCHEMA = 'weave.transport-profile/v1' +LIMIT = 65536 +REQUIRED = {'schema', 'switches', 'threads', 'arities', 'join_order', 'corpus'} + + +def build(profile: dict, size: int, materials: dict): + if type(profile) is not dict or set(profile) != REQUIRED or profile['schema'] != SCHEMA: + raise ValueError('unknown, missing or unsupported transport profile fields') + if type(size) is not int or not 0 <= size <= LIMIT * 8: + raise ValueError('transport resource limit: at most 64 KiB per message') + if type(profile['switches']) is not dict: + raise TypeError('switches must be an object') + switches = Switches(profile['switches']) + if any(switches[s] for s in ('key', 'gonol', 'bind', 'auth')): + raise Blocked('transport profile cannot supply key/gonol/bind/auth native laws') + count = profile['threads'] + if type(count) is not int or not 3 <= count <= 63: + raise ValueError('transport resource profile admits 3..63 threads') + params = {} + if switches['split']: + owners = cyclic_route(size, count) + params['split'] = (count, owners) + lengths = tuple(owners.count(i) for i in range(count)) + else: + lengths = (size,) + if switches['corpus']: + choices = profile['corpus'] + if type(choices) is not list or len(choices) != len(lengths): + raise ValueError('choose actual material/offset for each active lane') + clean = [] + for choice in choices: + if (type(choice) is not list or len(choice) != 2 or type(choice[0]) is not str + or type(choice[1]) is not int or choice[1] < 0): + raise ValueError('invalid corpus choice') + if choice[0] not in materials or type(materials[choice[0]]) is not bytes or not materials[choice[0]]: + raise Blocked('missing nonempty corpus material') + clean.append(tuple(choice)) + params['corpus'] = tuple(clean) + used_material = {label: materials[label] for label, offset in clean} + else: + used_material = {} + if switches['inter']: + arities = profile['arities'] + if type(arities) is not list or len(arities) != len(lengths): + raise ValueError('one arity schedule per active lane required') + for schedule in arities: + if (type(schedule) is not list or not 1 <= len(schedule) <= 64 + or any(type(a) is not int or not 3 <= a <= 4096 for a in schedule)): + raise ValueError('resource profile: 1..64 stages with arities 3..4096') + params['inter'] = tuple(balanced_schedule(n, tuple(a)) for n, a in zip(lengths, arities)) + if switches['join']: + order = profile['join_order'] + if (type(order) is not list or any(type(i) is not int for i in order) + or sorted(order) != list(range(len(lengths)))): + raise ValueError('join_order must visit all active lanes') + params['join'] = (lengths, tuple(order)) + elif switches['whole'] and len(lengths) != 1: + raise ValueError('incompatible ablation: whole needs one lane; join is OFF') + pipeline = Pipeline(switches, { + 'split': explicit_route_operator(), + 'corpus': content_route_operator(), + 'join': explicit_join_operator(), + }) + public = PublicContext(None, params, public_material=used_material) + private = PrivateContext(None, None, params, public_material=used_material) + return pipeline, public, private + + +def byte_stream(data: bytes) -> Streams: + if type(data) is not bytes or len(data) > LIMIT: + raise ValueError('transport input must be bytes of at most 64 KiB') + return Streams((tuple((byte >> shift) & 1 for byte in data for shift in range(7, -1, -1)),)) + + +def recover_bytes(streams: Streams) -> bytes: + if not isinstance(streams, Streams) or len(streams.lanes) != 1 or len(streams.lanes[0]) % 8: + raise ValueError('recovered input is not one byte-aligned stream') + bits = streams.lanes[0] + return bytes(sum(bits[i + j] << (7-j) for j in range(8)) for i in range(0, len(bits), 8))