akm-cli 0.9.0-beta.47 → 0.9.0-beta.49

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.
@@ -1,120 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- /**
5
- * #627 — getRelatedSessions helper.
6
- *
7
- * Finds session assets related to a seed by SHARED TAGS / GRAPH ENTITIES —
8
- * NEVER embedding similarity. Modeled on recombine.ts buildRelatednessClusters:
9
- * two sessions relate when they share at least one *topic* tag or graph entity;
10
- * two textually near-identical sessions with no shared topic signal do NOT
11
- * relate. This makes the helper a pure query-layer relatedness lookup that
12
- * makes NO network / embedding calls.
13
- *
14
- * The generic base tags every session asset carries (`session` + the harness
15
- * id, see session-asset.ts) are IGNORED for relatedness — otherwise every
16
- * session would trivially relate to every other. Callers should therefore seed
17
- * with derived topic tags, but the helper defensively strips the generic base
18
- * tags from candidate sessions too.
19
- *
20
- * Relatedness source:
21
- * - `"tags"` — score by count of (seedTags ∩ session tags).
22
- * - `"graph"` — score by count of (seedEntities ∩ session graph entities);
23
- * falls open to tag relatedness when the graph table is empty.
24
- * - `"both"` — sum of the tag + entity overlap.
25
- */
26
- import { makeAssetRef } from "../../core/asset/asset-ref.js";
27
- import { closeDatabase, getAllEntries, getEntitiesByEntryIds, openExistingDatabase, } from "../../indexer/db/db.js";
28
- /** Generic base tags every session asset carries — never a relatedness signal. */
29
- const GENERIC_SESSION_TAGS = new Set(["session"]);
30
- /**
31
- * Build the set of topic tags for a session entry, excluding generic base tags
32
- * (`session`) and the harness segment of the entry name (the harness id is the
33
- * first path component of `<harness>/<id>` and is also carried as a base tag).
34
- */
35
- function topicTagsForSession(entry) {
36
- const harness = entry.entry.name.split("/")[0];
37
- const result = new Set();
38
- for (const tag of entry.entry.tags ?? []) {
39
- if (GENERIC_SESSION_TAGS.has(tag))
40
- continue;
41
- if (harness && tag === harness)
42
- continue;
43
- result.add(tag);
44
- }
45
- return result;
46
- }
47
- /**
48
- * Find session assets related to a seed by shared tags / graph entities.
49
- * Relatedness is signal-based, NOT embedding similarity.
50
- */
51
- export function getRelatedSessions(opts) {
52
- const seedTags = (opts.seedTags ?? [])
53
- .filter((t) => !GENERIC_SESSION_TAGS.has(t))
54
- .map((t) => t.trim())
55
- .filter(Boolean);
56
- const seedEntities = (opts.seedEntities ?? []).map((e) => e.trim().toLowerCase()).filter(Boolean);
57
- const minShared = opts.minShared ?? 1;
58
- const limit = opts.limit ?? 5;
59
- const relatednessSource = opts.relatednessSource ?? "tags";
60
- const excludeRefs = new Set(opts.excludeRefs ?? []);
61
- // Empty seed input → nothing to relate to.
62
- if (seedTags.length === 0 && seedEntities.length === 0)
63
- return [];
64
- const seedTagSet = new Set(seedTags);
65
- const seedEntitySet = new Set(seedEntities);
66
- let db = opts.db;
67
- let ownsDb = false;
68
- if (!db) {
69
- db = openExistingDatabase();
70
- ownsDb = true;
71
- }
72
- try {
73
- const sessions = getAllEntries(db, "session");
74
- // Resolve graph entities for the candidate sessions when requested. Fail
75
- // open to tag relatedness when the graph table is empty (no rows).
76
- let entityByEntryId;
77
- const wantGraph = relatednessSource === "graph" || relatednessSource === "both";
78
- if (wantGraph) {
79
- try {
80
- entityByEntryId = getEntitiesByEntryIds(db, sessions.map((s) => s.id));
81
- }
82
- catch {
83
- entityByEntryId = undefined;
84
- }
85
- }
86
- const hasEntities = !!entityByEntryId && entityByEntryId.size > 0;
87
- // Effective signal selection. "graph" with no entities falls open to tags.
88
- const useTags = relatednessSource === "tags" || relatednessSource === "both" || (wantGraph && !hasEntities);
89
- const useGraph = wantGraph && hasEntities;
90
- const scored = [];
91
- for (const session of sessions) {
92
- const ref = makeAssetRef(session.entry.type, session.entry.name);
93
- if (excludeRefs.has(ref))
94
- continue;
95
- let sharedCount = 0;
96
- if (useTags && seedTagSet.size > 0) {
97
- for (const tag of topicTagsForSession(session)) {
98
- if (seedTagSet.has(tag))
99
- sharedCount += 1;
100
- }
101
- }
102
- if (useGraph && seedEntitySet.size > 0 && entityByEntryId) {
103
- for (const ent of entityByEntryId.get(session.id) ?? []) {
104
- if (seedEntitySet.has(ent))
105
- sharedCount += 1;
106
- }
107
- }
108
- if (sharedCount >= minShared) {
109
- scored.push({ ref, name: session.entry.name, sharedCount });
110
- }
111
- }
112
- // Rank by shared-signal count desc, then ref for a deterministic tiebreak.
113
- scored.sort((a, b) => b.sharedCount - a.sharedCount || a.ref.localeCompare(b.ref));
114
- return scored.slice(0, Math.max(0, limit));
115
- }
116
- finally {
117
- if (ownsDb && db)
118
- closeDatabase(db);
119
- }
120
- }
@@ -1,4 +0,0 @@
1
- // This Source Code Form is subject to the terms of the Mozilla Public
2
- // License, v. 2.0. If a copy of the MPL was not distributed with this
3
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
- export { akmLint } from "./lint/index.js";