@ngockhoale/ukit 3.0.8 → 3.0.9
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/CHANGELOG.md +14 -1
- package/manifests/documentation.yaml +11 -0
- package/package.json +1 -1
- package/scripts/audit/decision-coverage.mjs +29 -2
- package/scripts/bench/data-foundation.mjs +52 -3
- package/scripts/bench/decision-runtime-baseline.mjs +427 -0
- package/scripts/bench/decision-runtime-metrics.mjs +67 -0
- package/scripts/bench/decision-runtime-variant.mjs +626 -0
- package/scripts/bench/memory-ablation.mjs +495 -0
- package/scripts/bench/memory-baseline.mjs +596 -0
- package/scripts/bench/memory-bench.mjs +661 -0
- package/scripts/bench/memory-canary.mjs +321 -0
- package/scripts/bench/memory-corpus.mjs +354 -0
- package/scripts/bench/memory-gate.mjs +389 -0
- package/scripts/bench/memory-metrics.mjs +179 -0
- package/scripts/bench/parallel-agents.mjs +33 -11
- package/scripts/bench/recorder-overhead.mjs +204 -0
- package/scripts/bench/sqlite-spike.mjs +451 -0
- package/scripts/measure-decision-gateway.mjs +306 -0
- package/scripts/perf/audit-perf.mjs +35 -17
- package/src/bug/triageBug.js +4 -3
- package/src/cli/commands/memory.js +357 -63
- package/src/context/detectProjectContext.js +11 -1
- package/src/core/agentRuntime/adapters.js +254 -0
- package/src/core/agentRuntime/artifacts.js +192 -0
- package/src/core/agentRuntime/completionGate.js +176 -0
- package/src/core/agentRuntime/context.js +149 -0
- package/src/core/agentRuntime/contract.js +247 -0
- package/src/core/agentRuntime/diagnostics.js +244 -0
- package/src/core/agentRuntime/evaluation.js +163 -0
- package/src/core/agentRuntime/eventStore.js +404 -0
- package/src/core/agentRuntime/liveness.js +60 -0
- package/src/core/agentRuntime/planCompiler.js +322 -0
- package/src/core/agentRuntime/promotion.js +53 -0
- package/src/core/agentRuntime/qualityComparison.js +112 -0
- package/src/core/agentRuntime/recovery.js +266 -0
- package/src/core/agentRuntime/resourcePolicy.js +78 -0
- package/src/core/agentRuntime/runtimeSupport.js +237 -0
- package/src/core/agentRuntime/supervisor.js +565 -0
- package/src/core/agentRuntime/vmEngine.js +621 -0
- package/src/core/codeintel/analogy.js +3 -2
- package/src/core/experiments/dynamicWorkflow.js +17 -2
- package/src/core/fileOps.js +21 -3
- package/src/core/memory/deltaOverlays.js +75 -30
- package/src/core/memory/learningCandidates.js +93 -48
- package/src/core/memory/memoryFlags.js +83 -0
- package/src/core/memory/memoryFreshness.js +190 -0
- package/src/core/memory/memoryHit.js +144 -0
- package/src/core/memory/migrate.js +69 -189
- package/src/core/memory/migrateMapping.js +232 -0
- package/src/core/memory/mutateMemory.js +323 -0
- package/src/core/memory/policy.js +96 -0
- package/src/core/memory/projectIdentity.js +266 -0
- package/src/core/memory/recordIndex.js +178 -0
- package/src/core/memory/recordStore.js +133 -20
- package/src/core/memory/records.js +144 -6
- package/src/core/memory/retrieval.js +259 -125
- package/src/core/memory/store.js +16 -5
- package/src/core/memory/storeBackup.js +226 -0
- package/src/core/memory/storeV2.js +63 -26
- package/src/core/memory/storeV2Loader.js +30 -12
- package/src/core/memory/userMemory.js +38 -20
- package/src/core/memory/writeClassification.js +161 -0
- package/src/core/memory/writeGuard.js +129 -0
- package/src/core/observability/adapters/hookTelemetryAdapter.js +90 -0
- package/src/core/observability/analytics/cohorts.js +148 -0
- package/src/core/observability/analytics/storeDigest.js +163 -0
- package/src/core/observability/evaluation/experimentPlan.js +95 -0
- package/src/core/observability/evaluation/findings.js +99 -0
- package/src/core/observability/evaluation/optimizationKnowledge.js +10 -1
- package/src/core/observability/evaluation/perturbation.js +273 -0
- package/src/core/observability/evaluation/replay.js +7 -1
- package/src/core/observability/evaluation/scorecard.js +23 -3
- package/src/core/observability/rollout.js +11 -7
- package/src/core/observability/schema/compatibility.js +135 -0
- package/src/core/observability/schema/registry.js +99 -0
- package/src/core/observability/schema/validate.js +7 -0
- package/src/core/observability/support/import.js +53 -9
- package/src/core/observability/support/paths.js +13 -3
- package/src/core/observability/support/projector.js +148 -12
- package/src/core/output/index.js +12 -2
- package/src/core/runtimeConfig.js +83 -0
- package/src/core/runtimePaths.js +3 -0
- package/src/core/sensitiveValueScanner.js +40 -0
- package/src/core/token/index.js +40 -3
- package/src/decision/client.js +37 -13
- package/src/decision/protocol.js +1 -1
- package/src/decision/registry.js +5 -3
- package/src/decision/runtimeDecide.js +242 -0
- package/src/decision/runtimeFilter.js +150 -0
- package/src/decision/runtimeScheduler.js +239 -0
- package/src/index/buildIndex.js +13 -12
- package/src/index/queryIndex.js +35 -14
- package/src/index/relatedTests.js +50 -8
- package/src/index/resolveContext.js +9 -4
- package/src/manifest/selectItems.js +7 -3
- package/src/render/instructionRenderer.js +17 -5
- package/template_project/.claude/ukit/index/lib/index-core.mjs +94 -39
- package/template_project/.claude/ukit/index/route-task.mjs +121 -19
- package/template_project/.claude/ukit/index/unic-decision.mjs +28 -13
- package/template_project/.claude/ukit/runtime/memory-flags.mjs +51 -0
- package/template_project/.claude/ukit/runtime/memory-freshness.mjs +155 -0
- package/template_project/.claude/ukit/runtime/memory-policy.mjs +286 -0
- package/template_project/.claude/ukit/runtime/output-compression.mjs +3 -0
- package/template_project/.claude/ukit/runtime/reinject-context.mjs +145 -14
|
@@ -25,6 +25,43 @@ export const RECORD_STATUSES = Object.freeze([
|
|
|
25
25
|
'archived',
|
|
26
26
|
]);
|
|
27
27
|
|
|
28
|
+
export const SCHEMA_VERSION_RECORD = 2;
|
|
29
|
+
|
|
30
|
+
export const RECORD_TRUST_TIERS = Object.freeze([
|
|
31
|
+
'verified',
|
|
32
|
+
'legacy-unverified',
|
|
33
|
+
'candidate',
|
|
34
|
+
'observation',
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
export const RECORD_REASONS = Object.freeze([
|
|
38
|
+
'manual',
|
|
39
|
+
'migration',
|
|
40
|
+
'promotion',
|
|
41
|
+
'superseded',
|
|
42
|
+
'expired',
|
|
43
|
+
'purged',
|
|
44
|
+
'review',
|
|
45
|
+
'unknown-status',
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
export const EVIDENCE_KINDS = Object.freeze([
|
|
49
|
+
'file',
|
|
50
|
+
'command',
|
|
51
|
+
'ledger',
|
|
52
|
+
'manual',
|
|
53
|
+
'import',
|
|
54
|
+
]);
|
|
55
|
+
|
|
56
|
+
export const MAX_EVIDENCE = 8;
|
|
57
|
+
export const MAX_LOCATOR = 512;
|
|
58
|
+
|
|
59
|
+
// Record ids: `mem_<12 hex>` (random, createRecord default) or
|
|
60
|
+
// `v1-<40 hex sha1>` (deterministic migration ids — SPEC §5 FR-001).
|
|
61
|
+
const MEM_ID_RE = /^mem_[0-9a-f]{12}$/;
|
|
62
|
+
const V1_ID_RE = /^v1-[0-9a-f]{40}$/;
|
|
63
|
+
const RECORD_ID_RE = /^(mem_[0-9a-f]{12}|v1-[0-9a-f]{40})$/;
|
|
64
|
+
|
|
28
65
|
function newId() {
|
|
29
66
|
return `mem_${crypto.randomBytes(6).toString('hex')}`;
|
|
30
67
|
}
|
|
@@ -37,8 +74,8 @@ export function validateRecord(record) {
|
|
|
37
74
|
if (!record || typeof record !== 'object' || Array.isArray(record)) {
|
|
38
75
|
return { ok: false, errors: ['record is not an object'] };
|
|
39
76
|
}
|
|
40
|
-
if (typeof record.id !== 'string' ||
|
|
41
|
-
errors.push('id must match mem_<12 hex>');
|
|
77
|
+
if (typeof record.id !== 'string' || !RECORD_ID_RE.test(record.id)) {
|
|
78
|
+
errors.push('id must match mem_<12 hex> | v1-<40 hex>');
|
|
42
79
|
}
|
|
43
80
|
if (!RECORD_TYPES.includes(record.type)) {
|
|
44
81
|
errors.push(`type must be one of ${RECORD_TYPES.join('|')}`);
|
|
@@ -78,6 +115,64 @@ export function validateRecord(record) {
|
|
|
78
115
|
if (record.meta == null || typeof record.meta !== 'object' || Array.isArray(record.meta)) {
|
|
79
116
|
errors.push('meta must be an object');
|
|
80
117
|
}
|
|
118
|
+
if (record.schema_version != null
|
|
119
|
+
&& (!Number.isInteger(record.schema_version) || record.schema_version < 1)) {
|
|
120
|
+
errors.push('schema_version must be a positive integer');
|
|
121
|
+
}
|
|
122
|
+
if (record.evidence != null) {
|
|
123
|
+
if (!Array.isArray(record.evidence) || record.evidence.length > MAX_EVIDENCE) {
|
|
124
|
+
errors.push(`evidence must be an array of at most ${MAX_EVIDENCE} entries`);
|
|
125
|
+
} else {
|
|
126
|
+
for (const entry of record.evidence) {
|
|
127
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
|
|
128
|
+
errors.push('evidence entry must be an object');
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (!EVIDENCE_KINDS.includes(entry.kind)) {
|
|
132
|
+
errors.push(`evidence.kind must be one of ${EVIDENCE_KINDS.join('|')}`);
|
|
133
|
+
}
|
|
134
|
+
if (typeof entry.locator !== 'string' || entry.locator.length === 0
|
|
135
|
+
|| entry.locator.length > MAX_LOCATOR) {
|
|
136
|
+
errors.push(`evidence.locator must be a non-empty string <= ${MAX_LOCATOR} chars`);
|
|
137
|
+
}
|
|
138
|
+
if (typeof entry.observed_at !== 'number' || !Number.isFinite(entry.observed_at)) {
|
|
139
|
+
errors.push('evidence.observed_at must be epoch ms');
|
|
140
|
+
}
|
|
141
|
+
if (entry.fingerprint != null && typeof entry.fingerprint !== 'string') {
|
|
142
|
+
errors.push('evidence.fingerprint must be string | null');
|
|
143
|
+
}
|
|
144
|
+
if (!RECORD_TRUST_TIERS.includes(entry.trust_tier)) {
|
|
145
|
+
errors.push(`evidence.trust_tier must be one of ${RECORD_TRUST_TIERS.join('|')}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (record.valid_from != null
|
|
151
|
+
&& (typeof record.valid_from !== 'number' || !Number.isFinite(record.valid_from))) {
|
|
152
|
+
errors.push('valid_from must be epoch ms | null');
|
|
153
|
+
}
|
|
154
|
+
if (record.revision != null
|
|
155
|
+
&& (!Number.isInteger(record.revision) || record.revision < 1)) {
|
|
156
|
+
errors.push('revision must be an integer >= 1');
|
|
157
|
+
}
|
|
158
|
+
if (record.supersedes != null) {
|
|
159
|
+
if (!Array.isArray(record.supersedes)
|
|
160
|
+
|| record.supersedes.some((s) => typeof s !== 'string' || !RECORD_ID_RE.test(s))) {
|
|
161
|
+
errors.push('supersedes must be an array of record ids');
|
|
162
|
+
} else if (typeof record.id === 'string' && record.supersedes.includes(record.id)) {
|
|
163
|
+
errors.push('supersedes must not contain own id');
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (record.superseded_by != null
|
|
167
|
+
&& (typeof record.superseded_by !== 'string' || !RECORD_ID_RE.test(record.superseded_by))) {
|
|
168
|
+
errors.push('superseded_by must be record id | null');
|
|
169
|
+
}
|
|
170
|
+
if (record.trust_tier != null && !RECORD_TRUST_TIERS.includes(record.trust_tier)) {
|
|
171
|
+
errors.push(`trust_tier must be one of ${RECORD_TRUST_TIERS.join('|')}`);
|
|
172
|
+
}
|
|
173
|
+
if (record.reason != null && !RECORD_REASONS.includes(record.reason)) {
|
|
174
|
+
errors.push(`reason must be one of ${RECORD_REASONS.join('|')}`);
|
|
175
|
+
}
|
|
81
176
|
return { ok: errors.length === 0, errors };
|
|
82
177
|
}
|
|
83
178
|
|
|
@@ -85,6 +180,7 @@ export function validateRecord(record) {
|
|
|
85
180
|
* createRecord(input) → record — validates + fills defaults. Throws on invalid input.
|
|
86
181
|
*/
|
|
87
182
|
export function createRecord({
|
|
183
|
+
id = null,
|
|
88
184
|
type,
|
|
89
185
|
scope,
|
|
90
186
|
text,
|
|
@@ -95,9 +191,16 @@ export function createRecord({
|
|
|
95
191
|
projectId = null,
|
|
96
192
|
validUntil = null,
|
|
97
193
|
meta = {},
|
|
194
|
+
evidence = [],
|
|
195
|
+
validFrom = null,
|
|
196
|
+
revision = 1,
|
|
197
|
+
supersedes = [],
|
|
198
|
+
supersededBy = null,
|
|
199
|
+
trustTier = 'verified',
|
|
200
|
+
reason = 'manual',
|
|
98
201
|
} = {}) {
|
|
99
202
|
const record = {
|
|
100
|
-
id: newId(),
|
|
203
|
+
id: id != null ? id : newId(),
|
|
101
204
|
type,
|
|
102
205
|
scope,
|
|
103
206
|
text,
|
|
@@ -110,6 +213,14 @@ export function createRecord({
|
|
|
110
213
|
status: 'active',
|
|
111
214
|
project_id: projectId,
|
|
112
215
|
meta,
|
|
216
|
+
schema_version: SCHEMA_VERSION_RECORD,
|
|
217
|
+
evidence,
|
|
218
|
+
valid_from: validFrom,
|
|
219
|
+
revision,
|
|
220
|
+
supersedes,
|
|
221
|
+
superseded_by: supersededBy,
|
|
222
|
+
trust_tier: trustTier,
|
|
223
|
+
reason,
|
|
113
224
|
};
|
|
114
225
|
const { ok, errors } = validateRecord(record);
|
|
115
226
|
if (!ok) {
|
|
@@ -129,7 +240,26 @@ export function normalizeRecord(raw) {
|
|
|
129
240
|
if (!type || !text) return null;
|
|
130
241
|
|
|
131
242
|
const scope = RECORD_SCOPES.includes(raw.scope) ? raw.scope : 'repo';
|
|
132
|
-
|
|
243
|
+
|
|
244
|
+
// Fail-safe: unknown status or a record-level schema_version newer than this
|
|
245
|
+
// build must never coerce to 'active' — archive + flag for review instead.
|
|
246
|
+
const meta = raw.meta && typeof raw.meta === 'object' && !Array.isArray(raw.meta)
|
|
247
|
+
? { ...raw.meta } : {};
|
|
248
|
+
let status = raw.status == null
|
|
249
|
+
? 'active'
|
|
250
|
+
: (RECORD_STATUSES.includes(raw.status) ? raw.status : null);
|
|
251
|
+
let reason = RECORD_REASONS.includes(raw.reason) ? raw.reason : 'manual';
|
|
252
|
+
if (status == null) {
|
|
253
|
+
status = 'archived';
|
|
254
|
+
reason = 'unknown-status';
|
|
255
|
+
meta.unknown_status = String(raw.status).slice(0, 64);
|
|
256
|
+
} else if (typeof raw.schema_version === 'number'
|
|
257
|
+
&& Number.isInteger(raw.schema_version)
|
|
258
|
+
&& raw.schema_version > SCHEMA_VERSION_RECORD) {
|
|
259
|
+
status = 'archived';
|
|
260
|
+
reason = 'unknown-status';
|
|
261
|
+
meta.unknown_status = `schema_version:${raw.schema_version}`.slice(0, 64);
|
|
262
|
+
}
|
|
133
263
|
|
|
134
264
|
let confidence = typeof raw.confidence === 'number' && !Number.isNaN(raw.confidence)
|
|
135
265
|
? raw.confidence : 1.0;
|
|
@@ -141,7 +271,7 @@ export function normalizeRecord(raw) {
|
|
|
141
271
|
? raw.valid_until : null;
|
|
142
272
|
|
|
143
273
|
const record = {
|
|
144
|
-
id: typeof raw.id === 'string' &&
|
|
274
|
+
id: typeof raw.id === 'string' && RECORD_ID_RE.test(raw.id) ? raw.id : newId(),
|
|
145
275
|
type,
|
|
146
276
|
scope,
|
|
147
277
|
text,
|
|
@@ -154,7 +284,15 @@ export function normalizeRecord(raw) {
|
|
|
154
284
|
valid_until: validUntil,
|
|
155
285
|
status,
|
|
156
286
|
project_id: typeof raw.project_id === 'string' ? raw.project_id : null,
|
|
157
|
-
meta
|
|
287
|
+
meta,
|
|
288
|
+
schema_version: SCHEMA_VERSION_RECORD,
|
|
289
|
+
evidence: raw.evidence != null ? raw.evidence : [],
|
|
290
|
+
valid_from: raw.valid_from != null ? raw.valid_from : null,
|
|
291
|
+
revision: raw.revision != null ? raw.revision : 1,
|
|
292
|
+
supersedes: raw.supersedes != null ? raw.supersedes : [],
|
|
293
|
+
superseded_by: raw.superseded_by != null ? raw.superseded_by : null,
|
|
294
|
+
trust_tier: raw.trust_tier != null ? raw.trust_tier : 'verified',
|
|
295
|
+
reason,
|
|
158
296
|
};
|
|
159
297
|
|
|
160
298
|
const { ok } = validateRecord(record);
|