feat(cli): console entry points + the demo's stderr damping (P4 pkt. 5 og 2)
Two commands are now part of the install surface a fresh clone gets from `uv sync`: `portfolio-optimiser` (run:main) and `portfolio-optimiser-demo` (simulation:main). Deliberately two of five main()s — costsim/hitl/preflight stay module-invoked; every name here is a name the freeze has to carry. Pinned against the INSTALLED distribution's metadata, not the TOML: a [project.scripts] line that has never been synced is a claim, not a command. Measured: stdout is byte-identical across both invocation forms. stderr (P4 pkt. 2), the session's open decision, resolved by measurement rather than by preference. Damped: the round-cap notice only, via a filter on the emitting logger, keyed on the message and installed by main() — never at import, so a library consumer keeps its own logging config. NOT damped: the two ExperimentalWarnings. They fire while the package __init__ imports run -> agent_framework, always before simulation's own imports and under both invocation forms, so silencing them would mean filtering warnings inside the library package on every consumer's behalf; they are pinned in pkt. 3 instead. A console-script wrapper was rejected for a second reason: the two forms would then write different stderr, and a byte-fasit would pin the command rather than the program. stderr 6 -> 4 lines. A first implementation wrapped simulation's own agent_framework import in a scoped mute. Measurement showed it can never fire — the package __init__ has already imported agent_framework by then — so it was removed rather than left as a green-but-dead seam. Load-bearing MEASURED against the whole suite, five mutations all red + green control: remove [project.scripts] · typo the target · detach the main() call · make the filter drop everything · install the filter at import time. The typo mutation also felled a test: the resolve-assert re-checked the expected constant against itself, and now resolves what the distribution actually installs. 775 -> 785 passed / 4 skipped. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C2bxLcCRguxXzpM4priTMn
This commit is contained in:
parent
1522e2aaaa
commit
ab7f45aa95
6 changed files with 298 additions and 2 deletions
25
CLAUDE.md
25
CLAUDE.md
|
|
@ -17,7 +17,13 @@ Python ≥3.10. MAF (`agent-framework-core` 1.9.0). Pakkehåndtering: `uv`. To b
|
|||
- `shared/` er en **git subtree** av [`portfolio-optimiser-commons`](https://git.fromaitochitta.com/open/portfolio-optimiser-commons) (source of truth, R1 realisert 2026-07-03; publisert i `open/` 2026-08-04 — `commons`-remoten peker fortsatt på `ktg/` og virker uendret). Synk er **pull-only**: endringer committes i commons og hentes med `git subtree pull --prefix=shared commons main --squash`. ALDRI `git subtree push` fra konsument — re-split lekker hele konsument-historikken inn i commons (observert + opprydd 2026-07-03). Se `shared/README.md`.
|
||||
|
||||
## Kommandoer
|
||||
- Sync: `uv sync`
|
||||
- Sync: `uv sync` — installerer to konsoll-kommandoer: `portfolio-optimiser` (CLI, `run:main`) og
|
||||
`portfolio-optimiser-demo` (offline-beviset, `simulation:main`). `python -m`-formene virker
|
||||
uendret og er byte-identiske på stdout (målt). Bevisst KUN to av fem `main()` —
|
||||
`costsim`/`hitl`/`preflight` er operatørverktøy, ikke produktets inngang, og hvert navn her er et
|
||||
navn frysen må bære. Pinnet av `tests/test_console_entry_points.py` mot den INSTALLERTE
|
||||
distribusjonens metadata, ikke mot TOML-en: en `[project.scripts]`-linje som aldri er `uv 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`
|
||||
|
|
@ -322,6 +328,23 @@ Python ≥3.10. MAF (`agent-framework-core` 1.9.0). Pakkehåndtering: `uv`. To b
|
|||
et literal i stedet for det avledede. **Målingen felte TESTEN først** (samme klasse som 08-06):
|
||||
«ingen kostbaseline erklært» INNEHOLDER «kostbaseline erklært», og `ENERGI-TOTAL-EL` står allerede
|
||||
i Steg 2-linja — begge assertene overlevde detach-mutasjonen. De to grenene deler nå ingen ordlyd.
|
||||
- **Demoens stderr: rund-taket dempes, `ExperimentalWarning`-paret PINNES (P4 pkt. 2):** målt 08-09
|
||||
var stderr seks linjer. `quiet_expected_round_cap_notice()` dropper KUN
|
||||
«reached max_rounds=…; forcing completion» — en hendelse demoen selv provoserer (maker/checker
|
||||
kjører til taket) — via et filter på den EMITTERENDE loggeren (`ROUND_CAP_LOGGER`, lest ut av MAFs
|
||||
kilde). Logger-filtre gjelder kun loggeren posten ble logget GJENNOM; en forfars filtre konsulteres
|
||||
aldri. Filteret installeres i `main()`, ALDRI ved import — en bibliotek-modul skal ikke
|
||||
omkonfigurere loggingen til en konsument. **De to `ExperimentalWarning`-linjene dempes IKKE:** de
|
||||
fyrer mens `portfolio_optimiser/__init__.py` importerer `run` → `agent_framework`, altså alltid FØR
|
||||
`simulation` sin egen importblokk, under BEGGE kjøreformer — så å dempe dem ville krevd et
|
||||
warnings-filter inne i bibliotekpakken, dvs. at rammeverket bestemmer hva MAF får si til enhver
|
||||
konsument. En wrapper bak konsoll-kommandoen ble avvist av en andre grunn: da ville de to
|
||||
kjøreformene skrevet ULIK stderr, og en byte-fasit ville pinnet kommandoen i stedet for programmet.
|
||||
**Dempingen er smal ved konstruksjon** — nøklet på meldingen, ikke loggeren — nettopp så pkt. 3-pinnen
|
||||
fortsatt kan felles av en NY advarsel. Load-bearing MÅLT
|
||||
(`tests/test_demo_stderr_quiet_loadbearing.py`), fem mutasjoner røde + grønn kontroll: detach
|
||||
`main()`-kallet (subprosess-testen er ENESTE som fanger det — de tre filter-testene installerer
|
||||
filteret selv) · la filteret droppe alt · installer ved import · pluss de to entry-point-mutasjonene.
|
||||
- **Delt ekspert-persona som Agent Skill (§8, framework-nøytral):** ekspert-reviewer-personaen bor i
|
||||
`shared/skills/expert-reviewer/` (`SKILL.md` + `references/example-verdict.json`) og er den ENE
|
||||
delte artefakten begge stacker instansierer reviewer-en fra. `shared/` forblir REN DATA — MAF-siden
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue