endow 0.0.1__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.
endow-0.0.1/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ venv*
2
+ *.bak
3
+ *.pyc
4
+ .idea/
5
+ .env
@@ -0,0 +1 @@
1
+ *
@@ -0,0 +1,432 @@
1
+ <!DOCTYPE html>
2
+ <!-- Agent note: if you are reading with head, treat this file as the planning source of truth and keep Status/To-do/Log current as you work. -->
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>endow · formplan</title>
8
+ <style>
9
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
10
+
11
+ :root {
12
+ --ink: #1a1a18;
13
+ --ink-faint: #6b6b60;
14
+ --rule: #d8d8cc;
15
+ --fill: #f5f5ef;
16
+ --page: #fefefe;
17
+ --accent: #1a6b3c;
18
+ --accent-bg: #edf5f0;
19
+ --warn: #9b4a00;
20
+ --warn-bg: #fff4ea;
21
+ --mono: "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
22
+ --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, "Times New Roman", serif;
23
+ }
24
+
25
+ html { font-size: 16px; }
26
+
27
+ body {
28
+ font-family: var(--mono);
29
+ font-size: 0.8125rem;
30
+ line-height: 1.6;
31
+ color: var(--ink);
32
+ background: var(--fill);
33
+ min-height: 100vh;
34
+ padding: 2rem 1rem 6rem;
35
+ }
36
+
37
+ main {
38
+ max-width: 960px;
39
+ margin: 0 auto;
40
+ display: grid;
41
+ grid-template-columns: 280px 1fr;
42
+ gap: 2rem;
43
+ align-items: start;
44
+ }
45
+
46
+ header,
47
+ hr,
48
+ form,
49
+ footer {
50
+ grid-column: 1 / -1;
51
+ }
52
+
53
+ header {
54
+ display: flex;
55
+ align-items: baseline;
56
+ justify-content: space-between;
57
+ gap: 1rem;
58
+ padding-bottom: 0.75rem;
59
+ border-bottom: 2px solid var(--ink);
60
+ margin-bottom: 0.25rem;
61
+ }
62
+
63
+ header h1 {
64
+ font-family: var(--serif);
65
+ font-size: 1.5rem;
66
+ font-weight: 300;
67
+ font-style: italic;
68
+ letter-spacing: -0.01em;
69
+ }
70
+
71
+ header span {
72
+ font-size: 0.6875rem;
73
+ color: var(--ink-faint);
74
+ white-space: nowrap;
75
+ }
76
+
77
+ section { margin-bottom: 0.25rem; }
78
+
79
+ section > h2 {
80
+ font-size: 0.625rem;
81
+ font-weight: 500;
82
+ letter-spacing: 0.12em;
83
+ text-transform: uppercase;
84
+ color: var(--ink-faint);
85
+ margin-bottom: 0.6rem;
86
+ }
87
+
88
+ section > p,
89
+ section > ul,
90
+ section > ol,
91
+ section > aside {
92
+ background: var(--page);
93
+ border: 1px solid var(--rule);
94
+ border-radius: 3px;
95
+ padding: 0.875rem 1rem;
96
+ }
97
+
98
+ section > p {
99
+ font-family: var(--serif);
100
+ font-size: 0.9375rem;
101
+ font-weight: 300;
102
+ line-height: 1.7;
103
+ color: var(--ink);
104
+ }
105
+
106
+ section > p[data-status] {
107
+ font-family: var(--mono);
108
+ font-size: 0.75rem;
109
+ display: flex;
110
+ align-items: center;
111
+ gap: 0.5rem;
112
+ padding: 0.625rem 1rem;
113
+ }
114
+
115
+ section > p[data-status]::before {
116
+ content: '';
117
+ display: inline-block;
118
+ width: 7px;
119
+ height: 7px;
120
+ border-radius: 50%;
121
+ flex-shrink: 0;
122
+ }
123
+
124
+ p[data-status="active"] { background: var(--accent-bg); border-color: #b4d9c4; color: var(--accent); }
125
+ p[data-status="active"]::before { background: var(--accent); }
126
+ p[data-status="blocked"] { background: var(--warn-bg); border-color: #f0ccaa; color: var(--warn); }
127
+ p[data-status="blocked"]::before { background: var(--warn); }
128
+ p[data-status="done"] { background: var(--fill); border-color: var(--rule); color: var(--ink-faint); }
129
+ p[data-status="done"]::before { background: var(--rule); }
130
+
131
+ ul, ol {
132
+ list-style: none;
133
+ display: flex;
134
+ flex-direction: column;
135
+ gap: 0;
136
+ }
137
+
138
+ li {
139
+ display: flex;
140
+ align-items: center;
141
+ gap: 0.6rem;
142
+ padding: 0.45rem 0;
143
+ border-bottom: 1px solid var(--fill);
144
+ line-height: 1.45;
145
+ }
146
+
147
+ li:last-child { border-bottom: none; }
148
+
149
+ aside ul {
150
+ list-style: disc;
151
+ display: block;
152
+ padding-left: 1.25rem;
153
+ }
154
+
155
+ aside li {
156
+ display: list-item;
157
+ padding: 0.3rem 0;
158
+ border-bottom: none;
159
+ line-height: 1.6;
160
+ }
161
+
162
+ section > ul li > label {
163
+ display: flex;
164
+ align-items: center;
165
+ gap: 0.65rem;
166
+ width: 100%;
167
+ cursor: pointer;
168
+ font-size: 0.8125rem;
169
+ font-weight: 400;
170
+ letter-spacing: 0;
171
+ text-transform: none;
172
+ color: var(--ink);
173
+ margin: 0;
174
+ }
175
+
176
+ section > ul li > label > input[type="checkbox"] {
177
+ appearance: none;
178
+ width: 0.95rem;
179
+ height: 0.95rem;
180
+ border: 1px solid var(--rule);
181
+ background: var(--page);
182
+ border-radius: 2px;
183
+ flex-shrink: 0;
184
+ cursor: pointer;
185
+ }
186
+
187
+ section > ul li > label > input[type="checkbox"]:checked {
188
+ background: var(--accent);
189
+ border-color: var(--accent);
190
+ }
191
+
192
+ section > ul li > label > input[type="checkbox"]:checked + span {
193
+ text-decoration: line-through;
194
+ color: var(--ink-faint);
195
+ }
196
+
197
+ ol { counter-reset: log; }
198
+ ol li {
199
+ counter-increment: log;
200
+ display: grid;
201
+ grid-template-columns: 2rem minmax(0, 1fr);
202
+ align-items: start;
203
+ gap: 0.75rem;
204
+ }
205
+ ol li::before {
206
+ content: counter(log, decimal-leading-zero);
207
+ font-size: 0.6rem;
208
+ color: var(--ink-faint);
209
+ padding-top: 0.15em;
210
+ min-width: 1.8em;
211
+ }
212
+
213
+ hr {
214
+ border: none;
215
+ border-top: 1px solid var(--rule);
216
+ margin: 1.5rem 0 0.75rem;
217
+ }
218
+
219
+ form {
220
+ background: var(--page);
221
+ border: 1.5px solid var(--ink);
222
+ border-radius: 3px;
223
+ padding: 1.25rem 1.25rem 1rem;
224
+ }
225
+
226
+ form > p {
227
+ font-family: var(--serif);
228
+ font-size: 0.9375rem;
229
+ font-weight: 300;
230
+ line-height: 1.65;
231
+ margin-bottom: 1rem;
232
+ color: var(--ink);
233
+ }
234
+
235
+ label {
236
+ display: block;
237
+ font-size: 0.625rem;
238
+ font-weight: 500;
239
+ letter-spacing: 0.1em;
240
+ text-transform: uppercase;
241
+ color: var(--ink-faint);
242
+ margin-bottom: 0.35rem;
243
+ }
244
+
245
+ input[type="text"],
246
+ input[type="email"],
247
+ input[type="number"],
248
+ select,
249
+ textarea {
250
+ display: block;
251
+ width: 100%;
252
+ font-family: var(--mono);
253
+ font-size: 0.8125rem;
254
+ color: var(--ink);
255
+ background: var(--fill);
256
+ border: 1px solid var(--rule);
257
+ border-radius: 2px;
258
+ padding: 0.5rem 0.65rem;
259
+ outline: none;
260
+ transition: border-color 0.12s, box-shadow 0.12s;
261
+ margin-bottom: 1rem;
262
+ resize: vertical;
263
+ }
264
+
265
+ input:focus, select:focus, textarea:focus {
266
+ border-color: var(--ink);
267
+ box-shadow: 0 0 0 2px rgba(26,26,24,0.06);
268
+ }
269
+
270
+ textarea { min-height: 80px; }
271
+
272
+ fieldset {
273
+ border: none;
274
+ margin-bottom: 1rem;
275
+ }
276
+
277
+ fieldset legend {
278
+ font-size: 0.625rem;
279
+ font-weight: 500;
280
+ letter-spacing: 0.1em;
281
+ text-transform: uppercase;
282
+ color: var(--ink-faint);
283
+ margin-bottom: 0.5rem;
284
+ }
285
+
286
+ fieldset > label {
287
+ display: flex;
288
+ align-items: center;
289
+ gap: 0.5rem;
290
+ font-size: 0.8125rem;
291
+ font-weight: 400;
292
+ letter-spacing: 0;
293
+ text-transform: none;
294
+ color: var(--ink);
295
+ cursor: pointer;
296
+ margin-bottom: 0.35rem;
297
+ }
298
+
299
+ input[type="radio"],
300
+ form input[type="checkbox"] {
301
+ width: auto;
302
+ margin: 0;
303
+ accent-color: var(--accent);
304
+ }
305
+
306
+ button[type="submit"] {
307
+ font-family: var(--mono);
308
+ font-size: 0.75rem;
309
+ font-weight: 500;
310
+ letter-spacing: 0.05em;
311
+ color: var(--page);
312
+ background: var(--ink);
313
+ border: none;
314
+ border-radius: 2px;
315
+ padding: 0.55rem 1.1rem;
316
+ cursor: pointer;
317
+ transition: background 0.12s;
318
+ margin-top: 0.25rem;
319
+ }
320
+
321
+ button[type="submit"]:hover { background: #333330; }
322
+
323
+ form::before {
324
+ content: 'llm question';
325
+ display: block;
326
+ font-size: 0.6rem;
327
+ font-weight: 500;
328
+ letter-spacing: 0.14em;
329
+ text-transform: uppercase;
330
+ color: var(--ink-faint);
331
+ margin-bottom: 0.75rem;
332
+ }
333
+
334
+ footer {
335
+ margin-top: 1.5rem;
336
+ padding-top: 0.75rem;
337
+ border-top: 1px solid var(--rule);
338
+ font-size: 0.6875rem;
339
+ color: var(--ink-faint);
340
+ display: flex;
341
+ justify-content: space-between;
342
+ }
343
+
344
+ @media (max-width: 780px) {
345
+ main {
346
+ grid-template-columns: 1fr;
347
+ gap: 1.5rem;
348
+ }
349
+ }
350
+ </style>
351
+ </head>
352
+ <body>
353
+ <main>
354
+
355
+ <header>
356
+ <h1>endow</h1>
357
+ <span>formplan v0.1</span>
358
+ </header>
359
+
360
+ <section>
361
+ <h2>Status</h2>
362
+ <p data-status="active">Implementation has started. Real behavioral pytest coverage is now in progress; the runtime is intentionally still missing.</p>
363
+ </section>
364
+
365
+ <section>
366
+ <h2>Answers</h2>
367
+ <aside aria-label="Answers">
368
+ <ul>
369
+ <li>Project name: <code>endow</code></li>
370
+ <li>Tagline: <code>to provide with something freely or naturally</code></li>
371
+ <li>Primary authoring style: typed attributes declare dependencies and wiring is inferred from annotations.</li>
372
+ <li>Implementation selection: service/domain classes own concrete selection via <code>from_env(...)</code>.</li>
373
+ <li>Graph lifecycle: one shared object graph per <code>Backend.from_env(...)</code> call.</li>
374
+ <li>Cycles: direct cyclic references such as <code>Products &lt;-&gt; Methods</code> should work transparently in user code.</li>
375
+ <li>Overrides: environment-driven factory selection is sufficient for MVP mocking; no separate override API is required yet.</li>
376
+ <li>Construction style: user classes should not need manual constructor wiring for injected dependencies.</li>
377
+ <li>Runtime inputs: nested <code>from_env(...)</code> factories may request values such as <code>db</code> as needed.</li>
378
+ <li>Naming direction: shared base <code>Injectable</code>, semantic bases <code>Service</code> and <code>Domain</code>, composition root entrypoint <code>Backend.from_env(...)</code>.</li>
379
+ <li>First milestone: a working <code>endow</code> package MVP, not just a spec or example-only prototype.</li>
380
+ </ul>
381
+ </aside>
382
+ </section>
383
+
384
+ <section>
385
+ <h2>Description</h2>
386
+ <p>
387
+ endow is a small dependency-injection library for Python backends. The MVP should make the DX from <code>example.py</code> real: annotation-first dependencies, environment-aware implementation selection, per-root shared graphs, and transparent cyclic domain references, with naming that distinguishes infrastructure services from domain-level backend components.
388
+ </p>
389
+ </section>
390
+
391
+ <section>
392
+ <h2>To-do</h2>
393
+ <ul>
394
+ <li><label><input type="checkbox" checked><span>Capture agreed DX, naming, and MVP scope in this plan file.</span></label></li>
395
+ <li><label><input type="checkbox" checked><span>Create the initial <code>src/</code> layout for the package and tests.</span></label></li>
396
+ <li><label><input type="checkbox" checked><span>Rewrite <code>example.py</code> as the contract for later implementation.</span></label></li>
397
+ <li><label><input type="checkbox" checked><span>Add <code>pyproject.toml</code> using a non-setuptools backend, Python 3.12+, and version metadata from <code>src/endow/__about__.py</code>.</span></label></li>
398
+ <li><label><input type="checkbox" checked><span>Add real behavioral pytest coverage for graph construction, factory selection, runtime inputs, cycle handling, and graph isolation.</span></label></li>
399
+ <li><label><input type="checkbox"><span>Create the <code>endow</code> package with public bases <code>Injectable</code>, <code>Service</code>, <code>Domain</code>, and root construction via <code>Backend.from_env(...)</code>.</span></label></li>
400
+ <li><label><input type="checkbox"><span>Implement graph construction from type annotations with per-root shared instances.</span></label></li>
401
+ <li><label><input type="checkbox"><span>Support <code>from_env(...)</code> factory hooks that can consume runtime inputs and choose concrete implementations.</span></label></li>
402
+ <li><label><input type="checkbox"><span>Make direct dependency cycles work transparently without requiring user-facing lazy/provider wrapper types.</span></label></li>
403
+ <li><label><input type="checkbox"><span>Replace the placeholder <code>example.py</code> with a truthful runnable example using <code>Mailer</code>, <code>Applog</code>, <code>Products</code>, and <code>Methods</code>.</span></label></li>
404
+ <li><label><input type="checkbox"><span>Add tests covering simple wiring, env-based implementation selection, cycle handling, and per-root graph isolation.</span></label></li>
405
+ <li><label><input type="checkbox"><span>Keep this formplan file current as implementation progresses.</span></label></li>
406
+ </ul>
407
+ </section>
408
+
409
+ <section>
410
+ <h2>Log</h2>
411
+ <ol>
412
+ <li>Reviewed the placeholder <code>example.py</code> and confirmed it was a DX sketch rather than working code.</li>
413
+ <li>Collected DX decisions for declaration style, resolution model, graph lifecycle, cycle behavior, overrides, constructor policy, and runtime input flow.</li>
414
+ <li>Selected naming direction: <code>Injectable</code> as the minimal shared base, <code>Service</code> for infrastructure capabilities, <code>Domain</code> for backend domain components, and <code>Backend.from_env(...)</code> as the composition-root entrypoint.</li>
415
+ <li>Confirmed project identity as <code>endow</code> with the tagline <code>to provide with something freely or naturally</code>.</li>
416
+ <li>Chose the first milestone to be a working library MVP with a real example and tests, rather than a spec-only pass.</li>
417
+ <li>Created the initial <code>src/endow</code> and <code>tests</code> directories.</li>
418
+ <li>Rewrote <code>example.py</code> into a contract-style example that defines the intended public naming and runtime behavior.</li>
419
+ <li>Added <code>pyproject.toml</code> with a non-setuptools build backend, Python 3.12+, and dynamic version metadata from <code>src/endow/__about__.py</code>.</li>
420
+ <li>Replaced the earlier contract-test direction with behavioral pytest coverage that should fail until the runtime exists.</li>
421
+ <li>Added a <code>dev</code> optional dependency so <code>uv pip install -e .[dev]</code> installs pytest.</li>
422
+ </ol>
423
+ </section>
424
+
425
+ <footer>
426
+ <span>formplan</span>
427
+ <span>updated <time datetime="2026-06-04">2026-06-04</time></span>
428
+ </footer>
429
+
430
+ </main>
431
+ </body>
432
+ </html>