dsh-context-memory 0.7.1 → 0.9.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.
package/lib/types.d.ts CHANGED
@@ -13,15 +13,129 @@
13
13
  export type MemoryKind = 'fact' | 'decision' | 'preference' | 'pitfall';
14
14
  /** Who wrote the memory. Provenance, so "why does the agent think it knows this" has an answer. */
15
15
  export type MemorySource = 'user' | 'agent' | 'plugin';
16
+ /**
17
+ * Where the memory lives.
18
+ *
19
+ * `project` is a convention of one checkout; `user` is a working preference that holds
20
+ * everywhere. The distinction is scope, not importance — both are equally worth
21
+ * recalling, but they belong to different populations and must not leak into each other.
22
+ */
23
+ export type MemoryScope = 'project' | 'user';
16
24
  /** A memory is active until something explicitly supersedes it. */
17
25
  export type MemoryStatus = 'active' | 'superseded';
26
+ /**
27
+ * Which populations a search may draw from.
28
+ *
29
+ * `guidance` is the only one the push path may use: active and not contradicted. The
30
+ * others exist for questions that are *about* the log rather than for guidance —
31
+ * "what did we decide before", "what did the check disprove" — which only a reader who
32
+ * asked for them by name should receive.
33
+ */
34
+ export type MemoryTarget = 'guidance' | 'contradicted' | 'superseded' | 'all';
18
35
  /** The same three-outcome model dsh-verdict uses: inability to check is not failure. */
19
36
  export type GuardOutcome = 'passed' | 'violated' | 'broken';
20
- /** An executable check compiled from a memory statement. */
21
- export interface Guard {
22
- command: string;
37
+ /**
38
+ * An executable check compiled from a memory statement.
39
+ *
40
+ * A check names one predicate and its operands — never a program. That is what keeps
41
+ * memory text from becoming something to execute: the statement contributes paths,
42
+ * keys, and search strings, and the evaluation is `fs` plus `JSON.parse`, not a shell.
43
+ *
44
+ * The `kind` discriminates the predicate. Check `kind` before reading an operand: the
45
+ * operands each kind needs differ, so a field that exists on one is absent on another.
46
+ *
47
+ * The file predicates (`exists` / `absent` / `contains` / `lacks`) answer "is this text in
48
+ * this file". The structured predicates (`depends` / `script` / `option` / `lineLimit`)
49
+ * answer questions about a *parsed* file, which is a different thing: `contains` would say
50
+ * `"yarn"` is in `package.json` because the word appears in a comment, a description, or
51
+ * inside some other key. Parsing is still in-process and still has no program in it.
52
+ */
53
+ export type Guard = {
54
+ kind: 'exists';
55
+ path: string;
56
+ source: 'template';
57
+ } | {
58
+ kind: 'absent';
59
+ path: string;
60
+ source: 'template';
61
+ } | {
62
+ kind: 'contains';
63
+ path: string;
64
+ needle: string;
65
+ source: 'template';
66
+ } | {
67
+ kind: 'lacks';
68
+ path: string;
69
+ needle: string;
23
70
  source: 'template';
24
71
  }
72
+ /**
73
+ * `package.json` declares `name` in any of `dependencies` / `devDependencies` /
74
+ * `peerDependencies` / `optionalDependencies`. All four count: a memory saying "we use
75
+ * X" is not wrong because X arrived as a peer.
76
+ */
77
+ | {
78
+ kind: 'depends';
79
+ name: string;
80
+ source: 'template';
81
+ absent?: false;
82
+ }
83
+ /** `package.json` declares no such dependency. */
84
+ | {
85
+ kind: 'depends';
86
+ name: string;
87
+ source: 'template';
88
+ absent: true;
89
+ }
90
+ /** `package.json` has a `scripts` entry `name`, and `cmd` (when given) is its value. */
91
+ | {
92
+ kind: 'script';
93
+ name: string;
94
+ cmd?: string;
95
+ source: 'template';
96
+ absent?: false;
97
+ }
98
+ /** `package.json` has no such script. */
99
+ | {
100
+ kind: 'script';
101
+ name: string;
102
+ source: 'template';
103
+ absent: true;
104
+ }
105
+ /**
106
+ * A JSON config file sets `option`, and `value` (when given) is what it is set to.
107
+ *
108
+ * `value: true` plus `absent: true` is the negation of "the option is on" — it is
109
+ * satisfied by the key being absent *and* by it being explicitly `false`, because
110
+ * "strict is not enabled" is true in both cases.
111
+ */
112
+ | {
113
+ kind: 'option';
114
+ path: string;
115
+ option: string;
116
+ value?: boolean;
117
+ source: 'template';
118
+ absent?: false;
119
+ }
120
+ /** The same config option is not set to `value` (or is not set at all). */
121
+ | {
122
+ kind: 'option';
123
+ path: string;
124
+ option: string;
125
+ value?: boolean;
126
+ source: 'template';
127
+ absent: true;
128
+ }
129
+ /** The file has at most `max` lines, or at least `min`. */
130
+ | {
131
+ kind: 'lineLimit';
132
+ path: string;
133
+ max?: number;
134
+ min?: number;
135
+ source: 'template';
136
+ };
137
+ /** The predicates above, as a value to switch on. */
138
+ export type GuardKind = Guard['kind'];
25
139
  /** The immutable payload recorded by a `remember` event. */
26
140
  export interface Memory {
27
141
  id: string;
@@ -30,6 +144,13 @@ export interface Memory {
30
144
  text: string;
31
145
  kind: MemoryKind;
32
146
  source: MemorySource;
147
+ /**
148
+ * Which log this memory was written to.
149
+ *
150
+ * Absent in logs written before 0.9.0, which were project-only by construction; the
151
+ * fold reads a missing scope as `project`, since that is what those logs meant.
152
+ */
153
+ scope?: MemoryScope;
33
154
  createdAt: number;
34
155
  sessionId?: string;
35
156
  step?: number;
@@ -37,6 +158,8 @@ export interface Memory {
37
158
  }
38
159
  /** A memory folded together with every later event about it. */
39
160
  export interface MemoryState extends Memory {
161
+ /** Always known here: the fold derives it from the log the memory was read out of. */
162
+ scope: MemoryScope;
40
163
  status: MemoryStatus;
41
164
  supersededReason?: string;
42
165
  supersededBy?: string;
@@ -83,10 +206,47 @@ export interface Conflict {
83
206
  subject: string;
84
207
  memories: MemoryState[];
85
208
  }
209
+ /** A statement the capture heuristics noticed but did not have permission to keep. */
210
+ export interface Candidate {
211
+ id: string;
212
+ text: string;
213
+ kind: MemoryKind;
214
+ proposedAt: number;
215
+ sessionId?: string;
216
+ }
217
+ /**
218
+ * Where a candidate stands.
219
+ *
220
+ * `dismissed` is kept rather than deleted: the question was asked and answered, and a
221
+ * queue that forgets the answer asks it again on the next step.
222
+ */
223
+ export type CandidateStatus = 'pending' | 'accepted' | 'dismissed';
224
+ export interface CandidateState extends Candidate {
225
+ status: CandidateStatus;
226
+ }
227
+ /** The candidate log, folded the same way the memory log is. */
228
+ export type CandidateEvent = {
229
+ type: 'propose';
230
+ at: number;
231
+ candidate: Candidate;
232
+ } | {
233
+ type: 'decide';
234
+ at: number;
235
+ id: string;
236
+ status: Exclude<CandidateStatus, 'pending'>;
237
+ };
86
238
  /** One verification result per memory that was considered. */
87
239
  export interface VerifyResult {
88
240
  id: string;
89
241
  text: string;
242
+ /**
243
+ * The check that produced this outcome, when there was one.
244
+ *
245
+ * Reported rather than left to the caller to look up: `verify` already holds the guard
246
+ * it just ran, and a caller that wanted to describe the outcome would otherwise fold
247
+ * the whole log once per result to fetch what it was already handed.
248
+ */
249
+ guard?: Guard;
90
250
  /** `uncheckable` means no guard could be compiled — not that the memory is wrong. */
91
251
  outcome: GuardOutcome | 'uncheckable';
92
252
  exitCode: number | null;
@@ -103,12 +263,31 @@ export interface VerifySummary {
103
263
  export interface PanelPayload {
104
264
  active: MemoryState[];
105
265
  superseded: MemoryState[];
266
+ /**
267
+ * Active memories a check contradicted.
268
+ *
269
+ * Listed apart from `active` because they are a different kind of statement: still
270
+ * recorded, still visible, but no longer offered as guidance. The panel must show them
271
+ * — a memory the world disproved is the most informative record in the log — while the
272
+ * injection path must not.
273
+ */
274
+ contradicted: MemoryState[];
106
275
  conflicts: Conflict[];
276
+ /**
277
+ * Statements the capture heuristics noticed but did not have permission to keep.
278
+ *
279
+ * In the panel payload rather than folded into `active`, because they are a question
280
+ * for the user, not a memory: a candidate has no scope, no guard, and no claim on
281
+ * recall until someone accepts it.
282
+ */
283
+ candidates: CandidateState[];
107
284
  totals: {
108
285
  active: number;
109
286
  superseded: number;
287
+ contradicted: number;
110
288
  withGuard: number;
111
289
  verified: number;
112
290
  unverified: number;
291
+ candidates: number;
113
292
  };
114
293
  }
package/locale/en.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "Context memory",
4
+ "description": "Remembers what you decided across sessions, injects the relevant parts before each step, and re-checks the claims it can check."
5
+ }
6
+ }
package/locale/zh.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "跨会话记忆",
4
+ "description": "记住你在不同会话里定过的事,每次回复前自动注入相关的那几条,并重新核对能核对的部分。"
5
+ }
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-context-memory",
3
- "version": "0.7.1",
3
+ "version": "0.9.0",
4
4
  "description": "Cross-session memory for your dsh agent: remembered, recalled, and re-verified instead of assumed.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -17,14 +17,19 @@
17
17
  "types": "./lib/client/index.d.ts",
18
18
  "default": "./lib/memory.web.js"
19
19
  },
20
+ "./locale/*.json": "./locale/*.json",
21
+ "./icon": "./icon.svg",
20
22
  "./package.json": "./package.json"
21
23
  },
22
24
  "files": [
23
25
  "lib",
24
26
  "cordis.patch.yml",
27
+ "locale/*.json",
28
+ "icon.svg",
25
29
  "README.md",
26
30
  "CHANGELOG.md"
27
31
  ],
32
+ "icon": "./icon.svg",
28
33
  "keywords": [
29
34
  "dsh",
30
35
  "dsh-plugin",
@@ -62,25 +67,27 @@
62
67
  "node": ">=20"
63
68
  },
64
69
  "peerDependencies": {
65
- "@deepseek-ai/cordis": "~4.0.4",
66
- "@deepseek-ai/dsh-agent": "0.2.0-rc.2",
67
- "@deepseek-ai/dsh-llm": "0.2.0-rc.2",
68
- "@deepseek-ai/dsh-session": "0.2.0-rc.2"
70
+ "@deepseek-ai/cordis": "~4.0.5",
71
+ "@deepseek-ai/dsh-agent": "^0.2.1-rc.2",
72
+ "@deepseek-ai/dsh-home-paths": "^0.2.1-rc.2",
73
+ "@deepseek-ai/dsh-llm": "^0.2.1-rc.2",
74
+ "@deepseek-ai/dsh-session": "^0.2.1-rc.2",
75
+ "@deepseek-ai/dsh-tools": "^0.2.1-rc.2"
69
76
  },
70
77
  "devDependencies": {
71
- "@deepseek-ai/cordis": "~4.0.4",
72
- "@deepseek-ai/dsh-client-locale": "0.2.0-rc.2",
73
- "@deepseek-ai/dsh-client-ui-renderer": "0.2.0-rc.2",
74
- "@deepseek-ai/dsh-client-ui-settings": "0.2.0-rc.2",
75
- "@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.2",
76
- "@deepseek-ai/dsh-agent": "0.2.0-rc.2",
77
- "@deepseek-ai/dsh-attachment": "0.2.0-rc.2",
78
- "@deepseek-ai/dsh-brand": "0.2.0-rc.2",
79
- "@deepseek-ai/dsh-invariants": "0.2.0-rc.2",
80
- "@deepseek-ai/dsh-llm": "0.2.0-rc.2",
81
- "@deepseek-ai/dsh-session": "0.2.0-rc.2",
82
- "@deepseek-ai/dsh-timeout": "0.2.0-rc.2",
83
- "@deepseek-ai/dsh-tools": "0.2.0-rc.2",
78
+ "@deepseek-ai/cordis": "~4.0.5",
79
+ "@deepseek-ai/dsh-agent": "0.2.1-rc.2",
80
+ "@deepseek-ai/dsh-client-locale": "0.2.1-rc.2",
81
+ "@deepseek-ai/dsh-client-ui-renderer": "0.2.1-rc.2",
82
+ "@deepseek-ai/dsh-client-ui-settings": "0.2.1-rc.2",
83
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.1-rc.2",
84
+ "@deepseek-ai/dsh-home-paths": "0.2.1-rc.2",
85
+ "@deepseek-ai/dsh-llm": "0.2.1-rc.2",
86
+ "@deepseek-ai/dsh-sandbox": "0.2.1-rc.2",
87
+ "@deepseek-ai/dsh-scope": "0.2.1-rc.2",
88
+ "@deepseek-ai/dsh-session": "0.2.1-rc.2",
89
+ "@deepseek-ai/dsh-tools": "0.2.1-rc.2",
90
+ "@deepseek-ai/dsh-working-directory": "0.2.1-rc.2",
84
91
  "@types/node": "^22.20.3",
85
92
  "@types/react": "^19.3.0",
86
93
  "esbuild": "^0.28.2",