@ai-ecoverse/slicc-agent 3.13.1 → 3.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +22 -5
  2. package/bin/agent +1 -1
  3. package/dist/agents.js.map +2 -2
  4. package/dist/client.js +5 -1
  5. package/dist/client.js.map +2 -2
  6. package/dist/control.js +14 -1
  7. package/dist/control.js.map +2 -2
  8. package/dist/host.js +6 -2
  9. package/dist/host.js.map +2 -2
  10. package/dist/main.js +19 -2
  11. package/dist/main.js.map +2 -2
  12. package/dist/memory/context.js +91 -0
  13. package/dist/memory/context.js.map +7 -0
  14. package/dist/memory/format.js +251 -0
  15. package/dist/memory/format.js.map +7 -0
  16. package/dist/memory/index.js +32 -0
  17. package/dist/memory/index.js.map +7 -0
  18. package/dist/memory/prompt.js +175 -0
  19. package/dist/memory/prompt.js.map +7 -0
  20. package/dist/memory/runtime.js +194 -0
  21. package/dist/memory/runtime.js.map +7 -0
  22. package/dist/memory/store.js +153 -0
  23. package/dist/memory/store.js.map +7 -0
  24. package/dist/roles/frontmatter.js +9 -4
  25. package/dist/roles/frontmatter.js.map +2 -2
  26. package/dist/roles/roles.js +55 -11
  27. package/dist/roles/roles.js.map +2 -2
  28. package/dist/scoops/cli.js +3 -0
  29. package/dist/scoops/cli.js.map +2 -2
  30. package/dist/scoops/index.js +5 -3
  31. package/dist/scoops/index.js.map +2 -2
  32. package/dist/scoops/requests.js +1 -1
  33. package/dist/scoops/requests.js.map +2 -2
  34. package/dist/scoops/service.js +22 -4
  35. package/dist/scoops/service.js.map +2 -2
  36. package/dist/scoops/sync.js +1 -0
  37. package/dist/scoops/sync.js.map +2 -2
  38. package/dist/services.js.map +2 -2
  39. package/dist/skills/index.js +8 -1
  40. package/dist/skills/index.js.map +2 -2
  41. package/dist/spectrum/index.js +5 -1
  42. package/dist/spectrum/index.js.map +3 -3
  43. package/dist/spectrum/memory-port.js +64 -0
  44. package/dist/spectrum/memory-port.js.map +7 -0
  45. package/dist/types/agents.d.ts +7 -0
  46. package/dist/types/client.d.ts +3 -0
  47. package/dist/types/control.d.ts +2 -1
  48. package/dist/types/host.d.ts +2 -0
  49. package/dist/types/memory/context.d.ts +27 -0
  50. package/dist/types/memory/format.d.ts +67 -0
  51. package/dist/types/memory/index.d.ts +12 -0
  52. package/dist/types/memory/prompt.d.ts +48 -0
  53. package/dist/types/memory/runtime.d.ts +45 -0
  54. package/dist/types/memory/store.d.ts +41 -0
  55. package/dist/types/roles/frontmatter.d.ts +1 -1
  56. package/dist/types/roles/roles.d.ts +8 -0
  57. package/dist/types/scoops/cli.d.ts +1 -0
  58. package/dist/types/scoops/index.d.ts +1 -0
  59. package/dist/types/scoops/requests.d.ts +1 -1
  60. package/dist/types/scoops/service.d.ts +3 -0
  61. package/dist/types/services.d.ts +15 -0
  62. package/dist/types/spectrum/index.d.ts +3 -0
  63. package/dist/types/spectrum/memory-port.d.ts +12 -0
  64. package/package.json +4 -4
  65. package/packages/vfs-root/skills/memory/SKILL.md +48 -0
@@ -0,0 +1,27 @@
1
+ import type { Context } from '@earendil-works/chord';
2
+ import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
3
+ export declare const CANDIDATES: string[];
4
+ export declare const TRUSTED_ROOTS: string[];
5
+ export declare const UNTRUSTED = "outside /home: mounted folders and other roots load once SLICC can trust a folder";
6
+ export type ContextFile = {
7
+ path: string;
8
+ content: string;
9
+ };
10
+ export type Skipped = {
11
+ path: string;
12
+ reason: string;
13
+ };
14
+ export type ContextFiles = {
15
+ files: ContextFile[];
16
+ skipped: Skipped[];
17
+ };
18
+ type Files = Pick<ExecutionEnv, 'readTextFile' | 'canonicalPath'>;
19
+ export declare function trusted(path: string): boolean;
20
+ export declare function loadContextFiles(env: Files, options: {
21
+ cwd: string;
22
+ agentDir: string;
23
+ global?: boolean;
24
+ project?: boolean;
25
+ }, context: Context): Promise<ContextFiles>;
26
+ export declare function renderContextFiles({ files, skipped }: ContextFiles): string | undefined;
27
+ export {};
@@ -0,0 +1,67 @@
1
+ export type MemoryTag = 'user' | 'feedback' | 'project';
2
+ export interface MemoryEntry {
3
+ id: string;
4
+ scope: string;
5
+ section: string;
6
+ title: string;
7
+ body: string;
8
+ tag: MemoryTag | null;
9
+ updatedAt: number;
10
+ source: 'entry' | 'notes';
11
+ }
12
+ export interface MemoryScope {
13
+ id: string;
14
+ label: string;
15
+ group?: 'cones' | 'roles';
16
+ }
17
+ export type Entry = {
18
+ title: string;
19
+ tag: MemoryTag | null;
20
+ body: string;
21
+ };
22
+ export type Section = {
23
+ name: string;
24
+ intro: string;
25
+ entries: Entry[];
26
+ };
27
+ export type MemoryDoc = {
28
+ head: string;
29
+ sections: Section[];
30
+ };
31
+ export declare const MEMORY_FILE = "MEMORY.md";
32
+ export declare const NOTES = "Notes";
33
+ export declare const MAX_LINES = 200;
34
+ export declare const MAX_BYTES: number;
35
+ export declare function slugOf(text: string): string;
36
+ export declare function parseMemory(text: string): MemoryDoc;
37
+ export declare function serializeMemory(doc: MemoryDoc): string;
38
+ export declare function memoryEntries(doc: MemoryDoc, scope: string, updatedAt: number): MemoryEntry[];
39
+ export type Change = {
40
+ kind: 'save';
41
+ id?: string;
42
+ section: string;
43
+ title: string;
44
+ body: string;
45
+ tag: MemoryTag | null;
46
+ } | {
47
+ kind: 'remove';
48
+ id?: string;
49
+ section?: string;
50
+ title?: string;
51
+ };
52
+ export declare function oneLine(text: string): string;
53
+ export declare function demote(body: string): string;
54
+ export declare function applyChange(doc: MemoryDoc, scope: string, change: Change): {
55
+ doc: MemoryDoc;
56
+ found: boolean;
57
+ };
58
+ export declare function excerpt(text: string): {
59
+ text: string;
60
+ capped: boolean;
61
+ };
62
+ export declare function byteLength(text: string): number;
63
+ export declare const REDACTED = "[redacted]";
64
+ export declare function redactSecrets(text: string): {
65
+ text: string;
66
+ count: number;
67
+ };
@@ -0,0 +1,12 @@
1
+ import type { Context } from '@earendil-works/chord';
2
+ import { type Extension, type Registry, type ToolRegistration } from '@earendil-works/pi-durable';
3
+ import { type MemoryAttach, type MemoryRuntime } from './runtime.ts';
4
+ export { MEMORY_WRITE, whoIs } from './prompt.ts';
5
+ export type { MemoryAttach, MemoryDraft, MemoryRuntime } from './runtime.ts';
6
+ export { USAGE } from './runtime.ts';
7
+ export interface MemorySetup {
8
+ extension: Extension;
9
+ tools: readonly ToolRegistration[];
10
+ attach(options: MemoryAttach, context: Context): Promise<MemoryRuntime>;
11
+ }
12
+ export declare function setupMemory(registry: Registry): MemorySetup;
@@ -0,0 +1,48 @@
1
+ import type { Context } from '@earendil-works/chord';
2
+ import { Type } from '@earendil-works/pi-ai';
3
+ import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
4
+ import type { Agents, AgentsState, ScoopRecord } from '../agents.ts';
5
+ import { type MemoryFiles, type Place, type Written } from './store.ts';
6
+ export declare const MEMORY_WRITE = "memory_write";
7
+ export type Host = {
8
+ agents: Agents;
9
+ env: ExecutionEnv;
10
+ home: string;
11
+ files: MemoryFiles;
12
+ changed: (context: Context) => Promise<void>;
13
+ };
14
+ export type Who = {
15
+ kind: 'cone';
16
+ id: string;
17
+ } | {
18
+ kind: 'scoop';
19
+ id: string;
20
+ record: ScoopRecord;
21
+ } | {
22
+ kind: 'other';
23
+ };
24
+ type Problem = {
25
+ problem: string;
26
+ };
27
+ export declare function whoIs(state: Readonly<AgentsState>, conversation: number): Who;
28
+ export declare function ownPlace(host: Host, who: Who, cwd: string, context: Context): Promise<Place | Problem>;
29
+ export declare function contextSection(ready: Promise<Host>): import("@earendil-works/pi-durable").PromptSection<import("@earendil-works/pi-durable").ToolRegistration>;
30
+ export declare function memorySection(ready: Promise<Host>): import("@earendil-works/pi-durable").PromptSection<import("@earendil-works/pi-durable").ToolRegistration>;
31
+ type Args = {
32
+ section: string;
33
+ title: string;
34
+ body?: string;
35
+ tag?: 'user' | 'feedback' | 'project';
36
+ remove?: boolean;
37
+ scope?: 'own' | 'global';
38
+ };
39
+ export declare function writeAnswer(args: Args, place: Place, written: Written): string;
40
+ export declare function memoryWriteTool(ready: Promise<Host>): import("@earendil-works/pi-durable").ToolRegistration<Type.TObject<{
41
+ section: Type.TString;
42
+ title: Type.TString;
43
+ body: Type.TOptional<Type.TString>;
44
+ tag: Type.TOptional<Type.TUnion<[Type.TLiteral<"user">, Type.TLiteral<"feedback">, Type.TLiteral<"project">]>>;
45
+ remove: Type.TOptional<Type.TBoolean>;
46
+ scope: Type.TOptional<Type.TUnion<[Type.TLiteral<"own">, Type.TLiteral<"global">]>>;
47
+ }>, import("@earendil-works/chord").JsonValue>;
48
+ export {};
@@ -0,0 +1,45 @@
1
+ import { type Context, type ReplicatedState } from '@earendil-works/chord';
2
+ import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
3
+ import type { Agents } from '../agents.ts';
4
+ import type { Role } from '../roles/roles.ts';
5
+ import { type MemoryEntry, type MemoryScope, type MemoryTag } from './format.ts';
6
+ import type { Host } from './prompt.ts';
7
+ import { type Place } from './store.ts';
8
+ export type Answer = {
9
+ code: number;
10
+ out: string;
11
+ };
12
+ export interface MemoryDraft {
13
+ id?: string;
14
+ scope: string;
15
+ section: string;
16
+ title: string;
17
+ body: string;
18
+ tag: MemoryTag | null;
19
+ }
20
+ export interface MemoryRuntime {
21
+ readonly memories: ReplicatedState<MemoryEntry[]>;
22
+ readonly scopes: ReplicatedState<MemoryScope[]>;
23
+ save(draft: MemoryDraft, context: Context): Promise<MemoryEntry>;
24
+ remove(id: string, context: Context): Promise<boolean>;
25
+ command(argv: readonly string[], caller: string | null, context: Context): Promise<Answer>;
26
+ reload(context: Context): Promise<void>;
27
+ close(context: Context): Promise<void>;
28
+ }
29
+ export interface MemoryAttach {
30
+ agents: Agents;
31
+ env: ExecutionEnv;
32
+ home: string;
33
+ reloadMs: number;
34
+ roles?: (context: Context) => Promise<{
35
+ roles: readonly Role[];
36
+ } | undefined>;
37
+ }
38
+ export declare const USAGE = "usage:\n memory show [<scope>] print a memory file (yours by default)\n memory scopes every memory scope, its entries and its file\n\nScopes: global (everyone), a cone's id, or role:<path> for a role's memory.\nAgents write memory with the memory_write tool; the files are plain markdown you can edit.\n";
39
+ type Listed = Place & {
40
+ group?: 'cones' | 'roles';
41
+ name: string;
42
+ };
43
+ export declare function listPlaces(options: MemoryAttach, context: Context): Promise<Listed[]>;
44
+ export declare function attachMemory(options: MemoryAttach, connect: (host: Host) => void, context: Context): Promise<MemoryRuntime>;
45
+ export {};
@@ -0,0 +1,41 @@
1
+ import type { Context } from '@earendil-works/chord';
2
+ import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
3
+ import { type Change, type MemoryEntry } from './format.ts';
4
+ export declare const GLOBAL = "global";
5
+ export declare const ROLE_PREFIX = "role:";
6
+ export type RoleMemory = {
7
+ scope: 'user' | 'project';
8
+ path: string;
9
+ };
10
+ export type Place = {
11
+ scope: string;
12
+ file: string;
13
+ label: string;
14
+ };
15
+ export type Written = {
16
+ entry: MemoryEntry | null;
17
+ found: boolean;
18
+ bytes: number;
19
+ redacted: number;
20
+ file: string;
21
+ };
22
+ export declare function memoryRoot(home: string): string;
23
+ export declare function roleRoot(home: string): string;
24
+ export declare function safePath(path: string): string | null;
25
+ export declare function placeOf(home: string, scope: string): Place | null;
26
+ export declare function projectRoot(env: Pick<ExecutionEnv, 'exists'>, cwd: string, context: Context): Promise<string | null>;
27
+ export declare function rolePlace(env: Pick<ExecutionEnv, 'exists'>, home: string, memory: RoleMemory, cwd: string, context: Context): Promise<Place | {
28
+ problem: string;
29
+ }>;
30
+ type Files = Pick<ExecutionEnv, 'readTextFile' | 'writeFile' | 'createDir' | 'canonicalPath' | 'fileInfo'>;
31
+ export declare class MemoryFiles {
32
+ #private;
33
+ constructor(env: Files);
34
+ read(file: string, context: Context): Promise<{
35
+ text: string;
36
+ updatedAt: number;
37
+ } | null>;
38
+ entries(place: Place, context: Context): Promise<MemoryEntry[]>;
39
+ change(place: Place, change: Change, context: Context): Promise<Written>;
40
+ }
41
+ export {};
@@ -4,4 +4,4 @@ export interface Frontmatter {
4
4
  body: string;
5
5
  problems: string[];
6
6
  }
7
- export declare function parseFrontmatter(text: string): Frontmatter;
7
+ export declare function parseFrontmatter(text: string, mappings?: readonly string[]): Frontmatter;
@@ -1,5 +1,7 @@
1
1
  import type { Context } from '@earendil-works/chord';
2
2
  import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
3
+ import type { RoleMemory } from '../memory/store.ts';
4
+ import { type FrontmatterValue } from './frontmatter.ts';
3
5
  export type RoleSource = 'builtin' | 'package' | 'user' | 'project';
4
6
  export type Thinking = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
5
7
  export interface Role {
@@ -12,6 +14,11 @@ export interface Role {
12
14
  thinking?: Thinking;
13
15
  aliases: string[];
14
16
  output?: string;
17
+ memory?: RoleMemory;
18
+ context?: {
19
+ project: boolean;
20
+ global: boolean;
21
+ };
15
22
  source: RoleSource;
16
23
  path: string;
17
24
  }
@@ -32,6 +39,7 @@ export interface RoleSourceDir {
32
39
  source: RoleSource;
33
40
  dir: string;
34
41
  }
42
+ export declare function roleMemory(value: FrontmatterValue): RoleMemory | undefined;
35
43
  export declare function parseRole(text: string, source: RoleSource, path: string, warnings: string[]): Role | undefined;
36
44
  export interface LoadOptions {
37
45
  files: RoleFiles;
@@ -20,6 +20,7 @@ export interface CliOptions {
20
20
  alive?: (pid: number) => Promise<boolean>;
21
21
  now?: () => number;
22
22
  sprinkle?: (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;
23
+ memory?: (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;
23
24
  }
24
25
  export type Deps = CliOptions & {
25
26
  now: () => number;
@@ -25,6 +25,7 @@ export interface AttachOptions {
25
25
  alive?: (pid: number) => Promise<boolean>;
26
26
  reads: () => readonly string[];
27
27
  sprinkle?: CliOptions['sprinkle'];
28
+ memory?: CliOptions['memory'];
28
29
  }
29
30
  export interface ScoopsRuntime {
30
31
  roles(context: Context): Promise<Roles>;
@@ -6,7 +6,7 @@ export declare const PROTOCOL = "slicc-agent/1";
6
6
  export declare const STALE_MS: number;
7
7
  export interface Request {
8
8
  id: string;
9
- as: 'agent' | 'subagent' | 'sprinkle';
9
+ as: 'agent' | 'subagent' | 'sprinkle' | 'memory';
10
10
  caller: string;
11
11
  cwd: string;
12
12
  pid: number | null;
@@ -1,5 +1,6 @@
1
1
  import type { Context } from '@earendil-works/chord';
2
2
  import { type AgentChange, type AnyTask, type Conversation, type Harness, type ToolRegistration } from '@earendil-works/pi-durable';
3
+ import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
3
4
  import { type Agents, type AgentsState, type Mark, type ScoopRecord } from '../agents.ts';
4
5
  import type { ProcessGroups } from '../kernel/groups.ts';
5
6
  import type { Licks } from '../licks/licks.ts';
@@ -47,6 +48,7 @@ export interface ScoopsHost {
47
48
  groups?: ProcessGroups;
48
49
  tools?: readonly ToolRegistration[];
49
50
  reads?: () => readonly string[];
51
+ files?: Pick<ExecutionEnv, 'remove' | 'createDir'>;
50
52
  }
51
53
  export interface Rewound {
52
54
  stopped: string[];
@@ -73,6 +75,7 @@ export interface SpawnRequest {
73
75
  read: string[];
74
76
  };
75
77
  cwd?: string;
78
+ origin?: string;
76
79
  instructions?: string;
77
80
  target?: string | null;
78
81
  asker?: string | null;
@@ -1,5 +1,6 @@
1
1
  import { type Context, type JsonValue, type ReplicatedState } from '@earendil-works/chord';
2
2
  import type { ConversationView } from '@earendil-works/pi-durable';
3
+ import type { MemoryEntry, MemoryScope, MemoryTag } from './memory/format.ts';
3
4
  import type { Sprinkle } from './sprinkles/kind.ts';
4
5
  export type SendMode = 'steer' | 'followUp' | 'reject';
5
6
  export interface SendRequest {
@@ -61,6 +62,18 @@ export interface AgentControl {
61
62
  delivered: boolean;
62
63
  }>;
63
64
  sprinkleCall(sprinkleId: string, method: string, args: JsonValue[], context: Context): Promise<JsonValue>;
65
+ memorySave(draft: MemoryDraft, context: Context): Promise<MemoryEntry>;
66
+ memoryRemove(id: string, context: Context): Promise<{
67
+ removed: boolean;
68
+ }>;
69
+ }
70
+ export interface MemoryDraft {
71
+ id: string | null;
72
+ scope: string;
73
+ section: string;
74
+ title: string;
75
+ body: string;
76
+ tag: MemoryTag | null;
64
77
  }
65
78
  export type Created = {
66
79
  id: string;
@@ -120,6 +133,8 @@ export interface AgentTranscript {
120
133
  readonly views: ReplicatedState<Record<string, ConversationView>>;
121
134
  readonly commands: ReplicatedState<Command[]>;
122
135
  readonly sprinkles: ReplicatedState<Sprinkle[]>;
136
+ readonly memories: ReplicatedState<MemoryEntry[]>;
137
+ readonly memoryScopes: ReplicatedState<MemoryScope[]>;
123
138
  }
124
139
  export interface Command {
125
140
  name: string;
@@ -1,9 +1,11 @@
1
1
  import type { AgentConnection } from '../client.ts';
2
2
  import { AgentAdapter } from './agent-port.ts';
3
+ import { MemoryAdapter } from './memory-port.ts';
3
4
  import { type Login, SettingsAdapter } from './settings-port.ts';
4
5
  import { SprinkleAdapter } from './sprinkle-port.ts';
5
6
  import { TrayAdapter } from './tray-port.ts';
6
7
  export { AgentAdapter, CONE } from './agent-port.ts';
8
+ export { MemoryAdapter } from './memory-port.ts';
7
9
  export { assistant, errorAction, errorPart, isBusy, queued, textOf, toMessages, } from './messages.ts';
8
10
  export { type Login, SETTINGS_KEY, SettingsAdapter } from './settings-port.ts';
9
11
  export { SprinkleAdapter } from './sprinkle-port.ts';
@@ -16,4 +18,5 @@ export declare function createAgentModel(connection: AgentConnection, options?:
16
18
  settings: SettingsAdapter;
17
19
  tray: TrayAdapter;
18
20
  sprinkles: SprinkleAdapter;
21
+ memory: MemoryAdapter;
19
22
  };
@@ -0,0 +1,12 @@
1
+ import type { Memory, MemoryDraft, MemoryEvents, MemoryPort } from '@ai-ecoverse/slicc-spectrum/ui';
2
+ import type { AgentConnection } from '../client.ts';
3
+ import { type MemoryScope } from '../memory/format.ts';
4
+ import { Emitter } from './emitter.ts';
5
+ export declare class MemoryAdapter extends Emitter<MemoryEvents> implements MemoryPort {
6
+ #private;
7
+ constructor(connection: AgentConnection);
8
+ list(): readonly Memory[];
9
+ scopes(): readonly MemoryScope[];
10
+ save(draft: MemoryDraft): Memory;
11
+ remove(id: string): void;
12
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc-agent",
3
- "version": "3.13.1",
3
+ "version": "3.15.0",
4
4
  "description": "SLICC's agent core on pi durable: an agent worker, session storage, remoting and pi extensions",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -61,8 +61,8 @@
61
61
  "release": "semantic-release"
62
62
  },
63
63
  "devDependencies": {
64
- "@ai-ecoverse/slicc-shared-web": "1.9.0",
65
- "@ai-ecoverse/slicc-spectrum": "1.27.3",
64
+ "@ai-ecoverse/slicc-shared-web": "1.10.0",
65
+ "@ai-ecoverse/slicc-spectrum": "1.28.0",
66
66
  "@ai-ecoverse/wasm-bash": "5.3.0-8",
67
67
  "@ai-ecoverse/wasm-coreutils": "9.7.0-3",
68
68
  "@biomejs/biome": "2.5.15",
@@ -87,7 +87,7 @@
87
87
  "@sqlite.org/sqlite-wasm": "3.53.4-build2"
88
88
  },
89
89
  "peerDependencies": {
90
- "@ai-ecoverse/slicc-spectrum": "^1.27.2"
90
+ "@ai-ecoverse/slicc-spectrum": "^1.28.0"
91
91
  },
92
92
  "peerDependenciesMeta": {
93
93
  "@ai-ecoverse/slicc-spectrum": {
@@ -0,0 +1,48 @@
1
+ ---
2
+ name: memory
3
+ description: Use this when the user asks what you remember, tells you to remember or forget something, corrects how you work, or when you learn a durable fact worth keeping across conversations. Covers the memory files, the memory_write tool, scopes and the `memory` command.
4
+ ---
5
+
6
+ # Memory
7
+
8
+ Memory is plain markdown, one `MEMORY.md` per scope, shown to you in the `memory` section of your system prompt (the first 200 lines of each file):
9
+
10
+ | Scope | File | Who writes it |
11
+ | --- | --- | --- |
12
+ | `global` | `~/.pi/agent/memory/MEMORY.md` | cones, for every agent |
13
+ | a cone (`cone`, `cone-2`, …) | `~/.pi/agent/memory/<cone>/MEMORY.md` | that cone |
14
+ | a role (`role:<path>`) | `~/.pi/agent/agent-memory/<path>/MEMORY.md` | scoops of a role with `memory: { scope: user, path: <path> }` |
15
+
16
+ A role with `memory: { scope: project, path: <path> }` keeps it in `<project>/.pi/agent-memory/<path>/MEMORY.md`, where the project is the nearest folder above the scoop's working directory with a `.pi` or `.git`, inside /home.
17
+
18
+ ## Writing
19
+
20
+ Use `memory_write` rather than editing the files:
21
+
22
+ - `section` and `title` name the entry; saving the same section and title again replaces it.
23
+ - `tag` is `user` (who the user is), `feedback` (how they want you to work) or `project` (facts about their work).
24
+ - `remove: true` forgets an entry. `scope: "global"` writes the shared file (cones only).
25
+
26
+ Keep entries short and durable: a preference, a correction, a convention, a project fact. Don't save one-off task details, transcripts, or anything secret (keys, tokens, passwords, signed or launch URLs); memory_write redacts what looks like one. Each file holds 16 KB; when it's full, merge or remove entries before adding.
27
+
28
+ The file format, if you or the user edit it by hand:
29
+
30
+ ```markdown
31
+ ## Preferences
32
+
33
+ ### Lead with the result
34
+ tag: feedback
35
+
36
+ Keep replies short. Lead with the result, then the detail.
37
+ ```
38
+
39
+ ## The `memory` command
40
+
41
+ - `memory scopes` lists every scope with its entry count and file.
42
+ - `memory show [<scope>]` prints a memory file, yours by default.
43
+
44
+ The user sees and edits the same entries in the Memory panel.
45
+
46
+ ## Instructions are not memory
47
+
48
+ `AGENTS.md` and `CLAUDE.md` files hold instructions the user wrote: `~/.pi/agent/AGENTS.md` and the ones on your working directory's path inside /home are in the `project_context` section. Files in mounted folders are listed there as not loaded; they load once SLICC can trust a folder.