Skip to content

Commit ebefe0b

Browse files
committed
docs(spec): record avatar memory scope law
1 parent f90095b commit ebefe0b

9 files changed

Lines changed: 1301 additions & 0 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
schema: vision-driven
2+
created: 2026-05-31

openspec/changes/align-avatar-memory-scope-law/plans/plan-v1.md

Lines changed: 268 additions & 0 deletions
Large diffs are not rendered by default.

openspec/changes/align-avatar-memory-scope-law/plans/plan-v2.md

Lines changed: 286 additions & 0 deletions
Large diffs are not rendered by default.

openspec/changes/align-avatar-memory-scope-law/plans/plan.md

Lines changed: 296 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<title>align-avatar-memory-scope-law evidence</title>
6+
<style>
7+
body {
8+
font-family:
9+
ui-sans-serif,
10+
system-ui,
11+
-apple-system,
12+
BlinkMacSystemFont,
13+
"Segoe UI",
14+
sans-serif;
15+
margin: 32px;
16+
color: #1f2933;
17+
background: #f7f9fb;
18+
}
19+
main {
20+
max-width: 980px;
21+
margin: 0 auto;
22+
}
23+
section {
24+
margin: 18px 0;
25+
padding: 18px;
26+
border: 1px solid #d8e0e8;
27+
border-radius: 8px;
28+
background: #fff;
29+
}
30+
h1,
31+
h2 {
32+
margin: 0 0 12px;
33+
line-height: 1.2;
34+
}
35+
p {
36+
margin: 8px 0;
37+
}
38+
code,
39+
pre {
40+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
41+
}
42+
pre {
43+
overflow: auto;
44+
padding: 12px;
45+
border-radius: 6px;
46+
background: #0f172a;
47+
color: #e5edf6;
48+
}
49+
table {
50+
width: 100%;
51+
border-collapse: collapse;
52+
}
53+
th,
54+
td {
55+
padding: 9px 10px;
56+
border-bottom: 1px solid #e5ebf1;
57+
text-align: left;
58+
vertical-align: top;
59+
}
60+
th {
61+
color: #52606d;
62+
font-size: 13px;
63+
text-transform: uppercase;
64+
letter-spacing: 0.04em;
65+
}
66+
.pass {
67+
color: #0f766e;
68+
font-weight: 650;
69+
}
70+
.warn {
71+
color: #b45309;
72+
font-weight: 650;
73+
}
74+
</style>
75+
</head>
76+
<body>
77+
<main>
78+
<h1>align-avatar-memory-scope-law</h1>
79+
<p>Generated: 2026-05-31 12:16:50 +0800</p>
80+
81+
<section>
82+
<h2>Outcome</h2>
83+
<p>
84+
Shell default Memory pack now uses the global Avatar principal root. Project workspaces remain cwd, mount,
85+
grant, workbench, exec, and explicit overlay surfaces. Assistant ensure, runtime clear, and session id
86+
derivation no longer expose project workspace as identity authority. Old/reference package folders are
87+
excluded from active workspace discovery.
88+
</p>
89+
</section>
90+
91+
<section>
92+
<h2>Ownership Change</h2>
93+
<table>
94+
<thead>
95+
<tr>
96+
<th>Resource</th>
97+
<th>Before</th>
98+
<th>After</th>
99+
</tr>
100+
</thead>
101+
<tbody>
102+
<tr>
103+
<td>AGENTER.mdx</td>
104+
<td>Global Avatar principal root</td>
105+
<td>Global Avatar principal root</td>
106+
</tr>
107+
<tr>
108+
<td>Default Memory pack</td>
109+
<td>Workspace private asset via <code>workspacePath + avatarNickname</code></td>
110+
<td>Global Avatar principal memory via <code>avatarPrincipalId</code></td>
111+
</tr>
112+
<tr>
113+
<td>Workspace-private memory</td>
114+
<td>Explicit WorkspaceSystem private asset</td>
115+
<td>Still explicit overlay/artifact only</td>
116+
</tr>
117+
<tr>
118+
<td>Assistant ensure</td>
119+
<td>Accepted project-shaped <code>workspacePath</code> residue</td>
120+
<td>Avatar catalog fields only</td>
121+
</tr>
122+
<tr>
123+
<td>Runtime clear</td>
124+
<td><code>workspacePath + avatarNickname</code></td>
125+
<td><code>avatarPrincipalId</code></td>
126+
</tr>
127+
<tr>
128+
<td>Session id derivation</td>
129+
<td>Workspace-shaped helper name</td>
130+
<td>Avatar-scoped helper name and behavior</td>
131+
</tr>
132+
<tr>
133+
<td>Reference packages</td>
134+
<td><code>apps/*</code> and <code>packages/*</code> globs included old/bak folders</td>
135+
<td>Only active apps are listed; <code>packages/*-bak</code> is excluded</td>
136+
</tr>
137+
</tbody>
138+
</table>
139+
</section>
140+
141+
<section>
142+
<h2>Cleanup Evidence</h2>
143+
<p>Repo-local residue captured before deletion:</p>
144+
<pre>
145+
.agenter/avatars/by-nickname/shell-assistant/memory/hosting-objective.md
146+
.agenter/avatars/by-nickname/shell-assistant/memory/pairing-playbook.md
147+
.agenter/avatars/by-nickname/shell-assistant/memory/self-evolution-log.md
148+
.agenter/avatars/by-nickname/shell-assistant/memory/terminal-habits.md
149+
.agenter/avatars/by-nickname/shell-assistant/memory/user-model.md</pre
150+
>
151+
<p>Cleanup command removed <code>.agenter/avatars</code>; follow-up listing no longer contained that tree.</p>
152+
</section>
153+
154+
<section>
155+
<h2>Verification</h2>
156+
<table>
157+
<thead>
158+
<tr>
159+
<th>Command</th>
160+
<th>Status</th>
161+
</tr>
162+
</thead>
163+
<tbody>
164+
<tr>
165+
<td><code>bun test packages/app-runtime/test/app-runtime.test.ts</code></td>
166+
<td class="pass">Passed, 16 tests</td>
167+
</tr>
168+
<tr>
169+
<td><code>bun test packages/client-sdk/test/app-runtime.test.ts</code></td>
170+
<td class="pass">Passed, 12 tests</td>
171+
</tr>
172+
<tr>
173+
<td><code>bun test packages/app-server/test/session-catalog.test.ts</code></td>
174+
<td class="pass">Passed, 4 tests</td>
175+
</tr>
176+
<tr>
177+
<td><code>bun test packages/app-server/test/app-runtime.test.ts</code></td>
178+
<td class="pass">Passed, 10 tests</td>
179+
</tr>
180+
<tr>
181+
<td><code>bun test apps/shell/test/run-shell.test.ts</code></td>
182+
<td class="pass">Passed, 19 tests</td>
183+
</tr>
184+
<tr>
185+
<td><code>bun run --filter '@agenter/app-server' typecheck</code></td>
186+
<td class="pass">Passed</td>
187+
</tr>
188+
<tr>
189+
<td><code>bun run --filter 'agenter-app-shell' typecheck</code></td>
190+
<td class="pass">Passed</td>
191+
</tr>
192+
<tr>
193+
<td><code>bun run typecheck</code></td>
194+
<td class="pass">Passed</td>
195+
</tr>
196+
<tr>
197+
<td><code>bun run openspec:vision -- validate align-avatar-memory-scope-law</code></td>
198+
<td class="pass">Passed</td>
199+
</tr>
200+
<tr>
201+
<td><code>bun run openspec:vision -- check align-avatar-memory-scope-law</code></td>
202+
<td class="pass">Passed, ok true</td>
203+
</tr>
204+
</tbody>
205+
</table>
206+
</section>
207+
</main>
208+
</body>
209+
</html>
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Self Review: align-avatar-memory-scope-law
2+
3+
Generated: 2026-05-31 12:16:50 +0800
4+
5+
## Verdict
6+
7+
The implementation matches the selected law: Shell's default app-owned Memory pack is now addressed by `avatarPrincipalId` under the global Avatar principal root, while WorkspaceSystem private memory remains an explicit overlay/tool artifact.
8+
9+
Follow-up project-hard-code audit also removed remaining app/runtime/session API residue that still exposed project workspace as assistant/session identity authority.
10+
11+
## Plan Alignment
12+
13+
- `@agenter/app-runtime` now rejects `workspacePath + avatarNickname` for default memory-pack seeding and accepts only `avatarPrincipalId + roles`.
14+
- `@agenter/app-server` exposes `appRuntime.ensureAvatarMemoryPack` and writes role files under `~/.agenter/avatars/by-principal/<principalId>/memory/*`.
15+
- `@agenter/client-sdk` routes `AppRuntimeClient.ensureMemoryPackIfMissing` through the app-runtime global Avatar memory route instead of `workspace.ensurePrivateTextAsset`.
16+
- `apps/shell` passes the session `avatarPrincipalId` for default Memory pack initialization and prompt wording names global Avatar memory explicitly.
17+
- `apps/shell` and `apps/shell-old` no longer pass `workspacePath` to assistant ensure or `workspacePath + avatarNickname` to runtime clear; clear uses `avatarPrincipalId`.
18+
- `@agenter/app-server` now names session identity derivation as Avatar-scoped (`resolveAvatarSessionId`) and removed the internal workspace/avatar lookup wrapper.
19+
- Root workspace discovery now lists active apps explicitly and excludes `packages/*-bak`, so `apps/shell-old` and bak snapshots remain reference code instead of active projects.
20+
- Workspace private text assets remain supported through `WorkspaceSystem` for explicit overlays.
21+
- Durable specs now say project workspace is a tool surface, not the default owner for app-owned prompt or identity memory.
22+
23+
## Evidence
24+
25+
Before cleanup, repo-local memory residue existed:
26+
27+
```text
28+
.agenter/avatars/by-nickname/shell-assistant/memory/hosting-objective.md
29+
.agenter/avatars/by-nickname/shell-assistant/memory/pairing-playbook.md
30+
.agenter/avatars/by-nickname/shell-assistant/memory/self-evolution-log.md
31+
.agenter/avatars/by-nickname/shell-assistant/memory/terminal-habits.md
32+
.agenter/avatars/by-nickname/shell-assistant/memory/user-model.md
33+
```
34+
35+
Global prompt roots existed, while the searched global memory files were not present before the new seed route runs:
36+
37+
```text
38+
/Users/kzf/.agenter/avatars/by-principal/0x683fe694c23b7f3af3f76cbb05ca009320e45af2/AGENTER.mdx
39+
/Users/kzf/.agenter/avatars/by-principal/0x888bb66a5ec389d52df0c9ff3e19a61dec890a66/AGENTER.mdx
40+
/Users/kzf/.agenter/avatars/by-principal/0x9eb798d6d2bdea5d434dad84ce014b1fddba2232/AGENTER.mdx
41+
```
42+
43+
Approved cleanup removed repo-local `.agenter/avatars`; follow-up `find .agenter -maxdepth 6` showed no `.agenter/avatars` tree.
44+
45+
## Verification Commands
46+
47+
- `bun test packages/app-runtime/test/app-runtime.test.ts` passed: 16 tests.
48+
- `bun test packages/client-sdk/test/app-runtime.test.ts` passed: 12 tests.
49+
- `bun test packages/app-server/test/session-catalog.test.ts` passed: 4 tests.
50+
- `bun test packages/app-server/test/app-runtime.test.ts` passed: 10 tests.
51+
- `bun test apps/shell/test/run-shell.test.ts` passed: 19 tests.
52+
- `bun run --filter '@agenter/app-server' typecheck` passed.
53+
- `bun run --filter 'agenter-app-shell' typecheck` passed.
54+
- `bun run typecheck` passed after excluding reference/bak projects from workspace discovery.
55+
- `bun run openspec:vision -- validate align-avatar-memory-scope-law` passed.
56+
- `bun run openspec:vision -- check align-avatar-memory-scope-law` passed with `ok: true`.
57+
- `bun run openspec:vision -- status align-avatar-memory-scope-law` showed `research-plan`, `specs`, and `tasks` complete, with only `self-review` pending before this artifact.
58+
59+
## Workspace Project Set
60+
61+
`apps/shell-old` is reference code. It is no longer a workspace package, and `*-bak` package folders are also excluded from Bun and pnpm workspace discovery. The active root typecheck now passes without requiring those reference snapshots to satisfy current product contracts.
62+
63+
## Review Notes
64+
65+
- The change is generic: core/server code has no Shell-specific memory branch.
66+
- Principal id validation is enforced in the shared schema.
67+
- Memory role paths are constrained as safe relative paths in the shared schema and still contained again server-side.
68+
- Existing workspace-private memory APIs are intentionally retained to avoid deleting the explicit overlay tool surface.
69+
- Wider residue scans found no remaining code references to the removed `resolveWorkspaceAvatarSessionId` / `findByWorkspaceAvatar` names or `workspacePath + avatarNickname` reset shape; remaining `workspacePath` usages after this pass are intentional tool surfaces: cwd, mounts, grants, workbench browsing, workspace exec, and explicit private overlays.
70+
- No automatic migration/merge of existing project-local memory content was attempted.
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
## MODIFIED Requirements
2+
3+
### Requirement: App packages SHALL initialize assistant resources through generic APIs
4+
5+
The app runtime SHALL let apps ensure Avatar, global prompt-source, and app-owned global Avatar memory-pack resources through generic app APIs. App packages SHALL provide app defaults, but core runtime modules SHALL remain app-agnostic and prompt/memory files SHALL remain openly editable user assets. App-owned default prompt and memory-pack resources SHALL be addressed by the Avatar principal id under the global Avatar canonical root, not by a project workspace path or nickname alias. WorkspaceSystem private text assets remain available only for explicitly workspace-scoped private artifacts and overlays; they MUST NOT be the default target for app-owned assistant identity memory.
6+
7+
#### Scenario: App ensures default assistant without core special case
8+
9+
- **WHEN** Shell needs default Avatar `shell-assistant`
10+
- **THEN** it requests Avatar ensure through a generic Avatar/app API
11+
- **AND** it may create missing app-owned prompt and memory defaults through generic principal-addressed app APIs
12+
- **AND** core launcher modules do not hard-code the `shell-assistant` nickname
13+
14+
#### Scenario: App prompt initialization stays open and seed-if-missing
15+
16+
- **GIVEN** an app-owned default prompt resource already exists for an Avatar
17+
- **WHEN** Shell runs its initialization flow
18+
- **THEN** it reads the existing file as current truth
19+
- **AND** it creates the missing prompt without locking or automatically restoring app defaults over user edits
20+
- **AND** advanced users may edit the prompt resource manually
21+
22+
#### Scenario: App memory-pack initialization stays open and seed-if-missing
23+
24+
- **GIVEN** an app-owned default memory role file already exists under the Avatar principal root
25+
- **WHEN** Shell runs its initialization flow from any project workspace
26+
- **THEN** it reads the existing global Avatar memory file as current truth
27+
- **AND** it creates missing memory role files without locking or automatically restoring app defaults over user edits
28+
- **AND** advanced users may edit those memory resources manually
29+
30+
#### Scenario: App memory pack ignores project workspace locality
31+
32+
- **GIVEN** Shell starts from workspace `/repo`
33+
- **AND** Avatar `shell-assistant` resolves to principal `0xabc...`
34+
- **WHEN** Shell seeds the missing assistant memory pack
35+
- **THEN** each default role file is seeded under `~/.agenter/avatars/by-principal/0xabc.../memory/`
36+
- **AND** the app memory-pack seed contract does not expose `/repo` as the memory root input
37+
- **AND** Shell startup does not create `/repo/.agenter/avatars/.../memory` for the default app-owned memory pack
38+
39+
#### Scenario: Workspace-private memory remains explicit overlay data
40+
41+
- **WHEN** an app or operator intentionally creates a workspace-private memory asset
42+
- **THEN** it must use the WorkspaceSystem private text asset API with explicit `workspacePath`, `avatarNickname`, and `assetKind=memory`
43+
- **AND** that asset remains a workspace overlay or artifact
44+
- **AND** it is not treated as the default app-owned identity memory pack
45+
46+
#### Scenario: Legacy memory seed input rejects project workspace authority
47+
48+
- **WHEN** a caller tries to seed the default app memory pack with `workspacePath` instead of `avatarPrincipalId`
49+
- **THEN** the app memory-pack seed schema rejects that input
50+
- **AND** the caller must use the principal-addressed global Avatar memory contract
51+
52+
#### Scenario: App assistant ensure rejects project workspace authority
53+
54+
- **WHEN** an app ensures an assistant Avatar
55+
- **THEN** the input contract accepts app id, Avatar nickname, display name, and classify metadata
56+
- **AND** it MUST NOT accept `workspacePath` as assistant identity or creation authority
57+
58+
#### Scenario: Runtime clear uses Avatar principal authority
59+
60+
- **WHEN** an app clears an Avatar runtime session
61+
- **THEN** the input contract accepts `avatarPrincipalId`
62+
- **AND** it MUST reject project-shaped `workspacePath + avatarNickname` reset input
63+
- **AND** matching runtime session rows are selected by Avatar principal, not by project workspace path
64+
65+
#### Scenario: App memory seed rejects non-principal paths
66+
67+
- **WHEN** a caller passes a non-principal path-like value as `avatarPrincipalId`
68+
- **THEN** the app memory-pack seed route rejects the input before filesystem mutation
69+
- **AND** no workspace-local memory file is created as a fallback
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
## MODIFIED Requirements
2+
3+
### Requirement: WorkspaceSystem SHALL manage dynamic mounts and path grants independent of Avatar definitions
4+
5+
The system SHALL model workspaces as independently mountable resources, while also attaching one fixed avatar root workspace for every runtime. Avatar runtimes SHALL receive project workspace access only through explicit workspace mounts and ordered grant rules, and the fixed avatar root workspace SHALL exist in addition to those dynamic mounts. A project workspace is a tool surface for cwd, mounts, grants, workbench browsing, explicit private overlays, and one-shot execution; it SHALL NOT become the default owner for Avatar identity, app-owned assistant prompt truth, or app-owned assistant memory-pack truth.
6+
7+
#### Scenario: Runtime always includes one fixed avatar root workspace
8+
9+
- **WHEN** an avatar runtime starts
10+
- **THEN** WorkspaceSystem attaches the avatar's principal-address root workspace as a fixed mount
11+
- **AND** that mount remains available even if no project workspace is currently attached
12+
13+
#### Scenario: Dynamic project workspaces remain explicit
14+
15+
- **WHEN** an avatar runtime needs access to a project workspace
16+
- **THEN** that workspace still requires an explicit mount and grant set
17+
- **AND** the fixed avatar root workspace does not implicitly grant access to unrelated project paths
18+
- **AND** the project workspace does not become an Avatar identity or app-owned memory root merely because it was used as cwd
19+
20+
#### Scenario: One Avatar runtime mounts multiple workspaces concurrently
21+
22+
- **WHEN** one Avatar runtime mounts two different workspaces at the same time
23+
- **THEN** both mounts remain attached to the same runtime identity
24+
- **AND** each mount keeps its own ordered grant rule set and workspace metadata
25+
- **AND** app-owned assistant memory remains addressed by the same global Avatar principal root
26+
27+
#### Scenario: Ordered grant rules are evaluated last-match-wins
28+
29+
- **GIVEN** a workspace mount applies `/src` as `ro` and later applies `/src/generated` as `rw`
30+
- **WHEN** workspace bash writes under `/src/generated`
31+
- **THEN** the later `rw` rule wins and the write succeeds
32+
- **AND** writes under `/src/manual` still fail because the broader `ro` rule remains in effect there
33+
34+
#### Scenario: Path grants enforce read-only and writable boundaries
35+
36+
- **GIVEN** a workspace mount grants `/src` as read-only and `/tmp` as writable
37+
- **WHEN** workspace bash execution attempts to write under `/src`
38+
- **THEN** the execution is rejected as a permission violation
39+
- **AND** writes under `/tmp` remain allowed

0 commit comments

Comments
 (0)