tryharness 0.7.16 → 0.7.22

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/lib/worktrees.mjs CHANGED
@@ -24,6 +24,21 @@ export function repositoryOf(folder) {
24
24
  return { root: fs.realpathSync(top.out), inside: path.relative(fs.realpathSync(top.out), fs.realpathSync(folder)) };
25
25
  }
26
26
 
27
+ /**
28
+ * The folder a linked git worktree stands for: the same place in its repository's main checkout. A thread's copy here,
29
+ * T3 Code's and the person's own are all worktrees of the checkout the person works in (T3 counts their history as
30
+ * that checkout's too). Any other folder is itself.
31
+ */
32
+ export function mainCheckout(folder) {
33
+ if (!folder || !fs.existsSync(folder)) return folder;
34
+ const found = git(folder, ["rev-parse", "--path-format=absolute", "--show-toplevel", "--git-common-dir"]);
35
+ const [top, common] = found.ok ? found.out.split("\n") : [];
36
+ if (!top || !common || path.basename(common) !== ".git") return folder;
37
+ const main = path.dirname(common);
38
+ if (!fs.existsSync(main) || fs.realpathSync(main) === fs.realpathSync(top)) return folder;
39
+ return path.join(main, path.relative(fs.realpathSync(top), fs.realpathSync(folder)));
40
+ }
41
+
27
42
  const slug = (text) => String(text).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 32) || "thread";
28
43
 
29
44
  export function createWorktrees({ store, root }) {
@@ -127,17 +142,34 @@ export function createWorktrees({ store, root }) {
127
142
  return { ok: true };
128
143
  };
129
144
 
145
+ /**
146
+ * The thread's folder changed: its copy of the old repository goes when nothing in it is the person's yet, and the
147
+ * next turn makes whatever the new folder needs. Changes not yet merged or discarded keep it where it is.
148
+ */
149
+ const moved = (threadId) => {
150
+ const tree = get(threadId);
151
+ if (tree?.state === "open" && fs.existsSync(tree.path)) {
152
+ if (stat(tree.path, `${tree.base}..HEAD`).length) return { ok: false, error: `this thread changed files on ${tree.branch}; merge or discard them first` };
153
+ retire(tree);
154
+ git(tree.repo, ["branch", "-D", tree.branch]);
155
+ }
156
+ if (tree) save(threadId, null);
157
+ return { ok: true };
158
+ };
159
+
130
160
  /** A thread that carries on a session from a terminal works where that session did: agents find sessions by folder. */
131
161
  const inPlace = (threadId) => save(threadId, { state: "in_place" });
132
162
 
133
163
  /**
134
164
  * Where T3 Code runs a thread's agents (t3.mjs runInT3): the checkout T3 made for the thread's first agent, shared by
135
- * the rest as its own worktree is; before that, a new one on its own branch from what the person has checked out (as
165
+ * the rest as its own worktree is, or the thread's own copy when it worked here before; a task's room that works in
166
+ * place, T3's project checkout itself; else a new one on its own branch from what the person has checked out (as
136
167
  * folderFor's), or T3's project folder when the thread's folder is in no repository.
137
168
  */
138
169
  const t3Workspace = (thread) => {
139
170
  const current = get(thread.id);
140
- if (current?.state === "t3" && current.path) return { type: "existing_worktree", worktreePath: current.path, ...(current.branch ? { branch: current.branch } : {}) };
171
+ if (current?.state === "in_place" || current?.inPlace) return { type: "root" };
172
+ if ((current?.state === "t3" || current?.state === "open") && current.path) return { type: "existing_worktree", worktreePath: current.path, ...(current.branch ? { branch: current.branch } : {}) };
141
173
  const repo = repositoryOf(thread.goal.workspace);
142
174
  if (!repo) return { type: "root" };
143
175
  const branch = git(repo.root, ["rev-parse", "--abbrev-ref", "HEAD"]).out;
@@ -147,8 +179,8 @@ export function createWorktrees({ store, root }) {
147
179
  /** The thread works in T3 Code from now on; `where` and `branch` once T3 has made its checkout. */
148
180
  const inT3 = (threadId, where = null, branch = null) => {
149
181
  const current = get(threadId);
150
- if (current?.state !== "t3" || (where && where !== current.path)) save(threadId, { state: "t3", path: where ?? current?.path ?? null, branch: branch ?? current?.branch ?? null });
182
+ if (current?.state !== "t3" || (where && where !== current.path)) save(threadId, { ...current, ...(current?.state === "in_place" ? { inPlace: true } : {}), state: "t3", path: where ?? current?.path ?? null, branch: branch ?? current?.branch ?? null });
151
183
  };
152
184
 
153
- return { folderFor, commitTurn, diff, summary, merge, discard, inPlace, t3Workspace, inT3, get };
185
+ return { folderFor, commitTurn, diff, summary, merge, discard, moved, inPlace, t3Workspace, inT3, get };
154
186
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tryharness",
3
- "version": "0.7.16",
3
+ "version": "0.7.22",
4
4
  "description": "Harness Relay: the daemon that turns the agents on this machine into your personal swarm. Memory, history, and work handed between any of them.",
5
5
  "bin": {
6
6
  "tryharness": "cli.mjs"
@@ -39,8 +39,8 @@
39
39
  "ws": "^8.18.3"
40
40
  },
41
41
  "optionalDependencies": {
42
- "tryharness-desktop-darwin-arm64": "0.7.16",
43
- "tryharness-desktop-darwin-x64": "0.7.16",
42
+ "tryharness-desktop-darwin-arm64": "0.7.22",
43
+ "tryharness-desktop-darwin-x64": "0.7.22",
44
44
  "tryharness-desktop-linux-x64": "0.7.4",
45
45
  "tryharness-desktop-win32-x64": "0.7.4"
46
46
  }