release: prepare SoulLink Public 2.0 launch
This commit is contained in:
@@ -14,7 +14,7 @@ jobs:
|
||||
python-version: "3.11"
|
||||
- run: uv sync --group dev
|
||||
- run: uv run pytest -q
|
||||
- run: PYTHONPATH="packages/persona_engine:packages:adapters" uv run pytest -q packages/persona_engine/tests
|
||||
- run: PYTHONPATH=".:packages/persona_engine:packages:adapters" uv run pytest -q packages/persona_engine/tests
|
||||
- run: rm -rf packages/persona_engine/logs
|
||||
- run: uv run python scripts/public_release_audit.py --root .
|
||||
- run: uv build
|
||||
|
||||
@@ -1,44 +1,65 @@
|
||||
# SoulLink Public 2.0
|
||||
|
||||
SoulLink Public 2.0 is an open-source reference runtime for long-running persona agents.
|
||||
It is designed for agents that need more than a single prompt: stable identity, controllable state,
|
||||
auditable memory boundaries, emotion-aware mode routing, and safe model selection across long conversations.
|
||||
**Persistent identity, continuous emotion, governed memory, and auditable context for long-running AI personas.**
|
||||
|
||||
This repository is the public extraction of the SoulLink runtime architecture. It keeps the reusable engine,
|
||||
contracts, and tests, while deliberately excluding private deployment state, private memories, credentials,
|
||||
logs, and any concrete private character preset.
|
||||
[](https://github.com/miyamoriaoi1997-del/Soul-Llink/actions/workflows/verify.yml)
|
||||
[](https://www.python.org/)
|
||||
[](LICENSE)
|
||||
|
||||
## What SoulLink Is
|
||||
SoulLink is an open-source runtime for agents that should feel like the **same person over time**, not a fresh prompt on every turn. It combines a layered persona engine, continuous emotional state, governed long-term memory, exact context evidence, and reversible host integration.
|
||||
|
||||
SoulLink is a layered persona-agent runtime. Its core idea is simple: a long-running agent should not be
|
||||
assembled from one unstructured prompt blob. It should be assembled from explicit layers with clear priority,
|
||||
state ownership, memory contracts, and safety boundaries.
|
||||
> A memory is not automatically an instruction. An emotion is not only a style adjective. A summary is not the latest user request. SoulLink makes those distinctions executable and auditable.
|
||||
|
||||
SoulLink separates the runtime into three major capabilities:
|
||||

|
||||
|
||||
- **Persona Engine** — builds the active persona context from layered identity, mode, emotion, task, and style inputs.
|
||||
- **PCLTM** — governs memory/context continuity, recall boundaries, compaction semantics, and safe active-context assembly.
|
||||
- **Model Router** — routes OpenAI-compatible requests to upstream models based on explicit runtime metadata.
|
||||
*The screenshot uses synthetic public demo data rendered by the real read-only SoulLink WebUI. It contains no private persona, memory, or conversation data.*
|
||||
|
||||
Together they provide a reference architecture for persona agents that need to stay coherent over time without
|
||||
letting stale summaries, tool dumps, deployment artifacts, or unsafe memory records silently take over the current turn.
|
||||
## What you can verify
|
||||
|
||||
## Why SoulLink Exists
|
||||
| Capability | Observable behavior |
|
||||
|---|---|
|
||||
| **Continuous persona** | Stable identity stays anchored while work, daily, intimate, or crisis posture changes expression without replacing the person. |
|
||||
| **Dynamic emotion** | Affection, trust, possessiveness, and patience change tone, distance, initiative, and boundaries with intensity and aftereffects instead of resetting each turn. |
|
||||
| **Governed memory** | PCLTM separates the persistent archive, recall candidates, policy judgment, and records that actually influence the final model input. |
|
||||
| **Exact evidence** | The WebUI distinguishes exact host capture from sidecar reconstruction; missing evidence is shown as unavailable, never invented. |
|
||||
| **Reversible integration** | Host adapters follow detect → backup → apply → verify → receipt → byte-exact rollback. |
|
||||
|
||||
Most persona-agent systems fail in predictable ways once conversations become long-lived:
|
||||
## Five-minute local start
|
||||
|
||||
- identity and behavior are mixed into one prompt and become hard to audit;
|
||||
- summaries start acting like instructions instead of background context;
|
||||
- tool outputs leak across turns and become stale evidence;
|
||||
- memories have unclear priority, provenance, or approval status;
|
||||
- compression logic changes the meaning of the current request;
|
||||
- model routing is disconnected from runtime state;
|
||||
- host-specific deployment details become tangled with reusable agent logic.
|
||||
```bash
|
||||
git clone https://github.com/miyamoriaoi1997-del/Soul-Llink.git
|
||||
cd Soul-Llink
|
||||
uv sync --group dev
|
||||
uv run soullink init
|
||||
uv run soullink doctor
|
||||
uv run soullink webui
|
||||
```
|
||||
|
||||
SoulLink exists to make those boundaries explicit. The runtime treats persona, memory, context, tools, and routing as
|
||||
separate layers that can be inspected, tested, and replaced independently.
|
||||
The dashboard opens at `http://127.0.0.1:8765/`. Core runtime use does not require Hermes or Codex; both are optional, explicit adapters.
|
||||
|
||||
## Architecture Overview
|
||||
For a packaged install, download the wheel from the [latest GitHub Release](https://github.com/miyamoriaoi1997-del/Soul-Llink/releases/latest), verify `SHA256SUMS.txt`, then run:
|
||||
|
||||
```bash
|
||||
python -m pip install soullink_public_2_0-2.0.0-py3-none-any.whl
|
||||
soullink init
|
||||
soullink doctor
|
||||
soullink webui
|
||||
```
|
||||
|
||||
## Why SoulLink exists
|
||||
|
||||
Long-running persona agents commonly fail in ways that short demos hide:
|
||||
|
||||
- identity, behavior, and task instructions collapse into one unauditable prompt;
|
||||
- retrieved memories and compressed summaries gain accidental authority;
|
||||
- tool results leak across turns as stale evidence;
|
||||
- emotional state is computed but softened away before the final response;
|
||||
- host integration becomes an undocumented, irreversible local patch;
|
||||
- model routing cannot be correlated with the state that requested it.
|
||||
|
||||
SoulLink treats persona, memory, emotion, context, tools, and routing as separate governed layers. The result is a runtime that can remain expressive without surrendering factual discipline or operator control.
|
||||
|
||||
## Architecture overview
|
||||
|
||||
```text
|
||||
User / Host Adapter
|
||||
@@ -184,26 +205,29 @@ The public edition is meant to demonstrate the reusable architecture, not to pub
|
||||
|
||||
SoulLink does not require Hermes or Codex for its core runtime. Host support is provided through explicit, optional adapters.
|
||||
|
||||
## Quick Start
|
||||
## Detailed installation
|
||||
|
||||
### Install from a release wheel
|
||||
### Isolated wheel installation
|
||||
|
||||
Download both the wheel and `SHA256SUMS.txt` from the [latest release](https://github.com/miyamoriaoi1997-del/Soul-Llink/releases/latest), verify the checksum, then install into a fresh environment:
|
||||
|
||||
```bash
|
||||
python -m venv .venv
|
||||
# Linux/macOS
|
||||
. .venv/bin/activate
|
||||
# Windows PowerShell
|
||||
# .venv\\Scripts\\Activate.ps1
|
||||
# .venv\Scripts\Activate.ps1
|
||||
|
||||
python -m pip install soullink_public_2_0-2.0.0-py3-none-any.whl
|
||||
soullink init
|
||||
soullink doctor
|
||||
soullink webui
|
||||
```
|
||||
|
||||
### Install from source with uv
|
||||
### Development checkout
|
||||
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
git clone https://github.com/miyamoriaoi1997-del/Soul-Llink.git
|
||||
cd Soul-Llink
|
||||
uv sync --group dev
|
||||
uv run pytest -q
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# SoulLink Public 2.0
|
||||
|
||||
SoulLink Public 2.0 is the first packaged public release of the long-running persona runtime.
|
||||
|
||||
## Highlights
|
||||
|
||||
- Layered persona composition with stable identity and mode-specific behavior.
|
||||
- Continuous four-axis emotional state with intensity, momentum, and aftereffects.
|
||||
- PCLTM governed memory: archive → candidates → policy judgment → final influence.
|
||||
- Read-only SoulLink Observatory that distinguishes exact host capture from reconstruction previews.
|
||||
- Explicit Hermes and Codex adapter lifecycles with detection, verification, receipts, and rollback.
|
||||
- OpenAI-compatible model router with auditable request metadata boundaries.
|
||||
|
||||
## Install
|
||||
|
||||
1. Download the wheel and `SHA256SUMS.txt` from this release.
|
||||
2. Verify the wheel checksum.
|
||||
3. Install into a clean Python 3.11+ environment:
|
||||
|
||||
```bash
|
||||
python -m pip install soullink_public_2_0-2.0.0-py3-none-any.whl
|
||||
soullink init
|
||||
soullink doctor
|
||||
soullink webui
|
||||
```
|
||||
|
||||
The WebUI binds to `127.0.0.1` and is read-only by default.
|
||||
|
||||
## Public boundary
|
||||
|
||||
This release contains the reusable runtime, neutral public persona templates, tests, and explicit host adapters. It does not contain private personas, user memories, conversations, credentials, runtime databases, logs, or deployment-specific state.
|
||||
|
||||
## Verification
|
||||
|
||||
Release assets are built only after the public test suites, release audit, package build, clean-wheel installation, CLI smoke checks, and archive-member inspection complete successfully. See `RELEASE_CHECKLIST.md` for the gate.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 310 KiB |
+4
-4
@@ -45,9 +45,9 @@ soullink-codex-mcp = "soul_link.codex_mcp:main"
|
||||
soullink-codex-hook = "soul_link.codex_hook:main"
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/soullink-public/soullink-public-2.0"
|
||||
Repository = "https://github.com/soullink-public/soullink-public-2.0"
|
||||
Issues = "https://github.com/soullink-public/soullink-public-2.0/issues"
|
||||
Homepage = "https://github.com/miyamoriaoi1997-del/Soul-Llink"
|
||||
Repository = "https://github.com/miyamoriaoi1997-del/Soul-Llink"
|
||||
Issues = "https://github.com/miyamoriaoi1997-del/Soul-Llink/issues"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
@@ -125,4 +125,4 @@ model_router = [
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
testpaths = ["tests"]
|
||||
pythonpath = ["packages", "adapters"]
|
||||
pythonpath = [".", "packages", "adapters"]
|
||||
|
||||
@@ -38,6 +38,10 @@ PRIVATE_MARKERS = (
|
||||
"Nan" + "agami",
|
||||
"miyamori" + "aoi",
|
||||
)
|
||||
PUBLIC_PROJECT_URLS = (
|
||||
"https://github.com/miyamoriaoi1997-del/Soul-Llink",
|
||||
"https://github.com/miyamoriaoi1997-del/Soul-Llink/issues",
|
||||
)
|
||||
ABSOLUTE_HOST_PATTERNS = (
|
||||
re.compile(r"(?i)[a-z]:[\\/]users[\\/](?!example(?:-user)?(?:[\\/]|$))"),
|
||||
re.compile("(?i)/" + "ho" + "me/(?!example(?:-user)?(?:/|$))"),
|
||||
@@ -72,6 +76,8 @@ def audit(root: Path) -> dict[str, object]:
|
||||
continue
|
||||
text = path.read_text(encoding="utf-8", errors="replace")
|
||||
categories: set[str] = set()
|
||||
for project_url in PUBLIC_PROJECT_URLS:
|
||||
text = text.replace(project_url, "<PUBLIC_PROJECT_URL>")
|
||||
lowered = text.casefold()
|
||||
if any(marker.casefold() in lowered for marker in PRIVATE_MARKERS):
|
||||
categories.add("private-identity")
|
||||
|
||||
@@ -5,6 +5,8 @@ import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from scripts.public_release_audit import audit
|
||||
|
||||
|
||||
def test_public_release_audit_accepts_repository() -> None:
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
@@ -24,3 +26,28 @@ def test_public_release_audit_accepts_repository() -> None:
|
||||
assert report["private_marker_hits"] == []
|
||||
assert report["forbidden_files"] == []
|
||||
assert report["missing_required_files"] == []
|
||||
|
||||
|
||||
def test_public_release_audit_allows_private_marker_only_inside_declared_project_urls(tmp_path: Path) -> None:
|
||||
for name in (
|
||||
".gitignore", "CONTRIBUTING.md", "LICENSE", "MANIFEST.in", "README.md",
|
||||
"RELEASE_CHECKLIST.md", "SECURITY.md",
|
||||
):
|
||||
(tmp_path / name).write_text("public\n", encoding="utf-8")
|
||||
(tmp_path / "pyproject.toml").write_text(
|
||||
'[project]\nname = "example"\n\n[project.urls]\n'
|
||||
'Repository = "https://github.com/miyamoriaoi1997-del/Soul-Llink"\n',
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
assert audit(tmp_path)["ok"] is True
|
||||
|
||||
private_marker = "miyamori" + "aoi"
|
||||
(tmp_path / "README.md").write_text(
|
||||
private_marker + " private persona\n", encoding="utf-8"
|
||||
)
|
||||
report = audit(tmp_path)
|
||||
assert report["ok"] is False
|
||||
assert report["private_marker_hits"] == [
|
||||
{"path": "README.md", "categories": ["private-identity"]}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user