Auto-loaded at session start. Points at the durable contracts and the short list of project-specific gotchas.
luxe pins exactly one MoE model: Qwen3.6-35B-A3B-6bit (configured
in configs/single_64gb.yaml). The M5 Max m5max_moe bake-off (2026-05-10)
confirmed it across all eligible MoE candidates: 10/10 perfect, fastest
wall (40.0s avg), highest TPS (72.7), no bailouts. Larger MoE
candidates (Qwen3-Coder-Next-80B, GLM-4.5-Air-106B) also passed but
offered no win on speed/efficiency.
All ongoing development is centered on this single champion. Practical implications:
- Do not introduce model-fan-out: no per-task model selection, no router, no A/B against another model unless the user explicitly asks for a re-bench. The bake-off is settled.
- Tuning and substrate fixes target this model's failure modes.
When proposing changes (prompts, gates, tool surface), evaluate them
against
Qwen3.6-35B-A3B-6bitfirst; other-model evidence is secondary unless the user specifies a wider sweep. - The champion is platform-stable: it ran on M1 Max (64 GB) and is the M5 Max winner. There is no platform-specific MoE champion split to maintain.
- Don't keep alternate model configs warm: configs in
configs/_archive/are reference-only. Don't promote them.
If a re-bench is ever needed, follow ~/Downloads/luxe/RESUME.md §
"M5 Max MoE bake-off" structure and produce results under
acceptance/m5max_moe_<rebench-id>/.
Sanctioned exceptions — luxe chat slots + per-host manifests. The
interactive front-end (src/luxe/chat/) has two sanctioned carve-outs from
single-champion, both scoped to luxe chat/luxe code and never the
benchmark/maintain path (luxe.sdd):
(a) opt-in chat/plan/code model slots via configs/chat.yaml slots:;
(b) per-host manifests (hosts: in chat.yaml, 2026-07-30 fallback-kit
pivot): each fleet host declares an interactive main + fallback pair sized to
its RAM — m5 (128 GB) = champion + 27B-6bit; m1 (64 GB) and m4 (48 GB) =
35B-A3B-4bit main + 27B-4bit fallback (MoE-first, flipped 2026-07-30: Qwen3.6
is multimodal so oMLX runs it on the slow vlm engine — dense-27B prefills at
~65 tok/s with no cache reuse; the MoE holds ~10s turns). The interactive
default on m1/m4 is deliberately NOT the champion — do not "restore" it. The champion pin is a benchmark pin:
single_64gb.yaml still selects it and m1 keeps its weights via the
manifest's keep: list. A host with no hosts: entry behaves exactly as
before (champion everywhere). (c) The m5-only capacity model
(2026-08-03/04): GLM-4.5-Air-4bit (106B-A12B, bake-off-passing) lives in
m5's keep: + visible_models for capacity-over-speed sessions — opt-in
per session via /model all GLM-4.5-Air-4bit, never a slot default, never
a manifest main/fallback, never on m1/m4 (60 GB doesn't fit), never the
bench champion. Overnight drill verdict 9/9 at ~2× wall:
acceptance/glm_capacity_drills/REPORT.md (local),
scripts/capacity_drills.py to re-run. Do not extend fan-out beyond these.
Luxe's mission narrowed after the 2026-07-29 Anthropic outage: it is the local fallback dev tool for the fleet (m1 · m4 · m5), and it has to WORK when reached for — availability over capability. Concretely:
- Two entry points, one engine:
luxe chat(anywhere, read-only, conversation) andluxe code(REQUIRES a project, write tools ON from turn one, bash still gated). Wrappersluxe-chat/luxe-codelive in~/dotfiles/bin. Shared bodycli._run_interactive. - Per-host main+fallback manifests (
hosts:in configs/chat.yaml) with loud auto-degrade: main missing from the catalog / failing to load / failing a turn on a healthy endpoint → the session switches to the declared fallback and says so (status line,/doctor, debug.log). See chat.sdd. - Manifest models are locally cached, verified, and protected:
luxe pullprovisions (kappa mount preferred, HF via oMLX admin API),/doctor+luxe pull --listdetect DANGLING store symlinks (the HF-cache-wipe signature — a listed model the server can't load),luxe pull <name> --removedeletes but refuses manifest models sans --force. luxe ready(aliasluxe doctor) is the point-in-time host preflight (seconds, no model):/doctor's checks against a stand-in session, printed through the SHARED rendererchat.inspection.render_doctor, then a verdict — exit 0 on ok/warn, 1 on any FAIL, 2 on a bad--backend. Offline-safe (doctor's one ≤4supdatefetch degrades quietly). EveryCheck.fixis a runnable command.luxe outage//outageprintOUTAGE.md, the ≤120-line offline emergency card (one reader,luxe.outage.load_card; a test asserts everyluxe <sub>it names is a registered command, so it can't rot). There is deliberately no scheduled/cron/launchd/alerting counterpart — user decision; don't add one.luxe smokeis the aliveness drill (minutes): manifest → weights → endpoint → catalog → one real turn + tool call on main → one turn on fallback. Run it after provisioning and on a schedule; exit 0 = ready.luxe smoke --chat --coderuns the agentic drills: real run_single turns in a planted scratch repo (--code = fix a bug + failing test, verified by pytest + git diff; --chat = read-only file-grounded answer).--backend m5drills a remote host's manifest models from here. Headless diagnostics: pipe turns into the line REPL (printf 'msg\n/quit\n' | luxe chat --repo <dir>); post-hoc forensics in~/.luxe/sessions/<id>/(debug.log, transcript) +~/.luxe/runs/. See README § "Self-testing luxe". Chat bash runs with luxe's venv bin prepended to PATH (tools/shell.py_chat_bash_env) so agent test runs (pytest) work on every host — bench bash env untouched.- Every session writes
~/.luxe/sessions/<id>/debug.log(always-on; chat/debuglog.py) and failed turns persist kind="error" transcript records — post-outage diagnosis must not depend on what the TUI happened to show. luxe update(wrapperluxe-update) is the one-word host update: fetch → show incoming → rebase onto origin/main →uv sync --extra chat --extra dev --extra analyzers --extra web(the canonical host sync); no-op when current./doctor'supdatecheck is the only networked doctor line (≤4s fetch; offline = quiet OK, never a warning — doctor runs during outages). Startup banners stay offline-pure (local refs only).- gemma is out of the roster (no tool support); the bench apparatus is cold storage — capability re-benching only on explicit request.
luxe is the living center of the fleet's model/agent work; the sibling repos are satellites and their m5 clones go stale (that bit twice — see micro-mind's lessons.md 2026-08-03 "stale clone" entry). Current reality, recorded here so a luxe session doesn't have to rediscover it:
- neo (A18 Pro, 8 GB) runs micro-mind, whose champion since the
2026-08-03 neo bake-offs is
Qwen3-4B-Instruct-2507-Q4_K_M(GGUF via llama-server, ctx 16384, single-model — no fallback pair). It replacedqwen25-1.5b-instruct: the 1.5B's 0% BFCL multi-turn floor is a size artifact (lifts at 3B, closes at 4B), and the 4B is the smallest model that passes luxe's real code drill on that box. Coder variants lost to instruct at every size; 14B is Metal-unrunnable on 8 GB. - neo-llm-bench is marked superseded for deployment — canonical historical record for the sub-2B era; its methodology stays reusable.
- neo has no
hosts:entry in chat.yaml by design (no local oMLX); bareluxe smokefailing there is pinned in chat.sdd. neo's smoke is the agentic drill against m5. - When a question touches micro-mind/neo state, trust the checkouts on
neo (
ssh neo,~/Downloads/{micro-mind,neo-llm-bench}) or a freshly fetched origin/main — never an unfetched m5 clone.
Added 2026-06-01 (additive; benchmark path byte-identical). See RESUME.md
2026-06-01 handoff + memory project_luxe_chat_interactive_overhaul.md.
luxe chat— REPL. Each turn = onerun_singlecall; conversation + project memory inject ONLY via the newrun_single(extra_context="")seam (default""= byte-identical). Read-only tools by default (/writetoggles).- Chat is a CONVERSATION by default (2026-07-29 fix). Every freeform
turn gets the
chat_conversationalpersona (registry variant; task overlay cleared); the baseline maintenance persona applies only to/plandrafting,/goalrounds, and/use <slot>-pinned turns. Do NOT re-key the persona on the routed slot — slot routing comes from the_infer_task_typekeyword heuristic and misclassifies ordinary messages ("explain…", "add…", "fix…") as coding tasks; that was the "chats become coding sessions" bug. Slots still pick the MODEL only. - Multi-backend (chat-only carve-out, luxe.sdd):
configs/chat.yamlbackends:maps names → BackendEntry(base_url, api_key_env, timeout_s, stall_timeout_s, decode_stall_timeout_s, default)./backendlists (health ✓/✗, active),/backend <name|n>switches (health-checked; drops unresolvable/modeloverrides; never unloads the OLD server),--backend <name>picks at startup. Keys come from env vars only (m5 → OMLX_API_KEY_M5) — never YAML. Absent block ⇒ a synthesized "local" entry fromomlx_base_url; benchmark/maintain readomlx_base_urlonly. m5 entry carriestimeout_s: 2400(dense turns over Tailscale) — the old hardcoded Backend timeout hack is retired — plusstall_timeout_s: 2400(see "Progress deadlines" below). SessionMeta records backend_name/base_url; assistant transcript records are stamped"backend". - Progress deadlines — a request that stalls must not hang (B6, 2026-07-31).
httpx.Timeoutis a PER-READ deadline and oMLX emits keepalives on both response paths ("model":"keepalive"SSE chunks when streaming; a bareb' 'every ~10s under chunked encoding when not), so every keepalive resets it and no finitetimeout_scan bound a request whose generation has stopped — one hung 23 min against a 600s timeout with no error and no log line.Backendtherefore keeps a SECOND clock on progress (content delta / tool-call fragment / usage / finish_reason; keepalives never count):stall_timeout_s(1800s) before the first token, where a long prefill is legitimate, anddecode_stall_timeout_s(120s) once tokens flow, where a gap is unambiguous. A stall raiseshttpx.ReadTimeoutso the retry classifier treats it as transient. Overridable per endpoint viaBackendEntry; unset = inherit Backend's default (the numbers live inbackend.pyalone). Raisingtimeout_sis not a fix — it only moves the symptom. This one is NOT chat-only: the non-stream path is the benchmark/maintain path, which could previously wedge on one fixture forever. /attach <path> [...]stages file contents ONE-SHOT for the next turn: 48KB/file + 128KB/turn caps, binary refused (null-byte sniff), injected as<attached_files>just below<system_constraints>, cleared on consumption; kind="attachment" transcript records.- TUI paste + resume: multi-line pastes become a
[pasted N lines]chip expanded at submit (stock Textual Input kept only the first line);--resume//resumenow work inside the Textual TUI (transcript replays into the RichLog on mount). The[chat]extra installs viauv sync --extra chat— without it chat falls back to the line REPL. - Model roster + tool capability (2026-07-30).
configs/chat.yamlvisible_models:is the working set/modeloffers (5 ids on m1/m5); everything else the server holds is hidden. Local weights carry NO glyph now — only ☁ network / ⇅ remote.chat/modelcaps.pydetects tool support from the chat template: gemma-3 has none (system/user/assistant only + an alternation guard) and oMLX silently drops thetoolsarray for it, so luxe withholds the whole tool surface and tells the model not to fake it. Gemma is therefore selectable (/model chat gemma-3-27b-it-4bit) but NOT the default — a default has to be able to read a file. - Start a session anywhere (2026-07-30;
chat/project.py). The subject resolves to git (walks UP to the git root — a subdir session gets the whole repo), dir (pyproject.toml/package.json/… marker), or none.$HOMEand anything above it never count as the project.--reporesolves upward too (theluxe-chatwrapper always passes--repo "$PWD"). No-project mode: no index, no repo lock, read tools still work,bm25_search/find_symbolwithheld from the tool list, prompt carriesNO_PROJECT_CHAT_HINT, status bar showsno project./project [path]attaches or switches mid-session (moves the repo lock, acquiring the new one first);/index [path]builds the index where you are. Startup from$HOMEis now 0.5s. - Startup indexing is bounded and single-pass (2026-07-30). It used to
walk the tree THREE times (BM25, symbols, language detection) with no cap:
luxe chat --repo ~cost 210s of indexing + ~18s of language walking. Nowcli._build_chat_indexesrunsfswalk.scan_source_filesonce — gitls-fileswhen the root is a repo, else a breadth-first walk that prunesHOME_NOISE_DIRS(Library, …) at depth 1 — and feeds the list to both builders plus_languages_from_paths. Caps:LUXE_INDEX_MAX_FILES(8000),LUXE_INDEX_MAX_MB(96),LUXE_INDEX_NO_GIT=1to force the walk. Measured after: ~1s in a repo, ~16s from$HOME. Truncation prints what the model can't see + how to lift it. Benchmark/maintain keep the unbounded walk (builders called withoutfiles=). /pull— get model weights (2026-07-29;src/luxe/modelstore.py, CLIluxe pull). Mounted volume first (kappa/alpha over SMB — same bytes at LAN speed), else HuggingFace through oMLX's own downloader (/admin/api/hf/*; cookie session via/admin/api/login, Bearer alone is rejected). Never write a secondsnapshot_download— it would race the server over the HF cache. Mount imports resolve symlinks AND SynologyXSymstubs (1067-byte regular files on SMB — a naive copy imports stubs instead of weights); dangling links abort the copy. Copies stage in.<name>.partialand rename, so an interrupt never leaves a half-model. In chat,/pull <ref>previews and/pull <ref> --yestransfers.- Session commands added in the 2026-07-29/30
/helpaudit:/theme(live palette switch),/tools(real tool surface + what read-only gates),/status(session dump incl. model origin),/unload(free RAM without quitting),/retry(re-run the last message viaCommandResult.submit), plus/export,/diff,/doctor— logic inchat/inspection.py, all read-only./diffdefaults to the files THIS session wrote (ledger), diffs against HEAD, reports untracked as new;/exportrenders the PERSISTED transcript (survives/resume) to<session dir>/transcript.md;/doctorpreflights endpoint/key/model/weights/disk/index/git/mode/TUI and prints the fix for every warning. - MCP tools attach at STARTUP via
--mcp <name>(chat-only, repeatable; servers from--mcp-config <path>, defaultconfigs/mcp.yaml). There is no way to attach a server mid-session — a plainluxe chathas no MCP surface no matter what the user tells the model. The mage-hands home-lab relays are wired this way through the private dotfiles repo (~/dotfiles/luxe/relays.yaml- the
luxe-alpha/luxe-kappa/luxe-router/luxe-allwrappers); no hostname or token belongs in THIS repo. Tools are namespacedmcp__<server>__<tool>; the server'sgate_toolspatterns follow the/writegate,--mcp-read-onlydrops them entirely. Servers are isolated per connection (2026-07-31): one task + oneAsyncExitStackeach, so a dead server can neither cancel a healthy one nor be reported "up" with no session. Don't reintroduce a shared exit stack, and catchBaseException(notException) at any anyio connect boundary — seelessons.md2026-07-31 and the chat.sdd MCP bullet.
- the
- Web tools are
/web-gated, default OFF (2026-07-31;src/luxe/web/, walkweb/web.sddfirst).web_fetch(bounded GET → stdlib HTML→markdown;render=true= headless Chromium via the optional[web]extra),web_search(Brave/Tavily key through luxe.secrets; withheld when no key resolves), andweb_answer(2026-08-03; Brave Answers — a SEPARATE product/subscription from search: one server-side grounded answer via the OpenAI-compatible /res/v1/chat/completions endpoint, keyed byBRAVE_ANSWERS_API_KEY, withheld independently). Gated independently of/write— reading a page mutates nothing locally. Chat-only via the extra-tool seam: never add these toTOOL_FNS, since a benchmark that can reach the live internet is no longer reproducible. The egress guard refuses non-public hosts on every redirect hop; noteipaddress.is_privateis NOT enough — the tailnet is 100.64.0.0/10 (RFC 6598) and reports as non-private, sois_globalcarries the check.LUXE_WEB_ALLOWLISTadds an optional fnmatch host allowlist on top (unset = any public host; set = deny-by-default for hosts).src/luxe/web/is the ONLY web/browser stack — it absorbedsrc/luxe/browser.py(browse_navigate/browse_read,[browser]extra) on 2026-08-03 after the two landed in parallel. Don't add a second stack, browser dependency, or gating model. - Read-only default ≠ missing capability. luxe has the full mutation
surface —
write_file(creates parent dirs + files, i.e. scaffolds trees),edit_file,bash— butmake_read_only_role(mcp/server.py) strips{write_file, edit_file, bash}until/writeflipssession.write_enabled. A chat agent in read-only mode will honestly report it has no file-creation tool; that's the gate, not a gap. The read-only<session_mode>hint now tells it to point the user at/write. Seelessons.md2026-06-01 + memoryfeedback_luxe_dev_platform_write_mode. - Context window is
/ctx <small|medium|large|xlarge>(chat-only), clamped to the role'snum_ctx_max(configs/chat.yaml;0= no expansion). NOT dynamic/auto — high pressure only suggests the next tier. Benchmark/maintain ignorenum_ctx_max. /bashtoggles unrestricted shell (chat-only dev mode; default OFF = hardened allowlist). When ON + write mode, the turn swaps inmake_bash_fn(unrestricted=True)viarun_single's extra-tool seam — any command, chains/pipes/redirects, cwd=repo root but NOT sandboxed. The defaultTOOL_FNS["bash"]and the benchmark path stay allowlisted (tools.sdd).- The REPL shows a randomized rainbow banner + per-render color-shifting prompt
arrows; the footer carries
tok/sand start/end timestamps + elapsed (chat/render.py). - Status bar (
chat/status.py): orderpath · git · ctx · cache · start · last · write · bash · web · slot · model(ctx N% <size>e.g. 128K;cache=resident prompt size — no cross-turn cache;write/bash/webon/off, all three always visible; slot+model last). The model name carries a PROVENANCE glyph (chat/origin.py, 2026-07-29):⌂weights on local disk ·☁network volume / cloud-sync tree ·⇅remote endpoint (warn-coloured for the last two; no glyph when unknown). Same fact is stated at startup, in/model's listing, and on a weight swap. One cached/v1/models/statusprobe per endpoint, resolved off the render path; failures degrade tounknown. Palette: path blue (fixed hex), slot purple, model yellow, state on=green/off=red, ctx/write/bash labels in default fg, grey else; git keeps the theme's role colours. Startup banner minimal (bar shows repo/slot/model/mode).fields()(→Segmentlist with drop-priority) is the single source;fit()is responsive (drop low-value first → middle-ellipsis path; git/ctx/model protected). Live during a turn viarich.Live+LiveActivitywhenis_terminal(tool log scrolls above a ticking bar); falls back to line streaming otherwise. Colours follow the user's ACTIVE Claude statusline theme, resolved LIVE bychat/theme.py(reads~/.claude/statusline-theme, imports the user's yet-another-statuslinethemesmodule via thestatusline_command.pysymlink, converts each role's ANSI escape → ptk/Rich; ANSI 0-15 stay named so they track the terminal profile, 16-255 fixed). Built-in llmtop fallback if the repo is absent. Theming reads only the name file — NOT the memory subsystem (the~/.claudeprohibition is scoped to context/memory).luxe chat --devstarts write+bash ON. Hidden exit aliases:/exit,/q(both =/quit). - Flag-state failures self-explain. Defaults are safe (read-only +
allowlisted bash) and shown in the banner + chips; in write mode a restricted
bash rejection front-loads "enable unrestricted dev mode with /bash" onto the
error (
make_bash_fn(restricted_hint=True)), so the model surfaces the toggle instead of retrying. Genuine errors aren't augmented. Chat-only — benchmark bash untouched.
- Chat is a CONVERSATION by default (2026-07-29 fix). Every freeform
turn gets the
luxe compare run/review— side-by-side single-task comparison (3 modes, incl. luxe-vs-bare substrate ablation), blind + vote.src/luxe/memory/—~/.luxe/sessions/transcripts + curated-first project memory (repo.luxe/memory.md); must NOT read~/.claude/or repoCLAUDE.md..luxe/memory.mdnow carries two MACHINE-MANAGED fenced blocks whose markers are load-bearing (2026-08-04):luxe:brief(written byluxe init//init— one read-only gitkit pass withGIT_BRIEF_HINT, orientation only, capped at 2,000 chars in Python) andluxe:notes(written bychat/notes.pyat session end and by/note— one non-agenticbackend.chatover the deterministic fold, 900 chars/entry, rolling window of 5 entries / 1,500 chars).memory.project.splice_blockis the ONLY writer: it re-reads, replaces just its own block, appends at EOF when absent, and preserves every other byte — user-curated text must survive, and tests prove it.facts.jsonlis never touched. Notes failure is a SILENT skip with no retry and must never block exit; writing this file from a read-only session is sanctioned (luxe's own state file, orchestrator-side Python, same precedent asstore.mirror_to_repo) — do not "fix" it as a gate bypass. Config:notes: true|falseinconfigs/chat.yaml(default true;/noteignores it).
backend.pystreaming is gated (stream/on_token). As of 2026-06-01 the loop wires it CHAT-ONLY:run_single/run_agenttake anon_tokenthat, when set (interactive chat live tail), makesbackend.chatstream. Benchmark/maintain passon_token=None→stream=False→ byte-identical request, deterministic path untouched. Do NOT passon_tokenfrom the benchmark/maintain path.- New work here walks
src/luxe/{chat,compare,memory}/<dir>.sddfirst.
Read-only repo analysis + an apply-ready change planner. Package src/luxe/gitkit/;
walk gitkit.sdd first. TWO commands (collapsed from the original four 2026-06-07;
old names gitsummary/gitreview/gitrefactor→gitaudit, gitplan→gitchange
are hidden back-compat aliases):
gitaudit— ONE read-only report: orientation + bugs/security + structural advice. Also/gitauditinluxe chat.--base <ref>/--pr <N>switch to a DIFF AUDIT (internal kindgitaudit-diff, "Diff audit" report: change-scoped, no survey, never writesmap/; tags arelikely-introducedvspre-existing (touched code)with the hunk-overlap prior + caveat rendered in Python — seediffscope.py).--min-severityfilters the DISPLAY only (saved report always complete; honesty line counts what was hidden).gitchange— apply-ready structuredgitplan/v1JSON plan (schema string staysgitplan/v1— do NOT rename) + the gatedgitchange --apply/luxe gitapplyexecutor (gitkit's SOLE sanctioned agent-write path, six invariants inapply.py/gitkit.sdd).
Both auto-route by repo footprint: small → SINGLE-PASS; large → the staged DEEP
map-reduce (deep.py: survey → per-chunk → synthesis, per-repo HEAD-keyed map/
cache). Deep re-runs are INCREMENTAL by default (2026-06-10): the v2 breadcrumb
carries blob shas + per-chunk notes cache under map/notes/<kind>/; only dirty
chunks re-run (sha-validated; synthesis always re-runs; loud logging;
--no-incremental / --rebuild-map escape hatches; anti-drift compaction
triggers force a full rebuild — contract in gitkit.sdd). Prompts are GIT_AUDIT_*/GIT_CHANGE_* + deep GIT_SURVEY/*_CHUNK/*_SYNTH/ DEEP_FORMAT/DEEP_REDUCE in agents/prompts.py (gitkit.sdd Forbids inline prompts).
Load-bearing design finding (validated by sweeps + a chunk-conclude A/B,
2026-06; memories project_deep_gitplan, project_gitaudit_conclude_experiment):
the champion will NOT self-package — on large chunks it rambles 55–71k chars and
never emits the report header. So separate detection from packaging: chunk
prompts request a concise MARKDOWN list (a JSON-only chunk contract makes it ramble
worse), and Python recovers/packages the findings deterministically
(deep._heuristic_findings matches the numbered-bold finding lines it emits;
_render_report assembles). Prevention prompts ("emit header first" / "stop
exploring") were REFUTED — do not try to prompt-discipline conclusion; improve the
deterministic recovery instead.
scripts/toolcall_taxonomy.py mines ~/.luxe/{runs,sessions} (read-only) for
tool-call failure classes: schema rejects, unknown-tool dispatches, duplicate
storms, silent text-fallback drops, empty responses, aborts, turn errors.
Evidence bar: ≥5 occurrences across ≥2 distinct sessions in the window.
uv run python scripts/toolcall_taxonomy.py --days 45 --context-days 400 \
--out acceptance/toolcall_taxonomy_2026_08/REPORT.mdThe 2026-08-04 run: no class cleared the bar, so no hardening shipped —
verdicts per candidate in
acceptance/toolcall_taxonomy_2026_08/C2-VERDICTS.md; the silent
text-fallback drop (the highest-expected-value candidate on paper) is
refuted at 0 occurrences in both windows. Run it under
uv run (it reads the live tool registry; plain python3 degrades to a
static snapshot and says so). See lessons.md 2026-08-04 for why the
hand-written tool list had to go.
Measurement gaps closed same day (user-approved follow-up, additive
telemetry only — see agents.sdd § "Tool-call telemetry events"): the
loop now emits tool_reject (reason=schema|unknown_tool, name + message)
and textfallback_drop (dropped names) into events.jsonl, and
backend._chat_stream logs the same retry decision= line as the
non-stream path so chat outage retry history reaches debug.log. None of
this touches messages, dispatch, or control flow — the loop's model-visible
behavior is unchanged, only the records got richer. The taxonomy script
prefers direct events and suppresses its legacy proxies so mixed corpora
(records straddling 2026-08-04) never double-count.
Every directory of consequence has a <dir>/<dir>.sdd contract listing
Must / Must not / Owns / Forbids. Walk the chain when editing:
src/luxe/luxe.sdd— root invariants (no swarm/micro/phased; temp=0; pinned work_dir; no MoE Instruct-2507; noorigin/<branch>reads)src/luxe/agents/agents.sdd— prompt registry is the single source of truthsrc/luxe/tools/tools.sdd— honesty guards + Forbids enforcement orderbenchmarks/maintain_suite/maintain_suite.sdd— bench rules (vacuous_test gates,--keep-loaded, sidecar regrade)
Read the relevant .sdd before editing any file under that subtree.
LUXE_TIERED_COMPACT defaults to ON as of 2026-05-28 (forge-hybrid cycle
closeout, commit 9be486c). All run_agent callers — SWE-bench,
maintain_suite, BFCL — get 3-phase context compaction at
phase_thresholds=(0.50, 0.85, 0.95). Validated at n=75 across 2 reps:
resolves equivalent to baseline within substrate noise band (±2.8); 42-56%
wall reduction; 2 protected wrong_target instances healed; zero new damages.
- Disable for ablation:
LUXE_TIERED_COMPACT=0. If a workload behaves unexpectedly, try this first. Compaction default-ON is the largest behavior change shipped in 2026-05. - Retune:
LUXE_TIERED_COMPACT_PHASE_THRESHOLDS="p1,p2,p3"orLUXE_TIERED_COMPACT_THRESHOLD=<f>(single-knob, sets all 3 phases). - See
src/luxe/agents/agents.sdd§ "forge-hybrid Phase 2 (A) compaction invariants" for the pinned tuning rationale + counter-discipline rules.
Five subsystems are gated by env vars and default to off. Each has
invariants in its .sdd you must read before enabling:
- Reflect / verify stage (
LUXE_REFLECT=1) — a separatebackend.chatcritique pass. Verify-only by default (non-perturbing). Seesrc/luxe/agents/agents.sdd§ "Reflection / verify stage invariants". - Adaptive policy (
LUXE_ADAPTIVE_POLICY=1) — convergence-score-based intervention-intensity modulation. Bias-not-lock: never gates dispatch. Slew-rate limited viaLUXE_ADAPTIVE_MAX_INTENSITY_DELTA_PER_STEP. Seeagents.sdd§ "Stage 3 / v1.11 adaptive-policy invariants". - Cohort priors (
LUXE_LOAD_PRIORS=1) — reads~/.luxe/cohort-history/<instance>.json. Log-only in v1.11 (does not influence intervention intensity); promotion deferred to v1.11.1+. - Respond terminal tool (
LUXE_RESPOND_TERMINAL=1) — exposes arespond(message=...)tool with 4 watchdog gates (early-respond, no-writes-late, passive-surrender, compaction-phantom). Forge-hybrid Phase 3 (B) infrastructure; champion does not adopt the lever at any tested promotion (n=14 smoke 2026-05-28: 0/14 adoption with or without prompt guidance). Default-OFF; refute documented inlessons.md. - Trajectory-shape early_bail suppression (
LUXE_EARLY_BAIL_TRAJECTORY_SHAPE=1) — selectively suppressesearly_bailwhen the model is in deep localized reading with stable convergence. Forge-hybrid Phase 4 (D) infrastructure; locked predicate fired 0/14 at n=14 smoke (too narrow for this champion at num_ctx=32768). Implicit dependency onLUXE_ADAPTIVE_POLICY=1forscore_logpopulation. Default-OFF.
If you toggle any of these on, walk the relevant .sdd section first —
unbiased flips can silently change benchmark behavior.
- Mono only. No swarm/micro/phased — they're retired. Don't add
feature flags to bring them back. The
Forbids:rules insrc/luxe/luxe.sddare tool-side enforced. - Prompts go through
src/luxe/agents/prompts.py. Never inline prompt strings insingle.pyorcli.py— variant cells un-couple from runtime and the bake-off becomes uninterpretable. - Bench-as-truth. Don't trust paper analysis. Run
python -m benchmarks.maintain_suite.run --variants <yaml>and inspect every PASS by hand via the local-branch ref. SeeRESUME.md §The bench-as-truth pattern. oMLXis onlocalhost:8000; the API key lives in the login Keychain (serviceOMLX_API_KEY) and~/.luxe/secrets.env— never in this repo.- Read
RESUME.mdfirst for current project state and active tasks. - Read
lessons.mdfor postmortems of every historical surprise. - Git: rebase, never merge.
origin/mainenforces linear history (no merge commits, no force-push — admin-bypass only). Integrate remote changes withgit fetch+ rebase; never create a merge commit. A committed PreToolUse hook (.claude/hooks/precommit-pull.sh, wired in.claude/settings.json) plus repo-localpull.rebase/rebase.autoStashauto-rebase before each commit. Seelessons.md2026-05-25 + memoryfeedback_git_linear_history. - Never
Path.rglob/globa user-chosen root. pathlib swallows onlyPermissionError, so an unreachable network dir (OSError(ETIMEDOUT)from a NAS mount or~/Library/CloudStorage) crashes the caller — that killed the chat TUI on 2026-07-29. Useluxe.fswalk.iter_files(os.walk-based, prunes vendor dirs, logs skips).luxe.sddMust-not.
Default to the established patterns:
- New tools land with regression tests in
tests/test_tools.py - New prompt variants land with tests in
tests/test_prompts.py - New fixtures land with a
requirements:block (SpecDD Lever 1 schema) - New
.sddfiles follow<dir>/<dir>.sddplacement - New maintain_suite fixtures that need write-time create-only restrictions
use
forbids_create: [glob, ...]in fixtures.yaml; the bench harness's_inject_forbids_create_sdd(run.py) writes a synthetic<repo>.sddat the cloned-repo root and adds it to.git/info/excludeso the contract doesn't pollute fixture diffs
When in doubt, look at how the most recent shipped feature did it and match the shape.