@lotics/cli 0.245.0 → 0.246.0

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.
@@ -732,6 +732,15 @@ var __loticsProbe = (() => {
732
732
  });
733
733
  return { total: briefs.length, fold, below: briefs.filter((one) => one.bottom > fold) };
734
734
  }
735
+ function openPanel(body) {
736
+ return within(body, '[role="tabpanel"]').find(onScreen);
737
+ }
738
+ function headings(el) {
739
+ return within(el, ".lotics-section-heading").filter(onScreen).flatMap((heading) => {
740
+ const title = within(heading, "h1, h2, h3, h4, h5, h6")[0];
741
+ return title === void 0 ? [] : [words2(title)];
742
+ });
743
+ }
735
744
  function briefRepeats(root = document.body) {
736
745
  let total = 0;
737
746
  const repeated = surfaces(root).flatMap((surface) => {
@@ -741,10 +750,34 @@ var __loticsProbe = (() => {
741
750
  within(surface.root, "*").filter((el) => el.childElementCount === 0 && !surface.body.contains(el) && el.closest('button, [role="button"], [role="tab"]') === null && onScreen(el)).map((el) => said(words2(el))).filter((text) => text.length > 1)
742
751
  );
743
752
  const values = within(brief, ".lotics-record-facts__value").filter(onScreen);
744
- total += values.length;
745
- return values.flatMap((value) => {
746
- const text = said(words2(value));
747
- return text !== "" && head.has(text) ? [{ record: surface.name, value: words2(value), where: "head" }] : [];
753
+ const parts = headings(brief);
754
+ total += values.length + parts.length;
755
+ const panel = openPanel(surface.body);
756
+ const open = new Set(panel === void 0 ? [] : headings(panel).map(said));
757
+ return [
758
+ ...values.flatMap((value) => {
759
+ const text = said(words2(value));
760
+ return text !== "" && head.has(text) ? [{ record: surface.name, value: words2(value), where: "head" }] : [];
761
+ }),
762
+ ...parts.flatMap((part) => open.has(said(part)) ? [{ record: surface.name, value: part, where: "tab" }] : [])
763
+ ];
764
+ });
765
+ return { total, repeated };
766
+ }
767
+ function actRepeats(root = document.body) {
768
+ let total = 0;
769
+ const repeated = surfaces(root).flatMap((surface) => {
770
+ const panel = openPanel(surface.body);
771
+ if (panel === void 0) return [];
772
+ const verbs = new Set(
773
+ within(surface.root, PRIMARY).filter((act) => !surface.body.contains(act) && onScreen(act)).map((act) => said(words2(act))).filter((text) => text !== "")
774
+ );
775
+ const waiting = within(panel, ".lotics-act-card").filter((card) => card.querySelector(".lotics-act-card__fold") === null && onScreen(card));
776
+ const firsts = waiting.filter((card, at) => waiting.findIndex((other) => other.parentElement === card.parentElement) === at);
777
+ total += firsts.length;
778
+ return firsts.flatMap((card) => {
779
+ const title = words2(card.querySelector(".lotics-act-card__title"));
780
+ return title !== "" && verbs.has(said(title)) ? [{ record: surface.name, act: title }] : [];
748
781
  });
749
782
  });
750
783
  return { total, repeated };
@@ -755,7 +788,7 @@ var __loticsProbe = (() => {
755
788
  const tabs = within(surface.body, '[role="tab"]').filter(onScreen);
756
789
  total += tabs.length;
757
790
  const open = tabs.find((tab) => tab.getAttribute("aria-selected") === "true");
758
- const panel = within(surface.body, '[role="tabpanel"]').find(onScreen);
791
+ const panel = openPanel(surface.body);
759
792
  const bare = open !== void 0 && panel !== void 0 && within(panel, ".lotics-section").filter(onScreen).length === 0;
760
793
  return bare ? [{ record: surface.name, tab: words2(open).replace(/\d+$/, "").trim() }] : [];
761
794
  });
@@ -769,7 +802,7 @@ var __loticsProbe = (() => {
769
802
  const skipTag = /^(SCRIPT|STYLE|TITLE|META|LINK|NOSCRIPT|TEMPLATE)$/;
770
803
  const chrome = 'nav, [role="banner"]';
771
804
  const recordSurface = '.lotics-record-page, [role="dialog"]';
772
- const headings = 'h1, h2, h3, h4, h5, h6, [role="heading"]';
805
+ const headings2 = 'h1, h2, h3, h4, h5, h6, [role="heading"]';
773
806
  const noteFloor = 3;
774
807
  const formFloor = 3;
775
808
  const hueStep = 30;
@@ -778,7 +811,7 @@ var __loticsProbe = (() => {
778
811
  const sameEdge = 8;
779
812
  const words5 = (el) => el === null ? "" : (el.textContent || "").trim().slice(0, 40);
780
813
  const surfaces2 = within(root, recordSurface).filter(onScreen);
781
- const called2 = (el) => el.matches(headings) ? words5(el) || "the section" : el.matches(recordSurface) ? words5(el.querySelector(".lotics-record-page__heading, h1, h2")) || "the record" : "the screen";
814
+ const called2 = (el) => el.matches(headings2) ? words5(el) || "the section" : el.matches(recordSurface) ? words5(el.querySelector(".lotics-record-page__heading, h1, h2")) || "the record" : "the screen";
782
815
  const rules = [];
783
816
  const primary = '[data-variant="primary"]';
784
817
  const acts = within(root, primary).filter(
@@ -791,7 +824,7 @@ var __loticsProbe = (() => {
791
824
  const surface = act.closest(recordSurface) ?? page;
792
825
  let titles = titled.get(surface);
793
826
  if (titles === void 0) {
794
- titles = within(surface, headings).filter(onScreen);
827
+ titles = within(surface, headings2).filter(onScreen);
795
828
  titled.set(surface, titles);
796
829
  }
797
830
  let owner = surface;
@@ -1144,11 +1177,11 @@ var __loticsProbe = (() => {
1144
1177
  const tag = /^H([1-6])$/.exec(el.tagName);
1145
1178
  return tag === null ? 2 : Number(tag[1]);
1146
1179
  };
1147
- const headings = within(root, HEADING2).filter(
1180
+ const headings2 = within(root, HEADING2).filter(
1148
1181
  (el) => onScreen(el) && el.closest(NAVIGATION) === null && words3(el) !== ""
1149
1182
  );
1150
- const shallowest = headings.reduce((top, el) => Math.min(top, rank(el)), Infinity);
1151
- const pageTitle = headings.find((el) => rank(el) === shallowest);
1183
+ const shallowest = headings2.reduce((top, el) => Math.min(top, rank(el)), Infinity);
1184
+ const pageTitle = headings2.find((el) => rank(el) === shallowest);
1152
1185
  const headerRow = (heading) => {
1153
1186
  const own = words3(heading);
1154
1187
  let row = heading;
@@ -1162,7 +1195,7 @@ var __loticsProbe = (() => {
1162
1195
  let sections = 0;
1163
1196
  let badged = 0;
1164
1197
  const badges = [];
1165
- for (const heading of headings) {
1198
+ for (const heading of headings2) {
1166
1199
  if (heading === pageTitle) continue;
1167
1200
  sections += 1;
1168
1201
  const mark = graphicIn(headerRow(heading));
@@ -1366,18 +1399,18 @@ var __loticsProbe = (() => {
1366
1399
  const row = ".lotics-table__row";
1367
1400
  return within(root, table).filter((register) => onScreen(register) && !register.hasAttribute("data-stacked")).map((register) => {
1368
1401
  const rows = Array.from(register.querySelectorAll(row)).filter((one) => inside(one, register, table) && onScreen(one) && stored(one));
1369
- const headings = Array.from(register.querySelectorAll(".lotics-table__column")).filter((heading) => inside(heading, register, table));
1402
+ const headings2 = Array.from(register.querySelectorAll(".lotics-table__column")).filter((heading) => inside(heading, register, table));
1370
1403
  const cellsOf = (one) => {
1371
1404
  const box = Array.from(one.querySelectorAll(".lotics-table__cells")).find((cells) => inside(cells, one, row));
1372
1405
  return box === void 0 ? [] : Array.from(box.children).filter((cell) => cell.classList.contains("lotics-table__cell"));
1373
1406
  };
1374
1407
  const gutterOf = (one) => Array.from(one.querySelectorAll(".lotics-table__trailing")).find((gutter) => inside(gutter, one, row));
1375
1408
  const grid = rows.map(cellsOf);
1376
- const columns = Math.max(headings.length, ...grid.map((cells) => cells.length), 0);
1409
+ const columns = Math.max(headings2.length, ...grid.map((cells) => cells.length), 0);
1377
1410
  const slots = Array.from({ length: columns }, (_, index) => ({
1378
- name: words4(headings[index]) || `column ${index + 1}`,
1411
+ name: words4(headings2[index]) || `column ${index + 1}`,
1379
1412
  kind: "column",
1380
- heading: headings[index],
1413
+ heading: headings2[index],
1381
1414
  cells: grid.map((cells) => cells[index])
1382
1415
  }));
1383
1416
  const gutters = rows.map(gutterOf);
@@ -1388,19 +1421,19 @@ var __loticsProbe = (() => {
1388
1421
  function ariaRegisters(root) {
1389
1422
  const table = '[role="table"], [role="grid"]';
1390
1423
  return within(root, table).filter(onScreen).map((register) => {
1391
- const headings = Array.from(register.querySelectorAll('[role="columnheader"]')).filter((heading) => inside(heading, register, table)).map(words4);
1424
+ const headings2 = Array.from(register.querySelectorAll('[role="columnheader"]')).filter((heading) => inside(heading, register, table)).map(words4);
1392
1425
  const grid = Array.from(register.querySelectorAll('[role="row"]')).filter((one) => inside(one, register, table) && onScreen(one) && stored(one)).map((one) => ({
1393
1426
  row: one,
1394
1427
  cells: Array.from(one.querySelectorAll('[role="cell"], [role="gridcell"]')).filter(
1395
1428
  (cell) => inside(cell, one, '[role="row"]')
1396
1429
  )
1397
1430
  })).filter((one) => one.cells.length > 0);
1398
- const columns = Math.max(headings.length, ...grid.map((one) => one.cells.length), 0);
1431
+ const columns = Math.max(headings2.length, ...grid.map((one) => one.cells.length), 0);
1399
1432
  return {
1400
1433
  root: register,
1401
1434
  rows: grid.map((one) => one.row),
1402
1435
  slots: Array.from({ length: columns }, (_, index) => ({
1403
- name: headings[index] || `column ${index + 1}`,
1436
+ name: headings2[index] || `column ${index + 1}`,
1404
1437
  kind: "column",
1405
1438
  cells: grid.map((one) => one.cells[index])
1406
1439
  }))
@@ -1497,9 +1530,15 @@ var __loticsProbe = (() => {
1497
1530
  );
1498
1531
  return Math.max(0, width - drawn);
1499
1532
  }
1500
- function slotGap(register) {
1501
- const boxes = register.slots.map((slot) => slot.cells[0]).filter((cell) => cell !== void 0).map((cell) => cell.getBoundingClientRect()).sort((a, b) => a.left - b.left);
1502
- return boxes.length < 2 ? 0 : Math.max(0, Math.round(boxes[1].left - boxes[0].right));
1533
+ function slotGaps(register) {
1534
+ const first = register.slots.map((slot) => slot.cells[0]).filter((cell) => cell !== void 0);
1535
+ const boxes = first.map((cell) => cell.getBoundingClientRect()).sort((a, b) => a.left - b.left);
1536
+ if (boxes.length < 2) return { gap: 0, beyond: 0 };
1537
+ const drawn = boxes.slice(1).map((box, index) => Math.max(0, box.left - boxes[index].right));
1538
+ const parent = first[0].parentElement;
1539
+ const declared = parent === null ? Number.NaN : Number.parseFloat(getComputedStyle(parent).columnGap);
1540
+ const gap = Number.isFinite(declared) ? declared : Math.min(...drawn);
1541
+ return { gap: Math.round(gap), beyond: drawn.reduce((sum, one) => sum + Math.max(0, one - gap), 0) };
1503
1542
  }
1504
1543
  function shedWithRoom(root = document.body) {
1505
1544
  let total = 0;
@@ -1508,8 +1547,8 @@ var __loticsProbe = (() => {
1508
1547
  const shed = shedOf(register.root);
1509
1548
  if (shed.length === 0 || register.rows.length === 0) continue;
1510
1549
  total += shed.length;
1511
- const unused = Math.round(register.slots.reduce((sum, slot) => sum + spare(slot), 0));
1512
- const gap = slotGap(register);
1550
+ const { gap, beyond } = slotGaps(register);
1551
+ const unused = Math.round(register.slots.reduce((sum, slot) => sum + spare(slot), 0) + beyond);
1513
1552
  for (const column of shed) if (column.width + gap <= unused) found.push({ ...column, gap, unused });
1514
1553
  }
1515
1554
  return { total, shed: found };
@@ -1668,7 +1707,7 @@ var __loticsProbe = (() => {
1668
1707
  walk(root);
1669
1708
  }
1670
1709
  const dates = leaves.filter((leaf) => leaf.date);
1671
- const headings = leaves.filter((leaf) => !leaf.date);
1710
+ const headings2 = leaves.filter((leaf) => !leaf.date);
1672
1711
  const leads = (leaf) => !leaves.some(
1673
1712
  (other) => other.left < leaf.left && other.top < leaf.bottom && other.bottom > leaf.top
1674
1713
  );
@@ -1694,7 +1733,7 @@ var __loticsProbe = (() => {
1694
1733
  grouped += 1;
1695
1734
  if (runs.length < 3) {
1696
1735
  const top = Math.min(...column.items.map((leaf) => leaf.top));
1697
- const over = headings.filter((label) => label.top < top && top - label.top <= 360 && label.left < column.right && label.right > column.left).sort((a, b) => b.top - a.top)[0];
1736
+ const over = headings2.filter((label) => label.top < top && top - label.top <= 360 && label.left < column.right && label.right > column.left).sort((a, b) => b.top - a.top)[0];
1698
1737
  runs.push(
1699
1738
  `${over === void 0 ? "(unnamed)" : over.text}: ${column.items.length} rows over ${days.size} days, the date repeated per row`
1700
1739
  );
@@ -1811,12 +1850,12 @@ var __loticsProbe = (() => {
1811
1850
  const navFirst = nav === null ? void 0 : Array.from(nav.querySelectorAll('a[href], [role="link"]')).filter(
1812
1851
  (item) => onScreen(item) && (item.textContent || "").trim() !== ""
1813
1852
  )[0];
1814
- const headings = within(root, "h1, h2, h3, h4, h5, h6").filter(
1853
+ const headings2 = within(root, "h1, h2, h3, h4, h5, h6").filter(
1815
1854
  (el) => onScreen(el) && el.closest('nav, [role="banner"]') === null && (el.textContent || "").trim() !== ""
1816
1855
  );
1817
- const title = headings[0];
1856
+ const title = headings2[0];
1818
1857
  const rank = (el) => Number(el.tagName.slice(1));
1819
- const heading = title === void 0 ? void 0 : headings.slice(1).find((el) => rank(el) > rank(title));
1858
+ const heading = title === void 0 ? void 0 : headings2.slice(1).find((el) => rank(el) > rank(title));
1820
1859
  const primaries = within(root, '[data-variant="primary"]').filter(
1821
1860
  (el) => onScreen(el) && el.closest('nav, [role="banner"]') === null
1822
1861
  );
@@ -1987,7 +2026,12 @@ var __loticsProbe = (() => {
1987
2026
  brief_repeats: {
1988
2027
  law: "hierarchy.md",
1989
2028
  section: "One fact, one place",
1990
- fix: "Take the value out of the brief's band: the head already states it, so the band read under it is the same fact twice."
2029
+ fix: "Take it out of the brief: the head already states the value, or the tab open at rest already draws the part, so the brief says it a second time."
2030
+ },
2031
+ act_repeats: {
2032
+ law: "hierarchy.md",
2033
+ section: "One fact, one place",
2034
+ fix: "Draw the head's act in its queue's card by its words and outcomes alone (`ActCard` `carried`): its verb, due day and refusal are the head's."
1991
2035
  },
1992
2036
  empty_tab: {
1993
2037
  law: "hierarchy.md",
@@ -2244,7 +2288,19 @@ var __loticsProbe = (() => {
2244
2288
  ...signature("brief_repeats"),
2245
2289
  total: repeats.total,
2246
2290
  count: repeats.repeated.length,
2247
- detail: repeats.repeated.slice(0, 5).map((one) => `"${one.record}": the brief states "${one.value}", which the head already says`)
2291
+ detail: repeats.repeated.slice(0, 5).map(
2292
+ (one) => one.where === "head" ? `"${one.record}": the brief states "${one.value}", which the head already says` : `"${one.record}": the brief stands "${one.value}", which the tab open at rest draws too`
2293
+ )
2294
+ });
2295
+ }
2296
+ const acts = actRepeats(surface);
2297
+ if (acts.repeated.length > 0) {
2298
+ findings.push({
2299
+ probe: "act_repeats",
2300
+ ...signature("act_repeats"),
2301
+ total: acts.total,
2302
+ count: acts.repeated.length,
2303
+ detail: acts.repeated.slice(0, 5).map((one) => `"${one.record}": the head's act "${one.act}" heads a card in the tab open at rest too`)
2248
2304
  });
2249
2305
  }
2250
2306
  const tabs = emptyTabs(surface);