@evo-dev/core 0.0.1-alpha.19 → 0.0.1-alpha.20

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.
@@ -40,6 +40,16 @@ import {
40
40
  createOkfKnowledgeVerificationSnapshot,
41
41
  deriveOkfKnowledgeFreshness,
42
42
  } from "./freshness.ts";
43
+ import { type OkfKnowledgeSupportRef, isDirectKnowledgeSupport } from "./support.ts";
44
+
45
+ export type {
46
+ OkfKnowledgeDelivery,
47
+ OkfKnowledgeRuntimeEligibility,
48
+ OkfKnowledgeSourceStatus,
49
+ OkfKnowledgeSupportKind,
50
+ OkfKnowledgeSupportRef,
51
+ } from "./support.ts";
52
+ export { resolveOkfKnowledgeRuntimeEligibility } from "./support.ts";
43
53
 
44
54
  export type OkfKnowledgeDecision =
45
55
  | "auto-accept"
@@ -160,6 +170,7 @@ export interface OkfKnowledgePlanCandidate {
160
170
  scores: OkfKnowledgeCandidateScores;
161
171
  decisionReason: string;
162
172
  evidenceRefs: string[];
173
+ supportRef?: OkfKnowledgeSupportRef;
163
174
  reviewState: OkfKnowledgeReviewState;
164
175
  verificationNotApplicableReason?: string;
165
176
  evalSetRefs?: string[];
@@ -280,6 +291,7 @@ export interface OkfKnowledgeConcept {
280
291
  lifecycle: OkfKnowledgeLifecycle;
281
292
  lifecyclePersisted: boolean;
282
293
  verificationSnapshot: OkfKnowledgeVerificationSnapshotV1 | null;
294
+ supportRef: OkfKnowledgeSupportRef | null;
283
295
  title: string;
284
296
  description: string;
285
297
  tags: string[];
@@ -391,13 +403,13 @@ export interface ScopedKnowledgeContextPack {
391
403
  id: string;
392
404
  okfIndexRevision: string;
393
405
  scope: ScopedKnowledgeContextPackScope;
394
- queryText?: string;
406
+ queryHash?: string;
395
407
  items: ScopedKnowledgeContextPackItem[];
396
408
  warnings: string[];
397
409
  rawContentStored: false;
398
410
  }
399
411
 
400
- export type ContextInjectionTrigger = "team-startup" | "hook-safe-point";
412
+ export type ContextInjectionTrigger = "team-startup" | "hook-safe-point" | "ordinary-session";
401
413
 
402
414
  export interface ContextInjectionReceipt {
403
415
  version: 1;
@@ -405,9 +417,17 @@ export interface ContextInjectionReceipt {
405
417
  okfIndexRevision: string;
406
418
  scope: ScopedKnowledgeContextPackScope;
407
419
  itemIds: string[];
420
+ queryHash: string | null;
408
421
  injectedAt: string;
409
422
  hookEventId: string | null;
410
423
  trigger: ContextInjectionTrigger;
424
+ outcome: null | {
425
+ status: "verified";
426
+ eventId: string;
427
+ observedAt: string;
428
+ summaryHash: string;
429
+ rawContentStored: false;
430
+ };
411
431
  rawContentStored: false;
412
432
  }
413
433
 
@@ -963,6 +983,10 @@ function normalizePlanCandidate(value: unknown, path: string): OkfKnowledgePlanC
963
983
  readRequiredString(input.decisionReason, `${path}.decisionReason`),
964
984
  ),
965
985
  evidenceRefs: readStringArray(input.evidenceRefs, `${path}.evidenceRefs`).map(sanitizeOkfText),
986
+ supportRef:
987
+ input.supportRef === undefined
988
+ ? undefined
989
+ : normalizeKnowledgeSupportRef(input.supportRef, `${path}.supportRef`),
966
990
  reviewState: parseOkfReviewState(readRequiredString(input.reviewState, `${path}.reviewState`)),
967
991
  verificationNotApplicableReason:
968
992
  typeof input.verificationNotApplicableReason === "string"
@@ -1047,6 +1071,7 @@ function validateCandidateContract(
1047
1071
  validateStringArrayValue(candidate.pathScopes, `${path}.pathScopes`, add);
1048
1072
  validateStringArrayValue(candidate.relatedConceptLinks, `${path}.relatedConceptLinks`, add);
1049
1073
  validateStringArrayValue(candidate.evidenceRefs, `${path}.evidenceRefs`, add);
1074
+ validateKnowledgeSupportRefValue(candidate.supportRef, `${path}.supportRef`, add);
1050
1075
  validateOverlayUpdatesValue(candidate.overlayUpdates, `${path}.overlayUpdates`, add);
1051
1076
  validateScoresValue(candidate.scores, `${path}.scores`, add);
1052
1077
  validatePrivacyCheckValue(candidate.privacyCheck, `${path}.privacyCheck`, add);
@@ -1381,6 +1406,33 @@ function normalizeBasis(value: string): "direct" | "inferred" {
1381
1406
  return value;
1382
1407
  }
1383
1408
 
1409
+ function normalizeKnowledgeSupportRef(value: unknown, path: string): OkfKnowledgeSupportRef {
1410
+ const input = assertRecordValue(value, path) as Record<string, unknown>;
1411
+ const kind = readRequiredString(input.kind, `${path}.kind`);
1412
+ if (
1413
+ kind !== "user-declaration" &&
1414
+ kind !== "repo-policy" &&
1415
+ kind !== "state-observation" &&
1416
+ kind !== "verified-outcome" &&
1417
+ kind !== "semantic-inference"
1418
+ ) {
1419
+ throw new Error(`${path}.kind is invalid.`);
1420
+ }
1421
+ const observedAt = readRequiredString(input.observedAt, `${path}.observedAt`);
1422
+ if (!Number.isFinite(Date.parse(observedAt))) throw new Error(`${path}.observedAt is invalid.`);
1423
+ const subjectFingerprint =
1424
+ input.subjectFingerprint === null
1425
+ ? null
1426
+ : sanitizeOkfText(readRequiredString(input.subjectFingerprint, `${path}.subjectFingerprint`));
1427
+ return {
1428
+ id: sanitizeOkfText(readRequiredString(input.id, `${path}.id`)),
1429
+ kind,
1430
+ sourceRefId: sanitizeOkfText(readRequiredString(input.sourceRefId, `${path}.sourceRefId`)),
1431
+ subjectFingerprint,
1432
+ observedAt: new Date(observedAt).toISOString(),
1433
+ };
1434
+ }
1435
+
1384
1436
  function normalizeEvalSetDecision(value: string): OkfKnowledgeEvalSet["decision"] {
1385
1437
  const normalized = value === "no-write" ? "no_write" : value;
1386
1438
  if (
@@ -1550,6 +1602,45 @@ function validateStringArrayValue(
1550
1602
  });
1551
1603
  }
1552
1604
 
1605
+ function validateKnowledgeSupportRefValue(
1606
+ value: unknown,
1607
+ path: string,
1608
+ add: (path: string, code: string, message: string, severity?: "error" | "warning") => void,
1609
+ ): void {
1610
+ if (value === undefined) return;
1611
+ if (!isRecord(value)) {
1612
+ add(path, "supportRef.object", "Candidate supportRef must be an object.");
1613
+ return;
1614
+ }
1615
+ if (!isNonEmptyString(value.id)) add(`${path}.id`, "supportRef.id", "supportRef id is required.");
1616
+ if (
1617
+ value.kind !== "user-declaration" &&
1618
+ value.kind !== "repo-policy" &&
1619
+ value.kind !== "state-observation" &&
1620
+ value.kind !== "verified-outcome" &&
1621
+ value.kind !== "semantic-inference"
1622
+ ) {
1623
+ add(`${path}.kind`, "supportRef.kind", "supportRef kind is invalid.");
1624
+ }
1625
+ if (!isNonEmptyString(value.sourceRefId)) {
1626
+ add(`${path}.sourceRefId`, "supportRef.sourceRefId", "supportRef sourceRefId is required.");
1627
+ }
1628
+ if (value.subjectFingerprint !== null && !isNonEmptyString(value.subjectFingerprint)) {
1629
+ add(
1630
+ `${path}.subjectFingerprint`,
1631
+ "supportRef.subjectFingerprint",
1632
+ "supportRef subjectFingerprint must be null or a non-empty string.",
1633
+ );
1634
+ }
1635
+ if (!isNonEmptyString(value.observedAt) || !Number.isFinite(Date.parse(value.observedAt))) {
1636
+ add(
1637
+ `${path}.observedAt`,
1638
+ "supportRef.observedAt",
1639
+ "supportRef observedAt must be an ISO timestamp.",
1640
+ );
1641
+ }
1642
+ }
1643
+
1553
1644
  function validateOverlayUpdatesValue(
1554
1645
  value: unknown,
1555
1646
  path: string,
@@ -1858,6 +1949,7 @@ export function decideOkfKnowledgeCandidate(
1858
1949
  localActiveTarget &&
1859
1950
  sanitized.targetStore === "okf" &&
1860
1951
  sanitized.basis === "direct" &&
1952
+ isDirectKnowledgeSupport(sanitized.supportRef) &&
1861
1953
  sanitized.metadataOnlyEvidence &&
1862
1954
  hasVerification &&
1863
1955
  hasScopeTags &&
@@ -3101,10 +3193,8 @@ export function mergeAcceptedEvosCasesIntoKnowledgeQuery(
3101
3193
  score: structuredScore + lexical.score,
3102
3194
  title: evosCase.title,
3103
3195
  summary: evosCase.expectedFutureBehavior || evosCase.result.summary || evosCase.title,
3104
- freshness: "verified",
3105
- runtimeExcerpt: sanitizeOkfText(
3106
- evosCase.expectedFutureBehavior || evosCase.result.summary || evosCase.title,
3107
- ).slice(0, 1_200),
3196
+ freshness: "unknown",
3197
+ runtimeExcerpt: null,
3108
3198
  matchReasons:
3109
3199
  lexical.reasons.length === 0
3110
3200
  ? structuredReasons
@@ -3131,16 +3221,24 @@ export async function createScopedKnowledgeContextPack(input: {
3131
3221
  paths?: string[];
3132
3222
  queryText?: string;
3133
3223
  limit?: number;
3224
+ inlineOnly?: boolean;
3134
3225
  }): Promise<ScopedKnowledgeContextPack | null> {
3135
- const result = await queryScopedOkfKnowledgeContext(input);
3136
- if (result.items.length === 0) return null;
3226
+ const result = await queryScopedOkfKnowledgeContext({
3227
+ ...input,
3228
+ limit: input.inlineOnly === true ? Math.max(input.limit ?? 3, 50) : input.limit,
3229
+ });
3230
+ const selectedItems =
3231
+ input.inlineOnly === true
3232
+ ? result.items.filter((item) => item.runtimeExcerpt !== null).slice(0, input.limit ?? 3)
3233
+ : result.items;
3234
+ if (selectedItems.length === 0) return null;
3137
3235
  const scope: ScopedKnowledgeContextPackScope = {
3138
3236
  ...(result.projectKey === undefined ? {} : { projectKey: result.projectKey }),
3139
3237
  ...(result.roleId === undefined ? {} : { roleId: result.roleId }),
3140
3238
  ...(result.workflowId === undefined ? {} : { workflowId: result.workflowId }),
3141
3239
  paths: result.paths,
3142
3240
  };
3143
- const items = result.items.map<ScopedKnowledgeContextPackItem>((item) => ({
3241
+ const items = selectedItems.map<ScopedKnowledgeContextPackItem>((item) => ({
3144
3242
  id: item.id,
3145
3243
  sourceType: item.sourceType,
3146
3244
  sourceLink: item.sourceLink,
@@ -3160,10 +3258,11 @@ export async function createScopedKnowledgeContextPack(input: {
3160
3258
  }));
3161
3259
  const okfIndexRevision = createKnowledgeContextRevision(items);
3162
3260
  const queryText = normalizeKnowledgeQueryText(result.queryText);
3261
+ const queryHash = queryText === undefined ? undefined : sha256Short(queryText);
3163
3262
  const packSeed = stableJsonStringify({
3164
3263
  okfIndexRevision,
3165
3264
  scope,
3166
- queryText: queryText ?? null,
3265
+ queryHash: queryHash ?? null,
3167
3266
  items: items.map((item) => ({
3168
3267
  id: item.id,
3169
3268
  sourceType: item.sourceType,
@@ -3181,7 +3280,7 @@ export async function createScopedKnowledgeContextPack(input: {
3181
3280
  id: `ctxpack-${sha256Short(packSeed)}`,
3182
3281
  okfIndexRevision,
3183
3282
  scope,
3184
- ...(queryText === undefined ? {} : { queryText }),
3283
+ ...(queryHash === undefined ? {} : { queryHash }),
3185
3284
  items,
3186
3285
  warnings:
3187
3286
  result.warnings.length === 0
@@ -3200,7 +3299,6 @@ export function formatScopedKnowledgePromptBlock(pack: ScopedKnowledgeContextPac
3200
3299
  `Project: ${pack.scope.projectKey ?? "all"}`,
3201
3300
  `Role: ${pack.scope.roleId ?? "any"}`,
3202
3301
  `Workflow: ${pack.scope.workflowId ?? "any"}`,
3203
- ...(pack.queryText === undefined ? [] : [`Query: ${sanitizeOkfText(pack.queryText)}`]),
3204
3302
  `Paths: ${pack.scope.paths.length === 0 ? "all" : pack.scope.paths.join(", ")}`,
3205
3303
  "Raw content stored: false",
3206
3304
  "Freshness is determined by EvoDev lifecycle and verification metadata; do not infer validity from timestamps.",
@@ -3266,9 +3364,11 @@ export async function writeContextInjectionReceipt(input: {
3266
3364
  okfIndexRevision: input.pack.okfIndexRevision,
3267
3365
  scope: input.pack.scope,
3268
3366
  itemIds: input.pack.items.map((item) => item.id),
3367
+ queryHash: input.pack.queryHash ?? null,
3269
3368
  injectedAt: input.injectedAt ?? new Date().toISOString(),
3270
3369
  hookEventId: input.hookEventId ?? null,
3271
3370
  trigger: input.trigger,
3371
+ outcome: null,
3272
3372
  rawContentStored: false,
3273
3373
  };
3274
3374
  const path = resolveContextInjectionReceiptPath({
@@ -3280,6 +3380,57 @@ export async function writeContextInjectionReceipt(input: {
3280
3380
  return { path, receipt };
3281
3381
  }
3282
3382
 
3383
+ export async function recordContextInjectionOutcome(input: {
3384
+ homeDir: string;
3385
+ sessionKey: string;
3386
+ eventId: string;
3387
+ observedAt: string;
3388
+ summary: string;
3389
+ }): Promise<string[]> {
3390
+ const stateDir = resolveEvoDevPaths(input.homeDir).stateDir;
3391
+ const directory = join(
3392
+ stateDir,
3393
+ "context-injections",
3394
+ sanitizeReceiptPathSegment(input.sessionKey),
3395
+ );
3396
+ let names: string[];
3397
+ try {
3398
+ names = await readdir(directory);
3399
+ } catch {
3400
+ return [];
3401
+ }
3402
+ const paths: string[] = [];
3403
+ for (const name of names.filter((item) => item.endsWith(".json")).sort()) {
3404
+ const path = join(directory, name);
3405
+ let receipt: ContextInjectionReceipt;
3406
+ try {
3407
+ receipt = JSON.parse(await readFile(path, "utf8")) as ContextInjectionReceipt;
3408
+ } catch {
3409
+ continue;
3410
+ }
3411
+ if (
3412
+ receipt.version !== 1 ||
3413
+ receipt.rawContentStored !== false ||
3414
+ (receipt.outcome !== null && receipt.outcome !== undefined)
3415
+ ) {
3416
+ continue;
3417
+ }
3418
+ const updated: ContextInjectionReceipt = {
3419
+ ...receipt,
3420
+ outcome: {
3421
+ status: "verified",
3422
+ eventId: sanitizeReceiptPathSegment(input.eventId),
3423
+ observedAt: normalizeTimestamp(input.observedAt),
3424
+ summaryHash: sha256Short(input.summary),
3425
+ rawContentStored: false,
3426
+ },
3427
+ };
3428
+ await writeJson(path, updated, { overwrite: true });
3429
+ paths.push(path);
3430
+ }
3431
+ return paths;
3432
+ }
3433
+
3283
3434
  export async function markOkfKnowledgeConceptStale(input: {
3284
3435
  homeDir: string;
3285
3436
  conceptId: string;
@@ -3947,6 +4098,9 @@ function explainAutomaticNoWriteDecision(
3947
4098
  const reasons: string[] = [];
3948
4099
  if (candidate.targetStore !== "okf") reasons.push("target is not user-local OKF");
3949
4100
  if (candidate.basis !== "direct") reasons.push("basis is inferred");
4101
+ if (!isDirectKnowledgeSupport(candidate.supportRef)) {
4102
+ reasons.push("structured direct support is missing");
4103
+ }
3950
4104
  if (!candidate.metadataOnlyEvidence) reasons.push("evidence is not metadata-only");
3951
4105
  if (!hasVerification) reasons.push("verification evidence is missing");
3952
4106
  if (!hasScopeTags) reasons.push("repo or role tags are missing");
@@ -4233,6 +4387,7 @@ function renderOkfConcept(
4233
4387
  ` stableKey: ${yamlString(candidate.stableKey)}`,
4234
4388
  ` reviewState: ${yamlString(reviewState)}`,
4235
4389
  renderLifecycleYaml(" ", lifecycle),
4390
+ renderKnowledgeSupportRefYaml(" ", candidate.supportRef ?? null),
4236
4391
  renderVerificationSnapshotYaml(" ", verificationSnapshot),
4237
4392
  " source:",
4238
4393
  ` kind: ${yamlString("trace-distillation")}`,
@@ -4511,6 +4666,7 @@ function parseOkfConceptFile(
4511
4666
  lifecycle: lifecycleParsed.lifecycle,
4512
4667
  lifecyclePersisted: lifecycleParsed.persisted,
4513
4668
  verificationSnapshot: parseOkfVerificationSnapshot(frontmatter),
4669
+ supportRef: parseOkfKnowledgeSupportRef(frontmatter),
4514
4670
  title,
4515
4671
  description,
4516
4672
  tags,
@@ -4522,6 +4678,27 @@ function parseOkfConceptFile(
4522
4678
  };
4523
4679
  }
4524
4680
 
4681
+ function parseOkfKnowledgeSupportRef(frontmatter: string): OkfKnowledgeSupportRef | null {
4682
+ const block = extractNestedYamlBlock(frontmatter, "evodev", "supportRef");
4683
+ if (block === null) return null;
4684
+ try {
4685
+ return normalizeKnowledgeSupportRef(
4686
+ {
4687
+ id: readIndentedYamlScalar(block, "id"),
4688
+ kind: readIndentedYamlScalar(block, "kind"),
4689
+ sourceRefId: readIndentedYamlScalar(block, "sourceRefId"),
4690
+ subjectFingerprint: readNullableLifecycleString(
4691
+ readIndentedYamlScalar(block, "subjectFingerprint"),
4692
+ ),
4693
+ observedAt: readIndentedYamlScalar(block, "observedAt"),
4694
+ },
4695
+ "evodev.supportRef",
4696
+ );
4697
+ } catch {
4698
+ return null;
4699
+ }
4700
+ }
4701
+
4525
4702
  function parseOkfVerificationSnapshot(
4526
4703
  frontmatter: string,
4527
4704
  ): OkfKnowledgeVerificationSnapshotV1 | null {
@@ -5303,6 +5480,21 @@ function renderVerificationSnapshotYaml(
5303
5480
  ].join("\n");
5304
5481
  }
5305
5482
 
5483
+ function renderKnowledgeSupportRefYaml(
5484
+ indent: string,
5485
+ supportRef: OkfKnowledgeSupportRef | null,
5486
+ ): string {
5487
+ if (supportRef === null) return `${indent}supportRef: null`;
5488
+ return [
5489
+ `${indent}supportRef:`,
5490
+ `${indent} id: ${yamlString(supportRef.id)}`,
5491
+ `${indent} kind: ${yamlString(supportRef.kind)}`,
5492
+ `${indent} sourceRefId: ${yamlString(supportRef.sourceRefId)}`,
5493
+ `${indent} subjectFingerprint: ${yamlNullableString(supportRef.subjectFingerprint)}`,
5494
+ `${indent} observedAt: ${yamlString(supportRef.observedAt)}`,
5495
+ ].join("\n");
5496
+ }
5497
+
5306
5498
  function lifecycleStatusFromReviewState(
5307
5499
  reviewState: OkfKnowledgeReviewState,
5308
5500
  ): OkfKnowledgeLifecycleStatus {
@@ -0,0 +1,135 @@
1
+ export type OkfKnowledgeSupportKind =
2
+ | "user-declaration"
3
+ | "repo-policy"
4
+ | "state-observation"
5
+ | "verified-outcome"
6
+ | "semantic-inference";
7
+
8
+ export interface OkfKnowledgeSupportRef {
9
+ id: string;
10
+ kind: OkfKnowledgeSupportKind;
11
+ sourceRefId: string;
12
+ subjectFingerprint: string | null;
13
+ observedAt: string;
14
+ }
15
+
16
+ export type OkfKnowledgeDelivery = "inline" | "reference" | "blocked";
17
+ export type OkfKnowledgeSourceStatus = "current" | "changed" | "unknown";
18
+
19
+ export interface OkfKnowledgeRuntimeEligibility {
20
+ delivery: OkfKnowledgeDelivery;
21
+ freshness: "verified" | "review-due" | "unknown" | "stale";
22
+ reason: string;
23
+ }
24
+
25
+ export function resolveOkfKnowledgeRuntimeEligibility(input: {
26
+ reviewState: string;
27
+ lifecycle: {
28
+ status: string;
29
+ reviewAfter: string;
30
+ staleAfter: string;
31
+ };
32
+ supportRef: OkfKnowledgeSupportRef | null;
33
+ now?: string | Date;
34
+ sourceStatus?: OkfKnowledgeSourceStatus;
35
+ verifiedContradiction?: boolean;
36
+ }): OkfKnowledgeRuntimeEligibility {
37
+ const now = normalizeNow(input.now);
38
+ if (
39
+ input.verifiedContradiction === true ||
40
+ input.lifecycle.status === "stale" ||
41
+ input.lifecycle.status === "deprecated" ||
42
+ input.lifecycle.status === "revoked" ||
43
+ input.lifecycle.status === "superseded" ||
44
+ input.reviewState === "stale" ||
45
+ input.reviewState === "deprecated" ||
46
+ input.reviewState === "revoked" ||
47
+ input.reviewState === "superseded" ||
48
+ isDue(input.lifecycle.staleAfter, now)
49
+ ) {
50
+ return {
51
+ delivery: "blocked",
52
+ freshness: "stale",
53
+ reason:
54
+ input.verifiedContradiction === true
55
+ ? "Verified evidence contradicts the active claim."
56
+ : "Lifecycle state excludes this knowledge from runtime context.",
57
+ };
58
+ }
59
+ if (input.reviewState !== "accepted" && input.reviewState !== "auto-accepted") {
60
+ return {
61
+ delivery: "blocked",
62
+ freshness: "unknown",
63
+ reason: "Knowledge has not passed an active-compatible review state.",
64
+ };
65
+ }
66
+ if (input.sourceStatus === "changed") {
67
+ return {
68
+ delivery: "blocked",
69
+ freshness: "review-due",
70
+ reason: "The supporting source changed and requires revalidation.",
71
+ };
72
+ }
73
+ if (isDue(input.lifecycle.reviewAfter, now)) {
74
+ return {
75
+ delivery: "reference",
76
+ freshness: "review-due",
77
+ reason: `Review was due at ${input.lifecycle.reviewAfter}.`,
78
+ };
79
+ }
80
+ if (input.supportRef === null) {
81
+ return {
82
+ delivery: "reference",
83
+ freshness: "unknown",
84
+ reason: "Legacy knowledge has no structured support reference.",
85
+ };
86
+ }
87
+ if (input.supportRef.kind === "semantic-inference") {
88
+ if (input.reviewState === "accepted") {
89
+ return {
90
+ delivery: "inline",
91
+ freshness: "verified",
92
+ reason: "A human-accepted inference is runtime-eligible as an explicit decision.",
93
+ };
94
+ }
95
+ return {
96
+ delivery: "reference",
97
+ freshness: "unknown",
98
+ reason: "Model-inferred knowledge remains on-demand until supported by a direct source.",
99
+ };
100
+ }
101
+ if (
102
+ (input.supportRef.kind === "repo-policy" || input.supportRef.kind === "state-observation") &&
103
+ input.sourceStatus !== "current"
104
+ ) {
105
+ return {
106
+ delivery: "reference",
107
+ freshness: "unknown",
108
+ reason: "The supporting repository source has not been revalidated for this query.",
109
+ };
110
+ }
111
+ return {
112
+ delivery: "inline",
113
+ freshness: "verified",
114
+ reason: `Runtime-eligible through ${input.supportRef.kind}.`,
115
+ };
116
+ }
117
+
118
+ export function isDirectKnowledgeSupport(
119
+ supportRef: OkfKnowledgeSupportRef | null | undefined,
120
+ ): boolean {
121
+ return (
122
+ supportRef !== undefined && supportRef !== null && supportRef.kind !== "semantic-inference"
123
+ );
124
+ }
125
+
126
+ function normalizeNow(value: string | Date | undefined): Date {
127
+ if (value instanceof Date && Number.isFinite(value.getTime())) return value;
128
+ if (typeof value === "string" && Number.isFinite(Date.parse(value))) return new Date(value);
129
+ return new Date();
130
+ }
131
+
132
+ function isDue(value: string, now: Date): boolean {
133
+ const timestamp = Date.parse(value);
134
+ return Number.isFinite(timestamp) && timestamp <= now.getTime();
135
+ }