@seat-mesh/daemon 1.0.2 → 1.0.4

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 (127) hide show
  1. package/dist/ack/ack-open.d.ts +5 -0
  2. package/dist/ack/ack-open.d.ts.map +1 -0
  3. package/dist/ack/ack-open.js +86 -0
  4. package/dist/ack/ack-open.js.map +1 -0
  5. package/dist/ack/ack-sweep.d.ts +14 -0
  6. package/dist/ack/ack-sweep.d.ts.map +1 -0
  7. package/dist/ack/ack-sweep.js +186 -0
  8. package/dist/ack/ack-sweep.js.map +1 -0
  9. package/dist/ack/ack-watch.d.ts +13 -0
  10. package/dist/ack/ack-watch.d.ts.map +1 -0
  11. package/dist/ack/ack-watch.js +46 -0
  12. package/dist/ack/ack-watch.js.map +1 -0
  13. package/dist/border/border-paint.d.ts +24 -1
  14. package/dist/border/border-paint.d.ts.map +1 -1
  15. package/dist/border/border-paint.js +207 -82
  16. package/dist/border/border-paint.js.map +1 -1
  17. package/dist/border/border-paint.test.d.ts +2 -0
  18. package/dist/border/border-paint.test.d.ts.map +1 -0
  19. package/dist/border/border-paint.test.js +58 -0
  20. package/dist/border/border-paint.test.js.map +1 -0
  21. package/dist/checkback/checkback-fire.d.ts +13 -0
  22. package/dist/checkback/checkback-fire.d.ts.map +1 -1
  23. package/dist/checkback/checkback-fire.js +35 -0
  24. package/dist/checkback/checkback-fire.js.map +1 -1
  25. package/dist/checkback/checkback-fire.test.js +25 -1
  26. package/dist/checkback/checkback-fire.test.js.map +1 -1
  27. package/dist/connectivity/connectivity-recovery.d.ts +10 -2
  28. package/dist/connectivity/connectivity-recovery.d.ts.map +1 -1
  29. package/dist/connectivity/connectivity-recovery.js +54 -33
  30. package/dist/connectivity/connectivity-recovery.js.map +1 -1
  31. package/dist/connectivity/connectivity-recovery.test.js +7 -1
  32. package/dist/connectivity/connectivity-recovery.test.js.map +1 -1
  33. package/dist/connectivity/oc-resume-broadcast.d.ts +20 -0
  34. package/dist/connectivity/oc-resume-broadcast.d.ts.map +1 -0
  35. package/dist/connectivity/oc-resume-broadcast.js +74 -0
  36. package/dist/connectivity/oc-resume-broadcast.js.map +1 -0
  37. package/dist/connectivity/oc-resume-broadcast.test.d.ts +2 -0
  38. package/dist/connectivity/oc-resume-broadcast.test.d.ts.map +1 -0
  39. package/dist/connectivity/oc-resume-broadcast.test.js +9 -0
  40. package/dist/connectivity/oc-resume-broadcast.test.js.map +1 -0
  41. package/dist/index.d.ts +2 -0
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +1 -0
  44. package/dist/index.js.map +1 -1
  45. package/dist/inject/compose-gate.d.ts +7 -0
  46. package/dist/inject/compose-gate.d.ts.map +1 -1
  47. package/dist/inject/compose-gate.js +46 -2
  48. package/dist/inject/compose-gate.js.map +1 -1
  49. package/dist/inject/compose-gate.test.js +20 -1
  50. package/dist/inject/compose-gate.test.js.map +1 -1
  51. package/dist/inject/inject-delivery.d.ts.map +1 -1
  52. package/dist/inject/inject-delivery.js +7 -3
  53. package/dist/inject/inject-delivery.js.map +1 -1
  54. package/dist/inject/inject-delivery.test.js +2 -0
  55. package/dist/inject/inject-delivery.test.js.map +1 -1
  56. package/dist/inject/pane-hold.d.ts +4 -0
  57. package/dist/inject/pane-hold.d.ts.map +1 -0
  58. package/dist/inject/pane-hold.js +30 -0
  59. package/dist/inject/pane-hold.js.map +1 -0
  60. package/dist/mesh-inbox-server.js +228 -20
  61. package/dist/mesh-inbox-server.js.map +1 -1
  62. package/dist/mesh-inbox-supervisor.js +2 -2
  63. package/dist/mesh-inbox-supervisor.js.map +1 -1
  64. package/dist/notify/notify-act-ui.d.ts +9 -2
  65. package/dist/notify/notify-act-ui.d.ts.map +1 -1
  66. package/dist/notify/notify-act-ui.js +110 -30
  67. package/dist/notify/notify-act-ui.js.map +1 -1
  68. package/dist/notify/notify-act.d.ts +14 -2
  69. package/dist/notify/notify-act.d.ts.map +1 -1
  70. package/dist/notify/notify-act.js +44 -23
  71. package/dist/notify/notify-act.js.map +1 -1
  72. package/dist/notify/notify-act.test.js +11 -0
  73. package/dist/notify/notify-act.test.js.map +1 -1
  74. package/dist/notify/simple-markdown.d.ts +6 -0
  75. package/dist/notify/simple-markdown.d.ts.map +1 -0
  76. package/dist/notify/simple-markdown.js +74 -0
  77. package/dist/notify/simple-markdown.js.map +1 -0
  78. package/dist/notify/simple-markdown.test.d.ts +2 -0
  79. package/dist/notify/simple-markdown.test.d.ts.map +1 -0
  80. package/dist/notify/simple-markdown.test.js +15 -0
  81. package/dist/notify/simple-markdown.test.js.map +1 -0
  82. package/dist/orchestrator/mesh-orchestrator.d.ts +1 -0
  83. package/dist/orchestrator/mesh-orchestrator.d.ts.map +1 -1
  84. package/dist/orchestrator/mesh-orchestrator.js +99 -165
  85. package/dist/orchestrator/mesh-orchestrator.js.map +1 -1
  86. package/dist/peer/peer-backlog.d.ts +1 -1
  87. package/dist/peer/peer-backlog.d.ts.map +1 -1
  88. package/dist/peer/peer-backlog.js +52 -34
  89. package/dist/peer/peer-backlog.js.map +1 -1
  90. package/dist/peer/peer-bulk-drain.d.ts +18 -0
  91. package/dist/peer/peer-bulk-drain.d.ts.map +1 -0
  92. package/dist/peer/peer-bulk-drain.js +254 -0
  93. package/dist/peer/peer-bulk-drain.js.map +1 -0
  94. package/dist/peer/peer-skip.test.js +2 -2
  95. package/dist/peer/peer-skip.test.js.map +1 -1
  96. package/dist/peer/peer-target-resolve.d.ts +1 -0
  97. package/dist/peer/peer-target-resolve.d.ts.map +1 -1
  98. package/dist/peer/peer-target-resolve.js +17 -6
  99. package/dist/peer/peer-target-resolve.js.map +1 -1
  100. package/dist/store/create-queue-store.d.ts +1 -0
  101. package/dist/store/create-queue-store.d.ts.map +1 -1
  102. package/dist/store/create-queue-store.js.map +1 -1
  103. package/dist/store/jsonl-store.d.ts +34 -1
  104. package/dist/store/jsonl-store.d.ts.map +1 -1
  105. package/dist/store/jsonl-store.js +118 -2
  106. package/dist/store/jsonl-store.js.map +1 -1
  107. package/dist/store/sqlite-store.d.ts +22 -1
  108. package/dist/store/sqlite-store.d.ts.map +1 -1
  109. package/dist/store/sqlite-store.js +131 -4
  110. package/dist/store/sqlite-store.js.map +1 -1
  111. package/dist/store/target-jsonl.d.ts +31 -0
  112. package/dist/store/target-jsonl.d.ts.map +1 -0
  113. package/dist/store/target-jsonl.js +76 -0
  114. package/dist/store/target-jsonl.js.map +1 -0
  115. package/dist/store/target-jsonl.test.d.ts +2 -0
  116. package/dist/store/target-jsonl.test.d.ts.map +1 -0
  117. package/dist/store/target-jsonl.test.js +37 -0
  118. package/dist/store/target-jsonl.test.js.map +1 -0
  119. package/dist/target/target-fire.d.ts +22 -0
  120. package/dist/target/target-fire.d.ts.map +1 -0
  121. package/dist/target/target-fire.js +86 -0
  122. package/dist/target/target-fire.js.map +1 -0
  123. package/package.json +6 -5
  124. package/static/ui/decide.html +66 -0
  125. package/static/ui/index.html +68 -0
  126. package/static/ui/targets.css +119 -0
  127. package/static/ui/targets.js +186 -0
@@ -0,0 +1,31 @@
1
+ /** Operator self-deadline (EOD) — sibling to checkback, not pane poll-later. */
2
+ export interface TargetRow {
3
+ id: string;
4
+ status: "active" | "done" | "cancelled";
5
+ goal: string;
6
+ deadlineAt: string;
7
+ createdAt: string;
8
+ updatedAt: string;
9
+ /**
10
+ * scope = whole operator goal (e.g. "s13 remaining tickets") — leads break it down.
11
+ * slice = workable child with its own deadline under a scope.
12
+ */
13
+ kind?: "scope" | "slice";
14
+ /** Parent scope id when kind=slice. */
15
+ parentId?: string;
16
+ /** Last operator toast fire. */
17
+ remindedAt?: string;
18
+ /** Last triage peer to manager/secretary. */
19
+ triageAt?: string;
20
+ /** Seats to peer when due / on triage — default manager+secretary. */
21
+ triageTo?: string[];
22
+ source?: "operator";
23
+ }
24
+ export declare function readTargets(file: string): TargetRow[];
25
+ export declare function writeTargets(file: string, rows: TargetRow[]): void;
26
+ export declare function upsertTarget(file: string, row: TargetRow): TargetRow;
27
+ export declare function findTarget(file: string, id: string): TargetRow | null;
28
+ export declare function markTargetStatus(file: string, id: string, status: "done" | "cancelled"): TargetRow | null;
29
+ /** Cancel prior active targets with the same normalized goal. */
30
+ export declare function cancelActiveTargetsWithGoal(file: string, goal: string): number;
31
+ //# sourceMappingURL=target-jsonl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"target-jsonl.d.ts","sourceRoot":"","sources":["../../src/store/target-jsonl.ts"],"names":[],"mappings":"AAEA,gFAAgF;AAChF,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AA2BD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,CAErD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,CAElE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,GAAG,SAAS,CAKpE;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAMrE;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,GAAG,WAAW,GAC3B,SAAS,GAAG,IAAI,CAOlB;AAED,iEAAiE;AACjE,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAe9E"}
@@ -0,0 +1,76 @@
1
+ import fs from "node:fs";
2
+ function readJsonl(file) {
3
+ if (!fs.existsSync(file))
4
+ return [];
5
+ const out = [];
6
+ for (const line of fs.readFileSync(file, "utf8").split("\n")) {
7
+ const t = line.trim();
8
+ if (!t)
9
+ continue;
10
+ try {
11
+ out.push(JSON.parse(t));
12
+ }
13
+ catch {
14
+ /* skip bad line */
15
+ }
16
+ }
17
+ return out;
18
+ }
19
+ function writeJsonl(file, rows) {
20
+ fs.mkdirSync(pathDirname(file), { recursive: true });
21
+ fs.writeFileSync(file, rows.map((r) => JSON.stringify(r)).join("\n") + (rows.length ? "\n" : ""));
22
+ }
23
+ function pathDirname(file) {
24
+ const i = Math.max(file.lastIndexOf("/"), file.lastIndexOf("\\"));
25
+ return i >= 0 ? file.slice(0, i) : ".";
26
+ }
27
+ export function readTargets(file) {
28
+ return readJsonl(file);
29
+ }
30
+ export function writeTargets(file, rows) {
31
+ writeJsonl(file, rows);
32
+ }
33
+ export function upsertTarget(file, row) {
34
+ const rows = readTargets(file).filter((r) => r.id !== row.id);
35
+ rows.push(row);
36
+ writeTargets(file, rows);
37
+ return row;
38
+ }
39
+ export function findTarget(file, id) {
40
+ const needle = String(id || "").trim().toLowerCase();
41
+ if (!needle)
42
+ return null;
43
+ return (readTargets(file).find((r) => r.id === id || r.id.toLowerCase().startsWith(needle)) ?? null);
44
+ }
45
+ export function markTargetStatus(file, id, status) {
46
+ const row = findTarget(file, id);
47
+ if (!row)
48
+ return null;
49
+ if (row.status !== "active")
50
+ return row;
51
+ row.status = status;
52
+ row.updatedAt = new Date().toISOString();
53
+ return upsertTarget(file, row);
54
+ }
55
+ /** Cancel prior active targets with the same normalized goal. */
56
+ export function cancelActiveTargetsWithGoal(file, goal) {
57
+ const want = goal.trim().toLowerCase();
58
+ if (!want)
59
+ return 0;
60
+ const rows = readTargets(file);
61
+ const now = new Date().toISOString();
62
+ let n = 0;
63
+ for (const r of rows) {
64
+ if (r.status !== "active")
65
+ continue;
66
+ if (r.goal.trim().toLowerCase() !== want)
67
+ continue;
68
+ r.status = "cancelled";
69
+ r.updatedAt = now;
70
+ n++;
71
+ }
72
+ if (n)
73
+ writeTargets(file, rows);
74
+ return n;
75
+ }
76
+ //# sourceMappingURL=target-jsonl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"target-jsonl.js","sourceRoot":"","sources":["../../src/store/target-jsonl.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=target-jsonl.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"target-jsonl.test.d.ts","sourceRoot":"","sources":["../../src/store/target-jsonl.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,37 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { afterEach, describe, expect, it } from "vitest";
5
+ import { cancelActiveTargetsWithGoal, findTarget, markTargetStatus, readTargets, upsertTarget, } from "./target-jsonl.js";
6
+ describe("target-jsonl", () => {
7
+ let tmp = "";
8
+ afterEach(() => {
9
+ if (tmp)
10
+ fs.rmSync(tmp, { recursive: true, force: true });
11
+ });
12
+ it("upserts, finds by prefix, done/cancel, dedupes goal", () => {
13
+ tmp = fs.mkdtempSync(path.join(os.tmpdir(), "sm-tgt-"));
14
+ const file = path.join(tmp, "TARGET.jsonl");
15
+ const now = new Date().toISOString();
16
+ const row = {
17
+ id: "tgt-abc12345",
18
+ status: "active",
19
+ goal: "finish s13 tickets",
20
+ deadlineAt: now,
21
+ createdAt: now,
22
+ updatedAt: now,
23
+ triageTo: ["manager", "secretary"],
24
+ source: "operator",
25
+ };
26
+ upsertTarget(file, row);
27
+ expect(readTargets(file)).toHaveLength(1);
28
+ expect(findTarget(file, "tgt-abc")?.goal).toBe("finish s13 tickets");
29
+ cancelActiveTargetsWithGoal(file, "finish s13 tickets");
30
+ expect(readTargets(file)[0]?.status).toBe("cancelled");
31
+ const row2 = { ...row, id: "tgt-xyz99999", status: "active" };
32
+ upsertTarget(file, row2);
33
+ markTargetStatus(file, "tgt-xyz", "done");
34
+ expect(findTarget(file, "tgt-xyz")?.status).toBe("done");
35
+ });
36
+ });
37
+ //# sourceMappingURL=target-jsonl.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"target-jsonl.test.js","sourceRoot":"","sources":["../../src/store/target-jsonl.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EACL,2BAA2B,EAC3B,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,YAAY,GAEb,MAAM,mBAAmB,CAAC;AAE3B,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,GAAG;YAAE,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC;QACxD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAC5C,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,GAAG,GAAc;YACrB,EAAE,EAAE,cAAc;YAClB,MAAM,EAAE,QAAQ;YAChB,IAAI,EAAE,oBAAoB;YAC1B,UAAU,EAAE,GAAG;YACf,SAAS,EAAE,GAAG;YACd,SAAS,EAAE,GAAG;YACd,QAAQ,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC;YAClC,MAAM,EAAE,UAAU;SACnB,CAAC;QACF,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACxB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAErE,2BAA2B,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;QACxD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAEvD,MAAM,IAAI,GAAG,EAAE,GAAG,GAAG,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,QAAiB,EAAE,CAAC;QACvE,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACzB,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;QAC1C,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { LoadedProfile } from "@seat-mesh/core";
2
+ import type { TargetRow } from "../store/target-jsonl.js";
3
+ import type { PeerRow } from "../store/jsonl-store.js";
4
+ export interface TargetFireStore {
5
+ readTargets(): TargetRow[];
6
+ upsertTarget(row: TargetRow): TargetRow;
7
+ findTarget(id: string): TargetRow | null;
8
+ appendPeer(row: PeerRow): void;
9
+ }
10
+ export interface TargetFireCtx {
11
+ store: TargetFireStore;
12
+ loaded: LoadedProfile;
13
+ log: (line: string) => void;
14
+ nowMs?: number;
15
+ }
16
+ export declare function fireOneTarget(ctx: TargetFireCtx, row: TargetRow, opts?: {
17
+ forceToast?: boolean;
18
+ forceTriage?: boolean;
19
+ }): void;
20
+ /** One-shot: toast operator + peer manager/secretary when deadline passes. No renew. */
21
+ export declare function fireDueTargets(ctx: TargetFireCtx): void;
22
+ //# sourceMappingURL=target-fire.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"target-fire.d.ts","sourceRoot":"","sources":["../../src/target/target-fire.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAKvD,MAAM,WAAW,eAAe;IAC9B,WAAW,IAAI,SAAS,EAAE,CAAC;IAC3B,YAAY,CAAC,GAAG,EAAE,SAAS,GAAG,SAAS,CAAC;IACxC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACzC,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,eAAe,CAAC;IACvB,MAAM,EAAE,aAAa,CAAC;IACtB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAgDD,wBAAgB,aAAa,CAC3B,GAAG,EAAE,aAAa,EAClB,GAAG,EAAE,SAAS,EACd,IAAI,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,GACrD,IAAI,CAyBN;AAED,wFAAwF;AACxF,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAYvD"}
@@ -0,0 +1,86 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { resolvePaneTarget, sendDesktopToastSync } from "@seat-mesh/tmux";
3
+ const TARGET_FIRE_BUDGET = 4;
4
+ const DEFAULT_TRIAGE = ["manager", "secretary"];
5
+ function triageSeats(row) {
6
+ const raw = row.triageTo?.length ? row.triageTo : DEFAULT_TRIAGE;
7
+ return [...new Set(raw.map((s) => s.trim().toLowerCase()).filter(Boolean))];
8
+ }
9
+ function enqueueTriagePeers(ctx, row) {
10
+ const sent = [];
11
+ const short = row.id.slice(0, 8);
12
+ const kind = row.kind === "slice" ? "slice" : row.kind === "scope" ? "scope" : "target";
13
+ const breakdown = kind === "scope"
14
+ ? `\nSCOPE: break into workable slices — seatmesh target add "<ticket>" --under ${short} --deadline 6h\nThen assign workers; balance load. Mark scope done when children clear.`
15
+ : kind === "slice"
16
+ ? `\nSLICE under ${row.parentId?.slice(0, 8) ?? "?"}: assign a worker/mini; seatmesh target done ${short} when finished.`
17
+ : `\nTriage: balance load across workers/minis.`;
18
+ const msg = `[target ${short}] ${kind.toUpperCase()} DUE: ${row.goal}\n` +
19
+ `deadline=${row.deadlineAt}` +
20
+ breakdown +
21
+ `\nOperator: seatmesh target done ${short} · UI: http://127.0.0.1:<daemon>/ui/`;
22
+ const now = new Date().toISOString();
23
+ for (const seat of triageSeats(row)) {
24
+ const hit = resolvePaneTarget(seat, ctx.loaded);
25
+ if ("error" in hit) {
26
+ ctx.log(`target triage skip ${seat}: ${hit.error}`);
27
+ continue;
28
+ }
29
+ const peer = {
30
+ id: randomUUID(),
31
+ at: now,
32
+ kind: "to-slot",
33
+ fromSlot: "operator",
34
+ fromPorts: null,
35
+ roomSlug: null,
36
+ fromAgent: "target",
37
+ targetPane: hit.paneId,
38
+ targetLabel: seat,
39
+ msg,
40
+ sent: false,
41
+ };
42
+ ctx.store.appendPeer(peer);
43
+ sent.push(seat);
44
+ }
45
+ return sent;
46
+ }
47
+ export function fireOneTarget(ctx, row, opts) {
48
+ const nowIso = new Date(ctx.nowMs ?? Date.now()).toISOString();
49
+ const short = row.id.slice(0, 8);
50
+ const title = `Target due · ${short}`;
51
+ const body = `${row.goal}\n` +
52
+ `deadline ${row.deadlineAt}\n` +
53
+ `done: seatmesh target done ${short} cancel: seatmesh target cancel ${short}`;
54
+ if (opts?.forceToast || !row.remindedAt) {
55
+ const ok = sendDesktopToastSync(ctx.loaded.workspace, title, body);
56
+ ctx.log(`target toast id=${short} ok=${ok}`);
57
+ row.remindedAt = nowIso;
58
+ }
59
+ if (opts?.forceTriage || !row.triageAt) {
60
+ const seats = enqueueTriagePeers(ctx, row);
61
+ if (seats.length) {
62
+ row.triageAt = nowIso;
63
+ ctx.log(`target triage id=${short} -> ${seats.join(",")}`);
64
+ }
65
+ }
66
+ row.updatedAt = nowIso;
67
+ ctx.store.upsertTarget(row);
68
+ }
69
+ /** One-shot: toast operator + peer manager/secretary when deadline passes. No renew. */
70
+ export function fireDueTargets(ctx) {
71
+ const now = ctx.nowMs ?? Date.now();
72
+ const rows = ctx.store.readTargets().filter((r) => r.status === "active");
73
+ let n = 0;
74
+ for (const row of rows) {
75
+ if (n >= TARGET_FIRE_BUDGET)
76
+ break;
77
+ const due = Date.parse(row.deadlineAt);
78
+ if (Number.isNaN(due) || due > now)
79
+ continue;
80
+ if (row.remindedAt && row.triageAt)
81
+ continue;
82
+ fireOneTarget(ctx, row);
83
+ n++;
84
+ }
85
+ }
86
+ //# sourceMappingURL=target-fire.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"target-fire.js","sourceRoot":"","sources":["../../src/target/target-fire.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seat-mesh/daemon",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "type": "module",
5
5
  "description": "Inbox orchestrator \u2014 sole pane writer; BullMQ workers drain queues.",
6
6
  "main": "./dist/index.js",
@@ -11,9 +11,9 @@
11
11
  "prepublishOnly": "npm run build"
12
12
  },
13
13
  "dependencies": {
14
- "@seat-mesh/core": "1.0.2",
15
- "@seat-mesh/providers": "1.0.2",
16
- "@seat-mesh/tmux": "1.0.2",
14
+ "@seat-mesh/core": "1.0.4",
15
+ "@seat-mesh/providers": "1.0.4",
16
+ "@seat-mesh/tmux": "1.0.4",
17
17
  "bullmq": "^6.3.4",
18
18
  "ioredis": "^6.0.0"
19
19
  },
@@ -27,6 +27,7 @@
27
27
  "access": "public"
28
28
  },
29
29
  "files": [
30
- "dist"
30
+ "dist",
31
+ "static"
31
32
  ]
32
33
  }
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>seatmesh · decide</title>
7
+ <link rel="stylesheet" href="./targets.css" />
8
+ <style>
9
+ .panel {
10
+ padding: 1.25rem;
11
+ background: var(--panel);
12
+ border: 1px solid var(--line);
13
+ max-width: 40rem;
14
+ }
15
+ .steps { color: var(--muted); margin: 0 0 1rem; padding-left: 1.2rem; }
16
+ .steps li { margin: 0.35rem 0; }
17
+ .btn {
18
+ display: inline-block;
19
+ padding: 0.55rem 1.15rem;
20
+ text-decoration: none;
21
+ font-weight: 600;
22
+ border-radius: 2px;
23
+ border: 1px solid transparent;
24
+ margin: 0.25rem 0.4rem 0.25rem 0;
25
+ }
26
+ .btn-yes { background: var(--yes); color: #061018; }
27
+ .btn-info { background: transparent; color: var(--info); border-color: var(--line); }
28
+ .btn-link { background: var(--accent); color: #061018; }
29
+ code.url { word-break: break-all; color: var(--ink); }
30
+ </style>
31
+ </head>
32
+ <body>
33
+ <header class="top">
34
+ <div class="brand">seatmesh</div>
35
+ <nav>
36
+ <a href="./">Targets</a>
37
+ <a class="on" href="./decide.html">Decide</a>
38
+ </nav>
39
+ </header>
40
+
41
+ <main>
42
+ <section class="panel">
43
+ <h1>Decide (beta)</h1>
44
+ <p class="lede">
45
+ Agent <code>notify yesno</code> shows a toast with native
46
+ <strong>Info / Yes / No</strong> buttons (Linux notify-send) and opens the
47
+ browser decision card. Yes/No peer the reply seat as
48
+ <code>PRIORITY [operator-decide]</code>. Raw <code>/act/v1</code> URLs are not dumped in the toast (they are not clickable there).
49
+
50
+ </p>
51
+ <ol class="steps">
52
+ <li>Agent: <code>seatmesh agent notify yesno "&lt;title&gt;" "&lt;body&gt;"</code></li>
53
+ <li>Toast: click <strong>Info</strong> → this UI’s decision card (<code>/act/card/…</code>)</li>
54
+ <li>On the card (or toast): <strong>Yes</strong> / <strong>No</strong></li>
55
+ </ol>
56
+ <p class="lede">Try the live demo (fresh one-shot links):</p>
57
+ <a class="btn btn-link" href="./demo-yesno">Open Yes / No demo</a>
58
+ <a class="btn btn-info" href="./">Back to Targets</a>
59
+ </section>
60
+ </main>
61
+
62
+ <footer>
63
+ Toast Info URL looks like <code class="url">http://127.0.0.1:&lt;port&gt;/act/card/&lt;id&gt;</code>
64
+ </footer>
65
+ </body>
66
+ </html>
@@ -0,0 +1,68 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>seatmesh · targets</title>
7
+ <link rel="stylesheet" href="./targets.css" />
8
+ </head>
9
+ <body>
10
+ <header class="top">
11
+ <div class="brand">seatmesh</div>
12
+ <nav>
13
+ <a class="on" href="./">Targets</a>
14
+ <a href="./decide.html">Decide</a>
15
+ </nav>
16
+ <div class="meta" id="meta">…</div>
17
+ </header>
18
+
19
+ <main>
20
+ <section class="compose">
21
+ <h1>Targets</h1>
22
+ <p class="lede">
23
+ A <strong>scope</strong> is the whole goal (e.g. remaining s13 tickets). Manager/secretary break it into
24
+ <strong>slices</strong> with their own deadlines and balance workers.
25
+ </p>
26
+ <form id="add-form">
27
+ <label class="sr">Goal</label>
28
+ <input id="goal" name="goal" required placeholder="finish remaining s13 tickets" autocomplete="off" />
29
+ <div class="row">
30
+ <label>
31
+ Deadline
32
+ <input id="deadline" name="deadline" value="eod" placeholder="eod | 6h | ISO" />
33
+ </label>
34
+ <label>
35
+ Kind
36
+ <select id="kind">
37
+ <option value="scope">scope (whole goal)</option>
38
+ <option value="slice">slice (under scope)</option>
39
+ </select>
40
+ </label>
41
+ <label id="under-wrap" class="hidden">
42
+ Under scope id
43
+ <input id="under" placeholder="tgt-…" />
44
+ </label>
45
+ <button type="submit">Add</button>
46
+ </div>
47
+ <p id="form-err" class="err" hidden></p>
48
+ </form>
49
+ </section>
50
+
51
+ <section class="list-head">
52
+ <h2>Active</h2>
53
+ <label class="chk"><input type="checkbox" id="show-all" /> show done/cancelled</label>
54
+ <button type="button" id="refresh" class="ghost">Refresh</button>
55
+ </section>
56
+ <div id="list" class="list"></div>
57
+ <p id="empty" class="empty" hidden>No targets yet.</p>
58
+ </main>
59
+
60
+ <footer>
61
+ CLI: <code>seatmesh target add "…"</code> ·
62
+ <code>seatmesh target triage &lt;id&gt;</code> ·
63
+ notify: <code>seatmesh agent notify yesno</code> → toast <strong>Info · Yes · No</strong> ·
64
+ <a href="./decide.html">Decide</a>
65
+ </footer>
66
+ <script src="./targets.js" type="module"></script>
67
+ </body>
68
+ </html>
@@ -0,0 +1,119 @@
1
+ :root {
2
+ --bg: #0b1220;
3
+ --panel: #121a2b;
4
+ --ink: #e8eef8;
5
+ --muted: #8b9bb4;
6
+ --line: #243149;
7
+ --accent: #5b9fd4;
8
+ --yes: #3d8bfd;
9
+ --no: #5a6a80;
10
+ --info: #7eb8e8;
11
+ --warn: #d4a574;
12
+ --ok: #5bb89a;
13
+ --danger: #c47a6a;
14
+ --font: "IBM Plex Sans", "Segoe UI", system-ui, sans-serif;
15
+ --mono: "IBM Plex Mono", ui-monospace, monospace;
16
+ }
17
+
18
+ * { box-sizing: border-box; }
19
+ html, body {
20
+ margin: 0;
21
+ min-height: 100%;
22
+ background: var(--bg);
23
+ color: var(--ink);
24
+ font: 15px/1.45 var(--font);
25
+ }
26
+ .top {
27
+ display: flex;
28
+ align-items: center;
29
+ gap: 1.5rem;
30
+ padding: 0.85rem 1.5rem;
31
+ border-bottom: 1px solid var(--line);
32
+ background: var(--panel);
33
+ }
34
+ .brand {
35
+ font-weight: 650;
36
+ letter-spacing: 0.04em;
37
+ text-transform: lowercase;
38
+ }
39
+ nav a {
40
+ color: var(--muted);
41
+ text-decoration: none;
42
+ margin-right: 1rem;
43
+ }
44
+ nav a.on { color: var(--accent); }
45
+ .meta { margin-left: auto; color: var(--muted); font-size: 0.85rem; font-family: var(--mono); }
46
+ main { max-width: 920px; margin: 0 auto; padding: 1.75rem 1.25rem 4rem; }
47
+ h1 { font-size: 1.75rem; font-weight: 600; margin: 0 0 0.4rem; }
48
+ h2 { font-size: 1rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); font-weight: 600; }
49
+ .lede { color: var(--muted); max-width: 42rem; margin: 0 0 1.25rem; }
50
+ .compose {
51
+ padding: 1.25rem 1.25rem 1.4rem;
52
+ background: var(--panel);
53
+ border: 1px solid var(--line);
54
+ margin-bottom: 2rem;
55
+ }
56
+ form input, form select, form button {
57
+ font: inherit;
58
+ color: var(--ink);
59
+ background: var(--bg);
60
+ border: 1px solid var(--line);
61
+ border-radius: 2px;
62
+ padding: 0.55rem 0.7rem;
63
+ }
64
+ #goal { width: 100%; margin-bottom: 0.75rem; }
65
+ .row { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: flex-end; }
66
+ .row label { display: flex; flex-direction: column; gap: 0.3rem; color: var(--muted); font-size: 0.8rem; }
67
+ button {
68
+ background: var(--accent);
69
+ color: #061018;
70
+ border: none;
71
+ font-weight: 600;
72
+ cursor: pointer;
73
+ padding: 0.6rem 1rem;
74
+ }
75
+ button.ghost {
76
+ background: transparent;
77
+ color: var(--muted);
78
+ border: 1px solid var(--line);
79
+ font-weight: 500;
80
+ }
81
+ button.tiny { padding: 0.35rem 0.55rem; font-size: 0.8rem; }
82
+ .list-head {
83
+ display: flex;
84
+ align-items: center;
85
+ gap: 1rem;
86
+ margin-bottom: 0.75rem;
87
+ }
88
+ .chk { color: var(--muted); font-size: 0.85rem; margin-left: auto; }
89
+ .list { display: flex; flex-direction: column; gap: 0.65rem; }
90
+ .card {
91
+ border: 1px solid var(--line);
92
+ background: var(--panel);
93
+ padding: 0.9rem 1rem;
94
+ display: grid;
95
+ grid-template-columns: 1fr auto;
96
+ gap: 0.5rem 1rem;
97
+ }
98
+ .card.scope { border-left: 3px solid var(--accent); }
99
+ .card.slice { border-left: 3px solid var(--warn); margin-left: 1rem; }
100
+ .card.done, .card.cancelled { opacity: 0.55; }
101
+ .goal { font-weight: 550; }
102
+ .tags { color: var(--muted); font-family: var(--mono); font-size: 0.78rem; }
103
+ .actions { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: start; }
104
+ .empty { color: var(--muted); }
105
+ .err { color: var(--danger); margin: 0.5rem 0 0; }
106
+ .hidden { display: none !important; }
107
+ .sr { position: absolute; left: -9999px; }
108
+ footer {
109
+ border-top: 1px solid var(--line);
110
+ padding: 1rem 1.5rem;
111
+ color: var(--muted);
112
+ font-size: 0.8rem;
113
+ }
114
+ footer code { font-family: var(--mono); color: var(--ink); }
115
+ footer a { color: var(--accent); }
116
+ @media (max-width: 640px) {
117
+ .card { grid-template-columns: 1fr; }
118
+ .card.slice { margin-left: 0; }
119
+ }