Repository navigation
feat(character): bind startup roles, conversations and accepted Work identity - #162
Merged
Merged
Conversation
Manual Retry and Resume could lose the original role name or accept a caller override. Read it from the Operation's accepted Control evidence, including repeated and automatic retries, without loading the active character pack. New accepted amendments retain their own role identity. For legacy standalone Work, use the existing persisted request projection; only an absent field selects the historical name. Reject invalid identity before dispatch or writer-lease acquisition. Reuse Runtime's existing metadata protection to prevent Provider events and results from replacing that fact. Cover the handler-to-native request boundary, immutable legacy plans, amendments, invalid persisted values, provider projection protection, and AUIP repair. Validation: full Python CI suite (421 files): 5073 passed, 5 skipped, 5 xfailed; both shard commands exited 0. No dependencies installed or live model calls.
Show a role label only on foreign conversations. Deleting the last conversation for the startup character leaves an empty chat and clears its transient context; startup with no matching conversation still creates one. Keep selection errors outside chat history and preserve artifact-view behavior. Make the name-only character's mystery default describe visible evidence rather than assign a personality habit. Kurisu's original text and snapshot remain intact. Document these defaults, fail-without-overwrite session saving, and accepted Work recovery through persistent Cooperative context. Validate actual UI callbacks, component rendering, and role prompt snapshots. Validation: 230 Electron tests and build passed; full Python suite: 5073 passed, 5 skipped, 5 xfailed, both shards exited 0. Prompt fixture unchanged. The official Electron smoke was not run because an existing user backend holds port 17777; that application was left running.
Independent Work starts without a conversation role. Retry and Resume used to invent the historical Kurisu name and consequently change the meaning of "yourself" in the execution prompt. Preserve absence across intake, amendments, same-Operation attempts, and Resume, including stale Runtime metadata. Restore accepted conversation identity only from the Operation's Control effect. Remove unsupported Provider-result inheritance and redundant repair-time copying. Keep the legacy admission default in WorkControl. Missing adapter identity now uses the existing startup-name renderer without adding role-reference context; explicit accepted names never consult the startup pack. Control recovery still retains the role-reference context present on initial execution, correcting the previously lost context. This is a model-visible repair relative to origin/main; independent Kurisu tasks gain no such context. Validation includes native request assembly for four adapters, Kurisu/Mira independent Work, accepted-role recovery, immutable legacy plans, caller and Provider projection stripping, and amended automatic repair. The OpenClaw Resume prompt test supplies a synthetic restored Session in plan mode; it does not claim to repair the existing workspace/Session recovery integration. All 73 focused tests pass. Full Python CI suite (421 files): 5077 passed, 5 skipped, 5 existing xfailed; both shard commands exited 0. The 155-entry prompt snapshot check passes without fixture changes. Ruff and diff checks pass.
Deleting a chat with no detailed backend error incorrectly reported a switching failure. Let the existing selection helper accept an action-specific fallback, preserve nonempty backend and transport details, and retain chat state on failure. Validation: actual callback tests cover missing/empty reasons and transport rejections; all 239 Electron tests and the build pass. The official model-less desktop checks plus isolated role-selection/deletion checks pass 15/15, including no new or foreign session after deleting the last owned conversation. The test Electron and backend exit cleanly; no model requests were sent.
This was referenced Oct 7, 2026
Lucas1479
added a commit
that referenced
this pull request
Oct 8, 2026
…pts (#160) ## What and why Focus validation and task-reference lookup are non-speaking control queries, but the legacy single-prompt API could replace their instructions with a character persona on Gemini/Bedrock and failed to dispatch local/hybrid requests. Route both callers through the existing messages API and remove the unused legacy query interface. Merge order: #160 → #161 → #162. This first slice targets `main` at `e56faa1`. After merging each predecessor, rebase/retarget its dependent PR onto main as needed, especially after squash merges. Linked Issue: not required for this control-query bug fix. ## Change class - [x] Routine fix, documentation, test, maintenance, or presentation-only UI - [ ] Product-semantic or public-contract change discussed in the linked Issue - [ ] Isolated, default-off experiment Owning layer: control-query construction and the shared LLM messages interface. This does not change chat persona generation or execution authority. User-visible effects: - Task lookup receives neutral instructions at temperature 0 instead of persona instructions at 0.7. Candidate bounds and selection validation remain unchanged. - Focus validation keeps its narrow SET/CLEAR/NONE contract and unavailable result on failure. - Task-lookup infrastructure failures reach the existing `reason="error"` path and generic unresolved-task response instead of being mistaken for an ambiguous selection. - Both callers request a 10-second budget and 900 output tokens. Compatibility: internal legacy API and unused prompt constants removed; in-tree tests and diagnostic probes use the supported messages API. No persisted-state migration. Known limitation: Gemini's shared messages adapter does not currently enforce the supplied timeout. This PR intentionally does not alter all Gemini calls, including main chat, or promise a ten-second wall-clock bound. ## Evidence The relevant control suites (`test_focus_policy.py`, focus/handoff/acceptance suites, `test_task_lookup.py`, and `test_llm_message_query_backends.py`) passed in the final stacked validation at `1dc92d8`. ```powershell uv run --locked --no-sync python -X utf8 tools/run_tests.py --shard-count 2 --shard-index 0 uv run --locked --no-sync python -X utf8 tools/run_tests.py --shard-count 2 --shard-index 1 ``` That combined stack run covered 421 files: **5077 passed, 5 skipped, 5 existing xfailed**, both commands exited 0. This is combined-stack evidence, not a separate full-suite claim for this intermediate head; this PR's CI will validate its own head. No dependency install or live model calls. - [x] Relevant Python tests pass in the validated stack - [x] CPU/model-less baseline remains supported - [x] In-tree probes and tests are updated - Electron build, screenshots and dependency audit: not applicable to this slice ## Final check - [x] One coherent problem, no unrelated cleanup - [x] No new speculative API, fallback or compatibility path - [x] No secrets, local state, model weights, voice material or restricted assets included - [x] Third-party notices and provenance preserved
Matching template variables cannot stop a character file from reversing a Host execution or verification conclusion. Keep 93 fact/status templates and their reviewed Kurisu variants in the Host catalog. Reject explicit role-file overrides of those keys, including for Kurisu. Only 14 VN story-commentary lines remain role-configurable; the profile no longer stores resolved Host fact templates. Preserve the 107 original Kurisu outputs and the existing prompt fixtures. Exercise hostile persona instructions and simulated model output against the existing tool/candidate/ref, stance/version and receipt boundaries. These are deterministic authority regressions, not live-model semantic guarantees. Validation: 313 phrase/loader/startup/snapshot tests and 45 persona boundary tests pass. Full Python suite: 421 files, 5248 passed, 5 skipped, 5 existing xfailed; both shard commands exit 0. All tracked Python paths pass configured Ruff checks.
The current character could not open foreign conversations but could rename or delete them. Reuse persisted ownership validation in both request handlers before changing files, history, selection, project bindings or projections. Preserve generic internal store cleanup and same-role/legacy ownership behavior. Disable foreign rename/delete controls with restart guidance. Report rename failures separately from chat history; successful rename only applies list data. Clarify that character configuration/storage exists but role-management GUI, per-role RAG management and automatic voice/asset binding do not. Validation: 145 targeted backend tests, 247 Electron tests, build, and the full Python suite pass. Model-less desktop checks pass 19/19, including real foreign mutation refusal and same-role rename API/reload. The native double-click rename dialog probe timed out and is documented separately, not counted as passing. No live model calls, dependency installation, or real conversation data.
Lucas1479
added a commit
that referenced
this pull request
Oct 8, 2026
…tput (#161) ## What and why Character names and persona text are duplicated across Chat, AUIP, browser and VN request assembly. Move those values behind one prompt renderer and the packaged `characters/kurisu.toml` resource while keeping the existing Kurisu model inputs byte-identical. Base: `main`; predecessor #160 has been squash-merged. Next: #162. Merge commit `540b983` synchronizes that ancestry without changing any source file from `43ef7f8`. Rebase/retarget #162 after this PR is merged, especially after a squash merge. Linked Issue: not required for this behavior-preserving internal refactor. ## Change class - [x] Routine fix, documentation, test, maintenance, or presentation-only UI - [ ] Product-semantic or public-contract change discussed in the linked Issue - [ ] Isolated, default-off experiment Owning layer: character prompt data and request rendering. Host protocols, verification, task authority and system/user message boundaries remain owned by their existing components. User-visible effect: **none for this slice**. Startup selection, conversation ownership, RAG isolation, Host phrase extraction and persona-editor propagation belong to the next PR. Compatibility: no persisted-state migration or new startup setting here. Remove prompt copies and the unused local CLI implementation after checking for production callers. Add package-data and source-release inclusion for the new `characters/` directory. Dependencies are unchanged. ## Evidence - A subprocess harness assembles **155 actual production prompt surfaces** with synthetic configuration and external I/O blocked. - The pre-migration fixture was independently reproduced on untouched `origin/main` (`e56faa1`); **155/155 byte-identical**. - Independent audit of this refactor head (`3fd4bcf`) also found **155/155 byte-identical**, with no exception and no fixture relaxation. - Snapshot/module tests are `tests/test_character_prompt_snapshots.py` and `tests/test_character_prompt_module.py`. - The final combined stack at `1dc92d8` passed the full two-shard Python runner (421 files, 5077 passed, 5 skipped, 5 existing xfailed). That later slice deliberately changes warmup; it is not part of this PR. This PR's CI validates the intermediate head separately. ```powershell uv run --locked --no-sync python -m pytest tests/test_character_prompt_module.py tests/test_character_prompt_snapshots.py -q ``` - [x] Relevant Python tests and production-boundary snapshots pass - [x] CPU/model-less baseline remains supported - [x] Packaging/source-release policy and prompt documentation updated - Electron screenshots/build and dependency audit: not applicable to this slice Additional per-branch validation after the unused-import cleanup: Ruff passed for all tracked Python paths with repository exclusions, and `python -m pytest tests/test_provider_prompt_routing.py -q` passed **2/2** on each PR branch. New GitHub checks are running. ## Final check - [x] One coherent problem, no unrelated cleanup - [x] Reuses one renderer without speculative execution or authority changes - [x] No secrets, local state, model weights, voice material or restricted assets included - [x] Third-party notices and provenance preserved
Lucas1479
marked this pull request as ready for review
October 8, 2026 04:39
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
A second character must not inherit Kurisu's conversation history, reference corpus or accepted-task identity. Pin the prompt character at backend startup, bind each conversation to its owner, and preserve the accepted conversation identity across Work replay and recovery. Keep retained Projects, Work and artifacts shared through their existing references and permissions.
Base:
main. Prerequisites #160 and #161 are merged. This is the final integration slice; the control-query fix and byte-preserving extraction were reviewed separately.Linked Issue: #163. The startup character, conversation ownership, Work sharing and compatibility contract is recorded there.
Closes #163.
Change class
Owning layers: startup character loading; Host-owned conversation and accepted Work facts; prompt/phrase presentation. No new execution permission or shared-artifact authority.
Resulting behavior and compatibility
AMADEUS_CHARACTER_IDdefaults tokurisuand uses existing setting persistence. The backend fixes the character at startup; changing it or its prompt file requires restart. There is no hot switch, character list, new/import/delete-pack GUI, startup-role selector, or per-character persona editor. The existing GUI editor remains Kurisu's Japanese override only. New roles still require a manual TOML file and startup setting. Voice and visual resources are not automatically selected.kurisu. Only verified, model-facing copies render the presentation identity.Deliberate model-visible changes
Kurisu retains 154/155 pre-migration prompt surfaces byte-for-byte. The declared exception is llama warmup using the real character prefix; the neutral AUIP skill-trigger wording is checked separately. Control Work recovery now retains the role-reference paragraph already present on initial execution, where the old code lost it. Independent Work receives no such paragraph. Original snapshot fixtures are unchanged.
Evidence
Validation covers the boundary fixes committed as
8cb88cband1221e93. Baseline-sync merges1dcf4d1and4488a47preserve exactly the same file tree. For4488a47, main at2d1f692was verified tree-identical to the already-integrated #161 head540b983; recording its squash ancestry resolves all 13 conflicts without changing source, tests, fixtures or documentation. The existing validation therefore applies to the same file contents:OpenClaw Resume test limitation: its native prompt test supplies a synthetic restored Session and non-writer
planmode. Existing default-agent workspace-lease and native Session restoration wiring is outside this PR; the test does not establish complete OpenClaw Resume availability. Hostile-persona tests use simulated model output. They verify tool/candidate/ref contracts, fixed actor/payload, stance/version and receipt ownership, while still allowing valid decisions. They do not establish live-model semantic correctness or identical legal choices across personas; application-specific action legality stays with app receipt checks where the protocol assigns it. Real-model persona fidelity and voice experience are also not claimed.Actual isolated UI: before and after deleting the last owned conversation
These are two states of the current code, not a pixel comparison with an older revision. Only the foreign conversation shows a role label. After deletion the chat is empty and the real backend reports no active/new session.
Synthetic conversations; no character artwork, personal data, credentials or machine paths. See
docs/evidence/character-identity-2026-10-08/README.md.Capture-run observation: one additional screenshot run timed out waiting for the chat input to become enabled after the backend connected (no renderer console/page errors). Repeating with unchanged code, timeout and assertions passed 15/15, as did the prior validation run. The initial timeout remains an unresolved startup-timing observation and is not counted as a pass.
Current native-dialog limitation: a same-role double-click rename probe did not show a title change before timeout and reported no renderer errors. It is not counted as a pass; the final 19-check journey uses the real rename API plus reloaded rendering, with separate component callback coverage.
docs/character-runtime.mdDeferred: role-management GUI, per-role knowledge bases, remaining hardcoded UI character names, display-name deduplication, emotion-example polish, and voice/visual resource integration. No cross-role history viewer or new sharing ledger.
Additional per-branch validation after the unused-import cleanup: Ruff passed for all tracked Python paths with repository exclusions, and
python -m pytest tests/test_provider_prompt_routing.py -qpassed 2/2 on each PR branch. All 15 checks on pre-sync head1dcf4d1passed. Fresh checks for ancestry-only merge4488a47have been triggered; their result is pending.Final check