@arkhera30/cli 0.8.0 → 0.8.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/dist/index.js CHANGED
@@ -1,4 +1,1155 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire as __horusCreateRequire } from 'module'; const require = __horusCreateRequire(import.meta.url);
3
+ import {
4
+ __commonJS,
5
+ __require,
6
+ __toESM,
7
+ require_claude_code_strategy,
8
+ require_claude_md_writer,
9
+ require_compiler,
10
+ require_composite_adapter,
11
+ require_core,
12
+ require_cursor_strategy,
13
+ require_errors,
14
+ require_filesystem_adapter,
15
+ require_forge_search_client,
16
+ require_global_claude_code_strategy,
17
+ require_global_config_loader,
18
+ require_http_adapter,
19
+ require_local_repo_state,
20
+ require_mcp_settings_writer,
21
+ require_merge_workspace_configs,
22
+ require_models,
23
+ require_path_utils,
24
+ require_registry,
25
+ require_repo_develop,
26
+ require_repo_errors,
27
+ require_repo_index_query,
28
+ require_repo_index_store,
29
+ require_repo_registry_client,
30
+ require_repo_scanner,
31
+ require_resolver,
32
+ require_session_cleanup,
33
+ require_session_list,
34
+ require_session_store,
35
+ require_url_utils,
36
+ require_workspace_creator,
37
+ require_workspace_lifecycle,
38
+ require_workspace_manager,
39
+ require_workspace_metadata_store
40
+ } from "./chunk-6ROWQWZM.js";
41
+
42
+ // ../forge/packages/core/dist/adapters/git-adapter.js
43
+ var require_git_adapter = __commonJS({
44
+ "../forge/packages/core/dist/adapters/git-adapter.js"(exports) {
45
+ "use strict";
46
+ var __importDefault = exports && exports.__importDefault || function(mod) {
47
+ return mod && mod.__esModule ? mod : { "default": mod };
48
+ };
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ exports.GitAdapter = void 0;
51
+ var child_process_1 = __require("child_process");
52
+ var util_1 = __require("util");
53
+ var crypto_1 = __require("crypto");
54
+ var fs_1 = __require("fs");
55
+ var path_1 = __importDefault(__require("path"));
56
+ var os_1 = __importDefault(__require("os"));
57
+ var filesystem_adapter_js_1 = require_filesystem_adapter();
58
+ var errors_js_1 = require_errors();
59
+ var execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
60
+ var GitAdapter = class {
61
+ url;
62
+ ref;
63
+ registryPath;
64
+ sparse;
65
+ cacheDir;
66
+ tokenEnv;
67
+ delegate = null;
68
+ synced = false;
69
+ constructor(config) {
70
+ this.url = config.url;
71
+ this.ref = config.ref ?? "main";
72
+ this.registryPath = config.registryPath ?? "registry";
73
+ this.sparse = config.sparse;
74
+ this.tokenEnv = config.tokenEnv;
75
+ const baseCache = config.cacheDir ?? path_1.default.join(os_1.default.homedir(), ".forge", "cache", "git");
76
+ const repoHash = (0, crypto_1.createHash)("sha256").update(this.url).digest("hex").slice(0, 12);
77
+ this.cacheDir = path_1.default.join(baseCache, repoHash);
78
+ }
79
+ /**
80
+ * Returns the local cache directory path for this adapter.
81
+ * Useful for debugging and testing.
82
+ */
83
+ getCacheDir() {
84
+ return this.cacheDir;
85
+ }
86
+ // ---------------------------------------------------------------------------
87
+ // DataAdapter interface
88
+ // ---------------------------------------------------------------------------
89
+ async list(type) {
90
+ const delegate = await this.ensureCloned();
91
+ return delegate.list(type);
92
+ }
93
+ async read(type, id) {
94
+ const delegate = await this.ensureCloned();
95
+ return delegate.read(type, id);
96
+ }
97
+ async exists(type, id) {
98
+ const delegate = await this.ensureCloned();
99
+ return delegate.exists(type, id);
100
+ }
101
+ async write(type, id, bundle) {
102
+ const delegate = await this.ensureCloned();
103
+ return delegate.write(type, id, bundle);
104
+ }
105
+ async readResourceFile(type, id, relativePath) {
106
+ const delegate = await this.ensureCloned();
107
+ return delegate.readResourceFile(type, id, relativePath);
108
+ }
109
+ /**
110
+ * List all available semver versions for a specific artifact.
111
+ * Delegates to the underlying FilesystemAdapter's listVersions.
112
+ * Returns versions sorted descending (highest first).
113
+ * Returns empty array for flat layout artifacts or nonexistent artifacts.
114
+ */
115
+ async listVersions(type, id) {
116
+ const delegate = await this.ensureCloned();
117
+ return delegate.listVersions(type, id);
118
+ }
119
+ // ---------------------------------------------------------------------------
120
+ // Git operations
121
+ // ---------------------------------------------------------------------------
122
+ /**
123
+ * Ensure the repo is cloned/updated and return the FilesystemAdapter delegate.
124
+ */
125
+ async ensureCloned() {
126
+ if (this.delegate && this.synced) {
127
+ return this.delegate;
128
+ }
129
+ const exists = await this.cacheExists();
130
+ if (exists) {
131
+ await this.fetchAndCheckout();
132
+ } else {
133
+ await this.cloneRepo();
134
+ }
135
+ const registryRoot = path_1.default.join(this.cacheDir, this.registryPath);
136
+ this.delegate = new filesystem_adapter_js_1.FilesystemAdapter(registryRoot);
137
+ this.synced = true;
138
+ return this.delegate;
139
+ }
140
+ async cacheExists() {
141
+ try {
142
+ await fs_1.promises.access(path_1.default.join(this.cacheDir, ".git"));
143
+ return true;
144
+ } catch {
145
+ return false;
146
+ }
147
+ }
148
+ resolveUrl() {
149
+ if (!this.tokenEnv)
150
+ return this.url;
151
+ const token = process.env[this.tokenEnv];
152
+ if (!token) {
153
+ console.warn(`[GitAdapter] Token env var '${this.tokenEnv}' is not set. Falling back to unauthenticated access.`);
154
+ return this.url;
155
+ }
156
+ try {
157
+ const parsed = new URL(this.url);
158
+ parsed.username = token;
159
+ return parsed.toString();
160
+ } catch {
161
+ return this.url;
162
+ }
163
+ }
164
+ async cloneRepo() {
165
+ await fs_1.promises.mkdir(this.cacheDir, { recursive: true });
166
+ const cloneUrl = this.resolveUrl();
167
+ const args = ["clone", "--depth", "1", "--branch", this.ref, "--single-branch"];
168
+ if (this.sparse && this.sparse.length > 0) {
169
+ args.push("--sparse");
170
+ }
171
+ args.push(cloneUrl, this.cacheDir);
172
+ try {
173
+ await this.git(args, path_1.default.dirname(this.cacheDir));
174
+ } catch (err) {
175
+ throw new errors_js_1.AdapterError("GitAdapter", `Clone failed for ${this.url}: ${err.message}`, `Check that the URL is correct and you have access. If using HTTPS, set the tokenEnv config.`);
176
+ }
177
+ if (this.sparse && this.sparse.length > 0) {
178
+ try {
179
+ await this.git(["sparse-checkout", "set", ...this.sparse], this.cacheDir);
180
+ } catch (err) {
181
+ throw new errors_js_1.AdapterError("GitAdapter", `Sparse checkout config failed: ${err.message}`, `Check that the sparse paths are valid directories in the repository.`);
182
+ }
183
+ }
184
+ }
185
+ async fetchAndCheckout() {
186
+ try {
187
+ await this.git(["fetch", "--depth", "1", "origin", this.ref], this.cacheDir);
188
+ await this.git(["checkout", "FETCH_HEAD"], this.cacheDir);
189
+ } catch (err) {
190
+ throw new errors_js_1.AdapterError("GitAdapter", `Fetch/checkout failed for ${this.url} ref=${this.ref}: ${err.message}`, `Check that the ref '${this.ref}' exists in the repository and that you have network access.`);
191
+ }
192
+ }
193
+ async git(args, cwd) {
194
+ const { stdout } = await execFileAsync("git", args, {
195
+ cwd,
196
+ timeout: 3e4,
197
+ maxBuffer: 10 * 1024 * 1024
198
+ // 10MB
199
+ });
200
+ return stdout;
201
+ }
202
+ };
203
+ exports.GitAdapter = GitAdapter;
204
+ }
205
+ });
206
+
207
+ // ../forge/packages/core/dist/adapters/index.js
208
+ var require_adapters = __commonJS({
209
+ "../forge/packages/core/dist/adapters/index.js"(exports) {
210
+ "use strict";
211
+ Object.defineProperty(exports, "__esModule", { value: true });
212
+ exports.HttpAdapter = exports.GitAdapter = exports.CompositeAdapter = exports.FilesystemAdapter = exports.ForgeCoreVersionMismatchError = exports.PreUploadValidationError = exports.PublishValidationError = exports.PublishPushError = exports.PublishAuthError = exports.VersionConflictError = exports.AllAdaptersFailedError = exports.AdapterError = exports.UnsupportedTargetError = exports.VersionMismatchError = exports.CircularDependencyError = exports.InvalidMetadataError = exports.ArtifactNotFoundError = exports.ForgeError = void 0;
213
+ var errors_js_1 = require_errors();
214
+ Object.defineProperty(exports, "ForgeError", { enumerable: true, get: function() {
215
+ return errors_js_1.ForgeError;
216
+ } });
217
+ Object.defineProperty(exports, "ArtifactNotFoundError", { enumerable: true, get: function() {
218
+ return errors_js_1.ArtifactNotFoundError;
219
+ } });
220
+ Object.defineProperty(exports, "InvalidMetadataError", { enumerable: true, get: function() {
221
+ return errors_js_1.InvalidMetadataError;
222
+ } });
223
+ Object.defineProperty(exports, "CircularDependencyError", { enumerable: true, get: function() {
224
+ return errors_js_1.CircularDependencyError;
225
+ } });
226
+ Object.defineProperty(exports, "VersionMismatchError", { enumerable: true, get: function() {
227
+ return errors_js_1.VersionMismatchError;
228
+ } });
229
+ Object.defineProperty(exports, "UnsupportedTargetError", { enumerable: true, get: function() {
230
+ return errors_js_1.UnsupportedTargetError;
231
+ } });
232
+ Object.defineProperty(exports, "AdapterError", { enumerable: true, get: function() {
233
+ return errors_js_1.AdapterError;
234
+ } });
235
+ Object.defineProperty(exports, "AllAdaptersFailedError", { enumerable: true, get: function() {
236
+ return errors_js_1.AllAdaptersFailedError;
237
+ } });
238
+ Object.defineProperty(exports, "VersionConflictError", { enumerable: true, get: function() {
239
+ return errors_js_1.VersionConflictError;
240
+ } });
241
+ Object.defineProperty(exports, "PublishAuthError", { enumerable: true, get: function() {
242
+ return errors_js_1.PublishAuthError;
243
+ } });
244
+ Object.defineProperty(exports, "PublishPushError", { enumerable: true, get: function() {
245
+ return errors_js_1.PublishPushError;
246
+ } });
247
+ Object.defineProperty(exports, "PublishValidationError", { enumerable: true, get: function() {
248
+ return errors_js_1.PublishValidationError;
249
+ } });
250
+ Object.defineProperty(exports, "PreUploadValidationError", { enumerable: true, get: function() {
251
+ return errors_js_1.PreUploadValidationError;
252
+ } });
253
+ Object.defineProperty(exports, "ForgeCoreVersionMismatchError", { enumerable: true, get: function() {
254
+ return errors_js_1.ForgeCoreVersionMismatchError;
255
+ } });
256
+ var filesystem_adapter_js_1 = require_filesystem_adapter();
257
+ Object.defineProperty(exports, "FilesystemAdapter", { enumerable: true, get: function() {
258
+ return filesystem_adapter_js_1.FilesystemAdapter;
259
+ } });
260
+ var composite_adapter_js_1 = require_composite_adapter();
261
+ Object.defineProperty(exports, "CompositeAdapter", { enumerable: true, get: function() {
262
+ return composite_adapter_js_1.CompositeAdapter;
263
+ } });
264
+ var git_adapter_js_1 = require_git_adapter();
265
+ Object.defineProperty(exports, "GitAdapter", { enumerable: true, get: function() {
266
+ return git_adapter_js_1.GitAdapter;
267
+ } });
268
+ var http_adapter_js_1 = require_http_adapter();
269
+ Object.defineProperty(exports, "HttpAdapter", { enumerable: true, get: function() {
270
+ return http_adapter_js_1.HttpAdapter;
271
+ } });
272
+ }
273
+ });
274
+
275
+ // ../forge/packages/core/dist/resolver/index.js
276
+ var require_resolver2 = __commonJS({
277
+ "../forge/packages/core/dist/resolver/index.js"(exports) {
278
+ "use strict";
279
+ Object.defineProperty(exports, "__esModule", { value: true });
280
+ exports.mergeWorkspaceConfigs = exports.Resolver = void 0;
281
+ var resolver_js_1 = require_resolver();
282
+ Object.defineProperty(exports, "Resolver", { enumerable: true, get: function() {
283
+ return resolver_js_1.Resolver;
284
+ } });
285
+ var merge_workspace_configs_js_1 = require_merge_workspace_configs();
286
+ Object.defineProperty(exports, "mergeWorkspaceConfigs", { enumerable: true, get: function() {
287
+ return merge_workspace_configs_js_1.mergeWorkspaceConfigs;
288
+ } });
289
+ }
290
+ });
291
+
292
+ // ../forge/packages/core/dist/workspace/workspace-migration.js
293
+ var require_workspace_migration = __commonJS({
294
+ "../forge/packages/core/dist/workspace/workspace-migration.js"(exports) {
295
+ "use strict";
296
+ var __importDefault = exports && exports.__importDefault || function(mod) {
297
+ return mod && mod.__esModule ? mod : { "default": mod };
298
+ };
299
+ Object.defineProperty(exports, "__esModule", { value: true });
300
+ exports.runStartupMigrations = runStartupMigrations;
301
+ var fs_1 = __require("fs");
302
+ var path_1 = __importDefault(__require("path"));
303
+ var global_config_loader_js_1 = require_global_config_loader();
304
+ var path_utils_js_1 = require_path_utils();
305
+ var workspace_metadata_store_js_1 = require_workspace_metadata_store();
306
+ var mcp_settings_writer_js_1 = require_mcp_settings_writer();
307
+ async function runStartupMigrations(globalConfigPath) {
308
+ try {
309
+ await migrateReadGuardHook(globalConfigPath);
310
+ } catch (err) {
311
+ process.stderr.write(JSON.stringify({
312
+ level: "warn",
313
+ message: "[Forge] Startup migration failed",
314
+ error: err?.message ?? String(err),
315
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
316
+ }) + "\n");
317
+ }
318
+ }
319
+ async function migrateReadGuardHook(globalConfigPath) {
320
+ const globalConfig = await (0, global_config_loader_js_1.loadGlobalConfig)(globalConfigPath);
321
+ const mountPath = (0, path_utils_js_1.expandPath)(globalConfig.workspace.mount_path);
322
+ const hostMountPath = globalConfig.workspace.host_workspaces_path ? globalConfig.workspace.host_workspaces_path : mountPath;
323
+ const metaStore = new workspace_metadata_store_js_1.WorkspaceMetadataStore(globalConfig.workspace.store_path);
324
+ const workspaces = await metaStore.list({ status: "active" });
325
+ for (const ws of workspaces) {
326
+ const guardScript = path_1.default.join(ws.path, ".claude", "scripts", "guard-source-reads.sh");
327
+ let missing = false;
328
+ try {
329
+ await fs_1.promises.access(guardScript);
330
+ } catch {
331
+ missing = true;
332
+ }
333
+ if (!missing) {
334
+ continue;
335
+ }
336
+ const hostWorkspacePath = path_1.default.join(hostMountPath, ws.name);
337
+ try {
338
+ await (0, mcp_settings_writer_js_1.emitReadGuardHook)(ws.path, hostWorkspacePath);
339
+ process.stderr.write(JSON.stringify({
340
+ level: "info",
341
+ message: "[Forge] Migration: emitted read guard hook",
342
+ workspace: ws.name,
343
+ workspaceId: ws.id,
344
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
345
+ }) + "\n");
346
+ } catch (err) {
347
+ process.stderr.write(JSON.stringify({
348
+ level: "warn",
349
+ message: "[Forge] Migration: failed to emit read guard hook",
350
+ workspace: ws.name,
351
+ workspaceId: ws.id,
352
+ error: err?.message ?? String(err),
353
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
354
+ }) + "\n");
355
+ }
356
+ }
357
+ }
358
+ }
359
+ });
360
+
361
+ // ../forge/packages/core/dist/workspace/index.js
362
+ var require_workspace = __commonJS({
363
+ "../forge/packages/core/dist/workspace/index.js"(exports) {
364
+ "use strict";
365
+ Object.defineProperty(exports, "__esModule", { value: true });
366
+ exports.runStartupMigrations = exports.WRAPPER_PATH = exports.updateClaudeMcpServers = exports.emitMcpRemoteWrapper = exports.WorkspaceLifecycleManager = exports.generateBranchName = exports.slugify = exports.WorkspaceCreateError = exports.WorkspaceCreator = exports.WORKSPACES_FILE = exports.generateWorkspaceId = exports.WorkspaceMetadataStore = exports.WorkspaceManager = void 0;
367
+ var workspace_manager_js_1 = require_workspace_manager();
368
+ Object.defineProperty(exports, "WorkspaceManager", { enumerable: true, get: function() {
369
+ return workspace_manager_js_1.WorkspaceManager;
370
+ } });
371
+ var workspace_metadata_store_js_1 = require_workspace_metadata_store();
372
+ Object.defineProperty(exports, "WorkspaceMetadataStore", { enumerable: true, get: function() {
373
+ return workspace_metadata_store_js_1.WorkspaceMetadataStore;
374
+ } });
375
+ Object.defineProperty(exports, "generateWorkspaceId", { enumerable: true, get: function() {
376
+ return workspace_metadata_store_js_1.generateWorkspaceId;
377
+ } });
378
+ Object.defineProperty(exports, "WORKSPACES_FILE", { enumerable: true, get: function() {
379
+ return workspace_metadata_store_js_1.WORKSPACES_FILE;
380
+ } });
381
+ var workspace_creator_js_1 = require_workspace_creator();
382
+ Object.defineProperty(exports, "WorkspaceCreator", { enumerable: true, get: function() {
383
+ return workspace_creator_js_1.WorkspaceCreator;
384
+ } });
385
+ Object.defineProperty(exports, "WorkspaceCreateError", { enumerable: true, get: function() {
386
+ return workspace_creator_js_1.WorkspaceCreateError;
387
+ } });
388
+ Object.defineProperty(exports, "slugify", { enumerable: true, get: function() {
389
+ return workspace_creator_js_1.slugify;
390
+ } });
391
+ Object.defineProperty(exports, "generateBranchName", { enumerable: true, get: function() {
392
+ return workspace_creator_js_1.generateBranchName;
393
+ } });
394
+ var workspace_lifecycle_js_1 = require_workspace_lifecycle();
395
+ Object.defineProperty(exports, "WorkspaceLifecycleManager", { enumerable: true, get: function() {
396
+ return workspace_lifecycle_js_1.WorkspaceLifecycleManager;
397
+ } });
398
+ var mcp_settings_writer_js_1 = require_mcp_settings_writer();
399
+ Object.defineProperty(exports, "emitMcpRemoteWrapper", { enumerable: true, get: function() {
400
+ return mcp_settings_writer_js_1.emitMcpRemoteWrapper;
401
+ } });
402
+ Object.defineProperty(exports, "updateClaudeMcpServers", { enumerable: true, get: function() {
403
+ return mcp_settings_writer_js_1.updateClaudeMcpServers;
404
+ } });
405
+ Object.defineProperty(exports, "WRAPPER_PATH", { enumerable: true, get: function() {
406
+ return mcp_settings_writer_js_1.WRAPPER_PATH;
407
+ } });
408
+ var workspace_migration_js_1 = require_workspace_migration();
409
+ Object.defineProperty(exports, "runStartupMigrations", { enumerable: true, get: function() {
410
+ return workspace_migration_js_1.runStartupMigrations;
411
+ } });
412
+ }
413
+ });
414
+
415
+ // ../forge/packages/core/dist/compiler/index.js
416
+ var require_compiler2 = __commonJS({
417
+ "../forge/packages/core/dist/compiler/index.js"(exports) {
418
+ "use strict";
419
+ Object.defineProperty(exports, "__esModule", { value: true });
420
+ exports.removeManagedSection = exports.upsertManagedSection = exports.GlobalClaudeCodeStrategy = exports.CursorStrategy = exports.ClaudeCodeStrategy = exports.Compiler = void 0;
421
+ var compiler_js_1 = require_compiler();
422
+ Object.defineProperty(exports, "Compiler", { enumerable: true, get: function() {
423
+ return compiler_js_1.Compiler;
424
+ } });
425
+ var claude_code_strategy_js_1 = require_claude_code_strategy();
426
+ Object.defineProperty(exports, "ClaudeCodeStrategy", { enumerable: true, get: function() {
427
+ return claude_code_strategy_js_1.ClaudeCodeStrategy;
428
+ } });
429
+ var cursor_strategy_js_1 = require_cursor_strategy();
430
+ Object.defineProperty(exports, "CursorStrategy", { enumerable: true, get: function() {
431
+ return cursor_strategy_js_1.CursorStrategy;
432
+ } });
433
+ var global_claude_code_strategy_js_1 = require_global_claude_code_strategy();
434
+ Object.defineProperty(exports, "GlobalClaudeCodeStrategy", { enumerable: true, get: function() {
435
+ return global_claude_code_strategy_js_1.GlobalClaudeCodeStrategy;
436
+ } });
437
+ var claude_md_writer_js_1 = require_claude_md_writer();
438
+ Object.defineProperty(exports, "upsertManagedSection", { enumerable: true, get: function() {
439
+ return claude_md_writer_js_1.upsertManagedSection;
440
+ } });
441
+ Object.defineProperty(exports, "removeManagedSection", { enumerable: true, get: function() {
442
+ return claude_md_writer_js_1.removeManagedSection;
443
+ } });
444
+ }
445
+ });
446
+
447
+ // ../forge/packages/core/dist/config/index.js
448
+ var require_config = __commonJS({
449
+ "../forge/packages/core/dist/config/index.js"(exports) {
450
+ "use strict";
451
+ Object.defineProperty(exports, "__esModule", { value: true });
452
+ exports.expandPaths = exports.expandPath = exports.GLOBAL_CONFIG_PATH = exports.GLOBAL_CONFIG_DIR = exports.DEFAULT_GLOBAL_REGISTRY = exports.DEFAULT_LOCAL_REGISTRY = exports.selectSharedRepoRegistry = exports.ensureDefaultRegistries = exports.removeGlobalRegistry = exports.addGlobalRegistry = exports.saveGlobalConfig = exports.loadGlobalConfig = void 0;
453
+ var global_config_loader_js_1 = require_global_config_loader();
454
+ Object.defineProperty(exports, "loadGlobalConfig", { enumerable: true, get: function() {
455
+ return global_config_loader_js_1.loadGlobalConfig;
456
+ } });
457
+ Object.defineProperty(exports, "saveGlobalConfig", { enumerable: true, get: function() {
458
+ return global_config_loader_js_1.saveGlobalConfig;
459
+ } });
460
+ Object.defineProperty(exports, "addGlobalRegistry", { enumerable: true, get: function() {
461
+ return global_config_loader_js_1.addGlobalRegistry;
462
+ } });
463
+ Object.defineProperty(exports, "removeGlobalRegistry", { enumerable: true, get: function() {
464
+ return global_config_loader_js_1.removeGlobalRegistry;
465
+ } });
466
+ Object.defineProperty(exports, "ensureDefaultRegistries", { enumerable: true, get: function() {
467
+ return global_config_loader_js_1.ensureDefaultRegistries;
468
+ } });
469
+ Object.defineProperty(exports, "selectSharedRepoRegistry", { enumerable: true, get: function() {
470
+ return global_config_loader_js_1.selectSharedRepoRegistry;
471
+ } });
472
+ Object.defineProperty(exports, "DEFAULT_LOCAL_REGISTRY", { enumerable: true, get: function() {
473
+ return global_config_loader_js_1.DEFAULT_LOCAL_REGISTRY;
474
+ } });
475
+ Object.defineProperty(exports, "DEFAULT_GLOBAL_REGISTRY", { enumerable: true, get: function() {
476
+ return global_config_loader_js_1.DEFAULT_GLOBAL_REGISTRY;
477
+ } });
478
+ Object.defineProperty(exports, "GLOBAL_CONFIG_DIR", { enumerable: true, get: function() {
479
+ return global_config_loader_js_1.GLOBAL_CONFIG_DIR;
480
+ } });
481
+ Object.defineProperty(exports, "GLOBAL_CONFIG_PATH", { enumerable: true, get: function() {
482
+ return global_config_loader_js_1.GLOBAL_CONFIG_PATH;
483
+ } });
484
+ var path_utils_js_1 = require_path_utils();
485
+ Object.defineProperty(exports, "expandPath", { enumerable: true, get: function() {
486
+ return path_utils_js_1.expandPath;
487
+ } });
488
+ Object.defineProperty(exports, "expandPaths", { enumerable: true, get: function() {
489
+ return path_utils_js_1.expandPaths;
490
+ } });
491
+ }
492
+ });
493
+
494
+ // ../forge/packages/core/dist/repo/clone-layout.js
495
+ var require_clone_layout = __commonJS({
496
+ "../forge/packages/core/dist/repo/clone-layout.js"(exports) {
497
+ "use strict";
498
+ Object.defineProperty(exports, "__esModule", { value: true });
499
+ exports.horusDataPath = horusDataPath;
500
+ exports.horusReposRoot = horusReposRoot;
501
+ exports.repoClonePath = repoClonePath;
502
+ exports.repoClonePathFromCoordinate = repoClonePathFromCoordinate;
503
+ exports.repoWorktreesDir = repoWorktreesDir;
504
+ exports.worktreePath = worktreePath;
505
+ exports.ensureHorusIgnored = ensureHorusIgnored;
506
+ var node_os_1 = __require("os");
507
+ var node_path_1 = __require("path");
508
+ var node_fs_1 = __require("fs");
509
+ var url_utils_js_1 = require_url_utils();
510
+ function horusDataPath() {
511
+ return process.env.HORUS_DATA_PATH || (0, node_path_1.join)((0, node_os_1.homedir)(), "Horus", "data");
512
+ }
513
+ function horusReposRoot(dataPath = horusDataPath()) {
514
+ return (0, node_path_1.join)(dataPath, "repos");
515
+ }
516
+ function repoClonePath(url, dataPath = horusDataPath()) {
517
+ const { host, org, name } = (0, url_utils_js_1.deriveRepoCoordinate)(url);
518
+ return (0, node_path_1.join)(horusReposRoot(dataPath), host, org, name);
519
+ }
520
+ function repoClonePathFromCoordinate(coord, dataPath = horusDataPath()) {
521
+ return (0, node_path_1.join)(horusReposRoot(dataPath), coord.host, coord.org, coord.name);
522
+ }
523
+ function repoWorktreesDir(clonePath) {
524
+ return (0, node_path_1.join)(clonePath, ".horus", "worktrees");
525
+ }
526
+ function worktreePath(clonePath, sessionId) {
527
+ return (0, node_path_1.join)(repoWorktreesDir(clonePath), sessionId);
528
+ }
529
+ var HORUS_EXCLUDE_LINE = "/.horus/";
530
+ async function ensureHorusIgnored(clonePath) {
531
+ const excludePath = (0, node_path_1.join)(clonePath, ".git", "info", "exclude");
532
+ let existing = "";
533
+ try {
534
+ existing = await node_fs_1.promises.readFile(excludePath, "utf8");
535
+ } catch (err) {
536
+ if (err.code !== "ENOENT")
537
+ throw err;
538
+ await node_fs_1.promises.mkdir((0, node_path_1.join)(clonePath, ".git", "info"), { recursive: true });
539
+ }
540
+ const lines = existing.split("\n").map((l) => l.trim());
541
+ if (lines.includes(HORUS_EXCLUDE_LINE) || lines.includes(".horus/")) {
542
+ return;
543
+ }
544
+ const prefix = existing.length === 0 || existing.endsWith("\n") ? "" : "\n";
545
+ await node_fs_1.promises.appendFile(excludePath, `${prefix}# Horus-managed session worktrees (do not commit)
546
+ ${HORUS_EXCLUDE_LINE}
547
+ `);
548
+ }
549
+ }
550
+ });
551
+
552
+ // ../forge/packages/core/dist/repo/local-repo-state-store.js
553
+ var require_local_repo_state_store = __commonJS({
554
+ "../forge/packages/core/dist/repo/local-repo-state-store.js"(exports) {
555
+ "use strict";
556
+ var __importDefault = exports && exports.__importDefault || function(mod) {
557
+ return mod && mod.__esModule ? mod : { "default": mod };
558
+ };
559
+ Object.defineProperty(exports, "__esModule", { value: true });
560
+ exports.LocalRepoStateStoreManager = void 0;
561
+ exports.repoStatePath = repoStatePath;
562
+ var node_fs_1 = __require("fs");
563
+ var node_path_1 = __importDefault(__require("path"));
564
+ var local_repo_state_js_1 = require_local_repo_state();
565
+ var clone_layout_js_1 = require_clone_layout();
566
+ function repoStatePath(dataPath = (0, clone_layout_js_1.horusDataPath)()) {
567
+ return node_path_1.default.join(dataPath, "config", "repo-state.json");
568
+ }
569
+ var LocalRepoStateStoreManager = class {
570
+ storePath;
571
+ constructor(storePath = repoStatePath()) {
572
+ this.storePath = storePath;
573
+ }
574
+ async load() {
575
+ try {
576
+ const raw = await node_fs_1.promises.readFile(this.storePath, "utf8");
577
+ return local_repo_state_js_1.LocalRepoStateStoreSchema.parse(JSON.parse(raw));
578
+ } catch (err) {
579
+ if (err.code === "ENOENT") {
580
+ return { ...local_repo_state_js_1.EMPTY_LOCAL_REPO_STATE, repos: [] };
581
+ }
582
+ throw err;
583
+ }
584
+ }
585
+ async save(store) {
586
+ await node_fs_1.promises.mkdir(node_path_1.default.dirname(this.storePath), { recursive: true });
587
+ await node_fs_1.promises.writeFile(this.storePath, JSON.stringify(store, null, 2), "utf8");
588
+ }
589
+ async get(clonePath) {
590
+ const store = await this.load();
591
+ return store.repos.find((r) => r.clonePath === clonePath) ?? null;
592
+ }
593
+ /** Insert or replace the entry for this clonePath (dedup-safe). */
594
+ async upsert(entry) {
595
+ const store = await this.load();
596
+ const idx = store.repos.findIndex((r) => r.clonePath === entry.clonePath);
597
+ if (idx >= 0)
598
+ store.repos[idx] = entry;
599
+ else
600
+ store.repos.push(entry);
601
+ await this.save(store);
602
+ }
603
+ /** Patch fields on an existing entry, creating it if absent. */
604
+ async patch(seed, patch) {
605
+ const store = await this.load();
606
+ let entry = store.repos.find((r) => r.clonePath === seed.clonePath);
607
+ if (!entry) {
608
+ entry = { ...seed, lastFetchedAt: null, lastUsedAt: null, worktrees: [] };
609
+ store.repos.push(entry);
610
+ }
611
+ Object.assign(entry, patch);
612
+ await this.save(store);
613
+ return entry;
614
+ }
615
+ /** Add a worktree record, deduped by sessionId. */
616
+ async addWorktree(clonePath, wt) {
617
+ const store = await this.load();
618
+ const entry = store.repos.find((r) => r.clonePath === clonePath);
619
+ if (!entry)
620
+ throw new Error(`LocalRepoState: no entry for ${clonePath}`);
621
+ if (!entry.worktrees.some((w) => w.sessionId === wt.sessionId)) {
622
+ entry.worktrees.push(wt);
623
+ }
624
+ await this.save(store);
625
+ }
626
+ };
627
+ exports.LocalRepoStateStoreManager = LocalRepoStateStoreManager;
628
+ }
629
+ });
630
+
631
+ // ../forge/packages/core/dist/repo/clone-semantics.js
632
+ var require_clone_semantics = __commonJS({
633
+ "../forge/packages/core/dist/repo/clone-semantics.js"(exports) {
634
+ "use strict";
635
+ Object.defineProperty(exports, "__esModule", { value: true });
636
+ exports.DEFAULT_CLONE_TTL_MS = void 0;
637
+ exports.cloneTtlMs = cloneTtlMs;
638
+ exports.isCloneStale = isCloneStale;
639
+ exports.ensureClone = ensureClone;
640
+ exports.refreshIfStale = refreshIfStale;
641
+ exports.createSessionWorktree = createSessionWorktree;
642
+ var node_fs_1 = __require("fs");
643
+ var node_path_1 = __require("path");
644
+ var node_child_process_1 = __require("child_process");
645
+ var node_util_1 = __require("util");
646
+ var clone_layout_js_1 = require_clone_layout();
647
+ var url_utils_js_1 = require_url_utils();
648
+ var local_repo_state_store_js_1 = require_local_repo_state_store();
649
+ var execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
650
+ exports.DEFAULT_CLONE_TTL_MS = 60 * 60 * 1e3;
651
+ function cloneTtlMs(override) {
652
+ if (typeof override === "number")
653
+ return override;
654
+ const env = process.env.HORUS_CLONE_TTL_MS;
655
+ if (env && Number.isFinite(Number(env)))
656
+ return Number(env);
657
+ return exports.DEFAULT_CLONE_TTL_MS;
658
+ }
659
+ function isCloneStale(lastFetchedAt, ttlMs, now) {
660
+ if (lastFetchedAt === null)
661
+ return true;
662
+ return now.getTime() - new Date(lastFetchedAt).getTime() > ttlMs;
663
+ }
664
+ async function isGitRepo(dir) {
665
+ try {
666
+ await execFileAsync("git", ["rev-parse", "--git-dir"], { cwd: dir });
667
+ return true;
668
+ } catch {
669
+ return false;
670
+ }
671
+ }
672
+ async function ensureClone(url, opts = {}) {
673
+ const dataPath = opts.dataPath ?? (0, clone_layout_js_1.horusDataPath)();
674
+ const clonePath = (0, clone_layout_js_1.repoClonePath)(url, dataPath);
675
+ const coord = (0, url_utils_js_1.deriveRepoCoordinate)(url);
676
+ const store = new local_repo_state_store_js_1.LocalRepoStateStoreManager((0, local_repo_state_store_js_1.repoStatePath)(dataPath));
677
+ if (await isGitRepo(clonePath)) {
678
+ await store.patch({ ...coord, clonePath }, {});
679
+ await (0, clone_layout_js_1.ensureHorusIgnored)(clonePath);
680
+ return clonePath;
681
+ }
682
+ await node_fs_1.promises.rm(clonePath, { recursive: true, force: true }).catch(() => {
683
+ });
684
+ const tmpPath = `${clonePath}.tmp-${process.pid}-${Date.now()}`;
685
+ await node_fs_1.promises.mkdir((0, node_path_1.dirname)(clonePath), { recursive: true });
686
+ try {
687
+ await execFileAsync("git", ["clone", url, tmpPath], {
688
+ timeout: opts.gitTimeoutMs ?? 12e4
689
+ });
690
+ await node_fs_1.promises.rename(tmpPath, clonePath);
691
+ } catch (err) {
692
+ await node_fs_1.promises.rm(tmpPath, { recursive: true, force: true }).catch(() => {
693
+ });
694
+ throw err;
695
+ }
696
+ await (0, clone_layout_js_1.ensureHorusIgnored)(clonePath);
697
+ await store.patch({ ...coord, clonePath }, {});
698
+ return clonePath;
699
+ }
700
+ async function refreshIfStale(url, baseBranch, opts = {}) {
701
+ const dataPath = opts.dataPath ?? (0, clone_layout_js_1.horusDataPath)();
702
+ const now = (opts.now ?? (() => /* @__PURE__ */ new Date()))();
703
+ const ttl = cloneTtlMs(opts.ttlMs);
704
+ const clonePath = (0, clone_layout_js_1.repoClonePath)(url, dataPath);
705
+ const coord = (0, url_utils_js_1.deriveRepoCoordinate)(url);
706
+ const store = new local_repo_state_store_js_1.LocalRepoStateStoreManager((0, local_repo_state_store_js_1.repoStatePath)(dataPath));
707
+ const entry = await store.get(clonePath);
708
+ if (!isCloneStale(entry?.lastFetchedAt ?? null, ttl, now))
709
+ return false;
710
+ await execFileAsync("git", ["fetch", "origin", baseBranch], {
711
+ cwd: clonePath,
712
+ timeout: opts.gitTimeoutMs ?? 12e4
713
+ });
714
+ await store.patch({ ...coord, clonePath }, { lastFetchedAt: now.toISOString() });
715
+ return true;
716
+ }
717
+ async function createSessionWorktree(url, sessionId, baseBranch, branch, opts = {}) {
718
+ const dataPath = opts.dataPath ?? (0, clone_layout_js_1.horusDataPath)();
719
+ const now = (opts.now ?? (() => /* @__PURE__ */ new Date()))();
720
+ const clonePath = await ensureClone(url, opts);
721
+ await refreshIfStale(url, baseBranch, opts);
722
+ const wtPath = (0, clone_layout_js_1.worktreePath)(clonePath, sessionId);
723
+ await execFileAsync("git", ["worktree", "add", "-b", branch, wtPath, `origin/${baseBranch}`], { cwd: clonePath, timeout: opts.gitTimeoutMs ?? 12e4 });
724
+ const coord = (0, url_utils_js_1.deriveRepoCoordinate)(url);
725
+ const store = new local_repo_state_store_js_1.LocalRepoStateStoreManager((0, local_repo_state_store_js_1.repoStatePath)(dataPath));
726
+ await store.patch({ ...coord, clonePath }, { lastUsedAt: now.toISOString() });
727
+ await store.addWorktree(clonePath, {
728
+ sessionId,
729
+ path: wtPath,
730
+ branch,
731
+ createdAt: now.toISOString()
732
+ });
733
+ return wtPath;
734
+ }
735
+ }
736
+ });
737
+
738
+ // ../forge/packages/core/dist/session/agent-spawn.js
739
+ var require_agent_spawn = __commonJS({
740
+ "../forge/packages/core/dist/session/agent-spawn.js"(exports) {
741
+ "use strict";
742
+ Object.defineProperty(exports, "__esModule", { value: true });
743
+ exports.buildClaudeArgs = buildClaudeArgs;
744
+ exports.spawnAgentSession = spawnAgentSession;
745
+ var child_process_1 = __require("child_process");
746
+ var util_1 = __require("util");
747
+ var errors_js_1 = require_errors();
748
+ var execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
749
+ var MAX_BUFFER = 64 * 1024 * 1024;
750
+ function resolveClaudeBin(opts) {
751
+ return opts.claudeBin ?? process.env.CLAUDE_BIN ?? "claude";
752
+ }
753
+ function buildClaudeArgs(opts) {
754
+ const args = ["-p", opts.prompt, "--output-format", "json"];
755
+ if (opts.resume)
756
+ args.push("--resume", opts.resume);
757
+ args.push("--permission-mode", opts.permissionMode ?? "acceptEdits");
758
+ if (opts.allowedTools && opts.allowedTools.length > 0) {
759
+ args.push("--allowedTools", opts.allowedTools.join(","));
760
+ }
761
+ if (typeof opts.maxTurns === "number") {
762
+ args.push("--max-turns", String(opts.maxTurns));
763
+ }
764
+ return args;
765
+ }
766
+ async function spawnAgentSession(opts) {
767
+ const bin = resolveClaudeBin(opts);
768
+ const args = buildClaudeArgs(opts);
769
+ let stdout;
770
+ try {
771
+ const res = await execFileAsync(bin, args, {
772
+ cwd: opts.cwd,
773
+ timeout: opts.timeoutMs ?? 0,
774
+ maxBuffer: MAX_BUFFER,
775
+ encoding: "utf8"
776
+ // guarantee string stdout (and string err.stdout on the salvage path)
777
+ });
778
+ stdout = res.stdout;
779
+ } catch (err) {
780
+ if (err?.code === "ENOENT") {
781
+ throw new errors_js_1.ForgeError("AGENT_BIN_NOT_FOUND", `Claude Code binary "${bin}" was not found on PATH.`, `Install Claude Code or set CLAUDE_BIN to its absolute path. The edit-flow spawn requires a non-bare claude executable.`);
782
+ }
783
+ const salvaged = typeof err?.stdout === "string" ? err.stdout : "";
784
+ if (salvaged.trim()) {
785
+ stdout = salvaged;
786
+ } else {
787
+ throw new errors_js_1.ForgeError("AGENT_SPAWN_FAILED", `Headless claude run failed (cwd=${opts.cwd}): ${err?.message ?? "unknown error"}`, `Verify the worktree is valid and the claude session can authenticate (non-bare inherits the logged-in credential).`);
788
+ }
789
+ }
790
+ let parsed;
791
+ try {
792
+ parsed = JSON.parse(stdout);
793
+ } catch {
794
+ throw new errors_js_1.ForgeError("AGENT_OUTPUT_UNPARSEABLE", `Could not parse JSON from "claude --output-format json" (cwd=${opts.cwd}).`, `First 400 chars of output: ${stdout.slice(0, 400)}`);
795
+ }
796
+ const claudeSessionId = parsed["session_id"] ?? parsed["sessionId"];
797
+ if (!claudeSessionId) {
798
+ throw new errors_js_1.ForgeError("AGENT_OUTPUT_MISSING_SESSION_ID", `"claude --output-format json" did not return a session_id (cwd=${opts.cwd}).`, `session_id is required for resume + provenance. Confirm the Claude Code version supports --output-format json.`);
799
+ }
800
+ return {
801
+ claudeSessionId,
802
+ result: typeof parsed["result"] === "string" ? parsed["result"] : "",
803
+ isError: parsed["is_error"] === true,
804
+ costUsd: typeof parsed["total_cost_usd"] === "number" ? parsed["total_cost_usd"] : void 0,
805
+ numTurns: typeof parsed["num_turns"] === "number" ? parsed["num_turns"] : void 0,
806
+ raw: parsed
807
+ };
808
+ }
809
+ }
810
+ });
811
+
812
+ // ../forge/packages/core/dist/session/gc.js
813
+ var require_gc = __commonJS({
814
+ "../forge/packages/core/dist/session/gc.js"(exports) {
815
+ "use strict";
816
+ Object.defineProperty(exports, "__esModule", { value: true });
817
+ exports.isCleanTree = isCleanTree;
818
+ exports.classifyWorktree = classifyWorktree;
819
+ exports.getWorktreeTreeState = getWorktreeTreeState;
820
+ exports.worktreeGc = worktreeGc;
821
+ exports.cloneGc = cloneGc;
822
+ var node_fs_1 = __require("fs");
823
+ var node_child_process_1 = __require("child_process");
824
+ var node_util_1 = __require("util");
825
+ var local_repo_state_store_js_1 = require_local_repo_state_store();
826
+ var execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
827
+ var ACTIVE_STATUSES = /* @__PURE__ */ new Set([
828
+ "in_progress",
829
+ "in-progress",
830
+ "in_review",
831
+ "in-review",
832
+ "open",
833
+ "blocked"
834
+ ]);
835
+ function isCleanTree(t) {
836
+ return t.determined && !t.uncommitted && !t.unpushed && !t.stash;
837
+ }
838
+ function classifyWorktree(input2) {
839
+ const reasons = [];
840
+ const active = input2.status !== null && ACTIVE_STATUSES.has(input2.status);
841
+ if (active)
842
+ reasons.push(`work item status '${input2.status}' is active`);
843
+ if (input2.status === null)
844
+ reasons.push("work item status unknown (Anvil) \u2014 treated as active/unsafe");
845
+ const clean = isCleanTree(input2.tree);
846
+ if (!input2.tree.determined)
847
+ reasons.push("tree state could not be determined \u2014 treated as dirty/unsafe");
848
+ else {
849
+ if (input2.tree.uncommitted)
850
+ reasons.push("uncommitted changes");
851
+ if (input2.tree.unpushed)
852
+ reasons.push("unpushed commits");
853
+ if (input2.tree.stash)
854
+ reasons.push("stash entries present");
855
+ }
856
+ const eligible = !active && input2.status !== null && clean;
857
+ if (eligible)
858
+ reasons.push(`inactive + clean (age ${Math.round(input2.ageMs / 864e5)}d, informational only)`);
859
+ return { eligible, reasons };
860
+ }
861
+ async function getWorktreeTreeState(worktreePath) {
862
+ try {
863
+ const { stdout: porcelain } = await execFileAsync("git", ["status", "--porcelain"], {
864
+ cwd: worktreePath,
865
+ timeout: 15e3
866
+ });
867
+ const { stdout: stashList } = await execFileAsync("git", ["stash", "list"], {
868
+ cwd: worktreePath,
869
+ timeout: 1e4
870
+ });
871
+ let unpushed = true;
872
+ try {
873
+ const { stdout: up } = await execFileAsync("git", ["rev-list", "--count", "@{upstream}..HEAD"], { cwd: worktreePath, timeout: 1e4 });
874
+ unpushed = parseInt(up.trim(), 10) > 0;
875
+ } catch {
876
+ unpushed = true;
877
+ }
878
+ return {
879
+ uncommitted: porcelain.trim().length > 0,
880
+ unpushed,
881
+ stash: stashList.trim().length > 0,
882
+ determined: true
883
+ };
884
+ } catch {
885
+ return { uncommitted: true, unpushed: true, stash: true, determined: false };
886
+ }
887
+ }
888
+ async function worktreeGc(opts) {
889
+ const dataPath = opts.dataPath;
890
+ const now = (opts.now ?? (() => /* @__PURE__ */ new Date()))();
891
+ const store = new local_repo_state_store_js_1.LocalRepoStateStoreManager((0, local_repo_state_store_js_1.repoStatePath)(dataPath));
892
+ const state = await store.load();
893
+ const reclaimed = [];
894
+ const retained = [];
895
+ for (const entry of state.repos) {
896
+ for (const wt of entry.worktrees) {
897
+ const status = await opts.resolveStatus(wt, entry);
898
+ const tree = await getWorktreeTreeState(wt.path);
899
+ const ageMs = now.getTime() - new Date(wt.createdAt).getTime();
900
+ const { eligible, reasons } = classifyWorktree({ status, tree, ageMs });
901
+ const cand = {
902
+ clonePath: entry.clonePath,
903
+ sessionId: wt.sessionId,
904
+ worktreePath: wt.path,
905
+ branch: wt.branch,
906
+ eligible,
907
+ reasons
908
+ };
909
+ if (eligible)
910
+ reclaimed.push(cand);
911
+ else
912
+ retained.push(cand);
913
+ }
914
+ }
915
+ if (opts.apply === true) {
916
+ for (const cand of reclaimed) {
917
+ await execFileAsync("git", ["worktree", "remove", "--force", cand.worktreePath], {
918
+ cwd: cand.clonePath,
919
+ timeout: 15e3
920
+ }).catch(() => {
921
+ });
922
+ await execFileAsync("git", ["worktree", "prune"], {
923
+ cwd: cand.clonePath,
924
+ timeout: 1e4
925
+ }).catch(() => {
926
+ });
927
+ await node_fs_1.promises.rm(cand.worktreePath, { recursive: true, force: true }).catch(() => {
928
+ });
929
+ const entry = state.repos.find((r) => r.clonePath === cand.clonePath);
930
+ entry.worktrees = entry.worktrees.filter((w) => w.sessionId !== cand.sessionId);
931
+ }
932
+ await store.save(state);
933
+ }
934
+ return { applied: opts.apply === true, reclaimed, retained };
935
+ }
936
+ async function cloneGc(opts) {
937
+ const now = (opts.now ?? (() => /* @__PURE__ */ new Date()))();
938
+ const store = new local_repo_state_store_js_1.LocalRepoStateStoreManager((0, local_repo_state_store_js_1.repoStatePath)(opts.dataPath));
939
+ const state = await store.load();
940
+ const reclaimed = [];
941
+ const retained = [];
942
+ for (const entry of state.repos) {
943
+ const reasons = [];
944
+ let eligible = true;
945
+ if (entry.worktrees.length > 0) {
946
+ eligible = false;
947
+ reasons.push(`${entry.worktrees.length} live worktree(s) \u2014 never reclaim`);
948
+ } else if (entry.lastUsedAt === null) {
949
+ eligible = false;
950
+ reasons.push("never used \u2014 no LRU signal, retained");
951
+ } else {
952
+ const idle = now.getTime() - new Date(entry.lastUsedAt).getTime();
953
+ if (idle <= opts.maxIdleMs) {
954
+ eligible = false;
955
+ reasons.push(`idle ${Math.round(idle / 864e5)}d \u2264 threshold \u2014 retained`);
956
+ } else {
957
+ reasons.push(`idle ${Math.round(idle / 864e5)}d > threshold, no live worktrees`);
958
+ }
959
+ }
960
+ const cand = {
961
+ clonePath: entry.clonePath,
962
+ liveWorktrees: entry.worktrees.length,
963
+ lastUsedAt: entry.lastUsedAt,
964
+ eligible,
965
+ reasons
966
+ };
967
+ if (eligible)
968
+ reclaimed.push(cand);
969
+ else
970
+ retained.push(cand);
971
+ }
972
+ if (opts.apply === true) {
973
+ for (const cand of reclaimed) {
974
+ await node_fs_1.promises.rm(cand.clonePath, { recursive: true, force: true }).catch(() => {
975
+ });
976
+ }
977
+ state.repos = state.repos.filter((r) => !reclaimed.some((c) => c.clonePath === r.clonePath));
978
+ await store.save(state);
979
+ }
980
+ return { applied: opts.apply === true, reclaimed, retained };
981
+ }
982
+ }
983
+ });
984
+
985
+ // ../forge/packages/core/dist/index.js
986
+ var require_dist = __commonJS({
987
+ "../forge/packages/core/dist/index.js"(exports) {
988
+ "use strict";
989
+ var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
990
+ if (k2 === void 0) k2 = k;
991
+ var desc = Object.getOwnPropertyDescriptor(m, k);
992
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
993
+ desc = { enumerable: true, get: function() {
994
+ return m[k];
995
+ } };
996
+ }
997
+ Object.defineProperty(o, k2, desc);
998
+ }) : (function(o, m, k, k2) {
999
+ if (k2 === void 0) k2 = k;
1000
+ o[k2] = m[k];
1001
+ }));
1002
+ var __exportStar = exports && exports.__exportStar || function(m, exports2) {
1003
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) __createBinding(exports2, m, p);
1004
+ };
1005
+ Object.defineProperty(exports, "__esModule", { value: true });
1006
+ exports.cloneGc = exports.worktreeGc = exports.getWorktreeTreeState = exports.isCleanTree = exports.classifyWorktree = exports.sessionCleanup = exports.sessionList = exports.SessionStoreManager = exports.ForgeSearchClient = exports.RepoAmbiguousError = exports.RepoExistsError = exports.RepoNotFoundError = exports.RepoRegistryClient = exports.buildClaudeArgs = exports.spawnAgentSession = exports.repoDevelop = exports.repoStatePath = exports.LocalRepoStateStoreManager = exports.createSessionWorktree = exports.refreshIfStale = exports.ensureClone = exports.DEFAULT_CLONE_TTL_MS = exports.cloneTtlMs = exports.isCloneStale = exports.ensureHorusIgnored = exports.worktreePath = exports.repoWorktreesDir = exports.repoClonePathFromCoordinate = exports.repoClonePath = exports.horusReposRoot = exports.horusDataPath = exports.deriveRepoCoordinate = exports.normalizeHost = exports.normalizeGitUrl = exports.RepoIndexQuery = exports.loadRepoIndex = exports.saveRepoIndex = exports.scan = exports.Registry = exports.ForgeCore = void 0;
1007
+ var core_js_1 = require_core();
1008
+ Object.defineProperty(exports, "ForgeCore", { enumerable: true, get: function() {
1009
+ return core_js_1.ForgeCore;
1010
+ } });
1011
+ var registry_js_1 = require_registry();
1012
+ Object.defineProperty(exports, "Registry", { enumerable: true, get: function() {
1013
+ return registry_js_1.Registry;
1014
+ } });
1015
+ __exportStar(require_models(), exports);
1016
+ __exportStar(require_adapters(), exports);
1017
+ __exportStar(require_resolver2(), exports);
1018
+ __exportStar(require_workspace(), exports);
1019
+ __exportStar(require_compiler2(), exports);
1020
+ __exportStar(require_config(), exports);
1021
+ var repo_scanner_js_1 = require_repo_scanner();
1022
+ Object.defineProperty(exports, "scan", { enumerable: true, get: function() {
1023
+ return repo_scanner_js_1.scan;
1024
+ } });
1025
+ var repo_index_store_js_1 = require_repo_index_store();
1026
+ Object.defineProperty(exports, "saveRepoIndex", { enumerable: true, get: function() {
1027
+ return repo_index_store_js_1.saveRepoIndex;
1028
+ } });
1029
+ Object.defineProperty(exports, "loadRepoIndex", { enumerable: true, get: function() {
1030
+ return repo_index_store_js_1.loadRepoIndex;
1031
+ } });
1032
+ var repo_index_query_js_1 = require_repo_index_query();
1033
+ Object.defineProperty(exports, "RepoIndexQuery", { enumerable: true, get: function() {
1034
+ return repo_index_query_js_1.RepoIndexQuery;
1035
+ } });
1036
+ var url_utils_js_1 = require_url_utils();
1037
+ Object.defineProperty(exports, "normalizeGitUrl", { enumerable: true, get: function() {
1038
+ return url_utils_js_1.normalizeGitUrl;
1039
+ } });
1040
+ Object.defineProperty(exports, "normalizeHost", { enumerable: true, get: function() {
1041
+ return url_utils_js_1.normalizeHost;
1042
+ } });
1043
+ Object.defineProperty(exports, "deriveRepoCoordinate", { enumerable: true, get: function() {
1044
+ return url_utils_js_1.deriveRepoCoordinate;
1045
+ } });
1046
+ var clone_layout_js_1 = require_clone_layout();
1047
+ Object.defineProperty(exports, "horusDataPath", { enumerable: true, get: function() {
1048
+ return clone_layout_js_1.horusDataPath;
1049
+ } });
1050
+ Object.defineProperty(exports, "horusReposRoot", { enumerable: true, get: function() {
1051
+ return clone_layout_js_1.horusReposRoot;
1052
+ } });
1053
+ Object.defineProperty(exports, "repoClonePath", { enumerable: true, get: function() {
1054
+ return clone_layout_js_1.repoClonePath;
1055
+ } });
1056
+ Object.defineProperty(exports, "repoClonePathFromCoordinate", { enumerable: true, get: function() {
1057
+ return clone_layout_js_1.repoClonePathFromCoordinate;
1058
+ } });
1059
+ Object.defineProperty(exports, "repoWorktreesDir", { enumerable: true, get: function() {
1060
+ return clone_layout_js_1.repoWorktreesDir;
1061
+ } });
1062
+ Object.defineProperty(exports, "worktreePath", { enumerable: true, get: function() {
1063
+ return clone_layout_js_1.worktreePath;
1064
+ } });
1065
+ Object.defineProperty(exports, "ensureHorusIgnored", { enumerable: true, get: function() {
1066
+ return clone_layout_js_1.ensureHorusIgnored;
1067
+ } });
1068
+ var clone_semantics_js_1 = require_clone_semantics();
1069
+ Object.defineProperty(exports, "isCloneStale", { enumerable: true, get: function() {
1070
+ return clone_semantics_js_1.isCloneStale;
1071
+ } });
1072
+ Object.defineProperty(exports, "cloneTtlMs", { enumerable: true, get: function() {
1073
+ return clone_semantics_js_1.cloneTtlMs;
1074
+ } });
1075
+ Object.defineProperty(exports, "DEFAULT_CLONE_TTL_MS", { enumerable: true, get: function() {
1076
+ return clone_semantics_js_1.DEFAULT_CLONE_TTL_MS;
1077
+ } });
1078
+ Object.defineProperty(exports, "ensureClone", { enumerable: true, get: function() {
1079
+ return clone_semantics_js_1.ensureClone;
1080
+ } });
1081
+ Object.defineProperty(exports, "refreshIfStale", { enumerable: true, get: function() {
1082
+ return clone_semantics_js_1.refreshIfStale;
1083
+ } });
1084
+ Object.defineProperty(exports, "createSessionWorktree", { enumerable: true, get: function() {
1085
+ return clone_semantics_js_1.createSessionWorktree;
1086
+ } });
1087
+ var local_repo_state_store_js_1 = require_local_repo_state_store();
1088
+ Object.defineProperty(exports, "LocalRepoStateStoreManager", { enumerable: true, get: function() {
1089
+ return local_repo_state_store_js_1.LocalRepoStateStoreManager;
1090
+ } });
1091
+ Object.defineProperty(exports, "repoStatePath", { enumerable: true, get: function() {
1092
+ return local_repo_state_store_js_1.repoStatePath;
1093
+ } });
1094
+ var repo_develop_js_1 = require_repo_develop();
1095
+ Object.defineProperty(exports, "repoDevelop", { enumerable: true, get: function() {
1096
+ return repo_develop_js_1.repoDevelop;
1097
+ } });
1098
+ var agent_spawn_js_1 = require_agent_spawn();
1099
+ Object.defineProperty(exports, "spawnAgentSession", { enumerable: true, get: function() {
1100
+ return agent_spawn_js_1.spawnAgentSession;
1101
+ } });
1102
+ Object.defineProperty(exports, "buildClaudeArgs", { enumerable: true, get: function() {
1103
+ return agent_spawn_js_1.buildClaudeArgs;
1104
+ } });
1105
+ var repo_registry_client_js_1 = require_repo_registry_client();
1106
+ Object.defineProperty(exports, "RepoRegistryClient", { enumerable: true, get: function() {
1107
+ return repo_registry_client_js_1.RepoRegistryClient;
1108
+ } });
1109
+ var repo_errors_js_1 = require_repo_errors();
1110
+ Object.defineProperty(exports, "RepoNotFoundError", { enumerable: true, get: function() {
1111
+ return repo_errors_js_1.RepoNotFoundError;
1112
+ } });
1113
+ Object.defineProperty(exports, "RepoExistsError", { enumerable: true, get: function() {
1114
+ return repo_errors_js_1.RepoExistsError;
1115
+ } });
1116
+ Object.defineProperty(exports, "RepoAmbiguousError", { enumerable: true, get: function() {
1117
+ return repo_errors_js_1.RepoAmbiguousError;
1118
+ } });
1119
+ var forge_search_client_js_1 = require_forge_search_client();
1120
+ Object.defineProperty(exports, "ForgeSearchClient", { enumerable: true, get: function() {
1121
+ return forge_search_client_js_1.ForgeSearchClient;
1122
+ } });
1123
+ var session_store_js_1 = require_session_store();
1124
+ Object.defineProperty(exports, "SessionStoreManager", { enumerable: true, get: function() {
1125
+ return session_store_js_1.SessionStoreManager;
1126
+ } });
1127
+ var session_list_js_1 = require_session_list();
1128
+ Object.defineProperty(exports, "sessionList", { enumerable: true, get: function() {
1129
+ return session_list_js_1.sessionList;
1130
+ } });
1131
+ var session_cleanup_js_1 = require_session_cleanup();
1132
+ Object.defineProperty(exports, "sessionCleanup", { enumerable: true, get: function() {
1133
+ return session_cleanup_js_1.sessionCleanup;
1134
+ } });
1135
+ var gc_js_1 = require_gc();
1136
+ Object.defineProperty(exports, "classifyWorktree", { enumerable: true, get: function() {
1137
+ return gc_js_1.classifyWorktree;
1138
+ } });
1139
+ Object.defineProperty(exports, "isCleanTree", { enumerable: true, get: function() {
1140
+ return gc_js_1.isCleanTree;
1141
+ } });
1142
+ Object.defineProperty(exports, "getWorktreeTreeState", { enumerable: true, get: function() {
1143
+ return gc_js_1.getWorktreeTreeState;
1144
+ } });
1145
+ Object.defineProperty(exports, "worktreeGc", { enumerable: true, get: function() {
1146
+ return gc_js_1.worktreeGc;
1147
+ } });
1148
+ Object.defineProperty(exports, "cloneGc", { enumerable: true, get: function() {
1149
+ return gc_js_1.cloneGc;
1150
+ } });
1151
+ }
1152
+ });
2
1153
 
3
1154
  // src/index.ts
4
1155
  import { Command as Command16 } from "commander";
@@ -4177,13 +5328,13 @@ var guideCommand = new Command13("guide").description("Print a bundled Horus gui
4177
5328
  import { Command as Command14 } from "commander";
4178
5329
  import chalk14 from "chalk";
4179
5330
  import ora9 from "ora";
4180
- import { RepoRegistryClient } from "@forge/core";
5331
+ var import_core2 = __toESM(require_dist(), 1);
4181
5332
 
4182
5333
  // src/lib/repo-migrate.ts
5334
+ var import_core = __toESM(require_dist(), 1);
4183
5335
  import { promises as fs } from "fs";
4184
5336
  import os from "os";
4185
5337
  import path from "path";
4186
- import { RepoExistsError } from "@forge/core";
4187
5338
  function inferOrg(remoteUrl) {
4188
5339
  const sshMatch = remoteUrl.match(/git@[^:]+:([^/]+)\//);
4189
5340
  if (sshMatch) return sshMatch[1];
@@ -4235,7 +5386,7 @@ async function migrateRepos(opts) {
4235
5386
  await opts.client.register(input2);
4236
5387
  result.migrated.push(`${org}/${entry.name}`);
4237
5388
  } catch (err) {
4238
- if (err instanceof RepoExistsError) {
5389
+ if (err instanceof import_core.RepoExistsError) {
4239
5390
  result.skipped.push({ repo: `${org}/${entry.name}`, reason: "already registered" });
4240
5391
  } else {
4241
5392
  const msg = err.message ?? String(err);
@@ -4329,7 +5480,7 @@ repoCommand.command("migrate").description("Import existing repos.json entries i
4329
5480
  }
4330
5481
  const config = loadConfig();
4331
5482
  const registryUrl = opts.registry ?? config.enterprise_registry_url ?? "http://localhost:8744";
4332
- const client = new RepoRegistryClient({ baseUrl: registryUrl });
5483
+ const client = new import_core2.RepoRegistryClient({ baseUrl: registryUrl });
4333
5484
  if (opts.dryRun) {
4334
5485
  console.log(chalk14.yellow(" Dry-run mode \u2014 no changes will be written to the registry."));
4335
5486
  console.log("");