pi-straw-boss 0.34.0 → 0.34.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/stash.ts +7 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-straw-boss",
3
- "version": "0.34.0",
3
+ "version": "0.34.1",
4
4
  "description": "Straw Boss coordination for pi in Herdr: sessions join a tab's net by choice, the first joiner is its main agent, a workspace tower opens on demand with a live monitoring dashboard, and boss_broadcast reaches the rest",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/stash.ts CHANGED
@@ -38,8 +38,9 @@ export function listStashes(stateDir: string): string[] {
38
38
  const str = (v: unknown): v is string => typeof v === "string" && v.length > 0;
39
39
  function paneOk(p: unknown): p is StashPane {
40
40
  const x = p as Partial<StashPane> | null;
41
- return x !== null && typeof x === "object" && (x.kind === "shell" || ROLES.has(x.kind as string)) && str(x.cwd) && (x.kind === "shell" || str(x.session)) && (x.name === undefined || typeof x.name === "string");
41
+ return x !== null && typeof x === "object" && (x.kind === "shell" || ROLES.has(x.kind as string)) && str(x.cwd) && (x.session === undefined || str(x.session)) && (x.name === undefined || typeof x.name === "string");
42
42
  }
43
+ /** `session` is absent for a pi that never wrote its file (pi writes it at the first reply): it has no conversation to lose, so a pop starts it fresh in its role. */
43
44
  /** What a pop can open: the stash checks it before it closes anything, the pop before it opens anything. */
44
45
  const stashOk = (st: Stash | null) => st?.version === 1 && str(st.label) && str(st.cwd) && Array.isArray(st.tabs) && st.tabs.length > 0 && st.tabs.every((t) => Array.isArray(t?.panes) && t.panes.length > 0 && t.panes.every(paneOk) && (t.label === undefined || typeof t.label === "string"));
45
46
  export function readStash(stateDir: string, name: string, file = stashFile(stateDir, name)): Stash {
@@ -95,8 +96,9 @@ export async function survey(run: HerdrRun, workspaceId: string, live: Session[]
95
96
  else if (!ROLES.has(role)) reasons.push(`${who} is a subagent or outside the net`);
96
97
  if (p.agent !== "pi" || !ROLES.has(role)) continue;
97
98
  if (!SETTLED.has(p.agent_status ?? "")) reasons.push(`${who} is ${p.agent_status ?? "in an unknown state"}`);
98
- const file = p.agent_session?.value;
99
- if (!file || !existsSync(file)) reasons.push(`${who} has no session file Herdr knows of`);
99
+ // A path Herdr names whose file does not exist yet is a session that never replied: nothing to resume, it starts fresh at pop.
100
+ const named = p.agent_session?.value, file = named && existsSync(named) ? named : undefined;
101
+ if (!named) reasons.push(`${who} has no session file Herdr knows of`);
100
102
  if (!cwd) reasons.push(`${who} has no folder Herdr knows of`);
101
103
  if (session) agents.push(session);
102
104
  else reasons.push(`${who} is not on the intercom net`);
@@ -159,11 +161,11 @@ async function resume({ run, sleep, live }: PopDeps, ws: string, paneId: string,
159
161
  if (p.kind === "main") await report(run, "pane", paneId, { sb_open_main: "1" }); // authorises exactly this pi to promote itself (session.ts)
160
162
  // Herdr agent names are unique across workspaces and lowercase only.
161
163
  const agent = p.kind === "tower" ? `tower-${ws.toLowerCase()}` : `${p.kind}-${randomUUID().slice(0, 8)}`;
162
- await startPi(run, sleep, agent, paneId, ["--session", p.session!, ...(p.name ? ["--name", p.name] : [])]);
164
+ await startPi(run, sleep, agent, paneId, [...(p.session ? ["--session", p.session] : []), ...(p.name ? ["--name", p.name] : [])]);
163
165
  const back = p.kind === "tower"
164
166
  ? await waitFor(sleep, async () => ((id) => id && live(id))((await workspaces(run)).find((w) => w.workspace_id === ws)?.tokens?.tower), JOIN_MS, 1000)
165
167
  : await waitFor(sleep, async () => ((r) => (p.kind === "main" ? r === "main" : r === "member" || r === "main"))((await panes(run, ws)).find((x) => x.pane_id === paneId)?.tokens?.sb_role), JOIN_MS, 500);
166
- if (!back) throw new Error(`${p.name ?? p.session} did not come back as the ${p.kind} within ${JOIN_MS / 1000} s (pane ${paneId})`);
168
+ if (!back) throw new Error(`${p.name ?? p.session ?? p.kind} did not come back as the ${p.kind} within ${JOIN_MS / 1000} s (pane ${paneId})`);
167
169
  }
168
170
 
169
171
  /**