heyquilt 0.3.138 → 0.3.141

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.
Files changed (53) hide show
  1. package/RELEASES.md +10 -0
  2. package/bin/quilt.js +7 -143
  3. package/package.json +1 -1
  4. package/src/account.js +0 -29
  5. package/src/api/memory-store.js +0 -29
  6. package/src/api/routes/teams.js +0 -23
  7. package/src/api/server.js +5 -19
  8. package/src/api/supabase-store.js +0 -52
  9. package/src/branch-view.js +6 -131
  10. package/src/control.js +2 -33
  11. package/src/duties.js +1 -1
  12. package/src/github-commit.js +3 -315
  13. package/src/mcp.js +8 -157
  14. package/src/relay-ask.js +3 -66
  15. package/src/relay-cluster.js +3 -5
  16. package/src/relay-mcp.js +6 -418
  17. package/src/relay-prune.js +6 -145
  18. package/src/relay-turn-sync.js +1 -1
  19. package/src/server.js +33 -1331
  20. package/src/session-follow.js +18 -5
  21. package/src/session.js +58 -3526
  22. package/src/status.js +2 -58
  23. package/src/turn-sync.js +15 -2
  24. package/src/ui/changes.js +5 -14
  25. package/src/ui/chat.js +0 -1
  26. package/src/ui/common.js +0 -2
  27. package/src/ui/git-rule.js +2 -30
  28. package/src/ui/home.js +3 -76
  29. package/src/ui/session.js +34 -528
  30. package/src/ui/tree.js +2 -8
  31. package/src/ui/workspaces.js +2 -122
  32. package/src/ui-server.js +1 -38
  33. package/src/api/routes/github.js +0 -380
  34. package/src/branches.js +0 -194
  35. package/src/clash.js +0 -128
  36. package/src/commit-request.js +0 -59
  37. package/src/commit.js +0 -213
  38. package/src/git-hook.js +0 -48
  39. package/src/gitignore.js +0 -49
  40. package/src/gitstate.js +0 -1069
  41. package/src/relay-ci.js +0 -111
  42. package/src/relay-clash.js +0 -214
  43. package/src/relay-commit.js +0 -923
  44. package/src/relay-filekey.js +0 -46
  45. package/src/relay-git.js +0 -274
  46. package/src/relay-githttp.js +0 -166
  47. package/src/relay-github.js +0 -109
  48. package/src/relay-outbound.js +0 -1295
  49. package/src/relay-repo-moves.js +0 -43
  50. package/src/relay-sync.js +0 -795
  51. package/src/relay-upstream.js +0 -889
  52. package/src/sync-words.js +0 -42
  53. package/src/upstream.js +0 -192
@@ -307,8 +307,9 @@ export class SquareFollower {
307
307
  const s = this.session
308
308
  // Held before the first await: nothing of the folder reaches the read-only branch document while the block opens.
309
309
  const at = this.inPlaceOn() ? squareFor(quilt, s.squareBranchKey ? s.squareBranchKey() : s.branchKey()) : null
310
- if (at && s.enterSquare && !(this.here && this.here.square === at.square)) s.enterSquare(at, quilt)
311
- const next = this.turn.then(() => this.settle(quilt)).catch((err) => { if (s.log) s.log(`🧵 ${err.message}`) })
310
+ const entered = at && s.enterSquare && !(this.here && this.here.square === at.square) ? at.square : null
311
+ if (entered) s.enterSquare(at, quilt)
312
+ const next = this.turn.then(() => this.settle(quilt, entered)).catch((err) => { if (s.log) s.log(`🧵 ${err.message}`) })
312
313
  this.turn = next
313
314
  // A merge onto main moves a branch on (quiltNext), and the relay says so: the other squares may be behind now.
314
315
  next.then(() => this.catchUpSoon())
@@ -318,7 +319,8 @@ export class SquareFollower {
318
319
  /** Seam on for the app, a folder of the session's own, and a session that can hold its sync (a Session). */
319
320
  inPlaceOn () { return !!(appSeamUrl() && this.session.root && this.session.enterSquare) }
320
321
 
321
- async settle (quilt) {
322
+ /** `entered`: the square onQuilt already held the session's sync for. */
323
+ async settle (quilt, entered = null) {
322
324
  const s = this.session
323
325
  const at = this.inPlaceOn() ? squareFor(quilt, s.squareBranchKey ? s.squareBranchKey() : s.branchKey()) : null
324
326
  // The separate folder lets go of a square the branch no longer has (switched back, moved).
@@ -340,6 +342,11 @@ export class SquareFollower {
340
342
  } else if (s.log) s.log(`🧵 this folder left square ${squareShort(was)}: its branch is on ${squareShort(at.square)} now.`)
341
343
  }
342
344
  if (!at || (this.here && this.here.square === at.square)) return
345
+ // The branch may only be known now (a folder without git learns the room's default branch after
346
+ // the relay's quilt message): the session's own sync holds before the block opens, every time, or
347
+ // it writes the read-only branch document's older copy over the square's files and the block takes
348
+ // that for this member's edits (2026-11-01: an agent's new folder put 166 stale files into main's square).
349
+ if (s.enterSquare && entered !== at.square) s.enterSquare(at, quilt)
343
350
  await this.openHere(at, quilt)
344
351
  }
345
352
 
@@ -349,13 +356,18 @@ export class SquareFollower {
349
356
  const here = { square: at.square, quilt, block: null, problem: '', opening: true }
350
357
  this.here = here
351
358
  if (s.scheduleStatusWrite) s.scheduleStatusWrite()
359
+ // A folder that joined the quilt empty (Session.joinedEmpty): what it has is the session's sync from
360
+ // the read-only branch document, an older copy of the square's files. Its first look takes nothing
361
+ // of that for its edits (no refused writes, boxes or branch work of its own); only a file changed
362
+ // on disk since the session wrote it is the member's.
363
+ const empty = !fresh && !!s.joinedEmpty
352
364
  try {
353
365
  // Edits the read-only branch document refused (they reached it after the switch) are the folder's too.
354
- const unsent = !fresh && s.unsentPaths ? await s.unsentPaths().catch(() => null) : null
366
+ const unsent = !fresh && !empty && s.unsentPaths ? await s.unsentPaths().catch(() => null) : null
355
367
  const block = await this.open({
356
368
  dir: s.root,
357
369
  // A square opened for this folder's branch (Session.openSquareHere: the branch had none) takes the folder as it is: its files are the work.
358
- inPlace: fresh ? { edited: () => false, fresh: true } : s.folderWins === at.square ? { edited: () => true } : { edited: (p) => s.editedSinceSync(p) || !!(unsent && unsent.has(p)) || !!(s.boxedHere && s.boxedHere(p)), boxed: (p) => !!(s.boxedHere && s.boxedHere(p)), heldBack: (p) => !!(s.heldBackHere && s.heldBackHere(p)), synced: (p) => !!(s.syncedHere && s.syncedHere(p)), base: s.syncedText ? (p) => s.syncedText(p) : null, own: () => (s.branchOwnPaths ? s.branchOwnPaths() : null), atTip: ((quilt && quilt.atTip) || []).includes(s.squareBranchKey ? s.squareBranchKey() : s.branchKey()) },
370
+ inPlace: fresh ? { edited: () => false, fresh: true } : empty ? { edited: (p) => !!(s.editedSinceSync && s.editedSinceSync(p)), fresh: true } : s.folderWins === at.square ? { edited: () => true } : { edited: (p) => s.editedSinceSync(p) || !!(unsent && unsent.has(p)) || !!(s.boxedHere && s.boxedHere(p)), boxed: (p) => !!(s.boxedHere && s.boxedHere(p)), heldBack: (p) => !!(s.heldBackHere && s.heldBackHere(p)), synced: (p) => !!(s.syncedHere && s.syncedHere(p)), base: s.syncedText ? (p) => s.syncedText(p) : null, own: () => (s.branchOwnPaths ? s.branchOwnPaths() : null), atTip: ((quilt && quilt.atTip) || []).includes(s.squareBranchKey ? s.squareBranchKey() : s.branchKey()) },
359
371
  skip: (p) => !s.syncable(p),
360
372
  skipDir: s.ignoredDir ? (p) => s.ignoredDir(p) : null,
361
373
  record: path.join(s.stateDir || path.join(s.root, '.quilt'), 'block.json'),
@@ -371,6 +383,7 @@ export class SquareFollower {
371
383
  onEdits: s.squareEdits ? (list, doc, held) => { if (this.here === here) s.squareEdits(list, doc, held) } : null
372
384
  })
373
385
  if (this.here !== here) { await block.close().catch(() => {}); return }
386
+ if (empty) s.joinedEmpty = false
374
387
  here.block = block
375
388
  here.opening = false
376
389
  if (s.followSquareDoc) s.followSquareDoc(block.doc)