agents-city 0.5.8 → 0.5.9

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.
@@ -9,7 +9,7 @@
9
9
  {
10
10
  "name": "city",
11
11
  "source": "./plugin",
12
- "version": "0.5.8",
12
+ "version": "0.5.9",
13
13
  "description": "Operate one autonomous city seat, its domain, role, repo support agents, goal, recognised skills and explicit roads to other cities."
14
14
  }
15
15
  ]
package/bin/test-seat.py CHANGED
@@ -1635,6 +1635,75 @@ def arranque_escalonado():
1635
1635
  str(lineas)[:400],
1636
1636
  )
1637
1637
 
1638
+ # A card that moved on under a window that is already open. This is the trap
1639
+ # the reconcile created: `ui.api: tui` on a running city applies to nothing,
1640
+ # and if nothing says so the owner sets it, reopens, sees the same gateway
1641
+ # and concludes the feature does not work.
1642
+ card.pon_campo(ficha, "ui.api", "tui")
1643
+ # The gateway's own pid marker: the only positive proof of what an already
1644
+ # open window is running.
1645
+ marcas = subprocess.run(
1646
+ [sys.executable, "-c",
1647
+ "import sys; sys.path.insert(0, sys.argv[1]); import runtime_processes as r;"
1648
+ " print(r.ruta(sys.argv[2]))",
1649
+ os.path.join(RAIZ, "plugin", "scripts"), datos],
1650
+ capture_output=True, text=True,
1651
+ # The launcher's own environment, or this resolves a different marker
1652
+ # directory from the one the launcher will look in.
1653
+ env={k: v for k, v in dict(os.environ, HOME=casa).items()
1654
+ if k != "AGENTS_CITY_HOME"},
1655
+ ).stdout.strip()
1656
+ os.makedirs(os.path.join(marcas, "gateways"), exist_ok=True)
1657
+ open(os.path.join(marcas, "gateways", "api.pid"), "w").write("4242\n")
1658
+ desfase = subprocess.run(
1659
+ ["bash", guion, "ana", "--claude", "--no-sync"],
1660
+ capture_output=True, text=True, cwd=casa,
1661
+ env=dict(os.environ, HOME=casa, AGENTS_CITY_DATA=datos, CITY_CODE_DIR=codigo,
1662
+ PATH=fbin + os.pathsep + os.environ["PATH"],
1663
+ CITY_SETTLE="0", CITY_STAGGER="0",
1664
+ FAKE_SESSION="1", FAKE_WINDOWS="seat api docs"),
1665
+ ).stderr
1666
+ afirma(
1667
+ "· happy: a card that moved on under an open window is reported, with what to run",
1668
+ "the card says tui" in desfase and "kill-window" in desfase and "api" in desfase,
1669
+ desfase[-500:],
1670
+ )
1671
+ afirma(
1672
+ "· non-happy: and nothing is closed on the owner's behalf",
1673
+ "kill-window" not in open(registro).read(),
1674
+ open(registro).read()[-300:],
1675
+ )
1676
+ card.pon_campo(ficha, "ui.api", "")
1677
+ sin_desfase = subprocess.run(
1678
+ ["bash", guion, "ana", "--claude", "--no-sync"],
1679
+ capture_output=True, text=True, cwd=casa,
1680
+ env=dict(os.environ, HOME=casa, AGENTS_CITY_DATA=datos, CITY_CODE_DIR=codigo,
1681
+ PATH=fbin + os.pathsep + os.environ["PATH"],
1682
+ CITY_SETTLE="0", CITY_STAGGER="0",
1683
+ FAKE_SESSION="1", FAKE_WINDOWS="seat api docs"),
1684
+ ).stderr
1685
+ afirma(
1686
+ "· non-happy: and a city whose windows agree with its card says nothing about them",
1687
+ "the card says" not in sin_desfase, sin_desfase[-300:],
1688
+ )
1689
+ # The absence of a marker is not proof of anything, and used to be read as
1690
+ # proof of a TUI.
1691
+ card.pon_campo(ficha, "ui.api", "tui")
1692
+ os.remove(os.path.join(marcas, "gateways", "api.pid"))
1693
+ sin_marca = subprocess.run(
1694
+ ["bash", guion, "ana", "--claude", "--no-sync"],
1695
+ capture_output=True, text=True, cwd=casa,
1696
+ env=dict(os.environ, HOME=casa, AGENTS_CITY_DATA=datos, CITY_CODE_DIR=codigo,
1697
+ PATH=fbin + os.pathsep + os.environ["PATH"],
1698
+ CITY_SETTLE="0", CITY_STAGGER="0",
1699
+ FAKE_SESSION="1", FAKE_WINDOWS="seat api docs"),
1700
+ ).stderr
1701
+ afirma(
1702
+ "· non-happy: with no marker it says nothing, rather than guessing what is running",
1703
+ "the card says" not in sin_marca, sin_marca[-300:],
1704
+ )
1705
+ card.pon_campo(ficha, "ui.api", "")
1706
+
1638
1707
  # A window whose agent left the card may be mid-task. Say so; do not close
1639
1708
  # it. The owner decides what to do with somebody's unfinished work.
1640
1709
  sobra = subprocess.run(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agents-city",
3
- "version": "0.5.8",
3
+ "version": "0.5.9",
4
4
  "description": "Run autonomous agent cities: one chair seat, role-aware repo agents, repo-owned skills, and explicit roads.",
5
5
  "bin": {
6
6
  "agents-city": "bin/agents-city.js"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "city",
3
3
  "displayName": "Agents City",
4
- "version": "0.5.8",
4
+ "version": "0.5.9",
5
5
  "description": "One autonomous city seat with a work domain, role, goal, repo support agents, recognised skills and explicit roads to other cities.",
6
6
  "author": {
7
7
  "name": "jlcases",
@@ -757,6 +757,36 @@ if [ "$SESION_YA" -eq 1 ]; then
757
757
  else
758
758
  echo "Session '$SESSION' is already up, with every agent on the card — attaching." >&2
759
759
  fi
760
+ # A window that is already open is left alone — there may be work in it — and
761
+ # that is exactly why a card change to one of them has to be said out loud.
762
+ # `ui.dev: tui` on a running city applies to nothing and reports nothing, so
763
+ # the owner sets it, reopens, sees the same gateway and concludes the feature
764
+ # does not work. The gateway leaves a pid marker, so drift here is a fact and
765
+ # not a guess.
766
+ # Only where there is positive evidence. A gateway leaves a pid marker, so its
767
+ # presence proves what that window is running; its ABSENCE proves nothing —
768
+ # a session opened without --claude has no markers at all, and inferring "then
769
+ # it must be a TUI" reported drift on a city where nothing had drifted. So
770
+ # this speaks in one direction, and says nothing rather than something it
771
+ # cannot know.
772
+ desfasadas=()
773
+ MARCAS="$(python3 -c 'import sys; sys.path.insert(0, sys.argv[1]); import runtime_processes as r; print(r.ruta(sys.argv[2]))' "$(dirname "$0")" "$EQUIPO" 2>/dev/null || true)"
774
+ for w in $VENTANAS_YA; do
775
+ [ "$w" = seat ] && continue
776
+ [ "$(ui_de "$w" gateway)" = tui ] || continue
777
+ [ -n "$MARCAS" ] && [ -f "$MARCAS/gateways/$w.pid" ] \
778
+ && desfasadas+=("$w: the card says tui, and the open window is the city's gateway")
779
+ done
780
+ if [ ${#desfasadas[@]} -gt 0 ]; then
781
+ echo >&2
782
+ echo "These windows were left as they are, and their card has moved on:" >&2
783
+ printf ' %s\n' "${desfasadas[@]}" >&2
784
+ echo "Nothing was closed — there may be work in them. To apply:" >&2
785
+ for d in ${desfasadas[@]+"${desfasadas[@]}"}; do
786
+ echo " tmux kill-window -t $SESSION:${d%%:*} (then open the city again)" >&2
787
+ done
788
+ fi
789
+
760
790
  sobran=()
761
791
  for w in $VENTANAS_YA; do
762
792
  [ "$w" = seat ] && continue