@ssheleg/agent-sync 1.10.0 → 1.10.1

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/CHANGELOG.md CHANGED
@@ -1,3 +1,32 @@
1
+ ## v1.10.1
2
+
3
+ The claim tag could not be placed on nearly half a real board, and the lease was granted
4
+ anyway.
5
+
6
+ ### Fixed
7
+
8
+ - **A row that CITES an id no longer defeats that id's claim.** `claimTags` in `cell` mode
9
+ selected every row *containing* the id, so an ordinary board sentence — "closed by
10
+ B-12", "blocked until T-1 ships" — made the id ambiguous and the tag was refused.
11
+ Cross-referencing is what boards do: measured on `sshlg-skills`' own board on
12
+ 2026-08-14, **14 of 41 rows cited others, leaving 19 ids that could never be tagged**.
13
+
14
+ The refusal itself was correct — guessing which row carries a claim is how a claim lands
15
+ on somebody else's work. What was wrong is that `acquire` still returned `won`: the
16
+ lease was granted while the registry silently carried no claim, which is precisely the
17
+ state a claim exists to make visible.
18
+
19
+ A markdown board declares which row is which in its **first cell**. `acquire` now
20
+ narrows to the row whose id cell equals the key, and refuses only when no row's id cell
21
+ matches. Tried *after* the existing marker narrowing, so `release` still trusts the
22
+ marker it actually wrote rather than re-deriving the row.
23
+
24
+ Covered by `check_claim_lands_on_the_row_whose_id_cell_matches()`, which builds a two-row
25
+ board where the second row cites the first, and asserts the tag lands on exactly one row
26
+ and that it is the right one — then that release still restores the file byte for byte.
27
+ Watched failing before the fix: *"acquire wrote no claim — a row citing T-1 defeated the
28
+ selector, and the lease was granted with the registry unmarked"*.
29
+
1
30
  ## v1.10.0
2
31
 
3
32
  Following `task-pipeline` v1.53.0, which renamed the artifact root's default from
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ssheleg/agent-sync",
3
- "version": "1.10.0",
3
+ "version": "1.10.1",
4
4
  "description": "Let concurrent coding agents share one project without colliding — leases with TTL, race-free id reservation, a run journal and a generated board, over a pluggable knowledge cloud.",
5
5
  "bin": {
6
6
  "agent-sync": "bin/agent-sync.js"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agent-sync",
3
3
  "displayName": "Agent Sync",
4
- "version": "1.10.0",
4
+ "version": "1.10.1",
5
5
  "description": "Coordination layer for multi-agent repositories — leases with TTL, race-free ID reservation, a run journal, a cross-repo signal feed and a generated board, over a pluggable knowledge cloud.",
6
6
  "author": {
7
7
  "name": "ssheleg",
@@ -4,7 +4,7 @@ description: "Use when several coding agents work one repository at the same tim
4
4
  compatibility: "Requires the task-pipeline skill for its stages (npx sshlg-skills install). Needs python3 3.9+ (stdlib only, HTTP included - nothing to pip install) and bash for the hooks. The knowledge backend is configured per project; with none configured it degrades to git-file leases. Enforcement hooks are Claude Code only - on other agents the same checks run as a self-check."
5
5
  license: MIT
6
6
  metadata:
7
- version: "1.10.0"
7
+ version: "1.10.1"
8
8
  author: ssheleg
9
9
  ---
10
10
 
@@ -33,7 +33,7 @@ from datetime import datetime, timezone
33
33
  from pathlib import Path
34
34
  from typing import Any
35
35
 
36
- VERSION = "1.10.0"
36
+ VERSION = "1.10.1"
37
37
 
38
38
  CONFIG_PATH = Path(".claude/agent-sync.json")
39
39
  ENV_FILE = Path(".env.agent-sync")
@@ -1668,6 +1668,22 @@ class Sync:
1668
1668
  if len(narrowed) == 1:
1669
1669
  hits = narrowed
1670
1670
 
1671
+ # A board says which row is which in its FIRST cell. Every other match is a
1672
+ # row CITING this id — "closed by B-12", "blocked until T-1 ships" — and boards
1673
+ # cross-reference constantly: on the family's own board 14 rows cited others, so
1674
+ # 19 of 41 ids had two candidate rows and their claim was refused. The refusal
1675
+ # was right; granting the lease anyway was not, because the registry then carries
1676
+ # no claim while `acquire` reports `won`. Tried after the marker so a release
1677
+ # still trusts what it actually wrote.
1678
+ if len(hits) > 1:
1679
+ own = []
1680
+ for i in hits:
1681
+ cells = self._row_cells(lines[i])
1682
+ if cells and cells[0].strip() == key:
1683
+ own.append(i)
1684
+ if len(own) == 1:
1685
+ hits = own
1686
+
1671
1687
  if len(hits) > 1:
1672
1688
  notes.append(f"{rel}: `{key}` appears in {len(hits)} table rows — refusing "
1673
1689
  "to guess which one is the claim. Narrow the pattern or edit by hand")