Add dignity guardrail v1 design spec
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
# Dignity Guardrail v1 Design
|
||||
|
||||
**Date:** 2026-06-28
|
||||
**Scope:** `relationship` / `finance` strict workflow
|
||||
**Status:** Approved for planning
|
||||
|
||||
## Goal
|
||||
|
||||
Bridge the newly enriched D1 dignity output into `mcp_server.py` as a narrow, domain-aware guardrail that can slightly adjust score and confidence without overriding the existing adjudicators.
|
||||
|
||||
## Why This Exists
|
||||
|
||||
The codebase now exposes richer dignity states such as `NEECHA_BHANGA`, `GREAT_FRIEND`, and `GREAT_ENEMY`, but the current `mcp_server.py` changes apply them by scanning all natal planets and adding or subtracting points globally. That breaks the existing strict-workflow boundary in two ways:
|
||||
|
||||
1. Unrelated planets can alter `relationship` or `finance` verdicts.
|
||||
2. Dignity starts acting like a free-scoring system instead of a bounded evidence guardrail.
|
||||
|
||||
This design fixes that by introducing a small, explicit `dignity_guardrail` evidence block.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Do not redesign dignity scoring across the whole engine.
|
||||
- Do not use D9, D10, Vimsopaka, or any other divisional dignity in v1.
|
||||
- Do not change `dominant_label`, `primary_drivers`, `wealth_promise_strength`, `jaimini_marriage_support`, or `avayogi_risk`.
|
||||
- Do not merge this with Functional Benefic/Malefic logic in v1.
|
||||
- Do not allow dignity to stack into large score swings.
|
||||
|
||||
## Source Boundary
|
||||
|
||||
`dignity_guardrail` may only read from:
|
||||
|
||||
- `full-reading.modules.chart.planets[*].status`
|
||||
- `full-reading.modules.chart.ascendant.sign`
|
||||
|
||||
v1 must not read:
|
||||
|
||||
- `modules.varga_full.*.dignity`
|
||||
- D9 expanded dignity
|
||||
- Vimsopaka dignity layers
|
||||
- any derived dignity from divisional charts
|
||||
|
||||
This keeps the first bridge anchored to one stable source: D1 chart status.
|
||||
|
||||
## Output Contract
|
||||
|
||||
Add the following object to `present_evidence` for `relationship` and `finance`:
|
||||
|
||||
```json
|
||||
{
|
||||
"dignity_guardrail": {
|
||||
"route": "relationship | finance",
|
||||
"status": "ok | caution | conflict | blocked",
|
||||
"score_delta": -5 | 0 | 5,
|
||||
"source": "chart.planets.status",
|
||||
"relevant_planets": [
|
||||
{
|
||||
"planet": "Venus",
|
||||
"role": "relationship_karaka",
|
||||
"status": "落陷取消(Neecha Bhanga)",
|
||||
"dignity_code": "NEECHA_BHANGA",
|
||||
"effect": "supportive_recovery"
|
||||
}
|
||||
],
|
||||
"ignored_planets": [
|
||||
{
|
||||
"planet": "Mars",
|
||||
"reason": "not_domain_relevant"
|
||||
}
|
||||
],
|
||||
"conflict_flags": [],
|
||||
"notes": [
|
||||
"Only domain-relevant planets are allowed to affect score."
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Route-Specific Relevant Planet Selection
|
||||
|
||||
### Relationship
|
||||
|
||||
Relevant planets:
|
||||
|
||||
- `7L`
|
||||
- `Venus`
|
||||
- `Jupiter`
|
||||
- `DK` when present
|
||||
|
||||
Not required in v1:
|
||||
|
||||
- `UL-linked lord`
|
||||
- public-formalization-specific planets
|
||||
|
||||
### Finance
|
||||
|
||||
Relevant planets:
|
||||
|
||||
- `2L`
|
||||
- `11L`
|
||||
- `Venus`
|
||||
- `Jupiter`
|
||||
|
||||
Conditionally relevant:
|
||||
|
||||
- `10L`, but only when `career_convergence` is present
|
||||
|
||||
## Dignity Codes That Matter in v1
|
||||
|
||||
Only two dignity outcomes may affect score:
|
||||
|
||||
- `NEECHA_BHANGA` -> supportive recovery -> `+5`
|
||||
- `GREAT_ENEMY` -> high friction -> `-5`
|
||||
|
||||
All other dignity states may be recorded in `relevant_planets` but must not change score:
|
||||
|
||||
- `EXALTED`
|
||||
- `MOOLATRIKONA`
|
||||
- `OWN_SIGN`
|
||||
- `GREAT_FRIEND`
|
||||
- `FRIEND`
|
||||
- `NEUTRAL`
|
||||
- `ENEMY`
|
||||
- `DEBILITATED`
|
||||
|
||||
## Guardrail Resolution Rules
|
||||
|
||||
The guardrail must not stack.
|
||||
|
||||
Resolution order:
|
||||
|
||||
1. If source data required to identify route-relevant planets is missing, set:
|
||||
- `status = "blocked"`
|
||||
- `score_delta = 0`
|
||||
2. If relevant planets contain both:
|
||||
- at least one `NEECHA_BHANGA`
|
||||
- at least one `GREAT_ENEMY`
|
||||
then set:
|
||||
- `status = "conflict"`
|
||||
- `score_delta = 0`
|
||||
3. Else if any relevant planet has `NEECHA_BHANGA`, set:
|
||||
- `status = "caution"`
|
||||
- `score_delta = 5`
|
||||
4. Else if any relevant planet has `GREAT_ENEMY`, set:
|
||||
- `status = "caution"`
|
||||
- `score_delta = -5`
|
||||
5. Else set:
|
||||
- `status = "ok"`
|
||||
- `score_delta = 0`
|
||||
|
||||
Even if multiple relevant planets match, the maximum absolute adjustment is `5`.
|
||||
|
||||
## Event Judgement Integration
|
||||
|
||||
### Shared Rules
|
||||
|
||||
`dignity_guardrail` may affect only:
|
||||
|
||||
- `event_judgement.score`
|
||||
- `event_judgement.secondary_context`
|
||||
- `confidence_cap` when `status == "conflict"`
|
||||
|
||||
`dignity_guardrail` may not affect:
|
||||
|
||||
- `dominant_label`
|
||||
- `primary_drivers`
|
||||
- `wealth_promise_strength`
|
||||
- `jaimini_marriage_support`
|
||||
- `avayogi_risk`
|
||||
|
||||
### Relationship Integration
|
||||
|
||||
Allowed `secondary_context` additions:
|
||||
|
||||
- `dignity_supportive_recovery`
|
||||
- `dignity_high_friction`
|
||||
- `dignity_conflict`
|
||||
|
||||
Score change:
|
||||
|
||||
- add `score_delta` once
|
||||
|
||||
### Finance Integration
|
||||
|
||||
Allowed `secondary_context` additions:
|
||||
|
||||
- `dignity_supportive_recovery`
|
||||
- `dignity_high_friction`
|
||||
- `dignity_conflict`
|
||||
|
||||
Score change:
|
||||
|
||||
- add `score_delta` once
|
||||
|
||||
This must not change the existing `income_growth` vs `public_wealth_status` label logic.
|
||||
|
||||
## Blocked Conditions
|
||||
|
||||
Set `status = "blocked"` if any of the following prevents a reliable guardrail:
|
||||
|
||||
- missing `chart`
|
||||
- missing `chart.ascendant.sign`
|
||||
- unable to resolve required lords for the route
|
||||
- a required relevant planet exists conceptually but lacks `status`
|
||||
|
||||
When blocked:
|
||||
|
||||
- keep `score_delta = 0`
|
||||
- do not add a positive or negative dignity context
|
||||
- optionally add `dignity_guardrail_blocked` to `secondary_context`
|
||||
|
||||
## Implementation Shape
|
||||
|
||||
Implementation should follow the same pattern as the existing small bridge helpers:
|
||||
|
||||
- add a dedicated helper such as `_derive_dignity_guardrail(route, present)`
|
||||
- call it during strict evidence collection
|
||||
- store the result in `present["dignity_guardrail"]`
|
||||
- consume it in `_derive_event_judgement(...)`
|
||||
|
||||
Do not inline dignity scanning directly inside the scoring block.
|
||||
|
||||
## Testing Requirements
|
||||
|
||||
Add focused tests that prove the boundary:
|
||||
|
||||
1. `relationship` ignores non-relevant planets even if they have `Neecha Bhanga` or `Great Enemy`
|
||||
2. `finance` ignores non-relevant planets even if they have `Neecha Bhanga` or `Great Enemy`
|
||||
3. route-relevant `Neecha Bhanga` yields `score_delta = 5`
|
||||
4. route-relevant `Great Enemy` yields `score_delta = -5`
|
||||
5. mixed relevant signals yield `status = "conflict"` and `score_delta = 0`
|
||||
6. missing chart or unresolved lord yields `status = "blocked"`
|
||||
7. no test may allow dignity to change `dominant_label`
|
||||
8. no test may allow repeated relevant planets to stack score beyond `5`
|
||||
|
||||
## Risks and Containment
|
||||
|
||||
### Risk 1: D1 dignity leaks into divisional logic
|
||||
|
||||
Containment:
|
||||
|
||||
- v1 reads only D1 `chart.planets.status`
|
||||
|
||||
### Risk 2: Dignity becomes an alternate scoring engine
|
||||
|
||||
Containment:
|
||||
|
||||
- two codes only
|
||||
- one score delta only
|
||||
- no stacking
|
||||
|
||||
### Risk 3: Domain boundaries get blurred
|
||||
|
||||
Containment:
|
||||
|
||||
- route-specific relevant planet lists
|
||||
- explicit `ignored_planets`
|
||||
|
||||
## Next Step After v1
|
||||
|
||||
After this guardrail lands and is verified, the next bridge should be a separate `functional_role_guardrail` that consumes the already existing Functional Benefic/Malefic layer without mixing that logic into dignity v1.
|
||||
Reference in New Issue
Block a user