brainclaw 1.10.1 → 1.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/brainclaw-vscode.vsix +0 -0
- package/dist/core/worktree.js +46 -6
- package/dist/facts.js +3 -3
- package/dist/facts.json +2 -2
- package/package.json +1 -1
|
Binary file
|
package/dist/core/worktree.js
CHANGED
|
@@ -18,6 +18,13 @@ function gitPath(p) {
|
|
|
18
18
|
*
|
|
19
19
|
* Rules covered: no leading dots/dashes, no trailing dots, no `..`, no
|
|
20
20
|
* `@{`, no control/space/`~^:?*[\\` characters, no trailing `.lock`.
|
|
21
|
+
*
|
|
22
|
+
* Order matters: the 48-char length cap is applied BEFORE the trailing-dot/dash
|
|
23
|
+
* and `.lock` strips — never after. Dogfood 1.10.1: a multi-file scope ending in
|
|
24
|
+
* `…IntegrationHubPage.astro` sanitized fine, but the final `.slice(0, 48)` cut
|
|
25
|
+
* landed on the dot before `astro`, yielding `…IntegrationHubPage.` — a trailing
|
|
26
|
+
* dot git rejects (`fatal: not a valid branch name`). Truncating first, then
|
|
27
|
+
* stripping, guarantees the cap can never re-introduce an invalid ref.
|
|
21
28
|
*/
|
|
22
29
|
export function sanitizeBranchComponent(raw, fallback = 'scope') {
|
|
23
30
|
let slug = raw
|
|
@@ -27,12 +34,13 @@ export function sanitizeBranchComponent(raw, fallback = 'scope') {
|
|
|
27
34
|
.replace(/[^a-zA-Z0-9._-]/g, '-') // conservative whitelist for the rest
|
|
28
35
|
.replace(/-+/g, '-') // collapse dashes
|
|
29
36
|
.replace(/^[.-]+/, '') // no leading dot/dash
|
|
30
|
-
.
|
|
37
|
+
.slice(0, 48) // length cap BEFORE the trailing strips
|
|
38
|
+
.replace(/[.-]+$/, ''); // no trailing dot/dash (cut may have made one)
|
|
31
39
|
if (/\.lock$/i.test(slug))
|
|
32
|
-
slug = slug.slice(0, -'.lock'.length);
|
|
40
|
+
slug = slug.slice(0, -'.lock'.length).replace(/[.-]+$/, '');
|
|
33
41
|
if (!slug)
|
|
34
42
|
slug = fallback;
|
|
35
|
-
return slug
|
|
43
|
+
return slug;
|
|
36
44
|
}
|
|
37
45
|
/**
|
|
38
46
|
* Stack marker → shared directories mapping.
|
|
@@ -181,8 +189,40 @@ export function resolveWorktreePath(mainWorktreePath, branchName) {
|
|
|
181
189
|
const slug = branchName.replace(/[^a-zA-Z0-9._-]/g, '_').slice(0, 64);
|
|
182
190
|
return path.join(worktreesBaseDir(mainWorktreePath), slug);
|
|
183
191
|
}
|
|
184
|
-
|
|
185
|
-
|
|
192
|
+
/**
|
|
193
|
+
* Default timeout for quick git metadata queries (rev-parse, status, branch…).
|
|
194
|
+
* `git worktree add` is the exception — it materialises the entire working tree
|
|
195
|
+
* and on a large repo / Windows (Defender) easily exceeds this, so it passes an
|
|
196
|
+
* explicit, much larger timeout (see resolveWorktreeAddTimeoutMs).
|
|
197
|
+
*
|
|
198
|
+
* Dogfood 1.10.1: a 662-file site checkout was SIGTERM-killed at ~94% by this
|
|
199
|
+
* flat 15s cap, surfacing as a misleading "git worktree add failed: …Updating
|
|
200
|
+
* files: 94%" — the branch name was fine; the checkout simply ran out of time.
|
|
201
|
+
*/
|
|
202
|
+
const GIT_QUERY_TIMEOUT_MS = 15000;
|
|
203
|
+
/**
|
|
204
|
+
* Timeout for `git worktree add` (full working-tree checkout). Defaults to 120s;
|
|
205
|
+
* override with BRAINCLAW_WORKTREE_ADD_TIMEOUT_MS (milliseconds) for very large
|
|
206
|
+
* repos or slow filesystems.
|
|
207
|
+
*/
|
|
208
|
+
export function resolveWorktreeAddTimeoutMs() {
|
|
209
|
+
const raw = process.env.BRAINCLAW_WORKTREE_ADD_TIMEOUT_MS;
|
|
210
|
+
const n = raw ? Number.parseInt(raw, 10) : NaN;
|
|
211
|
+
return Number.isFinite(n) && n > 0 ? n : 120_000;
|
|
212
|
+
}
|
|
213
|
+
function runGit(args, cwd, timeoutMs = GIT_QUERY_TIMEOUT_MS) {
|
|
214
|
+
const result = spawnSync('git', args, { cwd, encoding: 'utf-8', timeout: timeoutMs });
|
|
215
|
+
// spawnSync kills on timeout (SIGTERM) and sets error.code=ETIMEDOUT; the raw
|
|
216
|
+
// stderr is then just partial progress ("Updating files: …%"), which reads as
|
|
217
|
+
// a cryptic failure. Surface the real cause — the timeout — instead.
|
|
218
|
+
if (result.error?.code === 'ETIMEDOUT') {
|
|
219
|
+
const hint = args[0] === 'worktree' ? ' (large checkout? raise BRAINCLAW_WORKTREE_ADD_TIMEOUT_MS)' : '';
|
|
220
|
+
return {
|
|
221
|
+
ok: false,
|
|
222
|
+
stdout: result.stdout ?? '',
|
|
223
|
+
stderr: `git ${args[0]} timed out after ${timeoutMs}ms and was killed${hint}.`,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
186
226
|
return {
|
|
187
227
|
ok: result.status === 0,
|
|
188
228
|
stdout: result.stdout ?? '',
|
|
@@ -496,7 +536,7 @@ export function createWorktree(mainWorktreePath, branchName, options = {}) {
|
|
|
496
536
|
const worktreeArgs = branchExists
|
|
497
537
|
? ['worktree', 'add', gitTargetPath, branchName]
|
|
498
538
|
: ['worktree', 'add', '-b', branchName, gitTargetPath, baseRef];
|
|
499
|
-
const result = runGit(worktreeArgs, mainWorktreePath);
|
|
539
|
+
const result = runGit(worktreeArgs, mainWorktreePath, resolveWorktreeAddTimeoutMs());
|
|
500
540
|
if (!result.ok) {
|
|
501
541
|
throw new Error(`git worktree add failed: ${result.stderr.trim()}`);
|
|
502
542
|
}
|
package/dist/facts.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// Generated by scripts/emit-site-facts.mjs at build time. Do not edit manually.
|
|
2
|
-
// Source: brainclaw v1.10.
|
|
2
|
+
// Source: brainclaw v1.10.2 on 2026-06-21T23:44:46.631Z
|
|
3
3
|
export const FACTS = {
|
|
4
|
-
"version": "1.10.
|
|
5
|
-
"generated_at": "2026-06-
|
|
4
|
+
"version": "1.10.2",
|
|
5
|
+
"generated_at": "2026-06-21T23:44:46.631Z",
|
|
6
6
|
"tools": {
|
|
7
7
|
"count": 66,
|
|
8
8
|
"published_count": 65,
|
package/dist/facts.json
CHANGED