zam-core 0.7.0 → 0.7.2
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/.agent/skills/zam/SKILL.md +12 -0
- package/.agents/skills/zam/SKILL.md +12 -0
- package/.claude/skills/zam/SKILL.md +12 -0
- package/dist/cli/index.js +1140 -117
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +71 -3
- package/dist/index.js +150 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -562,16 +562,23 @@ interface Prerequisite {
|
|
|
562
562
|
/** A prerequisite row joined with the token it points to. */
|
|
563
563
|
interface PrerequisiteWithToken extends Prerequisite {
|
|
564
564
|
slug: string;
|
|
565
|
+
title: string;
|
|
565
566
|
concept: string;
|
|
566
567
|
domain: string;
|
|
567
568
|
bloom_level: number;
|
|
568
569
|
}
|
|
570
|
+
/**
|
|
571
|
+
* Collect all prerequisite edges as an adjacency map: child → parent set.
|
|
572
|
+
* Only used for cycle detection; the full graph is loaded once per
|
|
573
|
+
* addPrerequisite call (small N in practice).
|
|
574
|
+
*/
|
|
575
|
+
declare function buildAncestorMap(db: Database): Promise<Map<string, Set<string>>>;
|
|
569
576
|
/**
|
|
570
577
|
* Returns true if adding edge (tokenId → requiresId) would create a cycle.
|
|
571
578
|
* Uses BFS from requiresId: if tokenId is reachable, adding the edge closes
|
|
572
579
|
* a loop.
|
|
573
580
|
*/
|
|
574
|
-
declare function wouldCreateCycle(db: Database, tokenId: string, requiresId: string): Promise<boolean>;
|
|
581
|
+
declare function wouldCreateCycle(db: Database, tokenId: string, requiresId: string, ancestors?: Map<string, Set<string>>): Promise<boolean>;
|
|
575
582
|
/**
|
|
576
583
|
* Add a prerequisite edge: tokenId requires requiresId.
|
|
577
584
|
*
|
|
@@ -597,6 +604,7 @@ declare function getDependents(db: Database, tokenId: string): Promise<Prerequis
|
|
|
597
604
|
interface NeighborhoodToken {
|
|
598
605
|
id: string;
|
|
599
606
|
slug: string;
|
|
607
|
+
title: string;
|
|
600
608
|
concept: string;
|
|
601
609
|
domain: string;
|
|
602
610
|
bloom_level: number;
|
|
@@ -796,6 +804,7 @@ type SymbiosisMode = "shadowing" | "copilot" | "autonomy";
|
|
|
796
804
|
interface Token {
|
|
797
805
|
id: string;
|
|
798
806
|
slug: string;
|
|
807
|
+
title: string;
|
|
799
808
|
concept: string;
|
|
800
809
|
domain: string;
|
|
801
810
|
bloom_level: BloomLevel$1;
|
|
@@ -811,6 +820,7 @@ interface Token {
|
|
|
811
820
|
}
|
|
812
821
|
interface CreateTokenInput {
|
|
813
822
|
slug: string;
|
|
823
|
+
title?: string;
|
|
814
824
|
concept: string;
|
|
815
825
|
domain?: string;
|
|
816
826
|
bloom_level?: BloomLevel$1;
|
|
@@ -822,6 +832,7 @@ interface CreateTokenInput {
|
|
|
822
832
|
topic_id?: string | null;
|
|
823
833
|
}
|
|
824
834
|
interface UpdateTokenInput {
|
|
835
|
+
title?: string | null;
|
|
825
836
|
concept?: string;
|
|
826
837
|
domain?: string;
|
|
827
838
|
bloom_level?: BloomLevel$1;
|
|
@@ -834,6 +845,11 @@ interface UpdateTokenInput {
|
|
|
834
845
|
}
|
|
835
846
|
interface ListTokensOptions {
|
|
836
847
|
domain?: string;
|
|
848
|
+
/**
|
|
849
|
+
* Filter by domain prefix using `/` as separator (e.g. "docuware-cops").
|
|
850
|
+
* Matches exact or startsWith(prefix + "/").
|
|
851
|
+
*/
|
|
852
|
+
domainPrefix?: string;
|
|
837
853
|
}
|
|
838
854
|
interface TokenDeleteImpact {
|
|
839
855
|
cards: number;
|
|
@@ -909,6 +925,7 @@ declare function listTokens(db: Database, options?: ListTokensOptions): Promise<
|
|
|
909
925
|
interface PersonalCard {
|
|
910
926
|
tokenId: string;
|
|
911
927
|
slug: string;
|
|
928
|
+
title: string;
|
|
912
929
|
concept: string;
|
|
913
930
|
domain: string;
|
|
914
931
|
bloomLevel: BloomLevel$1;
|
|
@@ -932,6 +949,18 @@ interface PersonalCard {
|
|
|
932
949
|
topicId: string | null;
|
|
933
950
|
}
|
|
934
951
|
declare function slugify(text: string): string;
|
|
952
|
+
/**
|
|
953
|
+
* Strip domain prefix (using / separator) from slug for display.
|
|
954
|
+
*/
|
|
955
|
+
declare function getShortSlug(slug: string, domainPrefix?: string | null): string;
|
|
956
|
+
/**
|
|
957
|
+
* Primary display name for a token: human title if present, else short slug.
|
|
958
|
+
* Never falls back to concept (which is a spoiler).
|
|
959
|
+
*/
|
|
960
|
+
declare function getDisplayTitle(t: {
|
|
961
|
+
title?: string | null;
|
|
962
|
+
slug: string;
|
|
963
|
+
}, activeDomainScope?: string | null): string;
|
|
935
964
|
declare function generateTokenSlug(db: Database, domain: string, concept: string, question?: string | null): Promise<string>;
|
|
936
965
|
declare function listPersonalCards(db: Database, userId: string, options?: {
|
|
937
966
|
query?: string;
|
|
@@ -940,6 +969,7 @@ declare function listPersonalCards(db: Database, userId: string, options?: {
|
|
|
940
969
|
interface CurriculumCardInput {
|
|
941
970
|
question: string;
|
|
942
971
|
concept: string;
|
|
972
|
+
title?: string;
|
|
943
973
|
domain: string;
|
|
944
974
|
source_link?: string | null;
|
|
945
975
|
context?: string;
|
|
@@ -976,6 +1006,7 @@ interface FoundationProposalInput {
|
|
|
976
1006
|
question: string;
|
|
977
1007
|
concept: string;
|
|
978
1008
|
domain: string;
|
|
1009
|
+
title?: string;
|
|
979
1010
|
context?: string;
|
|
980
1011
|
bloom_level?: number;
|
|
981
1012
|
symbiosis_mode?: string | null;
|
|
@@ -996,6 +1027,7 @@ interface SourceProposalInput {
|
|
|
996
1027
|
question: string;
|
|
997
1028
|
concept: string;
|
|
998
1029
|
domain: string;
|
|
1030
|
+
title?: string;
|
|
999
1031
|
bloom_level: number;
|
|
1000
1032
|
symbiosis_mode: string;
|
|
1001
1033
|
excerpt: string;
|
|
@@ -1048,7 +1080,9 @@ interface EmbeddedTokenRow {
|
|
|
1048
1080
|
* vector derives from exactly this string — never the slug, which is an
|
|
1049
1081
|
* identifier, not meaning.
|
|
1050
1082
|
*/
|
|
1051
|
-
declare function embeddingContentForToken(t: Pick<Token, "concept" | "question" | "domain">
|
|
1083
|
+
declare function embeddingContentForToken(t: Pick<Token, "concept" | "question" | "domain"> & {
|
|
1084
|
+
title?: string | null;
|
|
1085
|
+
}): string;
|
|
1052
1086
|
declare function computeContentHash(text: string): string;
|
|
1053
1087
|
/**
|
|
1054
1088
|
* Encode a vector as a little-endian float32 BLOB. Builds a fresh buffer (no
|
|
@@ -1849,6 +1883,7 @@ interface ReviewQueueItem {
|
|
|
1849
1883
|
cardId: string;
|
|
1850
1884
|
tokenId: string;
|
|
1851
1885
|
slug: string;
|
|
1886
|
+
title: string;
|
|
1852
1887
|
concept: string;
|
|
1853
1888
|
domain: string;
|
|
1854
1889
|
bloomLevel: number;
|
|
@@ -1910,6 +1945,39 @@ declare function cosineSimilarity(a: Float32Array, b: Float32Array): number;
|
|
|
1910
1945
|
*/
|
|
1911
1946
|
declare function searchTokensHybrid(db: Database, query: string, opts?: HybridSearchOptions): Promise<HybridScoredToken[]>;
|
|
1912
1947
|
|
|
1948
|
+
/**
|
|
1949
|
+
* Foundation suggestions for tokens.
|
|
1950
|
+
* Suggests existing tokens that are semantically related as prerequisite candidates.
|
|
1951
|
+
*
|
|
1952
|
+
* This module is pure math + database queries — zero LLM dependencies, no HTTP.
|
|
1953
|
+
*/
|
|
1954
|
+
|
|
1955
|
+
interface FoundationSuggestion {
|
|
1956
|
+
token: Token;
|
|
1957
|
+
similarity: number;
|
|
1958
|
+
alreadyPrerequisite: boolean;
|
|
1959
|
+
wouldCreateCycle: boolean;
|
|
1960
|
+
/** Candidate's bloom_level is higher than the target's — unusual for a foundation. */
|
|
1961
|
+
bloomAboveTarget: boolean;
|
|
1962
|
+
}
|
|
1963
|
+
interface SuggestFoundationsOptions {
|
|
1964
|
+
queryEmbedding: ArrayLike<number>;
|
|
1965
|
+
/** Canonical embedding model id the stored vectors must match. */
|
|
1966
|
+
model: string;
|
|
1967
|
+
/** Set when the target token already exists (register-after / rating-1 flow). */
|
|
1968
|
+
targetTokenId?: string;
|
|
1969
|
+
/** Used for the bloomAboveTarget flag; defaults to 5 (nothing flagged). */
|
|
1970
|
+
targetBloomLevel?: BloomLevel$1;
|
|
1971
|
+
limit?: number;
|
|
1972
|
+
minSimilarity?: number;
|
|
1973
|
+
maxSimilarity?: number;
|
|
1974
|
+
}
|
|
1975
|
+
/**
|
|
1976
|
+
* Suggests existing tokens that are semantically related as prerequisite candidates.
|
|
1977
|
+
* Filters by similarity range and ranks descending by similarity.
|
|
1978
|
+
*/
|
|
1979
|
+
declare function suggestFoundations(db: Database, opts: SuggestFoundationsOptions): Promise<FoundationSuggestion[]>;
|
|
1980
|
+
|
|
1913
1981
|
/**
|
|
1914
1982
|
* Get the path to ZAM's internal package SKILL.md.
|
|
1915
1983
|
*/
|
|
@@ -2194,4 +2262,4 @@ declare function resolveAllBeliefPaths(db: Database): Promise<string[]>;
|
|
|
2194
2262
|
*/
|
|
2195
2263
|
declare function resolveAllGoalPaths(db: Database): Promise<string[]>;
|
|
2196
2264
|
|
|
2197
|
-
export { type ADOConfig, type ADOCredentials, type AgentSkill, type AnalysisResult, type ApplySessionSynthesisInput, type ApplySessionSynthesisResult, BUILT_IN_SENSITIVE_MATCHERS, type BloomLevel$1 as BloomLevel, type CaptureDecision, type CaptureDenialReason, type CaptureRequest, type Card, type CardDeletionImpact, type CardState$1 as CardState, type CascadeBlockResult, type CommandRecord, type CommandSequence, type ConfirmFoundationsResult, type ConnectionOptions, type CreateAgentSkillInput, type CreateGoalInput, type CreateReviewInput, type CreateSessionInput, type CreateTokenInput, type Credentials, type CurriculumCardInput, DEFAULT_OBSERVER_POLICY, DEFAULT_REVIEW_CONTEXT_MAX_CHARS, type Database, type DatabaseProvider, type DatabaseTargetInfo, type DatabaseValue, type DeleteCardResult, type DeleteTokenResult, type DiscoveryOptions, type DomainCompetence, type EmbeddedTokenRow, type EmbeddingCoverage, type EmbeddingStaleness, type EvaluateInput, type EvaluateResult, type ExecuteReviewActionInput, type ExecutionContext, type FSRSParameters, type FoundationProposalInput, type Goal, type GoalFrontmatter, type GoalStatus, type GoalSummary, HOMEBREW_CASK, type HybridScoredToken, type HybridSearchOptions, type ImportCurriculumResult, type ImportResult, type InstallChannel, type InstallConfig, type InstallMode, type InstallPlan, type InstallResult, type LocalLLMRunner, type LogStepInput, type MachineAiConfig, type MachineProviderRecord, type MachineRoleBinding, type MonitorEvent, type Neighborhood, type NeighborhoodToken, OBSERVER_POLICY_UNSET_HINT, OBSERVER_POLICY_VERSION, type ObservationRating, type ObserverConsent, type ObserverPolicy, type ObserverRetention, type ObserverScope, type ObserverSettingKey, type OllamaDetectionOptions, type PersonalCard, type PrepareSessionSynthesisInput, type Prerequisite, type PrerequisiteWithToken, type PromptInput, REVIEW_CONTEXT_CACHE_TTL_MS, type Rating, type RecallPrompt, type RemoteDatabaseOptions, type RepoPaths, type ResolvedCaptureTarget, type ResolvedReference, type ReviewActionResult, type ReviewActionType, type ReviewContext, type ReviewLog, type ReviewQueue, type ReviewQueueItem, type ReviewQueueOptions, type RunResult, SIDECAR_POLICY_FILE, SNAPSHOT_VERSION, type SchedulingCard, type Session, type SessionStep, type SessionSummary, type SessionSynthesisCandidate, type SessionSynthesisEvidence, type SessionSynthesisPreview, type SessionSynthesisRecord, type SidecarPrivacyPolicy, type SkillProposal, type SkillSource, type SnapshotManifest, type SourceProposalInput, type SplitProposalInput, type Statement, type SupportedLocale, type SymbiosisMode, type SynthesisConfidence, type SystemProfile, type Token, type TokenDeleteImpact, type TokenEmbedding, type TokenNeedingEmbedding, type TokenPattern, type TranslationKey, type TursoCredentials, UI_OBSERVATION_PROTOCOL_VERSION, type UiActionType, type UiApplicationContext, type UiCandidateToken, type UiEvidenceRef, type UiEvidenceType, type UiObservationKind, type UiObservationReport, type UiObservedAction, type UnblockResult, type UpdateActionKind, type UpdateCardInput, type UpdateDecision, type UpdateStep, type UpdateStepKind, type UpdateTokenInput, type UserSetting, type UserStats, WINGET_PACKAGE_ID, type WorkItem, type WorkspaceConfig, type WorkspaceKind, type WorkspaceSourceControl, addPrerequisite, analyzeObservation, appendUiObservationReport, applySessionSynthesis, buildReviewQueue, buildUiSynthesisCandidates, cascadeBlock, clearADOCredentials, clearProviderApiKey, clearReviewContextCache, clearTursoCredentials, compareVersions, computeContentHash, confirmCardSplit, confirmFoundations, confirmSourceImport, cosineSimilarity, createAgentSkill, createFSRS, createGoal, createToken, decidePostCapture, decidePreCapture, decideUpdate, decodeEmbedding, deleteCardForUser, deleteSetting, deleteToken, deprecateToken, detectSyncProvider, detectSystemLocale, discoverSkills, distributeGlobalSkills, embeddingContentForToken, encodeEmbedding, endSession, ensureCard, ensureMonitorDir, ensureUiObserverDir, evaluateRating, executeReviewAction, exportSnapshot, extractTasks, extractTokenRefs, fetchActiveWorkItems, findTokens, generateBashHooks, generateBashUnhooks, generateConceptFreeCue, generatePowerShellHooks, generatePowerShellUnhooks, generatePrompt, generateTokenSlug, generateZshHooks, generateZshUnhooks, getADOCredentials, getActiveWorkspace, getActiveWorkspaceId, getAgentSkill, getAllSettings, getAllSettingsDetailed, getBlockedCards, getCard, getCardById, getCardDeletionImpact, getConfiguredWorkspaces, getDatabaseTargetInfo, getDefaultDbPath, getDependents, getDomainCompetence, getDueCards, getEmbeddingCoverage, getGoal, getGoalTree, getInstallChannel, getInstallMode, getMachineAiConfig, getMonitorDir, getMonitorLogStats, getMonitorPath, getPackageSkillPath, getPrerequisites, getProviderApiKey, getRepoPaths, getReviewsForCard, getReviewsForUser, getSessionSummary, getSessionSynthesisRecords, getSetting, getSystemProfile, getTokenById, getTokenBySlug, getTokenDeleteImpact, getTokenEmbedding, getTokenNeighborhood, getTursoCredentials, getUiObservationPath, getUiObserverDir, getUserStats, hasCommand, importCurriculumCards, importSnapshot, injectShellHooks, installFastFlowLM, installOllama, installOpenCode, interleave, isObserverPolicyConfigured, isOllamaInstalled, isUiObservationReport, listAgentSkills, listEmbeddedTokens, listGoals, listPersonalCards, listProviderApiKeyRefs, listTokens, listTokensNeedingEmbedding, loadADOConfig, loadCredentials, loadInstallConfig, logReview, logStep, matchBuiltInSensitive, matchDenylist, matchesFilePath, monitorLogExists, normalizeLocale, normalizePath, openDatabase, openDatabaseWithSync, openRemoteDatabase, pairCommands, parseGoalFile, parseMonitorLog, parseObserverList, parseObserverPolicy, parseSnapshot, parseUiObservationLog, planOpenCodeInstall, planUpdate, prepareLocalModel, prepareSessionSynthesis, readMonitorLog, readUiObservationLog, removeConfiguredWorkspace, resolveAllBeliefPaths, resolveAllGoalPaths, resolveObserverPolicy, resolveOllamaCommand, resolveReference, resolveRepoPath, resolveReviewContext, saveConfiguredWorkspaces, saveCredentials, saveInstallConfig, saveMachineAiConfig, searchTokensHybrid, serializeGoal, setADOCredentials, setActiveWorkspaceId, setInstallChannel, setInstallMode, setProviderApiKey, setSetting, setTursoCredentials, slugify, startSession, syncObserverSidecarPolicy, t, toSidecarPrivacyPolicy, uiObservationLogExists, uiObservationTimeSpan, unblockReady, updateCard, updateGoalStatus, updateToken, upsertConfiguredWorkspace, upsertTokenEmbedding, verifySnapshot, wouldCreateCycle, writeMonitorEvent };
|
|
2265
|
+
export { type ADOConfig, type ADOCredentials, type AgentSkill, type AnalysisResult, type ApplySessionSynthesisInput, type ApplySessionSynthesisResult, BUILT_IN_SENSITIVE_MATCHERS, type BloomLevel$1 as BloomLevel, type CaptureDecision, type CaptureDenialReason, type CaptureRequest, type Card, type CardDeletionImpact, type CardState$1 as CardState, type CascadeBlockResult, type CommandRecord, type CommandSequence, type ConfirmFoundationsResult, type ConnectionOptions, type CreateAgentSkillInput, type CreateGoalInput, type CreateReviewInput, type CreateSessionInput, type CreateTokenInput, type Credentials, type CurriculumCardInput, DEFAULT_OBSERVER_POLICY, DEFAULT_REVIEW_CONTEXT_MAX_CHARS, type Database, type DatabaseProvider, type DatabaseTargetInfo, type DatabaseValue, type DeleteCardResult, type DeleteTokenResult, type DiscoveryOptions, type DomainCompetence, type EmbeddedTokenRow, type EmbeddingCoverage, type EmbeddingStaleness, type EvaluateInput, type EvaluateResult, type ExecuteReviewActionInput, type ExecutionContext, type FSRSParameters, type FoundationProposalInput, type FoundationSuggestion, type Goal, type GoalFrontmatter, type GoalStatus, type GoalSummary, HOMEBREW_CASK, type HybridScoredToken, type HybridSearchOptions, type ImportCurriculumResult, type ImportResult, type InstallChannel, type InstallConfig, type InstallMode, type InstallPlan, type InstallResult, type ListTokensOptions, type LocalLLMRunner, type LogStepInput, type MachineAiConfig, type MachineProviderRecord, type MachineRoleBinding, type MonitorEvent, type Neighborhood, type NeighborhoodToken, OBSERVER_POLICY_UNSET_HINT, OBSERVER_POLICY_VERSION, type ObservationRating, type ObserverConsent, type ObserverPolicy, type ObserverRetention, type ObserverScope, type ObserverSettingKey, type OllamaDetectionOptions, type PersonalCard, type PrepareSessionSynthesisInput, type Prerequisite, type PrerequisiteWithToken, type PromptInput, REVIEW_CONTEXT_CACHE_TTL_MS, type Rating, type RecallPrompt, type RemoteDatabaseOptions, type RepoPaths, type ResolvedCaptureTarget, type ResolvedReference, type ReviewActionResult, type ReviewActionType, type ReviewContext, type ReviewLog, type ReviewQueue, type ReviewQueueItem, type ReviewQueueOptions, type RunResult, SIDECAR_POLICY_FILE, SNAPSHOT_VERSION, type SchedulingCard, type Session, type SessionStep, type SessionSummary, type SessionSynthesisCandidate, type SessionSynthesisEvidence, type SessionSynthesisPreview, type SessionSynthesisRecord, type SidecarPrivacyPolicy, type SkillProposal, type SkillSource, type SnapshotManifest, type SourceProposalInput, type SplitProposalInput, type Statement, type SuggestFoundationsOptions, type SupportedLocale, type SymbiosisMode, type SynthesisConfidence, type SystemProfile, type Token, type TokenDeleteImpact, type TokenEmbedding, type TokenNeedingEmbedding, type TokenPattern, type TranslationKey, type TursoCredentials, UI_OBSERVATION_PROTOCOL_VERSION, type UiActionType, type UiApplicationContext, type UiCandidateToken, type UiEvidenceRef, type UiEvidenceType, type UiObservationKind, type UiObservationReport, type UiObservedAction, type UnblockResult, type UpdateActionKind, type UpdateCardInput, type UpdateDecision, type UpdateStep, type UpdateStepKind, type UpdateTokenInput, type UserSetting, type UserStats, WINGET_PACKAGE_ID, type WorkItem, type WorkspaceConfig, type WorkspaceKind, type WorkspaceSourceControl, addPrerequisite, analyzeObservation, appendUiObservationReport, applySessionSynthesis, buildAncestorMap, buildReviewQueue, buildUiSynthesisCandidates, cascadeBlock, clearADOCredentials, clearProviderApiKey, clearReviewContextCache, clearTursoCredentials, compareVersions, computeContentHash, confirmCardSplit, confirmFoundations, confirmSourceImport, cosineSimilarity, createAgentSkill, createFSRS, createGoal, createToken, decidePostCapture, decidePreCapture, decideUpdate, decodeEmbedding, deleteCardForUser, deleteSetting, deleteToken, deprecateToken, detectSyncProvider, detectSystemLocale, discoverSkills, distributeGlobalSkills, embeddingContentForToken, encodeEmbedding, endSession, ensureCard, ensureMonitorDir, ensureUiObserverDir, evaluateRating, executeReviewAction, exportSnapshot, extractTasks, extractTokenRefs, fetchActiveWorkItems, findTokens, generateBashHooks, generateBashUnhooks, generateConceptFreeCue, generatePowerShellHooks, generatePowerShellUnhooks, generatePrompt, generateTokenSlug, generateZshHooks, generateZshUnhooks, getADOCredentials, getActiveWorkspace, getActiveWorkspaceId, getAgentSkill, getAllSettings, getAllSettingsDetailed, getBlockedCards, getCard, getCardById, getCardDeletionImpact, getConfiguredWorkspaces, getDatabaseTargetInfo, getDefaultDbPath, getDependents, getDisplayTitle, getDomainCompetence, getDueCards, getEmbeddingCoverage, getGoal, getGoalTree, getInstallChannel, getInstallMode, getMachineAiConfig, getMonitorDir, getMonitorLogStats, getMonitorPath, getPackageSkillPath, getPrerequisites, getProviderApiKey, getRepoPaths, getReviewsForCard, getReviewsForUser, getSessionSummary, getSessionSynthesisRecords, getSetting, getShortSlug, getSystemProfile, getTokenById, getTokenBySlug, getTokenDeleteImpact, getTokenEmbedding, getTokenNeighborhood, getTursoCredentials, getUiObservationPath, getUiObserverDir, getUserStats, hasCommand, importCurriculumCards, importSnapshot, injectShellHooks, installFastFlowLM, installOllama, installOpenCode, interleave, isObserverPolicyConfigured, isOllamaInstalled, isUiObservationReport, listAgentSkills, listEmbeddedTokens, listGoals, listPersonalCards, listProviderApiKeyRefs, listTokens, listTokensNeedingEmbedding, loadADOConfig, loadCredentials, loadInstallConfig, logReview, logStep, matchBuiltInSensitive, matchDenylist, matchesFilePath, monitorLogExists, normalizeLocale, normalizePath, openDatabase, openDatabaseWithSync, openRemoteDatabase, pairCommands, parseGoalFile, parseMonitorLog, parseObserverList, parseObserverPolicy, parseSnapshot, parseUiObservationLog, planOpenCodeInstall, planUpdate, prepareLocalModel, prepareSessionSynthesis, readMonitorLog, readUiObservationLog, removeConfiguredWorkspace, resolveAllBeliefPaths, resolveAllGoalPaths, resolveObserverPolicy, resolveOllamaCommand, resolveReference, resolveRepoPath, resolveReviewContext, saveConfiguredWorkspaces, saveCredentials, saveInstallConfig, saveMachineAiConfig, searchTokensHybrid, serializeGoal, setADOCredentials, setActiveWorkspaceId, setInstallChannel, setInstallMode, setProviderApiKey, setSetting, setTursoCredentials, slugify, startSession, suggestFoundations, syncObserverSidecarPolicy, t, toSidecarPrivacyPolicy, uiObservationLogExists, uiObservationTimeSpan, unblockReady, updateCard, updateGoalStatus, updateToken, upsertConfiguredWorkspace, upsertTokenEmbedding, verifySnapshot, wouldCreateCycle, writeMonitorEvent };
|
package/dist/index.js
CHANGED
|
@@ -530,6 +530,7 @@ var SCHEMA = `
|
|
|
530
530
|
CREATE TABLE IF NOT EXISTS tokens (
|
|
531
531
|
id TEXT PRIMARY KEY,
|
|
532
532
|
slug TEXT UNIQUE NOT NULL,
|
|
533
|
+
title TEXT NOT NULL DEFAULT '',
|
|
533
534
|
concept TEXT NOT NULL,
|
|
534
535
|
domain TEXT NOT NULL DEFAULT '',
|
|
535
536
|
bloom_level INTEGER NOT NULL DEFAULT 1 CHECK (bloom_level BETWEEN 1 AND 5),
|
|
@@ -678,6 +679,8 @@ CREATE INDEX IF NOT EXISTS idx_cards_token_user ON cards(token_id, user_id);
|
|
|
678
679
|
CREATE INDEX IF NOT EXISTS idx_review_logs_card ON review_logs(card_id);
|
|
679
680
|
CREATE INDEX IF NOT EXISTS idx_review_logs_user ON review_logs(user_id, reviewed_at);
|
|
680
681
|
CREATE INDEX IF NOT EXISTS idx_session_steps_session ON session_steps(session_id);
|
|
682
|
+
CREATE INDEX IF NOT EXISTS idx_tokens_title ON tokens(title);
|
|
683
|
+
CREATE INDEX IF NOT EXISTS idx_tokens_domain ON tokens(domain);
|
|
681
684
|
`;
|
|
682
685
|
|
|
683
686
|
// src/kernel/db/sync-adapter.ts
|
|
@@ -1011,6 +1014,15 @@ async function runMigrations(db) {
|
|
|
1011
1014
|
embedded_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1012
1015
|
)
|
|
1013
1016
|
`);
|
|
1017
|
+
if (!tokenCols.some((c) => c.name === "title")) {
|
|
1018
|
+
await db.exec(
|
|
1019
|
+
`ALTER TABLE tokens ADD COLUMN title TEXT NOT NULL DEFAULT ''`
|
|
1020
|
+
);
|
|
1021
|
+
}
|
|
1022
|
+
await db.exec(`CREATE INDEX IF NOT EXISTS idx_tokens_title ON tokens(title)`);
|
|
1023
|
+
await db.exec(
|
|
1024
|
+
`CREATE INDEX IF NOT EXISTS idx_tokens_domain ON tokens(domain)`
|
|
1025
|
+
);
|
|
1014
1026
|
}
|
|
1015
1027
|
|
|
1016
1028
|
// src/kernel/db/snapshot.ts
|
|
@@ -1512,12 +1524,14 @@ async function createToken(db, input) {
|
|
|
1512
1524
|
if (bloom < 1 || bloom > 5) {
|
|
1513
1525
|
throw new Error(`bloom_level must be between 1 and 5, got ${bloom}`);
|
|
1514
1526
|
}
|
|
1527
|
+
const title = input.title ?? "";
|
|
1515
1528
|
await db.prepare(`
|
|
1516
|
-
INSERT INTO tokens (id, slug, concept, domain, bloom_level, context, symbiosis_mode, source_link, question, provider, topic_id, created_at, updated_at)
|
|
1517
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1529
|
+
INSERT INTO tokens (id, slug, title, concept, domain, bloom_level, context, symbiosis_mode, source_link, question, provider, topic_id, created_at, updated_at)
|
|
1530
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1518
1531
|
`).run(
|
|
1519
1532
|
id,
|
|
1520
1533
|
input.slug,
|
|
1534
|
+
title,
|
|
1521
1535
|
input.concept,
|
|
1522
1536
|
input.domain ?? "",
|
|
1523
1537
|
bloom,
|
|
@@ -1560,6 +1574,10 @@ async function updateToken(db, slug, updates) {
|
|
|
1560
1574
|
}
|
|
1561
1575
|
const fields = [];
|
|
1562
1576
|
const values = [];
|
|
1577
|
+
if (updates.title !== void 0) {
|
|
1578
|
+
fields.push("title = ?");
|
|
1579
|
+
values.push(updates.title ?? "");
|
|
1580
|
+
}
|
|
1563
1581
|
if (updates.concept !== void 0) {
|
|
1564
1582
|
fields.push("concept = ?");
|
|
1565
1583
|
values.push(updates.concept);
|
|
@@ -1665,13 +1683,14 @@ async function deleteToken(db, slug) {
|
|
|
1665
1683
|
await db.transaction(async (tx) => {
|
|
1666
1684
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1667
1685
|
const skillRows = await tx.prepare("SELECT id, token_slugs FROM agent_skills").all();
|
|
1686
|
+
const skillUpdateStmt = tx.prepare(
|
|
1687
|
+
"UPDATE agent_skills SET token_slugs = ?, updated_at = ? WHERE id = ?"
|
|
1688
|
+
);
|
|
1668
1689
|
for (const row of skillRows) {
|
|
1669
1690
|
const tokenSlugs = JSON.parse(row.token_slugs);
|
|
1670
1691
|
const filtered = tokenSlugs.filter((tokenSlug) => tokenSlug !== slug);
|
|
1671
1692
|
if (filtered.length !== tokenSlugs.length) {
|
|
1672
|
-
await
|
|
1673
|
-
"UPDATE agent_skills SET token_slugs = ?, updated_at = ? WHERE id = ?"
|
|
1674
|
-
).run(JSON.stringify(filtered), now, row.id);
|
|
1693
|
+
await skillUpdateStmt.run(JSON.stringify(filtered), now, row.id);
|
|
1675
1694
|
}
|
|
1676
1695
|
}
|
|
1677
1696
|
await tx.prepare("DELETE FROM tokens WHERE id = ?").run(token.id);
|
|
@@ -1685,10 +1704,16 @@ async function findTokens(db, query) {
|
|
|
1685
1704
|
const shortTerms = searchTokens.filter((t2) => t2.length <= 2);
|
|
1686
1705
|
const longTerms = searchTokens.filter((t2) => t2.length > 2);
|
|
1687
1706
|
const scoreMap = /* @__PURE__ */ new Map();
|
|
1688
|
-
const likeSQL = `SELECT * FROM tokens WHERE deprecated_at IS NULL AND (lower(slug) LIKE ? OR lower(concept) LIKE ? OR lower(domain) LIKE ?)`;
|
|
1707
|
+
const likeSQL = `SELECT * FROM tokens WHERE deprecated_at IS NULL AND (lower(slug) LIKE ? OR lower(title) LIKE ? OR lower(concept) LIKE ? OR lower(domain) LIKE ?)`;
|
|
1708
|
+
const likeStmt = db.prepare(likeSQL);
|
|
1689
1709
|
for (const term of longTerms) {
|
|
1690
1710
|
const pattern = `%${term}%`;
|
|
1691
|
-
const rows = await
|
|
1711
|
+
const rows = await likeStmt.all(
|
|
1712
|
+
pattern,
|
|
1713
|
+
pattern,
|
|
1714
|
+
pattern,
|
|
1715
|
+
pattern
|
|
1716
|
+
);
|
|
1692
1717
|
for (const row of rows) {
|
|
1693
1718
|
const entry = scoreMap.get(row.id);
|
|
1694
1719
|
if (entry) {
|
|
@@ -1701,7 +1726,7 @@ async function findTokens(db, query) {
|
|
|
1701
1726
|
if (shortTerms.length > 0 || longTerms.length === 0) {
|
|
1702
1727
|
const allTokens = await db.prepare("SELECT * FROM tokens WHERE deprecated_at IS NULL").all();
|
|
1703
1728
|
for (const token of allTokens) {
|
|
1704
|
-
const words = `${token.slug} ${token.concept} ${token.domain}`.toLowerCase().split(/[\s,.\-_/\\:;!?()[\]{}]+/).filter(Boolean);
|
|
1729
|
+
const words = `${token.slug} ${token.title} ${token.concept} ${token.domain}`.toLowerCase().split(/[\s,.\-_/\\:;!?()[\]{}]+/).filter(Boolean);
|
|
1705
1730
|
let matchCount = 0;
|
|
1706
1731
|
for (const term of shortTerms.length > 0 ? shortTerms : searchTokens) {
|
|
1707
1732
|
for (const w of words) {
|
|
@@ -1735,6 +1760,11 @@ async function listTokens(db, options) {
|
|
|
1735
1760
|
tokens = await db.prepare(
|
|
1736
1761
|
"SELECT * FROM tokens WHERE domain = ? AND deprecated_at IS NULL ORDER BY bloom_level, slug"
|
|
1737
1762
|
).all(options.domain);
|
|
1763
|
+
} else if (options?.domainPrefix) {
|
|
1764
|
+
const prefix = options.domainPrefix;
|
|
1765
|
+
tokens = await db.prepare(
|
|
1766
|
+
`SELECT * FROM tokens WHERE (domain = ? OR domain LIKE ?) AND deprecated_at IS NULL ORDER BY bloom_level, slug`
|
|
1767
|
+
).all(prefix, `${prefix}/%`);
|
|
1738
1768
|
} else {
|
|
1739
1769
|
tokens = await db.prepare(
|
|
1740
1770
|
"SELECT * FROM tokens WHERE deprecated_at IS NULL ORDER BY bloom_level, domain, slug"
|
|
@@ -1746,7 +1776,20 @@ async function listTokens(db, options) {
|
|
|
1746
1776
|
return tokens;
|
|
1747
1777
|
}
|
|
1748
1778
|
function slugify(text) {
|
|
1749
|
-
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
|
|
1779
|
+
return text.toLowerCase().replace(/ä/g, "ae").replace(/ö/g, "oe").replace(/ü/g, "ue").replace(/ß/g, "ss").replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
|
|
1780
|
+
}
|
|
1781
|
+
function getShortSlug(slug, domainPrefix) {
|
|
1782
|
+
if (domainPrefix) {
|
|
1783
|
+
const folded = domainPrefix.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
1784
|
+
if (folded && slug.startsWith(`${folded}-`)) {
|
|
1785
|
+
return slug.substring(folded.length + 1);
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
return slug;
|
|
1789
|
+
}
|
|
1790
|
+
function getDisplayTitle(t2, activeDomainScope) {
|
|
1791
|
+
if (t2.title?.trim()) return t2.title.trim();
|
|
1792
|
+
return getShortSlug(t2.slug, activeDomainScope);
|
|
1750
1793
|
}
|
|
1751
1794
|
async function generateTokenSlug(db, domain, concept, question) {
|
|
1752
1795
|
const baseText = question && question.trim().length > 0 ? question : concept;
|
|
@@ -1776,6 +1819,7 @@ async function listPersonalCards(db, userId, options) {
|
|
|
1776
1819
|
SELECT
|
|
1777
1820
|
t.id AS tokenId,
|
|
1778
1821
|
t.slug,
|
|
1822
|
+
t.title,
|
|
1779
1823
|
t.concept,
|
|
1780
1824
|
t.domain,
|
|
1781
1825
|
t.bloom_level AS bloomLevel,
|
|
@@ -1877,6 +1921,7 @@ async function importCurriculumCards(db, userId, cards) {
|
|
|
1877
1921
|
);
|
|
1878
1922
|
token = await createToken(tx, {
|
|
1879
1923
|
slug: finalSlug,
|
|
1924
|
+
title: card.title,
|
|
1880
1925
|
concept: card.concept,
|
|
1881
1926
|
domain: card.domain,
|
|
1882
1927
|
bloom_level: bloom,
|
|
@@ -1994,23 +2039,28 @@ async function confirmCardSplit(db, userId, originalSlug, action, originalQuesti
|
|
|
1994
2039
|
(/* @__PURE__ */ new Date()).toISOString(),
|
|
1995
2040
|
originalToken.id
|
|
1996
2041
|
);
|
|
2042
|
+
const insertPrereqStmt = tx.prepare(
|
|
2043
|
+
"INSERT OR IGNORE INTO prerequisites (token_id, requires_id) VALUES (?, ?)"
|
|
2044
|
+
);
|
|
1997
2045
|
for (const propToken of proposalTokens) {
|
|
1998
|
-
await
|
|
1999
|
-
"INSERT OR IGNORE INTO prerequisites (token_id, requires_id) VALUES (?, ?)"
|
|
2000
|
-
).run(originalToken.id, propToken.id);
|
|
2046
|
+
await insertPrereqStmt.run(originalToken.id, propToken.id);
|
|
2001
2047
|
}
|
|
2002
2048
|
await tx.prepare(
|
|
2003
2049
|
"UPDATE cards SET blocked = 1 WHERE token_id = ? AND user_id = ?"
|
|
2004
2050
|
).run(originalToken.id, userId);
|
|
2051
|
+
const checkPrereqsStmt = tx.prepare(
|
|
2052
|
+
"SELECT COUNT(*) as n FROM prerequisites WHERE token_id = ?"
|
|
2053
|
+
);
|
|
2054
|
+
const unblockCardStmt = tx.prepare(
|
|
2055
|
+
"UPDATE cards SET blocked = 0, due_at = ? WHERE id = ?"
|
|
2056
|
+
);
|
|
2005
2057
|
for (const propToken of proposalTokens) {
|
|
2006
2058
|
const card = await ensureCard(tx, propToken.id, userId);
|
|
2007
2059
|
if (card.blocked === 1) {
|
|
2008
|
-
const prereqOfPrereq = await
|
|
2009
|
-
"SELECT COUNT(*) as n FROM prerequisites WHERE token_id = ?"
|
|
2010
|
-
).get(propToken.id);
|
|
2060
|
+
const prereqOfPrereq = await checkPrereqsStmt.get(propToken.id);
|
|
2011
2061
|
if (prereqOfPrereq.n === 0) {
|
|
2012
2062
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2013
|
-
await
|
|
2063
|
+
await unblockCardStmt.run(now, card.id);
|
|
2014
2064
|
}
|
|
2015
2065
|
}
|
|
2016
2066
|
}
|
|
@@ -2081,6 +2131,7 @@ async function confirmFoundations(db, userId, originalSlug, proposals) {
|
|
|
2081
2131
|
);
|
|
2082
2132
|
token = await createToken(tx, {
|
|
2083
2133
|
slug: finalSlug,
|
|
2134
|
+
title: card.title,
|
|
2084
2135
|
concept: card.concept,
|
|
2085
2136
|
domain: card.domain,
|
|
2086
2137
|
bloom_level: bloom,
|
|
@@ -2147,6 +2198,7 @@ async function confirmSourceImport(db, userId, sourceId, proposals) {
|
|
|
2147
2198
|
}
|
|
2148
2199
|
token = await createToken(tx, {
|
|
2149
2200
|
slug: finalSlug,
|
|
2201
|
+
title: card.title,
|
|
2150
2202
|
concept: card.concept,
|
|
2151
2203
|
domain: card.domain,
|
|
2152
2204
|
bloom_level: bloom,
|
|
@@ -2215,9 +2267,9 @@ async function buildAncestorMap(db) {
|
|
|
2215
2267
|
}
|
|
2216
2268
|
return map;
|
|
2217
2269
|
}
|
|
2218
|
-
async function wouldCreateCycle(db, tokenId, requiresId) {
|
|
2270
|
+
async function wouldCreateCycle(db, tokenId, requiresId, ancestors) {
|
|
2219
2271
|
if (tokenId === requiresId) return true;
|
|
2220
|
-
const
|
|
2272
|
+
const map = ancestors ?? await buildAncestorMap(db);
|
|
2221
2273
|
const visited = /* @__PURE__ */ new Set();
|
|
2222
2274
|
const queue = [requiresId];
|
|
2223
2275
|
while (queue.length > 0) {
|
|
@@ -2225,7 +2277,7 @@ async function wouldCreateCycle(db, tokenId, requiresId) {
|
|
|
2225
2277
|
if (current === tokenId) return true;
|
|
2226
2278
|
if (visited.has(current)) continue;
|
|
2227
2279
|
visited.add(current);
|
|
2228
|
-
const parents =
|
|
2280
|
+
const parents = map.get(current);
|
|
2229
2281
|
if (parents) {
|
|
2230
2282
|
for (const parent of parents) {
|
|
2231
2283
|
if (!visited.has(parent)) queue.push(parent);
|
|
@@ -2249,7 +2301,7 @@ async function addPrerequisite(db, tokenId, requiresId) {
|
|
|
2249
2301
|
}
|
|
2250
2302
|
async function getPrerequisites(db, tokenId) {
|
|
2251
2303
|
return await db.prepare(
|
|
2252
|
-
`SELECT p.token_id, p.requires_id, t.slug, t.concept, t.domain, t.bloom_level
|
|
2304
|
+
`SELECT p.token_id, p.requires_id, t.slug, t.title, t.concept, t.domain, t.bloom_level
|
|
2253
2305
|
FROM prerequisites p
|
|
2254
2306
|
JOIN tokens t ON t.id = p.requires_id
|
|
2255
2307
|
WHERE p.token_id = ?`
|
|
@@ -2257,7 +2309,7 @@ async function getPrerequisites(db, tokenId) {
|
|
|
2257
2309
|
}
|
|
2258
2310
|
async function getDependents(db, tokenId) {
|
|
2259
2311
|
return await db.prepare(
|
|
2260
|
-
`SELECT p.token_id, p.requires_id, t.slug, t.concept, t.domain, t.bloom_level
|
|
2312
|
+
`SELECT p.token_id, p.requires_id, t.slug, t.title, t.concept, t.domain, t.bloom_level
|
|
2261
2313
|
FROM prerequisites p
|
|
2262
2314
|
JOIN tokens t ON t.id = p.token_id
|
|
2263
2315
|
WHERE p.requires_id = ?`
|
|
@@ -2288,6 +2340,7 @@ async function getTokenNeighborhood(db, tokenId, userId) {
|
|
|
2288
2340
|
const toNode = (t2, card) => ({
|
|
2289
2341
|
id: t2.id,
|
|
2290
2342
|
slug: t2.slug,
|
|
2343
|
+
title: t2.title ?? t2.slug,
|
|
2291
2344
|
concept: t2.concept,
|
|
2292
2345
|
domain: t2.domain,
|
|
2293
2346
|
bloom_level: t2.bloom_level,
|
|
@@ -2307,6 +2360,7 @@ async function getTokenNeighborhood(db, tokenId, userId) {
|
|
|
2307
2360
|
{
|
|
2308
2361
|
id: p.requires_id,
|
|
2309
2362
|
slug: p.slug,
|
|
2363
|
+
title: p.title,
|
|
2310
2364
|
concept: p.concept,
|
|
2311
2365
|
domain: p.domain,
|
|
2312
2366
|
bloom_level: p.bloom_level
|
|
@@ -2319,6 +2373,7 @@ async function getTokenNeighborhood(db, tokenId, userId) {
|
|
|
2319
2373
|
{
|
|
2320
2374
|
id: d.token_id,
|
|
2321
2375
|
slug: d.slug,
|
|
2376
|
+
title: d.title,
|
|
2322
2377
|
concept: d.concept,
|
|
2323
2378
|
domain: d.domain,
|
|
2324
2379
|
bloom_level: d.bloom_level
|
|
@@ -2478,7 +2533,8 @@ import { createHash as createHash2 } from "crypto";
|
|
|
2478
2533
|
function embeddingContentForToken(t2) {
|
|
2479
2534
|
return `${t2.concept}
|
|
2480
2535
|
${t2.question ?? ""}
|
|
2481
|
-
${t2.domain}
|
|
2536
|
+
${t2.domain}
|
|
2537
|
+
${t2.title ?? ""}`;
|
|
2482
2538
|
}
|
|
2483
2539
|
function computeContentHash(text) {
|
|
2484
2540
|
return createHash2("sha256").update(text, "utf8").digest("hex");
|
|
@@ -4662,6 +4718,7 @@ async function buildReviewQueue(db, options) {
|
|
|
4662
4718
|
c.id AS card_id,
|
|
4663
4719
|
c.token_id AS token_id,
|
|
4664
4720
|
t.slug AS slug,
|
|
4721
|
+
t.title AS title,
|
|
4665
4722
|
t.concept AS concept,
|
|
4666
4723
|
t.domain AS domain,
|
|
4667
4724
|
t.bloom_level AS bloom_level,
|
|
@@ -4683,6 +4740,7 @@ async function buildReviewQueue(db, options) {
|
|
|
4683
4740
|
c.id AS card_id,
|
|
4684
4741
|
c.token_id AS token_id,
|
|
4685
4742
|
t.slug AS slug,
|
|
4743
|
+
t.title AS title,
|
|
4686
4744
|
t.concept AS concept,
|
|
4687
4745
|
t.domain AS domain,
|
|
4688
4746
|
t.bloom_level AS bloom_level,
|
|
@@ -4742,6 +4800,7 @@ function rowToItem(row) {
|
|
|
4742
4800
|
cardId: row.card_id,
|
|
4743
4801
|
tokenId: row.token_id,
|
|
4744
4802
|
slug: row.slug,
|
|
4803
|
+
title: getDisplayTitle(row),
|
|
4745
4804
|
concept: row.concept,
|
|
4746
4805
|
domain: row.domain,
|
|
4747
4806
|
bloomLevel: row.bloom_level,
|
|
@@ -4850,6 +4909,71 @@ async function searchTokensHybrid(db, query, opts) {
|
|
|
4850
4909
|
return results.slice(0, limit);
|
|
4851
4910
|
}
|
|
4852
4911
|
|
|
4912
|
+
// src/kernel/search/suggestions.ts
|
|
4913
|
+
async function suggestFoundations(db, opts) {
|
|
4914
|
+
const minSimilarity = opts.minSimilarity ?? 0.45;
|
|
4915
|
+
const maxSimilarity = opts.maxSimilarity ?? 0.85;
|
|
4916
|
+
const limit = opts.limit ?? 5;
|
|
4917
|
+
const targetBloomLevel = opts.targetBloomLevel ?? 5;
|
|
4918
|
+
if (minSimilarity >= maxSimilarity) {
|
|
4919
|
+
return [];
|
|
4920
|
+
}
|
|
4921
|
+
const embedded = await listEmbeddedTokens(db, opts.model);
|
|
4922
|
+
if (embedded.length === 0) {
|
|
4923
|
+
return [];
|
|
4924
|
+
}
|
|
4925
|
+
const queryVec = Float32Array.from(opts.queryEmbedding);
|
|
4926
|
+
const candidates = [];
|
|
4927
|
+
for (const row of embedded) {
|
|
4928
|
+
if (opts.targetTokenId && row.token.id === opts.targetTokenId) {
|
|
4929
|
+
continue;
|
|
4930
|
+
}
|
|
4931
|
+
const similarity = cosineSimilarity(queryVec, row.embedding);
|
|
4932
|
+
if (similarity >= minSimilarity && similarity < maxSimilarity) {
|
|
4933
|
+
candidates.push({ token: row.token, similarity });
|
|
4934
|
+
}
|
|
4935
|
+
}
|
|
4936
|
+
candidates.sort((a, b) => {
|
|
4937
|
+
if (Math.abs(a.similarity - b.similarity) > 1e-9) {
|
|
4938
|
+
return b.similarity - a.similarity;
|
|
4939
|
+
}
|
|
4940
|
+
return a.token.slug.localeCompare(b.token.slug);
|
|
4941
|
+
});
|
|
4942
|
+
const topCandidates = candidates.slice(0, limit);
|
|
4943
|
+
const prereqIds = /* @__PURE__ */ new Set();
|
|
4944
|
+
let ancestors;
|
|
4945
|
+
if (opts.targetTokenId) {
|
|
4946
|
+
const prereqs = await getPrerequisites(db, opts.targetTokenId);
|
|
4947
|
+
for (const p of prereqs) {
|
|
4948
|
+
prereqIds.add(p.requires_id);
|
|
4949
|
+
}
|
|
4950
|
+
ancestors = await buildAncestorMap(db);
|
|
4951
|
+
}
|
|
4952
|
+
const results = [];
|
|
4953
|
+
for (const cand of topCandidates) {
|
|
4954
|
+
let alreadyPrerequisite = false;
|
|
4955
|
+
let wouldCreateCycleFlag = false;
|
|
4956
|
+
const bloomAboveTarget = cand.token.bloom_level > targetBloomLevel;
|
|
4957
|
+
if (opts.targetTokenId) {
|
|
4958
|
+
alreadyPrerequisite = prereqIds.has(cand.token.id);
|
|
4959
|
+
wouldCreateCycleFlag = await wouldCreateCycle(
|
|
4960
|
+
db,
|
|
4961
|
+
opts.targetTokenId,
|
|
4962
|
+
cand.token.id,
|
|
4963
|
+
ancestors
|
|
4964
|
+
);
|
|
4965
|
+
}
|
|
4966
|
+
results.push({
|
|
4967
|
+
token: cand.token,
|
|
4968
|
+
similarity: cand.similarity,
|
|
4969
|
+
alreadyPrerequisite,
|
|
4970
|
+
wouldCreateCycle: wouldCreateCycleFlag,
|
|
4971
|
+
bloomAboveTarget
|
|
4972
|
+
});
|
|
4973
|
+
}
|
|
4974
|
+
return results;
|
|
4975
|
+
}
|
|
4976
|
+
|
|
4853
4977
|
// src/kernel/system/hooks.ts
|
|
4854
4978
|
import {
|
|
4855
4979
|
appendFileSync as appendFileSync3,
|
|
@@ -5874,6 +5998,7 @@ export {
|
|
|
5874
5998
|
analyzeObservation,
|
|
5875
5999
|
appendUiObservationReport,
|
|
5876
6000
|
applySessionSynthesis,
|
|
6001
|
+
buildAncestorMap,
|
|
5877
6002
|
buildReviewQueue,
|
|
5878
6003
|
buildUiSynthesisCandidates,
|
|
5879
6004
|
cascadeBlock,
|
|
@@ -5939,6 +6064,7 @@ export {
|
|
|
5939
6064
|
getDatabaseTargetInfo,
|
|
5940
6065
|
getDefaultDbPath,
|
|
5941
6066
|
getDependents,
|
|
6067
|
+
getDisplayTitle,
|
|
5942
6068
|
getDomainCompetence,
|
|
5943
6069
|
getDueCards,
|
|
5944
6070
|
getEmbeddingCoverage,
|
|
@@ -5959,6 +6085,7 @@ export {
|
|
|
5959
6085
|
getSessionSummary,
|
|
5960
6086
|
getSessionSynthesisRecords,
|
|
5961
6087
|
getSetting,
|
|
6088
|
+
getShortSlug,
|
|
5962
6089
|
getSystemProfile,
|
|
5963
6090
|
getTokenById,
|
|
5964
6091
|
getTokenBySlug,
|
|
@@ -6037,6 +6164,7 @@ export {
|
|
|
6037
6164
|
setTursoCredentials,
|
|
6038
6165
|
slugify,
|
|
6039
6166
|
startSession,
|
|
6167
|
+
suggestFoundations,
|
|
6040
6168
|
syncObserverSidecarPolicy,
|
|
6041
6169
|
t,
|
|
6042
6170
|
toSidecarPrivacyPolicy,
|