@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.
Files changed (105) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/manifests/documentation.yaml +11 -0
  3. package/package.json +1 -1
  4. package/scripts/audit/decision-coverage.mjs +29 -2
  5. package/scripts/bench/data-foundation.mjs +52 -3
  6. package/scripts/bench/decision-runtime-baseline.mjs +427 -0
  7. package/scripts/bench/decision-runtime-metrics.mjs +67 -0
  8. package/scripts/bench/decision-runtime-variant.mjs +626 -0
  9. package/scripts/bench/memory-ablation.mjs +495 -0
  10. package/scripts/bench/memory-baseline.mjs +596 -0
  11. package/scripts/bench/memory-bench.mjs +661 -0
  12. package/scripts/bench/memory-canary.mjs +321 -0
  13. package/scripts/bench/memory-corpus.mjs +354 -0
  14. package/scripts/bench/memory-gate.mjs +389 -0
  15. package/scripts/bench/memory-metrics.mjs +179 -0
  16. package/scripts/bench/parallel-agents.mjs +33 -11
  17. package/scripts/bench/recorder-overhead.mjs +204 -0
  18. package/scripts/bench/sqlite-spike.mjs +451 -0
  19. package/scripts/measure-decision-gateway.mjs +306 -0
  20. package/scripts/perf/audit-perf.mjs +35 -17
  21. package/src/bug/triageBug.js +4 -3
  22. package/src/cli/commands/memory.js +357 -63
  23. package/src/context/detectProjectContext.js +11 -1
  24. package/src/core/agentRuntime/adapters.js +254 -0
  25. package/src/core/agentRuntime/artifacts.js +192 -0
  26. package/src/core/agentRuntime/completionGate.js +176 -0
  27. package/src/core/agentRuntime/context.js +149 -0
  28. package/src/core/agentRuntime/contract.js +247 -0
  29. package/src/core/agentRuntime/diagnostics.js +244 -0
  30. package/src/core/agentRuntime/evaluation.js +163 -0
  31. package/src/core/agentRuntime/eventStore.js +404 -0
  32. package/src/core/agentRuntime/liveness.js +60 -0
  33. package/src/core/agentRuntime/planCompiler.js +322 -0
  34. package/src/core/agentRuntime/promotion.js +53 -0
  35. package/src/core/agentRuntime/qualityComparison.js +112 -0
  36. package/src/core/agentRuntime/recovery.js +266 -0
  37. package/src/core/agentRuntime/resourcePolicy.js +78 -0
  38. package/src/core/agentRuntime/runtimeSupport.js +237 -0
  39. package/src/core/agentRuntime/supervisor.js +565 -0
  40. package/src/core/agentRuntime/vmEngine.js +621 -0
  41. package/src/core/codeintel/analogy.js +3 -2
  42. package/src/core/experiments/dynamicWorkflow.js +17 -2
  43. package/src/core/fileOps.js +21 -3
  44. package/src/core/memory/deltaOverlays.js +75 -30
  45. package/src/core/memory/learningCandidates.js +93 -48
  46. package/src/core/memory/memoryFlags.js +83 -0
  47. package/src/core/memory/memoryFreshness.js +190 -0
  48. package/src/core/memory/memoryHit.js +144 -0
  49. package/src/core/memory/migrate.js +69 -189
  50. package/src/core/memory/migrateMapping.js +232 -0
  51. package/src/core/memory/mutateMemory.js +323 -0
  52. package/src/core/memory/policy.js +96 -0
  53. package/src/core/memory/projectIdentity.js +266 -0
  54. package/src/core/memory/recordIndex.js +178 -0
  55. package/src/core/memory/recordStore.js +133 -20
  56. package/src/core/memory/records.js +144 -6
  57. package/src/core/memory/retrieval.js +259 -125
  58. package/src/core/memory/store.js +16 -5
  59. package/src/core/memory/storeBackup.js +226 -0
  60. package/src/core/memory/storeV2.js +63 -26
  61. package/src/core/memory/storeV2Loader.js +30 -12
  62. package/src/core/memory/userMemory.js +38 -20
  63. package/src/core/memory/writeClassification.js +161 -0
  64. package/src/core/memory/writeGuard.js +129 -0
  65. package/src/core/observability/adapters/hookTelemetryAdapter.js +90 -0
  66. package/src/core/observability/analytics/cohorts.js +148 -0
  67. package/src/core/observability/analytics/storeDigest.js +163 -0
  68. package/src/core/observability/evaluation/experimentPlan.js +95 -0
  69. package/src/core/observability/evaluation/findings.js +99 -0
  70. package/src/core/observability/evaluation/optimizationKnowledge.js +10 -1
  71. package/src/core/observability/evaluation/perturbation.js +273 -0
  72. package/src/core/observability/evaluation/replay.js +7 -1
  73. package/src/core/observability/evaluation/scorecard.js +23 -3
  74. package/src/core/observability/rollout.js +11 -7
  75. package/src/core/observability/schema/compatibility.js +135 -0
  76. package/src/core/observability/schema/registry.js +99 -0
  77. package/src/core/observability/schema/validate.js +7 -0
  78. package/src/core/observability/support/import.js +53 -9
  79. package/src/core/observability/support/paths.js +13 -3
  80. package/src/core/observability/support/projector.js +148 -12
  81. package/src/core/output/index.js +12 -2
  82. package/src/core/runtimeConfig.js +83 -0
  83. package/src/core/runtimePaths.js +3 -0
  84. package/src/core/sensitiveValueScanner.js +40 -0
  85. package/src/core/token/index.js +40 -3
  86. package/src/decision/client.js +37 -13
  87. package/src/decision/protocol.js +1 -1
  88. package/src/decision/registry.js +5 -3
  89. package/src/decision/runtimeDecide.js +242 -0
  90. package/src/decision/runtimeFilter.js +150 -0
  91. package/src/decision/runtimeScheduler.js +239 -0
  92. package/src/index/buildIndex.js +13 -12
  93. package/src/index/queryIndex.js +35 -14
  94. package/src/index/relatedTests.js +50 -8
  95. package/src/index/resolveContext.js +9 -4
  96. package/src/manifest/selectItems.js +7 -3
  97. package/src/render/instructionRenderer.js +17 -5
  98. package/template_project/.claude/ukit/index/lib/index-core.mjs +94 -39
  99. package/template_project/.claude/ukit/index/route-task.mjs +121 -19
  100. package/template_project/.claude/ukit/index/unic-decision.mjs +28 -13
  101. package/template_project/.claude/ukit/runtime/memory-flags.mjs +51 -0
  102. package/template_project/.claude/ukit/runtime/memory-freshness.mjs +155 -0
  103. package/template_project/.claude/ukit/runtime/memory-policy.mjs +286 -0
  104. package/template_project/.claude/ukit/runtime/output-compression.mjs +3 -0
  105. 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' || !/^mem_[0-9a-f]{12}$/.test(record.id)) {
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
- const status = RECORD_STATUSES.includes(raw.status) ? raw.status : 'active';
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' && /^mem_[0-9a-f]{12}$/.test(raw.id) ? raw.id : newId(),
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: raw.meta && typeof raw.meta === 'object' && !Array.isArray(raw.meta) ? raw.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);