@vincemakes/kiso-tui-cells 0.16.5 → 0.16.6

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.
@@ -293,6 +293,18 @@ export declare function exploreRows(parts: readonly {
293
293
  * metadata terms survive (the W14 metadata rule — they give way LAST),
294
294
  * the words width-cut at the end with the honest "…" (never a silent
295
295
  * truncate — invariant ① holds on the ONE row by construction). */
296
+ /**
297
+ * R3b — what a run of work DID, in words. One definition, because two
298
+ * surfaces say it: the fold line (`turnFold`, above) and the expand
299
+ * header the compositor writes when that fold is opened. A second copy
300
+ * would be a second answer to the same question, and the first thing to
301
+ * drift would be the plurals — `search_text` is "matches", not
302
+ * "searchs", and only the ROLLUP_NOUN table knows that.
303
+ *
304
+ * Zero terms are dropped (owner ruling, R3b): a term earns its place by
305
+ * having a count.
306
+ */
307
+ export declare function foldTerms(reads: number, edits: number, others: readonly [string, number][]): string[];
296
308
  export declare function turnFold(t: {
297
309
  words: string;
298
310
  thoughtSeconds: number;
@@ -960,23 +960,56 @@ function countTerm(n, singular, plural) {
960
960
  * metadata terms survive (the W14 metadata rule — they give way LAST),
961
961
  * the words width-cut at the end with the honest "…" (never a silent
962
962
  * truncate — invariant ① holds on the ONE row by construction). */
963
- export function turnFold(t, W) {
964
- const p = palette();
965
- const parts = [`thought ${t.thoughtSeconds}s`, countTerm(t.reads, "read", "reads"), countTerm(t.edits, "edit", "edits")];
966
- for (const [name, n] of t.others) {
963
+ /**
964
+ * R3b — what a run of work DID, in words. One definition, because two
965
+ * surfaces say it: the fold line (`turnFold`, above) and the expand
966
+ * header the compositor writes when that fold is opened. A second copy
967
+ * would be a second answer to the same question, and the first thing to
968
+ * drift would be the plurals — `search_text` is "matches", not
969
+ * "searchs", and only the ROLLUP_NOUN table knows that.
970
+ *
971
+ * Zero terms are dropped (owner ruling, R3b): a term earns its place by
972
+ * having a count.
973
+ */
974
+ export function foldTerms(reads, edits, others) {
975
+ const parts = [];
976
+ if (reads > 0)
977
+ parts.push(countTerm(reads, "read", "reads"));
978
+ if (edits > 0)
979
+ parts.push(countTerm(edits, "edit", "edits"));
980
+ for (const [name, n] of others) {
981
+ if (n === 0)
982
+ continue;
967
983
  const noun = ROLLUP_NOUN[name];
968
- if (noun !== undefined) {
984
+ if (noun !== undefined)
969
985
  parts.push(countTerm(n, noun.endsWith("es") ? noun.slice(0, -2) : noun.slice(0, -1), noun));
970
- }
971
986
  else {
972
987
  const verb = displayVerb(name);
973
988
  parts.push(countTerm(n, verb, `${verb}s`));
974
989
  }
975
990
  }
976
- const meta = parts.join(" · ");
991
+ return parts;
992
+ }
993
+ export function turnFold(t, W) {
994
+ const p = palette();
995
+ // R3b (owner, 2026-08-27): ZERO TERMS ARE DROPPED. W14 always wrote
996
+ // `no reads · no edits`, which is a sentence about things that did not
997
+ // happen — on a segment fold, where a run is usually all reads or all
998
+ // edits, half the row was the half that said nothing. A term earns its
999
+ // place by having a count.
1000
+ const meta = [`thought ${t.thoughtSeconds}s`, ...foldTerms(t.reads, t.edits, t.others)].join(" · ");
977
1001
  const words = escapeTerminal(t.words);
978
1002
  if (words === "") {
979
1003
  const row = `${p.bold}✦${p.reset} ${meta}`;
1004
+ // R3b: the fold NAMES ITS OWN KEY. Without it the segment's work is
1005
+ // unreachable — no rollup row, no expand, nothing — and hiding a
1006
+ // tool call behind a line with no way back is the one thing this
1007
+ // product must not do. The suffix gives way first at a narrow
1008
+ // width, on the same principle the settled card's does: an
1009
+ // affordance that does not fit is dropped, never half-drawn.
1010
+ const keyed = `${row}${p.dim} · ctrl+r${p.reset}`;
1011
+ if (visibleWidth(keyed) <= W)
1012
+ return [keyed];
980
1013
  return visibleWidth(row) <= W ? [row] : [`${p.bold}✦${p.reset} ${widthCut(meta, Math.max(1, W - 3))}…`]; // a wordless turn folds to the W14 shape
981
1014
  }
982
1015
  // A9 (ruling R2, mock A): the user chip rides the fold — the human's
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  * package); the cli never imports it directly. Experimental — no
7
7
  * API-stability promise yet.
8
8
  */
9
- export { SPINNER, foldLine, foldWords, visibleWidth, bodySpacing, Container, cellComponent, focusToken, ROLLUP_NOUN, turnFold, CAP_TASK_LIVE, formatDuration, statusLine, boxTop, boxBottom, terminalPipe, type FrameCtx, type RenderLine, type Component, type BodyCell, } from "./components.js";
9
+ export { SPINNER, foldLine, foldWords, visibleWidth, bodySpacing, Container, cellComponent, focusToken, ROLLUP_NOUN, turnFold, foldTerms, CAP_TASK_LIVE, formatDuration, statusLine, boxTop, boxBottom, terminalPipe, type FrameCtx, type RenderLine, type Component, type BodyCell, } from "./components.js";
10
10
  export { editFileDiff, truncateDiff, writeFileDiff, type DiffLine, type DiffResult } from "./diff.js";
11
11
  export { pendingQueueRows } from "./components.js";
12
12
  export { charWidth, displayWidth, leadWidth, widthOf } from "./width.js";
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * package); the cli never imports it directly. Experimental — no
7
7
  * API-stability promise yet.
8
8
  */
9
- export { SPINNER, foldLine, foldWords, visibleWidth, bodySpacing, Container, cellComponent, focusToken, ROLLUP_NOUN, turnFold, CAP_TASK_LIVE, formatDuration, statusLine, boxTop, boxBottom, terminalPipe, } from "./components.js";
9
+ export { SPINNER, foldLine, foldWords, visibleWidth, bodySpacing, Container, cellComponent, focusToken, ROLLUP_NOUN, turnFold, foldTerms, CAP_TASK_LIVE, formatDuration, statusLine, boxTop, boxBottom, terminalPipe, } from "./components.js";
10
10
  export { editFileDiff, truncateDiff, writeFileDiff } from "./diff.js";
11
11
  // W22 (the v8 input round): the pending-queue chips — the SAME
12
12
  // UserMessage chip with the □ gutter, pre-rendered above the input
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vincemakes/kiso-tui-cells",
3
- "version": "0.16.5",
3
+ "version": "0.16.6",
4
4
  "description": "kiso tui-cells — the components cell renderer (components, diff, width, the render slice). Zero runtime dependencies: input is data, output is bytes.",
5
5
  "type": "module",
6
6
  "license": "MIT",