instar 1.3.1586 → 1.3.1588

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 (111) hide show
  1. package/dashboard/console/promises-model.js +16 -0
  2. package/dashboard/console/promises.js +14 -2
  3. package/dashboard/desktop-setup.js +164 -0
  4. package/dashboard/desktop.css +6 -0
  5. package/dashboard/desktop.html +5 -0
  6. package/dashboard/desktop.js +40 -4
  7. package/dist/commands/server.d.ts.map +1 -1
  8. package/dist/commands/server.js +12 -0
  9. package/dist/commands/server.js.map +1 -1
  10. package/dist/core/AutonomousRunStore.d.ts +7 -0
  11. package/dist/core/AutonomousRunStore.d.ts.map +1 -1
  12. package/dist/core/AutonomousRunStore.js +8 -1
  13. package/dist/core/AutonomousRunStore.js.map +1 -1
  14. package/dist/core/AutonomousStartAdmission.d.ts +94 -0
  15. package/dist/core/AutonomousStartAdmission.d.ts.map +1 -0
  16. package/dist/core/AutonomousStartAdmission.js +170 -0
  17. package/dist/core/AutonomousStartAdmission.js.map +1 -0
  18. package/dist/core/DesktopSetupGuide.d.ts +72 -0
  19. package/dist/core/DesktopSetupGuide.d.ts.map +1 -0
  20. package/dist/core/DesktopSetupGuide.js +186 -0
  21. package/dist/core/DesktopSetupGuide.js.map +1 -0
  22. package/dist/core/DesktopSetupTarget.d.ts +67 -0
  23. package/dist/core/DesktopSetupTarget.d.ts.map +1 -0
  24. package/dist/core/DesktopSetupTarget.js +227 -0
  25. package/dist/core/DesktopSetupTarget.js.map +1 -0
  26. package/dist/core/MacDesktopHost.d.ts +2 -0
  27. package/dist/core/MacDesktopHost.d.ts.map +1 -1
  28. package/dist/core/MacDesktopHost.js +2 -0
  29. package/dist/core/MacDesktopHost.js.map +1 -1
  30. package/dist/core/MobileDeviceKeys.d.ts +30 -0
  31. package/dist/core/MobileDeviceKeys.d.ts.map +1 -1
  32. package/dist/core/MobileDeviceKeys.js +60 -0
  33. package/dist/core/MobileDeviceKeys.js.map +1 -1
  34. package/dist/core/MobilePush.d.ts +81 -0
  35. package/dist/core/MobilePush.d.ts.map +1 -0
  36. package/dist/core/MobilePush.js +386 -0
  37. package/dist/core/MobilePush.js.map +1 -0
  38. package/dist/core/PostUpdateMigrator.d.ts +5 -0
  39. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  40. package/dist/core/PostUpdateMigrator.js +26 -0
  41. package/dist/core/PostUpdateMigrator.js.map +1 -1
  42. package/dist/core/WriteDomainRegistry.d.ts.map +1 -1
  43. package/dist/core/WriteDomainRegistry.js +4 -0
  44. package/dist/core/WriteDomainRegistry.js.map +1 -1
  45. package/dist/core/devGatedFeatures.d.ts.map +1 -1
  46. package/dist/core/devGatedFeatures.js +6 -0
  47. package/dist/core/devGatedFeatures.js.map +1 -1
  48. package/dist/core/types.d.ts +19 -0
  49. package/dist/core/types.d.ts.map +1 -1
  50. package/dist/core/types.js.map +1 -1
  51. package/dist/data/standards-guard-index.json +1 -1
  52. package/dist/data/standards-guard-index.meta.json +2 -2
  53. package/dist/data/standards-registry.meta.json +1 -1
  54. package/dist/lifeline/TelegramLifeline.d.ts +1 -0
  55. package/dist/lifeline/TelegramLifeline.d.ts.map +1 -1
  56. package/dist/lifeline/TelegramLifeline.js +7 -1
  57. package/dist/lifeline/TelegramLifeline.js.map +1 -1
  58. package/dist/lifeline/lifelineLock.d.ts +27 -4
  59. package/dist/lifeline/lifelineLock.d.ts.map +1 -1
  60. package/dist/lifeline/lifelineLock.js +198 -24
  61. package/dist/lifeline/lifelineLock.js.map +1 -1
  62. package/dist/messaging/TelegramAdapter.d.ts +7 -0
  63. package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
  64. package/dist/messaging/TelegramAdapter.js +11 -2
  65. package/dist/messaging/TelegramAdapter.js.map +1 -1
  66. package/dist/native/instar-desktop-host +0 -0
  67. package/dist/scaffold/templates.d.ts.map +1 -1
  68. package/dist/scaffold/templates.js +4 -2
  69. package/dist/scaffold/templates.js.map +1 -1
  70. package/dist/server/AgentServer.d.ts +5 -0
  71. package/dist/server/AgentServer.d.ts.map +1 -1
  72. package/dist/server/AgentServer.js +133 -5
  73. package/dist/server/AgentServer.js.map +1 -1
  74. package/dist/server/CapabilityIndex.d.ts.map +1 -1
  75. package/dist/server/CapabilityIndex.js +4 -3
  76. package/dist/server/CapabilityIndex.js.map +1 -1
  77. package/dist/server/desktopSetupRoutes.d.ts +34 -0
  78. package/dist/server/desktopSetupRoutes.d.ts.map +1 -0
  79. package/dist/server/desktopSetupRoutes.js +234 -0
  80. package/dist/server/desktopSetupRoutes.js.map +1 -0
  81. package/dist/server/machineRoutes.d.ts +2 -0
  82. package/dist/server/machineRoutes.d.ts.map +1 -1
  83. package/dist/server/machineRoutes.js +17 -0
  84. package/dist/server/machineRoutes.js.map +1 -1
  85. package/dist/server/mobilePairingRoutes.d.ts +9 -0
  86. package/dist/server/mobilePairingRoutes.d.ts.map +1 -1
  87. package/dist/server/mobilePairingRoutes.js +190 -0
  88. package/dist/server/mobilePairingRoutes.js.map +1 -1
  89. package/dist/server/routes.d.ts +3 -0
  90. package/dist/server/routes.d.ts.map +1 -1
  91. package/dist/server/routes.js +141 -4
  92. package/dist/server/routes.js.map +1 -1
  93. package/dist/testing/selfActionRegistry.d.ts.map +1 -1
  94. package/dist/testing/selfActionRegistry.js +37 -0
  95. package/dist/testing/selfActionRegistry.js.map +1 -1
  96. package/package.json +1 -1
  97. package/src/data/builtin-manifest.json +66 -66
  98. package/src/data/standards-guard-index.json +1 -1
  99. package/src/data/standards-guard-index.meta.json +2 -2
  100. package/src/data/standards-registry.meta.json +1 -1
  101. package/src/scaffold/templates.ts +4 -2
  102. package/upgrades/1.3.1587.md +27 -0
  103. package/upgrades/1.3.1588.md +61 -0
  104. package/upgrades/side-effects/autonomous-start-admission.eli16.md +27 -0
  105. package/upgrades/side-effects/autonomous-start-admission.md +141 -0
  106. package/upgrades/side-effects/console-promise-approve-decline.eli16.md +13 -0
  107. package/upgrades/side-effects/console-promise-approve-decline.md +36 -0
  108. package/upgrades/side-effects/desktop-guided-setup.md +117 -0
  109. package/upgrades/side-effects/ecosystem-idea-pipeline-spec.md +44 -0
  110. package/upgrades/side-effects/lifeline-lock-heartbeat.md +150 -0
  111. package/upgrades/side-effects/mobile-push.md +109 -0
@@ -174,8 +174,24 @@ export function updateQuestionOf(c, now = Date.now()) {
174
174
  : `What is the current status of “${subject}”? Please tell me what is done, what remains, and when I should expect the next update.`;
175
175
  }
176
176
 
177
+ /** A promise that waits only on the operator's yes or no: the page offers Approve and Decline. */
178
+ export function canDecide(c) {
179
+ return Boolean(c) && c.status === 'pending' && c.blockedOn === 'user-authorization';
180
+ }
181
+
182
+ /** The words after an Approve / Decline answer, from the server's reply. */
183
+ export function decideResultWords(decision, res) {
184
+ if (res && res.ok) {
185
+ const posted = res.data && res.data.postedInConversation === false ? ' I could not post it in the conversation, so mention it there if it matters.' : '';
186
+ return { ok: true, text: (decision === 'approve' ? 'Approved. I will go ahead.' : 'Declined. The promise is closed.') + posted };
187
+ }
188
+ const why = (res && res.reason) || 'the server could not be reached';
189
+ return { ok: false, text: `That did not go through: ${String(why).replace(/\.$/, '').replace(/^The /, 'the ')}.` };
190
+ }
191
+
177
192
  /** A concrete next step without assigning the agent's work to the operator. */
178
193
  export function nextStepOf(c, now = Date.now()) {
194
+ if (canDecide(c)) return 'Your approval is needed. Approve or decline it here, or reply in the conversation to talk it through first.';
179
195
  if (waitsOnOperator(c)) return 'Your answer or approval is needed. Open the conversation to respond.';
180
196
  if (isMissed(c, now) || needsPromiseReview(c, now)) return 'This follow-up is mine: I need to verify the current outcome. No action is needed from you.';
181
197
  return 'The next step is mine. No action is needed from you.';
@@ -1,7 +1,7 @@
1
1
  // Promises page (docs/specs/console-features/work.md, "Commitments → Promises").
2
2
  // Read with Home's rules; actions use the bearer token only (no PIN on these routes).
3
3
 
4
- import { buildPromisesPage, storyOf, backstoryOf, updateQuestionOf, nextStepOf, actionsFor } from './promises-model.js';
4
+ import { buildPromisesPage, storyOf, backstoryOf, updateQuestionOf, nextStepOf, actionsFor, canDecide, decideResultWords } from './promises-model.js';
5
5
  import { isInternalFollowUp } from './home-model.js';
6
6
  import { promiseActionLinks } from './promise-actions.js';
7
7
  import { el, setKids, pageHead, section, sheet, closeSheet, sheetIsOpen, story, actionButton, note, cantTell } from './ui.js';
@@ -131,7 +131,7 @@ function openPromise(r, { post, chatId, names, refresh }) {
131
131
  el('p', { class: 'promise-backstory-note', text: 'Copy this question and paste it in the conversation:' }),
132
132
  el('textarea', { class: 'promise-question', readonly: true }, question)) : null;
133
133
  if (fallback) blocks.push(fallback);
134
- row.append(el('a', { class: `${actionLinks.length || !waitsOnYou ? 'btn-quiet' : 'btn-primary'} btn-inline`, href: link,
134
+ row.append(el('a', { class: `${actionLinks.length || !waitsOnYou || canDecide(c) ? 'btn-quiet' : 'btn-primary'} btn-inline`, href: link,
135
135
  target: '_blank', rel: 'noopener', text: waitsOnYou ? 'Reply in the conversation' : internal ? 'View source conversation' : 'Optional: copy a question and open chat',
136
136
  onclick: question ? () => {
137
137
  // Topic links open the right chat; Telegram does not document a draft
@@ -150,6 +150,18 @@ function openPromise(r, { post, chatId, names, refresh }) {
150
150
  if (x.ok) return { ok: true, message: path === 'deliver' ? 'Marked as done.' : path === 'withdraw' ? 'Dropped.' : 'Reminders resumed.' };
151
151
  return { ok: false, message: x.reason };
152
152
  };
153
+ if (canDecide(c)) {
154
+ const decide = async (decision, note) => {
155
+ const x = await post(`/commitments/${id}/decide${q}`, { decision, ...(note ? { note } : {}) });
156
+ const w = decideResultWords(decision, x);
157
+ return { ok: w.ok, message: w.text };
158
+ };
159
+ const after = () => setTimeout(() => { closeSheet(); refresh(); }, 1200);
160
+ const decideRow = el('div', { class: 'sheet-actions promise-decide' },
161
+ actionButton({ label: 'Approve', kind: 'primary', confirm: 'Approve this? The session goes ahead with it.', run: () => decide('approve'), done: after }),
162
+ actionButton({ label: 'Decline', kind: 'quiet', confirm: 'Decline this? The promise closes and the session is told not to do it.', run: () => decide('decline'), done: after }));
163
+ blocks.push(decideRow);
164
+ }
153
165
  if (acts.includes('deliver')) row.append(actionButton({ label: waitsOnYou ? 'I handled this' : 'Mark as done', kind: link ? 'quiet' : 'primary',
154
166
  confirm: waitsOnYou ? 'Close this reminder? This does not send a reply or perform the requested approval.' : 'Mark this promise as done?',
155
167
  run: () => result('deliver', {}), done: () => setTimeout(() => { closeSheet(); refresh(); }, 700) }));
@@ -0,0 +1,164 @@
1
+ // Guided Remote Desktop setup. Everything shown here comes from the server, so
2
+ // the dashboard and the app say the same thing. It never decides anything.
3
+ const POLL_MS = 4_000;
4
+ const MAX_POLL_MS = 60_000;
5
+ const POLL_FOR_MS = 10 * 60_000;
6
+
7
+ export function createDesktopSetup({ api, $, onReady, onPinLost }) {
8
+ const rows = new Map();
9
+ let activeId = '';
10
+ let timer = 0;
11
+ let delay = POLL_MS;
12
+ let startedAt = 0;
13
+
14
+ function stopPolling() {
15
+ if (timer) clearTimeout(timer);
16
+ timer = 0;
17
+ activeId = '';
18
+ }
19
+
20
+ function schedule() {
21
+ if (timer) clearTimeout(timer);
22
+ timer = 0;
23
+ if (!activeId || Date.now() - startedAt > POLL_FOR_MS) { stopPolling(); return; }
24
+ timer = setTimeout(poll, delay);
25
+ }
26
+
27
+ async function poll() {
28
+ timer = 0;
29
+ const id = activeId;
30
+ if (!id) return;
31
+ try {
32
+ const row = await api(`/desktop/setup/${encodeURIComponent(id)}`);
33
+ delay = POLL_MS;
34
+ const wasReady = rows.get(id)?.ready;
35
+ show(row);
36
+ if (row.ready && !wasReady) {
37
+ stopPolling();
38
+ await onReady(row);
39
+ return;
40
+ }
41
+ if (row.ready) { stopPolling(); return; }
42
+ } catch (error) {
43
+ if (lostPin(error)) return;
44
+ delay = Math.min(delay * 2, MAX_POLL_MS);
45
+ }
46
+ schedule();
47
+ }
48
+
49
+ function lostPin(error) {
50
+ // This machine restarting ends the PIN session, which is expected here.
51
+ if (!/dashboard operator session/i.test(error?.message || '')) return false;
52
+ stopPolling();
53
+ onPinLost();
54
+ return true;
55
+ }
56
+
57
+ function follow(id) {
58
+ activeId = id;
59
+ delay = POLL_MS;
60
+ startedAt = Date.now();
61
+ schedule();
62
+ }
63
+
64
+ async function act(row, action, note) {
65
+ if (action.id === 'check') { note.textContent = 'Checking…'; }
66
+ try {
67
+ if (action.id === 'check') {
68
+ show(await api(`/desktop/setup/${encodeURIComponent(row.machineId)}`));
69
+ rows.get(row.machineId)?.ready ? await onReady(rows.get(row.machineId)) : follow(row.machineId);
70
+ return;
71
+ }
72
+ const reply = await api(`/desktop/setup/${encodeURIComponent(row.machineId)}`, 'POST',
73
+ { action: action.id, ...(action.pane ? { pane: action.pane } : {}) });
74
+ show(reply.step);
75
+ follow(row.machineId);
76
+ } catch (error) {
77
+ if (lostPin(error)) return;
78
+ if (error.step) show(error.step);
79
+ const current = rowElement(row.machineId)?.querySelector('.setup-note');
80
+ if (current) current.textContent = error.message || 'That did not work. Try again.';
81
+ follow(row.machineId);
82
+ }
83
+ }
84
+
85
+ function rowElement(id) {
86
+ return [...$('setupRows').children].find(item => item.dataset.machineId === id);
87
+ }
88
+
89
+ function show(row) {
90
+ rows.set(row.machineId, row);
91
+ const item = document.createElement('li');
92
+ item.dataset.machineId = row.machineId;
93
+ const title = document.createElement('strong');
94
+ title.textContent = row.title;
95
+ const detail = document.createElement('p');
96
+ detail.textContent = row.detail;
97
+ const actions = document.createElement('div');
98
+ actions.className = 'setup-actions';
99
+ const note = document.createElement('p');
100
+ note.className = 'setup-note';
101
+ note.setAttribute('role', 'status');
102
+ for (const action of row.actions) {
103
+ const button = document.createElement('button');
104
+ button.type = 'button';
105
+ button.textContent = action.label;
106
+ if (action.id === 'turn-off') button.className = 'setup-quiet';
107
+ button.addEventListener('click', async () => {
108
+ if (action.id === 'turn-off'
109
+ && !confirm(`Turn off Remote Desktop on ${row.label}? Its Instar server restarts.`)) return;
110
+ button.disabled = true;
111
+ try { await act(row, action, note); } finally { button.disabled = false; }
112
+ });
113
+ actions.append(button);
114
+ }
115
+ item.append(title, detail, actions);
116
+ if (row.note) {
117
+ const extra = document.createElement('p');
118
+ extra.textContent = row.note;
119
+ item.append(extra);
120
+ }
121
+ if (row.fallback) {
122
+ const more = document.createElement('details');
123
+ const summary = document.createElement('summary');
124
+ summary.textContent = 'Do it by hand instead';
125
+ const text = document.createElement('p');
126
+ text.textContent = row.fallback;
127
+ more.append(summary, text);
128
+ item.append(more);
129
+ }
130
+ item.append(note);
131
+ const existing = rowElement(row.machineId);
132
+ if (existing) existing.replaceWith(item);
133
+ else $('setupRows').append(item);
134
+ }
135
+
136
+ async function refresh() {
137
+ let list;
138
+ try { list = await api('/desktop/setup'); }
139
+ catch (error) {
140
+ if (lostPin(error)) return false;
141
+ // An older server, or one with no machine identity yet.
142
+ $('setup').hidden = true;
143
+ return false;
144
+ }
145
+ stopPolling();
146
+ $('setupRows').replaceChildren();
147
+ rows.clear();
148
+ if (list.frontElsewhere) {
149
+ $('setupLead').textContent = `Remote Desktop runs from ${list.frontLabel}. Open this page on ${list.frontLabel} to set up other machines.`;
150
+ for (const row of list.machines || []) show(row);
151
+ $('setup').hidden = false;
152
+ return true;
153
+ }
154
+ const machines = list.machines || [];
155
+ $('setupLead').textContent = 'This page rechecks by itself after each step. A machine is ready when the check here says so.';
156
+ for (const row of machines) show(row);
157
+ $('setup').hidden = machines.length === 0;
158
+ // These rows carry the same reasons with the steps to fix them.
159
+ if (machines.length) $('machineNotes')?.replaceChildren();
160
+ return machines.length > 0;
161
+ }
162
+
163
+ return { refresh, stop: stopPolling };
164
+ }
@@ -34,3 +34,9 @@ body.desktop-live #localCursor{display:block}
34
34
  .machine-notes{margin:.8rem 0 0;padding-left:1.1rem;font-size:.95rem;line-height:1.4}
35
35
  .machine-notes li{margin:.35rem 0}
36
36
  .machine-notes:empty{display:none}
37
+ .setup-rows { list-style: none; margin: 0; padding: 0; }
38
+ .setup-rows li { border-top: 1px solid currentColor; padding: 12px 0; }
39
+ .setup-rows p { margin: 6px 0; overflow-wrap: anywhere; }
40
+ .setup-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
41
+ .setup-note:empty { display: none; }
42
+ .setup-quiet { background: none; border: none; color: inherit; opacity: 0.7; text-decoration: underline; }
@@ -20,6 +20,11 @@
20
20
  <button id="requestButton">Open selected machine</button>
21
21
  <ul id="machineNotes" class="machine-notes" aria-label="Machines that are not ready"></ul>
22
22
  </section>
23
+ <section id="setup" hidden>
24
+ <h2>Machines</h2>
25
+ <p id="setupLead"></p>
26
+ <ul id="setupRows" class="setup-rows" aria-label="Each machine and its next step"></ul>
27
+ </section>
23
28
  <section id="control" hidden>
24
29
  <div class="desktop-bar"><strong id="machineName"></strong><span id="liveStatus" role="status"></span><button id="stopButton" class="danger">Stop</button></div>
25
30
  <div id="surface" aria-label="Remote desktop touch surface">
@@ -600,12 +600,15 @@ async function api(path, method = 'GET', body, signal) {
600
600
  if (!response.ok) {
601
601
  const error = new Error(result.error || `Server answered ${response.status}`);
602
602
  error.httpStatus = response.status;
603
+ if (result.step) error.step = result.step;
603
604
  throw error;
604
605
  }
605
606
  return result;
606
607
  }
607
608
 
608
609
  function requirePinAgain() {
610
+ desktopSetup?.stop();
611
+ if ($('setup')) $('setup').hidden = true;
609
612
  token = '';
610
613
  operatorSession = '';
611
614
  $('retryButton').hidden = true;
@@ -614,7 +617,40 @@ function requirePinAgain() {
614
617
  status('Your dashboard session ended. Enter your PIN again.');
615
618
  }
616
619
 
617
- async function loadTargetsAndMaybeOpen() {
620
+ let desktopSetup = null;
621
+ async function refreshSetup() {
622
+ try {
623
+ if (!desktopSetup) {
624
+ const { createDesktopSetup } = await import('./desktop-setup.js');
625
+ desktopSetup = createDesktopSetup({
626
+ api, $,
627
+ onPinLost: () => requirePinAgain(),
628
+ onReady: async row => {
629
+ status(`${row.label} is ready.`);
630
+ await loadTargetsAndMaybeOpen({ open: false });
631
+ },
632
+ });
633
+ }
634
+ await desktopSetup.refresh();
635
+ } catch {
636
+ // @silent-fallback-ok — setup is an aid; the picker above it still works.
637
+ }
638
+ }
639
+
640
+ // Setup exists even while this machine's own desktop is off, which is exactly
641
+ // when /desktop/targets answers 503.
642
+ async function loadDesktopPage(options) {
643
+ try { await loadTargetsAndMaybeOpen(options); }
644
+ catch (error) {
645
+ if (error.httpStatus !== 503) throw error;
646
+ $('unlock').hidden = true;
647
+ $('request').hidden = true;
648
+ status('Remote Desktop is off here. Set it up below.');
649
+ }
650
+ await refreshSetup();
651
+ }
652
+
653
+ async function loadTargetsAndMaybeOpen({ open = true } = {}) {
618
654
  const targets = await api('/desktop/targets');
619
655
  const machines = targets.machines || [];
620
656
  $('machine').replaceChildren();
@@ -664,7 +700,7 @@ async function loadTargetsAndMaybeOpen() {
664
700
  return;
665
701
  }
666
702
  $('retryButton').hidden = true;
667
- if (hasPreferredMachine || (machines.length === 1 && ready.length === 1)) {
703
+ if (open && (hasPreferredMachine || (machines.length === 1 && ready.length === 1))) {
668
704
  if (!hasPreferredMachine) $('machine').value = ready[0].value;
669
705
  status(`Opening ${$('machine').selectedOptions[0].textContent}…`);
670
706
  await requestDesktop();
@@ -689,7 +725,7 @@ $('unlockButton').addEventListener('click', async () => {
689
725
  token = result.token;
690
726
  operatorSession = result.operatorSessionToken;
691
727
  $('pin').value = '';
692
- await loadTargetsAndMaybeOpen();
728
+ await loadDesktopPage();
693
729
  } catch (error) {
694
730
  if (/dashboard operator session|dashboard PIN session/i.test(error.message || '')) requirePinAgain();
695
731
  else status(error.message || 'Could not unlock.');
@@ -699,7 +735,7 @@ $('unlockButton').addEventListener('click', async () => {
699
735
 
700
736
  $('retryButton').addEventListener('click', async () => {
701
737
  $('retryButton').disabled = true;
702
- try { await loadTargetsAndMaybeOpen(); }
738
+ try { await loadDesktopPage(); }
703
739
  catch (error) {
704
740
  if (/dashboard operator session|dashboard PIN session/i.test(error.message || '')) requirePinAgain();
705
741
  else status(error.message || 'Could not check this machine.');
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"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"}
@@ -3873,6 +3873,9 @@ export async function startServer(options) {
3873
3873
  // i.e. this machine is trivially the owner — a strict single-process limiter.
3874
3874
  // The pool block later calls configureBounds AGAIN to add the resolver.
3875
3875
  notificationBatcher.configureBounds({ stateDir: config.stateDir });
3876
+ // Mobile push hub-notice hook (docs/specs/mobile-push.md §2.3); reads the live adapter.
3877
+ let _hubNoticeAdapter = null;
3878
+ const _hubNoticeHook = (t) => _hubNoticeAdapter?.onHubPost?.(t);
3876
3879
  // State reference — set once StateManager is created, used by notify()
3877
3880
  let _notifyState = null;
3878
3881
  /**
@@ -3895,6 +3898,13 @@ export async function startServer(options) {
3895
3898
  return;
3896
3899
  }
3897
3900
  }
3901
+ // Mobile push (docs/specs/mobile-push.md §2.3): a hub notice the filter admitted.
3902
+ if ((!topicId || topicId === hubTopicId) && hubTopicId) {
3903
+ try {
3904
+ _hubNoticeHook?.({ kind: 'notice', dedupeKey: `notice:${category}`, priority: tier === 'IMMEDIATE' ? 'URGENT' : undefined });
3905
+ }
3906
+ catch { /* @silent-fallback-ok — push is best-effort and never affects the notice */ }
3907
+ }
3898
3908
  // Telegram: via notification batcher
3899
3909
  const resolvedTopicId = topicId ?? hubTopicId;
3900
3910
  if (resolvedTopicId) {
@@ -7804,6 +7814,7 @@ export async function startServer(options) {
7804
7814
  systemTopics: systemTopicsHooks(state),
7805
7815
  }, config.stateDir);
7806
7816
  armHolderForwardWait(telegram);
7817
+ _hubNoticeAdapter = telegram;
7807
7818
  console.log(pc.green(` Telegram send-only mode (${isStandbyTelegram ? 'standby' : lifelineOwnsPolling ? 'lifeline owns polling (lease detected)' : 'lifeline owns polling'})`));
7808
7819
  // Send-only still owns the attention store: run its hourly lifecycle
7809
7820
  // pass here too (start() is never called on this path). Idempotent.
@@ -7910,6 +7921,7 @@ export async function startServer(options) {
7910
7921
  systemTopics: systemTopicsHooks(state),
7911
7922
  }, config.stateDir);
7912
7923
  armHolderForwardWait(telegram);
7924
+ _hubNoticeAdapter = telegram;
7913
7925
  telegram.intelligence = sharedIntelligence ?? null;
7914
7926
  await telegram.start();
7915
7927
  console.log(pc.green(` Telegram connected (stall alerts: ${sharedIntelligence ? 'LLM-gated' : 'timer-only'})`));