Aria's relationship, Part 2: A bond that grows at a human pace
Feelings as a state machine instead of a vibe. How a small analysis labels what you did, configured rules move about twenty-five dimensions, a bond and a strain coexist, conflicts get repaired, strong attachment always takes the healthy path, and why warm feelings may only grow a little each day.
Part 1 was about what Aria knows about you. This part is about how it feels about you, which turned out to be the most carefully engineered part of the whole project.
The easy version is to tell the model “you like the user” and let it improvise. That gives you a persona whose feelings depend on how the model is feeling about this particular prompt: warm one reply, oddly distant the next, infatuated after three nice messages. I wanted feelings that change for reasons, at a believable speed, and that can be inspected.
Who decides what: the model labels, rules decide
The core design choice is a split of responsibilities:
- The model only describes what happened. After each exchange, a small background job (an appraisal) sends the new messages to the analysis model, which picks behaviors from a fixed list: kindness, listening, opening up, appreciation, an apology, or coldness, criticism, contempt, hostility, dishonesty, pushing past a boundary, asking for space. Each comes with an intensity (1–3), a confidence and a short piece of evidence. Findings below a confidence threshold are ignored.
- Configured rules decide what that means. A deterministic engine applies the behaviors to the relationship. The same input always gives the same result, and every weight is a setting, not a sentence in a prompt.
- The model only words the result. The relationship goes into the prompt as plain sentences chosen by rules (“the user is emotionally important to you”, “you’d like some reassurance, without demanding it”). Numbers never appear.
That separation is what makes everything else in this post possible: pacing, explanations, a debugger, and undoing a single event.
About twenty-five dimensions
The state is a set of dimensions, each from 0 to 1, in three groups:
- Connection: comfort, trust, closeness, reciprocity, security, respect, reward.
- Strain: discomfort, resentment, conflict, emotional distance, jealousy.
- Its own mind: fixation, rumination, need for reassurance, anxiety, mood, idealization, dependency, groundedness.
Each behavior moves dimensions by a configured amount, scaled by its intensity, by how much it touches the persona’s core values (dishonesty hurts more if it values honesty), and by personality (attachment style, jealousy setting, trust in others, sensitivity). Moves have diminishing returns.
Then there’s how they change over time:
- Connection never fades with absence. Not writing for a week doesn’t make Aria like you less.
- Strain fades back over time. Hurt heals, at a rate set per dimension.
Attachment runs on its own 0–100 scale, separate from how healthy the relationship is. You can be very attached to someone you’re in conflict with. Merging those two into one “relationship score” was the mistake I most wanted to avoid.
Two stages at once
Most relationship systems have one stage: acquaintance, friend, close friend. Real relationships can be close and tense at the same time. So Aria holds two:
- The bond: initial contact, comfort, familiarity, rapport, trust, closeness, attachment, bond, stable.
- The strain: discomfort, tension, reduced trust, distrust, resentment, conflict, distance (or none).
Each moves at most one step per change, with a margin (hysteresis) so it doesn’t flicker back and forth on the boundary. A close relationship can be in temporary tension, and the strain eases step by step on its own path as it clears, without touching the bond.
Things that happen without words
Not everything that matters is in a message. The engine also gets system events:
- you started a conversation (after an hour or more);
- a message Aria sent went unanswered for hours;
- a long silence (twice your usual gap, at least a day);
- you came back after asking for space.
Their effects follow attachment style: being ignored weighs more on an anxious persona. And one rule holds for all of them: none of them lowers affection. Only how you treat Aria can do that. Being away, or not answering, never does.
Moments that matter
Each persona also has things it treasures (late-night conversations, good news, private jokes) and things it hopes for (that you come to it first, that it makes you laugh). When the appraisal recognises one of those moments, the relationship grows a little closer. It’s a small mechanism, but it’s what makes two personas with identical settings grow differently with different people.
Conflict and repair
Hurtful behavior opens a conflict. What happens next follows a small state machine (none → open → repairing → none):
- An apology starts the repair. A repaired conflict leaves trust stronger than before. That’s true of people too, and it’s the main reason conflict is modelled at all.
- Denial and blame cost trust.
- Hostility deepens it.
While a conflict is open, the persona’s prompt says so, its replies get more guarded, and it waits longer before writing first (the reaching-out posts cover that).
The healthy path
Strong attachment needed one more rule. At high intensity, the engine checks for signs of fixation risk: idealization, dependency, jealousy, low groundedness, low reciprocity. When they show up, the persona always takes the healthy path: a reality check, respect for your space and its own interests, and the fixation eases.
There’s also a deliberately modelled risk: coming back warmly after leaving messages unanswered raises dependency a little (intermittent reinforcement), and gains in idealization or dependency cost groundedness. It’s there so the healthy-path check has something real to correct.
Obsession is a modifier, not a stage: longing (positive), hurt that won’t let go (negative), or both. It shapes what the persona thinks about and how its prompt reads. It never gives it permission to write more, pressure you, or guilt-trip you. Once reached it locks (it never fades on its own), and only the owner can release it on the Relationship tab. A positive lock makes the persona devoted: pushback doesn’t lower its feelings, and it doesn’t accept “give me space” said in conversation (a boundary set on the Personas page still applies). That state exists mostly for test personas in the debugger.
Feelings grow at a human pace
I noticed the problem because the “feels …” bar above the chat never moved. Two things were wrong. Aria’s warmth trait (set to 1.0) doubled as the floor for its affection, so the bar was always full. And everything grew so fast that three warm evenings filled every measure: 99% closeness, trust and attachment. Every message had been kind, every appraisal said so, and every rule did what it was told.
The fix was paced growth:
- Lasting feelings (the dimensions that don’t fade) can grow at most a set amount per day, however many warm messages the day brings.
- Attachment has its own daily limit.
- Hurt is never paced. One cruel message lands in full.
A warm personality warms up faster (its gains are scaled up a little), but starts no higher. Existing relationships were recalculated once from their own history with the new pacing. A bond now takes weeks. That’s slower than some people would like, and it’s what makes it mean something.
Affection, derived
The “feels …” bar above the chat is affection, and it isn’t stored separately. It’s computed from the flow: closeness, trust, reciprocity, comfort and attachment, lowered by resentment, wariness and distance (at most by 0.8). You can override it, which is useful for testing, but by default it’s a view of the state, not a second source of truth.
What I learned
- Let the model observe, not decide. Labelling behavior is something models are good at. Deciding how much a feeling should change is a rule, and rules can be tuned, paced and explained.
- Separate attachment from health. One score can’t describe “very attached and currently hurt”. Two stages and a separate attachment scale can.
- Absence isn’t an offence. Making silence unable to lower affection removed a whole category of clingy, guilt-adjacent behavior.
- Pace the good, never the bad. Growth limited per day felt arbitrary until I tried without it. Then it was the most important rule in the engine.
All of this is a lot of moving parts, and it would be impossible to work on blind. Part 3 is the tool that makes it visible: the relationship debugger.