@integrity-labs/agt-cli 0.28.679 → 0.28.681

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.
@@ -17,7 +17,7 @@ import {
17
17
  rotateDailySession,
18
18
  sessionFileExists,
19
19
  todayLocalIso
20
- } from "./chunk-GDT7JHV6.js";
20
+ } from "./chunk-OOFJUWMT.js";
21
21
  import {
22
22
  reapOrphanChannelMcps
23
23
  } from "./chunk-XWVM4KPK.js";
@@ -4531,4 +4531,4 @@ export {
4531
4531
  stopAllSessionsAndWait,
4532
4532
  getProjectDir
4533
4533
  };
4534
- //# sourceMappingURL=chunk-HLJKOJVJ.js.map
4534
+ //# sourceMappingURL=chunk-ZKNKHAHX.js.map
@@ -100,7 +100,7 @@ async function spawnPairSession(session) {
100
100
  return { ok: true };
101
101
  } catch {
102
102
  }
103
- const { resolveClaudeBinary } = await import("./persistent-session-GQZQWMJU.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-OQ7MFVEH.js");
104
104
  const claudeBin = resolveClaudeBinary();
105
105
  const pairEnv = {
106
106
  ...process.env,
@@ -373,4 +373,4 @@ export {
373
373
  startClaudePair,
374
374
  submitClaudePairCode
375
375
  };
376
- //# sourceMappingURL=claude-pair-runtime-5UDCBIB7.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-HPCXQDVY.js.map
@@ -55,7 +55,7 @@ import {
55
55
  setConfigHash,
56
56
  setSecretFileTmpfsBacking,
57
57
  tripClass
58
- } from "../chunk-CLNFPTVG.js";
58
+ } from "../chunk-Q44TIWZN.js";
59
59
  import {
60
60
  getProjectDir as getProjectDir2,
61
61
  getReadyTasks,
@@ -113,7 +113,7 @@ import {
113
113
  takeZombieDetection,
114
114
  toOpencodeModel,
115
115
  writeEgressAllowlist
116
- } from "../chunk-HLJKOJVJ.js";
116
+ } from "../chunk-ZKNKHAHX.js";
117
117
  import {
118
118
  ACCOUNT_ENFORCEMENT_MARKER_FILENAME,
119
119
  AnchorSessionClient,
@@ -194,7 +194,7 @@ import {
194
194
  subagentActivityAgeSeconds,
195
195
  sumTranscriptUsageInWindow,
196
196
  transcriptActivityAgeSeconds
197
- } from "../chunk-GDT7JHV6.js";
197
+ } from "../chunk-OOFJUWMT.js";
198
198
  import {
199
199
  reapOrphanChannelMcps
200
200
  } from "../chunk-XWVM4KPK.js";
@@ -11712,7 +11712,7 @@ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
11712
11712
  var dayRolloverInboundHold = /* @__PURE__ */ new Map();
11713
11713
  var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
11714
11714
  async function channelInboundActivityAgeSecondsFor(codeName) {
11715
- const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-QKKOHDHF.js");
11715
+ const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-MDL53OT2.js");
11716
11716
  const newest = newestPendingInboundActivityMtimeMs(dirname10(paneLogPath(codeName)));
11717
11717
  if (newest === null) return null;
11718
11718
  return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
@@ -12360,7 +12360,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
12360
12360
  var lastVersionCheckAt = 0;
12361
12361
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
12362
12362
  var lastResponsivenessProbeAt = 0;
12363
- var agtCliVersion = true ? "0.28.679" : "dev";
12363
+ var agtCliVersion = true ? "0.28.681" : "dev";
12364
12364
  function resolveBrewPath(execFileSync3) {
12365
12365
  try {
12366
12366
  const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -13821,7 +13821,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
13821
13821
  if (codeNames.length === 0) return;
13822
13822
  void (async () => {
13823
13823
  try {
13824
- const { collectDiagnostics } = await import("../persistent-session-GQZQWMJU.js");
13824
+ const { collectDiagnostics } = await import("../persistent-session-OQ7MFVEH.js");
13825
13825
  await api.post("/host/heartbeat", {
13826
13826
  host_id: hostId,
13827
13827
  agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor)
@@ -13938,7 +13938,7 @@ async function pollCycleInner() {
13938
13938
  }
13939
13939
  try {
13940
13940
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
13941
- const { collectDiagnostics } = await import("../persistent-session-GQZQWMJU.js");
13941
+ const { collectDiagnostics } = await import("../persistent-session-OQ7MFVEH.js");
13942
13942
  const diagCodeNames = [...agentState.persistentSessionAgents];
13943
13943
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor) : void 0;
13944
13944
  let tailscaleHostname;
@@ -14090,7 +14090,7 @@ async function pollCycleInner() {
14090
14090
  collectPanelessActivityProbes,
14091
14091
  getResponsivenessIntervalMs,
14092
14092
  occupancyQualificationClassifications
14093
- } = await import("../responsiveness-probe-QKKOHDHF.js");
14093
+ } = await import("../responsiveness-probe-MDL53OT2.js");
14094
14094
  const probeIntervalMs = getResponsivenessIntervalMs();
14095
14095
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
14096
14096
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -14200,7 +14200,7 @@ async function pollCycleInner() {
14200
14200
  collectResponsivenessProbes,
14201
14201
  livePendingInboundOldestAgeSeconds,
14202
14202
  parkPendingInbound
14203
- } = await import("../responsiveness-probe-QKKOHDHF.js");
14203
+ } = await import("../responsiveness-probe-MDL53OT2.js");
14204
14204
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
14205
14205
  const wedgeNow = /* @__PURE__ */ new Date();
14206
14206
  const liveAgents = agentState.persistentSessionAgents;
@@ -14356,7 +14356,7 @@ async function pollCycleInner() {
14356
14356
  }
14357
14357
  try {
14358
14358
  const { scrapeMcpFailedBannerCount } = await import("../pane-mcp-banner-scraper-JA437JIB.js");
14359
- const { probeSessionAuth } = await import("../session-auth-dead-CUEBDRZU.js");
14359
+ const { probeSessionAuth } = await import("../session-auth-dead-4OJ2XLH4.js");
14360
14360
  const observations = [];
14361
14361
  const pendingCacheCommits = [];
14362
14362
  const modelApiErrorReportingOn = hostFlagStore().getBoolean("model-api-error-reporting");
@@ -18117,7 +18117,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
18117
18117
  void api.post("/host/restart-ack", { host_id: hostId, agent_id: agentId, restart_requested_at: requestedAt }).catch((err) => log(`[restart-lane] ack failed for '${codeName}': ${err.message}`));
18118
18118
  void (async () => {
18119
18119
  try {
18120
- const { collectDiagnostics } = await import("../persistent-session-GQZQWMJU.js");
18120
+ const { collectDiagnostics } = await import("../persistent-session-OQ7MFVEH.js");
18121
18121
  await api.post("/host/heartbeat", {
18122
18122
  host_id: hostId,
18123
18123
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor)
@@ -18168,7 +18168,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
18168
18168
  }
18169
18169
  try {
18170
18170
  const hostId = await getHostId();
18171
- const { collectDiagnostics } = await import("../persistent-session-GQZQWMJU.js");
18171
+ const { collectDiagnostics } = await import("../persistent-session-OQ7MFVEH.js");
18172
18172
  await api.post("/host/heartbeat", {
18173
18173
  host_id: hostId,
18174
18174
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor)
@@ -18800,7 +18800,7 @@ async function processClaudePairSessions(agents) {
18800
18800
  killPairSession,
18801
18801
  pairTmuxSession,
18802
18802
  finalizeClaudePairOnboarding
18803
- } = await import("../claude-pair-runtime-5UDCBIB7.js");
18803
+ } = await import("../claude-pair-runtime-HPCXQDVY.js");
18804
18804
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
18805
18805
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
18806
18806
  const killed = await killPairSession(pairTmuxSession(pairId));
@@ -32291,6 +32291,15 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
32291
32291
  // long note on the window-capture click handler for why this is a mode and
32292
32292
  // not just always-on.
32293
32293
  var editMode = false;
32294
+ // ENG-9383: the ONE gate every edit-entry path asks. It exists because the
32295
+ // last time a path was added, the old ones did not come with it: ENG-8477
32296
+ // introduced editMode for the deep-probe handlers and left the ENG-6821
32297
+ // direct click/hover on an arming-only check, so text stayed editable with
32298
+ // the toggle off and the button gated one of two paths. A funnel is the fix
32299
+ // for that class of bug; adding the term twice is only the fix for this
32300
+ // instance of it. A fifth handler cannot forget the mode.
32301
+ function canEdit(){ return editEnabled && editMode && !editing; }
32302
+ var hoverCued = []; // ENG-9383: elements currently wearing the mouseover cue
32294
32303
 
32295
32304
  // Element-child indices from <body> down to el. Counts ELEMENT children only
32296
32305
  // (children, not childNodes), matching how the server walks source_html; our
@@ -32484,14 +32493,48 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
32484
32493
  // Hover affordance (only when armed and not mid-edit). Highlight leaves AND
32485
32494
  // inline-only containers (their bare text is per-node editable, ENG-6856).
32486
32495
  document.addEventListener('mouseover', function(e){
32487
- if(!editEnabled||editing) return; var el=e.target;
32488
- if(editable(el)||inlineOnlyEditable(el)){ el.style.cursor='text'; el.style.outline=el.style.outline||'1px dashed rgba(110,231,183,.6)'; el.__alHover=1; }
32496
+ if(!canEdit()) return; var el=e.target;
32497
+ if(editable(el)||inlineOnlyEditable(el)){
32498
+ // ENG-9383: remember what the author's cursor was before we overwrite it.
32499
+ // Blanking it on the way out would delete an inline cursor the artefact
32500
+ // set itself; '' is a legitimate saved value meaning "there was none".
32501
+ if(el.__alCur===undefined) el.__alCur = el.style.cursor || '';
32502
+ el.style.cursor='text'; el.style.outline=el.style.outline||'1px dashed rgba(110,231,183,.6)'; el.__alHover=1; hoverCued.push(el);
32503
+ }
32489
32504
  });
32490
32505
  document.addEventListener('mouseout', function(e){
32491
- var el=e.target; if(el&&el.__alHover&&el!==editing){ el.style.outline=''; el.__alHover=0; }
32506
+ var el=e.target; if(el&&el.__alHover&&el!==editing){ el.style.outline=''; restoreCursor(el); el.__alHover=0; dropHoverCue(el); }
32492
32507
  });
32508
+ // ENG-9383 (CodeRabbit on #4956): the cue is an outline AND an I-beam cursor.
32509
+ // Clearing only the outline leaves the text still saying "you can type here"
32510
+ // on a page that will now refuse the click - the same misdirection this ticket
32511
+ // is about, one property over.
32512
+ function restoreCursor(el){
32513
+ if(el.__alCur!==undefined){ try{ el.style.cursor=el.__alCur; }catch(e){} el.__alCur=undefined; }
32514
+ }
32515
+ // Keep hoverCued bounded. Without this it grows once per hovered element for
32516
+ // the life of the page and pins every one of them against GC - a list that
32517
+ // only ever empties when the viewer toggles the mode off is a leak on any page
32518
+ // nobody toggles.
32519
+ function dropHoverCue(el){
32520
+ var i=hoverCued.indexOf(el); if(i!==-1) hoverCued.splice(i,1);
32521
+ }
32522
+ // ENG-9383: drop every outline the mouseover cue left behind, without waiting
32523
+ // for a mouseout that may never come - the mode can go off while the pointer is
32524
+ // parked on the text, and then the artefact wears a dashed "editable" outline
32525
+ // on a page where you no longer can. Tracked in a list rather than queried back
32526
+ // out of the DOM: more than one element can carry the cue if the pointer moved
32527
+ // between mouseover and mouseout, and the bridge should not depend on a
32528
+ // selector matching an inline style it wrote.
32529
+ function clearHoverCues(){
32530
+ for(var i=0;i<hoverCued.length;i++){
32531
+ var el=hoverCued[i];
32532
+ if(el && el.__alHover && el!==editing){ try{ el.style.outline=''; }catch(e){} restoreCursor(el); el.__alHover=0; }
32533
+ }
32534
+ hoverCued.length=0;
32535
+ }
32493
32536
  document.addEventListener('click', function(e){
32494
- if(!editEnabled||editing) return;
32537
+ if(!canEdit()) return;
32495
32538
  var sel=document.getSelection(); if(sel && String(sel).trim()) return; // a selection => comment flow
32496
32539
  var el=e.target;
32497
32540
  if(editable(el)){ e.preventDefault(); e.stopPropagation(); startEdit(el); return; }
@@ -32535,7 +32578,7 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
32535
32578
  // Deliberately general: nothing here knows about .clickzone or any class name.
32536
32579
  // It fixes any artefact that covers its own content.
32537
32580
  window.addEventListener('click', function(e){
32538
- if(!editEnabled || !editMode || editing) return;
32581
+ if(!canEdit()) return;
32539
32582
  var sel=document.getSelection(); if(sel && String(sel).trim()) return; // selection => comment flow
32540
32583
  var t=e.target;
32541
32584
  // Our own toolbar (Save/Cancel) must keep its clicks.
@@ -32593,7 +32636,7 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
32593
32636
  hoverEl=null;
32594
32637
  }
32595
32638
  document.addEventListener('mousemove', function(e){
32596
- if(!editEnabled || !editMode || editing){ clearDeepHover(); return; }
32639
+ if(!canEdit()){ clearDeepHover(); return; }
32597
32640
  var t=e.target;
32598
32641
  if(editable(t)||inlineOnlyEditable(t)){ clearDeepHover(); return; }
32599
32642
  var now=Date.now(); if(now-hoverProbeAt<80) return; hoverProbeAt=now;
@@ -32693,12 +32736,17 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
32693
32736
  var d=e.data; if(!d || d['${MARKUP_CONTROL_MARKER}']!==true) return;
32694
32737
  if(d.type==='enable-edit'){ editEnabled=true; }
32695
32738
  else if(d.type==='enable-comment'){ commentEnabled=true; }
32696
- // ENG-8477: the viewer toggled Edit text in the shell. Turning it OFF must
32739
+ // ENG-8477: the viewer toggled Edit mode in the shell. Turning it OFF must
32697
32740
  // also close anything open and drop the hover cue, or the artefact is left
32698
32741
  // wearing our outlines with no way to clear them.
32742
+ // ENG-9383: clearDeepHover() only knows the deep-probe path's outline. The
32743
+ // ENG-6821 mouseover path marks its own element with __alHover and relies on
32744
+ // mouseout to undo it - which never fires if the pointer is still sitting on
32745
+ // the text when the mode goes off, leaving a dashed "you can edit this"
32746
+ // outline on a page where you now cannot. Clear both.
32699
32747
  else if(d.type==='set-edit-mode'){
32700
32748
  editMode = !!d.on;
32701
- if(!editMode){ if(editing) endEdit(false); clearDeepHover(); }
32749
+ if(!editMode){ if(editing) endEdit(false); clearDeepHover(); clearHoverCues(); }
32702
32750
  }
32703
32751
  else if(d.type==='edit-result'){
32704
32752
  if(d.ok){ /* republish hot-swaps the iframe; nothing to do */ }
@@ -35909,14 +35957,15 @@ var FLAG_REGISTRY = [
35909
35957
  // hand-written process.env gate) — same posture as memory-extraction /
35910
35958
  // tool-call-audit above. Gives a per-host canary before the DB flag exists.
35911
35959
  envVar: "AGT_SECRET_FILES_TMPFS_ENABLED",
35912
- // Deliberately-unreachable placeholder until this ships: no published CLI
35913
- // carries the manager reader + core writer yet, so reach must report "no
35914
- // host honors" rather than the `honors`-for-everyone that omitting `since`
35915
- // produces. MOVE THIS PIN to the actual auto-published agt-cli version at
35916
- // merge (auto-publish patch-bumps from main; verify against the tarball, the
35917
- // ENG-8575/ENG-9350 lesson) the marker is `setSecretFileTmpfsBacking` in
35918
- // package/dist/lib/manager-worker.js.
35919
- since: "99.0.0"
35960
+ // The real published build that carries the manager reader + core writer,
35961
+ // replacing the deliberately-unreachable `99.0.0` this flag shipped with.
35962
+ // Verified against the tarball (`npm pack @integrity-labs/agt-cli@0.28.678`):
35963
+ // `setSecretFileTmpfsBacking` is present in package/dist/lib/manager-worker.js
35964
+ // and the `secret-files-tmpfs` key ships in the bundle. Auto-publish patch-
35965
+ // bumps from main, so if a CLI-touching PR landed between the ENG-9348 merge
35966
+ // and this one the real cut is higher than 0.28.678 and reach under-reports;
35967
+ // re-verify before flipping the flag on for a canary (ENG-8575/ENG-9350).
35968
+ since: "0.28.678"
35920
35969
  },
35921
35970
  {
35922
35971
  key: "memory-file-tombstones",
@@ -36700,6 +36749,17 @@ var FLAG_REGISTRY = [
36700
36749
  // control that does nothing, which is the ENG-8303 class exactly.
36701
36750
  // enforce arms automated downtime on a customer's production host.
36702
36751
  sensitive: true
36752
+ },
36753
+ {
36754
+ key: "live-meeting-advisor",
36755
+ description: "Live meeting advising in Ninja Notes (ENG-9381). When ON for an org, a person recording a meeting on the Mac may arm an agent to watch it in flight: audio chunks stream to POST /notes/live/:id/chunks, a server-side Haiku vet decides moment by moment whether to escalate, and escalations reach the agent in a server-minted chat thread. Gates the CAPABILITY, not a surface: the refusal is in startLiveAdvisorSession, so a client that ignores the flag still cannot open a session, and GET /notes/destinations reports the same answer as advisor_enabled so the app can skip the arming modal entirely. Boolean gate; ships dark. OFF NEVER COSTS THE RECORDING. An unentitled org \u2014 or a flag read that fails \u2014 costs the advisor only; the microphone still starts and the note is still transcribed and delivered. That direction is deliberate: the user pressed Record and a recording is what they are owed, while arming on a failed read would spend money per minute on a session nobody confirmed. Deliberately NO envVar. This is an org-scoped gate, and an envVar is highest-precedence per ADR-0022 \u2014 a literal in sst.config.ts would pin every stage and make the admin control do nothing, the ENG-8303 class exactly.",
36756
+ flagType: "boolean",
36757
+ defaultValue: false,
36758
+ // Turning it ON arms a per-minute-metered capability AND starts streaming
36759
+ // meeting content to a server-side vet. Both halves are the deliberate,
36760
+ // audited decision ADR-0022 §4 reserves confirmation for — same treatment as
36761
+ // agent-hours-billing-enabled.
36762
+ sensitive: true
36703
36763
  }
36704
36764
  ];
36705
36765
  var REGISTRY_BY_KEY = new Map(FLAG_REGISTRY.map((definition) => [definition.key, definition]));
package/dist/mcp/index.js CHANGED
@@ -39691,6 +39691,15 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
39691
39691
  // long note on the window-capture click handler for why this is a mode and
39692
39692
  // not just always-on.
39693
39693
  var editMode = false;
39694
+ // ENG-9383: the ONE gate every edit-entry path asks. It exists because the
39695
+ // last time a path was added, the old ones did not come with it: ENG-8477
39696
+ // introduced editMode for the deep-probe handlers and left the ENG-6821
39697
+ // direct click/hover on an arming-only check, so text stayed editable with
39698
+ // the toggle off and the button gated one of two paths. A funnel is the fix
39699
+ // for that class of bug; adding the term twice is only the fix for this
39700
+ // instance of it. A fifth handler cannot forget the mode.
39701
+ function canEdit(){ return editEnabled && editMode && !editing; }
39702
+ var hoverCued = []; // ENG-9383: elements currently wearing the mouseover cue
39694
39703
 
39695
39704
  // Element-child indices from <body> down to el. Counts ELEMENT children only
39696
39705
  // (children, not childNodes), matching how the server walks source_html; our
@@ -39884,14 +39893,48 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
39884
39893
  // Hover affordance (only when armed and not mid-edit). Highlight leaves AND
39885
39894
  // inline-only containers (their bare text is per-node editable, ENG-6856).
39886
39895
  document.addEventListener('mouseover', function(e){
39887
- if(!editEnabled||editing) return; var el=e.target;
39888
- if(editable(el)||inlineOnlyEditable(el)){ el.style.cursor='text'; el.style.outline=el.style.outline||'1px dashed rgba(110,231,183,.6)'; el.__alHover=1; }
39896
+ if(!canEdit()) return; var el=e.target;
39897
+ if(editable(el)||inlineOnlyEditable(el)){
39898
+ // ENG-9383: remember what the author's cursor was before we overwrite it.
39899
+ // Blanking it on the way out would delete an inline cursor the artefact
39900
+ // set itself; '' is a legitimate saved value meaning "there was none".
39901
+ if(el.__alCur===undefined) el.__alCur = el.style.cursor || '';
39902
+ el.style.cursor='text'; el.style.outline=el.style.outline||'1px dashed rgba(110,231,183,.6)'; el.__alHover=1; hoverCued.push(el);
39903
+ }
39889
39904
  });
39890
39905
  document.addEventListener('mouseout', function(e){
39891
- var el=e.target; if(el&&el.__alHover&&el!==editing){ el.style.outline=''; el.__alHover=0; }
39906
+ var el=e.target; if(el&&el.__alHover&&el!==editing){ el.style.outline=''; restoreCursor(el); el.__alHover=0; dropHoverCue(el); }
39892
39907
  });
39908
+ // ENG-9383 (CodeRabbit on #4956): the cue is an outline AND an I-beam cursor.
39909
+ // Clearing only the outline leaves the text still saying "you can type here"
39910
+ // on a page that will now refuse the click - the same misdirection this ticket
39911
+ // is about, one property over.
39912
+ function restoreCursor(el){
39913
+ if(el.__alCur!==undefined){ try{ el.style.cursor=el.__alCur; }catch(e){} el.__alCur=undefined; }
39914
+ }
39915
+ // Keep hoverCued bounded. Without this it grows once per hovered element for
39916
+ // the life of the page and pins every one of them against GC - a list that
39917
+ // only ever empties when the viewer toggles the mode off is a leak on any page
39918
+ // nobody toggles.
39919
+ function dropHoverCue(el){
39920
+ var i=hoverCued.indexOf(el); if(i!==-1) hoverCued.splice(i,1);
39921
+ }
39922
+ // ENG-9383: drop every outline the mouseover cue left behind, without waiting
39923
+ // for a mouseout that may never come - the mode can go off while the pointer is
39924
+ // parked on the text, and then the artefact wears a dashed "editable" outline
39925
+ // on a page where you no longer can. Tracked in a list rather than queried back
39926
+ // out of the DOM: more than one element can carry the cue if the pointer moved
39927
+ // between mouseover and mouseout, and the bridge should not depend on a
39928
+ // selector matching an inline style it wrote.
39929
+ function clearHoverCues(){
39930
+ for(var i=0;i<hoverCued.length;i++){
39931
+ var el=hoverCued[i];
39932
+ if(el && el.__alHover && el!==editing){ try{ el.style.outline=''; }catch(e){} restoreCursor(el); el.__alHover=0; }
39933
+ }
39934
+ hoverCued.length=0;
39935
+ }
39893
39936
  document.addEventListener('click', function(e){
39894
- if(!editEnabled||editing) return;
39937
+ if(!canEdit()) return;
39895
39938
  var sel=document.getSelection(); if(sel && String(sel).trim()) return; // a selection => comment flow
39896
39939
  var el=e.target;
39897
39940
  if(editable(el)){ e.preventDefault(); e.stopPropagation(); startEdit(el); return; }
@@ -39935,7 +39978,7 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
39935
39978
  // Deliberately general: nothing here knows about .clickzone or any class name.
39936
39979
  // It fixes any artefact that covers its own content.
39937
39980
  window.addEventListener('click', function(e){
39938
- if(!editEnabled || !editMode || editing) return;
39981
+ if(!canEdit()) return;
39939
39982
  var sel=document.getSelection(); if(sel && String(sel).trim()) return; // selection => comment flow
39940
39983
  var t=e.target;
39941
39984
  // Our own toolbar (Save/Cancel) must keep its clicks.
@@ -39993,7 +40036,7 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
39993
40036
  hoverEl=null;
39994
40037
  }
39995
40038
  document.addEventListener('mousemove', function(e){
39996
- if(!editEnabled || !editMode || editing){ clearDeepHover(); return; }
40039
+ if(!canEdit()){ clearDeepHover(); return; }
39997
40040
  var t=e.target;
39998
40041
  if(editable(t)||inlineOnlyEditable(t)){ clearDeepHover(); return; }
39999
40042
  var now=Date.now(); if(now-hoverProbeAt<80) return; hoverProbeAt=now;
@@ -40093,12 +40136,17 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
40093
40136
  var d=e.data; if(!d || d['${MARKUP_CONTROL_MARKER}']!==true) return;
40094
40137
  if(d.type==='enable-edit'){ editEnabled=true; }
40095
40138
  else if(d.type==='enable-comment'){ commentEnabled=true; }
40096
- // ENG-8477: the viewer toggled Edit text in the shell. Turning it OFF must
40139
+ // ENG-8477: the viewer toggled Edit mode in the shell. Turning it OFF must
40097
40140
  // also close anything open and drop the hover cue, or the artefact is left
40098
40141
  // wearing our outlines with no way to clear them.
40142
+ // ENG-9383: clearDeepHover() only knows the deep-probe path's outline. The
40143
+ // ENG-6821 mouseover path marks its own element with __alHover and relies on
40144
+ // mouseout to undo it - which never fires if the pointer is still sitting on
40145
+ // the text when the mode goes off, leaving a dashed "you can edit this"
40146
+ // outline on a page where you now cannot. Clear both.
40099
40147
  else if(d.type==='set-edit-mode'){
40100
40148
  editMode = !!d.on;
40101
- if(!editMode){ if(editing) endEdit(false); clearDeepHover(); }
40149
+ if(!editMode){ if(editing) endEdit(false); clearDeepHover(); clearHoverCues(); }
40102
40150
  }
40103
40151
  else if(d.type==='edit-result'){
40104
40152
  if(d.ok){ /* republish hot-swaps the iframe; nothing to do */ }
@@ -42860,14 +42908,15 @@ var FLAG_REGISTRY = [
42860
42908
  // hand-written process.env gate) — same posture as memory-extraction /
42861
42909
  // tool-call-audit above. Gives a per-host canary before the DB flag exists.
42862
42910
  envVar: "AGT_SECRET_FILES_TMPFS_ENABLED",
42863
- // Deliberately-unreachable placeholder until this ships: no published CLI
42864
- // carries the manager reader + core writer yet, so reach must report "no
42865
- // host honors" rather than the `honors`-for-everyone that omitting `since`
42866
- // produces. MOVE THIS PIN to the actual auto-published agt-cli version at
42867
- // merge (auto-publish patch-bumps from main; verify against the tarball, the
42868
- // ENG-8575/ENG-9350 lesson) the marker is `setSecretFileTmpfsBacking` in
42869
- // package/dist/lib/manager-worker.js.
42870
- since: "99.0.0"
42911
+ // The real published build that carries the manager reader + core writer,
42912
+ // replacing the deliberately-unreachable `99.0.0` this flag shipped with.
42913
+ // Verified against the tarball (`npm pack @integrity-labs/agt-cli@0.28.678`):
42914
+ // `setSecretFileTmpfsBacking` is present in package/dist/lib/manager-worker.js
42915
+ // and the `secret-files-tmpfs` key ships in the bundle. Auto-publish patch-
42916
+ // bumps from main, so if a CLI-touching PR landed between the ENG-9348 merge
42917
+ // and this one the real cut is higher than 0.28.678 and reach under-reports;
42918
+ // re-verify before flipping the flag on for a canary (ENG-8575/ENG-9350).
42919
+ since: "0.28.678"
42871
42920
  },
42872
42921
  {
42873
42922
  key: "memory-file-tombstones",
@@ -43651,6 +43700,17 @@ var FLAG_REGISTRY = [
43651
43700
  // control that does nothing, which is the ENG-8303 class exactly.
43652
43701
  // enforce arms automated downtime on a customer's production host.
43653
43702
  sensitive: true
43703
+ },
43704
+ {
43705
+ key: "live-meeting-advisor",
43706
+ description: "Live meeting advising in Ninja Notes (ENG-9381). When ON for an org, a person recording a meeting on the Mac may arm an agent to watch it in flight: audio chunks stream to POST /notes/live/:id/chunks, a server-side Haiku vet decides moment by moment whether to escalate, and escalations reach the agent in a server-minted chat thread. Gates the CAPABILITY, not a surface: the refusal is in startLiveAdvisorSession, so a client that ignores the flag still cannot open a session, and GET /notes/destinations reports the same answer as advisor_enabled so the app can skip the arming modal entirely. Boolean gate; ships dark. OFF NEVER COSTS THE RECORDING. An unentitled org \u2014 or a flag read that fails \u2014 costs the advisor only; the microphone still starts and the note is still transcribed and delivered. That direction is deliberate: the user pressed Record and a recording is what they are owed, while arming on a failed read would spend money per minute on a session nobody confirmed. Deliberately NO envVar. This is an org-scoped gate, and an envVar is highest-precedence per ADR-0022 \u2014 a literal in sst.config.ts would pin every stage and make the admin control do nothing, the ENG-8303 class exactly.",
43707
+ flagType: "boolean",
43708
+ defaultValue: false,
43709
+ // Turning it ON arms a per-minute-metered capability AND starts streaming
43710
+ // meeting content to a server-side vet. Both halves are the deliberate,
43711
+ // audited decision ADR-0022 §4 reserves confirmation for — same treatment as
43712
+ // agent-hours-billing-enabled.
43713
+ sensitive: true
43654
43714
  }
43655
43715
  ];
43656
43716
  var REGISTRY_BY_KEY = new Map(FLAG_REGISTRY.map((definition) => [definition.key, definition]));
@@ -38499,6 +38499,15 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
38499
38499
  // long note on the window-capture click handler for why this is a mode and
38500
38500
  // not just always-on.
38501
38501
  var editMode = false;
38502
+ // ENG-9383: the ONE gate every edit-entry path asks. It exists because the
38503
+ // last time a path was added, the old ones did not come with it: ENG-8477
38504
+ // introduced editMode for the deep-probe handlers and left the ENG-6821
38505
+ // direct click/hover on an arming-only check, so text stayed editable with
38506
+ // the toggle off and the button gated one of two paths. A funnel is the fix
38507
+ // for that class of bug; adding the term twice is only the fix for this
38508
+ // instance of it. A fifth handler cannot forget the mode.
38509
+ function canEdit(){ return editEnabled && editMode && !editing; }
38510
+ var hoverCued = []; // ENG-9383: elements currently wearing the mouseover cue
38502
38511
 
38503
38512
  // Element-child indices from <body> down to el. Counts ELEMENT children only
38504
38513
  // (children, not childNodes), matching how the server walks source_html; our
@@ -38692,14 +38701,48 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
38692
38701
  // Hover affordance (only when armed and not mid-edit). Highlight leaves AND
38693
38702
  // inline-only containers (their bare text is per-node editable, ENG-6856).
38694
38703
  document.addEventListener('mouseover', function(e){
38695
- if(!editEnabled||editing) return; var el=e.target;
38696
- if(editable(el)||inlineOnlyEditable(el)){ el.style.cursor='text'; el.style.outline=el.style.outline||'1px dashed rgba(110,231,183,.6)'; el.__alHover=1; }
38704
+ if(!canEdit()) return; var el=e.target;
38705
+ if(editable(el)||inlineOnlyEditable(el)){
38706
+ // ENG-9383: remember what the author's cursor was before we overwrite it.
38707
+ // Blanking it on the way out would delete an inline cursor the artefact
38708
+ // set itself; '' is a legitimate saved value meaning "there was none".
38709
+ if(el.__alCur===undefined) el.__alCur = el.style.cursor || '';
38710
+ el.style.cursor='text'; el.style.outline=el.style.outline||'1px dashed rgba(110,231,183,.6)'; el.__alHover=1; hoverCued.push(el);
38711
+ }
38697
38712
  });
38698
38713
  document.addEventListener('mouseout', function(e){
38699
- var el=e.target; if(el&&el.__alHover&&el!==editing){ el.style.outline=''; el.__alHover=0; }
38714
+ var el=e.target; if(el&&el.__alHover&&el!==editing){ el.style.outline=''; restoreCursor(el); el.__alHover=0; dropHoverCue(el); }
38700
38715
  });
38716
+ // ENG-9383 (CodeRabbit on #4956): the cue is an outline AND an I-beam cursor.
38717
+ // Clearing only the outline leaves the text still saying "you can type here"
38718
+ // on a page that will now refuse the click - the same misdirection this ticket
38719
+ // is about, one property over.
38720
+ function restoreCursor(el){
38721
+ if(el.__alCur!==undefined){ try{ el.style.cursor=el.__alCur; }catch(e){} el.__alCur=undefined; }
38722
+ }
38723
+ // Keep hoverCued bounded. Without this it grows once per hovered element for
38724
+ // the life of the page and pins every one of them against GC - a list that
38725
+ // only ever empties when the viewer toggles the mode off is a leak on any page
38726
+ // nobody toggles.
38727
+ function dropHoverCue(el){
38728
+ var i=hoverCued.indexOf(el); if(i!==-1) hoverCued.splice(i,1);
38729
+ }
38730
+ // ENG-9383: drop every outline the mouseover cue left behind, without waiting
38731
+ // for a mouseout that may never come - the mode can go off while the pointer is
38732
+ // parked on the text, and then the artefact wears a dashed "editable" outline
38733
+ // on a page where you no longer can. Tracked in a list rather than queried back
38734
+ // out of the DOM: more than one element can carry the cue if the pointer moved
38735
+ // between mouseover and mouseout, and the bridge should not depend on a
38736
+ // selector matching an inline style it wrote.
38737
+ function clearHoverCues(){
38738
+ for(var i=0;i<hoverCued.length;i++){
38739
+ var el=hoverCued[i];
38740
+ if(el && el.__alHover && el!==editing){ try{ el.style.outline=''; }catch(e){} restoreCursor(el); el.__alHover=0; }
38741
+ }
38742
+ hoverCued.length=0;
38743
+ }
38701
38744
  document.addEventListener('click', function(e){
38702
- if(!editEnabled||editing) return;
38745
+ if(!canEdit()) return;
38703
38746
  var sel=document.getSelection(); if(sel && String(sel).trim()) return; // a selection => comment flow
38704
38747
  var el=e.target;
38705
38748
  if(editable(el)){ e.preventDefault(); e.stopPropagation(); startEdit(el); return; }
@@ -38743,7 +38786,7 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
38743
38786
  // Deliberately general: nothing here knows about .clickzone or any class name.
38744
38787
  // It fixes any artefact that covers its own content.
38745
38788
  window.addEventListener('click', function(e){
38746
- if(!editEnabled || !editMode || editing) return;
38789
+ if(!canEdit()) return;
38747
38790
  var sel=document.getSelection(); if(sel && String(sel).trim()) return; // selection => comment flow
38748
38791
  var t=e.target;
38749
38792
  // Our own toolbar (Save/Cancel) must keep its clicks.
@@ -38801,7 +38844,7 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
38801
38844
  hoverEl=null;
38802
38845
  }
38803
38846
  document.addEventListener('mousemove', function(e){
38804
- if(!editEnabled || !editMode || editing){ clearDeepHover(); return; }
38847
+ if(!canEdit()){ clearDeepHover(); return; }
38805
38848
  var t=e.target;
38806
38849
  if(editable(t)||inlineOnlyEditable(t)){ clearDeepHover(); return; }
38807
38850
  var now=Date.now(); if(now-hoverProbeAt<80) return; hoverProbeAt=now;
@@ -38901,12 +38944,17 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
38901
38944
  var d=e.data; if(!d || d['${MARKUP_CONTROL_MARKER}']!==true) return;
38902
38945
  if(d.type==='enable-edit'){ editEnabled=true; }
38903
38946
  else if(d.type==='enable-comment'){ commentEnabled=true; }
38904
- // ENG-8477: the viewer toggled Edit text in the shell. Turning it OFF must
38947
+ // ENG-8477: the viewer toggled Edit mode in the shell. Turning it OFF must
38905
38948
  // also close anything open and drop the hover cue, or the artefact is left
38906
38949
  // wearing our outlines with no way to clear them.
38950
+ // ENG-9383: clearDeepHover() only knows the deep-probe path's outline. The
38951
+ // ENG-6821 mouseover path marks its own element with __alHover and relies on
38952
+ // mouseout to undo it - which never fires if the pointer is still sitting on
38953
+ // the text when the mode goes off, leaving a dashed "you can edit this"
38954
+ // outline on a page where you now cannot. Clear both.
38907
38955
  else if(d.type==='set-edit-mode'){
38908
38956
  editMode = !!d.on;
38909
- if(!editMode){ if(editing) endEdit(false); clearDeepHover(); }
38957
+ if(!editMode){ if(editing) endEdit(false); clearDeepHover(); clearHoverCues(); }
38910
38958
  }
38911
38959
  else if(d.type==='edit-result'){
38912
38960
  if(d.ok){ /* republish hot-swaps the iframe; nothing to do */ }
@@ -41647,14 +41695,15 @@ var FLAG_REGISTRY = [
41647
41695
  // hand-written process.env gate) — same posture as memory-extraction /
41648
41696
  // tool-call-audit above. Gives a per-host canary before the DB flag exists.
41649
41697
  envVar: "AGT_SECRET_FILES_TMPFS_ENABLED",
41650
- // Deliberately-unreachable placeholder until this ships: no published CLI
41651
- // carries the manager reader + core writer yet, so reach must report "no
41652
- // host honors" rather than the `honors`-for-everyone that omitting `since`
41653
- // produces. MOVE THIS PIN to the actual auto-published agt-cli version at
41654
- // merge (auto-publish patch-bumps from main; verify against the tarball, the
41655
- // ENG-8575/ENG-9350 lesson) the marker is `setSecretFileTmpfsBacking` in
41656
- // package/dist/lib/manager-worker.js.
41657
- since: "99.0.0"
41698
+ // The real published build that carries the manager reader + core writer,
41699
+ // replacing the deliberately-unreachable `99.0.0` this flag shipped with.
41700
+ // Verified against the tarball (`npm pack @integrity-labs/agt-cli@0.28.678`):
41701
+ // `setSecretFileTmpfsBacking` is present in package/dist/lib/manager-worker.js
41702
+ // and the `secret-files-tmpfs` key ships in the bundle. Auto-publish patch-
41703
+ // bumps from main, so if a CLI-touching PR landed between the ENG-9348 merge
41704
+ // and this one the real cut is higher than 0.28.678 and reach under-reports;
41705
+ // re-verify before flipping the flag on for a canary (ENG-8575/ENG-9350).
41706
+ since: "0.28.678"
41658
41707
  },
41659
41708
  {
41660
41709
  key: "memory-file-tombstones",
@@ -42438,6 +42487,17 @@ var FLAG_REGISTRY = [
42438
42487
  // control that does nothing, which is the ENG-8303 class exactly.
42439
42488
  // enforce arms automated downtime on a customer's production host.
42440
42489
  sensitive: true
42490
+ },
42491
+ {
42492
+ key: "live-meeting-advisor",
42493
+ description: "Live meeting advising in Ninja Notes (ENG-9381). When ON for an org, a person recording a meeting on the Mac may arm an agent to watch it in flight: audio chunks stream to POST /notes/live/:id/chunks, a server-side Haiku vet decides moment by moment whether to escalate, and escalations reach the agent in a server-minted chat thread. Gates the CAPABILITY, not a surface: the refusal is in startLiveAdvisorSession, so a client that ignores the flag still cannot open a session, and GET /notes/destinations reports the same answer as advisor_enabled so the app can skip the arming modal entirely. Boolean gate; ships dark. OFF NEVER COSTS THE RECORDING. An unentitled org \u2014 or a flag read that fails \u2014 costs the advisor only; the microphone still starts and the note is still transcribed and delivered. That direction is deliberate: the user pressed Record and a recording is what they are owed, while arming on a failed read would spend money per minute on a session nobody confirmed. Deliberately NO envVar. This is an org-scoped gate, and an envVar is highest-precedence per ADR-0022 \u2014 a literal in sst.config.ts would pin every stage and make the admin control do nothing, the ENG-8303 class exactly.",
42494
+ flagType: "boolean",
42495
+ defaultValue: false,
42496
+ // Turning it ON arms a per-minute-metered capability AND starts streaming
42497
+ // meeting content to a server-side vet. Both halves are the deliberate,
42498
+ // audited decision ADR-0022 §4 reserves confirmation for — same treatment as
42499
+ // agent-hours-billing-enabled.
42500
+ sensitive: true
42441
42501
  }
42442
42502
  ];
42443
42503
  var REGISTRY_BY_KEY = new Map(FLAG_REGISTRY.map((definition) => [definition.key, definition]));