Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,23 +204,33 @@ locally and fail in CI.

## Documentation Index (`misc/docs/`)

**Master index: [misc/docs/README.md](misc/docs/README.md)** — overview of the two
architectures (shipping delegation vs the flat model), reading paths per audience,
and the full doc index with status labels. The table below is the quick version.

| Document | Contents |
|----------|----------|
| [README.md](misc/docs/README.md) | **Start here.** Master index: big picture, reading paths, status labels |
| [dol_flat_model.md](misc/docs/dol_flat_model.md) | **The flat model reference** (Option G): a wrap is `(leaf, spec, stack)` — flat compiled codec stack, typed interface specs, loudness policies, codec laws, scope limits, the six decisions Q0–Q5, code map for `dol/_interface_wrap.py` (private, experimental) |
| [dol_roadmap.md](misc/docs/dol_roadmap.md) | **Sequencing SSOT**: tracks A–E (flat engine P0–P3, is-a, paths engine, fleet program #91/#92/#94, hygiene) |
| [general_design.md](misc/docs/general_design.md) | Language-agnostic design: what dol is, the KV pipeline, layered composition, patterns |
| [dol_design.md](misc/docs/dol_design.md) | Python architecture: class hierarchy, `wrap_kvs` deep dive, `Codec`/`Sig`/`Pipe`, critique |
| [dol_design.md](misc/docs/dol_design.md) | Python architecture: class hierarchy, `wrap_kvs` deep dive, `Codec`/`Sig`/`Pipe`, critique. **Partially superseded** — see its banner; prefer the architecture map for mechanics |
| [dol_architecture_map.md](misc/docs/dol_architecture_map.md) | Code-verified structural map: module/dependency graph, public API, class hierarchy, `wrap_kvs`/codec machinery deep dive, ranked tech debt. **Start here for refactors.** |
| [issues_and_discussions.md](misc/docs/issues_and_discussions.md) | GitHub issues/discussions themes, known limitations, open design questions |
| [dol_issues_report.md](misc/docs/dol_issues_report.md) | Prioritized issue triage + wave-by-wave tackle order |
| [dol_issue16_design.md](misc/docs/dol_issue16_design.md) | Issue #16 design: optional key-path write-through / autovivification — opt-in `create_missing`, contextual per-level factory, the `path_set_writeback` boundary engine + persistent-store write-back protocol, scoped plan. Design-only (no code yet). |
| [dol_issues_report.md](misc/docs/dol_issues_report.md) | Historical triage snapshot (2026-07-02); sequencing superseded by `dol_roadmap.md`, verification log still cited |
| [dol_issue16_design.md](misc/docs/dol_issue16_design.md) | Issue #16 design: optional key-path write-through / autovivification — opt-in `create_missing`, contextual per-level factory, the `path_set_writeback` boundary engine + persistent-store write-back protocol. **Implementation shipped** (see Known Limitations below). |
| [dol_issue18_design.md](misc/docs/dol_issue18_design.md) | Issue #18 design: `self`-not-wrapped delegation trap — `wrapped_self` (shipped) now, is-a wrapping (deferred, major) later. |
| [dol_issue83_design.md](misc/docs/dol_issue83_design.md) | Issue #83 design study: the **inverse** of #18 — a delegated method *receives* the unmapped key. Two delegation routes (a fix for one is a no-op on the other), a 13-package census (mostly **latent**; 12 claims refuted), and options A–F with verified costs: `wrapped_self` has its own silent hole (degrades with no live strong reference), chain-walking free functions break on non-`Store` layers, and the only form correct *by construction* is routing the capability through `__getitem__` as a sibling store. **§5 is the carry-forward list for a future redesign.** |
| [dol_issue86_design.md](misc/docs/dol_issue86_design.md) | Discussion #86 design study: **Option G** — spec-carried boundary codecs on a flat proxy (wrapt lessons, KT/VT-annotated interface specs, flatten-and-compile codec stacks). Prototype in `dol/_interface_wrap.py` (private, experimental). Headline: is-a does **not** fix #83 for backend-direct method bodies — F and G serve disjoint populations; codec laws (§2.5) are the boundary invariant's fine print; flat-model guarantees are scoped to pure-codec stacks (filters/caches still nest). Open question 0: who owns the wrap_kvs endgame. |
| [dol_issue10_design.md](misc/docs/dol_issue10_design.md) | Issues #10 + #2 (paired) design: recursive wrapping of nested stores (`recursive_wrap`) + a flat `KvReader`/`KvPersister` view (`flat_store`), sharing one `(path,key,value)` descent frontier and reusing the #16 `path_set_writeback` engine. Load-bearing fix: the recursion read-surface and the write-back boundary must be **different** objects (naive `boundary=self` infinite-loops). Model-2 read + write-into-existing in scope; persistent creation deferred to P3. Design-only (no code yet). |
| [frontend_dol_ideas.md](misc/docs/frontend_dol_ideas.md) | `zoddal` design: TypeScript KV interface, adapters, Zod bridge, zod-collection-ui integration |
| [dol_content_metadata_bifurcation.md](misc/docs/dol_content_metadata_bifurcation.md) | The content/metadata split-store problem (feeds issue #80) |
| [code-quality-improvements.md](misc/docs/code-quality-improvements.md) | Tech-debt tracker: dead code, coverage gaps (feeds issue #94) |

> A **local-only** ecosystem inventory (gitignored) lives in `misc/data/`: dol's 76
> dependents, their usages (file:line), a pre-PR test-gate order + runner, and the
> `wrap_kvs` blast-radius scan. Regenerate with the scripts there.
> A **local-only** ecosystem inventory (gitignored) lives in `misc/data/`: dol's 85
> direct dependents (as of the 2026-08-03 scan), their usages (file:line), a pre-PR
> test-gate order + runner, and the `wrap_kvs` blast-radius scan. Regenerate with
> the scripts there. Growing this into a versioned fleet ledger is issue #91.

---

Expand Down
111 changes: 111 additions & 0 deletions misc/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# dol design documentation — start here

`dol` is a pure-Python, dependency-free toolkit for putting a uniform `dict`-like
(Mapping) face on any storage backend — files, S3, databases, in-memory — by
composing **key transforms**, **value transforms** (codecs), **filters**, and
**caches** over a raw backend. Domain code speaks `store[key]`; the layers decide
what that means physically.

This folder is the design memory of the project: reference docs (how it works),
design studies (why it works that way), decision records, and the roadmap. This
README is the master index — read the two paragraphs below for the big picture,
pick your reading path, then dig in.

## The one thing to understand first: two architectures

**Today (shipping)**: dol wraps by **has-a delegation** — each `wrap_kvs` /
`Store` layer is an object holding the previous one. It works, it's everywhere
(85 local dependent packages), and it has known structural traps: inside a
wrapped method `self` is the *unwrapped* store (#18), a delegated method
*receives* untransformed keys (#83), stacked wraps don't pickle, and there is no
inverse key mapping.

**The decided direction (experimental)**: the **flat model** — a wrap is
`(leaf, spec, stack)`: one proxy, a typed interface spec saying where keys/values
occur in *every* method, and a flat, compiled list of codec layers. Re-wrapping
extends the list; it never nests. The endgame (decision Q0, 2026-08-10) is a
**split synthesis**: codec/instance wrapping compiles to the flat engine;
class-decoration becomes is-a. Both mechanisms exist because they fix *disjoint*
populations of the delegation traps. Narrative walkthrough: discussion
[#90](https://github.com/i2mint/dol/discussions/90).

Where things stand and what's next: **[dol_roadmap.md](dol_roadmap.md)** (the
sequencing SSOT).

## Reading paths

**I want to build stores with dol (consumer).**
Repo-root `README.md` and `llms.txt` → the project `CLAUDE.md` core patterns (or
the `dol-store-building` skill) → [general_design.md](general_design.md) for the
conceptual model. Dip into [dol_design.md](dol_design.md)'s worked examples when
"why does this work" strikes. You should never need the issue docs; the gotchas
that matter (`wrapped_self`, `create_missing`) are in `CLAUDE.md`'s Known
Limitations.

**I'm changing dol itself (maintainer / refactorer).**
[dol_architecture_map.md](dol_architecture_map.md) first (code-verified map) →
the `dol-dev-wrap-kvs` skill before touching `trans.py`/`base.py` →
[dol_roadmap.md](dol_roadmap.md) for what's in flight → then the design-study
chain for your area (see the index). Before any PR touching `wrap_kvs`: the
dependents test-gate (local `misc/data/` inventory).

**I'm an agent needing orientation.**
`llms.txt` → project `CLAUDE.md` → stop. Escalate to
[dol_architecture_map.md](dol_architecture_map.md) §2–3 (navigation) and §9
(idioms). Prefer the architecture map over [dol_design.md](dol_design.md) for
citation-grade mechanics — the latter is partially superseded (see its banner).

**I want the design history (how we got here).**
[issues_and_discussions.md](issues_and_discussions.md) →
[dol_issues_report.md](dol_issues_report.md) (2026-07 triage snapshot) → the
study arc: [dol_issue18_design.md](dol_issue18_design.md) →
[dol_issue83_design.md](dol_issue83_design.md) →
[dol_issue86_design.md](dol_issue86_design.md) → discussion
[#90](https://github.com/i2mint/dol/discussions/90). The paths thread runs in
parallel: [dol_issue16_design.md](dol_issue16_design.md) →
[dol_issue10_design.md](dol_issue10_design.md).

## Index

### Reference (how it works)

| Doc | Status | Contents |
|---|---|---|
| [general_design.md](general_design.md) | current (one scoped note) | Language-agnostic architecture: KV interfaces, interface hierarchy, middleware principle, the KV transform pipeline. The timeless layer — note in *Layered Composition* distinguishing semantic layers from runtime nesting. |
| [dol_design.md](dol_design.md) | **partially superseded** — see banner | Python implementation narrative: class hierarchy, `Store` hooks, `wrap_kvs`, codecs, `Sig`, `Pipe`. Still the only home of the `Sig` narrative, the design-critique register, `double_up_as_factory`, and the mid-altitude worked examples. Mechanics claims: prefer the architecture map. |
| [dol_architecture_map.md](dol_architecture_map.md) | current | Code-verified structural map + ranked tech debt. **Start here for refactors.** |
| [dol_flat_model.md](dol_flat_model.md) | current (engine: experimental/private) | **The flat model reference**: `(leaf, spec, stack)`, role codecs, flatten-and-compile, loudness, codec laws, scope limits, the six decisions, code map. |

### Sequencing

| Doc | Status | Contents |
|---|---|---|
| [dol_roadmap.md](dol_roadmap.md) | **living SSOT** | Tracks A–E: flat engine P0–P3, is-a, paths engine, the fleet program (#91 ledger / #92 vocabulary / #94 cruft), hygiene. Supersedes the issues-report waves. |
| [dol_issues_report.md](dol_issues_report.md) | historical snapshot (2026-07-02) | The triage that ordered the program: close-list, dependency map, verification log. Sequencing superseded by the roadmap; evidence still cited. |
| [issues_and_discussions.md](issues_and_discussions.md) | current-ish | Themes from GitHub issues/discussions. |

### Design studies & decision records (why it works that way)

| Doc | Contents |
|---|---|
| [dol_issue18_design.md](dol_issue18_design.md) | The delegation trap (`self` unwrapped inside methods): `wrapped_self` (shipped), is-a plan (Track B), rebind rejection. |
| [dol_issue83_design.md](dol_issue83_design.md) | The inverse trap (methods *receive* unmapped keys): 13-package census, options A–F, the carry-forward list (§5). |
| [dol_issue86_design.md](dol_issue86_design.md) | **Option G decision record**: the flat model's design study, adversarial-panel evidence, codec laws, Q0–Q5 decisions (§11), migration P0–P3. |
| [dol_issue16_design.md](dol_issue16_design.md) | Key-path write-through / autovivification (shipped): the `path_set_writeback` boundary engine. |
| [dol_issue10_design.md](dol_issue10_design.md) | Recursive wrapping + flat store view (designed, code pending); reuses the #16 engine. |
| [dol_content_metadata_bifurcation.md](dol_content_metadata_bifurcation.md) | The content/metadata split-store problem (feeds #80). |

### Operational / peripheral

| Doc | Contents |
|---|---|
| [code-quality-improvements.md](code-quality-improvements.md) | Tech-debt tracker (dead code, coverage gaps). Feeds #94. |
| [CHANGELOG.md](CHANGELOG.md) | Change log. |
| [frontend_dol_ideas.md](frontend_dol_ideas.md) | `zoddal`: the TypeScript/Zod incarnation of the dol idea. |
| [generate_llms_txt_instruction.md](generate_llms_txt_instruction.md) | How the repo's `llms.txt` files are generated. |

> A **local-only** ecosystem inventory (gitignored) lives in `misc/data/`: dol's
> 85 direct dependents, their usages (file:line), a pre-PR test-gate order +
> runner, and the `wrap_kvs` blast-radius scan. Regenerate with the scripts
> there. Growing this into a versioned fleet ledger is
> [#91](https://github.com/i2mint/dol/issues/91).
5 changes: 3 additions & 2 deletions misc/docs/dol_architecture_map.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ It **complements, does not repeat** the existing `misc/docs`:
| GitHub issues/discussions themes | [issues_and_discussions.md](issues_and_discussions.md) | Corrects the Issue #9 root-cause (§5.4) |
| The split-store / content-metadata problem | [dol_content_metadata_bifurcation.md](dol_content_metadata_bifurcation.md) | — |
| Dead code / coverage tracker | [code-quality-improvements.md](code-quality-improvements.md) | Adds new debt found (§11) |
| Doc index | [dol_misc_docs_guide.md](dol_misc_docs_guide.md) | Should be updated to list this file |
| Doc index | [README.md](README.md) | The master index; routes here for refactors |

### Staleness / inaccuracies found in existing docs

Expand Down Expand Up @@ -600,7 +600,8 @@ single `cache_this` with an explicit `key`/`cache` over stacking.
`path_get`/`_path_get`/`chain_get`.
10. **Every module must keep its top-level docstring** (all 20 currently have one — verified;
they are auto-extracted for docs). When adding a module or editing one, preserve/enhance
it (per CLAUDE.md). And update `dol_misc_docs_guide.md` if you add a doc here.
it (per CLAUDE.md). And update `misc/docs/README.md` (the master index) if you
add a doc here.

---

Expand Down
41 changes: 40 additions & 1 deletion misc/docs/dol_design.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

This document describes the Python-specific implementation of dol's design. For the language-agnostic concepts, see [general_design.md](general_design.md).

> **Status (2026-08): partially superseded.** This doc describes the *shipping*
> delegation architecture, which remains what users run today — but the redesign
> program ([dol_flat_model.md](dol_flat_model.md),
> [dol_issue86_design.md](dol_issue86_design.md), decisions Q0–Q5) has superseded
> several sections; each carries an inline note. For citation-grade mechanics
> prefer [dol_architecture_map.md](dol_architecture_map.md). Still uniquely here:
> the `Sig` narrative, the design-critique register, `double_up_as_factory`, and
> the worked examples. Index: [README.md](README.md).

---

## Class Hierarchy
Expand Down Expand Up @@ -65,6 +74,13 @@ The hooks default to identity (no-op), so `Store(dict())` behaves exactly like a

## `wrap_kvs`: The Core Transformation Function

> **Note (2026-08):** accurate for the shipping architecture, with two updates:
> the method-transform parameters documented below (`outcoming_key_methods` /
> `ingoing_key_methods` …) are **verified broken** and replaced by typed interface
> specs in the flat model ([dol_issue86_design.md](dol_issue86_design.md) TL;DR 1);
> and per decision Q0, codec/instance wrapping compiles to the flat engine at the
> endgame ([dol_flat_model.md](dol_flat_model.md)).

Located in `dol/trans.py:1801`. The most important function in the library.

```python
Expand Down Expand Up @@ -152,6 +168,12 @@ store = wrap_kvs(store, obj_of_data=json.loads, data_of_obj=json.dumps)

## `store_decorator`: The Meta-Decorator

> **Note (2026-08):** the 4-way usage taxonomy survives, but the instance branch
> ("wraps it in `Store` first") is what changes under decision Q0: instance
> wrapping compiles to a flat proxy at the endgame, not a fresh `Store` subclass.
> The P2 compatibility questions are listed in
> [dol_roadmap.md](dol_roadmap.md) Track A.

Located in `dol/trans.py:130`. Enables writing a class-transforming function once and using it in 4 ways:

```python
Expand Down Expand Up @@ -331,6 +353,14 @@ def my_func(*args, **kwargs): ...

## Delegation Pattern

> **Note (2026-08): the most-superseded section of this doc.** The snippet below
> is simplified (the real implementation guards via `object.__getattribute__`,
> see the architecture map), and delegation-as-the-architecture is what the flat
> carrier replaces for codec stacks: capability mirroring plus the
> `undeclared='exclude'` policy (decision Q2) eliminate the verified
> `DelegatedAttribute` raw-data leaks (`__or__`/`copy`/`fromkeys`). Delegation
> remains the shipping mechanism, and remains the model for filter/cache layers.

`Store` uses the delegation pattern: it holds a reference to an inner store (`self.store`) and delegates all storage operations to it. Attribute access falls through via `__getattr__`:

```python
Expand Down Expand Up @@ -461,6 +491,12 @@ kt.dict_to_key({"user": "john", "year": "2024", "month": "01"}) # 'john/2024/01

## Design Critique and Alternatives

> **Note (2026-08):** this register predates the redesign; several critiques have
> since been *realized* rather than refuted — item 1's Protocol suggestion and
> item 6's missing generics are now the flat model's core mechanism
> (KT/VT-annotated Protocol specs, typed codecs per decision Q3). Items 2
> (`clear()`/LSP), 3 (naming — now issue #92), and 5 (async) remain live.

### 1. ABC Inheritance vs. Protocols

**Current approach**: Classes inherit from `collections.abc.Mapping`, `MutableMapping`, etc.
Expand Down Expand Up @@ -536,7 +572,10 @@ kt.dict_to_key({"user": "john", "year": "2024", "month": "01"}) # 'john/2024/01

`wrap_kvs` is powerful but creates anonymous classes at runtime, which has implications:
- `type(store).__name__` may not be meaningful
- Pickling can be tricky (though dol handles this via `__reduce__`)
- Pickling is **broken today** for decorator-form, `Files`, and stacked wraps (one
root cause: class-name shadowing — verified in the #86 study's 7-case matrix);
instance wraps and a single class-wrap work. The flat proxy repairs the stacked
case by construction.
- Debugging stack traces show generic names

For performance-critical code or when pickling is needed, direct subclassing is still more reliable.
Expand Down
Loading
Loading