Operator decision 2026-08-09: the two implementations are developed in the open
against each other. Reading the sibling is permitted and exchange may go both ways;
code is copied only where it genuinely serves the solution, never as a shortcut. The
constraint that remains is what the Microsoft Agent Framework and the Claude Agent
SDK each actually offer — which is the difference the comparison exists to measure.
The old rule lived in three places and two of them would have started lying:
- CLAUDE.md carried the prohibition, and it is read at every session start — left
alone it would have made the next session refuse exactly what was authorised.
- README stated in the present tense that this repo is "built from the shared spec
alone" and "deliberately does not reverse-engineer the MAF sibling". True for
every line written so far, and untrue for anything written from today.
So the README claim is DATED rather than deleted. Through 2026-08-09 the
independence is real and stays claimed; from 2026-08-09 the open-competition rule
applies and is stated plainly, with the consequence spelled out: anything comparing
the two implementations as INDEPENDENT evidence must be scoped to work on or before
that date. The honesty rule (method spec §1) does not let a claim outrun what was
actually done, and that applies to the README's claim about itself.
CHANGELOG is deliberately UNTOUCHED. It describes what was true at that release, and
it was true — 73 commits through 3e91072 were built from the spec alone. A changelog
records history; it is not rewritten because a forward rule changed.
What did NOT change, and is restated in the README so the dating cannot be misread as
a loosening of the method: the spec is still normative and the golden suite is still
the validator's only oracle.
787 tests green, ruff clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JYWMfPKmJtv7JvYnpomkdV
4.6 KiB
portfolio-optimiser-claude
Kontekst
Søsken-implementasjon (beslutning D7) av portfolio-optimiser-metoden på Claude Agent SDK:
generisk, åpent Python-rammeverk som finner kostnadsbesparelser INNI hvert prosjekt i en
portefølje. Bygges på metode-spec-en (shared/method-spec.md) som normativ kilde.
Åpen konkurranse med MAF-søskenet (~/repos/portfolio-optimiser, operatørbeslutning
2026-08-09): alle tilgjengelige midler er lov for å nå den beste løsningen, inkludert å lese
søskenets kode, og utvekslingen kan gå begge veier. Grensen er hensikten, ikke kilden:
kopiér kun der det faktisk gir mening for løsningen — aldri som snarvei. De reelle
begrensningene er hva MAF og Claude Agent SDK hver for seg tilbyr, og det er nettopp den
forskjellen sammenligningen skal måle. Fram til 2026-08-09 ble repoet bygget fra speccen
alene; det er datert i README og skal ikke påstås om arbeid etter den datoen. Program-planer
(sesjonsplan S5–S12, sammenligningsprotokoll, frossent målbilde) bor i hovedrepoets
docs/plan/. Løpende state: STATE.md (local-only).
Stack
Python ≥3.10. Claude Agent SDK (claude-agent-sdk ≥0.2, verifisert 0.2.110 per
2026-07-03: MIT-lisens, bundler Claude Code CLI — ingen separat installasjon; import og
konstruksjon fungerer uten API-nøkkel, nøkkel trengs kun ved faktisk query()).
Pakkehåndtering: uv. Pydantic for kontrakts-validering.
Konvensjoner
- Type hints overalt;
mypy --strict.rufffor lint+format.pytestfor test. - Testsuiten kjører uten API-nøkkel og uten nettverk (invariant fra S5; håndhevet ved at all kontrakts-/kontekst-logikk er ren config/fil-lag).
- Modell-valg som konfig:
src/portfolio_optimiser_claude/data/model_map.json(rolle→Claude-modell-id per backend-profil, hver profil kreverdefault; validert avcontracts.py). Modell-id-er verifiseres mot offisiell doc før endring. - SDK-primitiver (verifisert 2026-07-03):
query()/ClaudeSDKClient,ClaudeAgentOptions(max_turns,max_budget_usd— førsteklasses USD-tak),AgentDefinition(subagenter; sub-felt er camelCase),@tool+create_sdk_mcp_server(in-process MCP), hooks (PreToolUsemedpermissionDecision: "deny"for deterministisk gating). MERK:SessionStart/SessionEndfinnes IKKE som Python-callback-hooks. shared/er en git subtree avportfolio-optimiser-commons(source of truth; remotecommons). 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 i MAF-repoet 2026-07-03). Seshared/README.md.
Kommandoer
- Sync:
uv sync - 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 — kun tekniske forutsetninger (lokal-only, provenance, ingen stille egress) + disclaimer.
- Metode-spec-en er normativ (RFC 2119). Ærlighets-regelen (§1) er ufravikelig: ingen artefakt påstår mer enn implementasjonen gjør; skriptede stand-ins merkes som det.
- Deterministisk validator obligatorisk + blokkerende (§3 steg 4); golden-suiten
(
shared/examples/bygg-energi-mikro/golden.json) er ENESTE fasit (§7). - Load-bearing tester (§11): hver søm bevises med en test som blir RØD når sømmen detaches — grønn-men-død er feilmoden regelen finnes for.
- Stoppkriterier + budsjett-tak påkrevd ved oppstart (§8;
contracts.pyfail-fast). På kjørestien kommer USD-taket i tillegg viaClaudeAgentOptions.max_budget_usd. - Kostnadsdisiplin (D6): alt utvikles offline/deterministisk; den ENE ekte API-kjøringen i programmet er S10 (mikro-bundle, billigste egnede modell — per model_map Haiku 4.5 — harde tak, kost loggføres).
- STATE.md er local-only (gitignored — repoet skal publiseres; STATE når aldri et offentlig speil).
Communication patterns
Linking to local files
When pointing to local files in responses, always use markdown link syntax with a descriptive name:
- Use
[Human-friendly name](file:///absolute/path)— never barefile:///...URLs or autolinks<file://...>. - Always use absolute paths. Never
~/or relative paths. - For multiple files, render as a bullet list of named markdown links.
Why: bare file:// URLs only render the first as clickable across multiple lines. Named markdown links make each entry independently clickable and look cleaner.