From 976c5e6adaa48b2d1ffd6f8fafdeafcf83ac84d9 Mon Sep 17 00:00:00 2001 From: thisisjun786 <259586770+thisisjun786@users.noreply.github.com> Date: Mon, 14 Sep 2026 02:10:51 +0900 Subject: [PATCH 1/5] =?UTF-8?q?docs:=20=ED=8E=98=EB=A5=B4=EC=86=8C?= =?UTF-8?q?=EB=82=98=20=EA=B3=A0=EC=A0=95=C2=B7=EC=84=B1=EC=9E=A5=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20=EA=B3=84=EC=95=BD=20=ED=99=95=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 에이전트별 페르소나 프롬프트를 쓰기 전에 무엇을 고정으로 적고 무엇을 성장에 맡길지 판단할 근거가 한곳에 없었다. 층의 우선순위는 persona.ts의 권위 문구에, 잠금 판정은 persona-schema.ts에, 정체성 자료 생성은 fleet/life-runtime.ts에 흩어져 있어 작성자가 모아서 읽을 수 없었다. 018을 신설해 층 우선순위, 명시적 대화 선호의 적용 범위, evolution과 축별 잠금으로 하는 고정·성장 선언, 필드 소유권, 불완전한 정체성 자료 다섯 경우의 처리, 작성에서 소비까지의 연결표, 대표 예시와 프롬프트 작성 착수 판정을 기록한다. 정본에는 D24로 남기고 016·017·031에서 연결한다. 현재 생산자와 D18이 의도한 소유권, 아직 없는 저장 필드를 구분해 적었다. 개인별 선택 잠금을 저장할 곳이 없어 제품에서 실효 있는 선택이 manual과 adaptive 둘뿐이라는 사실과, PersonaSchema 파생 함수에 제품 호출자가 없다는 사실을 그대로 남겼다. 잠금 저장과 생성기 전환은 후속 작업이다. Refs: JUN-28 --- docs/MOIRAI_ENGINE.md | 2 + .../context-engines/031_persona_projection.md | 2 +- .../016_neural_preference_contract.md | 2 +- .../platform/017_moirai_module_composition.md | 2 +- .../018_persona_authoring_contract.md | 151 ++++++++++++++++++ 5 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 docs/plans/platform/018_persona_authoring_contract.md diff --git a/docs/MOIRAI_ENGINE.md b/docs/MOIRAI_ENGINE.md index 19b125f..4c88514 100644 --- a/docs/MOIRAI_ENGINE.md +++ b/docs/MOIRAI_ENGINE.md @@ -313,6 +313,7 @@ QA 채택 커널의 `Purpose`·`Adoption(understanding | plan | intention)`·`Ju | D21 | 이전 결정: OMO native 작업 실행·Senpi native 프로바이더 관리로 옮기고 Codex/OpenCodex 폐기. 2026-09-13 D22로 철회. 과거 QA와 자료는 근거 이력으로 보존 | | D22 | 2026-09-13 소유자 결정: 인지·대화·개발 작업은 Codex, 프로바이더 관리는 OpenCodex로 유지한다. D13·D21의 Senpi/OMO 전환을 철회한다. 세 목표·MaleCNS·Host 소유권은 유지하며 기존 실행 경로에 연결한다 | | D23 | 출력은 생성 토큰 예산과 저장용 문장 길이를 분리한다. 새 설명문은 길이 때문에 판단 전체를 실패시키지 않고 자른 표시·원래 길이·해시를 남긴다. 구조화된 필수 판단은 자르지 않는다. policy revision 2는 필수 평가 불가 시 보완 후 보류, 예산 소진 시 deferred를 사용하고 revision 1은 과거 재생으로 보존 | +| D24 | 2026-09-14 페르소나 작성 계약. 잠금·권한이 작성 정체성보다 앞서고, 검증된 성장은 자기 축에서만 초기 기질을 대체한다. 명시적 대화 선호는 말 거는 방식에만 적용되며 정체성·권한·잠긴 축을 바꾸지 않는다. 고정과 성장은 `evolution`과 축별 잠금 목록으로 선언하며 산문에는 강제력이 없다. 제공된 정체성 자료에 대상 개인이 없으면 정책 부재로 접지 않고 거부한다. 세부는 [018 작성 계약](plans/platform/018_persona_authoring_contract.md) | ## 이 문서가 확정하지 않는 것 @@ -335,6 +336,7 @@ QA 채택 커널의 `Purpose`·`Adoption(understanding | plan | intention)`·`Ju | --- | --- | | [016 계약](plans/platform/016_neural_preference_contract.md) | 타입·포트·저장·복구·실패 처리 | | [017 로드맵](plans/platform/017_moirai_module_composition.md) | 소스 재료 표, F1–F4 의존 순서, 검증 가설 | +| [018 작성 계약](plans/platform/018_persona_authoring_contract.md) | 페르소나 층 우선순위, 고정·성장 선언, 필드 소유권, 불완전 입력 처리 | | [015 근거](plans/platform/015_neural_preference_engine_research.md) | MaleCNS 선택 이유, 데이터 출처, 학습·계획·BDI 문헌 | | [030 운영](plans/context-engines/030_moirai_refactor_plan.md) | 사용자 경험 경계, 채널·세션 계약, 모델 프리셋, 검증 게이트 | | [ARCHITECTURE](ARCHITECTURE.md) | 패키지 owner와 신뢰 경계 | diff --git a/docs/plans/context-engines/031_persona_projection.md b/docs/plans/context-engines/031_persona_projection.md index 45f6329..0170fbf 100644 --- a/docs/plans/context-engines/031_persona_projection.md +++ b/docs/plans/context-engines/031_persona_projection.md @@ -8,7 +8,7 @@ 개인 대화용 현재 성향은 적격 self/relationship 기록을 검증해 읽는다. subject=user는 persona authority가 아니다. provisional 기록은 잠정 배경으로 표시하며 안정된 행동으로 승격하지 않는다. manual evolution에서는 동적 성향을 적용하지 않는다. world가 없는 대화에서도 이 개인 투영은 유효하다. 관계의 자유문장을 특정 agent id로 추측하지 않는다. -공유용 개인 성향은 별도의 제한된 해석 결과다. 모델은 등록된 LifeDefinition의 공유 허용 dimension만 선택할 수 있다. 출력은 trait(axisId, value), habit(habitId, value), attitude(axisId, toAgentId, value), 그리고 근거 record id 목록이다. 임의 label/text/quote/비밀/권한은 출력 필드가 아니다. label은 host가 당시 정의에서 가져오고 숫자 범위·boolean·참여자 id·방향을 검증한다. authored identity 또는 manual/explicit lock 변경 권한은 없다. 원본 self/relationship의 지원된 현재 기록만 근거로 쓴다. 일반 사용자 사실과 LIFE-derived 대화는 입력에서 제외한다. +공유용 개인 성향은 별도의 제한된 해석 결과다. 모델은 등록된 LifeDefinition의 공유 허용 dimension만 선택할 수 있다. 출력은 trait(axisId, value), habit(habitId, value), attitude(axisId, toAgentId, value), 그리고 근거 record id 목록이다. 임의 label/text/quote/비밀/권한은 출력 필드가 아니다. label은 host가 당시 정의에서 가져오고 숫자 범위·boolean·참여자 id·방향을 검증한다. authored identity 또는 manual/explicit lock 변경 권한은 없다. 여기서 지키는 작성 잠금이 어떤 형식으로 선언되고 누가 소유하는지는 [018 작성 계약](../platform/018_persona_authoring_contract.md)이 기록한다. 원본 self/relationship의 지원된 현재 기록만 근거로 쓴다. 일반 사용자 사실과 LIFE-derived 대화는 입력에서 제외한다. AgentStore v3에 agent_behavior_jobs와 agent_behavior_receipts를 추가한다. job은 agent/world/profile revision, definition/projection digest, memory record의 id/revision/contentHash와 적격 source proof digest, 정책·모델 revision, 요청 fingerprint, 상태·attempt를 고정한다. receipt는 정확한 typed output과 고정 입력을 묶는다. 같은 source content로 request id만 바꿔도 새 성장 근거가 되지 않는다. receipt의 원본 참조는 새 읽기마다 runtime의 현재 EngineStore로 검사한다. 취소·철회·만료로 부적격해지면 과거 receipt를 지우지 않고 현재 projection에서 제외한다. diff --git a/docs/plans/platform/016_neural_preference_contract.md b/docs/plans/platform/016_neural_preference_contract.md index cdfccfc..7b4d05e 100644 --- a/docs/plans/platform/016_neural_preference_contract.md +++ b/docs/plans/platform/016_neural_preference_contract.md @@ -142,7 +142,7 @@ Host는 `candidateLimit`, `maxEvaluationGenerations`, `maxAdditionalCalls`, 회 | `h`, 느린 `m`, 개인 `ΔW`, 학습 흔적·예측기 | Host의 제안 `NeuralPreferenceStore` | Python은 계산 결과를 제안하며 직접 저장하지 않음 | | 대화·LIFE가 읽는 성향 | 기존 성향 합성 owner | `dimensionSource`로 reflection/neural 중 하나 선택; 같은 dimension의 두 생성 결과를 합산하지 않음 | -`dimensionSource`는 새 버전의 owner 설정이다. 기존 LIFE origin 합성 규칙을 몰래 대체하지 않는다. 신경 origin을 선택한 dimension은 그 origin의 기존 모델 해석을 중지하고, 동일 경험이 reflection·neural·승격 stream에서 중복 가산되지 않도록 원본 사건 ID를 보존한다. 명시적 선호를 `p0`에 적용했다면 신경 편향에 같은 항목을 다시 더하지 않도록 경로를 선언한다. +`dimensionSource`는 새 버전의 owner 설정이다. 기존 LIFE origin 합성 규칙을 몰래 대체하지 않는다. 신경 origin을 선택한 dimension은 그 origin의 기존 모델 해석을 중지하고, 동일 경험이 reflection·neural·승격 stream에서 중복 가산되지 않도록 원본 사건 ID를 보존한다. 명시적 선호를 `p0`에 적용했다면 신경 편향에 같은 항목을 다시 더하지 않도록 경로를 선언한다. 현재 파생은 `reflection`을 고정으로 넣으며 이 설정의 작성 표면은 아직 없다. 소유자와 남은 범위는 [018 작성 계약](018_persona_authoring_contract.md)이 기록한다. 기존 behavior receipt가 신경 출처를 이미 지원한다고 가정하지 않는다. 후속 source 계약에 `NeuralProjectionRef`를 추가해 profile·state/learning revision·허용 dimension·값·원본 경험과 source proof의 digest를 묶는다. Host가 현재성을 확인하고 기존 합성 owner가 값만 투영한다. 원시 신경 데이터와 비밀 원문은 모델 입력에 전달하지 않는다. diff --git a/docs/plans/platform/017_moirai_module_composition.md b/docs/plans/platform/017_moirai_module_composition.md index f1115e8..a8a1ad3 100644 --- a/docs/plans/platform/017_moirai_module_composition.md +++ b/docs/plans/platform/017_moirai_module_composition.md @@ -82,7 +82,7 @@ F1의 `Purpose`·`Understanding`·`Plan` 의미와 typed Forecast/Claim, `Neural | 개인의 첫 행동 catalog | D15 `personal.v1` | F1: schema·정규화 규칙·전제/효과 필드의 코드 정의. F2: TaskManager·JudgmentStore effect 연결 | | 기회/행동 분류 | D09 원칙, LIFE catalog는 F3 선언 | F3: 기존 LIFE pack 전체의 family·actor·terminal 분류와 분포 변화 기록 | | 의도의 최소 schema | D16 `IntentionRecord` v1 | F1: 직렬화·전이 검증. F2: 약속·자율 목표의 충돌·완료·철회 시나리오 | -| 성향 축의 소유권 | D18 AgentStore `PersonaSchema` | F1: schema 정의. F4: 기존 Behavior receipt·projection의 데이터 이전 | +| 성향 축의 소유권 | D18 AgentStore `PersonaSchema`, 작성 계약은 [018](018_persona_authoring_contract.md) | F1: schema 정의와 작성 계약. 개인별 잠금 저장·정체성 자료 생성기·NativePersonaGrowth 전환은 F4의 데이터 이전과 함께 수행 | | 회로/의미 인터페이스 | D14 회로 프로필 v1 | F2: body 목록·부호·상수·해시 추출, encoder/readout 구현, `qualified` 검사 | | 목표별 판단·종합 정책 | D17 `personal.v1` 조정 정책 | F1: policy revision 2와 revision 1 과거 재생. F2: ResolutionRecord/SelectionSpec 재현 검증. 효용 비교는 아래 가설 | | 제품 세션·저장 경계 | D19 저장소 셋과 Python 계산기 하나 | F2: JudgmentStore·NeuralPreferenceStore·outbox/inbox·checkpoint manifest 편입 | diff --git a/docs/plans/platform/018_persona_authoring_contract.md b/docs/plans/platform/018_persona_authoring_contract.md new file mode 100644 index 0000000..cafefef --- /dev/null +++ b/docs/plans/platform/018_persona_authoring_contract.md @@ -0,0 +1,151 @@ +# 018 — 페르소나 고정·성장 작성 계약 + +상태: 2026-09-14. 이 문서는 페르소나 작성자가 "무엇을 고정으로 적고 무엇을 성장에 맡기는가"를 판단하는 계약을 소유한다. 확인한 소스는 `c5e9810`이다. 타입·포트·저장·복구는 [016 계약](016_neural_preference_contract.md), 구현 순서는 [017 로드맵](017_moirai_module_composition.md), 성장 해석과 합성은 [031 성장 투영](../context-engines/031_persona_projection.md), 프롬프트 조립 영역과 예산은 [PERSONA_CONTEXT](../../PERSONA_CONTEXT.md)가 계속 소유한다. 여기서는 그 계약들이 이미 정한 것을 다시 적지 않는다. + +## 상태와 범위 + +F1에서 확정하는 것은 의미와 작성 형식이다. 층의 우선순위, 고정·성장의 선언 방법, 각 필드의 소유자, 불완전한 입력의 처리, 작성에서 소비까지의 연결 지도를 정한다. + +F1에서 확정하지 않는 것은 배선이다. 개인별 잠금 목록을 담을 저장 필드, 그 값을 읽는 정체성 자료 생성기, `NativePersonaGrowth`가 `LifeDefinition` 대신 schema를 읽는 전환, 기존 성장 데이터의 이전은 모두 후속 작업이다. + +이 문서를 확정해도 개별 캐릭터의 성격·잠금·수치가 정해지지 않는다. 아래 예시는 구조를 검증하기 위한 것이고 실제 인물 설정이 아니다. + +## 층 모델과 우선순위 + +한 개인의 현재 행동은 여러 층이 겹쳐 만들어진다. 위 행이 아래 행을 이긴다. 아래 층은 위 층을 다시 쓰지 못한다. + +| 층 | 내용 | 현재 소유 타입 | 근거 | +| --- | --- | --- | --- | +| 잠금과 권한 | `evolution`, 축별 잠금, 공개 허용 목록 | [`IdentityProfilePolicy`](../../../packages/lina-core/src/world/life-types.ts#L121), [`ProjectionPolicy`](../../../packages/lina-core/src/world/life-types.ts#L38) | [manual 단락](../../../packages/lina-core/src/agents/persona.ts#L96), [성장 차단](../../../packages/lina-core/src/world/growth.ts#L40), [사회 효과 차단](../../../packages/lina-core/src/world/social-effect-state.ts#L127) | +| 작성 정체성 | 이름·역할·성격·말투·전기·외형·관심사 | [`AgentProfile`](../../../packages/lina-core/src/agents/types.ts#L3) | [핵심 권위 문구](../../../packages/lina-core/src/agents/persona.ts#L38) | +| 검증된 성장 | 근거가 확인된 현재 성향 값 | [`SharedPersonaView`](../../../packages/lina-core/src/world/views.ts#L253), 개인 투영 | [공유 성향 권위 문구](../../../packages/lina-core/src/agents/persona.ts#L53) | +| 초기 기질 | 축별 시작값 | [`PersonaDimension.initial`](../../../packages/lina-core/src/agents/persona-schema.ts#L43) | 같은 문구가 초기 기질을 "출발점"으로 규정 | +| 일시 상태 | 기분과 최근 관심·선호·관계 메모 | [`Dynamics`](../../../packages/lina-core/src/agents/types.ts#L19) | [변동 맥락 문구](../../../packages/lina-core/src/agents/persona.ts#L48) | + +검증된 성장은 **자기가 올라간 축에서만** 초기 기질을 대체한다. 작성 정체성의 성격 문장은 숫자로 대체되지 않는다. 두 가지가 모두 "작성한 것"이지만 성격은 표현의 기준이고 초기 기질은 축의 시작값이다. + +## 명시적 대화 선호의 범위 + +사용자가 직접 말한 대화 선호는 위 순서에 끼워 넣지 않는다. 적용 범위가 다르기 때문이다. + +이 선호는 사용자에게 말을 거는 방식에만 적용되고 에이전트의 정체성·권한·잠긴 축을 바꾸지 않는다. 같은 항목에 새 요청이 오면 이전 요청을 대체하고, 현재 대화의 지시가 저장된 선호보다 앞선다. 실행 중인 문구가 이미 그렇게 되어 있다([대화 선호 지침](../../../packages/lina-runtime/src/persona/conversation.ts#L59)). + +학습된 사용자 자료는 참고이며 페르소나 권위가 아니다. 계층별 전달·수명·충돌 처리의 전체 표는 [PERSONA_CONTEXT의 입력 계약](../../PERSONA_CONTEXT.md#lina의-정규화된-입력-계약)이 소유한다. 두 문서가 함께 뒷받침하지 않는 전면적인 순서는 여기서 단정하지 않는다. + +## 고정과 성장의 선언 + +"고정"과 "성장"은 새 개념이 아니라 기존 두 가지의 조합이다. + +`evolution`이 `manual`이면 공유 대상 축 전체가 잠긴다. `adaptive`이면 축별 잠금 목록에 적힌 축만 잠기고 나머지는 근거가 쌓이면 변한다. 판정 순서는 manual이 먼저다([`lockedFor`](../../../packages/lina-core/src/agents/persona-schema.ts#L289)). + +프롬프트 산문은 강제력이 없다. 성격 문장에 "쉽게 변하지 않는다"라고 적어도 잠기지 않고, "경험에 따라 달라진다"라고 적어도 잠긴 축이 열리지 않는다. 강제는 위 표의 잠금과 권한 층이 한다. + +## 필드 소유권 + +세 가지를 구분해서 읽어야 한다. + +**현재 생산자.** 축의 id·label·범위·기본 시작값과 공개 허용 목록은 [`LifeDefinition`](../../../packages/lina-core/src/world/life-types.ts#L45)이 제공한다. 성장 제어 설정 중 개인별로 실재하는 필드는 [`AgentProfile.evolution`](../../../packages/lina-core/src/agents/types.ts#L13) 하나다. 축별 잠금 목록은 저장된 값이 아니라 Fleet가 `evolution`에서 합성한다([생성 지점](../../../packages/lina-runtime/src/fleet/life-runtime.ts#L78)). `source`는 파생이 `reflection`으로 고정한다([고정 지점](../../../packages/lina-core/src/agents/persona-schema.ts#L328)). + +**의도된 소유권.** [D18](../../MOIRAI_ENGINE.md#확정된-결정-목록)대로 `PersonaSchema`의 소유자는 AgentStore다. World는 자기 축을 schema의 dimension에 대응시킨다. 이 절이 D18을 바꾸지 않는다. + +**미구현 저장.** 개인별 잠금 목록과 `source`를 담을 저장 필드는 아직 없다. 그래서 현재 제품에서는 개인별 선택 잠금을 작성할 방법이 없고, 실질적으로 전부 잠그거나 전부 여는 두 선택만 가능하다. 이 배선은 후속 작업이다. + +## 작성 입력과 검증 + +작성자가 개인별로 정하는 값은 `evolution`과 축별 잠금 목록 세 개다. 잠금 목록에 적는 id는 대상 세계 정의에 실재하는 축이어야 하고, 없는 id는 거부한다. 참여자 확인은 이미 같은 방식으로 거부한다([참여자 검사](../../../packages/lina-core/src/agents/persona-schema.ts#L310)). + +잠금 목록을 적지 않으면 빈 목록으로 읽는다. 빈 목록은 "아직 안 정함"이 아니라 "이 개인의 공유 축은 모두 성장 가능"이라는 뜻이다. 축 자체를 성장 대상에서 빼려면 잠그는 것이 아니라 공개 허용 목록에서 제외한다. 두 장치의 의미가 다르다. + +`source`는 AgentStore의 owner 설정이며 현재는 `reflection` 하나만 쓴다. [`DIMENSION_SOURCES`](../../../packages/lina-core/src/agents/behavior-types.ts#L176)에 `neural`이 선언돼 있지만 [형태만 선언된 후속 대상](../../../packages/lina-core/src/agents/behavior-types.ts#L183)이다. 작성 표면은 [016의 상태 소유권 절](016_neural_preference_contract.md#상태-소유권과-공개-범위)과 함께 F2에서 정한다. + +개인 성향 값을 담는 두 번째 수정 가능한 원본은 만들지 않는다. 잠금은 정책이고 값이 아니다. 값은 계속 receipt와 세계 상태로만 흐른다. + +## 근거와 공개 범위 + +근거는 작성하는 항목이 아니다. 성향이 왜 그 값인지는 해석 receipt와 사건 id가 만든다([성장 근거 검사](../../../packages/lina-core/src/world/growth.ts#L44)). 작성자가 항목마다 근거 문장을 적지 않는다. + +공개 범위도 항목별로 적지 않는다. 어떤 축을 공유하는지는 `projection`의 허용 목록이, 무엇을 드러낼지는 그 정책의 공개 항목이 소유한다. 파생은 허용 목록에 있는 축만 schema에 넣는다([필터 지점](../../../packages/lina-core/src/agents/persona-schema.ts#L321)). + +## 불완전 입력의 의미 + +정체성 자료가 온전하지 않은 다섯 경우를 구분한다. + +| 경우 | 처리 | 뜻 | +| --- | --- | --- | +| 자료를 아예 주지 않음 | 허용. 참조한 프로필이 없다고 기록하고 전 축을 잠그지 않음 | "정책을 조회하지 않았다". 이 결과는 성장·사회 입력으로 쓰지 않는다 | +| 자료는 줬는데 대상 개인이 없음 | **거부** | 자료 오류다. 정책 부재로 접지 않는다 | +| `adaptive`, 잠금 목록 비어 있음 | 허용. 공유 축 전부 성장 가능 | "허용 목록 안에서 전부 성장" | +| `manual` | 허용. 잠금 목록과 무관하게 전 축 잠금 | "고정" | +| 프로필 revision이 성장 기록 이후 바뀜 | 아래 참조 | 관찰되는 것만 기록한다 | + +두 번째 경우를 거부하는 이유는 형제 소비자가 이미 그렇게 하기 때문이다. [LIFE 공유 투영](../../../packages/lina-core/src/world/views.ts#L252), [현재 페르소나 투영](../../../packages/lina-core/src/world/views.ts#L416), [성장 적용](../../../packages/lina-core/src/world/growth.ts#L34), [사회 효과 규칙](../../../packages/lina-core/src/world/autonomy-rules.ts#L208)이 모두 대상 프로필이 없으면 실패한다. 제공된 자료는 참여자 전원에 대한 주장이므로 대상이 빠진 것은 부재가 아니라 결함이다. 운영 생산자도 참여자 전원을 넣거나 그 전에 실패한다([참여자 수집](../../../packages/lina-runtime/src/fleet/life-runtime.ts#L71)). + +revision이 바뀐 경우는 현재 관찰되는 것만 적는다. 파생은 호출자가 준 revision을 그대로 쓰고, 참조한 프로필 revision만 남긴다([기록 지점](../../../packages/lina-core/src/agents/persona-schema.ts#L372)). 프로필을 갱신해도 schema를 다시 파생하는 경로는 없다. 그 뒤 그 schema를 새로 파생할지, 현재 투영에서 뺄지, 재생 전용으로 읽을지는 아직 정하지 않았다. 다른 owner에 비슷한 선례가 있지만([receipt 적격성](../../../packages/lina-core/src/agents/behavior-store.ts#L284), [투영 revision 대조](../../../packages/lina-core/src/agents/persona.ts#L72)) 그 규칙을 `PersonaSchema`로 옮기지 않는다. + +## 작성에서 소비까지의 연결표 + +| 단계 | 현재 | 확인 위치 | 남은 일 | +| --- | --- | --- | --- | +| 작성 입력 | `evolution`만 지정 가능. 축별 잠금을 적을 입력이 없고 온보딩은 `evolution`을 작성 대상에서 제외 | [프로필 검증](../../../packages/lina-core/src/agents/validation.ts#L111), [온보딩 제외](../../../packages/lina-runtime/src/fleet/intro-prompt.ts#L32) | 잠금 입력 추가 | +| 저장 | `agent_profiles`에 `evolution` 열. 잠금 열 없음 | [schema](../../../packages/lina-core/src/agents/agent-schema.ts#L11) | 잠금 저장 추가 | +| 정체성 자료 | `evolution`에서 전 축 또는 빈 목록을 합성 | [생성 지점](../../../packages/lina-runtime/src/fleet/life-runtime.ts#L78) | 저장된 잠금을 읽도록 전환 | +| `PersonaSchema` 파생 | 허용 축에 `initial`·범위·`locked`·`source` 부여 | [파생 함수](../../../packages/lina-core/src/agents/persona-schema.ts#L301) | 제품 호출자 지정 | +| 일반 대화 | manual이면 비우고 아니면 검증된 현재 값을 투영 | [투영 경계](../../../packages/lina-core/src/agents/persona.ts#L56) | schema 소비로 전환 | +| LIFE | 성장과 사회 효과가 manual·잠금을 각각 확인 | [성장](../../../packages/lina-core/src/world/growth.ts#L40), [사회 효과](../../../packages/lina-core/src/world/social-effect-state.ts#L127) | 유지 | + +파생 함수에는 아직 제품 호출자가 없다. 배럴에서 내보내고 테스트가 호출할 뿐이다. 계약이 정의됐다는 것과 제품이 그 계약을 따른다는 것은 다르다. + +## 대표 예시 + +아래는 구조 검증용이며 실제 인물 설정이 아니다. 축과 값은 [PersonaSchema 회귀 픽스처](../../../packages/lina-core/test/persona-schema.test.ts#L27)를 그대로 쓴다. 공유 축은 `warmth`·`curiosity`·`tea`·`trust` 네 개다. + +고정으로 쓴 개인은 `evolution`이 `manual`이다. 네 축이 모두 잠기고 학습이 값을 바꾸지 못한다. + +선택 잠금으로 쓴 개인은 `evolution`이 `adaptive`이고 `lockedTraitIds`가 `["warmth"]`다. `warmth`만 잠기고 `curiosity`·`tea`·`trust`는 근거가 쌓이면 변한다. + +자료를 주지 않으면 네 축 모두 잠기지 않고 참조한 프로필이 없다고 기록된다. 세 결과는 digest가 서로 다르다. 이 픽스처에서 각각 `b7ade1a1`, `87fb41e7`, `aa57cfc0`로 시작한다. 64자 digest의 앞 8자이고 축의 label 하나만 바꿔도 달라지므로 다른 예시의 기대값으로 쓰지 않는다. + +대상 개인이 없는 자료를 주면 셋 중 어느 결과도 나오지 않고 파생이 실패한다. 참여자가 아닌 개인을 요청했을 때의 실패와는 메시지가 다르다. + +## 프롬프트 작성 규칙과 착수 판정 + +성격과 말투는 산문으로 쓰고 수치는 축에 쓴다. 산문에 "친밀도 7" 같은 값을 적지 않는다. + +잠근 축에 성장을 약속하지 않고, 열어 둔 축을 불변으로 묘사하지 않는다. 둘이 어긋나면 강제되는 쪽은 잠금이고 산문은 지켜지지 않는다. + +상대별 태도는 축 단위로만 잠근다. 특정 상대에 대해서만 잠그는 표현은 현재 없다. + +이 계약으로 **개별 페르소나 프롬프트 작성을 시작할 수 있다.** 작성자는 성격·말투·전기를 산문으로 쓰고, 각 공유 축을 고정으로 둘지 성장으로 둘지 정하고, 성장으로 둔 축의 시작값과 범위를 세계 정의에서 확인하면 된다. + +전제는 남는다. 개인별 선택 잠금을 제품에 저장할 방법이 아직 없으므로, 지금 작성한 선택 잠금은 문서상의 의도로 남고 배선이 끝나야 실제로 적용된다. 그 전까지 제품에서 실효가 있는 선택은 `manual`과 `adaptive` 둘뿐이다. + +## 기각한 대안 + +개인별 잠금을 `LifeDefinition`에 참여자별로 넣는 안은 기각한다. 페르소나 정책을 World로 옮겨 D18과 어긋나고, 정의가 세계마다 있으므로 한 개인이 두 세계에서 서로 다른 잠금을 갖게 된다. + +`PersonaSchema`를 직접 작성하는 안은 기각한다. schema는 파생물이고 digest로 묶여 있어서, 직접 쓰면 label과 범위가 세계 축과 갈라진다. + +고정과 성장을 프롬프트 산문으로만 표현하는 안은 기각한다. 산문은 강제력이 없고 잠금은 코드가 검사한다. + +## 확정하지 않은 것 + +| 항목 | 현재 상태 | +| --- | --- | +| 잠금 목록을 프로필에 둘지 별도 기록에 둘지 | 미정. 프로필에 두면 잠금 변경이 기존 성장 근거를 무효화한다 | +| 개인별 시작값 재정의 | 미정. 바꾸면 031의 합성식이 함께 바뀐다 | +| 자료를 주지 않는 입력을 계속 허용할지 | 미정. 제품 호출자가 생길 때 다시 본다 | +| 상대별 태도 잠금 | 축 단위만 수용. 상대별 잠금은 표현 불가 | +| `manual`에 잠금 목록이 함께 있을 때 | 잉여로 허용. 모순으로 거부할지는 미정 | +| revision이 바뀐 schema의 처리 | 미정. 자동 파생 여부와 현재·재생 적격성 판정이 모두 코드에 없다 | + +이 항목들의 결정과 구현은 후속 작업에서 다룬다. + +## 관련 문서 + +| 문서 | 소유 범위 | +| --- | --- | +| [MOIRAI_ENGINE](../../MOIRAI_ENGINE.md) | 정본 결정과 기존 모듈의 배치 | +| [016 계약](016_neural_preference_contract.md) | 타입·포트·저장·복구, `dimensionSource` | +| [017 로드맵](017_moirai_module_composition.md) | F1–F4 순서와 남은 산출물 | +| [031 성장 투영](../context-engines/031_persona_projection.md) | 성장 해석·receipt·합성식 | +| [PERSONA_CONTEXT](../../PERSONA_CONTEXT.md) | 프롬프트 조립 영역·예산·입력 계층 표 | From cc77c1529f8064b537c2d6c4f5f72de45ccf3ae7 Mon Sep 17 00:00:00 2001 From: thisisjun786 <259586770+thisisjun786@users.noreply.github.com> Date: Mon, 14 Sep 2026 03:38:46 +0900 Subject: [PATCH 2/5] =?UTF-8?q?docs:=20=EC=84=B1=EC=9E=A5=EC=9D=84=20?= =?UTF-8?q?=EB=A7=89=EB=8A=94=20=EC=9E=A5=EC=B9=98=EC=99=80=20=EC=9E=A0?= =?UTF-8?q?=EA=B8=88=20id=20=EB=B2=94=EC=9C=84=EB=A5=BC=20=EB=B0=94?= =?UTF-8?q?=EB=A1=9C=EC=9E=A1=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 코드리뷰가 018에서 두 가지를 짚었고 소스로 확인해 둘 다 맞았다. 첫째, 축을 성장에서 빼려면 공개 허용 목록에서 제외하라고 안내했는데 틀렸다. LIFE의 성장 검증·적용과 사회 효과는 evolution과 축별 잠금만 보고 허용 목록을 보지 않는다. LIFE 회고에 넘기는 자기 성향에도 그 필터가 없다. 허용 목록에서 뺀 축도 LIFE 경로로는 계속 변한다. 그 안내는 비공개이면서 성장하는 축이라는 정상 조합도 막았다. 반대로 잠금과 manual만이 성장을 막는다고 적지도 않는다. 허용 목록은 네이티브 개인 성향 해석의 대상을 실제로 제한하고, 그 밖에도 각 경로가 근거·범위·현재성·예산 검사를 따로 건다. 잠그지 않았다는 것은 변할 자격이 있다는 뜻이지 변화가 일어난다는 뜻이 아니다. 둘째, 잠금 id를 한 세계 기준으로만 설명했다. 잠금 목록은 개인 소유인데 축 id는 세계마다 정의되고 전역 이름공간이 없어서, 한 세계에서 유효한 잠금이 다른 세계에서 이름만 같은 다른 축을 잠글 수 있다. 표현 방식은 미해결로 남기고 잠정 규칙을 적었다. 초안에 어느 세계의 축인지 함께 적고 다른 세계로 옮겨 쓰지 않는다. LifeDefinition 소유를 기각한 것이 AgentStore가 소유하는 세계 범위 정책까지 금지하지는 않는다는 점도 분명히 했다. 덧붙여 아직 없는 동작을 현재형으로 적은 세 곳을 고쳤다. 없는 잠금 id 거부와 잠금 목록 생략 시의 기본값은 작성 경계에 요구하는 규칙이고, 대상 개인이 없는 자료의 거부는 후속 PR에서 적용되는 채택 규칙이다. Refs: JUN-28 --- .../018_persona_authoring_contract.md | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/docs/plans/platform/018_persona_authoring_contract.md b/docs/plans/platform/018_persona_authoring_contract.md index cafefef..9826f49 100644 --- a/docs/plans/platform/018_persona_authoring_contract.md +++ b/docs/plans/platform/018_persona_authoring_contract.md @@ -16,7 +16,7 @@ F1에서 확정하지 않는 것은 배선이다. 개인별 잠금 목록을 담 | 층 | 내용 | 현재 소유 타입 | 근거 | | --- | --- | --- | --- | -| 잠금과 권한 | `evolution`, 축별 잠금, 공개 허용 목록 | [`IdentityProfilePolicy`](../../../packages/lina-core/src/world/life-types.ts#L121), [`ProjectionPolicy`](../../../packages/lina-core/src/world/life-types.ts#L38) | [manual 단락](../../../packages/lina-core/src/agents/persona.ts#L96), [성장 차단](../../../packages/lina-core/src/world/growth.ts#L40), [사회 효과 차단](../../../packages/lina-core/src/world/social-effect-state.ts#L127) | +| 잠금과 권한 | `evolution`과 축별 잠금이 성장을 막고, 공개 허용 목록은 공유·투영 범위를 정한다. 역할이 다르다 | [`IdentityProfilePolicy`](../../../packages/lina-core/src/world/life-types.ts#L121), [`ProjectionPolicy`](../../../packages/lina-core/src/world/life-types.ts#L38) | [manual 단락](../../../packages/lina-core/src/agents/persona.ts#L96), [성장 차단](../../../packages/lina-core/src/world/growth.ts#L40), [사회 효과 차단](../../../packages/lina-core/src/world/social-effect-state.ts#L127) | | 작성 정체성 | 이름·역할·성격·말투·전기·외형·관심사 | [`AgentProfile`](../../../packages/lina-core/src/agents/types.ts#L3) | [핵심 권위 문구](../../../packages/lina-core/src/agents/persona.ts#L38) | | 검증된 성장 | 근거가 확인된 현재 성향 값 | [`SharedPersonaView`](../../../packages/lina-core/src/world/views.ts#L253), 개인 투영 | [공유 성향 권위 문구](../../../packages/lina-core/src/agents/persona.ts#L53) | | 초기 기질 | 축별 시작값 | [`PersonaDimension.initial`](../../../packages/lina-core/src/agents/persona-schema.ts#L43) | 같은 문구가 초기 기질을 "출발점"으로 규정 | @@ -36,7 +36,7 @@ F1에서 확정하지 않는 것은 배선이다. 개인별 잠금 목록을 담 "고정"과 "성장"은 새 개념이 아니라 기존 두 가지의 조합이다. -`evolution`이 `manual`이면 공유 대상 축 전체가 잠긴다. `adaptive`이면 축별 잠금 목록에 적힌 축만 잠기고 나머지는 근거가 쌓이면 변한다. 판정 순서는 manual이 먼저다([`lockedFor`](../../../packages/lina-core/src/agents/persona-schema.ts#L289)). +`evolution`이 `manual`이면 그 개인의 성장이 전부 막힌다. 공유 축만이 아니라 비공개 축의 LIFE 성장도 거부된다([성장 정책](../../../packages/lina-core/src/world/life-transition.ts#L294)). `adaptive`이면 축별 잠금 목록에 적힌 축만 잠긴다. 나머지 축은 변할 자격이 생길 뿐이고 실제로 변한다는 보장은 아니다. 각 경로가 근거·범위·현재성 검사를 따로 건다. 판정 순서는 manual이 먼저다([`lockedFor`](../../../packages/lina-core/src/agents/persona-schema.ts#L289)). 프롬프트 산문은 강제력이 없다. 성격 문장에 "쉽게 변하지 않는다"라고 적어도 잠기지 않고, "경험에 따라 달라진다"라고 적어도 잠긴 축이 열리지 않는다. 강제는 위 표의 잠금과 권한 층이 한다. @@ -52,9 +52,15 @@ F1에서 확정하지 않는 것은 배선이다. 개인별 잠금 목록을 담 ## 작성 입력과 검증 -작성자가 개인별로 정하는 값은 `evolution`과 축별 잠금 목록 세 개다. 잠금 목록에 적는 id는 대상 세계 정의에 실재하는 축이어야 하고, 없는 id는 거부한다. 참여자 확인은 이미 같은 방식으로 거부한다([참여자 검사](../../../packages/lina-core/src/agents/persona-schema.ts#L310)). +작성자가 개인별로 정하는 값은 `evolution`과 축별 잠금 목록 세 개다. -잠금 목록을 적지 않으면 빈 목록으로 읽는다. 빈 목록은 "아직 안 정함"이 아니라 "이 개인의 공유 축은 모두 성장 가능"이라는 뜻이다. 축 자체를 성장 대상에서 빼려면 잠그는 것이 아니라 공개 허용 목록에서 제외한다. 두 장치의 의미가 다르다. +잠금 id는 어느 세계 정의의 축인지와 함께 읽어야 한다. 축 id는 세계마다 정의되고 전역 이름공간이 없어서([축 정의](../../../packages/lina-core/src/world/life-types.ts#L26)), 한 세계에서 유효한 잠금이 다른 세계에서는 이름만 같은 다른 축을 잠글 수 있다. 그래서 검사는 세계 단위로 한다. 표현 방식은 아래 미해결 항목이고, 그전까지 작성자는 선택 잠금 초안에 어느 세계·정의의 축인지 함께 적고 다른 세계로 옮겨 쓰는 이식 가능한 개인 정책으로 취급하지 않는다. 소유권은 AgentStore에 둔다. + +아래 두 가지는 **작성 경계에 요구하는 규칙이며 현재 구현된 동작이 아니다.** 없는 잠금 id는 거부해야 하지만 지금 파서는 정의를 인자로 받지 않고 그대로 통과시킨다([현재 파서](../../../packages/lina-core/src/world/identity-policy.ts#L67)). 잠금 목록을 생략하면 빈 목록으로 읽어야 하지만 지금은 파싱이 실패한다([목록 파서](../../../packages/lina-core/src/world/life-json.ts#L31)). 참여자 확인은 이미 거부한다([참여자 검사](../../../packages/lina-core/src/agents/persona-schema.ts#L310)). + +빈 잠금 목록은 "아직 안 정함"이 아니라 "추가로 잠근 축이 없다"는 뜻이다. + +**공개 허용 목록으로 성장을 막지 않는다.** 두 장치는 보는 곳이 다르다. 네이티브 개인 성향 해석은 허용 목록으로 대상 축을 고르고 목록 밖 축의 출력을 거부하지만 축별 잠금은 읽지 않는다([selector 구성](../../../packages/lina-runtime/src/persona/native-growth.ts#L51), [출력 검사](../../../packages/lina-core/src/agents/behavior-validation.ts#L275)). 반면 LIFE의 성장 검증·적용과 사회 효과는 `evolution`과 잠금만 보고 허용 목록을 보지 않는다([성장 검증](../../../packages/lina-core/src/world/growth.ts#L40), [전이 적용](../../../packages/lina-core/src/world/life-transition.ts#L294), [사회 효과](../../../packages/lina-core/src/world/social-effect-state.ts#L127)). LIFE 회고에 넘기는 자기 성향에도 허용 목록 필터가 없다([회고 입력](../../../packages/lina-core/src/world/autonomy-views.ts#L221)). 그래서 허용 목록에서 뺀 축도 LIFE 경로로는 계속 변할 수 있다. 비공개이면서 성장하는 축은 정상 조합이다. `source`는 AgentStore의 owner 설정이며 현재는 `reflection` 하나만 쓴다. [`DIMENSION_SOURCES`](../../../packages/lina-core/src/agents/behavior-types.ts#L176)에 `neural`이 선언돼 있지만 [형태만 선언된 후속 대상](../../../packages/lina-core/src/agents/behavior-types.ts#L183)이다. 작성 표면은 [016의 상태 소유권 절](016_neural_preference_contract.md#상태-소유권과-공개-범위)과 함께 F2에서 정한다. @@ -64,7 +70,7 @@ F1에서 확정하지 않는 것은 배선이다. 개인별 잠금 목록을 담 근거는 작성하는 항목이 아니다. 성향이 왜 그 값인지는 해석 receipt와 사건 id가 만든다([성장 근거 검사](../../../packages/lina-core/src/world/growth.ts#L44)). 작성자가 항목마다 근거 문장을 적지 않는다. -공개 범위도 항목별로 적지 않는다. 어떤 축을 공유하는지는 `projection`의 허용 목록이, 무엇을 드러낼지는 그 정책의 공개 항목이 소유한다. 파생은 허용 목록에 있는 축만 schema에 넣는다([필터 지점](../../../packages/lina-core/src/agents/persona-schema.ts#L321)). +공개 범위도 항목별로 적지 않는다. 어떤 축을 공유하는지는 `projection`의 허용 목록이, 무엇을 드러낼지는 그 정책의 공개 항목이 소유한다. 파생은 허용 목록에 있는 축만 schema에 넣는다([필터 지점](../../../packages/lina-core/src/agents/persona-schema.ts#L321)). 허용 목록은 공유·투영 범위와 네이티브 해석의 대상을 정할 뿐 LIFE 전체의 성장 금지 정책을 대신하지 않는다. ## 불완전 입력의 의미 @@ -74,7 +80,7 @@ F1에서 확정하지 않는 것은 배선이다. 개인별 잠금 목록을 담 | --- | --- | --- | | 자료를 아예 주지 않음 | 허용. 참조한 프로필이 없다고 기록하고 전 축을 잠그지 않음 | "정책을 조회하지 않았다". 이 결과는 성장·사회 입력으로 쓰지 않는다 | | 자료는 줬는데 대상 개인이 없음 | **거부** | 자료 오류다. 정책 부재로 접지 않는다 | -| `adaptive`, 잠금 목록 비어 있음 | 허용. 공유 축 전부 성장 가능 | "허용 목록 안에서 전부 성장" | +| `adaptive`, 잠금 목록 비어 있음 | 허용. 추가로 잠근 축이 없음 | "이 개인에게 더 잠글 축은 없다". 변화의 발생을 보장하지는 않는다 | | `manual` | 허용. 잠금 목록과 무관하게 전 축 잠금 | "고정" | | 프로필 revision이 성장 기록 이후 바뀜 | 아래 참조 | 관찰되는 것만 기록한다 | @@ -101,11 +107,11 @@ revision이 바뀐 경우는 현재 관찰되는 것만 적는다. 파생은 호 고정으로 쓴 개인은 `evolution`이 `manual`이다. 네 축이 모두 잠기고 학습이 값을 바꾸지 못한다. -선택 잠금으로 쓴 개인은 `evolution`이 `adaptive`이고 `lockedTraitIds`가 `["warmth"]`다. `warmth`만 잠기고 `curiosity`·`tea`·`trust`는 근거가 쌓이면 변한다. +선택 잠금으로 쓴 개인은 `evolution`이 `adaptive`이고 `lockedTraitIds`가 `["warmth"]`다. `warmth`만 잠기고 `curiosity`·`tea`·`trust`는 변할 자격이 있다. 실제 변화는 각 경로의 근거·범위·현재성 검사를 통과해야 일어난다. 자료를 주지 않으면 네 축 모두 잠기지 않고 참조한 프로필이 없다고 기록된다. 세 결과는 digest가 서로 다르다. 이 픽스처에서 각각 `b7ade1a1`, `87fb41e7`, `aa57cfc0`로 시작한다. 64자 digest의 앞 8자이고 축의 label 하나만 바꿔도 달라지므로 다른 예시의 기대값으로 쓰지 않는다. -대상 개인이 없는 자료를 주면 셋 중 어느 결과도 나오지 않고 파생이 실패한다. 참여자가 아닌 개인을 요청했을 때의 실패와는 메시지가 다르다. +대상 개인이 없는 자료를 주면 파생이 실패한다. 참여자가 아닌 개인을 요청했을 때의 실패와는 메시지가 다르다. 이것은 이 문서가 채택한 규칙이며 별도 PR에서 적용된다. 이 문서가 기준으로 삼은 소스에서는 아직 거부하지 않고, 참조한 프로필이 없다고 기록된 잠금 해제 schema가 나온다. ## 프롬프트 작성 규칙과 착수 판정 @@ -115,13 +121,13 @@ revision이 바뀐 경우는 현재 관찰되는 것만 적는다. 파생은 호 상대별 태도는 축 단위로만 잠근다. 특정 상대에 대해서만 잠그는 표현은 현재 없다. -이 계약으로 **개별 페르소나 프롬프트 작성을 시작할 수 있다.** 작성자는 성격·말투·전기를 산문으로 쓰고, 각 공유 축을 고정으로 둘지 성장으로 둘지 정하고, 성장으로 둔 축의 시작값과 범위를 세계 정의에서 확인하면 된다. +이 계약으로 **개별 페르소나 프롬프트 작성을 시작할 수 있다.** 작성자는 성격·말투·전기를 산문으로 쓰고, 공유 축과 비공개 축을 가리지 않고 각 축을 고정으로 둘지 성장으로 둘지 정하고, 성장으로 둔 축의 시작값과 범위를 세계 정의에서 확인하면 된다. 전제는 남는다. 개인별 선택 잠금을 제품에 저장할 방법이 아직 없으므로, 지금 작성한 선택 잠금은 문서상의 의도로 남고 배선이 끝나야 실제로 적용된다. 그 전까지 제품에서 실효가 있는 선택은 `manual`과 `adaptive` 둘뿐이다. ## 기각한 대안 -개인별 잠금을 `LifeDefinition`에 참여자별로 넣는 안은 기각한다. 페르소나 정책을 World로 옮겨 D18과 어긋나고, 정의가 세계마다 있으므로 한 개인이 두 세계에서 서로 다른 잠금을 갖게 된다. +개인별 잠금을 `LifeDefinition`에 참여자별로 넣는 안은 기각한다. 페르소나 정책의 소유권을 World로 옮겨 D18과 어긋나기 때문이다. 기각한 것은 소유권이지 범위가 아니다. AgentStore가 소유하면서 세계 범위를 갖는 정책은 아래 미해결 항목의 후보로 남아 있다. `PersonaSchema`를 직접 작성하는 안은 기각한다. schema는 파생물이고 digest로 묶여 있어서, 직접 쓰면 label과 범위가 세계 축과 갈라진다. @@ -137,6 +143,7 @@ revision이 바뀐 경우는 현재 관찰되는 것만 적는다. 파생은 호 | 상대별 태도 잠금 | 축 단위만 수용. 상대별 잠금은 표현 불가 | | `manual`에 잠금 목록이 함께 있을 때 | 잉여로 허용. 모순으로 거부할지는 미정 | | revision이 바뀐 schema의 처리 | 미정. 자동 파생 여부와 현재·재생 적격성 판정이 모두 코드에 없다 | +| 잠금 id의 범위 | 미정. 안정적인 페르소나 dimension id와 세계별 대응을 둘지, 잠금을 세계 범위로 선언할지. 그전까지는 위의 잠정 규칙을 따른다 | 이 항목들의 결정과 구현은 후속 작업에서 다룬다. From 97e7075a8251968e6f94b8016afc4a959f6c00df Mon Sep 17 00:00:00 2001 From: thisisjun786 <259586770+thisisjun786@users.noreply.github.com> Date: Mon, 14 Sep 2026 03:45:35 +0900 Subject: [PATCH 3/5] =?UTF-8?q?docs:=20=EC=9E=91=EC=84=B1=20=EC=A0=95?= =?UTF-8?q?=EC=B2=B4=EC=84=B1=EC=9D=98=20=EC=86=8C=EC=9C=A0=EC=9E=90?= =?UTF-8?q?=EB=A5=BC=20=EC=84=B8=20=EA=B3=B3=EC=9C=BC=EB=A1=9C=20=EB=B0=94?= =?UTF-8?q?=EB=A1=9C=EC=9E=A1=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 층 표의 작성 정체성 행이 AgentProfile만 소유자로 적었다. 실제로 corePrompt는 AgentProfile 필드와 대화 방식·예시, 확정된 온보딩 장을 한 블록에 렌더링한 뒤 그 전체를 완전한 작성 정체성이라고 선언한다. 대화 설정은 ConversationStore에서, 확정 장은 OnboardingStore에서 온다. 온보딩 장은 가치·기질·관심·관계·표현을 담으므로, 빠뜨리면 그 항목들이 우선순위 계약 밖에 남아 나중에 성장과 충돌할 때 해결 규칙이 없다. 층 안의 순서도 적었다. AgentProfile 필드가 안정된 기준점이고, 확정 장은 덧붙인 작성 설정이며 겪은 일이 아니고, 대화 예시는 허구의 문체 참고라 현재 요청과 정한 말투보다 뒤에 온다. Refs: JUN-28 --- docs/plans/platform/018_persona_authoring_contract.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/plans/platform/018_persona_authoring_contract.md b/docs/plans/platform/018_persona_authoring_contract.md index 9826f49..c56e469 100644 --- a/docs/plans/platform/018_persona_authoring_contract.md +++ b/docs/plans/platform/018_persona_authoring_contract.md @@ -17,13 +17,17 @@ F1에서 확정하지 않는 것은 배선이다. 개인별 잠금 목록을 담 | 층 | 내용 | 현재 소유 타입 | 근거 | | --- | --- | --- | --- | | 잠금과 권한 | `evolution`과 축별 잠금이 성장을 막고, 공개 허용 목록은 공유·투영 범위를 정한다. 역할이 다르다 | [`IdentityProfilePolicy`](../../../packages/lina-core/src/world/life-types.ts#L121), [`ProjectionPolicy`](../../../packages/lina-core/src/world/life-types.ts#L38) | [manual 단락](../../../packages/lina-core/src/agents/persona.ts#L96), [성장 차단](../../../packages/lina-core/src/world/growth.ts#L40), [사회 효과 차단](../../../packages/lina-core/src/world/social-effect-state.ts#L127) | -| 작성 정체성 | 이름·역할·성격·말투·전기·외형·관심사 | [`AgentProfile`](../../../packages/lina-core/src/agents/types.ts#L3) | [핵심 권위 문구](../../../packages/lina-core/src/agents/persona.ts#L38) | +| 작성 정체성 | 이름·역할·성격·말투·전기·외형·관심사, 확정된 온보딩 장(가치·기질·관심·관계·표현), 대화 방식과 예시 | [`AgentProfile`](../../../packages/lina-core/src/agents/types.ts#L3), [확정 장](../../../packages/lina-core/src/onboarding/types.ts#L3), [대화 설정](../../../packages/lina-core/src/agents/conversation.ts#L26) | [핵심 권위 문구](../../../packages/lina-core/src/agents/persona.ts#L38), [세 출처를 함께 렌더링](../../../packages/lina-core/src/agents/persona.ts#L167) | | 검증된 성장 | 근거가 확인된 현재 성향 값 | [`SharedPersonaView`](../../../packages/lina-core/src/world/views.ts#L253), 개인 투영 | [공유 성향 권위 문구](../../../packages/lina-core/src/agents/persona.ts#L53) | | 초기 기질 | 축별 시작값 | [`PersonaDimension.initial`](../../../packages/lina-core/src/agents/persona-schema.ts#L43) | 같은 문구가 초기 기질을 "출발점"으로 규정 | | 일시 상태 | 기분과 최근 관심·선호·관계 메모 | [`Dynamics`](../../../packages/lina-core/src/agents/types.ts#L19) | [변동 맥락 문구](../../../packages/lina-core/src/agents/persona.ts#L48) | 검증된 성장은 **자기가 올라간 축에서만** 초기 기질을 대체한다. 작성 정체성의 성격 문장은 숫자로 대체되지 않는다. 두 가지가 모두 "작성한 것"이지만 성격은 표현의 기준이고 초기 기질은 축의 시작값이다. +작성 정체성은 한 곳에서 오지 않는다. `corePrompt`는 `AgentProfile` 필드와 대화 방식·예시, 확정된 온보딩 장을 한 블록에 렌더링하고 그 전체를 완전한 작성 정체성이라고 선언한다([조립 지점](../../../packages/lina-core/src/agents/persona.ts#L167)). 대화 설정은 ConversationStore에서, 확정 장은 OnboardingStore에서 온다([훅 배선](../../../packages/lina-runtime/src/persona/hooks.ts#L65), [확정 장 공급](../../../packages/lina-runtime/src/fleet/manager.ts#L355)). 셋 다 작성물이고 학습이 덮어쓰지 못한다. + +층 안의 순서는 이렇다. `AgentProfile` 필드가 안정된 기준점이다. 확정 장은 덧붙인 작성 설정이며 겪은 일이 아니다([표시 문구](../../../packages/lina-core/src/agents/persona.ts#L186)). 대화 예시는 허구의 문체 참고여서 현재 요청과 정한 말투보다 뒤에 온다([예시 표시](../../../packages/lina-core/src/agents/persona.ts#L160)). + ## 명시적 대화 선호의 범위 사용자가 직접 말한 대화 선호는 위 순서에 끼워 넣지 않는다. 적용 범위가 다르기 때문이다. From 6f984b086c45a07d04c0470f994d66c672182e54 Mon Sep 17 00:00:00 2001 From: thisisjun786 <259586770+thisisjun786@users.noreply.github.com> Date: Mon, 14 Sep 2026 03:52:13 +0900 Subject: [PATCH 4/5] =?UTF-8?q?docs:=20=EC=98=88=EC=8B=9C=20digest=20?= =?UTF-8?q?=EB=8C=80=EC=9D=91=EA=B3=BC=20=EC=9D=BC=EC=8B=9C=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EA=B2=BD=EB=A1=9C=EB=A5=BC=20=EB=B0=94=EB=A1=9C?= =?UTF-8?q?=EC=9E=A1=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 대표 예시가 고정·선택 잠금·자료 미제공 순서로 설명해 놓고 digest는 자료 미제공·고정·선택 잠금 순서로 적었다. 세 값이 모두 어긋나 있어서 예시를 따라간 작성자가 각 정책에 틀린 digest를 연결하게 된다. 순서에 기대지 않도록 각 값에 어느 경우인지 붙여 적었다. 실측은 고정 87fb41e7, 선택 잠금 aa57cfc0, 자료 미제공 b7ade1a1이다. 일시 상태 층이 Dynamics만 소유자로 적었다. 네이티브 모드에서는 Dynamics를 비운 채로 넘기고 EngineState의 비공개 개인 맥락을 대신 붙인다. 그 맥락은 대상이 사용자가 아닌 적격 관심·선호·기분·태도 기록만 담고, 지원된 항목은 표현에만 쓰며 잠정 항목은 확정된 성향으로 올리지 않는다. manual이면 붙지 않는다. 제품이 실제로 쓰는 경로라 층 모델에 넣었다. 온보딩 장 목록에서 빠져 있던 정체를 채웠고, 층 순서가 런타임 문구로 전부 규정되는 것은 아니라 이 문서가 채택한 계약임을 밝혔다. Refs: JUN-28 --- docs/plans/platform/018_persona_authoring_contract.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/plans/platform/018_persona_authoring_contract.md b/docs/plans/platform/018_persona_authoring_contract.md index c56e469..1de4973 100644 --- a/docs/plans/platform/018_persona_authoring_contract.md +++ b/docs/plans/platform/018_persona_authoring_contract.md @@ -12,20 +12,22 @@ F1에서 확정하지 않는 것은 배선이다. 개인별 잠금 목록을 담 ## 층 모델과 우선순위 -한 개인의 현재 행동은 여러 층이 겹쳐 만들어진다. 위 행이 아래 행을 이긴다. 아래 층은 위 층을 다시 쓰지 못한다. +한 개인의 현재 행동은 여러 층이 겹쳐 만들어진다. 위 행이 아래 행을 이긴다. 아래 층은 위 층을 다시 쓰지 못한다. 런타임 문구가 직접 규정하는 것은 인접한 일부 관계이고, 나머지 순서는 이 문서가 채택한 계약이다. | 층 | 내용 | 현재 소유 타입 | 근거 | | --- | --- | --- | --- | | 잠금과 권한 | `evolution`과 축별 잠금이 성장을 막고, 공개 허용 목록은 공유·투영 범위를 정한다. 역할이 다르다 | [`IdentityProfilePolicy`](../../../packages/lina-core/src/world/life-types.ts#L121), [`ProjectionPolicy`](../../../packages/lina-core/src/world/life-types.ts#L38) | [manual 단락](../../../packages/lina-core/src/agents/persona.ts#L96), [성장 차단](../../../packages/lina-core/src/world/growth.ts#L40), [사회 효과 차단](../../../packages/lina-core/src/world/social-effect-state.ts#L127) | -| 작성 정체성 | 이름·역할·성격·말투·전기·외형·관심사, 확정된 온보딩 장(가치·기질·관심·관계·표현), 대화 방식과 예시 | [`AgentProfile`](../../../packages/lina-core/src/agents/types.ts#L3), [확정 장](../../../packages/lina-core/src/onboarding/types.ts#L3), [대화 설정](../../../packages/lina-core/src/agents/conversation.ts#L26) | [핵심 권위 문구](../../../packages/lina-core/src/agents/persona.ts#L38), [세 출처를 함께 렌더링](../../../packages/lina-core/src/agents/persona.ts#L167) | +| 작성 정체성 | 이름·역할·성격·말투·전기·외형·관심사, 확정된 온보딩 장(정체·가치·기질·관심·관계·표현), 대화 방식과 예시 | [`AgentProfile`](../../../packages/lina-core/src/agents/types.ts#L3), [확정 장](../../../packages/lina-core/src/onboarding/types.ts#L3), [대화 설정](../../../packages/lina-core/src/agents/conversation.ts#L26) | [핵심 권위 문구](../../../packages/lina-core/src/agents/persona.ts#L38), [세 출처를 함께 렌더링](../../../packages/lina-core/src/agents/persona.ts#L167) | | 검증된 성장 | 근거가 확인된 현재 성향 값 | [`SharedPersonaView`](../../../packages/lina-core/src/world/views.ts#L253), 개인 투영 | [공유 성향 권위 문구](../../../packages/lina-core/src/agents/persona.ts#L53) | | 초기 기질 | 축별 시작값 | [`PersonaDimension.initial`](../../../packages/lina-core/src/agents/persona-schema.ts#L43) | 같은 문구가 초기 기질을 "출발점"으로 규정 | -| 일시 상태 | 기분과 최근 관심·선호·관계 메모 | [`Dynamics`](../../../packages/lina-core/src/agents/types.ts#L19) | [변동 맥락 문구](../../../packages/lina-core/src/agents/persona.ts#L48) | +| 일시 상태 | 기분과 최근 관심·선호·관계 메모. 경로가 둘이다 | [`Dynamics`](../../../packages/lina-core/src/agents/types.ts#L19), [EngineState 비공개 맥락](../../../packages/lina-runtime/src/persona/native-context.ts#L14) | [변동 맥락 문구](../../../packages/lina-core/src/agents/persona.ts#L48), [비공개 맥락 문구](../../../packages/lina-runtime/src/persona/native-context.ts#L10) | 검증된 성장은 **자기가 올라간 축에서만** 초기 기질을 대체한다. 작성 정체성의 성격 문장은 숫자로 대체되지 않는다. 두 가지가 모두 "작성한 것"이지만 성격은 표현의 기준이고 초기 기질은 축의 시작값이다. 작성 정체성은 한 곳에서 오지 않는다. `corePrompt`는 `AgentProfile` 필드와 대화 방식·예시, 확정된 온보딩 장을 한 블록에 렌더링하고 그 전체를 완전한 작성 정체성이라고 선언한다([조립 지점](../../../packages/lina-core/src/agents/persona.ts#L167)). 대화 설정은 ConversationStore에서, 확정 장은 OnboardingStore에서 온다([훅 배선](../../../packages/lina-runtime/src/persona/hooks.ts#L65), [확정 장 공급](../../../packages/lina-runtime/src/fleet/manager.ts#L355)). 셋 다 작성물이고 학습이 덮어쓰지 못한다. +일시 상태도 한 곳에서 오지 않는다. 네이티브 모드에서는 `Dynamics`를 비운 채로 넘기고 EngineState의 비공개 개인 맥락을 대신 붙인다([빈 Dynamics](../../../packages/lina-runtime/src/persona/hooks.ts#L73), [맥락 구성](../../../packages/lina-runtime/src/persona/hooks.ts#L66), [상태 공급](../../../packages/lina-runtime/src/session-app.ts#L408)). 그 맥락에는 대상이 사용자가 아닌 적격 관심·선호·기분·태도 기록만 들어간다([선별 기준](../../../packages/lina-runtime/src/persona/native-context.ts#L38)). 지원된 항목은 표현에만 쓰고 잠정 항목은 확정된 성향으로 올리지 않으며, 공유 LIFE 행동이 아니고 권한을 주지 않는다([맥락 헤더](../../../packages/lina-runtime/src/persona/native-context.ts#L10)). `manual`이면 이 맥락도 붙지 않는다([manual 차단](../../../packages/lina-runtime/src/persona/native-context.ts#L19)). + 층 안의 순서는 이렇다. `AgentProfile` 필드가 안정된 기준점이다. 확정 장은 덧붙인 작성 설정이며 겪은 일이 아니다([표시 문구](../../../packages/lina-core/src/agents/persona.ts#L186)). 대화 예시는 허구의 문체 참고여서 현재 요청과 정한 말투보다 뒤에 온다([예시 표시](../../../packages/lina-core/src/agents/persona.ts#L160)). ## 명시적 대화 선호의 범위 @@ -113,7 +115,7 @@ revision이 바뀐 경우는 현재 관찰되는 것만 적는다. 파생은 호 선택 잠금으로 쓴 개인은 `evolution`이 `adaptive`이고 `lockedTraitIds`가 `["warmth"]`다. `warmth`만 잠기고 `curiosity`·`tea`·`trust`는 변할 자격이 있다. 실제 변화는 각 경로의 근거·범위·현재성 검사를 통과해야 일어난다. -자료를 주지 않으면 네 축 모두 잠기지 않고 참조한 프로필이 없다고 기록된다. 세 결과는 digest가 서로 다르다. 이 픽스처에서 각각 `b7ade1a1`, `87fb41e7`, `aa57cfc0`로 시작한다. 64자 digest의 앞 8자이고 축의 label 하나만 바꿔도 달라지므로 다른 예시의 기대값으로 쓰지 않는다. +자료를 주지 않으면 네 축 모두 잠기지 않고 참조한 프로필이 없다고 기록된다. 세 결과는 digest가 서로 다르다. 이 픽스처에서 고정은 `87fb41e7`, 선택 잠금은 `aa57cfc0`, 자료 미제공은 `b7ade1a1`로 시작한다. 64자 digest의 앞 8자이고 축의 label 하나만 바꿔도 달라지므로 다른 예시의 기대값으로 쓰지 않는다. 대상 개인이 없는 자료를 주면 파생이 실패한다. 참여자가 아닌 개인을 요청했을 때의 실패와는 메시지가 다르다. 이것은 이 문서가 채택한 규칙이며 별도 PR에서 적용된다. 이 문서가 기준으로 삼은 소스에서는 아직 거부하지 않고, 참조한 프로필이 없다고 기록된 잠금 해제 schema가 나온다. From cb85240b67d8b36d730171e0573c5cc5da81fd28 Mon Sep 17 00:00:00 2001 From: thisisjun786 <259586770+thisisjun786@users.noreply.github.com> Date: Mon, 14 Sep 2026 03:56:31 +0900 Subject: [PATCH 5/5] =?UTF-8?q?docs:=20=EB=8C=80=ED=99=94=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=EC=9D=98=20=EC=B6=9C=EC=B2=98=EB=A5=BC=20=EB=91=90=20?= =?UTF-8?q?=EA=B0=88=EB=9E=98=EB=A1=9C=20=EA=B5=AC=EB=B6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 저장된 대화 설정이 없으면 프리셋 기본값이 쓰인다. installPersona는 ConversationStore의 revision이 0이면 그 값을 버리고 data/personas/conversations.json의 기본값을 읽는다. 프리셋으로 만든 에이전트는 저장된 행이 없으므로 기본값 쪽이 프롬프트에 들어간다. 계약이 두 경로를 모두 ConversationStore가 공급하는 것처럼 적어서, 작성자가 대화 방식을 바꾸려 할 때 엉뚱한 곳을 고칠 수 있었다. 두 출처를 나눠 적고 어느 쪽을 고치는지 먼저 확인하라고 명시했다. Refs: JUN-28 --- docs/plans/platform/018_persona_authoring_contract.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/plans/platform/018_persona_authoring_contract.md b/docs/plans/platform/018_persona_authoring_contract.md index 1de4973..18eba90 100644 --- a/docs/plans/platform/018_persona_authoring_contract.md +++ b/docs/plans/platform/018_persona_authoring_contract.md @@ -17,14 +17,16 @@ F1에서 확정하지 않는 것은 배선이다. 개인별 잠금 목록을 담 | 층 | 내용 | 현재 소유 타입 | 근거 | | --- | --- | --- | --- | | 잠금과 권한 | `evolution`과 축별 잠금이 성장을 막고, 공개 허용 목록은 공유·투영 범위를 정한다. 역할이 다르다 | [`IdentityProfilePolicy`](../../../packages/lina-core/src/world/life-types.ts#L121), [`ProjectionPolicy`](../../../packages/lina-core/src/world/life-types.ts#L38) | [manual 단락](../../../packages/lina-core/src/agents/persona.ts#L96), [성장 차단](../../../packages/lina-core/src/world/growth.ts#L40), [사회 효과 차단](../../../packages/lina-core/src/world/social-effect-state.ts#L127) | -| 작성 정체성 | 이름·역할·성격·말투·전기·외형·관심사, 확정된 온보딩 장(정체·가치·기질·관심·관계·표현), 대화 방식과 예시 | [`AgentProfile`](../../../packages/lina-core/src/agents/types.ts#L3), [확정 장](../../../packages/lina-core/src/onboarding/types.ts#L3), [대화 설정](../../../packages/lina-core/src/agents/conversation.ts#L26) | [핵심 권위 문구](../../../packages/lina-core/src/agents/persona.ts#L38), [세 출처를 함께 렌더링](../../../packages/lina-core/src/agents/persona.ts#L167) | +| 작성 정체성 | 이름·역할·성격·말투·전기·외형·관심사, 확정된 온보딩 장(정체·가치·기질·관심·관계·표현), 대화 방식과 예시 | [`AgentProfile`](../../../packages/lina-core/src/agents/types.ts#L3), [확정 장](../../../packages/lina-core/src/onboarding/types.ts#L3), [저장된 대화 설정](../../../packages/lina-core/src/agents/conversation.ts#L26), [프리셋 기본 대화 설정](../../../packages/lina-runtime/src/persona/conversation.ts#L13) | [핵심 권위 문구](../../../packages/lina-core/src/agents/persona.ts#L38), [세 출처를 함께 렌더링](../../../packages/lina-core/src/agents/persona.ts#L167) | | 검증된 성장 | 근거가 확인된 현재 성향 값 | [`SharedPersonaView`](../../../packages/lina-core/src/world/views.ts#L253), 개인 투영 | [공유 성향 권위 문구](../../../packages/lina-core/src/agents/persona.ts#L53) | | 초기 기질 | 축별 시작값 | [`PersonaDimension.initial`](../../../packages/lina-core/src/agents/persona-schema.ts#L43) | 같은 문구가 초기 기질을 "출발점"으로 규정 | | 일시 상태 | 기분과 최근 관심·선호·관계 메모. 경로가 둘이다 | [`Dynamics`](../../../packages/lina-core/src/agents/types.ts#L19), [EngineState 비공개 맥락](../../../packages/lina-runtime/src/persona/native-context.ts#L14) | [변동 맥락 문구](../../../packages/lina-core/src/agents/persona.ts#L48), [비공개 맥락 문구](../../../packages/lina-runtime/src/persona/native-context.ts#L10) | 검증된 성장은 **자기가 올라간 축에서만** 초기 기질을 대체한다. 작성 정체성의 성격 문장은 숫자로 대체되지 않는다. 두 가지가 모두 "작성한 것"이지만 성격은 표현의 기준이고 초기 기질은 축의 시작값이다. -작성 정체성은 한 곳에서 오지 않는다. `corePrompt`는 `AgentProfile` 필드와 대화 방식·예시, 확정된 온보딩 장을 한 블록에 렌더링하고 그 전체를 완전한 작성 정체성이라고 선언한다([조립 지점](../../../packages/lina-core/src/agents/persona.ts#L167)). 대화 설정은 ConversationStore에서, 확정 장은 OnboardingStore에서 온다([훅 배선](../../../packages/lina-runtime/src/persona/hooks.ts#L65), [확정 장 공급](../../../packages/lina-runtime/src/fleet/manager.ts#L355)). 셋 다 작성물이고 학습이 덮어쓰지 못한다. +작성 정체성은 한 곳에서 오지 않는다. `corePrompt`는 `AgentProfile` 필드와 대화 방식·예시, 확정된 온보딩 장을 한 블록에 렌더링하고 그 전체를 완전한 작성 정체성이라고 선언한다([조립 지점](../../../packages/lina-core/src/agents/persona.ts#L167)). + +대화 방식과 예시의 출처는 둘이다. 그 에이전트의 저장된 설정이 있으면 ConversationStore의 값을 쓰고, 없으면 `data/personas/conversations.json`의 프리셋 기본값을 쓴다([선택 지점](../../../packages/lina-runtime/src/persona/hooks.ts#L54), [기본값 읽기](../../../packages/lina-runtime/src/persona/conversation.ts#L13)). 프리셋으로 만든 에이전트는 저장된 행이 없으므로 기본값 쪽이 프롬프트에 들어간다. 작성자가 대화 방식을 바꾸려면 어느 쪽을 고치는지 먼저 확인해야 한다. 확정 장은 OnboardingStore에서 온다([확정 장 공급](../../../packages/lina-runtime/src/fleet/manager.ts#L355)). 이들 모두 작성물이고 학습이 덮어쓰지 못한다. 일시 상태도 한 곳에서 오지 않는다. 네이티브 모드에서는 `Dynamics`를 비운 채로 넘기고 EngineState의 비공개 개인 맥락을 대신 붙인다([빈 Dynamics](../../../packages/lina-runtime/src/persona/hooks.ts#L73), [맥락 구성](../../../packages/lina-runtime/src/persona/hooks.ts#L66), [상태 공급](../../../packages/lina-runtime/src/session-app.ts#L408)). 그 맥락에는 대상이 사용자가 아닌 적격 관심·선호·기분·태도 기록만 들어간다([선별 기준](../../../packages/lina-runtime/src/persona/native-context.ts#L38)). 지원된 항목은 표현에만 쓰고 잠정 항목은 확정된 성향으로 올리지 않으며, 공유 LIFE 행동이 아니고 권한을 주지 않는다([맥락 헤더](../../../packages/lina-runtime/src/persona/native-context.ts#L10)). `manual`이면 이 맥락도 붙지 않는다([manual 차단](../../../packages/lina-runtime/src/persona/native-context.ts#L19)).