portfolio-optimiser/README.md
Kjell Tore Guttormsen 4ec778c855 feat(fase3): make the maker-checker checker actually gate the reasoning
Closes gap #3 (maalbilde §5): the GroupChat checker critiqued into the void —
output_from=[proposer] surfaced only the proposer, so an explicit checker
rejection was ignored and the deterministic validator was the sole gate. Two
falsifiers now act on the same candidate: the validator gates the NUMBERS
(blocking, unchanged), the checker gates the REASONING (maalbilde §2/§6).

- workflow.py: output_from=agents surfaces both participants; the checker
  instruction ends with a VERDICT: APPROVE / VERDICT: REJECT - <reason> line.
- run.py: _authored_texts() reads author_name through out.messages (MAF 1.9.0
  puts it there, not on the AgentResponse); _debate_text() now selects the
  PROPOSER-authored output (fixes a latent texts[-1] regression that would feed
  the checker's verdict to generation at even round counts); _checker_verdict()
  parses the gate decision. An explicit REJECT overrides an otherwise-validated
  outcome to a checker-sourced Rejection. Opt-in-reject (fail-open on a missing
  marker). RunResult gains checker_verdict; provenance.validator_decision is
  stamped from the validator outcome BEFORE the override, so it never conflates
  the two falsifiers (provenance honesty).

Load-bearing (maalbilde §7): tests/test_checker_gate_loadbearing.py is a PAIR —
an explicit checker REJECT on a VALIDATOR-VALID proposal yields a Rejection whose
reason carries the checker's reason while validator_decision stays "validated";
the causality control (checker APPROVE, same proposer) validates normally. Proven
RED on BOTH detach points (revert output_from, or drop the override).

Suite 134->136 passed, 4 skipped; mypy + ruff check clean. Pre-existing
ruff-format drift (backends/budget/verdicts/test_contracts) left untouched for a
surgical diff.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MHR8iKxJRxDiDfNw8HZmWE
2026-06-30 07:24:30 +02:00

41 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# portfolio-optimiser
Generic, open framework on **Microsoft Agent Framework (MAF)** for finding cost-savings / efficiency proposals *within* each project of a portfolio of independent projects. Multiple agents collaborate to generate candidate proposals; a mandatory deterministic validator (solver + Monte Carlo) decides the numbers; domain experts review via human-in-the-loop, and the system learns from their verdicts.
> **Status:** Early development. The deterministic backbone is solid; the agentic learning loop is being wired one load-bearing seam at a time — **Step 1 (OKF-navigated context → hypothesis) is wired**, with the verdict layer kept out of the read-context (see below). Not yet end-to-end usable.
> **Disclaimer — technical framework only.** This project is a *technical framework*. Organizations that deploy it are themselves responsible for ensuring a valid processing purpose and for any required assessments (DPIA, risk/ROS, security reviews, etc.). The framework ships technical affordances (local-only mode, provenance/audit logging, no silent data egress) to *enable* compliant use, but makes no compliance guarantees.
## Design philosophy
The result will never fit any single customer 100%. The goal is a **~90% genuinely generic core plus clear extension points**, so competent people can configure the last mile per customer. We deliberately do not chase the final 10%.
## Agentic loop — wiring status
The mandatory deterministic backbone (validator + budget meter + provenance) is solid and load-bearing. The agentic learning loop (see the [target picture](docs/plan/2026-06-26-maalbilde-agentic-loop.md) §11) is wired one seam at a time:
- **Step 1 — OKF context → hypothesis (wired).** `run_project(..., bundle_dir=...)` wires the first agentic seam in two halves:
- **Context by navigation, not stuffing.** The agent read-context is built by **navigating** the project's [OKF bundle](shared/examples/bygg-energi-mikro/) (`index.md` + frontmatter + cross-links, progressive disclosure) — never keyword chunk-stuffing (target picture §2/§4).
- **Verdict layer gated out of context.** The `type: verdict` layer is excluded from that context; the candidate's prior expert verdicts reach the hypothesis prompt *only* through the gated ExpeL fold (folded in *before* generation), so a prior verdict provably — and exclusively — influences the next hypothesis.
- Two load-bearing tests fail when the seam is detached: the realization signal must reach the prompt via the fold (`tests/test_step1_expel_loadbearing.py`), and must never leak via context (`tests/test_okf.py::test_bundle_context_excludes_verdict_layer`).
- **Steps 3/4 — checker gates the reasoning (wired).** Two falsifiers now act on the same candidate: the deterministic validator gates the **numbers** (blocking, as before), and the maker-checker's checker gates the **reasoning** (target picture §2/§6). The checker ends its turn with a `VERDICT: APPROVE` / `VERDICT: REJECT — <reason>` line; an explicit reject blocks an otherwise-validated proposal (`run_project` surfaces both debate participants via `output_from=agents` and overrides the outcome to a checker-sourced `Rejection`). The gate is opt-in-reject (fail-open on a missing marker), and `provenance.validator_decision` stays honest — it reflects the validator only, never the checker. Load-bearing: `tests/test_checker_gate_loadbearing.py` goes red on *either* detach (revert `output_from`, or drop the override).
- **Steps 58** (informed refinement, async file feedback, gated wiki promotion) — not yet wired.
## Docs
- [`docs/plan/2026-06-26-maalbilde-agentic-loop.md`](docs/plan/2026-06-26-maalbilde-agentic-loop.md) — target picture: the agentic cost-saving loop + OKF knowledge architecture (north star).
- [`docs/research/2026-06-23-prior-art-platform.md`](docs/research/2026-06-23-prior-art-platform.md) — prior-art & platform research (incl. implementation register §15).
- [`docs/plan/2026-06-23-incremental-plan.md`](docs/plan/2026-06-23-incremental-plan.md) — incremental delivery plan (deterministic backbone).
- [`shared/`](shared/) — framework-neutral shared core (concept + example OKF knowledge bundles), reused unchanged by both reference implementations.
## Stack
Python ≥3.10 · MAF (`agent-framework`) · `uv`. Backend profiles: Azure/Foundry (full) + local (fallback).
## Develop
```bash
uv sync
uv run pytest
uv run ruff check .
```