@afokapu/atdd-flow 0.2.1 → 0.2.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@afokapu/atdd-flow",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Filesystem-first Desk registry for projects, seats, tasks, threads, and handoffs.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/adapters.ts CHANGED
@@ -24,13 +24,13 @@ export function discoverAddress(application: string, environment: Environment =
24
24
  return discover();
25
25
  }
26
26
 
27
- export function notificationCommand(application: string, address: string, notice: string): string[] | undefined {
27
+ export function notificationCommand(application: string, address: string, notice: string, herdrSession?: string): string[] | undefined {
28
28
  const commands: Record<string, () => string[] | undefined> = {
29
29
  tmux: () => ["tmux", "send-keys", "-t", address, notice, "Enter"],
30
30
  // A Herdr pane id is the canonical runtime address. `pane send-text` is
31
31
  // supported by both standalone Herdr and TUIOS's embedded Herdr server;
32
32
  // `agent send` is not available on every embedded-server version.
33
- herdr: () => ["herdr", "pane", "send-text", address, notice],
33
+ herdr: () => ["herdr", ...(herdrSession ? ["--session", herdrSession] : []), "pane", "send-text", address, notice],
34
34
  tuios: () => {
35
35
  const separator = address.indexOf("/");
36
36
  if (separator < 1 || separator === address.length - 1) return undefined;
@@ -81,8 +81,8 @@ export function launchedAddress(application: string, placement: string, output:
81
81
  return `${placement}/${window}`;
82
82
  }
83
83
 
84
- export async function notify(application: string, address: string, notice: string) {
85
- const command = notificationCommand(application, address, notice);
84
+ export async function notify(application: string, address: string, notice: string, herdrSession?: string) {
85
+ const command = notificationCommand(application, address, notice, herdrSession);
86
86
  if (!command) return;
87
87
  await run(command, true);
88
88
  }
package/src/core.ts CHANGED
@@ -14,6 +14,8 @@ export type Desk = {
14
14
  schema: "atdd-workflow/desk/v1";
15
15
  desk: string;
16
16
  application: string;
17
+ /** Native Herdr session used for Desk notifications when application is herdr. */
18
+ herdr_session?: string;
17
19
  /** Named commands that model portfolio entries may resolve through. */
18
20
  executables?: Record<string, string>;
19
21
  aliases?: Record<string, string>;
package/src/reviews.ts CHANGED
@@ -360,7 +360,7 @@ export async function launchBehavioralReview(
360
360
  const nativeAddress = launchedAddress(application, placement, output);
361
361
  await bind(root, reviewer.address, ["--application", application, "--address", nativeAddress], modelId);
362
362
  try {
363
- await notify(application, nativeAddress, reviewerNotice(projectName, taskId, attempt, conventionSource.text));
363
+ await notify(application, nativeAddress, reviewerNotice(projectName, taskId, attempt, conventionSource.text), config.herdr_session);
364
364
  } catch (error) {
365
365
  console.warn(`Behavioral review notification for ${reviewer.address} was not delivered: ${(error as Error).message}`);
366
366
  }
package/src/seats.ts CHANGED
@@ -36,6 +36,9 @@ export function resolveExecutable(config: Desk, agent: string) {
36
36
  }
37
37
 
38
38
  export async function init(root: string, name: string, args: string[]) {
39
+ if (await exists(paths(root).desk)) {
40
+ throw new Error(`Desk registry already exists at ${paths(root).desk}; refusing to overwrite it. Use an existing Desk command, or choose a new directory.`);
41
+ }
39
42
  const config = { schema: "atdd-workflow/desk/v1" as const, desk: name, application: "tuios", executables: defaultExecutables() };
40
43
  await Promise.all([mkdir(paths(root).work, { recursive: true }), mkdir(paths(root).threads, { recursive: true })]);
41
44
  await Promise.all([atomicYaml(paths(root).desk, config), atomicYaml(paths(root).models, defaultModels())]);
@@ -161,7 +164,7 @@ async function chooseLaunchModel(root: string, config: Desk, record: Seat, portf
161
164
  }
162
165
 
163
166
  export const launchNotice = (address: string) =>
164
- `SYSTEM: you are ${address}. Read your durable seat and assigned task with: atdd-flow open ${address}. Continue assigned in_progress work until it is review-ready or explicitly blocked.`;
167
+ `SYSTEM: you are ${address}. Read your durable seat and assigned task with: atdd-flow open ${address}. Use the installed atdd-flow command; never use bunx to replace it or run atdd-flow init against an existing Desk. If your native pane binding differs from the Desk record, report it to the operator or coordinator. Continue assigned in_progress work until it is review-ready or explicitly blocked.`;
165
168
 
166
169
  export async function launch(root: string, address: string, args: string[]) {
167
170
  const resolved = await canonicalAddress(root, address);
@@ -191,7 +194,7 @@ export async function launch(root: string, address: string, args: string[]) {
191
194
  const nativeAddress = launchedAddress(application, placement, output);
192
195
  await bind(root, resolved, ["--application", application, "--address", nativeAddress], selectedModel);
193
196
  const notice = launchNotice(resolved);
194
- try { await notify(application, nativeAddress, notice); }
197
+ try { await notify(application, nativeAddress, notice, config.herdr_session); }
195
198
  catch (error) { console.warn(`Launch notification for ${resolved} was not delivered: ${(error as Error).message}`); }
196
199
  }
197
200
 
package/src/threads.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { readdir } from "node:fs/promises";
2
2
  import { notify } from "./adapters";
3
3
  import {
4
- atomicYaml, canonicalAddress, has, id, now, paths, project, readYaml,
4
+ atomicYaml, canonicalAddress, desk, has, id, now, paths, project, readYaml,
5
5
  required, seat, words,
6
6
  } from "./core";
7
7
 
@@ -69,7 +69,7 @@ async function inject(root: string, address: string, message: Message, threadId:
69
69
  if (!nativeAddress) return;
70
70
  const file = paths(root).message(threadId, message.id);
71
71
  const notice = `SYSTEM: new thread mail ${message.id} from ${message.from}. Read ${file}`;
72
- try { await notify(runtime.application, nativeAddress, notice); }
72
+ try { await notify(runtime.application, nativeAddress, notice, (await desk(root)).herdr_session); }
73
73
  catch (error) { console.warn(`Notification for ${address} was not delivered: ${(error as Error).message}`); }
74
74
  }
75
75