CLAUDE.md had grown to 310 919 bytes against Claude Code's 150 000-character injection limit, so every row past the cut reached no session. The 93 measured rows move to docs/invarianter.md in their original order; CLAUDE.md keeps the eight short standing rules and a pointer, and says new rows are written there. Verified as a partition: every moved line appears in the original section in order, the eight kept rows likewise, and head/tail of CLAUDE.md are byte- identical apart from the visitor note. One code span is reworded and the ledger head says so: the funn 99 row cited MAF's DEFAULT_MAX_CONSECUTIVE_ERRORS_PER_ REQUEST with its value inside the span, which the doc-constant-sync gate reads as a citation of a constant in this package (fail-closed on an unknown name). The ledger is registered in _LIVE_DOCS, so that gate now also guards it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
5.9 KiB
portfolio-optimiser
Note for visitors — what this file is. This is the working agreement between the repository and the AI coding agent that builds it (the Claude Code convention), and it is written in Norwegian because that is the maintainer's working language. The repository's invariant ledger — each design decision, the measurement that forced it, and the test that turns red when the decision is undone — lives in
docs/invarianter.md.You need none of it to use the framework — start with the README. It is published anyway, because the reasoning behind a decision is worth more than the decision, and because a rule kept out of sight is a rule that drifts without anyone noticing.
Kontekst
Generisk, åpent Python-rammeverk på Microsoft Agent Framework (MAF) som finner kostnadsbesparelser INNI hvert prosjekt i en portefølje av uavhengige prosjekter. Multi-agent samarbeid genererer kandidat-tiltak; en obligatorisk deterministisk validator avgjør verdiene; fageksperter vurderer via HITL, og systemet lærer av dommene. Publiseres på Forgejo for alle som har MAF.
Bakgrunn og beslutninger: research (§15 implementeringsregister), plan. Løpende state: STATE.md (local-only).
Stack
Python ≥3.10. MAF (agent-framework-core 1.16.0, -orchestrations 1.1.1 — F15, 02.09). Pakkehåndtering: uv. To backend-profiler: Azure/Foundry (full) + lokal (fallback).
Konvensjoner
- Type hints overalt (
mypyder mulig). Pydantic for validering/IR. rufffor lint+format.pytestfor test.- Modell-valg som konfig (modell-map rolle→Foundry-deployment), ikke spredt i kode.
- Metode kodifiseres som Agent Skill (
agentskills.io:SKILL.md+scripts/+references/). - Datatilgang: in-process
FunctionTooler default-sømmen i kjørestien. MCP er wiret som opt-in i kjørestien (mcp_tools.py+--mcp-config, Trekk B 2026-08-05): konkrete eksterne servere blir verktøy agentene kan kalle UNDER debatten. Uten konfig gjøres null nettverkskall og verktøylista er uendret. Tre regler er load-bearing: allowlist er påkrevd (tom liste ville latt motparten bestemme hva agentene får kalle), hver server og hvert tillatte verktøy navngis i kunngjøringen før første kall (også uten--mandate— ingen udeklarert egress), og--live-dry-runåpner ingenting. Egen søm fraingest_mcp.py(kildedokumenter FØR kjøring, null-argument-tools) — samme protokoll, ulik jobb.build_mcp_server(datasource.py) er fortsatt kun demo. Data-source-konfig JSON-Schema-validert, fail-fast. shared/er en git subtree avportfolio-optimiser-commons(source of truth, R1 realisert 2026-07-03; publisert iopen/2026-08-04 —commons-remoten peker fortsatt på den private namespacen og virker uendret). Synk er pull-only: endringer committes i commons og hentes medgit subtree pull --prefix=shared commons main --squash. ALDRIgit subtree pushfra konsument — re-split lekker hele konsument-historikken inn i commons (observert + opprydd 2026-07-03). Seshared/README.md. Wheelen bærer treet som pakkede data siden Fase 4a — se invarianten under.
Kommandoer
- Sync:
uv sync— installerer to konsoll-kommandoer:portfolio-optimiser(CLI,run:main) ogportfolio-optimiser-demo(offline-beviset,simulation:main).python -m-formene virker uendret og er byte-identiske på stdout (målt). Bevisst KUN to av femmain()—costsim/hitl/preflighter operatørverktøy, ikke produktets inngang, og hvert navn her er et navn frysen må bære. Pinnet avtests/test_console_entry_points.pymot den INSTALLERTE distribusjonens metadata, ikke mot TOML-en: en[project.scripts]-linje som aldri eruv sync-et er en påstand, ikke en kommando. - Test:
uv run pytest - Lint:
uv run ruff check .+uv run ruff format . - Type:
uv run mypy src
Arbeidsflyt (invarianter)
- Rent teknisk rammeverk: deployer eier DPIA/ROS/behandlingsformål. Bygg IKKE compliance-funksjoner — kun tekniske forutsetninger (lokal-only, provenance, ingen stille egress) + disclaimer.
- 90%-prinsipp: bygg den generiske kjernen + tydelige extension points; jakt IKKE de siste 10 %.
- Deterministisk validator er obligatorisk og blokkerende — aldri valgfri plugin.
- Stoppkriterier + budsjett-tak påkrevd ved oppstart (fail-fast, aldri ubegrenset loop).
- Group Chat maker-checker som debatt-default (IKKE Magentic, som er eksperimentell).
- Kostnadsdisiplin: utvikle primært på lokal profil (gratis); Foundry/Azure (privat tenant finnes) kun til målrettet, minimal verifisering; billigste modeller + små syntetiske data + harde token-tak. Ingen tunge test-kjøringer.
- STATE.md er local-only (gitignored). Voyage session-state er efemert; STATE.md er kanonisk kontinuitet.
- Prosess: Voyage-plugin (
/trekbrief → /trekplan → /trekexecute → /trekreview) per større fase. - Invariant-hovedboken bor i
docs/invarianter.md(flyttet 18.09.2026, uendret): hver målte beslutning med sin load-bearing test. Nye rader skrives DER, aldri her — denne fila passerte 300 000 tegn mot Claude Codes 150 000-grense, og en regel bak kuttet når ingen. Les den raden som gjelder sømmen du rører (grep -n '^- \*\*<stikkord>' docs/invarianter.md) FØR du endrer den.
Communication patterns
When linking to local files in responses, use named markdown links — [Human-friendly name](file:///absolute/path), never bare file:// URLs or autolinks <file://...>, always absolute paths (never ~/ or relative), one bullet per file when there are several. (Bare file:// URLs render only the first as clickable across multiple lines; named links stay independently clickable.)