2026-10-11 policy reconciliation: The owner-decided #58 target is VIVY foundation memory; LIFE is the first default-enabled pilot and coding agents are excluded in phase one. Implementation remains open. See the selected unified context memory contract.
AGENT-VIVY V0 runtime — a personal gateway Agent assembled on the Eino execution framework with a Vivy-owned thin application shell.
This repository is the implementation home of AGENT-VIVY. The design dossier
(PRD v0.5, assembly options, reference index, go/no-go preflight) lives in the
parent directory ../ (diva-go/) and is the contract this code must honor.
V0/V1 species runtime is assembled (see docs/TODO.md). Vivy Studio
is the first-party daily development IDE and the independent owner of the
distribution lifecycle. Other authorized developer tools may work directly
in this repository with their own native capabilities; work does not need to
be transferred into Studio (docs/architecture/VIVY-STUDIO.md).
Do not add a “open Studio” door to vivy.exe. The species-side Studio
card is not Studio.
The SCX design covers extensible context views, memory, retrieval, multimodal references and lifecycle hooks. The integration map tracks Host ownership and gate evidence. This is design direction, not a shipped capability.
- Go 1.26.4, Node.js 22+, and pnpm 10.33.0 (
ui/package.jsonpins it). - Git. Windows development also uses PowerShell; WSL/Linux uses Bash.
justfor the task recipes. Without it, run the underlyingnode/gocommands directly; the cross-platform steps live inscripts/*.mjs.- Network access to GitHub for the first pinned Laputa bootstrap, and to a
Go module proxy. Recipes use a process-local
GOPROXY(VIVY_GOPROXY→GOPROXY→https://goproxy.cn,direct);just setupnever writesgo env -w, so a mirror cannot leak into other projects. - Diagnose the machine at any time with
just doctor(read-only).
The recommended split is: Windows for the editor, browser, daily use, and
native .exe acceptance; WSL2/Linux (code on the Linux filesystem) for the
main Go/Node development line; Docker/WSL for Postgres and packaged startup
acceptance. See Development environment.
just doctor # read-only tool, pin, proxy, port, and UI checks
just setup # prepare pinned ProjectViVy/laputa sources, then go mod download
just ensure-studio # git submodule update --init studio/ (ProjectViVy/vivy-studio)
just build # go build ./...
just test # go test ./...
just ci # Go fmt/vet/test + UI install/typecheck/unit/build + I18N completeness
just run # dev backend on 127.0.0.1:8788 with an isolated data root
just tui # build and run an independent VIVY CODE TUI
just dev # split loop: backend :8788 + Vite :3016
just build-split # build a headless backend plus standalone ui under dist/
just docker-up # one-container image, SQLite on a volume, host 127.0.0.1:8787
.\launch-vivy-studio.ps1 # Studio IDE on :3090 (auto-ensures studio submodule)Prefer git clone --recurse-submodules so studio/ is present immediately.
just ensure-studio / launch-vivy-studio.ps1 will init it on first use if not.
just setup and just dev work after a plain clone: they automatically prepare
../laputa from ProjectViVy/laputa at the commit in laputa-source.lock.json.
The Garden, Mentle and Laputa modules live in that one repository under the
github.com/ProjectViVy/laputa/ namespace. This complete Git source checkout
is required for VIVY builds and is separate from the optional Studio submodule.
The parent directory must be writable, and the first bootstrap requires access
to GitHub. No sibling INOFY checkout is required.
The same bootstrap runs in CI and is a no-op when the pinned checkout is ready.
A clean older checkout is updated to the pin; local changes at a different
revision or an unrelated repository cause an actionable error without overwriting
files. Commit or stash local changes before retrying. Without just, run:
node scripts/ensure-laputa.mjs --quiet
go mod download
.\dev.ps1Parallel work must not share one mutable ../laputa. Create a lane with its
own nested checkout instead of stacking branches in the root tree:
just lane-new diva-recall
# .worktrees/diva-recall/agent-vivy (git worktree, branch feat/diva-recall)
# .worktrees/diva-recall/laputa (pinned checkout for that lane)
Docker is a packaging of the same organism (embedded UI, one process,
replica=1). The build needs the pinned Laputa checkout as a named build
context; just docker-build verifies the pin and passes it, and
docker compose up --build receives it through additional_contexts.
docker compose up --build publishes only
127.0.0.1:8787:8787 and stores the Journal on the named volume
vivy-data (/data/vivy.db in the container). Do not scale the service
and do not bind 8787 on all host interfaces. Provider keys stay in the
environment (DEEPSEEK_API_KEY / OPENAI_API_KEY / ANTHROPIC_API_KEY);
DeepSeek is the default provider. Open
http://127.0.0.1:8787 after the container is healthy. The image does
not ship go / git / rg; execute / commandline stay gated and
unavailable until those binaries are present.
Optional Postgres is a second Journal engine, not a replica set. Set
storage.backend: postgres and storage.postgres.dsn_env (the
environment variable name); put the DSN in that variable. A second
process on the same DSN fails to start. just docker-up-postgres is the
compose overlay; default just docker-up stays SQLite on a volume.
For day-to-day Vivy feature work, run just dev from the repository root
(dev.ps1 on Windows, scripts/dev.sh on WSL/Linux). It starts the backend
on 127.0.0.1:8788 and the Vite UI on 127.0.0.1:3016, using
.workspace/dev/home as the data root, so the daily ~/.vivy home and the
embedded :8787 instance stay untouched. The dev entries load
scripts/dev.config.yaml (an empty overlay) instead of a repo config.yaml;
set VIVY_DEV_CONFIG to supply a different dev config. Set
VIVY_DEV_BACKEND_PORT /
VIVY_DEV_UI_PORT for a second lane. Or use two terminals: just run, then
cd ui; VIVY_BACKEND_ADDR=http://127.0.0.1:8788 pnpm dev (Vite stays on
:3015). Open http://127.0.0.1:3016 for just dev. The Vite server proxies /rpc to
the backend, so UI and Go changes can be iterated independently. The
embedded UI is the default release/CI path; use just build-split when
you need the packaged headless backend and standalone static UI.
English (en) is the product default. Exactly en and zh are supported;
browser or operating-system language does not select another locale.
For development or a new pack, set this non-secret input in the local root
.env (which remains gitignored; never commit it):
VIVY_DEFAULT_LOCALE=enAn already-set process VIVY_DEFAULT_LOCALE takes precedence over .env,
including validation: an empty or unsupported process value fails rather than
falling through to the file. If neither source supplies a value, use en.
Only this setting is read by the locale loader; unrelated .env values are
not logged or copied into presentation metadata.
vivy-sdk pack embeds the resolved default in the executable and in
generation.json at recipe.settings.locale. A sealed Generation keeps that
default even if the process environment or source-tree .env later changes.
An unsealed development body resolves the process/file default at startup.
This existing core locale embedding does not imply that the current SDK
implements the v1 plugin platform.
Settings → Language writes locale in the global VIVY workspace
settings.yaml, not the current project's settings or browser storage.
That user override wins over the Generation/development default and is shared
by Web, TUI, and VIVY CODE. An absent or empty workspace locale means no
override. Sealing fixes the default, not the user's presentation preference.
Both faces use backend authority: settings/get returns locale,
generation_locale, workspace_locale, and locale_read_only;
settings/locale accepts { "locale": "en" } or { "locale": "zh" }
and returns the same locale view. The narrow write preserves unrelated
settings, rejects unsupported locales and read-only deployments, and remains
allowed when provider settings are frozen. Web applies the successful backend
response; localStorage is only a startup cache and hydration supersedes it.
TUI hydrates through the same settings RPC for in-process and --live use;
if unavailable, it retains the embedded default with a sanitized warning.
This is shared persistence and hydration, not cross-process live push.
User/model/tool text, Journal content, and protocol identifiers remain data.
From the repository root, node scripts/check-i18n-completeness.js validates
Web catalog key/placeholder parity and maintained runtime copy. just ci
runs it after UI dependency installation without replacing the existing Go,
headless, plugin-module, or UI gates. See the
I18N implementation status
for fresh verification evidence and the deliberately deferred plugin catalog
proposal; Go/TUI execution and the complete just ci gate remain unverified
in the 2026-09-09 Task 9 environment.
cmd/vivy/ species entrypoint (daily gateway + worker + fullscreen `tui` command)
cmd/vivy-code/ independent VIVY CODE binary; shared config, private Journal per launch
sdk/ vivy-sdk binary (verify/pack); invoked by Studio, not by vivy.exe
sdk/tui/ canonical fullscreen TUI view, controller, protocol projection, and tests
internal/app/ composition and lifecycle
internal/config/ config loading and validation (secret boundary)
internal/domain/ Vivy-owned Session/Message/Run/RunEvent/... contract types
internal/runtime/ Run service + Eino adapter (event mapping, interrupt)
internal/provider/ sealed protocol adapters + embedded provider catalog
internal/tools/ ToolSpec registry + approval policy
internal/storage/ Journal/SnapshotStore/BlobStore/LeaseStore + SQLite backend
internal/events/ event fan-out and after_seq replay cursor
internal/rpc/ UI-facing command/query/event JSON-RPC control plane
internal/tui/ remote WebSocket transport for `vivy tui --live`
schemas/ RunEvent JSON Schema (provider data schema lives beside its data)
ui/ only browser UI (React + Vite + Zustand + TanStack Router)
studio/ git submodule → ProjectViVy/vivy-studio (Studio shell + plugins)
cmd/vivy-studio/ Studio lifecycle CLI (pack/eval/release); stays in this repo
docs/ implementation plan + project TODO board
The Studio shell (DSH profile bundles, first-party skin/console, plugin hub
fork, community plugin snapshots) is maintained in
ProjectViVy/vivy-studio and
mounted here at studio/. Bump the submodule gitlink after shell changes;
do not re-vendor those trees into this host repo.
The default vivy.exe remains a single-file, embedded-UI application. For a
same-machine split deployment, just build-split produces
dist/vivy-backend.exe and dist/vivy-ui/. Set server.allowed_origins in
the backend config to the exact loopback origin serving the static UI, then
set controlPlaneUrl in dist/vivy-ui/vivy-config.json to the backend URL.
The split build is intentionally loopback-only; it is not a remote or
multi-user deployment mode.
vivy-code.exe is a first-party terminal product built from the same kernel,
not a forked runtime. It reads the same config.yaml / VIVY_CONFIG, provider
environment variables, shared settings.yaml, and skills root as vivy.exe.
Each launch allocates its own SQLite Journal and runtime/log directory under
<shared-data-root>/code-instances/, so multiple TUI processes and the web
process can run concurrently without sharing sessions, messages, approvals,
runs, or checkpoints. just tui builds the headless-tagged binary and starts
it in the current project.
- Eino and reference-project types never leak past
internal/runtime/internal/providerinto the UI contract (PRD D-007). - Single Go module (D-006). No multi-module workspace.
- Secrets are never persisted (D-010).
- Exactly one terminal event per run (D-008).
- No
agent-diva-*code import or schema inheritance (D-005, D-021)..workspace/einoin the parent dossier is a read-only API reference only; this module consumes Eino exclusively as online dependencies.