byterover-cli 3.6.1 → 3.7.1
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/README.md +1 -1
- package/dist/agent/core/interfaces/cipher-services.d.ts +7 -0
- package/dist/agent/infra/agent/cipher-agent.js +4 -2
- package/dist/agent/infra/agent/service-initializer.js +28 -14
- package/dist/agent/infra/sandbox/curate-service.d.ts +4 -2
- package/dist/agent/infra/sandbox/curate-service.js +6 -4
- package/dist/agent/infra/tools/implementations/curate-tool.d.ts +4 -2
- package/dist/agent/infra/tools/implementations/curate-tool.js +169 -25
- package/dist/agent/infra/tools/implementations/expand-knowledge-tool.d.ts +2 -0
- package/dist/agent/infra/tools/implementations/expand-knowledge-tool.js +1 -1
- package/dist/agent/infra/tools/implementations/memory-symbol-tree.d.ts +0 -8
- package/dist/agent/infra/tools/implementations/memory-symbol-tree.js +3 -15
- package/dist/agent/infra/tools/implementations/search-knowledge-service.d.ts +49 -4
- package/dist/agent/infra/tools/implementations/search-knowledge-service.js +123 -53
- package/dist/agent/infra/tools/implementations/search-knowledge-tool.d.ts +2 -0
- package/dist/agent/infra/tools/tool-provider.js +1 -0
- package/dist/agent/infra/tools/tool-registry.d.ts +7 -0
- package/dist/agent/infra/tools/tool-registry.js +13 -6
- package/dist/oclif/commands/dream.d.ts +4 -0
- package/dist/oclif/commands/dream.js +31 -13
- package/dist/server/constants.d.ts +1 -1
- package/dist/server/constants.js +20 -1
- package/dist/server/core/domain/knowledge/markdown-writer.d.ts +12 -42
- package/dist/server/core/domain/knowledge/markdown-writer.js +55 -96
- package/dist/server/core/domain/knowledge/memory-scoring.d.ts +18 -37
- package/dist/server/core/domain/knowledge/memory-scoring.js +36 -85
- package/dist/server/core/domain/knowledge/runtime-signals-schema.d.ts +59 -0
- package/dist/server/core/domain/knowledge/runtime-signals-schema.js +46 -0
- package/dist/server/core/domain/knowledge/sidecar-logging.d.ts +14 -0
- package/dist/server/core/domain/knowledge/sidecar-logging.js +18 -0
- package/dist/server/core/interfaces/storage/i-runtime-signal-store.d.ts +111 -0
- package/dist/server/core/interfaces/storage/i-runtime-signal-store.js +38 -0
- package/dist/server/infra/context-tree/file-context-tree-archive-service.d.ts +16 -6
- package/dist/server/infra/context-tree/file-context-tree-archive-service.js +91 -32
- package/dist/server/infra/context-tree/file-context-tree-manifest-service.d.ts +14 -0
- package/dist/server/infra/context-tree/file-context-tree-manifest-service.js +20 -7
- package/dist/server/infra/context-tree/runtime-signal-store.d.ts +46 -0
- package/dist/server/infra/context-tree/runtime-signal-store.js +118 -0
- package/dist/server/infra/daemon/agent-process.js +25 -4
- package/dist/server/infra/dream/operations/consolidate.d.ts +17 -0
- package/dist/server/infra/dream/operations/consolidate.js +40 -19
- package/dist/server/infra/dream/operations/prune.d.ts +18 -0
- package/dist/server/infra/dream/operations/prune.js +31 -20
- package/dist/server/infra/dream/operations/synthesize.d.ts +13 -0
- package/dist/server/infra/dream/operations/synthesize.js +15 -3
- package/dist/server/infra/executor/dream-executor.d.ts +8 -0
- package/dist/server/infra/executor/dream-executor.js +3 -0
- package/dist/server/templates/skill/SKILL.md +79 -22
- package/oclif.manifest.json +429 -429
- package/package.json +1 -1
|
@@ -46,14 +46,6 @@ function determineKind(segments) {
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
function extractMetadataFromScoring(scoring) {
|
|
50
|
-
return {
|
|
51
|
-
importance: scoring.importance ?? 50,
|
|
52
|
-
keywords: [],
|
|
53
|
-
maturity: scoring.maturity ?? 'draft',
|
|
54
|
-
tags: [],
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
49
|
/**
|
|
58
50
|
* Get or create a folder symbol (Domain/Topic/Subtopic) at the given path.
|
|
59
51
|
* Creates intermediate nodes as needed.
|
|
@@ -133,12 +125,8 @@ export function buildSymbolTree(documentMap, summaryMap) {
|
|
|
133
125
|
const segments = doc.path.split('/');
|
|
134
126
|
const folderPath = segments.slice(0, -1).join('/');
|
|
135
127
|
const folderNode = symbolMap.get(folderPath);
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
...folderNode.metadata,
|
|
139
|
-
...extractMetadataFromScoring(doc.scoring),
|
|
140
|
-
};
|
|
141
|
-
}
|
|
128
|
+
// Post-commit-5: ranking signals (importance, maturity) are read from the
|
|
129
|
+
// sidecar at query time; the symbol tree only carries structural metadata.
|
|
142
130
|
// Also register the context.md path itself for direct lookups
|
|
143
131
|
symbolMap.set(doc.path, folderNode ?? getOrCreateFolderNode(symbolMap, root, folderPath, segments.slice(0, -1)));
|
|
144
132
|
}
|
|
@@ -150,7 +138,7 @@ export function buildSymbolTree(documentMap, summaryMap) {
|
|
|
150
138
|
const contextNode = {
|
|
151
139
|
children: [],
|
|
152
140
|
kind: MemorySymbolKind.Context,
|
|
153
|
-
metadata:
|
|
141
|
+
metadata: { ...DEFAULT_METADATA },
|
|
154
142
|
name: doc.title || segments.at(-1).replace(/\.md$/, ''),
|
|
155
143
|
parent: parentNode,
|
|
156
144
|
path: doc.path,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { IRuntimeSignalStore } from '../../../../server/core/interfaces/storage/i-runtime-signal-store.js';
|
|
1
2
|
import type { IFileSystem } from '../../../core/interfaces/i-file-system.js';
|
|
3
|
+
import type { ILogger } from '../../../core/interfaces/i-logger.js';
|
|
2
4
|
import type { ISearchKnowledgeService, SearchKnowledgeResult } from '../../sandbox/tools-sdk.js';
|
|
3
5
|
/**
|
|
4
6
|
* Configuration for SearchKnowledgeService.
|
|
@@ -8,6 +10,18 @@ export interface SearchKnowledgeServiceConfig {
|
|
|
8
10
|
baseDirectory?: string;
|
|
9
11
|
/** Cache TTL in milliseconds (defaults to 5000) */
|
|
10
12
|
cacheTtlMs?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Optional logger. When provided, sidecar read failures on the ranking
|
|
15
|
+
* path emit a `warn` so the fail-open degradation is observable rather
|
|
16
|
+
* than silent.
|
|
17
|
+
*/
|
|
18
|
+
logger?: ILogger;
|
|
19
|
+
/**
|
|
20
|
+
* Sidecar store for runtime ranking signals. When provided, `flushAccessHits`
|
|
21
|
+
* mirrors its importance/accessCount/maturity bumps to the store alongside
|
|
22
|
+
* the existing markdown writes. Phase 3 of the runtime-signals migration.
|
|
23
|
+
*/
|
|
24
|
+
runtimeSignalStore?: IRuntimeSignalStore;
|
|
11
25
|
}
|
|
12
26
|
/**
|
|
13
27
|
* Extended search options supporting symbolic filters.
|
|
@@ -36,15 +50,24 @@ export declare class SearchKnowledgeService implements ISearchKnowledgeService {
|
|
|
36
50
|
private readonly baseDirectory;
|
|
37
51
|
private readonly cacheTtlMs;
|
|
38
52
|
private readonly fileSystem;
|
|
53
|
+
private readonly logger?;
|
|
39
54
|
private readonly pendingAccessHits;
|
|
55
|
+
private readonly runtimeSignalStore?;
|
|
40
56
|
private readonly state;
|
|
41
57
|
constructor(fileSystem: IFileSystem, config?: SearchKnowledgeServiceConfig);
|
|
42
58
|
/**
|
|
43
|
-
* Flush accumulated access hits to
|
|
44
|
-
*
|
|
45
|
-
*
|
|
59
|
+
* Flush accumulated access hits to the runtime-signal sidecar.
|
|
60
|
+
*
|
|
61
|
+
* Post-commit-5 this no longer writes to markdown — ranking signals
|
|
62
|
+
* live exclusively in the sidecar. The `contextTreePath` parameter is
|
|
63
|
+
* retained for signature compatibility with the cache-invalidation
|
|
64
|
+
* callback but is no longer used.
|
|
65
|
+
*
|
|
66
|
+
* Returns `true` when hits were processed so the caller knows to
|
|
67
|
+
* refresh file mtimes (historical contract); with markdown writes
|
|
68
|
+
* removed the refresh is harmless but kept for symmetry.
|
|
46
69
|
*/
|
|
47
|
-
flushAccessHits(
|
|
70
|
+
flushAccessHits(_contextTreePath: string): Promise<boolean>;
|
|
48
71
|
/**
|
|
49
72
|
* Search the knowledge base for relevant topics.
|
|
50
73
|
* Supports symbolic path queries, scoped search, kind/maturity filtering, and overview mode.
|
|
@@ -64,6 +87,28 @@ export declare class SearchKnowledgeService implements ISearchKnowledgeService {
|
|
|
64
87
|
* For archive stubs, extracts points_to path into archiveFullPath.
|
|
65
88
|
*/
|
|
66
89
|
private enrichResult;
|
|
90
|
+
/**
|
|
91
|
+
* Load the runtime-signal map for this search via `getMany`, limiting the
|
|
92
|
+
* request to paths that this search could possibly rank: every indexed
|
|
93
|
+
* document plus every summary sibling (parent-propagation can touch any
|
|
94
|
+
* summary). The returned map contains entries only for paths with stored
|
|
95
|
+
* signals; callers use `.has()` / `.get()` to distinguish missing from
|
|
96
|
+
* default. Returns an empty map on sidecar failure so ranking degrades to
|
|
97
|
+
* BM25 alone rather than erroring out mid-query.
|
|
98
|
+
*/
|
|
99
|
+
private loadSignalsByPath;
|
|
100
|
+
/**
|
|
101
|
+
* Mirror a batch of access-hit bumps into the runtime-signal sidecar.
|
|
102
|
+
*
|
|
103
|
+
* Matches the markdown flush semantics above:
|
|
104
|
+
* - `recordAccessHits` bumps `importance` by `ACCESS_IMPORTANCE_BONUS * count`
|
|
105
|
+
* and `accessCount` by `count`.
|
|
106
|
+
* - `determineTier` recomputes `maturity` from the new importance.
|
|
107
|
+
* Both steps run inside `update`'s atomic read-modify-write callback so
|
|
108
|
+
* same-path contention within the process does not lose bumps.
|
|
109
|
+
* `updatedAt` is never mirrored — it is a content timestamp, not a signal.
|
|
110
|
+
*/
|
|
111
|
+
private mirrorHitsToSignalStore;
|
|
67
112
|
/**
|
|
68
113
|
* Run the standard text-based MiniSearch pipeline, optionally scoped to a subtree.
|
|
69
114
|
*/
|
|
@@ -3,8 +3,9 @@ import { realpath } from 'node:fs/promises';
|
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { removeStopwords } from 'stopword';
|
|
5
5
|
import { BRV_DIR, CONTEXT_FILE_EXTENSION, CONTEXT_TREE_DIR, OVERVIEW_EXTENSION, SHARED_SOURCE_LOCAL_SCORE_BOOST, SUMMARY_INDEX_FILE, } from '../../../../server/constants.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { applyDecay, compoundScore, determineTier, recordAccessHits, } from '../../../../server/core/domain/knowledge/memory-scoring.js';
|
|
7
|
+
import { createDefaultRuntimeSignals, } from '../../../../server/core/domain/knowledge/runtime-signals-schema.js';
|
|
8
|
+
import { warnSidecarFailure } from '../../../../server/core/domain/knowledge/sidecar-logging.js';
|
|
8
9
|
import { loadSources } from '../../../../server/core/domain/source/source-schema.js';
|
|
9
10
|
import { isArchiveStub, isDerivedArtifact } from '../../../../server/infra/context-tree/derived-artifact.js';
|
|
10
11
|
import { parseArchiveStubFrontmatter, parseSummaryFrontmatter, } from '../../../../server/infra/context-tree/summary-frontmatter.js';
|
|
@@ -55,7 +56,7 @@ function getSymbolPath(origin, relativePath) {
|
|
|
55
56
|
* @param propagationFactor - Score multiplier per level up (default 0.55)
|
|
56
57
|
* @returns New parent entries only — caller merges and re-sorts
|
|
57
58
|
*/
|
|
58
|
-
function propagateScoresToParents(results, symbolTree, summaryMap, symbolPathDocMap, propagationFactor = 0.55) {
|
|
59
|
+
function propagateScoresToParents(results, symbolTree, summaryMap, symbolPathDocMap, signalsByPath, propagationFactor = 0.55) {
|
|
59
60
|
const boosts = new Map();
|
|
60
61
|
for (const r of results) {
|
|
61
62
|
const symbol = symbolTree.symbolMap.get(r.path);
|
|
@@ -76,11 +77,15 @@ function propagateScoresToParents(results, symbolTree, summaryMap, symbolPathDoc
|
|
|
76
77
|
const doc = getSummarySource(parentPath, summaryMap, symbolPathDocMap);
|
|
77
78
|
if (!doc)
|
|
78
79
|
continue;
|
|
79
|
-
// Propagate the strongest child BM25 signal upward
|
|
80
|
-
// summary's own scoring
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
// Propagate the strongest child BM25 signal upward. Apply the parent
|
|
81
|
+
// summary's own scoring boost only when the sidecar has a concrete entry
|
|
82
|
+
// for this path — matches the pre-migration behaviour where summaries
|
|
83
|
+
// without scoring in their frontmatter were not boosted. Lookup uses the
|
|
84
|
+
// summary doc's file path (e.g. `auth/jwt/_index.md`) which matches the
|
|
85
|
+
// sidecar's relPath key scheme.
|
|
86
|
+
const sidecarSignals = signalsByPath.get(doc.path);
|
|
87
|
+
const finalScore = sidecarSignals
|
|
88
|
+
? compoundScore(score, sidecarSignals)
|
|
84
89
|
: score;
|
|
85
90
|
boosted.push({
|
|
86
91
|
backlinkCount: 0,
|
|
@@ -114,7 +119,6 @@ function getSummarySource(path, summaryMap, symbolPathDocMap) {
|
|
|
114
119
|
return {
|
|
115
120
|
excerpt: summaryDoc.excerpt ?? '',
|
|
116
121
|
path: summaryDoc.path,
|
|
117
|
-
scoring: summaryDoc.scoring,
|
|
118
122
|
};
|
|
119
123
|
}
|
|
120
124
|
// Look up context.md via symbolPath-keyed map since documentMap keys are
|
|
@@ -124,7 +128,6 @@ function getSummarySource(path, summaryMap, symbolPathDocMap) {
|
|
|
124
128
|
return {
|
|
125
129
|
excerpt: extractExcerpt(contextDoc.content, contextDoc.title),
|
|
126
130
|
path: contextDoc.path,
|
|
127
|
-
scoring: contextDoc.scoring,
|
|
128
131
|
};
|
|
129
132
|
}
|
|
130
133
|
return undefined;
|
|
@@ -318,7 +321,6 @@ async function indexOriginDocuments(fileSystem, origin, filesWithMtime) {
|
|
|
318
321
|
const fullPath = join(origin.contextTreeRoot, filePath);
|
|
319
322
|
const { content } = await fileSystem.readFile(fullPath);
|
|
320
323
|
const title = extractTitle(content, filePath.replace(/\.md$/, '').split('/').pop() || filePath);
|
|
321
|
-
const scoring = parseFrontmatterScoring(content) ?? applyDefaultScoring();
|
|
322
324
|
const qualifiedId = `${origin.originKey}::${filePath}`;
|
|
323
325
|
const symbolPath = getSymbolPath(origin, filePath);
|
|
324
326
|
// Check if a .overview.md sibling exists (written by abstract generation queue)
|
|
@@ -333,7 +335,6 @@ async function indexOriginDocuments(fileSystem, origin, filesWithMtime) {
|
|
|
333
335
|
originKey: origin.originKey,
|
|
334
336
|
...(overviewPath !== undefined && { overviewPath }),
|
|
335
337
|
path: filePath,
|
|
336
|
-
scoring,
|
|
337
338
|
symbolPath,
|
|
338
339
|
title,
|
|
339
340
|
};
|
|
@@ -352,16 +353,10 @@ async function indexOriginDocuments(fileSystem, origin, filesWithMtime) {
|
|
|
352
353
|
const fm = parseSummaryFrontmatter(content);
|
|
353
354
|
if (!fm)
|
|
354
355
|
return null;
|
|
355
|
-
// Persist frontmatter scoring so propagateScoresToParents can apply hotness/tier boosts
|
|
356
|
-
const frontmatter = parseFrontmatterScoring(content);
|
|
357
|
-
const scoring = frontmatter
|
|
358
|
-
? { importance: frontmatter.importance, maturity: frontmatter.maturity, recency: frontmatter.recency }
|
|
359
|
-
: undefined;
|
|
360
356
|
return {
|
|
361
357
|
condensationOrder: fm.condensation_order,
|
|
362
358
|
excerpt: stripMarkdownFrontmatter(content).slice(0, 400),
|
|
363
359
|
path: getSymbolPath(origin, filePath),
|
|
364
|
-
scoring,
|
|
365
360
|
tokenCount: fm.token_count,
|
|
366
361
|
};
|
|
367
362
|
}
|
|
@@ -600,7 +595,9 @@ export class SearchKnowledgeService {
|
|
|
600
595
|
baseDirectory;
|
|
601
596
|
cacheTtlMs;
|
|
602
597
|
fileSystem;
|
|
598
|
+
logger;
|
|
603
599
|
pendingAccessHits = new Map();
|
|
600
|
+
runtimeSignalStore;
|
|
604
601
|
state = {
|
|
605
602
|
buildingPromise: undefined,
|
|
606
603
|
cachedIndex: undefined,
|
|
@@ -609,34 +606,28 @@ export class SearchKnowledgeService {
|
|
|
609
606
|
this.fileSystem = fileSystem;
|
|
610
607
|
this.baseDirectory = config.baseDirectory ?? process.cwd();
|
|
611
608
|
this.cacheTtlMs = config.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;
|
|
609
|
+
this.logger = config.logger;
|
|
610
|
+
this.runtimeSignalStore = config.runtimeSignalStore;
|
|
612
611
|
}
|
|
613
612
|
/**
|
|
614
|
-
* Flush accumulated access hits to
|
|
615
|
-
*
|
|
616
|
-
*
|
|
613
|
+
* Flush accumulated access hits to the runtime-signal sidecar.
|
|
614
|
+
*
|
|
615
|
+
* Post-commit-5 this no longer writes to markdown — ranking signals
|
|
616
|
+
* live exclusively in the sidecar. The `contextTreePath` parameter is
|
|
617
|
+
* retained for signature compatibility with the cache-invalidation
|
|
618
|
+
* callback but is no longer used.
|
|
619
|
+
*
|
|
620
|
+
* Returns `true` when hits were processed so the caller knows to
|
|
621
|
+
* refresh file mtimes (historical contract); with markdown writes
|
|
622
|
+
* removed the refresh is harmless but kept for symmetry.
|
|
617
623
|
*/
|
|
618
|
-
async flushAccessHits(
|
|
624
|
+
async flushAccessHits(_contextTreePath) {
|
|
619
625
|
if (this.pendingAccessHits.size === 0) {
|
|
620
626
|
return false;
|
|
621
627
|
}
|
|
622
628
|
const hits = new Map(this.pendingAccessHits);
|
|
623
629
|
this.pendingAccessHits.clear();
|
|
624
|
-
|
|
625
|
-
try {
|
|
626
|
-
const fullPath = join(contextTreePath, relPath);
|
|
627
|
-
const { content } = await this.fileSystem.readFile(fullPath);
|
|
628
|
-
const scoring = parseFrontmatterScoring(content) ?? applyDefaultScoring();
|
|
629
|
-
const updated = recordAccessHits(scoring, count);
|
|
630
|
-
const newTier = determineTier(updated.importance ?? 50, (updated.maturity ?? 'draft'));
|
|
631
|
-
const finalScoring = { ...updated, maturity: newTier };
|
|
632
|
-
const newContent = updateScoringInContent(content, finalScoring);
|
|
633
|
-
await this.fileSystem.writeFile(fullPath, newContent);
|
|
634
|
-
}
|
|
635
|
-
catch {
|
|
636
|
-
// Best-effort — swallow per-file errors
|
|
637
|
-
}
|
|
638
|
-
});
|
|
639
|
-
await Promise.allSettled(tasks);
|
|
630
|
+
await this.mirrorHitsToSignalStore(hits);
|
|
640
631
|
return true;
|
|
641
632
|
}
|
|
642
633
|
/**
|
|
@@ -674,9 +665,16 @@ export class SearchKnowledgeService {
|
|
|
674
665
|
if (options?.overview) {
|
|
675
666
|
return this.buildOverviewResult(symbolTree, referenceIndex, normalizedScope, options.overviewDepth);
|
|
676
667
|
}
|
|
668
|
+
// Load the runtime-signal sidecar map for the specific paths this query
|
|
669
|
+
// touches: all document paths in the index plus their summary siblings.
|
|
670
|
+
// This is O(k) per search instead of O(all entries). Entries are present
|
|
671
|
+
// only for paths with stored signals — callers use `.has()` to distinguish
|
|
672
|
+
// missing from default, and `.get(path) ?? defaults` for ergonomic
|
|
673
|
+
// default-on-miss. On sidecar failure, degrade to BM25-only ranking.
|
|
674
|
+
const signalsByPath = await this.loadSignalsByPath(documentMap, summaryMap);
|
|
677
675
|
// Symbolic path resolution: try path-based query first
|
|
678
676
|
if (isPathLikeQuery(query, symbolTree)) {
|
|
679
|
-
const symbolicResult = this.trySymbolicSearch(query, symbolTree, referenceIndex, documentMap, index, limit, pathToDocumentId, summaryMap, symbolPathDocMap, options);
|
|
677
|
+
const symbolicResult = this.trySymbolicSearch(query, symbolTree, referenceIndex, documentMap, index, limit, pathToDocumentId, summaryMap, symbolPathDocMap, signalsByPath, options);
|
|
680
678
|
if (symbolicResult) {
|
|
681
679
|
return symbolicResult;
|
|
682
680
|
}
|
|
@@ -691,10 +689,10 @@ export class SearchKnowledgeService {
|
|
|
691
689
|
const effectiveScope = (rawScope !== undefined && rawScope !== '' ? rawScope : undefined) ?? parsed.scopePath;
|
|
692
690
|
const effectiveQuery = parsed.scopePath ? parsed.textQuery : query;
|
|
693
691
|
// Run text-based MiniSearch (existing pipeline), optionally scoped to a subtree
|
|
694
|
-
const textResult = this.runTextSearch(effectiveQuery || query, documentMap, index, limit, effectiveScope, pathToDocumentId, symbolTree, referenceIndex, summaryMap, symbolPathDocMap, options);
|
|
692
|
+
const textResult = this.runTextSearch(effectiveQuery || query, documentMap, index, limit, effectiveScope, pathToDocumentId, symbolTree, referenceIndex, summaryMap, symbolPathDocMap, signalsByPath, options);
|
|
695
693
|
// If scoped search returned nothing and we had a scope, fall back to global search
|
|
696
694
|
if (textResult.results.length === 0 && effectiveScope && effectiveQuery) {
|
|
697
|
-
return this.runTextSearch(query, documentMap, index, limit, undefined, pathToDocumentId, symbolTree, referenceIndex, summaryMap, symbolPathDocMap, options);
|
|
695
|
+
return this.runTextSearch(query, documentMap, index, limit, undefined, pathToDocumentId, symbolTree, referenceIndex, summaryMap, symbolPathDocMap, signalsByPath, options);
|
|
698
696
|
}
|
|
699
697
|
return textResult;
|
|
700
698
|
}
|
|
@@ -772,10 +770,72 @@ export class SearchKnowledgeService {
|
|
|
772
770
|
symbolPath: isContextSummary ? summaryPath : symbol?.path,
|
|
773
771
|
};
|
|
774
772
|
}
|
|
773
|
+
/**
|
|
774
|
+
* Load the runtime-signal map for this search via `getMany`, limiting the
|
|
775
|
+
* request to paths that this search could possibly rank: every indexed
|
|
776
|
+
* document plus every summary sibling (parent-propagation can touch any
|
|
777
|
+
* summary). The returned map contains entries only for paths with stored
|
|
778
|
+
* signals; callers use `.has()` / `.get()` to distinguish missing from
|
|
779
|
+
* default. Returns an empty map on sidecar failure so ranking degrades to
|
|
780
|
+
* BM25 alone rather than erroring out mid-query.
|
|
781
|
+
*/
|
|
782
|
+
async loadSignalsByPath(documentMap, summaryMap) {
|
|
783
|
+
if (!this.runtimeSignalStore)
|
|
784
|
+
return new Map();
|
|
785
|
+
const paths = new Set();
|
|
786
|
+
for (const doc of documentMap.values())
|
|
787
|
+
paths.add(doc.path);
|
|
788
|
+
for (const summary of summaryMap.values())
|
|
789
|
+
paths.add(summary.path);
|
|
790
|
+
try {
|
|
791
|
+
return await this.runtimeSignalStore.getMany([...paths]);
|
|
792
|
+
}
|
|
793
|
+
catch (error) {
|
|
794
|
+
this.logger?.warn(`SearchKnowledgeService: sidecar getMany failed, falling back to BM25-only ranking: ${error instanceof Error ? error.message : String(error)}`);
|
|
795
|
+
return new Map();
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* Mirror a batch of access-hit bumps into the runtime-signal sidecar.
|
|
800
|
+
*
|
|
801
|
+
* Matches the markdown flush semantics above:
|
|
802
|
+
* - `recordAccessHits` bumps `importance` by `ACCESS_IMPORTANCE_BONUS * count`
|
|
803
|
+
* and `accessCount` by `count`.
|
|
804
|
+
* - `determineTier` recomputes `maturity` from the new importance.
|
|
805
|
+
* Both steps run inside `update`'s atomic read-modify-write callback so
|
|
806
|
+
* same-path contention within the process does not lose bumps.
|
|
807
|
+
* `updatedAt` is never mirrored — it is a content timestamp, not a signal.
|
|
808
|
+
*/
|
|
809
|
+
async mirrorHitsToSignalStore(hits) {
|
|
810
|
+
const store = this.runtimeSignalStore;
|
|
811
|
+
if (!store)
|
|
812
|
+
return;
|
|
813
|
+
const updates = new Map([...hits.entries()].map(([relPath, count]) => [
|
|
814
|
+
relPath,
|
|
815
|
+
(current) => {
|
|
816
|
+
const bumped = recordAccessHits(current, count);
|
|
817
|
+
return {
|
|
818
|
+
...current,
|
|
819
|
+
accessCount: bumped.accessCount,
|
|
820
|
+
importance: bumped.importance,
|
|
821
|
+
maturity: determineTier(bumped.importance, current.maturity),
|
|
822
|
+
};
|
|
823
|
+
},
|
|
824
|
+
]));
|
|
825
|
+
try {
|
|
826
|
+
await store.batchUpdate(updates);
|
|
827
|
+
}
|
|
828
|
+
catch (error) {
|
|
829
|
+
// Best-effort — sidecar failure must not break the flush. The sidecar
|
|
830
|
+
// will re-sync on the next bump for these paths; the warn makes the
|
|
831
|
+
// fail-open visible to operators.
|
|
832
|
+
warnSidecarFailure(this.logger, 'search-knowledge-flush', 'batchUpdate', `${updates.size} path(s)`, error);
|
|
833
|
+
}
|
|
834
|
+
}
|
|
775
835
|
/**
|
|
776
836
|
* Run the standard text-based MiniSearch pipeline, optionally scoped to a subtree.
|
|
777
837
|
*/
|
|
778
|
-
runTextSearch(query, documentMap, index, limit, scopePath, pathToDocumentId, symbolTree, referenceIndex, summaryMap, symbolPathDocMap, options) {
|
|
838
|
+
runTextSearch(query, documentMap, index, limit, scopePath, pathToDocumentId, symbolTree, referenceIndex, summaryMap, symbolPathDocMap, signalsByPath, options) {
|
|
779
839
|
const filteredQuery = filterStopWords(query);
|
|
780
840
|
const filteredWords = filteredQuery.split(/\s+/).filter((w) => w.length >= 2);
|
|
781
841
|
// Build scope filter if a subtree is specified
|
|
@@ -811,14 +871,19 @@ export class SearchKnowledgeService {
|
|
|
811
871
|
// Normalize BM25 scores to [0, 1) then blend with importance + recency via compound scoring.
|
|
812
872
|
// Decay is computed lazily from file mtime — no disk writes during search.
|
|
813
873
|
// Local results get a configurable score boost to prefer local knowledge over shared.
|
|
874
|
+
//
|
|
875
|
+
// Runtime signals (importance / recency / maturity) come from the sidecar
|
|
876
|
+
// `signalsByPath` map. Paths with no sidecar entry fall back to defaults —
|
|
877
|
+
// matches the pre-migration behaviour where missing-frontmatter files used
|
|
878
|
+
// applyDefaultScoring().
|
|
814
879
|
const now = Date.now();
|
|
815
880
|
const searchResults = rawResults.map((r) => {
|
|
816
881
|
const doc = documentMap.get(r.id);
|
|
817
|
-
const
|
|
882
|
+
const signals = (doc && signalsByPath.get(doc.path)) ?? createDefaultRuntimeSignals();
|
|
818
883
|
const daysSince = doc ? Math.max(0, (now - doc.mtime) / 86_400_000) : 0;
|
|
819
|
-
const decayed = applyDecay(
|
|
884
|
+
const decayed = applyDecay(signals, daysSince);
|
|
820
885
|
const bm25 = normalizeScore(r.score);
|
|
821
|
-
let finalScore = compoundScore(bm25, decayed
|
|
886
|
+
let finalScore = compoundScore(bm25, decayed);
|
|
822
887
|
// Local score boost: prefer local results over shared when scores are close
|
|
823
888
|
if (doc?.origin === 'local') {
|
|
824
889
|
finalScore = Math.min(finalScore + SHARED_SOURCE_LOCAL_SCORE_BOOST, 1);
|
|
@@ -883,10 +948,15 @@ export class SearchKnowledgeService {
|
|
|
883
948
|
}
|
|
884
949
|
if (options?.minMaturity && enriched.symbolKind) {
|
|
885
950
|
const docMaturity = enriched.symbolKind === 'summary'
|
|
886
|
-
? (
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
951
|
+
? (() => {
|
|
952
|
+
const summaryDoc = getSummarySource(enriched.path, summaryMap, symbolPathDocMap);
|
|
953
|
+
return ((summaryDoc && signalsByPath.get(summaryDoc.path)?.maturity) ??
|
|
954
|
+
symbolTree.symbolMap.get(enriched.path)?.metadata.maturity ??
|
|
955
|
+
'draft');
|
|
956
|
+
})()
|
|
957
|
+
: (signalsByPath.get(document.path)?.maturity ??
|
|
958
|
+
symbolTree.symbolMap.get(document.symbolPath)?.metadata.maturity ??
|
|
959
|
+
'draft');
|
|
890
960
|
if ((MATURITY_TIER_RANK[docMaturity] ?? 1) < (MATURITY_TIER_RANK[options.minMaturity] ?? 1)) {
|
|
891
961
|
continue;
|
|
892
962
|
}
|
|
@@ -900,7 +970,7 @@ export class SearchKnowledgeService {
|
|
|
900
970
|
}
|
|
901
971
|
}
|
|
902
972
|
// Propagate scores upward to parent domain/topic nodes (hierarchical retrieval)
|
|
903
|
-
const propagated = propagateScoresToParents(propagationInputs, symbolTree, summaryMap, symbolPathDocMap);
|
|
973
|
+
const propagated = propagateScoresToParents(propagationInputs, symbolTree, summaryMap, symbolPathDocMap, signalsByPath);
|
|
904
974
|
for (const p of propagated) {
|
|
905
975
|
// Apply local score boost to propagated summaries so they stay competitive
|
|
906
976
|
// with boosted direct BM25 hits (the boost was already applied to direct hits above)
|
|
@@ -913,7 +983,7 @@ export class SearchKnowledgeService {
|
|
|
913
983
|
continue;
|
|
914
984
|
if (options?.minMaturity && p.symbolKind === 'summary') {
|
|
915
985
|
const summaryDoc = getSummarySource(p.path, summaryMap, symbolPathDocMap);
|
|
916
|
-
const summaryMaturity = summaryDoc?.
|
|
986
|
+
const summaryMaturity = (summaryDoc && signalsByPath.get(summaryDoc.path)?.maturity) ?? 'draft';
|
|
917
987
|
if ((MATURITY_TIER_RANK[summaryMaturity] ?? 1) < (MATURITY_TIER_RANK[options.minMaturity] ?? 1))
|
|
918
988
|
continue;
|
|
919
989
|
}
|
|
@@ -942,7 +1012,7 @@ export class SearchKnowledgeService {
|
|
|
942
1012
|
/**
|
|
943
1013
|
* Try to resolve the query as a symbolic path. Returns null if no path match found.
|
|
944
1014
|
*/
|
|
945
|
-
trySymbolicSearch(query, symbolTree, referenceIndex, documentMap, index, limit, pathToDocumentId, summaryMap, symbolPathDocMap, options) {
|
|
1015
|
+
trySymbolicSearch(query, symbolTree, referenceIndex, documentMap, index, limit, pathToDocumentId, summaryMap, symbolPathDocMap, signalsByPath, options) {
|
|
946
1016
|
const pathMatches = matchMemoryPath(symbolTree, query.split(/\s+/)[0].includes('/') ? query.split(/\s+/)[0] : query);
|
|
947
1017
|
if (pathMatches.length === 0) {
|
|
948
1018
|
return null;
|
|
@@ -971,7 +1041,7 @@ export class SearchKnowledgeService {
|
|
|
971
1041
|
const textPart = query.slice(query.indexOf(pathPart) + pathPart.length).trim();
|
|
972
1042
|
if (textPart) {
|
|
973
1043
|
// Scoped search: search text within the matched subtree
|
|
974
|
-
return this.runTextSearch(textPart, documentMap, index, limit, topMatch.path, pathToDocumentId, symbolTree, referenceIndex, summaryMap, symbolPathDocMap, options);
|
|
1044
|
+
return this.runTextSearch(textPart, documentMap, index, limit, topMatch.path, pathToDocumentId, symbolTree, referenceIndex, summaryMap, symbolPathDocMap, signalsByPath, options);
|
|
975
1045
|
}
|
|
976
1046
|
// No text part — return all children of the matched node
|
|
977
1047
|
const subtreeIds = getSubtreeDocumentIds(symbolTree, topMatch.path);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { IRuntimeSignalStore } from '../../../../server/core/interfaces/storage/i-runtime-signal-store.js';
|
|
1
2
|
import type { Tool } from '../../../core/domain/tools/types.js';
|
|
2
3
|
import type { IFileSystem } from '../../../core/interfaces/i-file-system.js';
|
|
3
4
|
/**
|
|
@@ -6,6 +7,7 @@ import type { IFileSystem } from '../../../core/interfaces/i-file-system.js';
|
|
|
6
7
|
export interface SearchKnowledgeToolConfig {
|
|
7
8
|
baseDirectory?: string;
|
|
8
9
|
cacheTtlMs?: number;
|
|
10
|
+
runtimeSignalStore?: IRuntimeSignalStore;
|
|
9
11
|
}
|
|
10
12
|
/**
|
|
11
13
|
* Creates the search knowledge tool.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { IRuntimeSignalStore } from '../../../server/core/interfaces/storage/i-runtime-signal-store.js';
|
|
1
2
|
import type { EnvironmentContext } from '../../core/domain/environment/types.js';
|
|
2
3
|
import type { KnownTool } from '../../core/domain/tools/constants.js';
|
|
3
4
|
import type { Tool } from '../../core/domain/tools/types.js';
|
|
@@ -42,6 +43,12 @@ export interface ToolServices {
|
|
|
42
43
|
memoryManager?: MemoryManager;
|
|
43
44
|
/** Process service for command execution */
|
|
44
45
|
processService?: IProcessService;
|
|
46
|
+
/**
|
|
47
|
+
* Sidecar store for per-machine ranking signals. When provided, curate and
|
|
48
|
+
* search tools mirror their scoring writes here alongside the markdown
|
|
49
|
+
* writes. Phase 3 of the runtime-signals migration.
|
|
50
|
+
*/
|
|
51
|
+
runtimeSignalStore?: IRuntimeSignalStore;
|
|
45
52
|
/** Sandbox service for code execution */
|
|
46
53
|
sandboxService?: ISandboxService;
|
|
47
54
|
/** Swarm coordinator for cross-provider memory queries */
|
|
@@ -57,7 +57,7 @@ export const TOOL_REGISTRY = {
|
|
|
57
57
|
},
|
|
58
58
|
[ToolName.CODE_EXEC]: {
|
|
59
59
|
descriptionFile: 'code_exec',
|
|
60
|
-
factory({ abstractQueue, environmentContext, fileSystemService, sandboxService, swarmCoordinator }) {
|
|
60
|
+
factory({ abstractQueue, environmentContext, fileSystemService, runtimeSignalStore, sandboxService, swarmCoordinator }) {
|
|
61
61
|
const sandbox = getRequiredService(sandboxService, 'sandboxService');
|
|
62
62
|
// Inject file system service into sandbox for Tools SDK
|
|
63
63
|
if (fileSystemService && sandbox.setFileSystem) {
|
|
@@ -65,12 +65,14 @@ export const TOOL_REGISTRY = {
|
|
|
65
65
|
}
|
|
66
66
|
// Inject search knowledge service into sandbox for Tools SDK
|
|
67
67
|
if (fileSystemService && sandbox.setSearchKnowledgeService) {
|
|
68
|
-
const searchKnowledgeService = createSearchKnowledgeService(fileSystemService
|
|
68
|
+
const searchKnowledgeService = createSearchKnowledgeService(fileSystemService, {
|
|
69
|
+
runtimeSignalStore,
|
|
70
|
+
});
|
|
69
71
|
sandbox.setSearchKnowledgeService(searchKnowledgeService);
|
|
70
72
|
}
|
|
71
73
|
// Inject curate service into sandbox for Tools SDK
|
|
72
74
|
if (sandbox.setCurateService) {
|
|
73
|
-
const curateService = createCurateService(environmentContext?.workingDirectory, abstractQueue);
|
|
75
|
+
const curateService = createCurateService(environmentContext?.workingDirectory, abstractQueue, runtimeSignalStore);
|
|
74
76
|
sandbox.setCurateService(curateService);
|
|
75
77
|
}
|
|
76
78
|
// Inject environment context into sandbox for env.* access
|
|
@@ -88,14 +90,17 @@ export const TOOL_REGISTRY = {
|
|
|
88
90
|
},
|
|
89
91
|
[ToolName.CURATE]: {
|
|
90
92
|
descriptionFile: 'curate',
|
|
91
|
-
factory: ({ abstractQueue, environmentContext }) => createCurateTool(environmentContext?.workingDirectory, abstractQueue),
|
|
93
|
+
factory: ({ abstractQueue, environmentContext, logger, runtimeSignalStore }) => createCurateTool(environmentContext?.workingDirectory, abstractQueue, runtimeSignalStore, logger),
|
|
92
94
|
markers: [ToolMarker.ContextBuilding, ToolMarker.Modification],
|
|
93
95
|
outputGuidance: 'curate',
|
|
94
96
|
requiredServices: [],
|
|
95
97
|
},
|
|
96
98
|
[ToolName.EXPAND_KNOWLEDGE]: {
|
|
97
99
|
descriptionFile: 'expand_knowledge',
|
|
98
|
-
factory: ({ environmentContext }) => createExpandKnowledgeTool({
|
|
100
|
+
factory: ({ environmentContext, runtimeSignalStore }) => createExpandKnowledgeTool({
|
|
101
|
+
baseDirectory: environmentContext?.workingDirectory,
|
|
102
|
+
runtimeSignalStore,
|
|
103
|
+
}),
|
|
99
104
|
markers: [ToolMarker.Discovery],
|
|
100
105
|
requiredServices: [],
|
|
101
106
|
},
|
|
@@ -144,7 +149,9 @@ export const TOOL_REGISTRY = {
|
|
|
144
149
|
},
|
|
145
150
|
[ToolName.SEARCH_KNOWLEDGE]: {
|
|
146
151
|
descriptionFile: 'search_knowledge',
|
|
147
|
-
factory: (services) => createSearchKnowledgeTool(getRequiredService(services.fileSystemService, 'fileSystemService')
|
|
152
|
+
factory: (services) => createSearchKnowledgeTool(getRequiredService(services.fileSystemService, 'fileSystemService'), {
|
|
153
|
+
runtimeSignalStore: services.runtimeSignalStore,
|
|
154
|
+
}),
|
|
148
155
|
markers: [ToolMarker.ContextBuilding, ToolMarker.Discovery],
|
|
149
156
|
requiredServices: ['fileSystemService'],
|
|
150
157
|
},
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
+
import type { ILogger } from '../../agent/core/interfaces/i-logger.js';
|
|
3
|
+
import { undoLastDream } from '../../server/infra/dream/dream-undo.js';
|
|
2
4
|
import { type DaemonClientOptions } from '../lib/daemon-client.js';
|
|
5
|
+
/** Build the dep bundle for `undoLastDream` on the CLI-direct path; exported for wiring tests. */
|
|
6
|
+
export declare function buildUndoDeps(projectRoot: string, logger?: ILogger): Promise<Parameters<typeof undoLastDream>[0]>;
|
|
3
7
|
export default class Dream extends Command {
|
|
4
8
|
static description: string;
|
|
5
9
|
static examples: string[];
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
2
|
import { randomUUID } from 'node:crypto';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
+
import { NoOpLogger } from '../../agent/core/interfaces/i-logger.js';
|
|
5
|
+
import { ConsoleLogger } from '../../agent/infra/logger/console-logger.js';
|
|
6
|
+
import { FileKeyStorage } from '../../agent/infra/storage/file-key-storage.js';
|
|
4
7
|
import { BRV_DIR, CONTEXT_TREE_DIR } from '../../server/constants.js';
|
|
5
8
|
import { TransportStateEventNames } from '../../server/core/domain/transport/schemas.js';
|
|
6
9
|
import { FileContextTreeArchiveService } from '../../server/infra/context-tree/file-context-tree-archive-service.js';
|
|
7
10
|
import { FileContextTreeManifestService } from '../../server/infra/context-tree/file-context-tree-manifest-service.js';
|
|
11
|
+
import { RuntimeSignalStore } from '../../server/infra/context-tree/runtime-signal-store.js';
|
|
8
12
|
import { DreamLogStore } from '../../server/infra/dream/dream-log-store.js';
|
|
9
13
|
import { DreamStateService } from '../../server/infra/dream/dream-state-service.js';
|
|
10
14
|
import { undoLastDream } from '../../server/infra/dream/dream-undo.js';
|
|
@@ -16,6 +20,28 @@ import { TaskEvents } from '../../shared/transport/events/index.js';
|
|
|
16
20
|
import { formatConnectionError, hasLeakedHandles, providerMissingMessage, withDaemonRetry, } from '../lib/daemon-client.js';
|
|
17
21
|
import { writeJsonResponse } from '../lib/json-response.js';
|
|
18
22
|
import { DEFAULT_TIMEOUT_SECONDS, MAX_TIMEOUT_SECONDS, MIN_TIMEOUT_SECONDS, waitForTaskCompletion } from '../lib/task-client.js';
|
|
23
|
+
/** Build the dep bundle for `undoLastDream` on the CLI-direct path; exported for wiring tests. */
|
|
24
|
+
export async function buildUndoDeps(projectRoot, logger = new ConsoleLogger()) {
|
|
25
|
+
const brvDir = join(projectRoot, BRV_DIR);
|
|
26
|
+
const contextTreeDir = join(brvDir, CONTEXT_TREE_DIR);
|
|
27
|
+
const projectDataDir = getProjectDataDir(projectRoot);
|
|
28
|
+
// Runtime-signal sidecar — keeps archive/restore from leaking orphan
|
|
29
|
+
// signal entries on the CLI-direct `brv dream --undo` path. Mirrors the
|
|
30
|
+
// daemon wiring in agent-process.ts.
|
|
31
|
+
const keyStorage = new FileKeyStorage({ storageDir: projectDataDir });
|
|
32
|
+
await keyStorage.initialize();
|
|
33
|
+
const runtimeSignalStore = new RuntimeSignalStore(keyStorage, logger);
|
|
34
|
+
return {
|
|
35
|
+
archiveService: new FileContextTreeArchiveService(runtimeSignalStore),
|
|
36
|
+
contextTreeDir,
|
|
37
|
+
curateLogStore: new FileCurateLogStore({ baseDir: projectDataDir }),
|
|
38
|
+
dreamLogStore: new DreamLogStore({ baseDir: brvDir }),
|
|
39
|
+
dreamStateService: new DreamStateService({ baseDir: brvDir }),
|
|
40
|
+
manifestService: new FileContextTreeManifestService({ baseDirectory: projectRoot, runtimeSignalStore }),
|
|
41
|
+
projectRoot,
|
|
42
|
+
reviewBackupStore: new FileReviewBackupStore(brvDir),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
19
45
|
export default class Dream extends Command {
|
|
20
46
|
static description = 'Run background memory consolidation on the context tree';
|
|
21
47
|
static examples = [
|
|
@@ -119,20 +145,12 @@ export default class Dream extends Command {
|
|
|
119
145
|
}
|
|
120
146
|
async runUndo(format) {
|
|
121
147
|
const projectRoot = resolveProject()?.projectRoot ?? process.cwd();
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const
|
|
148
|
+
// JSON mode: route sidecar warnings to a no-op so structured stdout
|
|
149
|
+
// is never paired with stderr noise that breaks downstream parsers.
|
|
150
|
+
const logger = format === 'json' ? new NoOpLogger() : new ConsoleLogger();
|
|
151
|
+
const deps = await buildUndoDeps(projectRoot, logger);
|
|
125
152
|
try {
|
|
126
|
-
const result = await undoLastDream(
|
|
127
|
-
archiveService: new FileContextTreeArchiveService(),
|
|
128
|
-
contextTreeDir,
|
|
129
|
-
curateLogStore: new FileCurateLogStore({ baseDir: projectDataDir }),
|
|
130
|
-
dreamLogStore: new DreamLogStore({ baseDir: brvDir }),
|
|
131
|
-
dreamStateService: new DreamStateService({ baseDir: brvDir }),
|
|
132
|
-
manifestService: new FileContextTreeManifestService({ baseDirectory: projectRoot }),
|
|
133
|
-
projectRoot,
|
|
134
|
-
reviewBackupStore: new FileReviewBackupStore(brvDir),
|
|
135
|
-
});
|
|
153
|
+
const result = await undoLastDream(deps);
|
|
136
154
|
if (format === 'json') {
|
|
137
155
|
writeJsonResponse({ command: 'dream', data: { ...result, status: 'undone' }, success: true });
|
|
138
156
|
}
|
|
@@ -71,6 +71,6 @@ export declare const OVERVIEW_EXTENSION = ".overview.md";
|
|
|
71
71
|
export declare const MANIFEST_FILE = "_manifest.json";
|
|
72
72
|
export declare const ARCHIVE_IMPORTANCE_THRESHOLD = 35;
|
|
73
73
|
export declare const DEFAULT_GHOST_CUE_MAX_TOKENS = 220;
|
|
74
|
-
/** Patterns the context-tree .gitignore must contain
|
|
74
|
+
/** Patterns the context-tree .gitignore must contain. */
|
|
75
75
|
export declare const CONTEXT_TREE_GITIGNORE_PATTERNS: string[];
|
|
76
76
|
export declare const CONTEXT_TREE_GITIGNORE_HEADER = "# Derived artifacts \u2014 do not track";
|