byterover-cli 3.0.1 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/.env.production +4 -0
  2. package/README.md +17 -0
  3. package/dist/agent/core/domain/tools/constants.d.ts +1 -0
  4. package/dist/agent/core/domain/tools/constants.js +1 -0
  5. package/dist/agent/core/interfaces/cipher-services.d.ts +8 -0
  6. package/dist/agent/core/interfaces/i-cipher-agent.d.ts +1 -0
  7. package/dist/agent/infra/agent/agent-error-codes.d.ts +0 -1
  8. package/dist/agent/infra/agent/agent-error-codes.js +0 -1
  9. package/dist/agent/infra/agent/agent-error.d.ts +0 -1
  10. package/dist/agent/infra/agent/agent-error.js +0 -1
  11. package/dist/agent/infra/agent/agent-schemas.d.ts +8 -0
  12. package/dist/agent/infra/agent/agent-schemas.js +1 -0
  13. package/dist/agent/infra/agent/agent-state-manager.d.ts +1 -3
  14. package/dist/agent/infra/agent/agent-state-manager.js +1 -3
  15. package/dist/agent/infra/agent/base-agent.d.ts +1 -1
  16. package/dist/agent/infra/agent/base-agent.js +1 -1
  17. package/dist/agent/infra/agent/cipher-agent.d.ts +15 -1
  18. package/dist/agent/infra/agent/cipher-agent.js +188 -3
  19. package/dist/agent/infra/agent/index.d.ts +1 -1
  20. package/dist/agent/infra/agent/index.js +1 -1
  21. package/dist/agent/infra/agent/service-initializer.d.ts +3 -3
  22. package/dist/agent/infra/agent/service-initializer.js +14 -8
  23. package/dist/agent/infra/agent/types.d.ts +0 -1
  24. package/dist/agent/infra/file-system/file-system-service.js +6 -5
  25. package/dist/agent/infra/folder-pack/folder-pack-service.d.ts +1 -0
  26. package/dist/agent/infra/folder-pack/folder-pack-service.js +29 -15
  27. package/dist/agent/infra/llm/providers/openai.js +12 -0
  28. package/dist/agent/infra/llm/stream-to-text.d.ts +7 -0
  29. package/dist/agent/infra/llm/stream-to-text.js +14 -0
  30. package/dist/agent/infra/map/abstract-generator.d.ts +22 -0
  31. package/dist/agent/infra/map/abstract-generator.js +67 -0
  32. package/dist/agent/infra/map/abstract-queue.d.ts +67 -0
  33. package/dist/agent/infra/map/abstract-queue.js +218 -0
  34. package/dist/agent/infra/memory/memory-deduplicator.d.ts +44 -0
  35. package/dist/agent/infra/memory/memory-deduplicator.js +88 -0
  36. package/dist/agent/infra/memory/memory-manager.d.ts +1 -0
  37. package/dist/agent/infra/memory/memory-manager.js +6 -5
  38. package/dist/agent/infra/sandbox/curate-service.d.ts +4 -2
  39. package/dist/agent/infra/sandbox/curate-service.js +20 -7
  40. package/dist/agent/infra/sandbox/local-sandbox.d.ts +5 -0
  41. package/dist/agent/infra/sandbox/local-sandbox.js +57 -1
  42. package/dist/agent/infra/sandbox/sandbox-service.js +1 -0
  43. package/dist/agent/infra/sandbox/tools-sdk.d.ts +13 -1
  44. package/dist/agent/infra/sandbox/tools-sdk.js +9 -1
  45. package/dist/agent/infra/session/session-compressor.d.ts +43 -0
  46. package/dist/agent/infra/session/session-compressor.js +296 -0
  47. package/dist/agent/infra/session/session-manager.d.ts +7 -0
  48. package/dist/agent/infra/session/session-manager.js +9 -0
  49. package/dist/agent/infra/tools/implementations/curate-tool.d.ts +3 -2
  50. package/dist/agent/infra/tools/implementations/curate-tool.js +54 -27
  51. package/dist/agent/infra/tools/implementations/expand-knowledge-tool.d.ts +3 -3
  52. package/dist/agent/infra/tools/implementations/expand-knowledge-tool.js +34 -7
  53. package/dist/agent/infra/tools/implementations/ingest-resource-tool.d.ts +17 -0
  54. package/dist/agent/infra/tools/implementations/ingest-resource-tool.js +224 -0
  55. package/dist/agent/infra/tools/implementations/memory-symbol-tree.d.ts +8 -0
  56. package/dist/agent/infra/tools/implementations/search-knowledge-service.d.ts +1 -1
  57. package/dist/agent/infra/tools/implementations/search-knowledge-service.js +392 -106
  58. package/dist/agent/infra/tools/implementations/search-knowledge-tool.js +2 -2
  59. package/dist/agent/infra/tools/implementations/write-file-tool.d.ts +2 -1
  60. package/dist/agent/infra/tools/implementations/write-file-tool.js +16 -2
  61. package/dist/agent/infra/tools/tool-provider.js +1 -0
  62. package/dist/agent/infra/tools/tool-registry.d.ts +3 -0
  63. package/dist/agent/infra/tools/tool-registry.js +16 -5
  64. package/dist/agent/infra/tools/write-guard.d.ts +11 -0
  65. package/dist/agent/infra/tools/write-guard.js +48 -0
  66. package/dist/agent/resources/prompts/system-prompt.yml +9 -0
  67. package/dist/agent/resources/tools/expand_knowledge.txt +4 -0
  68. package/dist/agent/resources/tools/search_knowledge.txt +11 -1
  69. package/dist/oclif/commands/curate/index.js +4 -3
  70. package/dist/oclif/commands/curate/view.js +2 -2
  71. package/dist/oclif/commands/main.js +13 -0
  72. package/dist/oclif/commands/query.js +4 -3
  73. package/dist/oclif/commands/source/add.d.ts +12 -0
  74. package/dist/oclif/commands/source/add.js +42 -0
  75. package/dist/oclif/commands/source/index.d.ts +6 -0
  76. package/dist/oclif/commands/source/index.js +8 -0
  77. package/dist/oclif/commands/source/list.d.ts +6 -0
  78. package/dist/oclif/commands/source/list.js +32 -0
  79. package/dist/oclif/commands/source/remove.d.ts +9 -0
  80. package/dist/oclif/commands/source/remove.js +33 -0
  81. package/dist/oclif/commands/status.d.ts +5 -1
  82. package/dist/oclif/commands/status.js +41 -6
  83. package/dist/oclif/commands/worktree/add.d.ts +12 -0
  84. package/dist/oclif/commands/worktree/add.js +44 -0
  85. package/dist/oclif/commands/worktree/index.d.ts +6 -0
  86. package/dist/oclif/commands/worktree/index.js +8 -0
  87. package/dist/oclif/commands/worktree/list.d.ts +6 -0
  88. package/dist/oclif/commands/worktree/list.js +28 -0
  89. package/dist/oclif/commands/worktree/remove.d.ts +9 -0
  90. package/dist/oclif/commands/worktree/remove.js +35 -0
  91. package/dist/oclif/hooks/init/validate-brv-config.js +4 -0
  92. package/dist/oclif/lib/daemon-client.d.ts +4 -2
  93. package/dist/oclif/lib/daemon-client.js +19 -3
  94. package/dist/server/constants.d.ts +8 -0
  95. package/dist/server/constants.js +10 -0
  96. package/dist/server/core/domain/client/client-info.d.ts +7 -0
  97. package/dist/server/core/domain/client/client-info.js +11 -0
  98. package/dist/server/core/domain/knowledge/memory-scoring.d.ts +3 -3
  99. package/dist/server/core/domain/knowledge/memory-scoring.js +5 -5
  100. package/dist/server/core/domain/knowledge/summary-types.d.ts +4 -0
  101. package/dist/server/core/domain/project/worktrees-schema.d.ts +29 -0
  102. package/dist/server/core/domain/project/worktrees-schema.js +17 -0
  103. package/dist/server/core/domain/source/source-operations.d.ts +31 -0
  104. package/dist/server/core/domain/source/source-operations.js +201 -0
  105. package/dist/server/core/domain/source/source-schema.d.ts +94 -0
  106. package/dist/server/core/domain/source/source-schema.js +121 -0
  107. package/dist/server/core/domain/transport/schemas.d.ts +18 -10
  108. package/dist/server/core/domain/transport/schemas.js +4 -0
  109. package/dist/server/core/domain/transport/task-info.d.ts +2 -0
  110. package/dist/server/core/interfaces/client/i-client-manager.d.ts +13 -0
  111. package/dist/server/core/interfaces/executor/i-curate-executor.d.ts +4 -0
  112. package/dist/server/core/interfaces/executor/i-folder-pack-executor.d.ts +7 -3
  113. package/dist/server/core/interfaces/executor/i-query-executor.d.ts +2 -0
  114. package/dist/server/infra/client/client-manager.d.ts +1 -0
  115. package/dist/server/infra/client/client-manager.js +16 -0
  116. package/dist/server/infra/context-tree/derived-artifact.js +5 -1
  117. package/dist/server/infra/context-tree/file-context-tree-manifest-service.d.ts +2 -1
  118. package/dist/server/infra/context-tree/file-context-tree-manifest-service.js +43 -7
  119. package/dist/server/infra/context-tree/file-context-tree-summary-service.js +20 -2
  120. package/dist/server/infra/daemon/agent-process.js +15 -5
  121. package/dist/server/infra/executor/curate-executor.js +6 -3
  122. package/dist/server/infra/executor/direct-search-responder.js +5 -1
  123. package/dist/server/infra/executor/folder-pack-executor.js +88 -7
  124. package/dist/server/infra/executor/query-executor.d.ts +23 -0
  125. package/dist/server/infra/executor/query-executor.js +125 -23
  126. package/dist/server/infra/mcp/mcp-mode-detector.d.ts +7 -5
  127. package/dist/server/infra/mcp/mcp-mode-detector.js +11 -18
  128. package/dist/server/infra/mcp/mcp-server.d.ts +1 -0
  129. package/dist/server/infra/mcp/mcp-server.js +11 -6
  130. package/dist/server/infra/mcp/tools/brv-curate-tool.d.ts +2 -1
  131. package/dist/server/infra/mcp/tools/brv-curate-tool.js +9 -16
  132. package/dist/server/infra/mcp/tools/brv-query-tool.d.ts +2 -1
  133. package/dist/server/infra/mcp/tools/brv-query-tool.js +9 -16
  134. package/dist/server/infra/mcp/tools/mcp-project-context.d.ts +11 -0
  135. package/dist/server/infra/mcp/tools/mcp-project-context.js +54 -0
  136. package/dist/server/infra/process/connection-coordinator.js +11 -0
  137. package/dist/server/infra/process/feature-handlers.js +4 -1
  138. package/dist/server/infra/process/task-router.d.ts +1 -0
  139. package/dist/server/infra/process/task-router.js +60 -5
  140. package/dist/server/infra/project/resolve-project.d.ts +106 -0
  141. package/dist/server/infra/project/resolve-project.js +473 -0
  142. package/dist/server/infra/transport/handlers/index.d.ts +4 -0
  143. package/dist/server/infra/transport/handlers/index.js +2 -0
  144. package/dist/server/infra/transport/handlers/source-handler.d.ts +12 -0
  145. package/dist/server/infra/transport/handlers/source-handler.js +37 -0
  146. package/dist/server/infra/transport/handlers/status-handler.js +65 -13
  147. package/dist/server/infra/transport/handlers/worktree-handler.d.ts +12 -0
  148. package/dist/server/infra/transport/handlers/worktree-handler.js +67 -0
  149. package/dist/server/infra/transport/transport-connector.d.ts +10 -4
  150. package/dist/server/infra/transport/transport-connector.js +2 -2
  151. package/dist/server/utils/curate-result-parser.d.ts +4 -4
  152. package/dist/server/utils/path-utils.d.ts +5 -0
  153. package/dist/server/utils/path-utils.js +11 -1
  154. package/dist/shared/transport/events/client-events.d.ts +3 -0
  155. package/dist/shared/transport/events/client-events.js +3 -0
  156. package/dist/shared/transport/events/index.d.ts +13 -0
  157. package/dist/shared/transport/events/index.js +9 -0
  158. package/dist/shared/transport/events/source-events.d.ts +30 -0
  159. package/dist/shared/transport/events/source-events.js +5 -0
  160. package/dist/shared/transport/events/status-events.d.ts +5 -0
  161. package/dist/shared/transport/events/task-events.d.ts +4 -1
  162. package/dist/shared/transport/events/worktree-events.d.ts +31 -0
  163. package/dist/shared/transport/events/worktree-events.js +5 -0
  164. package/dist/shared/transport/types/dto.d.ts +26 -0
  165. package/dist/tui/features/commands/definitions/index.js +6 -0
  166. package/dist/tui/features/commands/definitions/source-add.d.ts +2 -0
  167. package/dist/tui/features/commands/definitions/source-add.js +48 -0
  168. package/dist/tui/features/commands/definitions/source-list.d.ts +2 -0
  169. package/dist/tui/features/commands/definitions/source-list.js +47 -0
  170. package/dist/tui/features/commands/definitions/source-remove.d.ts +2 -0
  171. package/dist/tui/features/commands/definitions/source-remove.js +38 -0
  172. package/dist/tui/features/commands/definitions/source.d.ts +2 -0
  173. package/dist/tui/features/commands/definitions/source.js +8 -0
  174. package/dist/tui/features/commands/definitions/worktree-add.d.ts +2 -0
  175. package/dist/tui/features/commands/definitions/worktree-add.js +35 -0
  176. package/dist/tui/features/commands/definitions/worktree-list.d.ts +2 -0
  177. package/dist/tui/features/commands/definitions/worktree-list.js +36 -0
  178. package/dist/tui/features/commands/definitions/worktree-remove.d.ts +2 -0
  179. package/dist/tui/features/commands/definitions/worktree-remove.js +33 -0
  180. package/dist/tui/features/commands/definitions/worktree.d.ts +2 -0
  181. package/dist/tui/features/commands/definitions/worktree.js +8 -0
  182. package/dist/tui/features/curate/api/create-curate-task.js +3 -1
  183. package/dist/tui/features/query/api/create-query-task.js +3 -1
  184. package/dist/tui/features/source/api/source-api.d.ts +4 -0
  185. package/dist/tui/features/source/api/source-api.js +22 -0
  186. package/dist/tui/features/status/api/get-status.js +2 -1
  187. package/dist/tui/features/status/utils/format-status.js +23 -1
  188. package/dist/tui/features/transport/components/transport-initializer.js +36 -1
  189. package/dist/tui/features/worktree/api/worktree-api.d.ts +4 -0
  190. package/dist/tui/features/worktree/api/worktree-api.js +22 -0
  191. package/dist/tui/repl-startup.d.ts +2 -0
  192. package/dist/tui/repl-startup.js +5 -3
  193. package/dist/tui/stores/transport-store.d.ts +6 -0
  194. package/dist/tui/stores/transport-store.js +6 -0
  195. package/oclif.manifest.json +261 -1
  196. package/package.json +10 -4
@@ -1,6 +1,6 @@
1
1
  import { Command, Flags } from '@oclif/core';
2
2
  import chalk from 'chalk';
3
- import { StatusEvents } from '../../shared/transport/events/status-events.js';
3
+ import { StatusEvents, } from '../../shared/transport/events/status-events.js';
4
4
  import { formatConnectionError, withDaemonRetry } from '../lib/daemon-client.js';
5
5
  import { writeJsonResponse } from '../lib/json-response.js';
6
6
  export default class Status extends Command {
@@ -13,18 +13,29 @@ export default class Status extends Command {
13
13
  description: 'Output format',
14
14
  options: ['text', 'json'],
15
15
  }),
16
+ 'project-root': Flags.string({
17
+ description: 'Explicit project root path (overrides auto-detection)',
18
+ required: false,
19
+ }),
20
+ verbose: Flags.boolean({
21
+ char: 'v',
22
+ default: false,
23
+ description: 'Show resolution source and diagnostic info',
24
+ }),
16
25
  };
17
26
  async fetchStatus(options) {
27
+ const request = { cwd: process.cwd(), projectRootFlag: options?.projectRootFlag };
18
28
  return withDaemonRetry(async (client) => {
19
- const response = await client.requestWithAck(StatusEvents.GET);
29
+ const response = await client.requestWithAck(StatusEvents.GET, request);
20
30
  return response.status;
21
31
  }, options);
22
32
  }
23
33
  async run() {
24
34
  const { flags } = await this.parse(Status);
35
+ const projectRootFlag = flags['project-root'];
25
36
  const isJson = flags.format === 'json';
26
37
  try {
27
- const status = await this.fetchStatus({ projectPath: process.cwd() });
38
+ const status = await this.fetchStatus({ projectPath: process.cwd(), projectRootFlag });
28
39
  if (isJson) {
29
40
  writeJsonResponse({
30
41
  command: 'status',
@@ -33,7 +44,7 @@ export default class Status extends Command {
33
44
  });
34
45
  }
35
46
  else {
36
- this.formatTextOutput(status);
47
+ this.formatTextOutput(status, flags.verbose);
37
48
  this.logVcHint();
38
49
  }
39
50
  }
@@ -51,7 +62,7 @@ export default class Status extends Command {
51
62
  }
52
63
  }
53
64
  }
54
- formatTextOutput(status) {
65
+ formatTextOutput(status, verbose = false) {
55
66
  this.log(`CLI Version: ${this.config.version}`);
56
67
  // Auth status (cloud sync only — not required for local usage)
57
68
  switch (status.authStatus) {
@@ -71,7 +82,31 @@ export default class Status extends Command {
71
82
  this.log('Account: Unable to check');
72
83
  }
73
84
  }
74
- this.log(`Current Directory: ${status.currentDirectory}`);
85
+ this.log(`Project: ${status.projectRoot ?? status.currentDirectory}`);
86
+ if (status.worktreeRoot && status.worktreeRoot !== status.projectRoot) {
87
+ this.log(`Worktree: ${status.worktreeRoot} (linked)`);
88
+ }
89
+ if (status.resolverError) {
90
+ this.log(chalk.yellow(`⚠ ${status.resolverError}`));
91
+ }
92
+ if (verbose && status.resolutionSource) {
93
+ this.log(`Resolution: ${status.resolutionSource}`);
94
+ }
95
+ // Knowledge sources
96
+ if (status.sourcesError) {
97
+ this.log(chalk.yellow(`⚠ ${status.sourcesError}`));
98
+ }
99
+ else if (status.sources && status.sources.length > 0) {
100
+ this.log('Knowledge Sources:');
101
+ for (const source of status.sources) {
102
+ if (source.valid) {
103
+ this.log(` ${source.alias} → ${source.projectRoot} ${chalk.green('(valid)')}`);
104
+ }
105
+ else {
106
+ this.log(` ${source.alias} → ${source.projectRoot} ${chalk.red(`[BROKEN - run brv source remove ${source.alias}]`)}`);
107
+ }
108
+ }
109
+ }
75
110
  // Space
76
111
  if (status.teamName && status.spaceName) {
77
112
  this.log(`Space: ${status.teamName}/${status.spaceName}`);
@@ -0,0 +1,12 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class WorktreeAdd extends Command {
3
+ static args: {
4
+ path: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,44 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { resolve } from 'node:path';
3
+ import { WorktreeEvents } from '../../../shared/transport/events/worktree-events.js';
4
+ import { formatConnectionError, withDaemonRetry } from '../../lib/daemon-client.js';
5
+ export default class WorktreeAdd extends Command {
6
+ static args = {
7
+ path: Args.string({
8
+ description: 'Path to the directory to register as a worktree (relative or absolute)',
9
+ required: false,
10
+ }),
11
+ };
12
+ static description = 'Register a directory as a worktree of this project';
13
+ static examples = [
14
+ '<%= config.bin %> <%= command.id %> packages/api',
15
+ '<%= config.bin %> <%= command.id %> ../other-checkout',
16
+ '<%= config.bin %> <%= command.id %> (auto-detect parent from subdirectory)',
17
+ ];
18
+ static flags = {
19
+ force: Flags.boolean({
20
+ default: false,
21
+ description: 'Replace existing .brv/ directory in target with a worktree pointer',
22
+ }),
23
+ };
24
+ async run() {
25
+ const { args, flags } = await this.parse(WorktreeAdd);
26
+ const cwd = resolve(process.cwd());
27
+ const worktreePath = args.path ? resolve(args.path) : cwd;
28
+ try {
29
+ const result = await withDaemonRetry(async (client) => client.requestWithAck(WorktreeEvents.ADD, {
30
+ force: flags.force,
31
+ worktreePath,
32
+ }), { projectPath: cwd });
33
+ if (result.success) {
34
+ this.log(result.message);
35
+ }
36
+ else {
37
+ this.error(result.message, { exit: 1 });
38
+ }
39
+ }
40
+ catch (error) {
41
+ this.error(formatConnectionError(error), { exit: 1 });
42
+ }
43
+ }
44
+ }
@@ -0,0 +1,6 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class Worktree extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ run(): Promise<void>;
6
+ }
@@ -0,0 +1,8 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class Worktree extends Command {
3
+ static description = 'Manage worktree links for subdirectories and sibling checkouts';
4
+ static examples = ['<%= config.bin %> <%= command.id %> --help'];
5
+ async run() {
6
+ await this.config.runCommand('help', ['worktree']);
7
+ }
8
+ }
@@ -0,0 +1,6 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class WorktreeList extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ run(): Promise<void>;
6
+ }
@@ -0,0 +1,28 @@
1
+ import { Command } from '@oclif/core';
2
+ import { WorktreeEvents } from '../../../shared/transport/events/worktree-events.js';
3
+ import { formatConnectionError, withDaemonRetry } from '../../lib/daemon-client.js';
4
+ export default class WorktreeList extends Command {
5
+ static description = 'Show the current worktree link and list all registered worktrees';
6
+ static examples = ['<%= config.bin %> <%= command.id %>'];
7
+ async run() {
8
+ try {
9
+ const result = await withDaemonRetry(async (client) => client.requestWithAck(WorktreeEvents.LIST), { projectPath: process.cwd() });
10
+ if (result.source === 'linked') {
11
+ this.log(`Worktree: ${result.worktreeRoot}`);
12
+ this.log(`Linked to: ${result.projectRoot}`);
13
+ }
14
+ else {
15
+ this.log(`Project: ${result.projectRoot}`);
16
+ }
17
+ if (result.worktrees.length > 0) {
18
+ this.log('\nRegistered worktrees:');
19
+ for (const wt of result.worktrees) {
20
+ this.log(` ${wt.name} → ${wt.worktreePath}`);
21
+ }
22
+ }
23
+ }
24
+ catch (error) {
25
+ this.error(formatConnectionError(error), { exit: 1 });
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,9 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class WorktreeRemove extends Command {
3
+ static args: {
4
+ path: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ run(): Promise<void>;
9
+ }
@@ -0,0 +1,35 @@
1
+ import { Args, Command } from '@oclif/core';
2
+ import { resolve } from 'node:path';
3
+ import { WorktreeEvents } from '../../../shared/transport/events/worktree-events.js';
4
+ import { formatConnectionError, withDaemonRetry } from '../../lib/daemon-client.js';
5
+ export default class WorktreeRemove extends Command {
6
+ static args = {
7
+ path: Args.string({
8
+ description: 'Path to the worktree to remove (defaults to cwd)',
9
+ required: false,
10
+ }),
11
+ };
12
+ static description = 'Remove a worktree registration and its .brv pointer';
13
+ static examples = [
14
+ '<%= config.bin %> <%= command.id %> (remove cwd as worktree)',
15
+ '<%= config.bin %> <%= command.id %> packages/api (remove from parent)',
16
+ ];
17
+ async run() {
18
+ const { args } = await this.parse(WorktreeRemove);
19
+ const targetPath = args.path ? resolve(args.path) : resolve(process.cwd());
20
+ try {
21
+ const result = await withDaemonRetry(async (client) => client.requestWithAck(WorktreeEvents.REMOVE, {
22
+ worktreePath: targetPath,
23
+ }), { projectPath: process.cwd() });
24
+ if (result.success) {
25
+ this.log(result.message);
26
+ }
27
+ else {
28
+ this.error(result.message, { exit: 1 });
29
+ }
30
+ }
31
+ catch (error) {
32
+ this.error(formatConnectionError(error), { exit: 1 });
33
+ }
34
+ }
35
+ }
@@ -2,6 +2,7 @@ import { BRV_CONFIG_VERSION } from '../../../server/constants.js';
2
2
  import { ensureProjectInitialized } from '../../../server/infra/config/auto-init.js';
3
3
  import { ProjectConfigStore } from '../../../server/infra/config/file-config-store.js';
4
4
  import { FileContextTreeService } from '../../../server/infra/context-tree/file-context-tree-service.js';
5
+ import { isWorktreePointer } from '../../../server/infra/project/resolve-project.js';
5
6
  import { syncConfigToXdg } from '../../../server/utils/config-xdg-sync.js';
6
7
  /**
7
8
  * Commands that should skip auto-init and config version validation.
@@ -22,6 +23,9 @@ const HELP_FLAGS = new Set(['--h', '--help', '-h', '-help']);
22
23
  export const validateBrvConfigVersion = async (commandId, configStore, argv = [], autoInitDeps) => {
23
24
  if (argv.some((arg) => HELP_FLAGS.has(arg)))
24
25
  return;
26
+ // Skip auto-init if .brv is a pointer file (worktree) — the project lives elsewhere
27
+ if (isWorktreePointer(process.cwd()))
28
+ return;
25
29
  const exists = await configStore.exists();
26
30
  if (!exists && COMMANDS_NEED_AUTO_INIT.has(commandId)) {
27
31
  const deps = autoInitDeps ?? {
@@ -5,6 +5,8 @@ export interface DaemonClientOptions {
5
5
  maxRetries?: number;
6
6
  /** Explicit project path — bypasses walk-up discovery. Use for `init` where .brv/ doesn't exist yet. */
7
7
  projectPath?: string;
8
+ /** Explicit --project-root flag value to override auto-detection */
9
+ projectRootFlag?: string;
8
10
  /** Delay between retries in ms. Default: 2000. Set to 0 in tests. */
9
11
  retryDelayMs?: number;
10
12
  /** Optional transport connector for DI/testing */
@@ -13,14 +15,14 @@ export interface DaemonClientOptions {
13
15
  /**
14
16
  * Connects to the daemon, auto-starting it if needed.
15
17
  */
16
- export declare function connectToDaemonClient(options?: Pick<DaemonClientOptions, 'transportConnector'>): Promise<ConnectionResult>;
18
+ export declare function connectToDaemonClient(options?: Pick<DaemonClientOptions, 'projectRootFlag' | 'transportConnector'>): Promise<ConnectionResult>;
17
19
  /**
18
20
  * Executes an operation against the daemon with retry logic.
19
21
  *
20
22
  * Retries on infrastructure failures (daemon spawn timeout, connection dropped,
21
23
  * agent disconnected). Does NOT retry on business errors (auth, validation, etc.).
22
24
  */
23
- export declare function withDaemonRetry<T>(fn: (client: ITransportClient, projectRoot?: string) => Promise<T>, options?: DaemonClientOptions & {
25
+ export declare function withDaemonRetry<T>(fn: (client: ITransportClient, projectRoot?: string, worktreeRoot?: string) => Promise<T>, options?: DaemonClientOptions & {
24
26
  /** Called before each retry with attempt number (1-indexed) */
25
27
  onRetry?: (attempt: number, maxRetries: number) => void;
26
28
  }): Promise<T>;
@@ -1,5 +1,6 @@
1
1
  import { ConnectionError, ConnectionFailedError, DaemonSpawnError, InstanceCrashedError, NoInstanceRunningError, TransportRequestError, TransportRequestTimeoutError, } from '@campfirein/brv-transport-client';
2
2
  import { TaskErrorCode } from '../../server/core/domain/errors/task-error.js';
3
+ import { resolveProject } from '../../server/infra/project/resolve-project.js';
3
4
  import { createDaemonAwareConnector } from '../../server/infra/transport/transport-connector.js';
4
5
  import { getSandboxEnvironmentName, isSandboxEnvironment, isSandboxNetworkError, } from '../../server/utils/sandbox-detector.js';
5
6
  import { VcErrorCode } from '../../shared/transport/events/vc-events.js';
@@ -34,12 +35,22 @@ const USER_FRIENDLY_MESSAGES = {
34
35
  // UNCOMMITTED_CHANGES intentionally omitted: fall through to server's detailed message with file paths
35
36
  // USER_NOT_CONFIGURED intentionally omitted: fall through to server's specific hint with actual values
36
37
  };
38
+ function resolveRequiredProjectPath(projectRootFlag) {
39
+ const resolution = resolveProject({ projectRootFlag });
40
+ if (!resolution) {
41
+ // No .brv found at cwd — fall back to cwd. The daemon will auto-init .brv/ on first connection.
42
+ const cwd = process.cwd();
43
+ return { projectRoot: cwd, worktreeRoot: cwd };
44
+ }
45
+ return resolution;
46
+ }
37
47
  /**
38
48
  * Connects to the daemon, auto-starting it if needed.
39
49
  */
40
50
  export async function connectToDaemonClient(options) {
41
51
  const connector = options?.transportConnector ?? createDaemonAwareConnector();
42
- return connector();
52
+ const resolution = resolveRequiredProjectPath(options?.projectRootFlag);
53
+ return connector(undefined, resolution.projectRoot);
43
54
  }
44
55
  /**
45
56
  * Executes an operation against the daemon with retry logic.
@@ -51,14 +62,19 @@ export async function withDaemonRetry(fn, options) {
51
62
  const maxRetries = options?.maxRetries ?? MAX_RETRIES;
52
63
  const retryDelayMs = options?.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
53
64
  const connector = options?.transportConnector ?? createDaemonAwareConnector(options?.projectPath);
65
+ // Pre-resolve project (workspace-link-aware) so the connector registers
66
+ // with the correct projectPath and callers get the resolved worktreeRoot.
67
+ const resolution = resolveRequiredProjectPath(options?.projectRootFlag);
68
+ const resolvedProjectPath = resolution.projectRoot;
69
+ const resolvedWorkspaceRoot = resolution.worktreeRoot;
54
70
  let lastError;
55
71
  /* eslint-disable no-await-in-loop -- intentional sequential retry loop */
56
72
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
57
73
  let client;
58
74
  try {
59
- const { client: connectedClient, projectRoot } = await connector();
75
+ const { client: connectedClient, projectRoot } = await connector(undefined, resolvedProjectPath);
60
76
  client = connectedClient;
61
- const value = await fn(client, projectRoot);
77
+ const value = await fn(client, projectRoot ?? resolvedProjectPath, resolvedWorkspaceRoot);
62
78
  await client.disconnect().catch(() => { });
63
79
  return value;
64
80
  }
@@ -1,6 +1,12 @@
1
1
  export declare const BRV_DIR = ".brv";
2
2
  export declare const PROJECT_CONFIG_FILE = "config.json";
3
3
  export declare const BRV_CONFIG_VERSION = "0.0.1";
4
+ export declare const WORKTREES_DIR = "worktrees";
5
+ export declare const WORKTREE_LINK_METADATA = "link.json";
6
+ export declare const SOURCES_FILE = "sources.json";
7
+ export declare const SHARED_SOURCE_LOCAL_SCORE_BOOST = 0.1;
8
+ export declare const MCP_ASSOCIATE_PROJECT_TIMEOUT_MS = 3000;
9
+ export declare const MCP_ASSOCIATE_PROJECT_MAX_ATTEMPTS = 2;
4
10
  export declare const GLOBAL_CONFIG_DIR = "brv";
5
11
  export declare const GLOBAL_CONFIG_FILE = "config.json";
6
12
  export declare const GLOBAL_CONFIG_VERSION = "0.0.1";
@@ -55,6 +61,8 @@ export declare const SUMMARY_INDEX_FILE = "_index.md";
55
61
  export declare const ARCHIVE_DIR = "_archived";
56
62
  export declare const STUB_EXTENSION = ".stub.md";
57
63
  export declare const FULL_ARCHIVE_EXTENSION = ".full.md";
64
+ export declare const ABSTRACT_EXTENSION = ".abstract.md";
65
+ export declare const OVERVIEW_EXTENSION = ".overview.md";
58
66
  export declare const MANIFEST_FILE = "_manifest.json";
59
67
  export declare const ARCHIVE_IMPORTANCE_THRESHOLD = 35;
60
68
  export declare const DEFAULT_GHOST_CUE_MAX_TOKENS = 220;
@@ -1,6 +1,14 @@
1
1
  export const BRV_DIR = '.brv';
2
2
  export const PROJECT_CONFIG_FILE = 'config.json';
3
3
  export const BRV_CONFIG_VERSION = '0.0.1';
4
+ // Worktree linking (git-style: .brv is a file pointing to parent project)
5
+ export const WORKTREES_DIR = 'worktrees';
6
+ export const WORKTREE_LINK_METADATA = 'link.json';
7
+ // Knowledge sources (read-only references to other projects)
8
+ export const SOURCES_FILE = 'sources.json';
9
+ export const SHARED_SOURCE_LOCAL_SCORE_BOOST = 0.1;
10
+ export const MCP_ASSOCIATE_PROJECT_TIMEOUT_MS = 3000;
11
+ export const MCP_ASSOCIATE_PROJECT_MAX_ATTEMPTS = 2;
4
12
  // Global config constants (user-level, stored in XDG config directory)
5
13
  export const GLOBAL_CONFIG_DIR = 'brv';
6
14
  export const GLOBAL_CONFIG_FILE = 'config.json';
@@ -75,6 +83,8 @@ export const SUMMARY_INDEX_FILE = '_index.md';
75
83
  export const ARCHIVE_DIR = '_archived';
76
84
  export const STUB_EXTENSION = '.stub.md';
77
85
  export const FULL_ARCHIVE_EXTENSION = '.full.md';
86
+ export const ABSTRACT_EXTENSION = '.abstract.md';
87
+ export const OVERVIEW_EXTENSION = '.overview.md';
78
88
  export const MANIFEST_FILE = '_manifest.json';
79
89
  export const ARCHIVE_IMPORTANCE_THRESHOLD = 35;
80
90
  export const DEFAULT_GHOST_CUE_MAX_TOKENS = 220;
@@ -78,5 +78,12 @@ export declare class ClientInfo {
78
78
  * Called after MCP initialize handshake provides clientInfo.
79
79
  */
80
80
  setAgentName(agentName: string): void;
81
+ /**
82
+ * Update this client's project path, even if already associated.
83
+ * Used for reassociation after worktree add/remove operations.
84
+ *
85
+ * @returns The previous project path (undefined if not previously associated)
86
+ */
87
+ updateProjectPath(projectPath: string): string | undefined;
81
88
  }
82
89
  export {};
@@ -84,4 +84,15 @@ export class ClientInfo {
84
84
  setAgentName(agentName) {
85
85
  this._agentName = agentName;
86
86
  }
87
+ /**
88
+ * Update this client's project path, even if already associated.
89
+ * Used for reassociation after worktree add/remove operations.
90
+ *
91
+ * @returns The previous project path (undefined if not previously associated)
92
+ */
93
+ updateProjectPath(projectPath) {
94
+ const oldPath = this._projectPath;
95
+ this._projectPath = projectPath;
96
+ return oldPath;
97
+ }
87
98
  }
@@ -19,11 +19,11 @@ export declare const ACCESS_IMPORTANCE_BONUS = 3;
19
19
  /** Importance bonus per curate update */
20
20
  export declare const UPDATE_IMPORTANCE_BONUS = 5;
21
21
  /** BM25 relevance weight in compound score */
22
- export declare const W_RELEVANCE = 1;
22
+ export declare const W_RELEVANCE = 0.6;
23
23
  /** Importance weight in compound score */
24
- export declare const W_IMPORTANCE = 0;
24
+ export declare const W_IMPORTANCE = 0.2;
25
25
  /** Recency weight in compound score */
26
- export declare const W_RECENCY = 0;
26
+ export declare const W_RECENCY = 0.2;
27
27
  /** Importance threshold to promote draft -> validated */
28
28
  export declare const PROMOTE_TO_VALIDATED = 65;
29
29
  /** Importance threshold to promote validated -> core */
@@ -21,11 +21,11 @@ export const ACCESS_IMPORTANCE_BONUS = 3;
21
21
  /** Importance bonus per curate update */
22
22
  export const UPDATE_IMPORTANCE_BONUS = 5;
23
23
  /** BM25 relevance weight in compound score */
24
- export const W_RELEVANCE = 1;
24
+ export const W_RELEVANCE = 0.6;
25
25
  /** Importance weight in compound score */
26
- export const W_IMPORTANCE = 0;
26
+ export const W_IMPORTANCE = 0.2;
27
27
  /** Recency weight in compound score */
28
- export const W_RECENCY = 0;
28
+ export const W_RECENCY = 0.2;
29
29
  /** Importance threshold to promote draft -> validated */
30
30
  export const PROMOTE_TO_VALIDATED = 65;
31
31
  /** Importance threshold to promote validated -> core */
@@ -36,8 +36,8 @@ export const DEMOTE_FROM_CORE = 60;
36
36
  export const DEMOTE_FROM_VALIDATED = 35;
37
37
  /** Search score multiplier per maturity tier */
38
38
  export const TIER_BOOST = {
39
- core: 1,
40
- draft: 1,
39
+ core: 1.15,
40
+ draft: 0.85,
41
41
  validated: 1,
42
42
  };
43
43
  // ---------------------------------------------------------------------------
@@ -41,6 +41,10 @@ export interface ArchiveStubFrontmatter {
41
41
  type: 'archive_stub';
42
42
  }
43
43
  export interface ManifestEntry {
44
+ /** Relative path to .abstract.md sibling, if it exists */
45
+ abstractPath?: string;
46
+ /** Token count of .abstract.md (used for lane budgeting) */
47
+ abstractTokens?: number;
44
48
  /** Importance score from frontmatter (0-100, default 50) */
45
49
  importance?: number;
46
50
  /** Condensation order (only for summaries) */
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Schema for the `.brv` pointer file (when .brv is a FILE, not a directory).
4
+ * Like git's `.git` file in worktrees: contains a single `projectRoot` field
5
+ * pointing to the parent project's absolute path.
6
+ */
7
+ export declare const WorktreePointerSchema: z.ZodObject<{
8
+ projectRoot: z.ZodString;
9
+ }, "strip", z.ZodTypeAny, {
10
+ projectRoot: string;
11
+ }, {
12
+ projectRoot: string;
13
+ }>;
14
+ export type WorktreePointer = z.infer<typeof WorktreePointerSchema>;
15
+ /**
16
+ * Schema for `.brv/worktrees/<name>/link.json` — metadata about a registered worktree.
17
+ * Stored in the parent project's `.brv/worktrees/` directory (like `.git/worktrees/`).
18
+ */
19
+ export declare const WorktreeLinkMetadataSchema: z.ZodObject<{
20
+ addedAt: z.ZodOptional<z.ZodString>;
21
+ worktreePath: z.ZodString;
22
+ }, "strip", z.ZodTypeAny, {
23
+ worktreePath: string;
24
+ addedAt?: string | undefined;
25
+ }, {
26
+ worktreePath: string;
27
+ addedAt?: string | undefined;
28
+ }>;
29
+ export type WorktreeLinkMetadata = z.infer<typeof WorktreeLinkMetadataSchema>;
@@ -0,0 +1,17 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Schema for the `.brv` pointer file (when .brv is a FILE, not a directory).
4
+ * Like git's `.git` file in worktrees: contains a single `projectRoot` field
5
+ * pointing to the parent project's absolute path.
6
+ */
7
+ export const WorktreePointerSchema = z.object({
8
+ projectRoot: z.string().min(1),
9
+ });
10
+ /**
11
+ * Schema for `.brv/worktrees/<name>/link.json` — metadata about a registered worktree.
12
+ * Stored in the parent project's `.brv/worktrees/` directory (like `.git/worktrees/`).
13
+ */
14
+ export const WorktreeLinkMetadataSchema = z.object({
15
+ addedAt: z.string().optional(),
16
+ worktreePath: z.string().min(1),
17
+ });
@@ -0,0 +1,31 @@
1
+ import { type SourceStatus } from './source-schema.js';
2
+ export interface OperationResult {
3
+ message: string;
4
+ success: boolean;
5
+ }
6
+ /**
7
+ * Adds a read-only knowledge source from another project's context tree.
8
+ *
9
+ * Validates: target is a brv project, not self, not duplicate, not circular.
10
+ * Writes to `.brv/sources.json`.
11
+ */
12
+ export declare function addSource(projectRoot: string, targetPath: string, alias?: string): OperationResult;
13
+ /**
14
+ * Removes a knowledge source by alias or path.
15
+ */
16
+ export declare function removeSource(projectRoot: string, aliasOrPath: string): OperationResult;
17
+ export interface ListSourcesResult {
18
+ error?: string;
19
+ statuses: SourceStatus[];
20
+ }
21
+ /**
22
+ * Returns status for all sources in the project.
23
+ * Surfaces malformed file errors instead of silently returning empty.
24
+ */
25
+ export declare function listSourceStatuses(projectRoot: string): ListSourcesResult;
26
+ /**
27
+ * Checks if adding projectRoot → targetRoot would create a circular dependency.
28
+ * A circular reference exists if the target project already has a source pointing
29
+ * back to the current project (direct cycle only — no transitive check in v1).
30
+ */
31
+ export declare function detectCircularSource(projectRoot: string, targetRoot: string): boolean;