daftar 0.1.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.
- daftar-0.1.0/LICENSE +202 -0
- daftar-0.1.0/MANIFEST.in +5 -0
- daftar-0.1.0/PKG-INFO +289 -0
- daftar-0.1.0/PUBLISHING.md +112 -0
- daftar-0.1.0/README.md +261 -0
- daftar-0.1.0/examples/adapter_usage.py +130 -0
- daftar-0.1.0/examples/demo_end_to_end.py +117 -0
- daftar-0.1.0/pyproject.toml +41 -0
- daftar-0.1.0/setup.cfg +4 -0
- daftar-0.1.0/src/daftar/__init__.py +36 -0
- daftar-0.1.0/src/daftar/__version__.py +1 -0
- daftar-0.1.0/src/daftar/adapters/__init__.py +37 -0
- daftar-0.1.0/src/daftar/adapters/base.py +91 -0
- daftar-0.1.0/src/daftar/adapters/cpm_adapter.py +244 -0
- daftar-0.1.0/src/daftar/adapters/jaxley_adapter.py +176 -0
- daftar-0.1.0/src/daftar/adapters/meltingpot_adapter.py +235 -0
- daftar-0.1.0/src/daftar/capture.py +257 -0
- daftar-0.1.0/src/daftar/cli.py +183 -0
- daftar-0.1.0/src/daftar/diff.py +269 -0
- daftar-0.1.0/src/daftar/manifest.py +168 -0
- daftar-0.1.0/src/daftar/run.py +317 -0
- daftar-0.1.0/src/daftar/store.py +202 -0
- daftar-0.1.0/src/daftar/sweep.py +370 -0
- daftar-0.1.0/src/daftar.egg-info/PKG-INFO +289 -0
- daftar-0.1.0/src/daftar.egg-info/SOURCES.txt +28 -0
- daftar-0.1.0/src/daftar.egg-info/dependency_links.txt +1 -0
- daftar-0.1.0/src/daftar.egg-info/entry_points.txt +2 -0
- daftar-0.1.0/src/daftar.egg-info/requires.txt +13 -0
- daftar-0.1.0/src/daftar.egg-info/top_level.txt +1 -0
- daftar-0.1.0/tests/test_core.py +432 -0
daftar-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
daftar-0.1.0/MANIFEST.in
ADDED
daftar-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: daftar
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Record what produced each computational result: environment, code, parameters, seeds, inputs.
|
|
5
|
+
Author: Aslan Satary Dizaji
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/aslansd/daftar
|
|
8
|
+
Project-URL: Repository, https://github.com/aslansd/daftar
|
|
9
|
+
Project-URL: Issues, https://github.com/aslansd/daftar/issues
|
|
10
|
+
Keywords: reproducibility,provenance,simulation,computational-science
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Provides-Extra: jaxley
|
|
19
|
+
Requires-Dist: jaxley; extra == "jaxley"
|
|
20
|
+
Provides-Extra: cpm
|
|
21
|
+
Requires-Dist: cpm-toolbox; extra == "cpm"
|
|
22
|
+
Provides-Extra: meltingpot
|
|
23
|
+
Requires-Dist: dm-meltingpot; extra == "meltingpot"
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
26
|
+
Requires-Dist: numpy; extra == "dev"
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
|
|
29
|
+
# daftar
|
|
30
|
+
|
|
31
|
+
**دفتر** — *ledger, register, record-book.* The same word in Persian, Turkish
|
|
32
|
+
(*defter*), Azerbaijani, Arabic, Urdu, and Hindi.
|
|
33
|
+
|
|
34
|
+
Record what produced each computational result — the environment, code version,
|
|
35
|
+
parameters, random seeds, and input files — so two runs can be compared and any
|
|
36
|
+
past run can be rebuilt.
|
|
37
|
+
|
|
38
|
+
Experiment trackers solved this for deep learning, where an experiment is
|
|
39
|
+
`model.fit()`. They do not help when the experiment is a Hodgkin–Huxley
|
|
40
|
+
simulation of 302 neurons, a hierarchical fit across 60 participants, or a
|
|
41
|
+
200-episode multi-agent sweep. Those runs have no epochs, no loss curves, and no
|
|
42
|
+
checkpoints. They have parameter grids, solver tolerances, random seeds, and
|
|
43
|
+
derived quantities.
|
|
44
|
+
|
|
45
|
+
**No dependencies. Runs offline. No account, no server, no network call.**
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install daftar
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## The thirty-second version
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
import daftar # no alias: `df` would collide with the pandas convention
|
|
57
|
+
|
|
58
|
+
with daftar.track("celegans", params={"dt": 0.025, "solver": "bwd_euler"}, seed=42) as run:
|
|
59
|
+
run.add_input("data/connectome.csv")
|
|
60
|
+
v = simulate(dt=0.025)
|
|
61
|
+
run.log_result("mean_rate_hz", float(v.mean()))
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Then, next Thursday, when the number is different:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
$ daftar diff r-4f21ab r-88c07e
|
|
68
|
+
|
|
69
|
+
--- r-4f21ab celegans 2026-05-14T14:02:11+00:00
|
|
70
|
+
+++ r-88c07e celegans 2026-05-16T09:47:03+00:00
|
|
71
|
+
|
|
72
|
+
candidate causes (1)
|
|
73
|
+
env.jax 0.4.35 -> 0.4.41
|
|
74
|
+
|
|
75
|
+
observed effects (1)
|
|
76
|
+
result.mean_rate_hz 4.812 -> 4.796
|
|
77
|
+
|
|
78
|
+
2 meaningful field(s) differ, 27 identical
|
|
79
|
+
|
|
80
|
+
Results differ, and so do things that could explain it.
|
|
81
|
+
The candidate causes below are where to look.
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Same code, same seed, same inputs. A patch-level JAX upgrade moved the answer.
|
|
85
|
+
That is the question this tool exists to answer, and it answers it the same
|
|
86
|
+
afternoon you install it.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Why this and not the eight tools that came before
|
|
91
|
+
|
|
92
|
+
Binder, ReproZip, Sciunit, Whole Tale, Gigantum, Renku, Code Ocean: in a
|
|
93
|
+
published survey, exactly **one of 38 researchers** had ever used a dedicated
|
|
94
|
+
platform to save and re-run a computational experiment.
|
|
95
|
+
|
|
96
|
+
Every one of those tools asked scientists to change how they work today in
|
|
97
|
+
exchange for a benefit arriving in three years. That trade never closes.
|
|
98
|
+
|
|
99
|
+
`daftar` inverts it. `diff` answers a question people ask weekly — *why is
|
|
100
|
+
this number different from Tuesday's?* — and provenance arrives as a free side
|
|
101
|
+
effect of a tool they already wanted. Reproducibility is the by-product, not
|
|
102
|
+
the pitch.
|
|
103
|
+
|
|
104
|
+
Three consequences of taking that seriously:
|
|
105
|
+
|
|
106
|
+
- **One line and one indent.** No DSL, no workflow language, no migration. If
|
|
107
|
+
wrapping an existing simulation costs more than that, nobody does it.
|
|
108
|
+
- **The manifest is plain JSON with sorted, dotted keys.** Readable and
|
|
109
|
+
greppable without this package installed, and `git diff`-able. If daftar
|
|
110
|
+
disappears, the record survives.
|
|
111
|
+
- **Failed runs are recorded too.** A crashed run that took four hours is
|
|
112
|
+
exactly the one you will want to look at later.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## What gets captured
|
|
117
|
+
|
|
118
|
+
| Namespace | Contents |
|
|
119
|
+
|---|---|
|
|
120
|
+
| `code.*` | git commit, branch, dirty flag, **hash of uncommitted changes**, entrypoint, argv |
|
|
121
|
+
| `param.*` | everything you chose, including defaults you never passed |
|
|
122
|
+
| `seed.*` | seeds **applied** to `random`, numpy, torch; the JAX root key |
|
|
123
|
+
| `input.*` | sha256 and size of every declared input file or directory |
|
|
124
|
+
| `env.*` | interpreter, OS, and versions of packages the run actually imported |
|
|
125
|
+
| `result.*` | scalar outcomes worth comparing |
|
|
126
|
+
| `output.*` | sha256 of produced files |
|
|
127
|
+
| `cost.*` | wall clock, host, cpu count |
|
|
128
|
+
|
|
129
|
+
Two of these are less obvious than they look.
|
|
130
|
+
|
|
131
|
+
**Seeds are applied, not merely recorded.** A tool that only writes down the
|
|
132
|
+
seed is close to useless: if the code seeded itself from the clock, recording
|
|
133
|
+
that fact tells you the run is irreproducible but does nothing to fix it.
|
|
134
|
+
`track(seed=...)` sets every RNG it can reach, then records what it set. If you
|
|
135
|
+
pass no seed, one is generated, applied, and recorded — an accidental seed that
|
|
136
|
+
is written down is reproducible; a deliberate one that isn't, is not.
|
|
137
|
+
|
|
138
|
+
**Dirty working trees get their diff hashed.** "Dirty" alone tells you there
|
|
139
|
+
were uncommitted edits but not whether they were the *same* edits. Hashing the
|
|
140
|
+
diff means two dirty runs can still be proven identical, which is the common
|
|
141
|
+
case during a debugging session.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## The four commands
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
daftar list # what has been run
|
|
149
|
+
daftar show r-4f21ab # one run's full manifest
|
|
150
|
+
daftar diff r-4f21ab r-88c07e # what changed, and whether it mattered
|
|
151
|
+
daftar vary -l my-sweep # which fields differ across many runs
|
|
152
|
+
daftar replay r-4f21ab # what it would take to reproduce this
|
|
153
|
+
daftar export r-4f21ab -o run.zip
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
`diff` exits 0 if the second run reproduces the first and 1 otherwise, so it
|
|
157
|
+
works in CI as a regression check on your own results.
|
|
158
|
+
|
|
159
|
+
### Verdicts
|
|
160
|
+
|
|
161
|
+
`diff` does not just list changed fields. It separates fields that could have
|
|
162
|
+
**caused** a difference (`code`, `param`, `seed`, `input`, `env`) from fields
|
|
163
|
+
that merely **record** one (`result`, `output`), and reports what the
|
|
164
|
+
combination implies:
|
|
165
|
+
|
|
166
|
+
| Verdict | Meaning |
|
|
167
|
+
|---|---|
|
|
168
|
+
| `identical` | Nothing meaningful moved. |
|
|
169
|
+
| `explained` | Results differ and so do plausible causes. Here they are. |
|
|
170
|
+
| `no_effect` | Environment changed, results didn't. Evidence of robustness. |
|
|
171
|
+
| **`nondeterministic`** | **Results differ and nothing that could have caused it does.** |
|
|
172
|
+
| `incomparable` | The runs recorded different result fields. |
|
|
173
|
+
|
|
174
|
+
That fourth verdict is the valuable one. An unseeded RNG buried three libraries
|
|
175
|
+
deep can survive for years because nobody ever compares two runs precisely
|
|
176
|
+
enough to notice. `daftar` reports it as a finding rather than a glitch.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Sweeps
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
result = daftar.sweep(
|
|
184
|
+
simulate, label="tau-sweep", seed=42,
|
|
185
|
+
dt=[0.025, 0.01], tau=[5.0, 10.0, 20.0],
|
|
186
|
+
)
|
|
187
|
+
print(result.table())
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Each grid point is a separate run with its own manifest — not one run with a
|
|
191
|
+
nested table. That means a sweep point and a run you did by hand last Tuesday
|
|
192
|
+
are the same kind of object, and `diff` works across them. A sweep that fails at
|
|
193
|
+
point 3 of 40 keeps the first two results.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Replay
|
|
198
|
+
|
|
199
|
+
`daftar replay` prints a plan, and deliberately does **not** execute
|
|
200
|
+
anything. Re-running arbitrary recorded code would mean this package executes
|
|
201
|
+
whatever a manifest tells it to, and it still could not restore your CUDA
|
|
202
|
+
driver. What it does honestly is state the target state, check the current state
|
|
203
|
+
against it, and list every discrepancy:
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
Replay plan for r-4f21ab
|
|
207
|
+
|
|
208
|
+
entrypoint sim/celegans_hh.py::run_network
|
|
209
|
+
commit 9c1d0ae
|
|
210
|
+
seed 42
|
|
211
|
+
|
|
212
|
+
BLOCKERS -- this run cannot be reproduced as recorded:
|
|
213
|
+
- input file changed since the run: data/connectome.csv
|
|
214
|
+
(was a7f39b21, now 3e0c77af)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Export
|
|
220
|
+
|
|
221
|
+
`daftar export` writes a zip containing `README.md`, `manifest.json`,
|
|
222
|
+
`fields.tsv`, and the referenced input and output files. The README is generated
|
|
223
|
+
in plain English at the archive root, so a successor learns what they are
|
|
224
|
+
looking at without installing anything. A bundle that needs our tool to be
|
|
225
|
+
understood defeats its own purpose.
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Framework adapters
|
|
230
|
+
|
|
231
|
+
The core tracks any Python function. An adapter earns its existence only by
|
|
232
|
+
knowing something a generic tracker cannot infer.
|
|
233
|
+
|
|
234
|
+
| Adapter | Records what you'd otherwise lose |
|
|
235
|
+
|---|---|
|
|
236
|
+
| `jaxley` | morphology (compartments, branches, channels, synapses), `jx.integrate` defaults you never passed, `jax_enable_x64`, backend |
|
|
237
|
+
| `cpm` | parameter **bounds and priors**, estimator and its scipy method/tolerance, per-participant convergence counts, cohort hash |
|
|
238
|
+
| `meltingpot` | resolved substrate ConfigDict hash, roles, episode-length cap, pinned bot checkpoints, per-player returns and Gini |
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
from daftar.adapters import jaxley as jxa
|
|
242
|
+
|
|
243
|
+
with daftar.track("hh-cell", seed=0) as run:
|
|
244
|
+
v = jxa.integrate(cell, run, t_max=10.0, delta_t=0.025)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Adapters never import their framework at module load, so `import daftar`
|
|
248
|
+
works with none of them installed. Every probe is best-effort: a provenance tool
|
|
249
|
+
that crashes a four-hour simulation because a framework renamed an attribute has
|
|
250
|
+
done far more harm than the missing field was worth.
|
|
251
|
+
|
|
252
|
+
See `examples/adapter_usage.py` for the full pattern for each.
|
|
253
|
+
|
|
254
|
+
### Why not Concordia
|
|
255
|
+
|
|
256
|
+
Every Concordia agent step calls `LanguageModel.sample_text()`, and no major
|
|
257
|
+
provider guarantees token-level determinism even with a fixed seed. `replay`
|
|
258
|
+
there cannot mean what it means everywhere else, and shipping an adapter whose
|
|
259
|
+
replay silently does not replay would undermine the one property this package
|
|
260
|
+
sells.
|
|
261
|
+
|
|
262
|
+
The right design is a different contract — wrap the model, hash every
|
|
263
|
+
`(prompt, response)` pair in order, and have `diff` report the first step at
|
|
264
|
+
which two runs diverged. That turns Concordia into the strongest argument for
|
|
265
|
+
this whole package rather than an awkward fit, because LLM-driven simulation is
|
|
266
|
+
the case where nobody can currently audit anything. It comes after the
|
|
267
|
+
deterministic adapters have users.
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Try it
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
python examples/demo_end_to_end.py
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
No frameworks needed. Walks through a clean reproduction, a deliberate parameter
|
|
278
|
+
change, a genuine nondeterminism catch, a sweep, a replay plan, and an export.
|
|
279
|
+
|
|
280
|
+
## Development
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
pip install -e ".[dev]"
|
|
284
|
+
pytest -q
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Licence
|
|
288
|
+
|
|
289
|
+
Apache 2.0.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Publishing daftar
|
|
2
|
+
|
|
3
|
+
## Why your TestPyPI upload returned 403
|
|
4
|
+
|
|
5
|
+
**TestPyPI is a completely separate service from PyPI.** Separate database,
|
|
6
|
+
separate accounts, separate API tokens. A token issued by `pypi.org` is
|
|
7
|
+
meaningless to `test.pypi.org` and is rejected with a bare `403 Forbidden` —
|
|
8
|
+
which is exactly what you saw.
|
|
9
|
+
|
|
10
|
+
In likelihood order:
|
|
11
|
+
|
|
12
|
+
1. **You used a PyPI token on TestPyPI.** Overwhelmingly the most common cause.
|
|
13
|
+
2. **You have no TestPyPI account.** Registering on PyPI does not register you
|
|
14
|
+
on TestPyPI. Sign up separately at
|
|
15
|
+
<https://test.pypi.org/account/register/>.
|
|
16
|
+
3. **Email not verified** on the TestPyPI account. Unverified accounts cannot
|
|
17
|
+
upload, and the error is a 403 with no explanation.
|
|
18
|
+
4. **The name is taken on TestPyPI.** Its namespace is full of abandoned junk
|
|
19
|
+
and is pruned irregularly. If someone holds `daftar` there you get a 403,
|
|
20
|
+
and it says nothing about real PyPI, where `daftar` is confirmed free.
|
|
21
|
+
|
|
22
|
+
To rule out 1–3, get a token from
|
|
23
|
+
<https://test.pypi.org/manage/account/token/> and retry with `--verbose`:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
python -m twine upload --repository testpypi --verbose dist/*
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The verbose output distinguishes "bad credentials" from "you do not own this
|
|
30
|
+
project name", which the plain error does not.
|
|
31
|
+
|
|
32
|
+
## The thing worth noticing
|
|
33
|
+
|
|
34
|
+
Your upload reached **100%** before failing. The bytes crossed the network and
|
|
35
|
+
were rejected at the authorization layer. Uploading to the Python package index
|
|
36
|
+
from where you are is not blocked. That was the open question, and it is now
|
|
37
|
+
answered.
|
|
38
|
+
|
|
39
|
+
## Recommendation: skip TestPyPI
|
|
40
|
+
|
|
41
|
+
TestPyPI's purpose is rehearsing a release. You have already done the parts that
|
|
42
|
+
matter:
|
|
43
|
+
|
|
44
|
+
- `python -m build` succeeds with no warnings
|
|
45
|
+
- `python -m twine check dist/*` passes both artifacts
|
|
46
|
+
- the wheel installs into a clean virtualenv and imports with zero dependencies
|
|
47
|
+
- 34 tests pass
|
|
48
|
+
|
|
49
|
+
A successful TestPyPI upload would tell you nothing further, and every day spent
|
|
50
|
+
debugging it is a day `daftar` remains unclaimed on the index that matters.
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# 1. Account on pypi.org, email verified
|
|
54
|
+
# 2. Token: pypi.org -> Account settings -> API tokens -> "Add API token"
|
|
55
|
+
# Scope "Entire account" for the first upload; re-scope to the project after.
|
|
56
|
+
python -m twine upload dist/*
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
When prompted, paste the token including the `pypi-` prefix. Twine 7 asks for
|
|
60
|
+
the token directly, so you do not need to type `__token__` as a username.
|
|
61
|
+
|
|
62
|
+
To avoid re-pasting, put it in `~/.pypirc` (mode 600):
|
|
63
|
+
|
|
64
|
+
```ini
|
|
65
|
+
[distutils]
|
|
66
|
+
index-servers = pypi testpypi
|
|
67
|
+
|
|
68
|
+
[pypi]
|
|
69
|
+
username = __token__
|
|
70
|
+
password = pypi-AgEIcHlwaS5vcmc...
|
|
71
|
+
|
|
72
|
+
[testpypi]
|
|
73
|
+
repository = https://test.pypi.org/legacy/
|
|
74
|
+
username = __token__
|
|
75
|
+
password = pypi-AgENdGVzdC5weXBpLm9yZw...
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Note the two tokens differ: TestPyPI tokens encode `dGVzdC5weXBpLm9yZw` —
|
|
79
|
+
base64 for `test.pypi.org`. If yours does not, you are holding the wrong one.
|
|
80
|
+
|
|
81
|
+
## A version number can never be reused
|
|
82
|
+
|
|
83
|
+
Not even after deleting the release. If 0.1.0 turns out wrong, ship 0.1.1. Do
|
|
84
|
+
not agonise over the first upload; the name is the scarce thing, not the
|
|
85
|
+
version.
|
|
86
|
+
|
|
87
|
+
## Also claim
|
|
88
|
+
|
|
89
|
+
- GitHub `github.com/aslansd/daftar` (the org name `daftar` was free when checked)
|
|
90
|
+
- Update `[project.urls]` in `pyproject.toml` if you use a different path
|
|
91
|
+
|
|
92
|
+
## Before announcing
|
|
93
|
+
|
|
94
|
+
- [ ] `pytest -q` green
|
|
95
|
+
- [ ] `python examples/demo_end_to_end.py` runs on a fresh clone
|
|
96
|
+
- [ ] wheel installed into a clean venv and imported
|
|
97
|
+
- [ ] README renders correctly on the live PyPI page
|
|
98
|
+
- [ ] **run daftar across three of your own repos, unmodified**
|
|
99
|
+
- [ ] `git tag v0.1.0 && git push --tags`
|
|
100
|
+
|
|
101
|
+
The fifth item is the month-7 milestone from the feasibility plan and the only
|
|
102
|
+
real test of whether the API is unobtrusive enough that you keep using it when
|
|
103
|
+
nobody is watching. Do it before the announcement, not after.
|
|
104
|
+
|
|
105
|
+
## On the licence
|
|
106
|
+
|
|
107
|
+
`LICENSE` now contains the full Apache-2.0 text, and `pyproject.toml` declares
|
|
108
|
+
`license = "Apache-2.0"` as an SPDX expression. This is not bookkeeping: the
|
|
109
|
+
strategy rests on publishing freely available source code, which has generally
|
|
110
|
+
been treated as "information and informational materials". A public repository
|
|
111
|
+
with a permissive licence and a licence file present is a different legal object
|
|
112
|
+
from a private or licence-gated artifact. Keep it that way.
|