strom-research 1.26.0-beta.4 → 1.26.0-beta.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.
package/CHANGELOG.cs.md CHANGED
@@ -7,22 +7,26 @@ Změny každé verze ve zkratce. Úplné poznámky a instalační řádky jsou n
7
7
 
8
8
  ## 1.26.0
9
9
 
10
- *Připravuje se: bety do 1.26.0-beta.4. Oddíl bude úplný s vydáním.*
10
+ *Připravuje se: bety do 1.26.0-beta.6. Oddíl bude úplný s vydáním.*
11
11
 
12
12
  - **Linie výzkumu z aplikace Strom: založit, upravit, pozastavit, seřadit.** Linii jde v aplikaci založit nebo upravit
13
13
  (osoba, směr, otázka, meze), pozastavit, ukončit nebo znovu spustit; pořadí linií je pořadí práce a stránka telefonu
14
14
  linii posune nahoru nebo dolů a pozastaví. Práce mimo linie – vedlejší větev, kam žádná linie nesahá, třeba sestra
15
15
  předka a její rodina – teď přijde občas, jeden úkol z deseti sezení, místo jen na konci. Každá taková větev může mít
16
- vlastní volbu (občas, na konci, normálně jako práce linií, nikdy, nebo přidat k linii) a u větve, která roste, se
17
- v Co čeká navrhne linie: přidat k linii, založit pro ni linii, nechat, jak je, nebo nezkoumat. Manžel nebo manželka
18
- předka patří k linii předka. Kterýkoli úkol jde udělat hned nebo dát na konec a každý úkol ve frontě říká, proč stojí
19
- tam, kde stojí. V terminálu: Nastavení → Samostatná práce agenta → Práce mimo linie, `strom offline`,
20
- `strom task order`.
21
-
22
- - **Přepsané vyprávění nic neztratí.** Když výzkum vyprávění napíše znovu – víc údajů, lepší čtení, vyprávění
23
- převzaté ze staršího výzkumu – každý údaj, pramen a odkaz předchozí verze zůstane, nebo odejde jen záměrně
24
- s důvodem, který se uloží k vyprávění. Prameny, o které se vyprávění opírá, jsou u něj vidět, u každého údaje název
25
- a adresa, i když je text nejmenuje, a aplikace Strom je dostane s vyprávěním. Údaj z vodítka v textu říká, odkud je.
16
+ vlastní volbu (občas, na konci, normálně jako práce linií, nikdy, nebo přidat k linii) a u větve, která roste, se v Co
17
+ čeká navrhne linie: přidat k linii, založit pro ni linii, nechat, jak je, nebo nezkoumat. Manžel nebo manželka předka
18
+ patří k linii předka a linie s otázkou má v sobě svou osobu. Kterýkoli úkol jde udělat hned nebo dát na konec a každý
19
+ úkol ve frontě říká, proč stojí tam, kde stojí. V terminálu: Nastavení → Samostatná práce agenta → Práce mimo linie,
20
+ `strom offline`, `strom task order`.
21
+
22
+ - **Přepsané vyprávění nic neztratí.** Když výzkum vyprávění napíše znovu – víc údajů, lepší čtení, vyprávění převzaté
23
+ ze staršího výzkumu – každý údaj, pramen a odkaz předchozí verze zůstane, nebo odejde jen záměrně s důvodem, který se
24
+ uloží k vyprávění. Prameny, o které se vyprávění opírá, jsou u něj vidět, u každého údaje název a adresa, i když je
25
+ text nejmenuje, i pramen, který text jmenuje jen kódem; aplikace Strom je dostane s vyprávěním. Údaj z vodítka v textu
26
+ říká, odkud je.
27
+
28
+ - Velký rodokmen převzatý ve Windows (zhruba 1 500 osob a víc) už neskončí chybou gitu o příliš dlouhém příkazu
29
+ (ENAMETOOLONG) bez jediného zapsaného údaje: vše převzaté se zapíše.
26
30
 
27
31
  ## 1.25.2
28
32
 
package/CHANGELOG.de.md CHANGED
@@ -7,25 +7,29 @@ Die Änderungen jeder Version in Kürze. Die vollständigen Hinweise und die Ins
7
7
 
8
8
  ## 1.26.0
9
9
 
10
- *In Vorbereitung: die Betas bis 1.26.0-beta.4. Der Abschnitt ist mit dem Release vollständig.*
10
+ *In Vorbereitung: die Betas bis 1.26.0-beta.6. Der Abschnitt ist mit dem Release vollständig.*
11
11
 
12
12
  - **Die Linien der Forschung aus der Strom-App: anlegen, ändern, pausieren, ordnen.** Eine Linie lässt sich in der App
13
13
  anlegen oder ändern (Person, Richtung, Frage, Grenzen), pausieren, beenden oder wieder aufnehmen; die Reihenfolge der
14
- Linien ist die Reihenfolge der Arbeit, und die Seite fürs Telefon schiebt eine Linie nach oben oder unten und
15
- pausiert sie. Arbeit außerhalb der Linien – ein Nebenzweig, den keine Linie erreicht, etwa die Schwester eines
16
- Vorfahren und ihre Familie – kommt jetzt gelegentlich, eine Aufgabe in zehn Sitzungen, statt nur am Ende. Jeder
17
- solche Zweig kann eine eigene Wahl haben (gelegentlich, am Ende, wie die Arbeit der Linien, nie oder einer Linie
18
- hinzugefügt), und für einen wachsenden Zweig wird unter „Was wartet“ eine Linie vorgeschlagen: einer Linie
19
- hinzufügen, eine Linie für ihn anlegen, so lassen oder nicht erforschen. Ehemann oder Ehefrau eines Vorfahren gehören
20
- zur Linie des Vorfahren. Jede Aufgabe lässt sich sofort nehmen oder ans Ende stellen, und jede Aufgabe in der
21
- Warteschlange sagt, warum sie dort steht. Im Terminal: Einstellungen → Der Agent allein → Arbeit außerhalb der
22
- Linien, `strom offline`, `strom task order`.
14
+ Linien ist die Reihenfolge der Arbeit, und die Seite fürs Telefon schiebt eine Linie nach oben oder unten und pausiert
15
+ sie. Arbeit außerhalb der Linien – ein Nebenzweig, den keine Linie erreicht, etwa die Schwester eines Vorfahren und
16
+ ihre Familie – kommt jetzt gelegentlich, eine Aufgabe in zehn Sitzungen, statt nur am Ende. Jeder solche Zweig kann
17
+ eine eigene Wahl haben (gelegentlich, am Ende, wie die Arbeit der Linien, nie oder einer Linie hinzugefügt), und für
18
+ einen wachsenden Zweig wird unter „Was wartet“ eine Linie vorgeschlagen: einer Linie hinzufügen, eine Linie für ihn
19
+ anlegen, so lassen oder nicht erforschen. Ehemann oder Ehefrau eines Vorfahren gehören zur Linie des Vorfahren, und
20
+ eine Linie mit einer Frage enthält ihre Person. Jede Aufgabe lässt sich sofort nehmen oder ans Ende stellen, und jede
21
+ Aufgabe in der Warteschlange sagt, warum sie dort steht. Im Terminal: Einstellungen → Der Agent allein → Arbeit
22
+ außerhalb der Linien, `strom offline`, `strom task order`.
23
23
 
24
24
  - **Eine neu geschriebene Erzählung verliert nichts.** Schreibt die Forschung eine Erzählung neu – mehr Angaben, eine
25
25
  bessere Lesung, eine aus älterer Forschung übernommene Erzählung –, bleibt jede Angabe, Quelle und jeder Link der
26
- vorigen Fassung, oder geht nur absichtlich mit dem Grund, der bei der Erzählung gespeichert wird. Die Quellen, auf
27
- die sich eine Erzählung stützt, stehen bei ihr, Titel und Adresse unter jeder Angabe, auch wenn der Text sie nicht
28
- nennt, und die Strom-App erhält sie mit der Erzählung. Eine Angabe aus einem Hinweis nennt im Text ihre Herkunft.
26
+ vorigen Fassung, oder geht nur absichtlich mit dem Grund, der bei der Erzählung gespeichert wird. Die Quellen, auf die
27
+ sich eine Erzählung stützt, stehen bei ihr, Titel und Adresse unter jeder Angabe, auch wenn der Text sie nicht nennt,
28
+ auch eine Quelle, die der Text nur mit ihrem Kürzel nennt; die Strom-App erhält sie mit der Erzählung. Eine Angabe aus
29
+ einem Hinweis nennt im Text ihre Herkunft.
30
+
31
+ - Ein großer Stammbaum, unter Windows übernommen (etwa 1 500 Personen und mehr), scheitert nicht mehr in git an einer zu
32
+ langen Befehlszeile (ENAMETOOLONG), ohne dass etwas davon bleibt: alles Übernommene wird geschrieben.
29
33
 
30
34
  ## 1.25.2
31
35
 
package/CHANGELOG.md CHANGED
@@ -7,7 +7,7 @@ The changes of each version in short. The full notes and the install lines are o
7
7
 
8
8
  ## 1.26.0
9
9
 
10
- *In preparation: the betas up to 1.26.0-beta.4. The section is complete with the release.*
10
+ *In preparation: the betas up to 1.26.0-beta.6. The section is complete with the release.*
11
11
 
12
12
  - **The lines of the research from the Strom app: created, changed, paused, put in order.** A line is created or changed
13
13
  in the app (its person, direction, question, limits), paused, ended or taken up again; the order of the lines is the
@@ -15,15 +15,19 @@ The changes of each version in short. The full notes and the install lines are o
15
15
  reaches, such as an ancestor's sister and her family – now comes now and then, one task in ten sessions, instead of
16
16
  only at the end. Each such branch can have a choice of its own (now and then, at the end, as the lines' work, never,
17
17
  or added to a line), and a branch that grows gets a line proposed in What waits: add it to a line, create a line for
18
- it, leave it as it is, or not research it. The husband or wife of an ancestor belongs to the ancestor's line. Any task
19
- can be taken next or put at the end, and each task in the queue says why it stands where it does. In the terminal:
20
- Settings → the agent working alone → Work off the lines, `strom offline`, `strom task order`.
21
-
22
- - **A story written again loses nothing.** When the research writes a story anew – more facts, a better reading, a
23
- story taken over from older work – each fact, source and link of the version before stays, or goes only on purpose
24
- with the reason, kept with the story. The sources a story rests on are shown with it, title and address under each
25
- fact, also where the text does not name them, and the Strom app receives them with the story. A fact told from a
26
- lead names in the text where it comes from.
18
+ it, leave it as it is, or not research it. The husband or wife of an ancestor belongs to the ancestor's line, and a
19
+ line asking a question has its person in it. Any task can be taken next or put at the end, and each task in the queue
20
+ says why it stands where it does. In the terminal: Settings → the agent working alone → Work off the lines, `strom
21
+ offline`, `strom task order`.
22
+
23
+ - **A story written again loses nothing.** When the research writes a story anew – more facts, a better reading, a story
24
+ taken over from older work – each fact, source and link of the version before stays, or goes only on purpose with the
25
+ reason, kept with the story. The sources a story rests on are shown with it, title and address under each fact, also
26
+ where the text does not name them, and a source the text names only by its code among them; the Strom app receives
27
+ them with the story. A fact told from a lead names in the text where it comes from.
28
+
29
+ - A big family tree taken in on Windows (some 1 500 people and more) no longer fails in git over a command line too long
30
+ (ENAMETOOLONG) with nothing of it kept: everything taken in is written.
27
31
 
28
32
  ## 1.25.2
29
33
 
package/CHANGELOG.pl.md CHANGED
@@ -7,23 +7,27 @@ Zmiany każdej wersji w skrócie. Pełne informacje o wydaniach i polecenia inst
7
7
 
8
8
  ## 1.26.0
9
9
 
10
- *W przygotowaniu: bety do 1.26.0-beta.4. Sekcja będzie kompletna z wydaniem.*
10
+ *W przygotowaniu: bety do 1.26.0-beta.6. Sekcja będzie kompletna z wydaniem.*
11
11
 
12
12
  - **Linie badania z aplikacji Strom: założyć, zmienić, wstrzymać, uporządkować.** Linię można w aplikacji założyć lub
13
- zmienić (osoba, kierunek, pytanie, granice), wstrzymać, zakończyć lub wznowić; kolejność linii to kolejność pracy,
14
- a strona na telefon przesuwa linię w górę lub w dół i ją wstrzymuje. Praca poza liniami – boczna gałąź, do której nie
13
+ zmienić (osoba, kierunek, pytanie, granice), wstrzymać, zakończyć lub wznowić; kolejność linii to kolejność pracy, a
14
+ strona na telefon przesuwa linię w górę lub w dół i ją wstrzymuje. Praca poza liniami – boczna gałąź, do której nie
15
15
  sięga żadna linia, na przykład siostra przodka i jej rodzina – przychodzi teraz czasem, jedno zadanie na dziesięć
16
16
  sesji, a nie tylko na końcu. Każda taka gałąź może mieć własny wybór (czasem, na końcu, jak praca linii, nigdy albo
17
17
  dodana do linii), a dla rosnącej gałęzi w „Co czeka” proponowana jest linia: dodać do linii, założyć dla niej linię,
18
- zostawić bez zmian albo nie badać. Mąż lub żona przodka należą do linii przodka. Każde zadanie można wziąć od razu lub
19
- przenieść na koniec, a każde zadanie w kolejce mówi, dlaczego stoi tam, gdzie stoi. W terminalu: Ustawienia →
20
- Samodzielna praca agenta → Praca poza liniami, `strom offline`, `strom task order`.
18
+ zostawić bez zmian albo nie badać. Mąż lub żona przodka należą do linii przodka, a linia z pytaniem obejmuje swoją
19
+ osobę. Każde zadanie można wziąć od razu lub przenieść na koniec, a każde zadanie w kolejce mówi, dlaczego stoi tam,
20
+ gdzie stoi. W terminalu: Ustawienia → Samodzielna praca agenta → Praca poza liniami, `strom offline`, `strom task
21
+ order`.
21
22
 
22
23
  - **Opowieść napisana na nowo niczego nie traci.** Gdy badanie pisze opowieść od nowa – więcej danych, lepszy odczyt,
23
24
  opowieść przejęta ze starszego badania – każda dana, źródło i link poprzedniej wersji zostają albo odchodzą tylko
24
- celowo z powodem, zapisanym przy opowieści. Źródła, na których opiera się opowieść, są przy niej widoczne, tytuł
25
- i adres pod każdą daną, także gdy tekst ich nie wymienia, a aplikacja Strom dostaje je z opowieścią. Dana
26
- z poszlaki mówi w tekście, skąd pochodzi.
25
+ celowo z powodem, zapisanym przy opowieści. Źródła, na których opiera się opowieść, są przy niej widoczne, tytuł i
26
+ adres pod każdą daną, także gdy tekst ich nie wymienia, również źródło, które tekst wymienia tylko kodem; aplikacja
27
+ Strom dostaje je z opowieścią. Dana z poszlaki mówi w tekście, skąd pochodzi.
28
+
29
+ - Duże drzewo przejęte w systemie Windows (około 1500 osób i więcej) nie kończy się już błędem gita o zbyt długim
30
+ poleceniu (ENAMETOOLONG) bez żadnej zapisanej danej: wszystko, co przejęte, zostaje zapisane.
27
31
 
28
32
  ## 1.25.2
29
33
 
@@ -71,10 +71,12 @@ function restsOn(tree, v, history) {
71
71
  return [` ${id} ${owner} ${rest.join(" ")}`, ...its.map((s) => ` ← ${sourceLine(s)}`)];
72
72
  });
73
73
  const background = sources.filter((s) => s.background);
74
+ const named = sources.filter((s) => s.named);
74
75
  return [
75
76
  v.facts.length ? "rests on" : "rests on no recorded fact",
76
77
  ...facts,
77
78
  ...(background.length ? ["the background of place and time from", ...background.map((s) => ` ${sourceLine(s)}`)] : []),
79
+ ...(named.length ? ["named in the text", ...named.map((s) => ` ${sourceLine(s)}`)] : []),
78
80
  ...(v.sources ?? []).filter((s) => !background.some((b) => b.id === s)).map((s) => ` ${s} (no longer exists)`),
79
81
  ...history(v.history),
80
82
  ...(v.dropped?.length ? ["left out on purpose of the version before", ...v.dropped.map((d) => ` ${d.ref}: ${d.why}`)] : []),
@@ -170,11 +170,14 @@ export function researchPeople(tree, research) {
170
170
  /**
171
171
  * The people of a line as the person sees it (the app's GET /directions/people, strom research show): those of
172
172
  * researchPeople, and for a line of descendants — of which researchPeople proposes nothing — the descendants of its
173
- * person within its generations (the person 1, the children 2, …). The queue and the stories keep researchPeople.
173
+ * person within its generations (the person 1, the children 2, …); a question is about its person (generation 1).
174
+ * The queue and the stories keep researchPeople.
174
175
  */
175
176
  export function linePeople(tree, research) {
176
177
  if (research.direction === "descendants")
177
178
  return tree.get(research.focus) ? descendantGenerations(tree, research.focus, research.limits?.generations ?? 50) : new Map();
179
+ if (research.direction === "question")
180
+ return tree.get(research.focus) ? new Map([[research.focus, 1]]) : new Map();
178
181
  return researchPeople(tree, research);
179
182
  }
180
183
  export function frontier(tree, research) {
package/dist/core/git.js CHANGED
@@ -43,6 +43,32 @@ function withStdin(input, run) {
43
43
  fs.rmSync(dir, { recursive: true, force: true });
44
44
  }
45
45
  }
46
+ /**
47
+ * How many characters the paths of one git command line may take. Windows starts a program with a command line of at
48
+ * most 32 767 characters (spawnSync: ENAMETOOLONG — found: a family tree of 1 450 people taken in on Windows, its
49
+ * commit's `git add` naming every file, nothing of it kept); a longer list reaches git in parts, well within that.
50
+ * Not `--pathspec-from-file`: a git before 2.25 (older macOS command line tools, older Linux) knows none.
51
+ */
52
+ const ARGS_ROOM = 8000;
53
+ /** The paths in parts, in their order, each part within `room` characters on a command line (a path, quotes, a space). */
54
+ export function pathParts(paths, room = ARGS_ROOM) {
55
+ const parts = [];
56
+ let part = [];
57
+ let used = 0;
58
+ for (const p of paths) {
59
+ const size = p.length + 3;
60
+ if (part.length && used + size > room) {
61
+ parts.push(part);
62
+ part = [];
63
+ used = 0;
64
+ }
65
+ part.push(p);
66
+ used += size;
67
+ }
68
+ if (part.length)
69
+ parts.push(part);
70
+ return parts;
71
+ }
46
72
  /** A git that did not finish in time: stopped (SIGKILL by spawnSync), said. */
47
73
  function gitTimedOut(args, error) {
48
74
  if (error?.code !== "ETIMEDOUT")
@@ -257,7 +283,7 @@ export function ignoredOf(dir, paths) {
257
283
  }
258
284
  /** Which of these paths (files or folders) git knows — one process for all of them. */
259
285
  function trackedOf(dir, paths) {
260
- const files = runGit(dir, ["ls-files", "-z", "--", ...paths]).stdout.split("\0").filter(Boolean);
286
+ const files = pathParts(paths).flatMap((part) => runGit(dir, ["ls-files", "-z", "--", ...part]).stdout.split("\0").filter(Boolean));
261
287
  return new Set(paths.filter((p) => {
262
288
  const rel = p.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "");
263
289
  return files.some((f) => f === rel || f.startsWith(`${rel}/`));
@@ -290,8 +316,9 @@ export function commitAll(dir, message, pathspec = ["."], seal, always = false)
290
316
  const missing = pathspec.filter((p) => p !== "." && !fs.existsSync(path.join(dir, p)));
291
317
  const known = missing.length ? trackedOf(dir, missing) : new Set();
292
318
  const specs = pathspec.filter((p) => !missing.includes(p) || known.has(p));
293
- if (specs.length)
294
- git(dir, ["add", "-A", "--", ...specs]);
319
+ // in parts: a commit of a big family tree names thousands of files (pathParts)
320
+ for (const part of pathParts(specs))
321
+ git(dir, ["add", "-A", "--", ...part]);
295
322
  const tree = git(dir, ["write-tree"]).trim();
296
323
  const parent = headInfo(dir);
297
324
  if (parent && parent.tree === tree && !always)
@@ -362,15 +389,20 @@ export function showFiles(dir, rev, files) {
362
389
  }
363
390
  /** Uncommitted changes with their status codes. */
364
391
  export function changes(dir, pathspec = []) {
365
- const out = git(dir, ["status", "--porcelain=v1", "-z", "--untracked-files=all", "--", ...pathspec]);
366
- const items = out.split("\0").filter(Boolean);
367
392
  const list = [];
368
- for (let i = 0; i < items.length; i++) {
369
- const item = items[i];
370
- const code = item.slice(0, 2);
371
- list.push({ path: item.slice(3), code });
372
- if (code.startsWith("R") || code.startsWith("C"))
373
- i++;
393
+ const seen = new Set();
394
+ for (const part of pathspec.length ? pathParts(pathspec) : [[]]) {
395
+ const items = git(dir, ["status", "--porcelain=v1", "-z", "--untracked-files=all", "--", ...part]).split("\0").filter(Boolean);
396
+ for (let i = 0; i < items.length; i++) {
397
+ const item = items[i];
398
+ const code = item.slice(0, 2);
399
+ // a path two parts name (a folder and a file in it) once
400
+ if (!seen.has(item.slice(3)))
401
+ list.push({ path: item.slice(3), code });
402
+ seen.add(item.slice(3));
403
+ if (code.startsWith("R") || code.startsWith("C"))
404
+ i++;
405
+ }
374
406
  }
375
407
  return list;
376
408
  }
package/dist/core/live.js CHANGED
@@ -20,10 +20,10 @@
20
20
  // GET <token>/tree.ged the tree for the Strom app, as it is now, each entry with its image (the settings excerpts.*);
21
21
  // for an app that keeps them the bounds of a lineage the person set (_STROM_LINE, _STROM_LINES;
22
22
  // feature lineage.read: strom sync takes them back); under each _STORY (and its 2 _DRAFT) the
23
- // sources it rests on as 2 SOUR @S…@ (3 SOUR), each a record of the file — those its facts cite
24
- // and those of its background (feature story.sources); made on a thread of its own (core/liveged.ts:
25
- // new images decode whole scans, the file of a big research is tens of MB) — one making at a
26
- // time, the asks for the same file wait for it together, /status and the rest answer meanwhile
23
+ // sources it rests on as 2 SOUR @S…@ (3 SOUR), each a record of the file — those its facts cite,
24
+ // those of its background and those its text names by ID (feature story.sources); made on a
25
+ // thread of its own (core/liveged.ts: new images decode whole scans, the file of a big research
26
+ // is tens of MB) — one making at a time, the asks for the same file wait for it together, /status and the rest answer meanwhile
27
27
  // GET <token>/images.ged the same (the address an older strom gave)
28
28
  // GET <token>/log what the research saved, newest first (each commit: when, what, for which task;
29
29
  // text: its lines as the user reads them, kinds: what each is about, sources: the S… each
@@ -1372,13 +1372,13 @@ function foundNow(tree, all, h) {
1372
1372
  }
1373
1373
  /**
1374
1374
  * Who is in which line (GET /directions/people): the narrowest line first, only active and paused ones. A line of
1375
- * descendants: the descendants of its person within its generations (core/frontier.ts linePeople).
1375
+ * descendants: the descendants of its person within its generations; a question: its person (core/frontier.ts linePeople).
1376
1376
  */
1377
1377
  function directionPeople(tree, all) {
1378
1378
  const out = {};
1379
1379
  const lines = all
1380
1380
  .filter((s) => s.research.state !== "done" && !s.research.retracted)
1381
- .map((s) => ({ id: s.research.id, people: s.research.direction === "descendants" ? linePeople(tree, s.research) : s.people }))
1381
+ .map((s) => ({ id: s.research.id, people: s.research.direction === "descendants" || s.research.direction === "question" ? linePeople(tree, s.research) : s.people }))
1382
1382
  .sort((a, b) => a.people.size - b.people.size || a.id.localeCompare(b.id));
1383
1383
  for (const s of lines)
1384
1384
  for (const p of s.people.keys())
@@ -53,17 +53,25 @@ function eventOf(tree, id) {
53
53
  }
54
54
  return undefined;
55
55
  }
56
- /** The sources a version of a story rests on: those its facts cite, then those of its background. */
56
+ /**
57
+ * The sources a version of a story rests on: those its facts cite, then those of its background, then those its text
58
+ * names by their ID alone (found 2026-11-03: a source named so counted for a story written again, yet neither the Strom
59
+ * file nor strom story show gave it).
60
+ */
57
61
  export function storySources(tree, v, events) {
58
62
  const out = new Map();
59
- const add = (id, fact) => {
63
+ const add = (id, how = {}) => {
60
64
  const s = tree.get(id);
61
65
  if (!s || s.type !== "source" || s.retracted)
62
66
  return;
63
67
  const row = out.get(id) ?? { id, title: s.title, ...(s.url ? { url: s.url } : {}), facts: [], background: false };
64
- if (fact && !row.facts.includes(fact))
65
- row.facts.push(fact);
66
- if (!fact)
68
+ if (how.fact && !row.facts.includes(how.fact))
69
+ row.facts.push(how.fact);
70
+ else if (how.named) {
71
+ if (!out.has(id))
72
+ row.named = true;
73
+ }
74
+ else if (!how.fact)
67
75
  row.background = true;
68
76
  out.set(id, row);
69
77
  };
@@ -72,10 +80,12 @@ export function storySources(tree, v, events) {
72
80
  if (!e || e.retracted)
73
81
  continue;
74
82
  for (const c of e.citations)
75
- add(c.source, e.id);
83
+ add(c.source, { fact: e.id });
76
84
  }
77
85
  for (const s of v.sources ?? [])
78
86
  add(s);
87
+ for (const s of sourcesNamed(tree, words(v)))
88
+ add(s, { named: true });
79
89
  return [...out.values()];
80
90
  }
81
91
  /** A fact as one line: its kind, date and place, how sure it is. */
package/dist/core/tree.js CHANGED
@@ -31,7 +31,7 @@ export const TREE_FILE = "strom.json";
31
31
  export const SEAL_FOREIGN = "seal.foreign";
32
32
  // between releases the candidate being made (a bridge run from the sources says what it is: the Strom app goes by it);
33
33
  // at a release the release's own (package.json)
34
- export const VERSION = "1.26.0-beta.4";
34
+ export const VERSION = "1.26.0-beta.6";
35
35
  const GITIGNORE = `# Strom Research — local state and large files are not versioned
36
36
  .strom/
37
37
  /media/
@@ -970,9 +970,9 @@ export function exportGedcom(tree, opts = {}) {
970
970
  w.line(level, "DATA", clipChars([e.kind, e.date, e.place, e.value, cites ? `[${cites}]` : ""].filter(Boolean).join(" "), 200));
971
971
  }
972
972
  };
973
- // the sources it rests on — those its facts cite and those of its background — each a record of the file, so a
974
- // reader shows their titles and addresses even where the text names none (found 2026-11-03); an app that does not
975
- // read them passes them by
973
+ // the sources it rests on — those its facts cite, those of its background and those its text names by ID — each a
974
+ // record of the file, so a reader shows their titles and addresses even where the text names none (found
975
+ // 2026-11-03); an app that does not read them passes them by
976
976
  const sour = (level, v) => {
977
977
  for (const s of storySources(tree, v, eventById)) {
978
978
  if (!sourceById.has(s.id))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strom-research",
3
- "version": "1.26.0-beta.4",
3
+ "version": "1.26.0-beta.6",
4
4
  "description": "Genealogical research toolkit for AI coding agents",
5
5
  "type": "module",
6
6
  "stromLayout": 2,