@jmtrin/opencode-kevin 0.7.0 → 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.
Files changed (70) hide show
  1. package/README.md +254 -12
  2. package/dist/migrations/009_v08_team.sql +100 -0
  3. package/dist/migrations/010_v09_native.sql +78 -0
  4. package/dist/plugin/ArtifactWriter.d.ts +28 -0
  5. package/dist/plugin/ArtifactWriter.js +35 -2
  6. package/dist/plugin/ArtifactWriter.js.map +1 -1
  7. package/dist/plugin/ContextInjector.d.ts +9 -0
  8. package/dist/plugin/ContextInjector.js +14 -3
  9. package/dist/plugin/ContextInjector.js.map +1 -1
  10. package/dist/plugin/Curator.d.ts +22 -2
  11. package/dist/plugin/Curator.js +56 -14
  12. package/dist/plugin/Curator.js.map +1 -1
  13. package/dist/plugin/HookLiveness.d.ts +81 -0
  14. package/dist/plugin/HookLiveness.js +324 -0
  15. package/dist/plugin/HookLiveness.js.map +1 -0
  16. package/dist/plugin/InjectionLedger.d.ts +6 -0
  17. package/dist/plugin/InjectionLedger.js +6 -0
  18. package/dist/plugin/InjectionLedger.js.map +1 -1
  19. package/dist/plugin/Materializer.d.ts +29 -5
  20. package/dist/plugin/Materializer.js +48 -16
  21. package/dist/plugin/Materializer.js.map +1 -1
  22. package/dist/plugin/MemoryService.d.ts +34 -5
  23. package/dist/plugin/MemoryService.js +215 -7
  24. package/dist/plugin/MemoryService.js.map +1 -1
  25. package/dist/plugin/Migrate.d.ts +1 -0
  26. package/dist/plugin/Migrate.js +74 -3
  27. package/dist/plugin/Migrate.js.map +1 -1
  28. package/dist/plugin/RepoIdentity.d.ts +124 -0
  29. package/dist/plugin/RepoIdentity.js +301 -0
  30. package/dist/plugin/RepoIdentity.js.map +1 -0
  31. package/dist/plugin/Retrospective.js +18 -0
  32. package/dist/plugin/Retrospective.js.map +1 -1
  33. package/dist/plugin/SharedLayer.d.ts +159 -0
  34. package/dist/plugin/SharedLayer.js +463 -0
  35. package/dist/plugin/SharedLayer.js.map +1 -0
  36. package/dist/plugin/host.d.ts +70 -0
  37. package/dist/plugin/host.js +251 -0
  38. package/dist/plugin/host.js.map +1 -0
  39. package/dist/plugin/index.d.ts +30 -1
  40. package/dist/plugin/index.js +582 -12
  41. package/dist/plugin/index.js.map +1 -1
  42. package/dist/plugin/kevin_approve.js +7 -4
  43. package/dist/plugin/kevin_approve.js.map +1 -1
  44. package/dist/plugin/kevin_audit.d.ts +48 -1
  45. package/dist/plugin/kevin_audit.js +179 -3
  46. package/dist/plugin/kevin_audit.js.map +1 -1
  47. package/dist/plugin/kevin_doctor.d.ts +57 -0
  48. package/dist/plugin/kevin_doctor.js +168 -0
  49. package/dist/plugin/kevin_doctor.js.map +1 -0
  50. package/dist/plugin/kevin_native.d.ts +29 -0
  51. package/dist/plugin/kevin_native.js +80 -0
  52. package/dist/plugin/kevin_native.js.map +1 -0
  53. package/dist/plugin/metrics.d.ts +1 -1
  54. package/dist/plugin/metrics.js +9 -0
  55. package/dist/plugin/metrics.js.map +1 -1
  56. package/dist/plugin/native.d.ts +92 -0
  57. package/dist/plugin/native.js +191 -0
  58. package/dist/plugin/native.js.map +1 -0
  59. package/dist/plugin/okf-export.d.ts +2 -2
  60. package/dist/plugin/okf-export.js +15 -7
  61. package/dist/plugin/okf-export.js.map +1 -1
  62. package/dist/plugin/okf.d.ts +107 -0
  63. package/dist/plugin/okf.js +304 -0
  64. package/dist/plugin/okf.js.map +1 -0
  65. package/dist/plugin/replay-types.d.ts +29 -287
  66. package/dist/plugin/replay-types.js +145 -53
  67. package/dist/plugin/replay-types.js.map +1 -1
  68. package/migrations/009_v08_team.sql +100 -0
  69. package/migrations/010_v09_native.sql +78 -0
  70. package/package.json +2 -3
@@ -0,0 +1,124 @@
1
+ import type { ArtifactWriter } from "./ArtifactWriter.js";
2
+ import type { HostSurface } from "./host.js";
3
+ /**
4
+ * The four sources `resolve()` tries, in order (plan §5.2, D9-13).
5
+ */
6
+ export type IdentitySource = "declared" | "remote" | "host" | "path";
7
+ /**
8
+ * The outcome of resolving a repository identity.
9
+ */
10
+ export interface ResolvedIdentity {
11
+ /** The repository-scoped id every Team scope is keyed on. */
12
+ repoId: string;
13
+ /** Which source produced `repoId`. */
14
+ source: IdentitySource;
15
+ /**
16
+ * A short, non-secret description of how the id was derived,
17
+ * surfaced by `kevin_project show`. Never contains a credential
18
+ * or an absolute path.
19
+ */
20
+ evidence: string;
21
+ /** The v0.7.0 project scope, always returned regardless of source. */
22
+ projectId: string;
23
+ }
24
+ /**
25
+ * Read the first `url = …` value inside `[remote "<name>"]` of a
26
+ * `.git/config`-style INI text.
27
+ *
28
+ * Line-oriented reader, not an INI library: tracks the current
29
+ * `[section "sub"]` header, tolerates tabs, spaces around `=`,
30
+ * CRLF, and comment lines. Returns `null` on anything unrecognised
31
+ * and never throws — on any input, including binary.
32
+ */
33
+ export declare function parseGitConfigRemote(text: string, name?: string): string | null;
34
+ /**
35
+ * Fold the URL shapes git accepts into one canonical string.
36
+ *
37
+ * Steps, in order (K8-005):
38
+ * 1. strip a trailing `.git`;
39
+ * 2. strip a `scheme://` prefix;
40
+ * 3. strip everything up to and including the last `@` in the
41
+ * authority (userinfo and embedded credentials — a token must
42
+ * never reach a hash that lands in a committed file, D8-04);
43
+ * 4. strip a numeric port (`:8443`, `:443`, …) so the same repo
44
+ * served over different transports folds to one id;
45
+ * 5. rewrite the scp-style `host:path` separator to `host/path`;
46
+ * 6. strip a trailing `/`;
47
+ * 7. lowercase the whole result.
48
+ *
49
+ * Returns `null` when the result contains no `/` (e.g. a local
50
+ * path remote) — the caller falls through to the path source.
51
+ */
52
+ export declare function normalizeRemote(url: string): string | null;
53
+ /**
54
+ * Derive a repository id from a normalized remote (K8-006).
55
+ *
56
+ * The domain prefix means a repo id can never collide with a memory
57
+ * fingerprint computed over the same string, and it leaves room to
58
+ * version the derivation later.
59
+ */
60
+ export declare function computeRepoId(normalized: string): string;
61
+ /**
62
+ * Resolve the repository identity for `cwd`, trying the four
63
+ * sources in order (plan §5.2, D9-13):
64
+ *
65
+ * 1. `declared` — `.kevin/project.json` → `id` (validated as
66
+ * exactly 16 lowercase hex characters; anything else is ignored
67
+ * and falls through, because a hand-edited garbage id in a
68
+ * committed file would otherwise scope a whole team's corpus
69
+ * onto a typo);
70
+ * 2. `remote` — `.git/config` → `[remote "origin"] url`,
71
+ * normalized and hashed;
72
+ * 3. `host` — the value the host resolved for this directory,
73
+ * `host.project.worktree` first, `host.project.directory` as
74
+ * fallback; both empty or absent falls through to `path`.
75
+ * This is strictly better than `process.cwd()` — the host's own
76
+ * ToolContext documents "prefer this over `process.cwd()`" —
77
+ * but it sits below the explicit sources, because monorepos and
78
+ * D8-03's confirmed re-keying depend on `.kevin/project.json`
79
+ * winning;
80
+ * 4. `path` — `fingerprint(cwd)`, the v0.7.0 behaviour, preserved
81
+ * exactly when `host` is absent.
82
+ *
83
+ * Never throws: a directory that is not a git repository, an
84
+ * unreadable `.git/config`, a malformed `project.json`, and a host
85
+ * with no usable project fields all fall through to source 4.
86
+ * `projectId` is always returned alongside `repoId`, regardless of
87
+ * which source won.
88
+ */
89
+ export declare function resolve(cwd: string, host?: HostSurface): ResolvedIdentity;
90
+ /**
91
+ * The outcome of `initProjectFile` (K8-008).
92
+ */
93
+ export interface InitProjectResult {
94
+ /** Whether the file was written. */
95
+ ok: boolean;
96
+ /** The absolute path the file was written to, or refused. */
97
+ path: string;
98
+ /** Human-readable refusal reason when `ok` is false. */
99
+ reason?: string;
100
+ /** The pinned id when the file was written. */
101
+ id?: string;
102
+ /** The ISO-8601 Z timestamp written into the file. */
103
+ createdAt?: string;
104
+ }
105
+ /**
106
+ * Write `.kevin/project.json` pinning the repository identity (K8-008
107
+ * / plan §5.8). The id comes from the current `resolve(cwd)` — so `init`
108
+ * in a repository with a remote *pins* the remote-derived id, which is
109
+ * the point: it survives the organisation renaming the repo (a remote
110
+ * URL change would otherwise silently re-scope the corpus).
111
+ *
112
+ * The file is `{"id": "<16 hex>", "created_at": "<ISO-8601 Z>",
113
+ * "generator": "opencode-kevin/0.8.0"}` with sorted keys and a
114
+ * terminating newline (deterministic bytes, the codec discipline of
115
+ * plan §7.3). `init` refuses when the file already exists: overwriting
116
+ * it re-scopes a team's corpus, and that is `rekey`'s job (K8-009),
117
+ * with a confirmation.
118
+ *
119
+ * NOTE (K8-019): the write goes through `ArtifactWriter` in whole-file
120
+ * mode — `.kevin/project.json` is a Kevin-owned file, and D8-08 leaves
121
+ * no scenario in which a second raw write path is acceptable (asserted
122
+ * by tests/unit/single_write_path.test.ts).
123
+ */
124
+ export declare function initProjectFile(cwd: string, writer: ArtifactWriter): InitProjectResult;
@@ -0,0 +1,301 @@
1
+ import { mkdirSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { fingerprint, fnv1a64 } from "./fingerprint.js";
4
+ // ============================================================
5
+ // Kevin 0.8.0 — RepoIdentity (K8-005/K8-006 / plan §5.1, D8-04)
6
+ // v0.9.0 — host identity source (K9-006 / plan §5.2, D9-13)
7
+ // ============================================================
8
+ // Repository-derived identity that survives a clone. Two clones
9
+ // of the same remote must agree on one `repo_id` even though
10
+ // `process.cwd()` differs.
11
+ //
12
+ // This file deliberately contains no process-launching calls (D8-01)
13
+ // and no `new URL()` — the scp-style `git@host:path` form that git
14
+ // accepts and roughly half of all clones use rejects URL parsing
15
+ // (K8-005).
16
+ // ============================================================
17
+ // Comment lines git accepts inside a config section: `#` and `;`.
18
+ const COMMENT_RE = /^[#;]/;
19
+ // A declared id must be exactly 16 lowercase hex characters (K8-006).
20
+ const DECLARED_ID_RE = /^[0-9a-f]{16}$/;
21
+ const PROJECT_JSON_PATH = join(".kevin", "project.json");
22
+ const GIT_CONFIG_PATH = join(".git", "config");
23
+ /**
24
+ * Read the first `url = …` value inside `[remote "<name>"]` of a
25
+ * `.git/config`-style INI text.
26
+ *
27
+ * Line-oriented reader, not an INI library: tracks the current
28
+ * `[section "sub"]` header, tolerates tabs, spaces around `=`,
29
+ * CRLF, and comment lines. Returns `null` on anything unrecognised
30
+ * and never throws — on any input, including binary.
31
+ */
32
+ export function parseGitConfigRemote(text, name = "origin") {
33
+ // Never throw on any input, including binary and huge strings.
34
+ if (typeof text !== "string" || text.length === 0)
35
+ return null;
36
+ const lines = text.split(/\r\n|\n|\r/);
37
+ let currentSection = null;
38
+ let currentSub = null;
39
+ for (const raw of lines) {
40
+ const line = raw.trim();
41
+ if (line.length === 0)
42
+ continue;
43
+ if (COMMENT_RE.test(line))
44
+ continue;
45
+ // Section header: `[section "sub"]` or `[section]`.
46
+ if (line.startsWith("[")) {
47
+ const header = line.slice(1, line.indexOf("]"));
48
+ if (header === null)
49
+ return null;
50
+ const q = header.indexOf('"');
51
+ if (q === -1) {
52
+ currentSection = header.trim();
53
+ currentSub = null;
54
+ }
55
+ else {
56
+ currentSection = header.slice(0, q).trim();
57
+ const sub = header.slice(q + 1, header.lastIndexOf('"'));
58
+ currentSub = sub;
59
+ }
60
+ continue;
61
+ }
62
+ if (currentSection !== "remote")
63
+ continue;
64
+ const eq = line.indexOf("=");
65
+ if (eq === -1)
66
+ return null;
67
+ const key = line.slice(0, eq).trim();
68
+ const value = line.slice(eq + 1).trim();
69
+ if (key !== "url")
70
+ continue;
71
+ if (currentSub === name)
72
+ return value;
73
+ }
74
+ return null;
75
+ }
76
+ /**
77
+ * Fold the URL shapes git accepts into one canonical string.
78
+ *
79
+ * Steps, in order (K8-005):
80
+ * 1. strip a trailing `.git`;
81
+ * 2. strip a `scheme://` prefix;
82
+ * 3. strip everything up to and including the last `@` in the
83
+ * authority (userinfo and embedded credentials — a token must
84
+ * never reach a hash that lands in a committed file, D8-04);
85
+ * 4. strip a numeric port (`:8443`, `:443`, …) so the same repo
86
+ * served over different transports folds to one id;
87
+ * 5. rewrite the scp-style `host:path` separator to `host/path`;
88
+ * 6. strip a trailing `/`;
89
+ * 7. lowercase the whole result.
90
+ *
91
+ * Returns `null` when the result contains no `/` (e.g. a local
92
+ * path remote) — the caller falls through to the path source.
93
+ */
94
+ export function normalizeRemote(url) {
95
+ if (typeof url !== "string" || url.length === 0)
96
+ return null;
97
+ // 1. Strip a trailing `.git` (case-insensitive for file names
98
+ // like `App.GIT`; hosts are lowercased later anyway).
99
+ let s = url.replace(/\.git$/i, "");
100
+ // 2. Strip a `scheme://` prefix — any scheme, including
101
+ // `ssh://`, `https://`, `git://`, `file://`. A `file://`
102
+ // remote collapses to a local path and will fall through.
103
+ s = s.replace(/^[a-z][a-z0-9+.-]*:\/\//i, "");
104
+ // 3. Strip userinfo: everything up to and including the last
105
+ // `@` in the authority. `https://user:token@host/…` and
106
+ // `ssh://git@host/…` both lose the credential half here,
107
+ // before anything else can retain a copy.
108
+ const at = s.lastIndexOf("@");
109
+ if (at !== -1)
110
+ s = s.slice(at + 1);
111
+ // 4. Strip a numeric port: `https://host:8443/org/repo`, `host:8443/
112
+ // org/repo` and `host/org/repo` are the same repository served
113
+ // over different transports — they must fold to one id or the
114
+ // team silently splits by transport form. The scp-style
115
+ // `host:path` form (path not starting with digits) is rewritten
116
+ // by the step below.
117
+ s = s.replace(/^([^/]+):(\d+)(\/|$)/, "$1$3");
118
+ // 5. scp-style `host:path` → `host/path`. The first `:` that
119
+ // remains is the separator; everything after it is the path.
120
+ // After step 3 there is no userinfo `:` left to confuse it.
121
+ const colon = s.indexOf(":");
122
+ if (colon !== -1) {
123
+ s = `${s.slice(0, colon)}/${s.slice(colon + 1)}`;
124
+ }
125
+ // 6. Strip a trailing `/`.
126
+ s = s.replace(/\/+$/, "");
127
+ // 7. Lowercase.
128
+ s = s.toLowerCase();
129
+ if (s.length === 0)
130
+ return null;
131
+ // Anything without a `/` is a bare host or a bare local name,
132
+ // not a remote repository path — the caller falls through.
133
+ if (!s.includes("/"))
134
+ return null;
135
+ // A leading `/` means the remote is a local filesystem path
136
+ // (e.g. `/srv/git/bare.git` or a `file://` remote) — plan §5.1's
137
+ // fifth fixture — and the caller falls through to source 3.
138
+ if (s.startsWith("/"))
139
+ return null;
140
+ return s;
141
+ }
142
+ /**
143
+ * Derive a repository id from a normalized remote (K8-006).
144
+ *
145
+ * The domain prefix means a repo id can never collide with a memory
146
+ * fingerprint computed over the same string, and it leaves room to
147
+ * version the derivation later.
148
+ */
149
+ export function computeRepoId(normalized) {
150
+ return fnv1a64(`okf:repo:v1\u0000${normalized}`);
151
+ }
152
+ /**
153
+ * Resolve the repository identity for `cwd`, trying the four
154
+ * sources in order (plan §5.2, D9-13):
155
+ *
156
+ * 1. `declared` — `.kevin/project.json` → `id` (validated as
157
+ * exactly 16 lowercase hex characters; anything else is ignored
158
+ * and falls through, because a hand-edited garbage id in a
159
+ * committed file would otherwise scope a whole team's corpus
160
+ * onto a typo);
161
+ * 2. `remote` — `.git/config` → `[remote "origin"] url`,
162
+ * normalized and hashed;
163
+ * 3. `host` — the value the host resolved for this directory,
164
+ * `host.project.worktree` first, `host.project.directory` as
165
+ * fallback; both empty or absent falls through to `path`.
166
+ * This is strictly better than `process.cwd()` — the host's own
167
+ * ToolContext documents "prefer this over `process.cwd()`" —
168
+ * but it sits below the explicit sources, because monorepos and
169
+ * D8-03's confirmed re-keying depend on `.kevin/project.json`
170
+ * winning;
171
+ * 4. `path` — `fingerprint(cwd)`, the v0.7.0 behaviour, preserved
172
+ * exactly when `host` is absent.
173
+ *
174
+ * Never throws: a directory that is not a git repository, an
175
+ * unreadable `.git/config`, a malformed `project.json`, and a host
176
+ * with no usable project fields all fall through to source 4.
177
+ * `projectId` is always returned alongside `repoId`, regardless of
178
+ * which source won.
179
+ */
180
+ export function resolve(cwd, host) {
181
+ const projectId = fingerprint(cwd);
182
+ // 1. Declared.
183
+ try {
184
+ const raw = readFileSync(join(cwd, PROJECT_JSON_PATH), "utf8");
185
+ const parsed = JSON.parse(raw);
186
+ if (typeof parsed.id === "string" && DECLARED_ID_RE.test(parsed.id)) {
187
+ return {
188
+ repoId: parsed.id,
189
+ source: "declared",
190
+ evidence: ".kevin/project.json#id",
191
+ projectId,
192
+ };
193
+ }
194
+ }
195
+ catch {
196
+ // Missing, unreadable, or malformed — fall through.
197
+ }
198
+ // 2. Remote.
199
+ try {
200
+ const config = readFileSync(join(cwd, GIT_CONFIG_PATH), "utf8");
201
+ const url = parseGitConfigRemote(config);
202
+ const normalized = url === null ? null : normalizeRemote(url);
203
+ if (normalized !== null) {
204
+ return {
205
+ repoId: computeRepoId(normalized),
206
+ source: "remote",
207
+ evidence: `remote:${normalized}`,
208
+ projectId,
209
+ };
210
+ }
211
+ }
212
+ catch {
213
+ // Unreadable or missing — fall through.
214
+ }
215
+ // 3. Host — the value the host already resolved for this
216
+ // directory (D9-13), inserted above `path` and below the two
217
+ // explicit sources. `worktree` first, `directory` as fallback;
218
+ // both empty or absent falls through. The chosen value feeds
219
+ // the unchanged `computeRepoId()` — this chain changes which
220
+ // string is hashed, never how.
221
+ const worktree = host?.project?.worktree;
222
+ if (typeof worktree === "string" && worktree.length > 0) {
223
+ return {
224
+ repoId: computeRepoId(worktree),
225
+ source: "host",
226
+ evidence: "host:worktree",
227
+ projectId,
228
+ };
229
+ }
230
+ const directory = host?.project?.directory;
231
+ if (typeof directory === "string" && directory.length > 0) {
232
+ return {
233
+ repoId: computeRepoId(directory),
234
+ source: "host",
235
+ evidence: "host:directory",
236
+ projectId,
237
+ };
238
+ }
239
+ // 4. Path — the v0.7.0 behaviour, preserved exactly.
240
+ return { repoId: projectId, source: "path", evidence: "cwd", projectId };
241
+ }
242
+ /**
243
+ * Write `.kevin/project.json` pinning the repository identity (K8-008
244
+ * / plan §5.8). The id comes from the current `resolve(cwd)` — so `init`
245
+ * in a repository with a remote *pins* the remote-derived id, which is
246
+ * the point: it survives the organisation renaming the repo (a remote
247
+ * URL change would otherwise silently re-scope the corpus).
248
+ *
249
+ * The file is `{"id": "<16 hex>", "created_at": "<ISO-8601 Z>",
250
+ * "generator": "opencode-kevin/0.8.0"}` with sorted keys and a
251
+ * terminating newline (deterministic bytes, the codec discipline of
252
+ * plan §7.3). `init` refuses when the file already exists: overwriting
253
+ * it re-scopes a team's corpus, and that is `rekey`'s job (K8-009),
254
+ * with a confirmation.
255
+ *
256
+ * NOTE (K8-019): the write goes through `ArtifactWriter` in whole-file
257
+ * mode — `.kevin/project.json` is a Kevin-owned file, and D8-08 leaves
258
+ * no scenario in which a second raw write path is acceptable (asserted
259
+ * by tests/unit/single_write_path.test.ts).
260
+ */
261
+ export function initProjectFile(cwd, writer) {
262
+ const path = join(cwd, PROJECT_JSON_PATH);
263
+ try {
264
+ readFileSync(path, "utf8");
265
+ return {
266
+ ok: false,
267
+ path,
268
+ reason: `.kevin/project.json already exists — overwriting it would re-scope the corpus; use "kevin_project rekey" instead`,
269
+ };
270
+ }
271
+ catch {
272
+ // Absent or unreadable — proceed.
273
+ }
274
+ const id = resolve(cwd).repoId;
275
+ const createdAt = new Date().toISOString();
276
+ const payload = `${JSON.stringify({
277
+ created_at: createdAt,
278
+ generator: "opencode-kevin/0.9.0",
279
+ id,
280
+ })}\n`;
281
+ try {
282
+ mkdirSync(join(cwd, ".kevin"), { recursive: true });
283
+ const outcome = writer.write({ path, mode: "whole", content: payload });
284
+ if (outcome !== "written") {
285
+ return {
286
+ ok: false,
287
+ path,
288
+ reason: `could not write .kevin/project.json: ${outcome}`,
289
+ };
290
+ }
291
+ return { ok: true, path, id, createdAt };
292
+ }
293
+ catch (err) {
294
+ return {
295
+ ok: false,
296
+ path,
297
+ reason: `could not write .kevin/project.json: ${err?.message ?? "unknown error"}`,
298
+ };
299
+ }
300
+ }
301
+ //# sourceMappingURL=RepoIdentity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RepoIdentity.js","sourceRoot":"","sources":["../../plugin/RepoIdentity.ts"],"names":[],"mappings":"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"}
@@ -49,6 +49,24 @@ export const METRIC_KEY_LABELS = {
49
49
  conventions_mined: "Convenciones minadas",
50
50
  conflicts_detected: "Conflictos detectados",
51
51
  error_lessons_suppressed: "Lecciones de error suprimidas",
52
+ // v0.8.0 (K8-003 / plan §8.16) — the K8 metric keys need their own
53
+ // Spanish labels; the audit regression forbids raw-key fallback for any
54
+ // key in METRIC_KEYS.
55
+ shared_entries_total: "Entradas compartidas (totales)",
56
+ shared_entries_imported: "Entradas compartidas importadas",
57
+ shared_entries_exported: "Entradas compartidas exportadas",
58
+ okf_merge_folds: "Fusiones OKF (folds)",
59
+ rekey_events: "Re-keys de repositorio",
60
+ injections_from_shared: "Inyecciones desde la capa compartida",
61
+ // v0.9.0 (K9-003 / plan §8.16) — the K9 metric keys need their own
62
+ // Spanish labels; the audit regression forbids raw-key fallback for any
63
+ // key in METRIC_KEYS.
64
+ hook_fires_total: "Disparos de hooks (totales)",
65
+ hook_errors_total: "Errores de hooks",
66
+ hooks_dead_total: "Hooks muertos",
67
+ injections_suppressed_dead_hook: "Inyecciones suprimidas (hook muerto)",
68
+ native_registrations_total: "Registros nativos (totales)",
69
+ native_registration_failures: "Fallos de registro nativo",
52
70
  };
53
71
  function originLabel(origin) {
54
72
  if (origin === "reflector")
@@ -1 +1 @@
1
- {"version":3,"file":"Retrospective.js","sourceRoot":"","sources":["../../plugin/Retrospective.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Retrospective.js","sourceRoot":"","sources":["../../plugin/Retrospective.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,159 @@
1
+ import type { ArtifactWriter, WriteOutcome, WritePlan, WriteRequest } from "./ArtifactWriter.js";
2
+ import { type ParseResult } from "./okf.js";
3
+ export interface ImportReport {
4
+ path: string;
5
+ /** null when the file does not exist. */
6
+ fileHash: string | null;
7
+ parsed: number;
8
+ folded: number;
9
+ rejected: number;
10
+ /** rows inserted or updated in shared_entries. */
11
+ imported: number;
12
+ /** shared memories retired by an incoming tombstone. */
13
+ tombstoned: number;
14
+ /** true when fileHash matches the last okf_imports row. */
15
+ skipped: boolean;
16
+ }
17
+ /**
18
+ * A planned (or applied) export (K8-020 / plan §5.5). The refusal is
19
+ * carried by the write plan itself — `outcome: "refused"` with both
20
+ * hashes audited — so a refused plan is indistinguishable from a
21
+ * written one until `outcome` is read.
22
+ */
23
+ export interface ExportPlan {
24
+ path: string;
25
+ /** The whole-mode write request; applying re-plans through the single write funnel. */
26
+ request: WriteRequest;
27
+ /** The pure preview from planning time — diff and outcome, nothing written. */
28
+ write: WritePlan;
29
+ /** Entry ids in the merged corpus absent from the current file. */
30
+ entriesAdded: number;
31
+ /** Set by applyExport: the outcome of the actual write. */
32
+ applied?: WriteOutcome;
33
+ }
34
+ export declare class SharedLayer {
35
+ private readonly store;
36
+ private readonly repoId;
37
+ private readonly projectId;
38
+ private readonly version;
39
+ private readonly writer;
40
+ constructor(deps: {
41
+ store: StoreLike;
42
+ repoId: string;
43
+ projectId: string;
44
+ version: string;
45
+ writer: ArtifactWriter;
46
+ });
47
+ /**
48
+ * The single whole-file (mode `whole`) construction site in
49
+ * SharedLayer (K8-019 / K8-020, D8-08, asserted by
50
+ * tests/unit/single_write_path.test.ts): the OKF file is written
51
+ * through the ArtifactWriter's write funnel like every other file
52
+ * Kevin owns — there is no second write path.
53
+ */
54
+ private wholeRequest;
55
+ /**
56
+ * Pure export planner (K8-020 / plan §5.5): reads the current file
57
+ * and merges the given local memories' projections into the corpus,
58
+ * producing a {@link WritePlan} — but writes nothing. Refusals are
59
+ * audited like any other write: `after === before`, both hashes
60
+ * recorded (D6-04). The refusal ladder, in the order the code
61
+ * evaluates it — file-side refusals first (not_okf, version_ahead,
62
+ * repo_mismatch), then candidate-side refusals in the loop order
63
+ * (line_too_long, below_floor, not_curated, unknown_entry), then
64
+ * too_many_entries and finally parse_damaged.
65
+ */
66
+ planExport(memoryIds: string[], path: string): ExportPlan;
67
+ /**
68
+ * Tombstone-append planner (K8-020 / D8-09): emits one `tombstone`
69
+ * line per entry id, never deletes a line. The identifying triple is
70
+ * reconstructed from the local projection (a memory with
71
+ * `shared_entry_id`) so the line still passes parse's
72
+ * tamper-evident entry_id check; an id with no local projection is
73
+ * refused rather than emitting an invalid line.
74
+ */
75
+ planTombstone(entryIds: string[], path: string): ExportPlan;
76
+ /**
77
+ * v0.8.0 (BUG-003) — heal a stale `#repo` header after a rekey.
78
+ * Rekey changes the scope the file is written under; a stale first
79
+ * line would make every later planExport/planTombstone refuse with
80
+ * repo_mismatch forever. Only the header line is replaced; the entry
81
+ * bytes, line endings and trailing newline are preserved. The write
82
+ * goes through the single funnel (D8-08). Returns true when the
83
+ * header was rewritten. Never throws: a missing or unreadable file
84
+ * is nothing to heal.
85
+ */
86
+ healHeader(path: string, newRepoId: string): boolean;
87
+ /**
88
+ * Apply a previously planned export: the write goes through the
89
+ * single write funnel (re-planning against the file's current state),
90
+ * and the outcome is recorded on the returned plan (K8-020).
91
+ */
92
+ applyExport(plan: ExportPlan): ExportPlan;
93
+ /** Refusal plans are audited with both hashes (after === before). */
94
+ private refused;
95
+ /**
96
+ * Convert the requested local memories into OKF candidates and run
97
+ * the candidate-side refusals — line_too_long, below_floor,
98
+ * not_curated — in plan §5.5 order.
99
+ */
100
+ private candidateEntries;
101
+ private setting;
102
+ private readWithFlag;
103
+ /**
104
+ * Read and parse the shared file. Total: a missing or unreadable
105
+ * file yields an empty ParseResult, never a throw (D8-14).
106
+ */
107
+ read(path: string): ParseResult;
108
+ /**
109
+ * Idempotent and cheap to call (K8-016 / plan §5.5): hash the file
110
+ * first and return `{ skipped: true }` when the hash matches the
111
+ * most recent `okf_imports` row for this repo_id — the session.idle
112
+ * path costs one readFileSync plus one hash on an unchanged
113
+ * repository. A missing file is not an error: it returns
114
+ * `fileHash: null`, `parsed: 0`, and still writes an audit row.
115
+ */
116
+ import(path: string): ImportReport;
117
+ private writeImportRow;
118
+ /**
119
+ * Project every imported entry into memories (K8-017 / plan §5.5,
120
+ * D8-10): a shared memory IS a memory, so getRelevant(), rankScore(),
121
+ * the five gates, truth_penalty, ConflictDetector and every audit
122
+ * rollup keep working unchanged.
123
+ *
124
+ * - assert entries: inserted once, never updated — re-importing an
125
+ * unchanged file must not create duplicates, bump evidence_count or
126
+ * move updated_at. `fingerprint` is deliberately left NULL: it is a
127
+ * different identity dimension (plan §3.3) and conflating it with
128
+ * `shared_entry_id` would make the v0.4.0 supersede path fire on
129
+ * unrelated entries (K8-017 acceptance).
130
+ * - tombstone entries: the ONE place in this codebase where the shared
131
+ * layer may write memories.status. This is NOT a v0.7.0 Principle 24
132
+ * violation: that principle forbids *contradiction* — a fuzzy
133
+ * inference — from writing status, and a tombstone is the opposite:
134
+ * an explicit, committed, human-reviewed decision that arrived
135
+ * through a pull request (D8-09, plan §5.5).
136
+ *
137
+ * Returns the number of memories archived by tombstones.
138
+ */
139
+ private projectEntries;
140
+ /**
141
+ * Upsert every entry into shared_entries keyed on (repo_id,
142
+ * entry_id) — the UNIQUE index from migration 009 makes this an
143
+ * upsert rather than an append. `confidence` is the DERIVED value
144
+ * (deriveConfidence), never a transported float (plan §5.3).
145
+ * Returns the number of rows inserted or updated.
146
+ */
147
+ private upsertEntries;
148
+ }
149
+ /**
150
+ * The Store surface SharedLayer needs. Kept structural so tests can
151
+ * use the real Store without importing plugin internals.
152
+ */
153
+ export interface StoreLike {
154
+ prepare(sql: string): {
155
+ get(...params: unknown[]): unknown;
156
+ all(...params: unknown[]): unknown[];
157
+ run(...params: unknown[]): void;
158
+ };
159
+ }