@nanonets/graft 0.21.0 → 0.22.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.
- package/README.md +549 -315
- package/dist/app/review-process.d.ts.map +1 -1
- package/dist/app/review-process.js +6 -5
- package/dist/app/review-process.js.map +1 -1
- package/dist/app/sources.js +2 -2
- package/dist/app/sources.js.map +1 -1
- package/dist/ask/ask.d.ts +12 -6
- package/dist/ask/ask.d.ts.map +1 -1
- package/dist/ask/ask.js +28 -38
- package/dist/ask/ask.js.map +1 -1
- package/dist/bin/graft.d.ts +3 -0
- package/dist/bin/graft.d.ts.map +1 -0
- package/dist/bin/graft.js +8 -0
- package/dist/bin/graft.js.map +1 -0
- package/dist/bin/trail.d.ts +3 -0
- package/dist/bin/trail.d.ts.map +1 -0
- package/dist/bin/trail.js +6 -0
- package/dist/bin/trail.js.map +1 -0
- package/dist/blast/blast-cli.d.ts.map +1 -1
- package/dist/blast/blast-cli.js +2 -1
- package/dist/blast/blast-cli.js.map +1 -1
- package/dist/blast/render.d.ts.map +1 -1
- package/dist/blast/render.js +3 -2
- package/dist/blast/render.js.map +1 -1
- package/dist/brand.d.ts +97 -0
- package/dist/brand.d.ts.map +1 -0
- package/dist/brand.js +254 -0
- package/dist/brand.js.map +1 -0
- package/dist/check/local-check.d.ts +104 -0
- package/dist/check/local-check.d.ts.map +1 -0
- package/dist/check/local-check.js +830 -0
- package/dist/check/local-check.js.map +1 -0
- package/dist/check/types.d.ts +31 -0
- package/dist/check/types.d.ts.map +1 -0
- package/dist/check/types.js +2 -0
- package/dist/check/types.js.map +1 -0
- package/dist/claude/format.d.ts +44 -1
- package/dist/claude/format.d.ts.map +1 -1
- package/dist/claude/format.js +113 -19
- package/dist/claude/format.js.map +1 -1
- package/dist/claude/hook-layers.d.ts +8 -0
- package/dist/claude/hook-layers.d.ts.map +1 -0
- package/dist/claude/hook-layers.js +72 -0
- package/dist/claude/hook-layers.js.map +1 -0
- package/dist/claude/hooks.d.ts +34 -0
- package/dist/claude/hooks.d.ts.map +1 -1
- package/dist/claude/hooks.js +220 -12
- package/dist/claude/hooks.js.map +1 -1
- package/dist/claude/init.d.ts +12 -1
- package/dist/claude/init.d.ts.map +1 -1
- package/dist/claude/init.js +48 -19
- package/dist/claude/init.js.map +1 -1
- package/dist/claude/session-metrics.d.ts +1 -1
- package/dist/claude/session-metrics.d.ts.map +1 -1
- package/dist/claude/session-metrics.js +11 -8
- package/dist/claude/session-metrics.js.map +1 -1
- package/dist/claude/settings-merge.d.ts +1 -0
- package/dist/claude/settings-merge.d.ts.map +1 -1
- package/dist/claude/settings-merge.js +21 -18
- package/dist/claude/settings-merge.js.map +1 -1
- package/dist/claude/shim-template.d.ts +17 -2
- package/dist/claude/shim-template.d.ts.map +1 -1
- package/dist/claude/shim-template.js +116 -22
- package/dist/claude/shim-template.js.map +1 -1
- package/dist/claude/skill-template.d.ts +10 -1
- package/dist/claude/skill-template.d.ts.map +1 -1
- package/dist/claude/skill-template.js +132 -1
- package/dist/claude/skill-template.js.map +1 -1
- package/dist/claude/state.d.ts +8 -0
- package/dist/claude/state.d.ts.map +1 -1
- package/dist/claude/state.js.map +1 -1
- package/dist/claude/statusline.d.ts.map +1 -1
- package/dist/claude/statusline.js +4 -1
- package/dist/claude/statusline.js.map +1 -1
- package/dist/claude/tally.js +1 -1
- package/dist/claude/tally.js.map +1 -1
- package/dist/cli-epilogue.d.ts +0 -6
- package/dist/cli-epilogue.d.ts.map +1 -1
- package/dist/cli-epilogue.js +5 -4
- package/dist/cli-epilogue.js.map +1 -1
- package/dist/cli-meta.d.ts +8 -0
- package/dist/cli-meta.d.ts.map +1 -1
- package/dist/cli-meta.js +28 -8
- package/dist/cli-meta.js.map +1 -1
- package/dist/cli-picker.d.ts.map +1 -1
- package/dist/cli-picker.js +11 -7
- package/dist/cli-picker.js.map +1 -1
- package/dist/cli.d.ts +0 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1037 -595
- package/dist/cli.js.map +1 -1
- package/dist/cloud/diff.d.ts +18 -0
- package/dist/cloud/diff.d.ts.map +1 -0
- package/dist/cloud/diff.js +58 -0
- package/dist/cloud/diff.js.map +1 -0
- package/dist/cloud/nudge.d.ts +66 -0
- package/dist/cloud/nudge.d.ts.map +1 -0
- package/dist/cloud/nudge.js +269 -0
- package/dist/cloud/nudge.js.map +1 -0
- package/dist/cloud/workspace-sync.d.ts +58 -0
- package/dist/cloud/workspace-sync.d.ts.map +1 -0
- package/dist/cloud/workspace-sync.js +268 -0
- package/dist/cloud/workspace-sync.js.map +1 -0
- package/dist/cloud/workspace.d.ts +159 -0
- package/dist/cloud/workspace.d.ts.map +1 -0
- package/dist/cloud/workspace.js +134 -0
- package/dist/cloud/workspace.js.map +1 -0
- package/dist/context/check.d.ts +1 -1
- package/dist/context/check.d.ts.map +1 -1
- package/dist/context/check.js +9 -8
- package/dist/context/check.js.map +1 -1
- package/dist/context/node-file.js +1 -1
- package/dist/context/node-file.js.map +1 -1
- package/dist/context/savings.d.ts.map +1 -1
- package/dist/context/savings.js +10 -7
- package/dist/context/savings.js.map +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +3 -1
- package/dist/engine.js.map +1 -1
- package/dist/graph/build.d.ts +30 -0
- package/dist/graph/build.d.ts.map +1 -1
- package/dist/graph/build.js +65 -19
- package/dist/graph/build.js.map +1 -1
- package/dist/graph/cards.d.ts.map +1 -1
- package/dist/graph/cards.js +4 -2
- package/dist/graph/cards.js.map +1 -1
- package/dist/graph/check.d.ts.map +1 -1
- package/dist/graph/check.js +17 -18
- package/dist/graph/check.js.map +1 -1
- package/dist/graph/container.d.ts.map +1 -1
- package/dist/graph/container.js +7 -2
- package/dist/graph/container.js.map +1 -1
- package/dist/graph/extract-cache.d.ts +4 -0
- package/dist/graph/extract-cache.d.ts.map +1 -1
- package/dist/graph/extract-cache.js.map +1 -1
- package/dist/graph/extract.d.ts +2 -0
- package/dist/graph/extract.d.ts.map +1 -1
- package/dist/graph/extract.js +5 -32
- package/dist/graph/extract.js.map +1 -1
- package/dist/graph/generic.d.ts +7 -1
- package/dist/graph/generic.d.ts.map +1 -1
- package/dist/graph/generic.js +48 -8
- package/dist/graph/generic.js.map +1 -1
- package/dist/graph/native.d.ts +38 -0
- package/dist/graph/native.d.ts.map +1 -0
- package/dist/graph/native.js +169 -0
- package/dist/graph/native.js.map +1 -0
- package/dist/graph/refresh.d.ts.map +1 -1
- package/dist/graph/refresh.js +3 -2
- package/dist/graph/refresh.js.map +1 -1
- package/dist/graph/traverse-cli.d.ts.map +1 -1
- package/dist/graph/traverse-cli.js +4 -3
- package/dist/graph/traverse-cli.js.map +1 -1
- package/dist/graph/workspace-cli.d.ts +2 -0
- package/dist/graph/workspace-cli.d.ts.map +1 -1
- package/dist/graph/workspace-cli.js +13 -1
- package/dist/graph/workspace-cli.js.map +1 -1
- package/dist/graph/workspace.d.ts.map +1 -1
- package/dist/graph/workspace.js +6 -5
- package/dist/graph/workspace.js.map +1 -1
- package/dist/hosts/antigravity.d.ts +10 -3
- package/dist/hosts/antigravity.d.ts.map +1 -1
- package/dist/hosts/antigravity.js +27 -10
- package/dist/hosts/antigravity.js.map +1 -1
- package/dist/hosts/claude-global.d.ts +27 -4
- package/dist/hosts/claude-global.d.ts.map +1 -1
- package/dist/hosts/claude-global.js +90 -9
- package/dist/hosts/claude-global.js.map +1 -1
- package/dist/hosts/codex-hooks.d.ts.map +1 -1
- package/dist/hosts/codex-hooks.js +1 -2
- package/dist/hosts/codex-hooks.js.map +1 -1
- package/dist/hosts/config-write.d.ts.map +1 -1
- package/dist/hosts/config-write.js +2 -1
- package/dist/hosts/config-write.js.map +1 -1
- package/dist/hosts/cursor-hooks.d.ts +5 -2
- package/dist/hosts/cursor-hooks.d.ts.map +1 -1
- package/dist/hosts/cursor-hooks.js +14 -9
- package/dist/hosts/cursor-hooks.js.map +1 -1
- package/dist/hosts/init.d.ts +3 -0
- package/dist/hosts/init.d.ts.map +1 -1
- package/dist/hosts/init.js +32 -10
- package/dist/hosts/init.js.map +1 -1
- package/dist/hosts/instructions.d.ts +9 -4
- package/dist/hosts/instructions.d.ts.map +1 -1
- package/dist/hosts/instructions.js +19 -16
- package/dist/hosts/instructions.js.map +1 -1
- package/dist/hosts/mcp-config.d.ts +19 -4
- package/dist/hosts/mcp-config.d.ts.map +1 -1
- package/dist/hosts/mcp-config.js +81 -30
- package/dist/hosts/mcp-config.js.map +1 -1
- package/dist/hosts/plan.d.ts.map +1 -1
- package/dist/hosts/plan.js +11 -9
- package/dist/hosts/plan.js.map +1 -1
- package/dist/hosts/registry.d.ts +25 -2
- package/dist/hosts/registry.d.ts.map +1 -1
- package/dist/hosts/registry.js +53 -0
- package/dist/hosts/registry.js.map +1 -1
- package/dist/hosts/retract.d.ts.map +1 -1
- package/dist/hosts/retract.js +73 -33
- package/dist/hosts/retract.js.map +1 -1
- package/dist/hosts/sections.d.ts +17 -1
- package/dist/hosts/sections.d.ts.map +1 -1
- package/dist/hosts/sections.js +52 -2
- package/dist/hosts/sections.js.map +1 -1
- package/dist/mcp/instructions.d.ts +1 -25
- package/dist/mcp/instructions.d.ts.map +1 -1
- package/dist/mcp/instructions.js +6 -4
- package/dist/mcp/instructions.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +7 -3
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tool-names.d.ts +10 -3
- package/dist/mcp/tool-names.d.ts.map +1 -1
- package/dist/mcp/tool-names.js +13 -5
- package/dist/mcp/tool-names.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +6 -5
- package/dist/mcp/tools.js.map +1 -1
- package/dist/notes/ask-notes.d.ts +8 -0
- package/dist/notes/ask-notes.d.ts.map +1 -0
- package/dist/notes/ask-notes.js +18 -0
- package/dist/notes/ask-notes.js.map +1 -0
- package/dist/notes/branches.d.ts +85 -0
- package/dist/notes/branches.d.ts.map +1 -0
- package/dist/notes/branches.js +238 -0
- package/dist/notes/branches.js.map +1 -0
- package/dist/notes/cold-start.d.ts +127 -0
- package/dist/notes/cold-start.d.ts.map +1 -0
- package/dist/notes/cold-start.js +476 -0
- package/dist/notes/cold-start.js.map +1 -0
- package/dist/notes/git-facts.d.ts +17 -0
- package/dist/notes/git-facts.d.ts.map +1 -0
- package/dist/notes/git-facts.js +117 -0
- package/dist/notes/git-facts.js.map +1 -0
- package/dist/notes/home.d.ts +87 -0
- package/dist/notes/home.d.ts.map +1 -0
- package/dist/notes/home.js +423 -0
- package/dist/notes/home.js.map +1 -0
- package/dist/notes/notes.d.ts +178 -0
- package/dist/notes/notes.d.ts.map +1 -0
- package/dist/notes/notes.js +498 -0
- package/dist/notes/notes.js.map +1 -0
- package/dist/notes/repo-trail.d.ts +16 -0
- package/dist/notes/repo-trail.d.ts.map +1 -0
- package/dist/notes/repo-trail.js +74 -0
- package/dist/notes/repo-trail.js.map +1 -0
- package/dist/notes/session-cost.d.ts +21 -0
- package/dist/notes/session-cost.d.ts.map +1 -0
- package/dist/notes/session-cost.js +162 -0
- package/dist/notes/session-cost.js.map +1 -0
- package/dist/search/grep-cli.d.ts.map +1 -1
- package/dist/search/grep-cli.js +4 -3
- package/dist/search/grep-cli.js.map +1 -1
- package/dist/skills/skills.d.ts +118 -0
- package/dist/skills/skills.d.ts.map +1 -0
- package/dist/skills/skills.js +370 -0
- package/dist/skills/skills.js.map +1 -0
- package/dist/telemetry/contract.d.ts +2 -14
- package/dist/telemetry/contract.d.ts.map +1 -1
- package/dist/telemetry/contract.js +39 -24
- package/dist/telemetry/contract.js.map +1 -1
- package/dist/telemetry/gate.d.ts.map +1 -1
- package/dist/telemetry/gate.js +2 -1
- package/dist/telemetry/gate.js.map +1 -1
- package/dist/telemetry/notice.d.ts +1 -1
- package/dist/telemetry/notice.d.ts.map +1 -1
- package/dist/telemetry/notice.js +6 -5
- package/dist/telemetry/notice.js.map +1 -1
- package/dist/telemetry/track.d.ts.map +1 -1
- package/dist/telemetry/track.js +5 -0
- package/dist/telemetry/track.js.map +1 -1
- package/dist/upkeep-run.d.ts +7 -0
- package/dist/upkeep-run.d.ts.map +1 -1
- package/dist/upkeep-run.js +52 -12
- package/dist/upkeep-run.js.map +1 -1
- package/dist/upkeep.d.ts +9 -19
- package/dist/upkeep.d.ts.map +1 -1
- package/dist/upkeep.js +38 -59
- package/dist/upkeep.js.map +1 -1
- package/dist/util/browser.d.ts +3 -0
- package/dist/util/browser.d.ts.map +1 -0
- package/dist/util/browser.js +14 -0
- package/dist/util/browser.js.map +1 -0
- package/dist/util/front-matter.d.ts +19 -0
- package/dist/util/front-matter.d.ts.map +1 -0
- package/dist/util/front-matter.js +21 -0
- package/dist/util/front-matter.js.map +1 -0
- package/dist/util/state.d.ts +1 -18
- package/dist/util/state.d.ts.map +1 -1
- package/dist/util/state.js +4 -2
- package/dist/util/state.js.map +1 -1
- package/dist/viz/assemble.js +1 -1
- package/dist/viz/assemble.js.map +1 -1
- package/dist/viz/serve.d.ts.map +1 -1
- package/dist/viz/serve.js +4 -3
- package/dist/viz/serve.js.map +1 -1
- package/package.json +7 -7
- package/scripts/pack-trail.mjs +53 -0
- package/scripts/postinstall.mjs +17 -2
- package/scripts/run-tests.mjs +4 -1
- package/dist/brain/attach.d.ts +0 -44
- package/dist/brain/attach.d.ts.map +0 -1
- package/dist/brain/attach.js +0 -63
- package/dist/brain/attach.js.map +0 -1
- package/dist/brain/claude-md.d.ts +0 -61
- package/dist/brain/claude-md.d.ts.map +0 -1
- package/dist/brain/claude-md.js +0 -171
- package/dist/brain/claude-md.js.map +0 -1
- package/dist/brain/connect.d.ts +0 -59
- package/dist/brain/connect.d.ts.map +0 -1
- package/dist/brain/connect.js +0 -80
- package/dist/brain/connect.js.map +0 -1
- package/dist/brain/context-files.d.ts +0 -79
- package/dist/brain/context-files.d.ts.map +0 -1
- package/dist/brain/context-files.js +0 -245
- package/dist/brain/context-files.js.map +0 -1
- package/dist/brain/link.d.ts +0 -106
- package/dist/brain/link.d.ts.map +0 -1
- package/dist/brain/link.js +0 -167
- package/dist/brain/link.js.map +0 -1
- package/dist/brain/pull.d.ts +0 -17
- package/dist/brain/pull.d.ts.map +0 -1
- package/dist/brain/pull.js +0 -172
- package/dist/brain/pull.js.map +0 -1
- package/dist/brain/push.d.ts +0 -155
- package/dist/brain/push.d.ts.map +0 -1
- package/dist/brain/push.js +0 -304
- package/dist/brain/push.js.map +0 -1
- package/dist/brain/signup.d.ts +0 -117
- package/dist/brain/signup.d.ts.map +0 -1
- package/dist/brain/signup.js +0 -276
- package/dist/brain/signup.js.map +0 -1
- package/dist/brain/upload.d.ts +0 -61
- package/dist/brain/upload.d.ts.map +0 -1
- package/dist/brain/upload.js +0 -210
- package/dist/brain/upload.js.map +0 -1
- package/dist/brain/watch.d.ts +0 -209
- package/dist/brain/watch.d.ts.map +0 -1
- package/dist/brain/watch.js +0 -396
- package/dist/brain/watch.js.map +0 -1
- package/dist/brain/wire.d.ts +0 -38
- package/dist/brain/wire.d.ts.map +0 -1
- package/dist/brain/wire.js +0 -133
- package/dist/brain/wire.js.map +0 -1
- package/dist/legacy-args.d.ts +0 -12
- package/dist/legacy-args.d.ts.map +0 -1
- package/dist/legacy-args.js +0 -31
- package/dist/legacy-args.js.map +0 -1
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Teammates' pushed branches: which files each one changes, and the learnings
|
|
3
|
+
* it carries that the default branch doesn't have yet.
|
|
4
|
+
*
|
|
5
|
+
* This is how two people find out they're on the same thing before review,
|
|
6
|
+
* with no server: once work is pushed, `git fetch` brings it to every clone.
|
|
7
|
+
* Learnings committed on a branch reach everyone the same way, hours or days
|
|
8
|
+
* before the branch merges.
|
|
9
|
+
*
|
|
10
|
+
* Reading branches takes git, and hooks and `ask` must not wait on it, so a
|
|
11
|
+
* detached `_trail-branches` child fetches and writes what it found to a
|
|
12
|
+
* cache, at most every REFRESH_MS. Everything that reads it reads the cache.
|
|
13
|
+
*/
|
|
14
|
+
import { execFileSync, spawn } from "node:child_process";
|
|
15
|
+
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { graftCliPath } from "../claude/paths.js";
|
|
18
|
+
import { cacheDir, readJson, writeJsonAtomic } from "../util/state.js";
|
|
19
|
+
import { LEARNINGS_DIR } from "./repo-trail.js";
|
|
20
|
+
/** How old the cache may get before the next command refreshes it in the
|
|
21
|
+
* background: about what editors that fetch on their own wait between fetches. */
|
|
22
|
+
export const REFRESH_MS = 3 * 60 * 1000;
|
|
23
|
+
/** At the start of a session, a cache older than this is refreshed. */
|
|
24
|
+
export const SESSION_REFRESH_MS = 60 * 1000;
|
|
25
|
+
/** A refresh that started this long ago without finishing is presumed dead. */
|
|
26
|
+
const STALE_RUN_MS = 2 * 60 * 1000;
|
|
27
|
+
/** Branches older than this are finished or abandoned work, not overlap. */
|
|
28
|
+
export const BRANCH_WINDOW_MS = 30 * 24 * 60 * 60 * 1000;
|
|
29
|
+
/** Most branches read per refresh, newest first. */
|
|
30
|
+
const MAX_BRANCHES = 30;
|
|
31
|
+
/** Most changed files kept per branch. */
|
|
32
|
+
const MAX_FILES = 200;
|
|
33
|
+
/** A learning file name as `trail note` writes it: no folders, no shell characters. */
|
|
34
|
+
export const SAFE_LEARNING_NAME = /^[A-Za-z0-9._-]+\.md$/;
|
|
35
|
+
/** Most learnings read per branch, and the most bytes per learning. */
|
|
36
|
+
const MAX_LEARNINGS = 20;
|
|
37
|
+
const MAX_LEARNING_BYTES = 64 * 1024;
|
|
38
|
+
function cachePath(repo) {
|
|
39
|
+
return join(cacheDir(repo), "trail-branches.json");
|
|
40
|
+
}
|
|
41
|
+
export function readBranchCache(repo) {
|
|
42
|
+
return readJson(cachePath(repo));
|
|
43
|
+
}
|
|
44
|
+
function git(repo, args, timeout = 15_000) {
|
|
45
|
+
try {
|
|
46
|
+
// Never a credential prompt: this runs detached, where nobody could answer it.
|
|
47
|
+
return execFileSync("git", args, {
|
|
48
|
+
cwd: repo,
|
|
49
|
+
encoding: "utf8",
|
|
50
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
51
|
+
timeout,
|
|
52
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
53
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" },
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** First word of a name, capitalised, the way a learning's author is written. Letters only, at most 40. */
|
|
61
|
+
function firstName(name) {
|
|
62
|
+
const first = (name.trim().split(/\s+/)[0] ?? "").replace(/[^\p{L}\p{N}._-]/gu, "").slice(0, 40);
|
|
63
|
+
return first ? first[0].toUpperCase() + first.slice(1) : "";
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* A branch name as it may appear in what the agent reads: the characters git
|
|
67
|
+
* branch names are usually made of, at most 80. Branch names and authors come
|
|
68
|
+
* from whoever pushed, so nothing else of theirs reaches an instruction.
|
|
69
|
+
*/
|
|
70
|
+
export function safeRef(ref) {
|
|
71
|
+
return ref.replace(/[^A-Za-z0-9._/-]/g, "").slice(0, 80);
|
|
72
|
+
}
|
|
73
|
+
/** The remote branch everything is compared with: what origin/HEAD points at, else a usual name. */
|
|
74
|
+
function defaultRef(repo) {
|
|
75
|
+
const head = git(repo, ["symbolic-ref", "--quiet", "--short", "refs/remotes/origin/HEAD"])?.trim();
|
|
76
|
+
if (head)
|
|
77
|
+
return head;
|
|
78
|
+
for (const name of ["origin/main", "origin/master", "origin/trunk", "origin/dev"]) {
|
|
79
|
+
if (git(repo, ["rev-parse", "--verify", "--quiet", name]) !== null)
|
|
80
|
+
return name;
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Fetch, then read every recently pushed branch: the files it changes and the
|
|
86
|
+
* learnings it adds. Writes the cache and returns it. `fetch: false` reads
|
|
87
|
+
* the refs already on this machine, for tests and for a repo that's offline.
|
|
88
|
+
*/
|
|
89
|
+
export function refreshBranches(repo, opts = {}) {
|
|
90
|
+
const now = opts.now ?? Date.now();
|
|
91
|
+
// TRAIL_NO_FETCH: tests, and anyone who'd rather fetch themselves.
|
|
92
|
+
if (opts.fetch !== false && !process.env.TRAIL_NO_FETCH)
|
|
93
|
+
git(repo, ["fetch", "--quiet", "--prune", "origin"], opts.fetchTimeoutMs ?? 30_000);
|
|
94
|
+
const base = defaultRef(repo);
|
|
95
|
+
const branches = [];
|
|
96
|
+
if (base) {
|
|
97
|
+
const listed = git(repo, ["for-each-ref", "--sort=-committerdate", "--format=%(refname:short)%09%(committerdate:unix)%09%(authorname)", "refs/remotes/origin"]) ?? "";
|
|
98
|
+
for (const line of listed.split("\n")) {
|
|
99
|
+
if (branches.length >= MAX_BRANCHES)
|
|
100
|
+
break;
|
|
101
|
+
const [ref, unix, author] = line.split("\t");
|
|
102
|
+
if (!ref || ref === base || ref === "origin/HEAD" || ref === "origin")
|
|
103
|
+
continue;
|
|
104
|
+
// A name made only of what branch names are usually made of, or the branch is skipped:
|
|
105
|
+
// it reaches what the agent reads, and a cleaned-up copy would name a different branch.
|
|
106
|
+
if (safeRef(ref) !== ref)
|
|
107
|
+
continue;
|
|
108
|
+
const at = Number(unix) * 1000;
|
|
109
|
+
if (!Number.isFinite(at) || now - at > BRANCH_WINDOW_MS)
|
|
110
|
+
continue;
|
|
111
|
+
const changed = (git(repo, ["diff", "--name-only", `${base}...${ref}`]) ?? "").split("\n").map((f) => f.trim()).filter(Boolean);
|
|
112
|
+
if (changed.length === 0)
|
|
113
|
+
continue;
|
|
114
|
+
const learnings = [];
|
|
115
|
+
// Only names trail itself would write: the name reaches a command the agent may run.
|
|
116
|
+
const named = changed.filter((f) => f.startsWith(`${LEARNINGS_DIR}/`) && SAFE_LEARNING_NAME.test(f.slice(LEARNINGS_DIR.length + 1)));
|
|
117
|
+
for (const path of named.slice(0, MAX_LEARNINGS)) {
|
|
118
|
+
const text = git(repo, ["show", `${ref}:${path}`]);
|
|
119
|
+
if (text && text.length <= MAX_LEARNING_BYTES)
|
|
120
|
+
learnings.push({ name: path.slice(LEARNINGS_DIR.length + 1), text });
|
|
121
|
+
}
|
|
122
|
+
branches.push({ ref, author: firstName(author ?? ""), at, files: changed.slice(0, MAX_FILES), learnings });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const cache = { fetchedAt: Date.now(), stamp: refsStamp(repo), base, branches };
|
|
126
|
+
writeJsonAtomic(cachePath(repo), cache, true);
|
|
127
|
+
return cache;
|
|
128
|
+
}
|
|
129
|
+
/** The checkout's shared git dir: `.git`, or for a linked worktree the main one's. Read, never spawned. */
|
|
130
|
+
function commonGitDir(repo) {
|
|
131
|
+
const dot = join(repo, ".git");
|
|
132
|
+
try {
|
|
133
|
+
if (statSync(dot).isDirectory())
|
|
134
|
+
return dot;
|
|
135
|
+
const line = readFileSync(dot, "utf8").split("\n").find((l) => l.startsWith("gitdir:"));
|
|
136
|
+
const gitDir = line?.slice("gitdir:".length).trim();
|
|
137
|
+
if (!gitDir)
|
|
138
|
+
return null;
|
|
139
|
+
try {
|
|
140
|
+
return join(gitDir, readFileSync(join(gitDir, "commondir"), "utf8").trim());
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return gitDir;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* When this clone's idea of the remote last changed: the newest mtime under
|
|
152
|
+
* `refs/remotes/`, `packed-refs` and `FETCH_HEAD`. A push updates the
|
|
153
|
+
* remote-tracking ref it pushed, and a fetch rewrites FETCH_HEAD, so either
|
|
154
|
+
* shows here without running git.
|
|
155
|
+
*/
|
|
156
|
+
export function refsStamp(repo) {
|
|
157
|
+
const dir = commonGitDir(repo);
|
|
158
|
+
if (!dir)
|
|
159
|
+
return "";
|
|
160
|
+
let newest = 0;
|
|
161
|
+
const walk = (p, depth) => {
|
|
162
|
+
try {
|
|
163
|
+
const st = statSync(p);
|
|
164
|
+
newest = Math.max(newest, st.mtimeMs);
|
|
165
|
+
if (st.isDirectory() && depth < 6)
|
|
166
|
+
for (const e of readdirSync(p))
|
|
167
|
+
walk(join(p, e), depth + 1);
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
/* gone, or never there */
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
walk(join(dir, "refs", "remotes"), 0);
|
|
174
|
+
for (const f of ["packed-refs", "FETCH_HEAD"])
|
|
175
|
+
walk(join(dir, f), 6);
|
|
176
|
+
return String(Math.round(newest));
|
|
177
|
+
}
|
|
178
|
+
/** Whether the cache is older than `maxAgeMs`, or the clone's remote refs moved since it was written. */
|
|
179
|
+
export function branchesStale(repo, now = Date.now(), maxAgeMs = REFRESH_MS) {
|
|
180
|
+
const cache = readBranchCache(repo);
|
|
181
|
+
return !cache || now - cache.fetchedAt >= maxAgeMs || cache.stamp !== refsStamp(repo);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Refresh in a detached child when the cache is older than `maxAgeMs`, or
|
|
185
|
+
* the clone's remote refs moved since (a push, a fetch), and no refresh is
|
|
186
|
+
* already running. Never waits, never throws. A checkout with no origin gets
|
|
187
|
+
* an empty cache.
|
|
188
|
+
*/
|
|
189
|
+
export function maybeRefreshBranches(repo, now = Date.now(), maxAgeMs = REFRESH_MS) {
|
|
190
|
+
try {
|
|
191
|
+
const cache = readBranchCache(repo);
|
|
192
|
+
if (!branchesStale(repo, now, maxAgeMs))
|
|
193
|
+
return false;
|
|
194
|
+
if (cache?.runningSince && now - cache.runningSince < STALE_RUN_MS)
|
|
195
|
+
return false;
|
|
196
|
+
writeJsonAtomic(cachePath(repo), { ...(cache ?? { fetchedAt: 0, base: null, branches: [] }), runningSince: now }, true);
|
|
197
|
+
const child = spawn(process.execPath, [graftCliPath(), "_trail-branches", repo], { detached: true, stdio: "ignore", windowsHide: true });
|
|
198
|
+
child.unref();
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Teammates' pushed branches that change any of `files`: work going on in the
|
|
207
|
+
* same place, from someone other than `me`, newest first.
|
|
208
|
+
*/
|
|
209
|
+
export function overlapsWith(repo, files, me, cache = readBranchCache(repo)) {
|
|
210
|
+
if (!cache || files.length === 0)
|
|
211
|
+
return [];
|
|
212
|
+
const mine = new Set(files.filter((f) => !f.startsWith(".trail/")));
|
|
213
|
+
const out = [];
|
|
214
|
+
for (const b of cache.branches) {
|
|
215
|
+
if (!b.author || b.author === me)
|
|
216
|
+
continue;
|
|
217
|
+
const shared = b.files.filter((f) => mine.has(f));
|
|
218
|
+
if (shared.length)
|
|
219
|
+
out.push({ ref: b.ref, author: b.author, at: b.at, shared });
|
|
220
|
+
}
|
|
221
|
+
return out.sort((a, b) => b.at - a.at);
|
|
222
|
+
}
|
|
223
|
+
const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
224
|
+
/** `today 14:20`, `Oct 7`: when a branch was pushed, short. */
|
|
225
|
+
export function pushedWhen(at, now = Date.now()) {
|
|
226
|
+
const d = new Date(at);
|
|
227
|
+
const n = new Date(now);
|
|
228
|
+
if (d.toDateString() === n.toDateString())
|
|
229
|
+
return `today ${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
|
|
230
|
+
return `${MONTHS[d.getMonth()]} ${d.getDate()}`;
|
|
231
|
+
}
|
|
232
|
+
/** `● overlap · Kumar's branch kumar/jitter also changes client.go (pushed today 14:20)`. */
|
|
233
|
+
export function formatOverlap(o, now = Date.now()) {
|
|
234
|
+
const branch = o.ref.replace(/^origin\//, "");
|
|
235
|
+
const files = o.shared.length <= 2 ? o.shared.join(" and ") : `${o.shared.slice(0, 2).join(", ")} and ${o.shared.length - 2} more`;
|
|
236
|
+
return `● overlap · ${o.author}'s branch ${branch} also changes ${files} (pushed ${pushedWhen(o.at, now)})`;
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=branches.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branches.js","sourceRoot":"","sources":["../../src/notes/branches.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { type Note } from "./notes.js";
|
|
2
|
+
/** One message the person wrote, with the end of what Claude said just before it. */
|
|
3
|
+
export interface PastPrompt {
|
|
4
|
+
text: string;
|
|
5
|
+
/** The tail of Claude's last reply before this message, so "no, use a worktree" reads on its own. */
|
|
6
|
+
before?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface PastSession {
|
|
9
|
+
id: string;
|
|
10
|
+
/** ISO time of the first message. */
|
|
11
|
+
at: string;
|
|
12
|
+
branch?: string;
|
|
13
|
+
prompts: PastPrompt[];
|
|
14
|
+
}
|
|
15
|
+
export interface Finding {
|
|
16
|
+
title: string;
|
|
17
|
+
/** `team`: about the code or how the team works here. `you`: this person's own habits or machine. */
|
|
18
|
+
for: "team" | "you";
|
|
19
|
+
/** Markdown under `## Decided` and maybe `## Watch out`, secrets scrubbed. */
|
|
20
|
+
body: string;
|
|
21
|
+
/** Sessions the cited quotes were found in, newest first. */
|
|
22
|
+
sessions: string[];
|
|
23
|
+
/** YYYY-MM-DD of the newest of them. */
|
|
24
|
+
last: string;
|
|
25
|
+
quotes: string[];
|
|
26
|
+
}
|
|
27
|
+
export interface FindResult {
|
|
28
|
+
/** Past sessions with at least one message of the person's. */
|
|
29
|
+
sessions: number;
|
|
30
|
+
/** How many of them, newest first, Claude read. */
|
|
31
|
+
read: number;
|
|
32
|
+
findings: Finding[];
|
|
33
|
+
model: string;
|
|
34
|
+
durationMs: number;
|
|
35
|
+
costUsd?: number;
|
|
36
|
+
/** Why nothing came back, when nothing did. */
|
|
37
|
+
reason?: "no_sessions" | "no_claude" | "failed" | "none_found";
|
|
38
|
+
}
|
|
39
|
+
/** Sonnet: on assign's history it merged related corrections into fewer, stronger findings than Haiku. */
|
|
40
|
+
export declare const COLD_START_MODEL = "claude-sonnet-5-5";
|
|
41
|
+
/**
|
|
42
|
+
* The checkout `repo` belongs to and every worktree of it git still lists:
|
|
43
|
+
* sessions run in any of them, or in a folder under one, are this repo's.
|
|
44
|
+
* Worktrees git has forgotten were usually under the main checkout
|
|
45
|
+
* (`.claude/worktrees/…`), so their sessions are still found under it.
|
|
46
|
+
*/
|
|
47
|
+
export declare function repoRoots(repo: string): string[];
|
|
48
|
+
/**
|
|
49
|
+
* Transcript files for sessions run inside `roots`. Claude Code names a
|
|
50
|
+
* project's folder after its path with every other character as `-`, so a
|
|
51
|
+
* folder under a root starts with the root's name; but so does a sibling like
|
|
52
|
+
* `assign-old`, so each file's own `cwd` decides.
|
|
53
|
+
*/
|
|
54
|
+
export declare function sessionFiles(roots: string[], home?: string): string[];
|
|
55
|
+
/** The person's message with what isn't theirs taken out, or null when nothing of theirs is left. */
|
|
56
|
+
export declare function ownWords(raw: string): string | null;
|
|
57
|
+
/**
|
|
58
|
+
* One transcript's messages from the person, oldest first. Headless runs
|
|
59
|
+
* (`claude -p`, scripts) are skipped whole: their prompts were written once
|
|
60
|
+
* and replayed, so a repeat there isn't the person repeating themselves.
|
|
61
|
+
*/
|
|
62
|
+
export declare function readSession(path: string): PastSession | null;
|
|
63
|
+
/** Every past session of the repo with something the person wrote, newest first. */
|
|
64
|
+
export declare function pastSessions(repo: string, home?: string): PastSession[];
|
|
65
|
+
/**
|
|
66
|
+
* The sessions as one text for Claude, newest first, cut at `maxChars`. Each
|
|
67
|
+
* session is headed by a short id that the findings cite back.
|
|
68
|
+
*/
|
|
69
|
+
export declare function digest(sessions: PastSession[], maxChars?: number): {
|
|
70
|
+
text: string;
|
|
71
|
+
ids: Map<string, string>;
|
|
72
|
+
};
|
|
73
|
+
interface RawFinding {
|
|
74
|
+
title?: string;
|
|
75
|
+
for?: string;
|
|
76
|
+
body?: string;
|
|
77
|
+
evidence?: {
|
|
78
|
+
session?: string;
|
|
79
|
+
quote?: string;
|
|
80
|
+
}[];
|
|
81
|
+
}
|
|
82
|
+
/** Whether `claude` (Claude Code) is on PATH. */
|
|
83
|
+
export declare function hasClaude(): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* The findings whose quotes are really in the person's messages, in two or
|
|
86
|
+
* more sessions, best first. A quote filed under the wrong session still
|
|
87
|
+
* counts for the session it's in.
|
|
88
|
+
*/
|
|
89
|
+
export declare function verify(raw: RawFinding[], sessions: PastSession[], ids: Map<string, string>): Finding[];
|
|
90
|
+
/** Anything that looks like a credential, a key or an email address, replaced. Learnings get committed. */
|
|
91
|
+
export declare function scrub(text: string): string;
|
|
92
|
+
/**
|
|
93
|
+
* What the person kept telling Claude in this repo, checked against their
|
|
94
|
+
* messages. Never throws: no sessions, no Claude Code, or a failed call come
|
|
95
|
+
* back as an empty list with the reason.
|
|
96
|
+
*/
|
|
97
|
+
export declare function findLearnings(repo: string, opts?: {
|
|
98
|
+
model?: string;
|
|
99
|
+
timeoutMs?: number;
|
|
100
|
+
home?: string;
|
|
101
|
+
limit?: number;
|
|
102
|
+
sessions?: PastSession[];
|
|
103
|
+
}): Promise<FindResult>;
|
|
104
|
+
export interface PastRead {
|
|
105
|
+
sessions: number;
|
|
106
|
+
started: number;
|
|
107
|
+
result: Promise<FindResult>;
|
|
108
|
+
done: boolean;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Start reading the repo's past Claude sessions, once per repo per machine,
|
|
112
|
+
* for `trail init` to collect at its end; null when there's nothing to read,
|
|
113
|
+
* it was read before, or TRAIL_NO_FETCH is set.
|
|
114
|
+
*/
|
|
115
|
+
export declare function beginPastRead(repo: string, env?: NodeJS.ProcessEnv): PastRead | null;
|
|
116
|
+
/**
|
|
117
|
+
* Each finding as a standing learning: the team's in `.trail/learnings/`,
|
|
118
|
+
* the person's own in ~/.trail. The body says where it came from.
|
|
119
|
+
*/
|
|
120
|
+
export declare function saveFindings(repo: string, findings: Finding[], author?: string, date?: string): Note[];
|
|
121
|
+
/** Wait for the read, save what it found, and remember the repo was read. */
|
|
122
|
+
export declare function finishPastRead(repo: string, read: PastRead): Promise<{
|
|
123
|
+
result: FindResult;
|
|
124
|
+
saved: Note[];
|
|
125
|
+
}>;
|
|
126
|
+
export {};
|
|
127
|
+
//# sourceMappingURL=cold-start.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cold-start.d.ts","sourceRoot":"","sources":["../../src/notes/cold-start.ts"],"names":[],"mappings":"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"}
|