@webappwiz/arbor 0.0.2 → 0.0.3

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 CHANGED
@@ -216,7 +216,7 @@ The agent's control flow runs on these.
216
216
  | 6 | `lease_held` | Another agent is driving this tree. |
217
217
  | 7 | `dirty` | Uncommitted changes. Commit before merging. |
218
218
  | 8 | `not_found` | No such task, or not run from a task worktree. |
219
- | 9 | `hook_failed` | `postCheckout` failed. The worktree still exists; fix and re-run the hook. |
219
+ | 9 | `hook_failed` | `postCheckout` failed (worktree still exists; fix and re-run the hook), or `postMerge` failed (the branch already landed; nothing rolled back). |
220
220
  | 10 | `exists` | Task already exists. `arbor claim` it, or `arbor rm` first. |
221
221
  | 11 | `orphaned` | Record with no worktree. `arbor rm` it. |
222
222
  | 12 | `merge_failed` | Trunk could not be fast-forwarded (usually a dirty main worktree). |
@@ -239,6 +239,7 @@ export default defineConfig({
239
239
  postCheckout: "bun install && cp ../../myrepo/.env .env",
240
240
  postRewrite: "bun install", // after each rebase, before preMerge
241
241
  preMerge: "bun test", // the last gate before the branch lands
242
+ postMerge: "bun install", // in the main tree, after the branch lands
242
243
  leaseStalenessMs: 90_000,
243
244
  mergeRetryCount: 2,
244
245
  removedCapacity: 50, // removed names kept, so rm can say "already removed"
@@ -254,7 +255,11 @@ The hooks are named for the git events they sit around: `postCheckout` runs
254
255
  once, when `add` checks the worktree out; `postRewrite` runs after every rebase
255
256
  `merge` does; `preMerge` runs after that, and is the last thing between the
256
257
  branch and the base. They all run through `sh -c` in the worktree with
257
- `ARBOR_TASK` and `ARBOR_WORKTREE` in the environment.
258
+ `ARBOR_TASK` and `ARBOR_WORKTREE` in the environment. `postMerge` is the
259
+ exception: it runs in the main tree after the branch lands and the worktree is
260
+ gone (so only `ARBOR_TASK` is set), for keeping the main tree current the way
261
+ `postRewrite` keeps the worktree current. It reports failure but rolls nothing
262
+ back; the landing already happened.
258
263
 
259
264
  Every hook is unset by default: arbor has no opinion about what a repo runs, or
260
265
  whether it has tests at all. Configure `preMerge` and a nonzero exit rolls the
package/config.d.ts CHANGED
@@ -22,6 +22,12 @@ export interface Config {
22
22
  * rebase alone.
23
23
  */
24
24
  preMerge: string | null;
25
+ /**
26
+ * Command run by `merge` in the main tree after the base fast-forwards, via
27
+ * `sh -c`. The branch has already landed and the worktree is gone: a nonzero
28
+ * exit reports the failure but rolls nothing back.
29
+ */
30
+ postMerge: string | null;
25
31
  /** How long since its last heartbeat before a task's lease is up for grabs. */
26
32
  leaseStalenessMs: number;
27
33
  /** Failed `merge` attempts a task gets before it must escalate or be removed. */
package/index.js CHANGED
@@ -627,6 +627,21 @@ ${gated.stderr}`)
627
627
  fail("usage", `landed '${task}' on ${base} (${head}) but could not discard its worktree: ${discarded.stderr || discarded.stdout}
628
628
  Run \`arbor rm ${task}\` to clean up.`, { task });
629
629
  }
630
+ if (config.postMerge) {
631
+ const ran = await shell.run(config.postMerge, {
632
+ cwd: git.root,
633
+ env: { ARBOR_TASK: task }
634
+ });
635
+ if (ran.exitCode !== 0) {
636
+ fail("hook_failed", [
637
+ `landed '${task}' on ${base} (${head}) but the postMerge hook failed (exit ${ran.exitCode}).`,
638
+ "",
639
+ tail(`${ran.stdout}
640
+ ${ran.stderr}`)
641
+ ].join(`
642
+ `), { task, exitCode: ran.exitCode });
643
+ }
644
+ }
630
645
  log2.info(`${color8.green("merged")} ${task} onto ${base} (${head})
631
646
  worktree removed, cd ${git.root}`);
632
647
  }
@@ -846,6 +861,7 @@ function defaults(root, trunk) {
846
861
  postCheckout: null,
847
862
  postRewrite: null,
848
863
  preMerge: null,
864
+ postMerge: null,
849
865
  leaseStalenessMs: 90000,
850
866
  mergeRetryCount: 2,
851
867
  removedCapacity: 50,
@@ -19033,14 +19049,21 @@ function App() {
19033
19049
  }, [feed]);
19034
19050
  const { snapshot, offline } = useReactive(feed, (feed2) => ({ snapshot: feed2.snapshot, offline: feed2.offline }), ["changed"]);
19035
19051
  const [tab, setTab] = import_react6.useState("tasks");
19052
+ const emoji = offline ? "⚠️" : "\\uD83C\\uDF32";
19053
+ import_react6.useEffect(() => {
19054
+ document.querySelector("link[rel=icon]")?.setAttribute("href", \`data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><text y='26' font-size='28'>\${emoji}</text></svg>\`);
19055
+ }, [emoji]);
19036
19056
  return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV("div", {
19037
19057
  className: "mx-auto max-w-6xl px-4 py-8 font-mono text-[13px]",
19038
19058
  children: [
19039
19059
  /* @__PURE__ */ jsx_dev_runtime2.jsxDEV("h1", {
19040
19060
  className: "mb-4 text-base",
19041
19061
  children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV("b", {
19042
- children: "\\uD83C\\uDF32 arbor"
19043
- }, undefined, false, undefined, this)
19062
+ children: [
19063
+ emoji,
19064
+ " arbor"
19065
+ ]
19066
+ }, undefined, true, undefined, this)
19044
19067
  }, undefined, false, undefined, this),
19045
19068
  /* @__PURE__ */ jsx_dev_runtime2.jsxDEV("nav", {
19046
19069
  className: "mb-4 flex gap-6 text-xs uppercase tracking-widest",
@@ -19369,7 +19392,7 @@ var shell_default = `<!doctype html>
19369
19392
  <meta name="viewport" content="width=device-width, initial-scale=1" />
19370
19393
  <title>arbor</title>
19371
19394
  <!-- The emoji drawn as SVG inline, so there is no file for the server to
19372
- serve and nothing to keep in step with the heading on the page. -->
19395
+ serve. The page rewrites it to a warning when the server goes away. -->
19373
19396
  <link
19374
19397
  rel="icon"
19375
19398
  href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><text y='26' font-size='28'>🌲</text></svg>"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webappwiz/arbor",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Runs several AI coding agents on one repository at once, each in its own git worktree",
5
5
  "license": "MIT",
6
6
  "author": "Jared Johnson",
@@ -17,7 +17,7 @@
17
17
  "access": "public"
18
18
  },
19
19
  "dependencies": {
20
- "webappwiz": "^0.0.2"
20
+ "webappwiz": "^0.0.3"
21
21
  },
22
22
  "main": "./index.js",
23
23
  "types": "./index.d.ts",