@askdkc/kiokuko 0.1.24 → 0.1.25

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 (40) hide show
  1. package/dist/agent-file/render.d.ts +1 -1
  2. package/dist/agent-file/render.d.ts.map +1 -1
  3. package/dist/agent-file/render.js +4 -3
  4. package/dist/agent-file/render.js.map +1 -1
  5. package/dist/akinator/agent-task.d.ts +7 -0
  6. package/dist/akinator/agent-task.d.ts.map +1 -1
  7. package/dist/akinator/agent-task.js +25 -11
  8. package/dist/akinator/agent-task.js.map +1 -1
  9. package/dist/commands/use.d.ts +2 -1
  10. package/dist/commands/use.d.ts.map +1 -1
  11. package/dist/commands/use.js +20 -5
  12. package/dist/commands/use.js.map +1 -1
  13. package/dist/context/feedback.d.ts +2 -3
  14. package/dist/context/feedback.d.ts.map +1 -1
  15. package/dist/context/feedback.js +2 -3
  16. package/dist/context/feedback.js.map +1 -1
  17. package/dist/ledger/checkpoint-contract.d.ts +139 -2
  18. package/dist/ledger/checkpoint-contract.d.ts.map +1 -1
  19. package/dist/ledger/checkpoint-contract.js +85 -1
  20. package/dist/ledger/checkpoint-contract.js.map +1 -1
  21. package/dist/mcp/server.d.ts.map +1 -1
  22. package/dist/mcp/server.js +10 -49
  23. package/dist/mcp/server.js.map +1 -1
  24. package/dist/memory/checkpoint-contract.d.ts +490 -0
  25. package/dist/memory/checkpoint-contract.d.ts.map +1 -0
  26. package/dist/memory/checkpoint-contract.js +105 -0
  27. package/dist/memory/checkpoint-contract.js.map +1 -0
  28. package/dist/memory/scoped-memory.d.ts +9 -3
  29. package/dist/memory/scoped-memory.d.ts.map +1 -1
  30. package/dist/memory/scoped-memory.js +198 -109
  31. package/dist/memory/scoped-memory.js.map +1 -1
  32. package/dist/repository/detect-root.d.ts +1 -0
  33. package/dist/repository/detect-root.d.ts.map +1 -1
  34. package/dist/repository/detect-root.js +1 -1
  35. package/dist/repository/detect-root.js.map +1 -1
  36. package/dist/setup/render.d.ts.map +1 -1
  37. package/dist/setup/render.js +10 -9
  38. package/dist/setup/render.js.map +1 -1
  39. package/package.json +1 -1
  40. package/templates/AGENTS.md +4 -3
@@ -0,0 +1,105 @@
1
+ import * as z from 'zod/v4';
2
+ import { ENTRY_KINDS } from '../serialization/validate.js';
3
+ import { CHECKPOINT_OUTCOMES, CHECKPOINT_RUN_ID_DESCRIPTION, MAX_CHECKPOINT_FEEDBACK_ITEMS, MAX_CHECKPOINT_MEMORY_ITEMS, checkpointEvidenceSchema, checkpointFeedbackSchema, hasCheckpointEvidenceContent, } from '../ledger/checkpoint-contract.js';
4
+ const memoryKind = z.enum(ENTRY_KINDS);
5
+ const memoryClass = z.enum([
6
+ 'implementation-pattern', 'troubleshooting', 'tool-usage', 'extension-usage',
7
+ 'configuration', 'workflow', 'gotcha', 'reference', 'preference',
8
+ ]);
9
+ const applicability = z.object({
10
+ languages: z.array(z.string().trim().min(1).max(500)).max(100).optional(),
11
+ frameworks: z.array(z.object({
12
+ name: z.string().trim().min(1).max(500),
13
+ version: z.string().trim().min(1).max(100).optional(),
14
+ }).strict()).max(50).optional(),
15
+ databases: z.array(z.string().trim().min(1).max(500)).max(100).optional(),
16
+ runtimes: z.array(z.string().trim().min(1).max(500)).max(100).optional(),
17
+ tools: z.array(z.string().trim().min(1).max(500)).max(100).optional(),
18
+ platforms: z.array(z.string().trim().min(1).max(500)).max(100).optional(),
19
+ }).strict();
20
+ const signals = z.object({
21
+ symbols: z.array(z.string().trim().min(1).max(500)).max(100).optional(),
22
+ paths: z.array(z.string().trim().min(1).max(500)).max(100).optional(),
23
+ errors: z.array(z.string().trim().min(1).max(500)).max(100).optional(),
24
+ packages: z.array(z.string().trim().min(1).max(500)).max(100).optional(),
25
+ commands: z.array(z.string().trim().min(1).max(500)).max(100).optional(),
26
+ }).strict();
27
+ export const checkpointMemorySchema = z.object({
28
+ kind: memoryKind,
29
+ title: z.string().trim().min(1).max(300),
30
+ body: z.string().max(20_000),
31
+ summary: z.string().max(2000).optional(),
32
+ scope: z.enum(['project', 'global']).default('project'),
33
+ retrievalScope: z.enum(['project-only', 'ecosystem', 'global']).optional(),
34
+ tags: z.array(z.string().trim().min(1).max(200)).max(20).optional(),
35
+ confidence: z.number().min(0).max(1).default(0.7),
36
+ memoryClass: memoryClass.optional(),
37
+ applicability: applicability.optional(),
38
+ signals: signals.optional(),
39
+ portableReason: z.string().trim().min(1).max(2000).optional(),
40
+ }).strict();
41
+ const checkpointRunId = z.string().min(1).max(256).refine((value) => value.trim() === value && !/\p{Cc}/u.test(value), { message: 'runId must be a canonical bounded identity' }).describe(CHECKPOINT_RUN_ID_DESCRIPTION);
42
+ const checkpointDeliveryId = z.string().min(1).max(256).refine((value) => value.trim() === value && !/\p{Cc}/u.test(value), { message: 'deliveryId must be a canonical bounded identity' });
43
+ function hasCheckpointContent(value) {
44
+ return (value.memories?.length ?? 0) > 0
45
+ || (value.feedback?.length ?? 0) > 0
46
+ || hasCheckpointEvidenceContent(value.evidence);
47
+ }
48
+ function addIssue(context, path, message) {
49
+ context.addIssue({ code: 'custom', path, message });
50
+ }
51
+ function refineRunBoundCheckpoint(value, context) {
52
+ if (value.outcome === undefined)
53
+ addIssue(context, ['outcome'], 'outcome is required when runId is supplied');
54
+ if (!hasCheckpointContent(value))
55
+ addIssue(context, [], 'A run-bound checkpoint requires memory, feedback, or non-empty evidence');
56
+ if ((value.feedback?.length ?? 0) > 0 && value.deliveryId === undefined) {
57
+ addIssue(context, ['deliveryId'], 'deliveryId is required when feedback is supplied');
58
+ }
59
+ }
60
+ export const runBoundCheckpointSchema = z.object({
61
+ cwd: z.string().min(1).optional(),
62
+ runId: checkpointRunId,
63
+ deliveryId: checkpointDeliveryId.optional(),
64
+ outcome: z.enum(CHECKPOINT_OUTCOMES),
65
+ memories: z.array(checkpointMemorySchema).max(MAX_CHECKPOINT_MEMORY_ITEMS).optional(),
66
+ feedback: z.array(checkpointFeedbackSchema).max(MAX_CHECKPOINT_FEEDBACK_ITEMS).optional(),
67
+ evidence: checkpointEvidenceSchema.optional(),
68
+ }).strict().superRefine((value, context) => refineRunBoundCheckpoint(value, context));
69
+ export const standaloneMemoryCheckpointSchema = z.object({
70
+ cwd: z.string().min(1).optional(),
71
+ memories: z.array(checkpointMemorySchema).min(1).max(MAX_CHECKPOINT_MEMORY_ITEMS),
72
+ }).strict();
73
+ export const memoryCheckpointVariantsSchema = z.union([
74
+ runBoundCheckpointSchema,
75
+ standaloneMemoryCheckpointSchema,
76
+ ]);
77
+ function refineCheckpointInput(value, context) {
78
+ if (value.runId !== undefined) {
79
+ refineRunBoundCheckpoint(value, context);
80
+ return;
81
+ }
82
+ if ((value.memories?.length ?? 0) === 0)
83
+ addIssue(context, ['memories'], 'Without runId, at least one memory is required');
84
+ if (value.outcome !== undefined)
85
+ addIssue(context, ['outcome'], 'outcome is only valid for a run-bound checkpoint');
86
+ if (value.deliveryId !== undefined)
87
+ addIssue(context, ['deliveryId'], 'deliveryId requires runId');
88
+ if (value.feedback !== undefined)
89
+ addIssue(context, ['feedback'], 'feedback requires runId');
90
+ if (value.evidence !== undefined)
91
+ addIssue(context, ['evidence'], 'evidence requires runId');
92
+ }
93
+ // The MCP SDK only serializes object schemas in tools/list; a union would be
94
+ // advertised as an empty schema. This closed object retains the same runtime
95
+ // cross-field contract while keeping the public property schema visible.
96
+ export const memoryCheckpointInputSchema = z.object({
97
+ cwd: z.string().min(1).optional(),
98
+ memories: z.array(checkpointMemorySchema).max(MAX_CHECKPOINT_MEMORY_ITEMS).optional(),
99
+ runId: checkpointRunId.optional(),
100
+ deliveryId: checkpointDeliveryId.optional(),
101
+ outcome: z.enum(CHECKPOINT_OUTCOMES).optional(),
102
+ feedback: z.array(checkpointFeedbackSchema).max(MAX_CHECKPOINT_FEEDBACK_ITEMS).optional(),
103
+ evidence: checkpointEvidenceSchema.optional(),
104
+ }).strict().superRefine((value, context) => refineCheckpointInput(value, context));
105
+ //# sourceMappingURL=checkpoint-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint-contract.js","sourceRoot":"","sources":["../../src/memory/checkpoint-contract.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ import { type EntryKind } from '../serialization/validate.js';
5
5
  import { type Applicability, type MemoryClass, type MemorySignals, type RetrievalScope } from './structured-memory.js';
6
6
  import { type FederatedScope, type FederatedRecallResult } from './federated-retrieval.js';
7
7
  import type { ProjectFingerprint } from '../repository/project-fingerprint.js';
8
+ import { type CheckpointOutcome } from '../ledger/checkpoint-contract.js';
8
9
  interface GitProvenanceExecOptions {
9
10
  cwd: string;
10
11
  encoding: 'utf8';
@@ -42,15 +43,20 @@ export interface CheckpointMemory {
42
43
  signals?: MemorySignals;
43
44
  portableReason?: string;
44
45
  }
45
- export interface ScopedCheckpointInput {
46
+ export interface ScopedCheckpointStandaloneInput {
46
47
  cwd?: string;
47
48
  memories: CheckpointMemory[];
48
- runId?: string;
49
+ }
50
+ export interface ScopedCheckpointRunInput {
51
+ cwd?: string;
52
+ memories: CheckpointMemory[];
53
+ runId: string;
49
54
  deliveryId?: string;
50
- outcome?: 'completed' | 'failed' | 'cancelled' | 'interrupted';
55
+ outcome: CheckpointOutcome;
51
56
  feedback?: unknown[];
52
57
  evidence?: unknown;
53
58
  }
59
+ export type ScopedCheckpointInput = ScopedCheckpointStandaloneInput | ScopedCheckpointRunInput;
54
60
  export interface ScopedCheckpointResult {
55
61
  project: ResolvedProjectWorkspace | null;
56
62
  entries: Array<Pick<EntryRecord, 'id' | 'workspace' | 'kind' | 'status' | 'title' | 'revision'>>;
@@ -1 +1 @@
1
- {"version":3,"file":"scoped-memory.d.ts","sourceRoot":"","sources":["../../src/memory/scoped-memory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scoped-memory.d.ts","sourceRoot":"","sources":["../../src/memory/scoped-memory.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,7 @@ import { findSecret } from './secrets.js';
15
15
  import { assertContextFeedbackRecordable, recordContextFeedbackInTransaction } from '../context/feedback.js';
16
16
  import { readContextDelivery } from '../context/delivery.js';
17
17
  import { recordKnowledgePathsInTransaction } from '../akinator/knowledge-path.js';
18
+ import { CHECKPOINT_COMMAND_FIELD_NAMES, CHECKPOINT_EVIDENCE_FIELD_NAMES, CHECKPOINT_FEEDBACK_FIELD_NAMES, CHECKPOINT_OUTCOMES, CHECKPOINT_RESULT_OUTCOMES, CHECKPOINT_TEST_FIELD_NAMES, CHECKPOINT_VERIFICATION_FIELD_NAMES, MAX_CHECKPOINT_EVIDENCE_ITEMS, MAX_CHECKPOINT_EXECUTABLE_CHARS, MAX_CHECKPOINT_PATHS, MAX_CHECKPOINT_SHORT_TEXT_CHARS, MAX_CHECKPOINT_SIGNALS, } from '../ledger/checkpoint-contract.js';
18
19
  const GIT_PROVENANCE_TIMEOUT_MS = 5_000;
19
20
  const GIT_PROVENANCE_MAX_BUFFER = 64 * 1024;
20
21
  const executeGitProvenance = (executable, args, options) => execFileSync(executable, args, options);
@@ -67,8 +68,8 @@ const CHECKPOINT_MEMORY_FIELDS = new Set([
67
68
  'kind', 'title', 'body', 'summary', 'scope', 'retrievalScope', 'tags', 'confidence',
68
69
  'memoryClass', 'applicability', 'signals', 'portableReason',
69
70
  ]);
70
- const CHECKPOINT_FEEDBACK_FIELDS = new Set(['entryId', 'entryRevision', 'verdict', 'comment']);
71
- const CHECKPOINT_OUTCOMES = new Set(['completed', 'failed', 'cancelled', 'interrupted']);
71
+ const CHECKPOINT_INPUT_FIELDS = new Set(['cwd', 'memories', 'runId', 'deliveryId', 'outcome', 'feedback', 'evidence']);
72
+ const CHECKPOINT_FEEDBACK_FIELDS = new Set(CHECKPOINT_FEEDBACK_FIELD_NAMES);
72
73
  function assertCheckpointEligible(status) {
73
74
  const eligibility = checkpointEligibility(status);
74
75
  if (eligibility.allowed)
@@ -86,9 +87,12 @@ function checkpointObject(value, allowed, message) {
86
87
  if (prototype !== Object.prototype && prototype !== null) {
87
88
  throw new KiokukoError('VALIDATION_ERROR', message);
88
89
  }
90
+ const keys = Reflect.ownKeys(value);
91
+ if (keys.length > allowed.size)
92
+ throw new KiokukoError('VALIDATION_ERROR', message);
89
93
  const result = Object.create(null);
90
94
  const descriptors = Object.getOwnPropertyDescriptors(value);
91
- for (const key of Reflect.ownKeys(value)) {
95
+ for (const key of keys) {
92
96
  if (typeof key !== 'string' || !allowed.has(key)) {
93
97
  throw new KiokukoError('VALIDATION_ERROR', message);
94
98
  }
@@ -107,87 +111,192 @@ function sameProject(left, right) {
107
111
  && left.repositoryId === right.repositoryId
108
112
  && left.workspace === right.workspace;
109
113
  }
110
- function boundedEvidence(raw) {
111
- if (raw === undefined)
112
- return { changedPaths: [], errorSignatures: [], commands: [], tests: [] };
113
- if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
114
- throw new KiokukoError('VALIDATION_ERROR', 'Evidence is invalid');
115
- let canonicalEvidence;
116
- try {
117
- canonicalEvidence = canonicalJson(raw);
114
+ function checkpointArray(value, maximum, message) {
115
+ if (!Array.isArray(value) || isProxy(value) || value.length > maximum) {
116
+ throw new KiokukoError('VALIDATION_ERROR', message);
118
117
  }
119
- catch (error) {
120
- if (error instanceof RangeError || (error instanceof KiokukoError && error.code === 'VALIDATION_ERROR')) {
121
- throw new KiokukoError('VALIDATION_ERROR', 'Evidence is invalid');
118
+ const keys = Reflect.ownKeys(value);
119
+ if (keys.length !== value.length + 1 || !keys.includes('length') || keys.some((key) => typeof key !== 'string')) {
120
+ throw new KiokukoError('VALIDATION_ERROR', message);
121
+ }
122
+ const descriptors = Object.getOwnPropertyDescriptors(value);
123
+ const result = [];
124
+ for (let index = 0; index < value.length; index += 1) {
125
+ const descriptor = descriptors[String(index)];
126
+ if (descriptor === undefined || !('value' in descriptor) || descriptor.enumerable !== true) {
127
+ throw new KiokukoError('VALIDATION_ERROR', message);
122
128
  }
123
- throw error;
129
+ result.push(descriptor.value);
124
130
  }
125
- if (findSecret(canonicalEvidence))
126
- throw new KiokukoError('SECURITY_REJECTION', 'Evidence resembles a secret and was not stored');
127
- const value = raw;
128
- if (Object.keys(value).some((field) => !['changedPaths', 'errorSignatures', 'commands', 'tests', 'verification'].includes(field)))
129
- throw new KiokukoError('VALIDATION_ERROR', 'Evidence is invalid');
130
- const strings = (value, max) => {
131
- if (value === undefined)
131
+ return result;
132
+ }
133
+ function boundedEvidence(raw) {
134
+ if (raw === undefined)
135
+ return { changedPaths: [], errorSignatures: [], commands: [], tests: [] };
136
+ const value = checkpointObject(raw, new Set(CHECKPOINT_EVIDENCE_FIELD_NAMES), 'Evidence is invalid');
137
+ const evidenceError = () => new KiokukoError('VALIDATION_ERROR', 'Evidence is invalid');
138
+ const pathError = () => new KiokukoError('VALIDATION_ERROR', 'Evidence path is invalid');
139
+ const strings = (candidate, maximum) => {
140
+ if (candidate === undefined)
132
141
  return [];
133
- if (!Array.isArray(value) || value.length > max || value.some((item) => typeof item !== 'string' || item.length === 0 || item.length > 500 || /[\u0000-\u001f\u007f]/u.test(item)))
134
- throw new KiokukoError('VALIDATION_ERROR', 'Evidence is invalid');
135
- return [...new Set(value)];
142
+ const values = checkpointArray(candidate, maximum, 'Evidence is invalid');
143
+ return [...new Set(values.map((item) => {
144
+ if (typeof item !== 'string' || item.length === 0 || item.length > MAX_CHECKPOINT_SHORT_TEXT_CHARS || /[\u0000-\u001f\u007f]/u.test(item)) {
145
+ throw evidenceError();
146
+ }
147
+ return item;
148
+ }))];
136
149
  };
137
- const changedPaths = strings(value.changedPaths, 200).map((item) => {
138
- if (item.startsWith('/') || /^[A-Za-z]:[\\/]/u.test(item) || item.split(/[\\/]/u).includes('..'))
139
- throw new KiokukoError('VALIDATION_ERROR', 'Evidence path is invalid');
150
+ const changedPaths = strings(value.changedPaths, MAX_CHECKPOINT_PATHS).map((item) => {
151
+ if (item.startsWith('/') || item.startsWith('\\') || /^[A-Za-z]:/u.test(item) || item.split(/[\\/]/u).includes('..'))
152
+ throw pathError();
140
153
  return item.replaceAll('\\', '/');
141
154
  });
142
- const errorSignatures = strings(value.errorSignatures, 200);
155
+ const errorSignatures = strings(value.errorSignatures, MAX_CHECKPOINT_SIGNALS);
143
156
  const normalizeItems = (items, kind) => {
144
157
  if (items === undefined)
145
158
  return [];
146
- if (!Array.isArray(items) || items.length > 100)
147
- throw new KiokukoError('VALIDATION_ERROR', 'Evidence is invalid');
148
- return items.map((item) => {
149
- if (typeof item !== 'object' || item === null || Array.isArray(item))
150
- throw new KiokukoError('VALIDATION_ERROR', 'Evidence is invalid');
151
- const record = item;
152
- const allowedFields = kind === 'command' ? ['executable', 'classification', 'exitCode', 'outcome', 'digest'] : ['runner', 'target', 'outcome', 'digest'];
153
- if (Object.keys(record).some((field) => !allowedFields.includes(field)))
154
- throw new KiokukoError('VALIDATION_ERROR', 'Evidence is invalid');
155
- const required = kind === 'command' ? 'executable' : 'runner';
156
- if (typeof record[required] !== 'string' || record[required].length === 0 || record[required].length > 200)
157
- throw new KiokukoError('VALIDATION_ERROR', 'Evidence is invalid');
158
- if (typeof record.outcome !== 'string' || !['passed', 'failed', 'unknown'].includes(record.outcome))
159
- throw new KiokukoError('VALIDATION_ERROR', 'Evidence is invalid');
160
- const result = { [required]: record[required], outcome: record.outcome };
161
- for (const field of kind === 'command' ? ['classification', 'digest'] : ['target', 'digest']) {
162
- if (record[field] !== undefined) {
163
- if (typeof record[field] !== 'string' || record[field].length === 0 || record[field].length > 500)
164
- throw new KiokukoError('VALIDATION_ERROR', 'Evidence is invalid');
165
- result[field] = record[field];
166
- }
159
+ const values = checkpointArray(items, MAX_CHECKPOINT_EVIDENCE_ITEMS, 'Evidence is invalid');
160
+ const allowedFields = new Set(kind === 'command' ? CHECKPOINT_COMMAND_FIELD_NAMES : CHECKPOINT_TEST_FIELD_NAMES);
161
+ const optionalFields = kind === 'command' ? ['classification', 'digest'] : ['target', 'digest'];
162
+ const required = kind === 'command' ? 'executable' : 'runner';
163
+ return values.map((item) => {
164
+ const record = checkpointObject(item, allowedFields, 'Evidence is invalid');
165
+ const requiredValue = record[required];
166
+ if (typeof requiredValue !== 'string' || requiredValue.length === 0
167
+ || requiredValue.length > MAX_CHECKPOINT_EXECUTABLE_CHARS
168
+ || /[\u0000-\u001f\u007f]/u.test(requiredValue))
169
+ throw evidenceError();
170
+ const rawOutcome = record.outcome;
171
+ if (typeof rawOutcome !== 'string' || !CHECKPOINT_RESULT_OUTCOMES.includes(rawOutcome))
172
+ throw evidenceError();
173
+ const outcome = rawOutcome;
174
+ const optional = {};
175
+ for (const field of optionalFields) {
176
+ const optionalValue = record[field];
177
+ if (optionalValue === undefined)
178
+ continue;
179
+ if (typeof optionalValue !== 'string' || optionalValue.length === 0
180
+ || optionalValue.length > MAX_CHECKPOINT_SHORT_TEXT_CHARS
181
+ || /[\u0000-\u001f\u007f]/u.test(optionalValue))
182
+ throw evidenceError();
183
+ if (field === 'classification' || field === 'target' || field === 'digest')
184
+ optional[field] = optionalValue;
167
185
  }
168
- if (kind === 'command' && record.exitCode !== undefined) {
186
+ if (kind === 'command') {
169
187
  const exitCode = record.exitCode;
170
- if (typeof exitCode !== 'number' || !Number.isSafeInteger(exitCode) || exitCode < 0)
171
- throw new KiokukoError('VALIDATION_ERROR', 'Evidence is invalid');
172
- result.exitCode = exitCode;
188
+ if (exitCode !== undefined && (typeof exitCode !== 'number' || !Number.isSafeInteger(exitCode) || exitCode < 0))
189
+ throw evidenceError();
190
+ return {
191
+ executable: requiredValue,
192
+ outcome,
193
+ ...(optional.classification === undefined ? {} : { classification: optional.classification }),
194
+ ...(exitCode === undefined ? {} : { exitCode }),
195
+ ...(optional.digest === undefined ? {} : { digest: optional.digest }),
196
+ };
173
197
  }
174
- return result;
198
+ return {
199
+ runner: requiredValue,
200
+ outcome,
201
+ ...(optional.target === undefined ? {} : { target: optional.target }),
202
+ ...(optional.digest === undefined ? {} : { digest: optional.digest }),
203
+ };
175
204
  });
176
205
  };
177
- const verification = value.verification === undefined ? undefined : (() => {
178
- if (typeof value.verification !== 'object' || value.verification === null || Array.isArray(value.verification))
179
- throw new KiokukoError('VALIDATION_ERROR', 'Evidence is invalid');
180
- const verificationValue = value.verification;
181
- if (Object.keys(verificationValue).some((field) => field !== 'outcome'))
182
- throw new KiokukoError('VALIDATION_ERROR', 'Evidence is invalid');
183
- const outcome = verificationValue.outcome;
184
- if (typeof outcome !== 'string' || !['fresh', 'stale', 'failed', 'unknown'].includes(outcome))
185
- throw new KiokukoError('VALIDATION_ERROR', 'Evidence is invalid');
186
- return { outcome };
187
- })();
188
206
  const commands = normalizeItems(value.commands, 'command');
189
207
  const tests = normalizeItems(value.tests, 'test');
190
- return { changedPaths, errorSignatures, commands, tests, ...(verification === undefined ? {} : { verification }) };
208
+ const verification = value.verification === undefined ? undefined : (() => {
209
+ const verificationValue = checkpointObject(value.verification, new Set(CHECKPOINT_VERIFICATION_FIELD_NAMES), 'Evidence is invalid');
210
+ const rawOutcome = verificationValue.outcome;
211
+ if (typeof rawOutcome !== 'string' || !['fresh', 'stale', 'failed', 'unknown'].includes(rawOutcome))
212
+ throw evidenceError();
213
+ return { outcome: rawOutcome };
214
+ })();
215
+ const normalized = {
216
+ changedPaths,
217
+ errorSignatures,
218
+ commands,
219
+ tests,
220
+ ...(verification === undefined ? {} : { verification }),
221
+ };
222
+ let canonicalEvidence;
223
+ try {
224
+ canonicalEvidence = canonicalJson(normalized);
225
+ }
226
+ catch (error) {
227
+ if (error instanceof RangeError || (error instanceof KiokukoError && error.code === 'VALIDATION_ERROR')) {
228
+ throw new KiokukoError('VALIDATION_ERROR', 'Evidence is invalid');
229
+ }
230
+ throw error;
231
+ }
232
+ if (findSecret(canonicalEvidence))
233
+ throw new KiokukoError('SECURITY_REJECTION', 'Evidence resembles a secret and was not stored');
234
+ return normalized;
235
+ }
236
+ function checkpointIdentifier(value, label) {
237
+ if (value === undefined)
238
+ return undefined;
239
+ if (typeof value !== 'string' || value.length === 0 || value.length > 256 || value.trim() !== value || /\p{Cc}/u.test(value)) {
240
+ throw new KiokukoError('VALIDATION_ERROR', `${label} is invalid`);
241
+ }
242
+ return value;
243
+ }
244
+ function normalizeCheckpointInput(input) {
245
+ const value = checkpointObject(input, CHECKPOINT_INPUT_FIELDS, 'Checkpoint input is invalid');
246
+ const cwd = value.cwd === undefined
247
+ ? undefined
248
+ : typeof value.cwd === 'string' && value.cwd.length > 0 && !/\p{Cc}/u.test(value.cwd)
249
+ ? value.cwd
250
+ : (() => { throw new KiokukoError('VALIDATION_ERROR', 'Checkpoint cwd is invalid'); })();
251
+ const memoryValues = value.memories === undefined
252
+ ? []
253
+ : checkpointArray(value.memories, 20, 'Checkpoint memories must be an array');
254
+ const memories = memoryValues.map((memory) => checkpointObject(memory, CHECKPOINT_MEMORY_FIELDS, 'Checkpoint memory is invalid'));
255
+ const feedbackValues = value.feedback === undefined
256
+ ? []
257
+ : checkpointArray(value.feedback, 100, 'Checkpoint feedback is invalid');
258
+ const feedback = feedbackValues.map((item) => checkpointObject(item, CHECKPOINT_FEEDBACK_FIELDS, 'Checkpoint feedback is invalid'));
259
+ const evidence = boundedEvidence(value.evidence);
260
+ const runId = checkpointIdentifier(value.runId, 'Checkpoint runId');
261
+ const deliveryId = checkpointIdentifier(value.deliveryId, 'Checkpoint deliveryId');
262
+ const rawOutcome = value.outcome;
263
+ if (runId === undefined) {
264
+ if (memories.length === 0)
265
+ throw new KiokukoError('VALIDATION_ERROR', 'Without runId, at least one memory is required');
266
+ if (rawOutcome !== undefined)
267
+ throw new KiokukoError('VALIDATION_ERROR', 'Checkpoint outcome requires runId');
268
+ if (deliveryId !== undefined)
269
+ throw new KiokukoError('VALIDATION_ERROR', 'Checkpoint deliveryId requires runId');
270
+ if (value.feedback !== undefined)
271
+ throw new KiokukoError('VALIDATION_ERROR', 'Checkpoint feedback requires runId');
272
+ if (value.evidence !== undefined)
273
+ throw new KiokukoError('VALIDATION_ERROR', 'Checkpoint evidence requires runId');
274
+ return { ...(cwd === undefined ? {} : { cwd }), memories };
275
+ }
276
+ if (typeof rawOutcome !== 'string' || !CHECKPOINT_OUTCOMES.includes(rawOutcome)) {
277
+ throw new KiokukoError('VALIDATION_ERROR', 'Checkpoint outcome is required and invalid');
278
+ }
279
+ const outcome = rawOutcome;
280
+ const hasEvidence = evidence.changedPaths.length > 0
281
+ || evidence.errorSignatures.length > 0
282
+ || evidence.commands.length > 0
283
+ || evidence.tests.length > 0
284
+ || evidence.verification !== undefined;
285
+ if (memories.length === 0 && feedback.length === 0 && !hasEvidence) {
286
+ throw new KiokukoError('VALIDATION_ERROR', 'An empty checkpoint is not allowed');
287
+ }
288
+ if (feedback.length > 0 && deliveryId === undefined) {
289
+ throw new KiokukoError('VALIDATION_ERROR', 'Checkpoint feedback requires deliveryId');
290
+ }
291
+ return {
292
+ ...(cwd === undefined ? {} : { cwd }),
293
+ memories,
294
+ runId,
295
+ ...(deliveryId === undefined ? {} : { deliveryId }),
296
+ outcome,
297
+ feedback,
298
+ evidence,
299
+ };
191
300
  }
192
301
  export async function recallScopedMemory(database, input) {
193
302
  return retrieveFederatedMemory(database, {
@@ -202,49 +311,27 @@ export async function recallScopedMemory(database, input) {
202
311
  });
203
312
  }
204
313
  export async function checkpointScopedMemory(database, input) {
205
- if (!Array.isArray(input.memories))
206
- throw new KiokukoError('VALIDATION_ERROR', 'Checkpoint memories must be an array');
207
- if (input.memories.length === 0 && input.runId === undefined)
208
- throw new KiokukoError('VALIDATION_ERROR', 'A checkpoint requires a run or at least one memory');
209
- if (input.memories.length > 20)
210
- throw new KiokukoError('VALIDATION_ERROR', 'At most 20 memories may be checkpointed at once');
211
- const memories = input.memories.map((memory) => checkpointObject(memory, CHECKPOINT_MEMORY_FIELDS, 'Checkpoint memory is invalid'));
212
- if (input.feedback !== undefined && (!Array.isArray(input.feedback) || input.feedback.length > 100)) {
213
- throw new KiokukoError('VALIDATION_ERROR', 'Checkpoint feedback is invalid');
214
- }
215
- const feedback = (input.feedback ?? []).map((item) => checkpointObject(item, CHECKPOINT_FEEDBACK_FIELDS, 'Checkpoint feedback is invalid'));
216
- if (input.outcome !== undefined && !CHECKPOINT_OUTCOMES.has(input.outcome)) {
217
- throw new KiokukoError('VALIDATION_ERROR', 'Checkpoint outcome is invalid');
218
- }
219
- if (input.deliveryId !== undefined && input.runId === undefined) {
220
- throw new KiokukoError('VALIDATION_ERROR', 'Checkpoint deliveryId requires runId');
221
- }
222
- if (input.runId === undefined && feedback.length > 0) {
223
- throw new KiokukoError('VALIDATION_ERROR', 'Checkpoint feedback requires runId');
224
- }
225
- if (feedback.length > 0 && input.deliveryId === undefined) {
226
- throw new KiokukoError('VALIDATION_ERROR', 'Checkpoint feedback requires deliveryId');
227
- }
228
- const evidence = boundedEvidence(input.evidence);
229
- const hasEvidence = evidence.changedPaths.length > 0 || evidence.errorSignatures.length > 0 || evidence.commands.length > 0 || evidence.tests.length > 0 || evidence.verification !== undefined;
230
- if (input.runId === undefined && hasEvidence) {
231
- throw new KiokukoError('VALIDATION_ERROR', 'Checkpoint evidence requires runId');
232
- }
233
- const run = input.runId === undefined ? undefined : new LedgerStore(database).readRun(input.runId);
234
- if (input.runId !== undefined && run === undefined)
314
+ const request = normalizeCheckpointInput(input);
315
+ const runId = 'runId' in request ? request.runId : undefined;
316
+ const deliveryId = 'runId' in request ? request.deliveryId : undefined;
317
+ const outcome = 'runId' in request ? request.outcome : undefined;
318
+ const feedback = 'runId' in request ? request.feedback : [];
319
+ const evidence = 'runId' in request
320
+ ? request.evidence
321
+ : { changedPaths: [], errorSignatures: [], commands: [], tests: [] };
322
+ const memories = request.memories;
323
+ const run = runId === undefined ? undefined : new LedgerStore(database).readRun(runId);
324
+ if (runId !== undefined && run === undefined)
235
325
  throw new KiokukoError('NOT_FOUND', 'Checkpoint run was not found');
236
326
  if (run !== undefined)
237
327
  assertCheckpointEligible(run.status);
238
- if (input.deliveryId !== undefined) {
239
- const delivery = readContextDelivery(database, { workspace: run.workspace, deliveryId: input.deliveryId });
328
+ if (deliveryId !== undefined) {
329
+ const delivery = readContextDelivery(database, { workspace: run.workspace, deliveryId });
240
330
  if (delivery.runId !== run.runId)
241
331
  throw new KiokukoError('NOT_FOUND', 'Checkpoint delivery was not found for this run');
242
332
  }
243
- if (memories.length === 0 && feedback.length === 0 && !hasEvidence) {
244
- throw new KiokukoError('VALIDATION_ERROR', 'An empty checkpoint is not allowed');
245
- }
246
333
  const needsProject = memories.some((memory) => (memory.scope ?? 'project') === 'project');
247
- const plannedProject = await resolveProjectWorkspaceReadOnly(database, input.cwd);
334
+ const plannedProject = await resolveProjectWorkspaceReadOnly(database, request.cwd);
248
335
  if (needsProject && !plannedProject) {
249
336
  throw new KiokukoError('NOT_FOUND', 'No Git repository or .kiokuko.json binding was found for project-scoped memory; use scope "global" only for cross-project preferences or lessons');
250
337
  }
@@ -325,7 +412,7 @@ export async function checkpointScopedMemory(database, input) {
325
412
  ...(plannedProject === undefined ? {} : { sourceRepositoryId: plannedProject.repositoryId, sourceWorkspace: plannedProject.workspace }),
326
413
  ...(sourceCommit === null ? {} : { sourceCommit }),
327
414
  ...(run === undefined ? {} : { runId: run.runId }),
328
- ...(input.deliveryId === undefined ? {} : { deliveryId: input.deliveryId }),
415
+ ...(deliveryId === undefined ? {} : { deliveryId }),
329
416
  ...(evidenceIds.length === 0 ? {} : { evidenceIds }),
330
417
  ...(evidence.changedPaths.length === 0 ? {} : { sourcePaths: evidence.changedPaths }),
331
418
  clientKind: 'mcp',
@@ -336,7 +423,7 @@ export async function checkpointScopedMemory(database, input) {
336
423
  const preparedFeedback = feedback.map((value, index) => {
337
424
  const record = {
338
425
  workspace: run.workspace,
339
- deliveryId: input.deliveryId,
426
+ deliveryId: deliveryId,
340
427
  entryId: value.entryId,
341
428
  entryRevision: value.entryRevision,
342
429
  verdict: value.verdict,
@@ -350,7 +437,7 @@ export async function checkpointScopedMemory(database, input) {
350
437
  assertContextFeedbackRecordable(database, record);
351
438
  return record;
352
439
  });
353
- const project = await resolveProjectWorkspace(database, input.cwd);
440
+ const project = await resolveProjectWorkspace(database, request.cwd);
354
441
  if (!sameProject(plannedProject, project)) {
355
442
  throw new KiokukoError('CONFLICT', 'Checkpoint project identity changed after validation');
356
443
  }
@@ -394,8 +481,10 @@ export async function checkpointScopedMemory(database, input) {
394
481
  const memoryAck = transactionRun === undefined || memoryEvents.length === 0 ? { eventIds: [] } : store.appendBatchInTransaction(transactionRun.runId, { events: memoryEvents });
395
482
  const eventId = evidenceAck.eventIds[0] ?? memoryAck.eventIds[0] ?? null;
396
483
  if (transactionRun !== undefined) {
484
+ if (outcome === undefined)
485
+ throw new KiokukoError('INTEGRITY_ERROR', 'Run-bound checkpoint outcome is missing');
397
486
  for (const entry of saved) {
398
- database.prepare('INSERT INTO ledger_memory_links (link_id, run_id, event_id, delivery_id, entry_id, created_at) VALUES (?, ?, ?, ?, ?, ?)').run(randomUUID(), transactionRun.runId, eventId, input.deliveryId ?? null, entry.id, now);
487
+ database.prepare('INSERT INTO ledger_memory_links (link_id, run_id, event_id, delivery_id, entry_id, created_at) VALUES (?, ?, ?, ?, ?, ?)').run(randomUUID(), transactionRun.runId, eventId, deliveryId ?? null, entry.id, now);
399
488
  }
400
489
  for (const feedbackRecord of preparedFeedback) {
401
490
  recordContextFeedbackInTransaction(database, feedbackRecord);
@@ -404,7 +493,7 @@ export async function checkpointScopedMemory(database, input) {
404
493
  runId: transactionRun.runId,
405
494
  workspace: transactionRun.workspace,
406
495
  entries: saved,
407
- outcome: input.outcome ?? 'completed',
496
+ outcome,
408
497
  verification: {
409
498
  fresh: evidence.verification?.outcome === 'fresh',
410
499
  passedTests: evidence.tests.filter((test) => test.outcome === 'passed').length,
@@ -413,7 +502,7 @@ export async function checkpointScopedMemory(database, input) {
413
502
  },
414
503
  createdAt: now,
415
504
  });
416
- const updated = new LedgerStore(database).updateRunStatusInTransaction(transactionRun.runId, input.outcome ?? 'completed', now);
505
+ const updated = new LedgerStore(database).updateRunStatusInTransaction(transactionRun.runId, outcome, now);
417
506
  return {
418
507
  saved,
419
508
  run: {