09 — Portfolio
- Status
- contract + as-built
- Conceptual layer
- ④ Decision
- Repo layer
- L4
knowledge-reasoning - Source
- architecture section 3.6.4, section 5.3
- Related
00-kernel.md·07-finding-runtime.md·08-discovery.md·04-constraints.md· ADR-022
The plant is not one card at a time in isolation. Open cards, held proposals, and in-flight cases share assets, feeders, crews, and owner attention. The portfolio manager keeps that set coherent before anything reaches L5.
HITL still holds: portfolio decides what may be proposed this shift. Owners accept. The system does not clear conflicts by writing the plant.
Decision#
After constraints pass for a candidate set:
- Dedupe by condition keyStable id for “this plant condition”; one open card per key (shared key function).
- Conflict by footprint overlap and constraint evaluation across proposals.
- Supersede only before owner acceptance.
- Attention budget per plant / owner role / shift — over budget → hold (L4-internal).
- Exception-response cards are attention-exempt via the domain registry flag, not a hard-coded domain name in kernel or portfolio code.
- Kernel re-check on the chosen set after portfolio actions.
Money is not re-ranked here into a hero ₹. Section effects stay separate; ranking already refused summed wallets (08-discovery.md).
Why#
Without portfolio, two honest Findings still double-book a feeder or bury the ops head. Without hold-as-internal, "over budget" either drops silently (lost opportunity) or ships anyway (nuisance). Supersede after accept rewrites a human commitment; that is a new card or a conflict note, not a quiet replace.
Stage position#
Fixed relative order (see default stage graph in 01-system-overview.md):
candidates → constraint evaluator → portfolio → kernel re-check → terminal
Portfolio never prefers a candidate the constraint evaluator already failed. Any declared stage graph must keep portfolio after constraints and before the pre-terminal kernel checkpoint.
How to read it.
- Portfolio runs only after the constraint evaluator passes; it never revives a failed candidate.
- Hold is L4-internal; it is not an L5 terminal but still ledgered.
- Kernel re-check runs on the chosen set before any Prescription reaches L5.
Build now: dedupe, conflict, attention hold, exception exempt via domain registry flag. Later: Jev on conflict-action seam when it beats the log.
View Mermaid source
flowchart TB
%% house-style: portfolio-stage
cand["Constraint-satisfied candidates"]
subgraph pf["Portfolio manager"]
direction LR
ded{{"Same condition key?"}}
conf{{"Footprint / constraint conflict?"}}
sup{{"Supersede open unaccepted?"}}
bud{{"Attention budget"}}
end
set["Chosen set"]
ck{{"Kernel re-check"}}
term(["↩ Emit / supersede terminal"])
wa["Withhold / abstain"]
hold["Hold L4 store"]
ol["Opportunity ledger"]
cand --> ded
ded -->|"merge / drop"| set
ded --> conf
conf -->|"resolve"| set
conf --> sup
sup -->|"supersede"| set
sup --> bud
bud -->|"over, not exempt"| hold --> ol
bud -->|"ok or exempt"| set
set --> ck
ck -->|"pass"| term
ck -->|"fail"| wa
classDef govc fill:#fff4d6,stroke:#c99a2e,color:#000
classDef agentc fill:#e8f0ff,stroke:#5b7bd5,color:#000
classDef loopc fill:#eef7ee,stroke:#4f9a4f,color:#000
class ded,conf,sup,bud,ck govc
class term loopc
Dedupe#
Same condition key as an open L5 card, a held proposal, or an in-flight DecisionCaseOne run unit: intake + snapshot + obligations + candidates + terminal → merge or drop.
- Prefer the richer evidence ledgerTyped rows (measured / advisory / model partitions) frozen into the trace and the stricter (narrower) verification plan.
- Primary domain stays the registry id from the family or pattern — L4 does not re-tag primary to "win" a duplicate.
- FindingAs-built L3 detector output admitted to L4 (finding.json 1.2.0) refs and pattern refs accumulate on the surviving case where useful for audit.
The key function is shared with L3 and discovery (15-l3-l4-interface.md).
Conflict#
Conflict when either:
- Footprint overlap — assets, shared resources, crew/role, material, or time windows (with lag) intersect; or
- Constraint conflict — evaluating the joint claim set returns violated or unknown-on-hard.
Resolution (seam-assisted, closed options — see 11-models-and-seams.md):
- keep the rank-preferred proposal and attach the conflict on the card / trace
- hold one
- hold both
- request evidence (withhold path with gate idStable id of the hard or soft gate that blocked a candidate)
Both withheld when the joint set is unknown on a hard constraint. Modeled benefit does not break a tie against a hard conflict.
Supersede#
Allowed only before the owner accepts the open card.
- State changed and a better proposal exists for that condition key → new proposal version, terminal
supersede, L5 marks the prior proposal superseded (not a new closure state). - After acceptance → separate card, or a conflict note on the open card. Do not silently replace an accepted commitment.
Attention budget#
- Scope: per plant, per owner role, per shift.
- Counting unit: cards that would notify or assign that role this shift (exact counter in ops config).
- Over budget → hold: proposal stays in the L4 operational store, visible to Stamped staff and (as labelled backlog items where soft-gated) to the plant owner. Not sent to L5 as a live card.
- Hold is not a kernel terminal to L5; it still produces a DecisionTraceAlways-on record: observed, context, action, policy, approval, outcome (and seam decisions) and an opportunity-ledger row.
Exception-response exemption#
Cards whose primary domain registry entry sets attention_budget_exempt=true skip the budget gate. Seed: the exception-response domain. The portfolio code reads the flag on the registry entry. It never branches on a hard-coded domain name. A future exempt domain is data, not a kernel change.
Exempt cards still dedupe, conflict-check, and supersede by the same rules.
Kernel re-check#
After portfolio chooses the set, run kernel criteria again (00-kernel.md): one card per condition key, money references, constraint results, hard stops, verification narrowing, no write tools. Failure → withhold / abstain even if portfolio had selected emit. This is what keeps a graph reorder from sneaking a bad candidate past the yardstick.
Rejected alternatives#
| Rejected | Why |
|---|---|
| Drop over-budget items silently | Loses real opportunities; no calibration signal |
| Ship over budget and "let the owner triage" | Trains nuisance; breaks the one-queue promise |
| Hard-code exception exemption in portfolio source | Breaks open domain set; kernel/portfolio must not name domains |
| Supersede after accept | Rewrites a human commitment without a new decision |
| Rank by summed ₹ across sections | Dual-wallet honesty; calculator sections stay separate |
What evidence would change this#
- Measured portfolio regret and owner dismiss reasons showing budget too tight → raise per-role budget via plant override + replay (soft gateThreshold in registry; calibrated from opportunity ledger + exploration).
- Conflict miss rate (two shipped cards that fought one resource) → tighten footprint templates or lag defaults.
- Exempt domain flooding attention → clear the registry flag or add a separate exception cap (still registry, not kernel).
v1 slice vs later#
| v1 | Later |
|---|---|
| Dedupe + footprint overlap + attention hold | Richer cumulative-resource conflict packs as constraint kinds expand |
| Exception exempt via domain registry flag | Same mechanism; more flags if product ADR amends |
| Seam for conflict action (send one / hold one / hold both / request evidence) | Jev when it beats the logged seam baseline |
| Staff-visible holds + owner backlog for soft gates | Clearer L6 backlog UX (contract delta in doc 18) |
Links#
- Kernel:
00-kernel.md - Finding path:
07-finding-runtime.md - Discovery ranking feeds this set:
08-discovery.md - Constraints and footprints:
04-constraints.md
Page history: last 3 changes
- docs(technical): rewrite l4 00-10 to the architecture
c52a111 - docs(decisions): renumber live ADRs 001-032 in order, mark withdrawn refs ADR-W###, repoint withdrawn links to archive, note partial supersessions
36c944e - docs(l4): agentic decision architecture, ADRs, and production hardness
8275e7c