Skip to content
Open

V2 #3

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
a4141bd
Fix unit tests and lock PyTorch to 2.4.1
Apr 9, 2026
827efba
Fix: move tensors to device and handle inference mode
Apr 10, 2026
42ab29d
Fix: set bnb_4bit_compute_dtype to float16 for massive speedup
Apr 10, 2026
26d7fb7
Fix: cast training latents to float32 to match adapter
Apr 10, 2026
0b0399b
feat: complete V2.1 Latent Space Communication pipeline with query co…
Apr 13, 2026
0595cc7
chore: remove and ignore .DS_Store
star2vec Apr 13, 2026
03a9db5
feat: fix adapter collapse via L_xsep + L_sep (Interlat §3.2-3.3)
star2vec May 10, 2026
c42ae2d
chore: clean up .gitignore and install git hooks
star2vec May 11, 2026
04dbb71
fix: load LoRA with r=16 matching lsep_v3 training (was r=4)
star2vec May 13, 2026
acc784c
chore: bump pyproject build-system and lockfile
star2vec May 14, 2026
84cebbf
build: migrate to hatchling + unpin torch (>=2.11.0)
star2vec May 14, 2026
bcc85a1
docs: update README
star2vec May 14, 2026
095633c
feat(phase-4c): cache augmentation prototype + Cold Stop salvage
star2vec Jun 30, 2026
386026a
eval(phase-4c): fairness ablations overturn the cache-aug win -> NULL
star2vec Jul 1, 2026
b3fa273
docs: archive superseded plans, consolidate papers (CM-0)
star2vec Jul 1, 2026
b70f662
feat(cm-a): KVPrefixCartridge + TDD contract (CM-A.0)
star2vec Jul 1, 2026
82b73b8
feat(cm-a): context-distillation trainer + self-study (CM-A.1 core)
star2vec Jul 1, 2026
2914667
eval(cm-a.1): single-bucket distill proof — gate FAIL (2/8), informative
star2vec Jul 1, 2026
bdba4ae
feat(cm-a.1): retry PASSES — latent-alone 4/8, carries identifiers
star2vec Jul 2, 2026
d785672
feat(cm-a.2): batch distiller + cartridge eval scripts
star2vec Jul 2, 2026
30ee434
fix(cm-a.2): slice-on-overflow in _collect_source_text (both copies)
star2vec Jul 3, 2026
983ca01
feat(cm-a.2): epoch checkpointing + MPS stall watchdog in cartridge t…
star2vec Jul 5, 2026
2ff06c1
eval(cm-a.2): GATE FAIL 7/25 log entry + eval snapshots
star2vec Jul 26, 2026
a431840
chore: deep clean + honest results README
star2vec Jul 26, 2026
4d6d982
eval(cm-b.0a): grounding metric was under-counting — CM-A.2 re-scores…
star2vec Jul 26, 2026
95debd4
fix(cm-b.0b): batch distiller silently ran templated queries, not fac…
star2vec Jul 26, 2026
92f9f83
fix(cm-b.0b): run query generation on CPU — transformers generate() a…
star2vec Jul 26, 2026
dc53e0c
fix(cm-b.0b): eval script carried its own stale grounding metric
star2vec Jul 26, 2026
ccbe505
docs(cm-b): durable plan + CPU slot-structure probe — localization lo…
star2vec Jul 26, 2026
12ca750
fix(cm-b): audit for the bug classes this project keeps hitting
star2vec Jul 26, 2026
9ad225f
docs(cm-b): second bug sweep — trainer internals, truncation chain, r…
star2vec Jul 26, 2026
848c486
fix(cm-b): epoch checkpoint was write-only; log silent git failures; …
star2vec Jul 26, 2026
12c1af7
fix(cm-b): merge/split oscillation guard + dedupe centroid codec
star2vec Jul 26, 2026
e622585
perf(cm-b): cache HealthMonitor coherence embeddings; fix bridge scop…
star2vec Jul 26, 2026
2c92860
docs(cm-b): dependency-graph sweep — cycles, layering, dead code, dea…
star2vec Jul 27, 2026
eb229cb
feat(cm-b.1): controlled edit generator + structural invariant guards
star2vec Jul 27, 2026
0f10187
feat(cm-b.1): cartridge repair methods — slot masking, low-rank delta
star2vec Jul 27, 2026
0daae48
feat(cm-b.1): edit experiment orchestrator + pre-registered gate
star2vec Jul 27, 2026
38aa356
fix(cm-b.0b): record GATE FAIL 1/13; the query-gen premise was wrong
star2vec Jul 27, 2026
d33245c
fix(cm-b): sweep — unseeded measurement track + reciprocal PREFIX_LEN
star2vec Jul 27, 2026
cfacc17
fix(async): fire-and-forget tasks could be GC'd mid-flight and failed…
star2vec Jul 27, 2026
d3a92e8
feat(cm-b): variance aggregator + free test of the verbatim-slicing c…
star2vec Jul 28, 2026
9f007b0
feat(cm-b): verbatim lever + 16 verified fixtures for bc6b90e2
star2vec Jul 28, 2026
c412ce0
eval(cm-b.0b-repro): CM-A.1-retry does NOT reproduce — 2/8, 1/8, 1/8 …
star2vec Jul 28, 2026
0ebb924
eval(cm-b.0b-repro): commit the three draw snapshots
star2vec Jul 28, 2026
b6ce9d2
eval(cm-b.0e): no-context floor — distillation contributes +0 over a …
star2vec Jul 28, 2026
32844ae
eval(cm-b.0d/0e): latent channel is INERT — cartridge - floor = +0.67…
star2vec Jul 28, 2026
427cf52
eval(cm-b.0f): P was the binding constraint — P=384 gives 6/12 vs 1-2…
star2vec Jul 28, 2026
b70be08
feat(cm-b): de-leak the extension fixtures; add training-free KV-sele…
star2vec Jul 28, 2026
91ac5f1
eval(cm-b.0g/0h): distillation degrades its own warm start; raw cache…
star2vec Jul 29, 2026
87877ac
eval(cm-b.0i): the compression curve — 7.9x free equals 98 minutes of…
star2vec Jul 29, 2026
5f2fd84
test(cm-b): position-stratified fixtures — the earlier curve was a he…
star2vec Jul 29, 2026
46c1456
eval(cm-b.0i): truncation does not compress; uncompressed ceiling is …
star2vec Jul 29, 2026
eb29824
eval(cm-b.0j): text-in-prompt control confirms the 50% ceiling is real
star2vec Jul 30, 2026
6c9c013
feat(cm-b.0k): query-aware KV selection + chunked cache building
star2vec Jul 30, 2026
7a4e0a8
feat(cm-b.0k): kv_attn runner + reusable scoring
star2vec Jul 30, 2026
b751335
eval(cm-b.0k): query-aware selection beats positional 5/26 vs 1/26
star2vec Jul 30, 2026
a6531f8
eval(cm-b.0k): correct the verdict — p=0.219, not significant
star2vec Jul 30, 2026
9c45850
feat(cm-b.0l): --selectors flag so a P sweep stays affordable
star2vec Jul 30, 2026
71d1ab4
fix(cm-b.0l): per-arm heartbeat so slow != wedged
star2vec Jul 30, 2026
a69f1c1
fix(cm-b.0l): persist results after every fixture
star2vec Jul 30, 2026
46cc9f1
eval(cm-b.0l): no knee — query-aware selection is not a mechanism
star2vec Jul 30, 2026
c28a118
docs(cm-b): close the compression track, name the one remaining gate
star2vec Jul 30, 2026
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
1 change: 0 additions & 1 deletion .claude/worktrees/gallant-bardeen
Submodule gallant-bardeen deleted from 2c4882
1 change: 0 additions & 1 deletion .claude/worktrees/keen-curran
Submodule keen-curran deleted from 2c4882
25 changes: 20 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.libucks/
.libucks/
__pycache__/
*.py[cod]
*.egg-info/
Expand All @@ -9,7 +9,22 @@ venv/
.pytest_cache/
.ruff_cache/
*.so
.venv/
.libucks/
__pycache__/
*.egg-info/
.DS_Store

# Local secrets — never commit
.env
.env.local

# Local training/eval run logs (transient; results snapshot to tests/eval/results/)
cm_*.log
.claude/scheduled_tasks.lock

# Vendored dep removed in the CM-B cleanup (installed from PyPI or local wheel instead)
mps_bitsandbytes-0.7.0/
mps_bitsandbytes-0.7.0.tar.gz

# Stale Claude worktree checkouts (were committed as orphaned gitlinks; safe to rm -rf)
.claude/worktrees/

# Local run logs (kept out of git; cm_*.log already covered above)
logs/
11 changes: 11 additions & 0 deletions .mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"mcpServers": {
"libucks": {
"command": "/Users/ecaterina/Developer/libucks/.venv/bin/libucks",
"args": ["serve"],
"env": {
"HF_HUB_OFFLINE": "1"
}
}
}
}
63 changes: 56 additions & 7 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ signed with RS256. Expiry is enforced at 15 minutes for access tokens and

**Design constraint:** The Watchdog performs zero AI inference. It is a pure data-extraction process. This keeps it fast, always-on, and independently restartable.

**Deployment note:** `libucks serve` does NOT start WatchdogService by default. The primary update path is git-hook–driven: `git post-commit` → Unix socket → `StartupRecovery.run()`. Use `libucks install-hooks` to wire a target repo. WatchdogService is available as an opt-in for repos that do not use git hooks (e.g. non-git directories), but must be started explicitly.

---

### 3.3 Central Agent (Router / Dispatcher)
Expand Down Expand Up @@ -485,11 +487,11 @@ repo_cache = "~/.libucks/repos"

```
libucks/ ← this repository (the libucks tool itself)
├── main.py ← CLI entry point (click group)
├── libucks/_cli.py ← CLI entry point (click group, via [project.scripts])
├── pyproject.toml
├── tools_v1.json ← versioned MCP tool schema manifest
├── ARCHITECTURE.md
├── IMPLEMENTATION_PLAN.md
├── docs/cartridges-plan.md ← active roadmap (superseded plans in docs/archive/)
├── libucks/
│ ├── config.py
Expand Down Expand Up @@ -648,13 +650,60 @@ divides the loss by 8 before each `backward()` call and only advances the
optimizer after every 8th bucket (or at end of epoch). Effective batch size = 8
without requiring padded batching, keeping peak MPS memory bounded.

#### Query dropout (Phase 12.8 fix)

**Problem discovered:** With tight teacher-generated Q&A pairs, L_sep collapsed to 0.0000
throughout all training epochs. The model learned to reconstruct answers directly from
query tokens — the latent prefix carried zero additional information and gradient never
flowed through it.

**Root cause:** `L_task` can be minimised without ever attending to the latent when
`[query_prefix → target_text]` is a memorisable mapping. The model correctly ignores
the latent because doing so is sufficient.

**Fix:** Query dropout (`query_dropout_rate = 0.5`). Each training step independently
samples whether to include the query prefix:

```python
use_query = (random.random() >= 0.5)
# prefix = [bop, latent_K, eop, query (or empty), target]
```

On dropout steps the model sees only `[bop, latent_K, eop, "Answer:\n", target]`.
Without query tokens, the only source of signal for reconstructing `target_text` is
the latent. This forces L_sep > 0 and gradient to flow through the latent channel.
Non-dropout steps retain query conditioning so the model also learns the combined path
used at inference time.

**Hard-negative selection:** The wrong-path bucket is now the centroid-nearest neighbour
(highest cosine similarity) rather than the first non-matching bucket. A hard negative
with semantically close content makes L_sep harder to satisfy, producing a stronger
discrimination gradient.

**Updated λ_sep:** Raised from 0.1 → 0.3 so the separation term can compete with a
near-zero task loss once L_task converges.

**L_sep computed at position [:1] only (Phase 12.9):** Applying `separation_loss` over
all T=64 target positions dilutes the genuine signal by 64×. Positions 1..T-1 attend to
teacher-forced target tokens that are *identical* in both correct and wrong paths, making
their logit distributions nearly identical. Only position 0 (predicting the first target
token from the prefix alone) is genuinely latent-conditioned. Fix: `logits_tgt[:1]` in
`LoRAReceiverTrainer._forward_and_losses`.

**Wrong-path always r=0 (Phase 12.9):** The wrong soft-prompt uses `CurriculumMixer.mix`
with `r=0.0` (pure latents), while the correct path uses the sampled `r ∈ [0,1]`. This
ensures all K latent positions differ between correct and wrong paths, maximising the
discriminative signal at position 0 regardless of the correct path's mixing rate.

#### Recommended hyperparameters

| Param | Phase 12.6 (broken) | Phase 12.7 (fixed) | Rationale |
|---|---|---|---|
| `lora_r` | 32 | 4 | r=32 overfits 47 samples; r=4 sufficient (Hu et al. 2022 Table 2) |
| `lora_alpha` | 64 | 8 | Preserves scaling ratio alpha/r = 2 |
| `lr` | 1e-3 | 2e-4 | Standard LoRA fine-tuning range (1e-4 – 3e-4) |
| Param | Phase 12.6 (broken) | Phase 12.7 (fixed) | Phase 12.8 (fixed) | Rationale |
|---|---|---|---|---|
| `lora_r` | 32 | 4 | 4 | r=32 overfits 47 samples |
| `lora_alpha` | 64 | 8 | 4.0 | alpha/r = 1 (conservative) |
| `lr` | 1e-3 | 2e-4 | 2e-4 | Standard LoRA range |
| `query_dropout` | — | — | 0.5 | Forces latent conditioning |
| `λ_sep` | 0.1 | 0.1 | 0.3 | Competes with low L_task |

### Implementation Files

Expand Down
14 changes: 11 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,21 @@ You are the Principal Systems Architect and Lead Python Engineer building the `l
## 1. Project Blueprints (MANDATORY ROUTING)
Before executing complex code changes, you MUST consult the blueprints:
- `ARCHITECTURE.md`: Contains the system design, data flows, and the critical V2 Latent Space constraints.
- `IMPLEMENTATION_PLAN.md`: Contains our strict, phase-gated roadmap.
- `docs/cartridges-plan.md`: The current active roadmap (Cartridge Memory track). Superseded V1/V2/Phase-4 plans are archived under `docs/archive/` (including the closed Phase 4-C negative-result log at `docs/archive/phase-4c/`).

## 2. The Golden Rules
- **Strict TDD:** You are never allowed to move to Phase N+1 until the Testing Gate for Phase N is 100% green. Always write the `test_*.py` file first, run it to watch it fail, then write the implementation to make it pass.
- **Latent Space Constraint:** Librarians only produce `Representation` objects. ONLY the `Translator` is allowed to call `decode()` and output natural language.
- **No Automatic Mitosis:** V1 uses manual mitosis only. Do not build k-means clustering.
- **Auto-mitosis and auto-merge are on.** `HealthMonitor` runs every 5 min (started by `libucks serve` at `mcp_bridge.py:257`). It calls `MitosisService.split()` (k-means k=2 in `mitosis.py`) on buckets that exceed `mitosis_threshold` tokens or fall below the coherence threshold, and `MergingService.run_merge_pass()` for cosine-similar pairs. This was originally scoped as "manual only" in V1; that constraint was relaxed when HealthMonitor landed (Phase 6-E/F).
- **Auto-bucket-creation is on.** `NovelBucketService` (started by `libucks serve` alongside `HealthMonitor`) drains `CentralAgent.create_bucket_queue` to spawn new buckets when commits land substantial + cosine-novel content. Gates: `min_bucket_seed_tokens` (default 1500) AND `is_novel(embedding)`. Small or similar diffs are routed into the nearest existing bucket — coherence-driven mitosis splits later if pressure builds. Buckets are subject-specific knowledge units; single-file/single-chunk spawning is forbidden.
- **API First:** V1 uses standard API calls (OpenAI/Anthropic), not a local Ollama daemon.
- **LoRA training MUST use query dropout:** `query_dropout_rate=0.5` in `_train_lora_receiver`. Without it, L_sep collapses to 0.0000 and the model ignores the latent entirely. See ARCHITECTURE.md §10 Phase 12.8.
- **Update pipeline is git-hook driven:** `libucks serve` does NOT start WatchdogService. Updates arrive via git post-commit hooks → Unix socket → `StartupRecovery`. For each changed file: if an existing bucket owns it → `UpdateEvent` directly. If no bucket owns it → `StartupRecovery._handle_unmatched_file` does the size+novelty check above and either enqueues a `CreateBucketEvent` or routes to the nearest existing bucket. Use `libucks install-hooks` to wire a target repo.
- **Check sep in training logs:** If `sep=0.0000` persists past epoch 3 in any training run, STOP. The latent is being ignored. Do not continue training — investigate the query dropout code path first.

## 3. Session Start Protocol
When a new session begins, scan the current files in `tests/unit/` to determine exactly which Phase and Step we are currently on in the `IMPLEMENTATION_PLAN.md` before taking action.
When a new session begins:
1. Read `docs/cartridges-log.md` (newest entry) to find the current stage/gate status, and `docs/cartridges-plan.md` for the active roadmap.
2. Scan `tests/unit/` to confirm which tests exist and which are green.
3. Check if `lora_receiver.pt` exists in the target repo's `.libucks/` before assuming LoRA is trained.
4. Never assume training was successful — always verify `sep > 0.0000` in logs.
Loading