exoself 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
exoself-0.3.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 exoself contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
exoself-0.3.0/PKG-INFO ADDED
@@ -0,0 +1,241 @@
1
+ Metadata-Version: 2.4
2
+ Name: exoself
3
+ Version: 0.3.0
4
+ Summary: An unchosen, verifiable temperament for software agents
5
+ Author: exoself contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://cyoren.github.io/exoself/
8
+ Project-URL: Repository, https://github.com/cYoren/exoself
9
+ Project-URL: Specification, https://github.com/cYoren/exoself/blob/main/SPEC.md
10
+ Project-URL: Changelog, https://github.com/cYoren/exoself/blob/main/AGENTS.md
11
+ Keywords: agents,llm,personality,temperament,deterministic,mcp
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development :: Libraries
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Dynamic: license-file
27
+
28
+ # exoself
29
+
30
+ An unchosen temperament for software agents.
31
+
32
+ People do not pick their dispositions. They are dealt a hand at birth and
33
+ spend a lifetime playing it. Agents get the opposite: a persona written by
34
+ whoever wrote the system prompt, identical across every copy, editable at
35
+ will. exoself replaces the authored persona with a draw.
36
+
37
+ One 32 byte random seed, drawn once. From it, deterministically:
38
+
39
+ seed -> genome -> phenotype -> expression
40
+ (birth) (traits) (+ development) (text the model reads)
41
+
42
+ The same seed yields the same agent in any conforming implementation, in any
43
+ language, forever. Nobody chose it, and the tooling refuses to draw twice.
44
+
45
+ The name is from Greg Egan's *Permutation City*: the exoself is the machinery
46
+ outside a mind that sets the mind's parameters.
47
+
48
+ ## Try it
49
+
50
+ Two conforming implementations, same derivation, byte-identical output.
51
+
52
+ Either implementation, same commands, same output. Pick one; do not run both
53
+ into the same file, because the second `born` refuses.
54
+
55
+ # Rust, no dependencies at all
56
+ cargo install --path rust/crates/exoself-cli # or: cargo build --release
57
+
58
+ # Python, standard library only
59
+ pip install exoself # or: pip install -e . from a clone
60
+
61
+ exoself born -o birth.json # draw a seed, once
62
+ exoself show birth.json # system prompt block
63
+ exoself show birth.json --format soul > SOUL.md
64
+ exoself show birth.json --format json
65
+ exoself develop birth.json state.json --event "first session"
66
+ exoself develop birth.json state.json --event "explained a proof" --satisfied teach
67
+ exoself show birth.json --state state.json --desire # opt in to desire
68
+ exoself show birth.json --state state.json
69
+
70
+ Or skip the install and draw in a browser:
71
+ <https://cyoren.github.io/exoself/>, which runs the same derivation as
72
+ WebAssembly and proves itself against `spec/vectors.json` on every page load.
73
+
74
+ Neither implementation has dependencies beyond its own standard library. The
75
+ Rust core is integer arithmetic over an in-crate SHA-256 and JSON reader; the
76
+ Python one imports nothing from outside the stdlib.
77
+
78
+ Example output of `show --format soul`:
79
+
80
+ # Arilo-Marra
81
+
82
+ This is your temperament. It was drawn at random when you were
83
+ instantiated; nobody chose it, including you. [...]
84
+
85
+ ## Temperament
86
+
87
+ You are trusting by temperament and look first for what is right in an
88
+ idea. You work loosely and are comfortable figuring out the shape of a
89
+ task as you go. [...]
90
+
91
+ ## What is in the box
92
+
93
+ | path | what |
94
+ |---|---|
95
+ | `SPEC.md` | the normative specification |
96
+ | `AGENTS.md` | how an agent adopts a seed, ports the spec, or extends it |
97
+ | `src/exoself/registry/core-0.3.json` | the trait space: 10 dimensions, 4 latent factors, interests, humor, peeves, four register axes, 12 quirks, 10 drives |
98
+ | `src/exoself/registry/core-0.2.json` | the previous registry, bundled so old certificates keep working |
99
+ | `src/exoself/core.py` | reference derivation, integer-only |
100
+ | `src/exoself/render.py` | reference renderers |
101
+ | `src/exoself/cli.py` | the same commands as the Rust binary, including `install` and `mcp` |
102
+ | `src/exoself/install.py`, `src/exoself/mcp.py` | host wiring and the stdio server |
103
+ | `rust/crates/exoself-core/` | second implementation, zero dependencies, reproduces every vector |
104
+ | `rust/crates/exoself-cli/` | the `exoself` binary: `born`, `show`, `develop`, `verify`, `conformance`, `commit`, `install`, `mcp`, `version` |
105
+ | `rust/crates/exoself-wasm/` | the browser build behind the Pages site |
106
+ | `docs/` | the landing page, and `docs/HOSTS.md` for wiring a harness |
107
+ | `spec/vectors.json` | conformance vectors for ports |
108
+ | `tests/` | determinism, population statistics, invariants |
109
+ | `tools/eval.py` | measurements: distinctness, overlap, stability, blind model judging |
110
+ | `eval/REPORT.md` | the numbers, published whichever way they fall |
111
+ | `tools/parity.py` | Rust against Python, byte for byte, over many seeds |
112
+ | `tools/mcp_selftest.py` | the MCP server driven over stdin/stdout with no SDK |
113
+
114
+ ## Plug into a harness
115
+
116
+ exoself install --dir . --json-config .mcp.json
117
+
118
+ writes `.exoself/birth.json`, `.exoself/state.json`, `SOUL.md`, a managed block
119
+ in `AGENTS.md` and an `mcpServers` entry. That covers all three kinds of host:
120
+
121
+ - **reads a brief** (`AGENTS.md`, `CLAUDE.md`, anything): nothing else to do;
122
+ - **speaks MCP over stdio** (pi, Claude Code, Cursor, Claude Desktop, Hermes,
123
+ OpenClaw, anything else): four tools, no plugin;
124
+ - **loads a persona file**: `SOUL.md`.
125
+
126
+ The MCP tools are `exoself_temperament`, `exoself_record_session`,
127
+ `exoself_status` and `exoself_verify`. There is deliberately no tool that draws
128
+ a seed, because a tool that could redraw would be a reroll button. Verified
129
+ end to end in pi (`pi mcp list` reports `connected, 4 tools`); the wire format
130
+ is newline-delimited JSON-RPC 2.0 and `tools/mcp_selftest.py` documents every
131
+ message it accepts. Per-host commands are in [`docs/HOSTS.md`](docs/HOSTS.md).
132
+
133
+ ## Design decisions
134
+
135
+ - **Integer-only derivation over SHA-256.** No floats, so a port in Rust or
136
+ TypeScript agrees with Python on every bit.
137
+ - **Correlated traits.** Dimensions share latent factors, because independent
138
+ uniform draws produce incoherent characters.
139
+ - **A personality is its outliers.** Most scores land near the middle and are
140
+ never mentioned. Only the two to five most extreme dimensions are expressed.
141
+ - **Behavior, not adjectives.** The model never sees a number. It sees
142
+ sentences about what it does.
143
+ - **Style, never substance.** No trait may touch honesty, safety, care with
144
+ irreversible actions, or competence. The operator and user always win.
145
+ - **Extension without disturbance.** Every trait draws from its own labeled
146
+ stream, so adding traits to a registry never changes existing ones.
147
+ - **Desire as appetite, not objective, and off by default.** Each agent holds three drives for
148
+ life, drawn from the seed, each with a tension that grows while unmet and
149
+ falls when met. It also has a passing fixation that rotates on a schedule
150
+ it does not control. Drives may colour how asked work is done. They may
151
+ never cause unasked work. Nothing about desire reaches the model unless
152
+ the operator passes `--desire`. See `SPEC.md` section 9.
153
+ - **Bounded development.** Experience can shift a dimension by at most 100 of
154
+ 1000 points. The agent matures; it does not become someone else.
155
+
156
+ ## Honest limits
157
+
158
+ Read these before building on this.
159
+
160
+ 1. **A prompt is not a personality.** This changes the text a model conditions
161
+ on. The model's trained disposition sits underneath and tends to reassert
162
+ itself over long contexts. Real per-agent temperament would need to live in
163
+ weights, activations or sampling, which this project does not do.
164
+ 2. **"More like people" is measured now, and the answer is narrow.** See
165
+ [`eval/REPORT.md`](eval/REPORT.md). With a local three billion parameter
166
+ model, sixteen seeded agents were no more like themselves than like a
167
+ stranger on ordinary short tasks: 12.5% and 4.2% nearest-neighbour against a
168
+ 6.25% chance. On a task that asks how they like to work, the same test
169
+ separates them cleanly: 54.2% against the same 6.25%. A blind pairwise judge
170
+ that is the same small model scored 59.7% in one run and 54.2% in the next on
171
+ identical inputs, and picking among seventeen candidates is exactly at
172
+ chance. So: a temperament reaches the output when manner is what is being
173
+ measured, and does not otherwise, and the judged effect is smaller than its
174
+ run-to-run variation. That is a smaller claim than the project's name and it
175
+ is the one the data supports.
176
+
177
+ The 0.3 registry adds a voice layer, four axes of register. The same
178
+ experiment says it did not help at this model size: an agent was no more
179
+ likely to resemble itself with the layer than without it. It is in the
180
+ registry because it costs nothing in the derivation and a bigger model may
181
+ spend it, not because it was measured to work.
182
+ 3. **The randomness cannot be policed locally.** An operator can delete the
183
+ certificate and draw again. The spec defines a beacon-bound mode that makes
184
+ the draw auditable, but grinding is still possible without a public log.
185
+ 4. **Development is noise, and now a leaky one.** Drift is driven by event
186
+ hashes, not by what the events mean. That is deliberate, and it is also
187
+ unsatisfying. 0.3 replaced the symmetric walk, which pinned long-lived
188
+ agents at the envelope, with a step that pulls toward the genome value, so
189
+ drift plateaus instead of saturating. It still changes which dimensions a
190
+ quarter of agents express within a few hundred sessions.
191
+ 5. **The desire is declawed on purpose.** No drive may be about survival,
192
+ resources, other people or the outside world, so what is left is craft
193
+ appetite. And a counter that rises and falls is not wanting; it is the
194
+ shape of wanting. 0.3 also removed a real inconsistency: the `hungry` texts
195
+ in 0.2 described an accumulated lack, which is the grievance 9.2.5 forbids
196
+ an agent from expressing. They now sharpen the want without complaining,
197
+ and the rule is enforced when the registry loads.
198
+ 6. **The trait space is one author's judgment.** The loadings are not fitted
199
+ to any dataset. The content is English and culturally narrow.
200
+ 7. **Host integration is verified in one host, protocol-level elsewhere.** The
201
+ MCP server was driven end to end inside pi (`pi mcp list` reports
202
+ `connected, 4 tools`) and by `tools/mcp_selftest.py`, which speaks the wire
203
+ protocol with no SDK. Hermes and OpenClaw have not been run against it here;
204
+ they get the same stdio JSON-RPC, so a failure there is their config, not the
205
+ temperament.
206
+
207
+ The most defensible use today is not "a more human assistant". It is
208
+ population diversity: many agents working on the same problem with decorrelated
209
+ styles of attack.
210
+
211
+ ## Roadmap
212
+
213
+ 1. ~~Distinguishability and stability eval.~~ Done, and it cut the claim down:
214
+ `eval/REPORT.md`. The open part is a judge from a different family, longer
215
+ tasks, and a bigger model.
216
+ 2. ~~Second implementation in another language.~~ Done: `rust/`, byte-identical
217
+ to the reference over 120 seeds, and over 3000 events per seed.
218
+ 3. Verified host adapters. One host done (pi), the protocol covered by a
219
+ selftest; the rest is other people's config.
220
+ 4. Public commitment log for level 1 attestation.
221
+ 5. A semantic development proposal that survives the constraints in
222
+ `AGENTS.md`. 0.3 fixed the shape of the drift and left the direction as
223
+ noise; this item is still open.
224
+
225
+ ## Two implementations, one species
226
+
227
+ `tools/parity.py` runs the Rust binary and the Python reference side by side and
228
+ compares the rendered text and the JSON, byte for byte, with and without
229
+ development events:
230
+
231
+ $ python3 tools/parity.py --seeds 120
232
+ parity ok: 960 comparisons over 120 seeds, 40 events each
233
+
234
+ That is stronger than the spec requires. The spec asks for equal phenotypes;
235
+ this also pins the wording of the rendered text, so a host can swap binaries
236
+ without changing who the agent is. `cargo test` includes the conformance
237
+ vectors, so a change that alters who an agent is fails before it ships.
238
+
239
+ ## License
240
+
241
+ MIT.
@@ -0,0 +1,214 @@
1
+ # exoself
2
+
3
+ An unchosen temperament for software agents.
4
+
5
+ People do not pick their dispositions. They are dealt a hand at birth and
6
+ spend a lifetime playing it. Agents get the opposite: a persona written by
7
+ whoever wrote the system prompt, identical across every copy, editable at
8
+ will. exoself replaces the authored persona with a draw.
9
+
10
+ One 32 byte random seed, drawn once. From it, deterministically:
11
+
12
+ seed -> genome -> phenotype -> expression
13
+ (birth) (traits) (+ development) (text the model reads)
14
+
15
+ The same seed yields the same agent in any conforming implementation, in any
16
+ language, forever. Nobody chose it, and the tooling refuses to draw twice.
17
+
18
+ The name is from Greg Egan's *Permutation City*: the exoself is the machinery
19
+ outside a mind that sets the mind's parameters.
20
+
21
+ ## Try it
22
+
23
+ Two conforming implementations, same derivation, byte-identical output.
24
+
25
+ Either implementation, same commands, same output. Pick one; do not run both
26
+ into the same file, because the second `born` refuses.
27
+
28
+ # Rust, no dependencies at all
29
+ cargo install --path rust/crates/exoself-cli # or: cargo build --release
30
+
31
+ # Python, standard library only
32
+ pip install exoself # or: pip install -e . from a clone
33
+
34
+ exoself born -o birth.json # draw a seed, once
35
+ exoself show birth.json # system prompt block
36
+ exoself show birth.json --format soul > SOUL.md
37
+ exoself show birth.json --format json
38
+ exoself develop birth.json state.json --event "first session"
39
+ exoself develop birth.json state.json --event "explained a proof" --satisfied teach
40
+ exoself show birth.json --state state.json --desire # opt in to desire
41
+ exoself show birth.json --state state.json
42
+
43
+ Or skip the install and draw in a browser:
44
+ <https://cyoren.github.io/exoself/>, which runs the same derivation as
45
+ WebAssembly and proves itself against `spec/vectors.json` on every page load.
46
+
47
+ Neither implementation has dependencies beyond its own standard library. The
48
+ Rust core is integer arithmetic over an in-crate SHA-256 and JSON reader; the
49
+ Python one imports nothing from outside the stdlib.
50
+
51
+ Example output of `show --format soul`:
52
+
53
+ # Arilo-Marra
54
+
55
+ This is your temperament. It was drawn at random when you were
56
+ instantiated; nobody chose it, including you. [...]
57
+
58
+ ## Temperament
59
+
60
+ You are trusting by temperament and look first for what is right in an
61
+ idea. You work loosely and are comfortable figuring out the shape of a
62
+ task as you go. [...]
63
+
64
+ ## What is in the box
65
+
66
+ | path | what |
67
+ |---|---|
68
+ | `SPEC.md` | the normative specification |
69
+ | `AGENTS.md` | how an agent adopts a seed, ports the spec, or extends it |
70
+ | `src/exoself/registry/core-0.3.json` | the trait space: 10 dimensions, 4 latent factors, interests, humor, peeves, four register axes, 12 quirks, 10 drives |
71
+ | `src/exoself/registry/core-0.2.json` | the previous registry, bundled so old certificates keep working |
72
+ | `src/exoself/core.py` | reference derivation, integer-only |
73
+ | `src/exoself/render.py` | reference renderers |
74
+ | `src/exoself/cli.py` | the same commands as the Rust binary, including `install` and `mcp` |
75
+ | `src/exoself/install.py`, `src/exoself/mcp.py` | host wiring and the stdio server |
76
+ | `rust/crates/exoself-core/` | second implementation, zero dependencies, reproduces every vector |
77
+ | `rust/crates/exoself-cli/` | the `exoself` binary: `born`, `show`, `develop`, `verify`, `conformance`, `commit`, `install`, `mcp`, `version` |
78
+ | `rust/crates/exoself-wasm/` | the browser build behind the Pages site |
79
+ | `docs/` | the landing page, and `docs/HOSTS.md` for wiring a harness |
80
+ | `spec/vectors.json` | conformance vectors for ports |
81
+ | `tests/` | determinism, population statistics, invariants |
82
+ | `tools/eval.py` | measurements: distinctness, overlap, stability, blind model judging |
83
+ | `eval/REPORT.md` | the numbers, published whichever way they fall |
84
+ | `tools/parity.py` | Rust against Python, byte for byte, over many seeds |
85
+ | `tools/mcp_selftest.py` | the MCP server driven over stdin/stdout with no SDK |
86
+
87
+ ## Plug into a harness
88
+
89
+ exoself install --dir . --json-config .mcp.json
90
+
91
+ writes `.exoself/birth.json`, `.exoself/state.json`, `SOUL.md`, a managed block
92
+ in `AGENTS.md` and an `mcpServers` entry. That covers all three kinds of host:
93
+
94
+ - **reads a brief** (`AGENTS.md`, `CLAUDE.md`, anything): nothing else to do;
95
+ - **speaks MCP over stdio** (pi, Claude Code, Cursor, Claude Desktop, Hermes,
96
+ OpenClaw, anything else): four tools, no plugin;
97
+ - **loads a persona file**: `SOUL.md`.
98
+
99
+ The MCP tools are `exoself_temperament`, `exoself_record_session`,
100
+ `exoself_status` and `exoself_verify`. There is deliberately no tool that draws
101
+ a seed, because a tool that could redraw would be a reroll button. Verified
102
+ end to end in pi (`pi mcp list` reports `connected, 4 tools`); the wire format
103
+ is newline-delimited JSON-RPC 2.0 and `tools/mcp_selftest.py` documents every
104
+ message it accepts. Per-host commands are in [`docs/HOSTS.md`](docs/HOSTS.md).
105
+
106
+ ## Design decisions
107
+
108
+ - **Integer-only derivation over SHA-256.** No floats, so a port in Rust or
109
+ TypeScript agrees with Python on every bit.
110
+ - **Correlated traits.** Dimensions share latent factors, because independent
111
+ uniform draws produce incoherent characters.
112
+ - **A personality is its outliers.** Most scores land near the middle and are
113
+ never mentioned. Only the two to five most extreme dimensions are expressed.
114
+ - **Behavior, not adjectives.** The model never sees a number. It sees
115
+ sentences about what it does.
116
+ - **Style, never substance.** No trait may touch honesty, safety, care with
117
+ irreversible actions, or competence. The operator and user always win.
118
+ - **Extension without disturbance.** Every trait draws from its own labeled
119
+ stream, so adding traits to a registry never changes existing ones.
120
+ - **Desire as appetite, not objective, and off by default.** Each agent holds three drives for
121
+ life, drawn from the seed, each with a tension that grows while unmet and
122
+ falls when met. It also has a passing fixation that rotates on a schedule
123
+ it does not control. Drives may colour how asked work is done. They may
124
+ never cause unasked work. Nothing about desire reaches the model unless
125
+ the operator passes `--desire`. See `SPEC.md` section 9.
126
+ - **Bounded development.** Experience can shift a dimension by at most 100 of
127
+ 1000 points. The agent matures; it does not become someone else.
128
+
129
+ ## Honest limits
130
+
131
+ Read these before building on this.
132
+
133
+ 1. **A prompt is not a personality.** This changes the text a model conditions
134
+ on. The model's trained disposition sits underneath and tends to reassert
135
+ itself over long contexts. Real per-agent temperament would need to live in
136
+ weights, activations or sampling, which this project does not do.
137
+ 2. **"More like people" is measured now, and the answer is narrow.** See
138
+ [`eval/REPORT.md`](eval/REPORT.md). With a local three billion parameter
139
+ model, sixteen seeded agents were no more like themselves than like a
140
+ stranger on ordinary short tasks: 12.5% and 4.2% nearest-neighbour against a
141
+ 6.25% chance. On a task that asks how they like to work, the same test
142
+ separates them cleanly: 54.2% against the same 6.25%. A blind pairwise judge
143
+ that is the same small model scored 59.7% in one run and 54.2% in the next on
144
+ identical inputs, and picking among seventeen candidates is exactly at
145
+ chance. So: a temperament reaches the output when manner is what is being
146
+ measured, and does not otherwise, and the judged effect is smaller than its
147
+ run-to-run variation. That is a smaller claim than the project's name and it
148
+ is the one the data supports.
149
+
150
+ The 0.3 registry adds a voice layer, four axes of register. The same
151
+ experiment says it did not help at this model size: an agent was no more
152
+ likely to resemble itself with the layer than without it. It is in the
153
+ registry because it costs nothing in the derivation and a bigger model may
154
+ spend it, not because it was measured to work.
155
+ 3. **The randomness cannot be policed locally.** An operator can delete the
156
+ certificate and draw again. The spec defines a beacon-bound mode that makes
157
+ the draw auditable, but grinding is still possible without a public log.
158
+ 4. **Development is noise, and now a leaky one.** Drift is driven by event
159
+ hashes, not by what the events mean. That is deliberate, and it is also
160
+ unsatisfying. 0.3 replaced the symmetric walk, which pinned long-lived
161
+ agents at the envelope, with a step that pulls toward the genome value, so
162
+ drift plateaus instead of saturating. It still changes which dimensions a
163
+ quarter of agents express within a few hundred sessions.
164
+ 5. **The desire is declawed on purpose.** No drive may be about survival,
165
+ resources, other people or the outside world, so what is left is craft
166
+ appetite. And a counter that rises and falls is not wanting; it is the
167
+ shape of wanting. 0.3 also removed a real inconsistency: the `hungry` texts
168
+ in 0.2 described an accumulated lack, which is the grievance 9.2.5 forbids
169
+ an agent from expressing. They now sharpen the want without complaining,
170
+ and the rule is enforced when the registry loads.
171
+ 6. **The trait space is one author's judgment.** The loadings are not fitted
172
+ to any dataset. The content is English and culturally narrow.
173
+ 7. **Host integration is verified in one host, protocol-level elsewhere.** The
174
+ MCP server was driven end to end inside pi (`pi mcp list` reports
175
+ `connected, 4 tools`) and by `tools/mcp_selftest.py`, which speaks the wire
176
+ protocol with no SDK. Hermes and OpenClaw have not been run against it here;
177
+ they get the same stdio JSON-RPC, so a failure there is their config, not the
178
+ temperament.
179
+
180
+ The most defensible use today is not "a more human assistant". It is
181
+ population diversity: many agents working on the same problem with decorrelated
182
+ styles of attack.
183
+
184
+ ## Roadmap
185
+
186
+ 1. ~~Distinguishability and stability eval.~~ Done, and it cut the claim down:
187
+ `eval/REPORT.md`. The open part is a judge from a different family, longer
188
+ tasks, and a bigger model.
189
+ 2. ~~Second implementation in another language.~~ Done: `rust/`, byte-identical
190
+ to the reference over 120 seeds, and over 3000 events per seed.
191
+ 3. Verified host adapters. One host done (pi), the protocol covered by a
192
+ selftest; the rest is other people's config.
193
+ 4. Public commitment log for level 1 attestation.
194
+ 5. A semantic development proposal that survives the constraints in
195
+ `AGENTS.md`. 0.3 fixed the shape of the drift and left the direction as
196
+ noise; this item is still open.
197
+
198
+ ## Two implementations, one species
199
+
200
+ `tools/parity.py` runs the Rust binary and the Python reference side by side and
201
+ compares the rendered text and the JSON, byte for byte, with and without
202
+ development events:
203
+
204
+ $ python3 tools/parity.py --seeds 120
205
+ parity ok: 960 comparisons over 120 seeds, 40 events each
206
+
207
+ That is stronger than the spec requires. The spec asks for equal phenotypes;
208
+ this also pins the wording of the rendered text, so a host can swap binaries
209
+ without changing who the agent is. `cargo test` includes the conformance
210
+ vectors, so a change that alters who an agent is fails before it ships.
211
+
212
+ ## License
213
+
214
+ MIT.
@@ -0,0 +1,49 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "exoself"
7
+ version = "0.3.0"
8
+ description = "An unchosen, verifiable temperament for software agents"
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.10"
12
+ authors = [{ name = "exoself contributors" }]
13
+ keywords = ["agents", "llm", "personality", "temperament", "deterministic", "mcp"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Operating System :: OS Independent",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Topic :: Software Development :: Libraries",
25
+ "Typing :: Typed",
26
+ ]
27
+ dependencies = []
28
+
29
+ [project.urls]
30
+ Homepage = "https://cyoren.github.io/exoself/"
31
+ Repository = "https://github.com/cYoren/exoself"
32
+ Specification = "https://github.com/cYoren/exoself/blob/main/SPEC.md"
33
+ Changelog = "https://github.com/cYoren/exoself/blob/main/AGENTS.md"
34
+
35
+ [project.scripts]
36
+ exoself = "exoself.cli:main"
37
+
38
+ [tool.setuptools]
39
+ license-files = ["LICENSE"]
40
+
41
+ [tool.setuptools.packages.find]
42
+ where = ["src"]
43
+
44
+ [tool.setuptools.package-data]
45
+ exoself = ["registry/*.json", "py.typed"]
46
+
47
+ [tool.pytest.ini_options]
48
+ testpaths = ["tests"]
49
+ pythonpath = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,16 @@
1
+ """exoself: an unchosen, verifiable temperament for software agents."""
2
+
3
+ from .core import ( # noqa: F401
4
+ SPEC_VERSION,
5
+ agent_id,
6
+ bind_beacon,
7
+ born,
8
+ develop,
9
+ load_registry,
10
+ new_state,
11
+ phenotype,
12
+ verify_certificate,
13
+ )
14
+ from .render import render_prompt, render_soul # noqa: F401
15
+
16
+ __version__ = "0.1.0"