strom-research 1.22.0-beta.2 → 1.22.0-beta.4
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 +16 -1
- package/CHANGELOG.de.md +20 -1
- package/CHANGELOG.md +18 -1
- package/assets/lang/cs.json +34 -1
- package/assets/lang/de.json +34 -1
- package/assets/plugins/gates/README.md +11 -0
- package/assets/plugins/gates/claude-usage/gate.json +1 -1
- package/assets/plugins/gates/claude-usage/gate.ts +57 -8
- package/dist/brief/brief.js +23 -3
- package/dist/brief/history.js +217 -0
- package/dist/cli/menu-links.js +33 -0
- package/dist/cli/menu.js +8 -6
- package/dist/cli/registry.js +3 -2
- package/dist/cli/ui.js +24 -1
- package/dist/commands/browse.js +18 -7
- package/dist/commands/checks.js +4 -4
- package/dist/commands/connectors.js +70 -11
- package/dist/commands/guide.js +2 -1
- package/dist/commands/history.js +481 -0
- package/dist/commands/index.js +1 -0
- package/dist/commands/links.js +23 -0
- package/dist/commands/read.js +10 -5
- package/dist/commands/readers.js +7 -2
- package/dist/commands/session.js +71 -7
- package/dist/commands/setup.js +22 -0
- package/dist/commands/tasks.js +53 -7
- package/dist/commands/trees.js +3 -1
- package/dist/core/config.js +11 -0
- package/dist/core/errors.js +5 -0
- package/dist/core/integrity.js +70 -2
- package/dist/core/leftalone.js +125 -0
- package/dist/core/links.js +9 -2
- package/dist/core/live.js +161 -5
- package/dist/core/logimages.js +203 -0
- package/dist/core/pack.js +23 -1
- package/dist/core/pagecheck.js +437 -0
- package/dist/core/pastevents.js +1124 -0
- package/dist/core/phrases.js +10 -0
- package/dist/core/queue.js +56 -6
- package/dist/core/reader.js +17 -0
- package/dist/core/readstats.js +84 -9
- package/dist/core/session.js +9 -0
- package/dist/core/tidy.js +156 -24
- package/dist/core/tree.js +15 -1
- package/dist/core/web.js +5 -1
- package/dist/gedcom/export.js +42 -7
- package/dist/gedcom/lines.js +5 -1
- package/dist/runners/claude.js +86 -16
- package/dist/runners/jsonl.js +13 -4
- package/package.json +1 -1
package/CHANGELOG.cs.md
CHANGED
|
@@ -7,13 +7,28 @@ Změny každé verze ve zkratce. Úplné poznámky a instalační řádky jsou n
|
|
|
7
7
|
|
|
8
8
|
## 1.22.0
|
|
9
9
|
|
|
10
|
-
*Připravuje se: bety do 1.22.0-beta.
|
|
10
|
+
*Připravuje se: bety do 1.22.0-beta.4. Oddíl bude úplný s vydáním.*
|
|
11
11
|
|
|
12
12
|
- **Jméno jednou v tom, co čeká.** Úkol k materiálu poslanému z aplikace Strom jmenoval ve widgetu a na stránce
|
|
13
13
|
telefonu každého člověka dvakrát (podruhé v hranatých závorkách) a jeho text bez jmen nechal prázdné závorky; menu,
|
|
14
14
|
`strom plan`, aplikace Strom i soubor GEDCOM ukazovaly jméno s jeho ID zopakované. Každé teď jméno řekne jednou.
|
|
15
15
|
- **Widget otevře správný výzkum.** Při několika stromech stejného jména v aplikaci Strom mohl widget na ploše Macu
|
|
16
16
|
otevřít jiný z nich; teď otevře strom svého výzkumu.
|
|
17
|
+
- **Mnohem menší logy sezení.** Logy sezení a čtenářů už neuchovávají obrázky, na které se agent díval (jen jejich
|
|
18
|
+
velikost a cestu k náhledu), takže jsou o 95–99 % menší.
|
|
19
|
+
- **Úklid, který stačí.** `strom tidy` zvládne logy jakékoli velikosti. Náhledy skenů, přerušená stahování a další,
|
|
20
|
+
co strom umí vyrobit znovu, se uklízejí i bez souhlasu; logy se pak jen zmenší, nikdy nesmažou. Po odmítnutí přijde
|
|
21
|
+
otázka ještě jednou, když `.strom` výrazně přeroste samotný výzkum.
|
|
22
|
+
- **Archiv, který neodpovídá, zastaví smyčku agenta.** `strom fetch` řekne, kdy to zkusit znovu a co dělat mezitím;
|
|
23
|
+
stejný dotaz ve stejném sezení skončí hned (exit 8) a nic neodešle. Úkol, jehož archiv má pauzu, počká mimo frontu
|
|
24
|
+
(plán ho ukáže odložený do té doby) a `strom run --loop` do té doby počká, místo aby pouštěl sezení bez práce.
|
|
25
|
+
- **Čtenáři nečekají na umlklou službu.** Čtenář, jehož agent po opakovaném pokusu služby zmlkne, se jednou obnoví
|
|
26
|
+
tam, kde skončil; když mlčí dál, hned skončí. Takový výpadek už nezmenšuje dávky čtení.
|
|
27
|
+
- **Brána týdne předplatného pustí víc sezení za sebou.** Když jednou čeká na náskok, pustí znovu až se dvěma body navíc
|
|
28
|
+
(při 15: 17), místo jednoho sezení po každém čekání.
|
|
29
|
+
- **Experiment: co předek zažil.** Pokusné a ve výchozím stavu vypnuté: události v místech stromu – dějiny kraje ze
|
|
30
|
+
stránek, které strom sám stáhl a ověřil, místní události z přečtených záznamů – ukáže aplikace Strom. Zapnout ho
|
|
31
|
+
může jen člověk; dokud je vypnuté, nic se nehledá.
|
|
17
32
|
|
|
18
33
|
## 1.21.0
|
|
19
34
|
|
package/CHANGELOG.de.md
CHANGED
|
@@ -7,7 +7,7 @@ Die Änderungen jeder Version in Kürze. Die vollständigen Hinweise und die Ins
|
|
|
7
7
|
|
|
8
8
|
## 1.22.0
|
|
9
9
|
|
|
10
|
-
*In Vorbereitung: die Betas bis 1.22.0-beta.
|
|
10
|
+
*In Vorbereitung: die Betas bis 1.22.0-beta.4. Der Abschnitt ist mit dem Release vollständig.*
|
|
11
11
|
|
|
12
12
|
- **Jeder Name einmal in dem, was wartet.** Eine Aufgabe zu Material, das aus der Strom-App gesendet wurde, nannte im
|
|
13
13
|
Widget und auf der Seite des Telefons jede Person zweimal (das zweite Mal in eckigen Klammern), und ihr Text ohne
|
|
@@ -15,6 +15,25 @@ Die Änderungen jeder Version in Kürze. Die vollständigen Hinweise und die Ins
|
|
|
15
15
|
seiner ID wiederholt. Jedes nennt den Namen jetzt einmal.
|
|
16
16
|
- **Das Widget öffnet die richtige Forschung.** Bei mehreren Stammbäumen gleichen Namens in der Strom-App konnte das
|
|
17
17
|
Widget auf dem Mac-Schreibtisch einen der anderen öffnen; jetzt öffnet es den Stammbaum seiner eigenen Forschung.
|
|
18
|
+
- **Viel kleinere Sitzungsprotokolle.** Die Protokolle der Sitzungen und Leser behalten die Bilder, die der Agent
|
|
19
|
+
angesehen hat, nicht mehr (nur ihre Größe und den Pfad der Ansicht) und sind dadurch 95–99 % kleiner.
|
|
20
|
+
- **Aufräumen, das mithält.** `strom tidy` bewältigt Protokolle jeder Größe. Ansichten von Scans, abgebrochene
|
|
21
|
+
Downloads und anderes, was strom neu erstellen kann, werden auch ohne Zustimmung aufgeräumt; Protokolle werden dann
|
|
22
|
+
nur verkleinert, nie gelöscht. Nach einem Nein kommt die Frage noch einmal, wenn `.strom` weit über die Forschung
|
|
23
|
+
hinauswächst.
|
|
24
|
+
- **Ein Archiv, das nicht antwortet, beendet die Schleife des Agenten.** `strom fetch` sagt, wann es wieder zu
|
|
25
|
+
versuchen ist und was bis dahin zu tun ist; dieselbe Anfrage in derselben Sitzung endet sofort (Exit 8) und sendet
|
|
26
|
+
nichts. Eine Aufgabe, deren Archiv pausiert, wartet bis dahin außerhalb der Warteschlange (der Plan zeigt sie bis zu
|
|
27
|
+
dieser Zeit zurückgestellt), und `strom run --loop` wartet bis dahin, statt Sitzungen ohne Arbeit zu starten.
|
|
28
|
+
- **Leser warten nicht mehr auf einen verstummten Dienst.** Ein Leser, dessen Agent nach einem erneuten Versuch seines
|
|
29
|
+
Dienstes verstummt, wird einmal dort fortgesetzt, wo er aufhörte; bleibt er still, endet er sofort. Ein solcher
|
|
30
|
+
Ausfall verkleinert die Lesestapel nicht mehr.
|
|
31
|
+
- **Das Tor der Abo-Woche lässt mehrere Sitzungen hintereinander laufen.** Wartet es einmal auf Vorsprung, lässt es
|
|
32
|
+
erst mit zwei Punkten mehr wieder los (bei 15: 17), statt einer Sitzung nach jedem Warten.
|
|
33
|
+
- **Ein Experiment: was die Vorfahren erlebten.** Experimentell und standardmäßig aus: die Ereignisse an den Orten des
|
|
34
|
+
Stammbaums – die Geschichte einer Region aus Seiten, die strom selbst geladen und geprüft hat, örtliche Ereignisse
|
|
35
|
+
aus gelesenen Einträgen – zeigt die Strom-App. Einschalten kann es nur ein Mensch; solange es aus ist, wird nichts
|
|
36
|
+
gesucht.
|
|
18
37
|
|
|
19
38
|
## 1.21.0
|
|
20
39
|
|
package/CHANGELOG.md
CHANGED
|
@@ -7,13 +7,30 @@ The changes of each version in short. The full notes and the install lines are o
|
|
|
7
7
|
|
|
8
8
|
## 1.22.0
|
|
9
9
|
|
|
10
|
-
*In preparation: the betas up to 1.22.0-beta.
|
|
10
|
+
*In preparation: the betas up to 1.22.0-beta.4. The section is complete with the release.*
|
|
11
11
|
|
|
12
12
|
- **Each name once in what waits.** A task for material sent from the Strom app named each person twice in the
|
|
13
13
|
widget and on the phone's page (the second time in brackets), and its text without names kept empty brackets; the
|
|
14
14
|
menu, `strom plan`, the Strom app and the GEDCOM file showed the name with its ID repeated. Each says the name once.
|
|
15
15
|
- **The widget opens the right research.** With several trees of one name in the Strom app, the widget on the Mac's
|
|
16
16
|
desktop could open one of the others; it now opens the tree of its own research.
|
|
17
|
+
- **Much smaller session logs.** The logs of sessions and readers no longer keep the images the agent looked at
|
|
18
|
+
(only their size and the view's path), so they are 95–99 % smaller.
|
|
19
|
+
- **Tidying that keeps up.** `strom tidy` handles logs of any size. Views of scans, downloads cut short and other
|
|
20
|
+
things strom makes again are kept in order even without a yes; logs are only made smaller then, never removed. After
|
|
21
|
+
a no, the question comes once more when `.strom` grows far beyond the research.
|
|
22
|
+
- **An archive that stops answering stops the agent's loop.** `strom fetch` says when to try again and what to do
|
|
23
|
+
meanwhile; asked again in the same session it ends at once (exit 8) and sends nothing. A task whose archive is left
|
|
24
|
+
alone waits out of the queue until then (the plan shows it put off until that time), and `strom run --loop` waits
|
|
25
|
+
for that time instead of starting sessions with nothing to do.
|
|
26
|
+
- **Readers no longer wait out a silent service.** A reader whose agent goes silent after a retry of its service is
|
|
27
|
+
resumed once where it stopped; still silent, it ends at once. Such a failure no longer makes the reading batches
|
|
28
|
+
smaller.
|
|
29
|
+
- **The gate of the subscription's week lets several sessions run in a row.** Once it waits for points in hand, it goes again only
|
|
30
|
+
with two more (at 15: 17), instead of one session after every wait.
|
|
31
|
+
- **An experiment: what the ancestors lived through.** Experimental and off by default: the events at the places of
|
|
32
|
+
the tree — the history of a region from pages strom downloaded and checked itself, local events from the records
|
|
33
|
+
read — shown by the Strom app. Only a person turns it on; while it is off, nothing is looked for.
|
|
17
34
|
|
|
18
35
|
## 1.21.0
|
|
19
36
|
|
package/assets/lang/cs.json
CHANGED
|
@@ -250,7 +250,7 @@
|
|
|
250
250
|
"ui.tune.context.none": "Kontext: nevyčistil se (čtenáři: {of})",
|
|
251
251
|
"ui.tune.context.unknown": "Vyčištění kontextu: neznámé (spotřeba se hlásí až na konci)",
|
|
252
252
|
"ui.tune.readers": "Čtenáři bez výsledku: {bad} z {n}",
|
|
253
|
-
"ui.tune.readers.halted": "Čtenáři zastavení přihlášením, limitem plánu nebo
|
|
253
|
+
"ui.tune.readers.halted": "Čtenáři zastavení přihlášením, limitem plánu, chybou nebo výpadkem služby: {n} – nepočítají se, o čtení neříkají nic",
|
|
254
254
|
"ui.tune.books": "Knihy:",
|
|
255
255
|
"ui.tune.more": " … další: {n} (všechny: --json)",
|
|
256
256
|
"ui.tune.book": " {id} {title}: skeny {scans} · pohledy na sken {vps}",
|
|
@@ -544,6 +544,8 @@
|
|
|
544
544
|
"ui.run.stop.user": "zastaveno ručně",
|
|
545
545
|
"ui.run.stop.time": "časový limit",
|
|
546
546
|
"ui.run.stop.empty": "žádné otevřené úkoly",
|
|
547
|
+
"ui.run.stop.history": "dějiny míst počkají do zítřka: bez podmínky (run.gate) jedno sezení denně, nic jiného k práci",
|
|
548
|
+
"ui.run.stop.asleep": "do {at} není co dělat – zbylé úkoly potřebují {host}, který teď neodpovídá",
|
|
547
549
|
"ui.run.stop.problems": "doklady mají problém – strom check",
|
|
548
550
|
"ui.run.stop.denied": "agent nesměl spouštět strom – nepustila ho jeho oprávnění nebo sandbox; nic dalšího se nespustilo",
|
|
549
551
|
"ui.run.stop.limit": "limit předplatného{resets}",
|
|
@@ -720,6 +722,16 @@
|
|
|
720
722
|
"archive.held": "odloženo: výzkum je Archiv Stromu (data přicházejí z aplikace Strom); do fronty se vrátí, až se zapne práce s agentem",
|
|
721
723
|
"archive.removed": "odebráno v aplikaci Strom",
|
|
722
724
|
"archive.wait": "Rozhodnutí o stahování z archivu {title}",
|
|
725
|
+
"history.why.archive": "Dokud je výzkum vedený jako archiv, nic se nehledá.",
|
|
726
|
+
"history.why.held": "Události regionu {region} hledá jiný výzkum na tomto počítači.",
|
|
727
|
+
"history.places.what": "Místa údajů pro dějiny předků ({n}): regiony, kam které patřilo, i s roky",
|
|
728
|
+
"history.places.why": "události dějin (války, epidemie, sčítání lidu, změny státu) se ukazují u míst údajů podle regionů, kam patřila – pokus",
|
|
729
|
+
"history.places.done": "každé místo přiřazené k regionům i s roky, nebo označené jako nedohledané",
|
|
730
|
+
"history.region.what": "Události dějin v regionu {region}: války, epidemie, sčítání lidu, změny státu, vystěhovalectví",
|
|
731
|
+
"history.region.where": "encyklopedie, státní instituce, archivy, Wikipedie v jazyce regionu s jejími odkazy",
|
|
732
|
+
"history.region.why": "co předkové zažili, ukázané u jejich životů – pokus",
|
|
733
|
+
"history.region.done": "důležité události období nalezené, každá ze stránky, kterou strom sám přečetl (nanejvýš asi 60); katalog regionu označený jako hotový",
|
|
734
|
+
"history.region.finished": "události regionu {region} jsou hotové",
|
|
723
735
|
"review.reread.what": "Přečíst znovu modelem {model}, o co se opírají údaje osoby {name}: {list}{more}",
|
|
724
736
|
"review.reread.why": "tyto zápisy četl jen jiný model; {model} je ten, kterým uživatel čte teď ({research})",
|
|
725
737
|
"review.reread.done": "zápis každého údaje přečtený naslepo modelem {model} (strom read M… --blind): shoda → poznámka u údaje; rozdíl → rozpor s oběma čteními",
|
|
@@ -1124,6 +1136,7 @@
|
|
|
1124
1136
|
"ui.tidy.no": "Nic se nesmazalo.",
|
|
1125
1137
|
"ui.consent.tidy": "Uvolnit asi {size} vedle výzkumu {name} (staré záznamy sezení, náhledy skenů, dávno zapsaná poslání)? Výzkum i jeho skeny zůstanou.",
|
|
1126
1138
|
"ui.tidy.first": "Vedle výzkumu se nastřádalo, co jde uvolnit, asi {size} (záznamy práce, náhledy snímků a podobně – nikdy výzkum). Ukazuje se tu jednou; později v menu Nastavení → Údržba → Místo na disku.",
|
|
1139
|
+
"ui.tidy.again": "Co si strom drží vedle výzkumu, narostlo na {strom} (samotný výzkum má {research}); uvolnit jde asi {size} (hlavně záznamy práce – nikdy výzkum). Ukazuje se tu ještě jednou, naposledy; později v menu Nastavení → Údržba → Místo na disku.",
|
|
1127
1140
|
"ui.tidy.hint": "Vedle výzkumu si strom drží {strom}, z toho jde uvolnit {size}: strom tidy (v menu Nastavení → Údržba → Místo na disku)",
|
|
1128
1141
|
"ui.error.consent": "tady je potřeba souhlas – {question}",
|
|
1129
1142
|
"ui.error.consent.hint": "spustit ve vlastním terminálu: {set}",
|
|
@@ -1153,6 +1166,10 @@
|
|
|
1153
1166
|
"ui.recent.more": "… a další: {n}",
|
|
1154
1167
|
"ui.recent.morechanges": "(a další změny: {n})",
|
|
1155
1168
|
"ui.history.none": "historie je zatím prázdná",
|
|
1169
|
+
"ui.history.past.hidden": "Skryto: {event} – {where}",
|
|
1170
|
+
"ui.history.past.shown": "Znovu zobrazeno: {event} – {where}",
|
|
1171
|
+
"ui.history.past.same": "Beze změny: {event} – {where}",
|
|
1172
|
+
"ui.history.past.redo": "Události regionu {region} se budou hledat znovu (nalezené zůstávají).",
|
|
1156
1173
|
"ui.browse.plan": "Co agent udělá dál",
|
|
1157
1174
|
"ui.review.new": "{name} — {n, plural, one {# nový úkol} few {# nové úkoly} other {# nových úkolů}}:",
|
|
1158
1175
|
"ui.review.nothing": "{name} — nic nového k revizi",
|
|
@@ -1642,6 +1659,8 @@
|
|
|
1642
1659
|
"ui.plan.title": "Co agent udělá dál – {name}:",
|
|
1643
1660
|
"ui.plan.now": "právě teď",
|
|
1644
1661
|
"ui.plan.images": " (nejdřív potřebuje snímky)",
|
|
1662
|
+
"ui.plan.later": "později",
|
|
1663
|
+
"ui.plan.asleep": " (odloženo do {at}: {host} teď neodpovídá)",
|
|
1645
1664
|
"ui.plan.more": "… a další úkoly: {n}",
|
|
1646
1665
|
"ui.plan.stories": "Potom vyprávění: {n} ({names})",
|
|
1647
1666
|
"ui.plan.waiting": "Čeká: {count} · v menu: Co čeká",
|
|
@@ -1670,6 +1689,8 @@
|
|
|
1670
1689
|
"ui.run.beside.sure": "Spustit další vedle něj?",
|
|
1671
1690
|
"ui.run.gate": "· podmínka: {name} — ptá se před každým sezením; běh může nechat čekat",
|
|
1672
1691
|
"ui.run.gate.wait": "⏸ čekám do {at} — {reason} (Ctrl-C běh ukončí)",
|
|
1692
|
+
"ui.run.asleep.wait": "⏸ čekám do {at} – zbylé úkoly potřebují {host}, který teď neodpovídá (Ctrl-C běh ukončí)",
|
|
1693
|
+
"ui.run.asleep.why": "{host} teď neodpovídá",
|
|
1673
1694
|
"ui.run.stop.gate": "podmínka „{name}“ řekla dost — {reason}",
|
|
1674
1695
|
"ui.run.stop.gate.error": "podmínka „{name}“ neodpověděla, jak má — {reason} (strom gate test)",
|
|
1675
1696
|
"ui.run.gate.once": "· podmínka: {name} — tyto úkoly jsou spuštěné ručně: zeptám se jí jednou, a kdyby nespouštěla, přijde otázka, zda přesto začít",
|
|
@@ -1698,6 +1719,7 @@
|
|
|
1698
1719
|
"ui.archives.agentbrowser.off": "Vrátit prohlížeč jen pro archivy přes prohlížeč?",
|
|
1699
1720
|
"ui.consent.remote": "Spouštět sezení Claude Code, která strom otevírá, se vzdáleným ovládáním (Remote Control), aby je šlo sledovat a řídit z claude.ai nebo z aplikace Claude v telefonu?",
|
|
1700
1721
|
"ui.consent.addons": "Dovolit agentovi při samostatné práci načíst osobní doplňky z jeho nastavení (skilly, pluginy, MCP servery – třeba i poštu nebo dokumenty) jako v chatu? Pracuje přitom bez dozoru.",
|
|
1722
|
+
"ui.consent.history": "Hledat události dějin v místech všech výzkumů na tomto počítači – války, epidemie, sčítání, změny státu? Experiment: agent je hledá, jen když rodinný výzkum nemá co dělat, a stojí to jeho čas i čerpání předplatného.",
|
|
1701
1723
|
"ui.consent.effort": "Nastavit sezením {agent}, která spouští strom, hloubku uvažování {effort}? Vyšší hloubka uvažování (high, xhigh) rychleji spotřebuje limity předplatného.",
|
|
1702
1724
|
"ui.consent.webPerHost": "Dovolit vlastnímu webovému nástroji agenta až {n, plural, one {# požadavek} few {# požadavky} other {# požadavků}} na jeden web (jeho servery a zrcadla dohromady) v sezení (nyní {now})? Více požadavků víc zatěžuje web; více stránek jednoho webu je šetrnější stahovat přes konektor.",
|
|
1703
1725
|
"ui.consent.effort.run": "Spustit samostatnou práci {agent} pro tento běh s hloubkou uvažování {effort}, vyšší než v nastavení ({now})? Vyšší hloubka uvažování (high, xhigh) rychleji spotřebuje limity předplatného.",
|
|
@@ -2648,6 +2670,17 @@
|
|
|
2648
2670
|
"ui.archives.permissions.title": "Archivy stahovačů na tomto počítači – co platí pro jejich snímky:",
|
|
2649
2671
|
"ui.archives.state.way": "{way}, rozhodnuto {date}",
|
|
2650
2672
|
"ui.link.archive.none": "O tomto archivu tu není co rozhodnout. Nic se nestalo.",
|
|
2673
|
+
"ui.experiments.link": "Hledání událostí dějin se zapíná jen v terminálu, který otevře odkaz.",
|
|
2674
|
+
"ui.link.what.experiment.history": "hledat události dějin v místech tohoto stromu – války, epidemie, sčítání, změny státu",
|
|
2675
|
+
"ui.link.experiment.note": "Experiment: hledá se jen tehdy, když rodinný výzkum nemá co dělat, nejvýš jedno sezení denně do {minutes} minut.",
|
|
2676
|
+
"ui.link.experiment.note.gate": "Experiment: hledá se jen tehdy, když rodinný výzkum nemá co dělat; kdy, rozhoduje brána běhů, sezení trvá nejvýš {minutes} minut.",
|
|
2677
|
+
"ui.link.experiment.all": "Zapíná se v nastavení tohoto počítače: platí pro všechny výzkumy na něm (každý jde vypnout zvlášť).",
|
|
2678
|
+
"ui.link.experiment.on.done": "Hledání událostí dějin je pro tento výzkum zapnuté.",
|
|
2679
|
+
"ui.link.experiment.on.already": "Hledání událostí dějin je pro tento výzkum zapnuté už. Nic se nestalo.",
|
|
2680
|
+
"ui.link.experiment.off.done": "Hledání událostí dějin je pro tento výzkum vypnuté; co už bylo nalezeno, zůstává.",
|
|
2681
|
+
"ui.link.experiment.off.already": "Hledání událostí dějin je pro tento výzkum vypnuté už. Nic se nestalo.",
|
|
2682
|
+
"ui.link.experiment.archive": "Dokud je výzkum vedený jako archiv, události dějin se nehledají. Nic se nestalo.",
|
|
2683
|
+
"ui.link.experiment.waiting": "Na tomto výzkumu se na tomto počítači nepracuje, a tak se události dějin nehledají. Nic se nestalo.",
|
|
2651
2684
|
"ui.error.archive.permission": "stahování snímků z archivu {title} ({hosts}) čeká na rozhodnutí – podmínky archivu automatické stahování omezují; z archivu se nic nestahovalo",
|
|
2652
2685
|
"ui.error.archive.permission.new": "stahování snímků z archivu {title} ({hosts}) čeká na rozhodnutí – čtení podmínek stahovačem zatím nikdo nepotvrdil; z archivu se nic nestahovalo",
|
|
2653
2686
|
"ui.error.archive.permission.hint": "rozhodnout v menu strom (Co čeká), nebo v terminálu: strom allow archive {host} --way {ways}",
|
package/assets/lang/de.json
CHANGED
|
@@ -250,7 +250,7 @@
|
|
|
250
250
|
"ui.tune.context.none": "Kontext: nicht geleert (Leser: {of})",
|
|
251
251
|
"ui.tune.context.unknown": "Leeren des Kontexts: unbekannt (der Verbrauch wird erst am Ende genannt)",
|
|
252
252
|
"ui.tune.readers": "Leser ohne Ergebnis: {bad} von {n}",
|
|
253
|
-
"ui.tune.readers.halted": "Leser, die eine Anmeldung, das Limit des Plans oder ein
|
|
253
|
+
"ui.tune.readers.halted": "Leser, die eine Anmeldung, das Limit des Plans, ein Fehler oder ein Ausfall des Dienstes gestoppt hat: {n} – nicht gezählt, nichts über das Lesen",
|
|
254
254
|
"ui.tune.books": "Bücher:",
|
|
255
255
|
"ui.tune.more": " … weitere: {n} (alle: --json)",
|
|
256
256
|
"ui.tune.book": " {id} {title}: Scans {scans} · Ansichten pro Scan {vps}",
|
|
@@ -544,6 +544,8 @@
|
|
|
544
544
|
"ui.run.stop.user": "von Hand angehalten",
|
|
545
545
|
"ui.run.stop.time": "Zeitlimit",
|
|
546
546
|
"ui.run.stop.empty": "keine offenen Aufgaben",
|
|
547
|
+
"ui.run.stop.history": "die Geschichte der Orte wartet bis morgen: ohne Bedingung (run.gate) eine Sitzung am Tag, sonst nichts zu tun",
|
|
548
|
+
"ui.run.stop.asleep": "bis {at} nichts zu tun – die übrigen Aufgaben brauchen {host}, der gerade nicht antwortet",
|
|
547
549
|
"ui.run.stop.problems": "die Belege haben Probleme – strom check",
|
|
548
550
|
"ui.run.stop.denied": "der Agent durfte strom nicht starten – seine Berechtigungen oder seine Sandbox ließen es nicht zu; nichts weiter wurde gestartet",
|
|
549
551
|
"ui.run.stop.limit": "Limit des Abonnements{resets}",
|
|
@@ -720,6 +722,16 @@
|
|
|
720
722
|
"archive.held": "zurückgestellt: die Forschung ist ein Strom-Archiv (die Daten kommen aus der Strom-App); zurück in der Warteschlange, wenn die Arbeit mit einem Agenten eingeschaltet wird",
|
|
721
723
|
"archive.removed": "in der Strom-App entfernt",
|
|
722
724
|
"archive.wait": "Entscheidung über das Herunterladen aus dem Archiv {title}",
|
|
725
|
+
"history.why.archive": "Solange die Forschung als Archiv geführt wird, wird nichts gesucht.",
|
|
726
|
+
"history.why.held": "Die Ereignisse von {region} sucht eine andere Forschung auf diesem Computer.",
|
|
727
|
+
"history.places.what": "Die Orte der Angaben für die Geschichte der Vorfahren ({n}): zu welchen Regionen jeder gehörte, mit den Jahren",
|
|
728
|
+
"history.places.why": "die Ereignisse der Geschichte (Kriege, Epidemien, Volkszählungen, Wechsel des Staates) erscheinen an den Orten der Angaben nach den Regionen, zu denen sie gehörten – ein Experiment",
|
|
729
|
+
"history.places.done": "jeder Ort seinen Regionen mit den Jahren zugeordnet oder als nicht auffindbar vermerkt",
|
|
730
|
+
"history.region.what": "Ereignisse der Geschichte in {region}: Kriege, Epidemien, Volkszählungen, Wechsel des Staates, Auswanderung",
|
|
731
|
+
"history.region.where": "Enzyklopädien, staatliche Institutionen, Archive, die Wikipedia in der Sprache der Region mit ihren Belegen",
|
|
732
|
+
"history.region.why": "was die Vorfahren erlebten, bei ihren Lebensläufen gezeigt – ein Experiment",
|
|
733
|
+
"history.region.done": "die wichtigen Ereignisse des Zeitraums gefunden, jedes von einer Seite, die strom selbst gelesen hat (höchstens etwa 60); der Katalog der Region als fertig vermerkt",
|
|
734
|
+
"history.region.finished": "die Ereignisse von {region} sind fertig",
|
|
723
735
|
"review.reread.what": "Mit {model} neu lesen, worauf die Angaben von {name} beruhen: {list}{more}",
|
|
724
736
|
"review.reread.why": "diese Einträge hat nur ein anderes Modell gelesen; mit {model} liest der Nutzer jetzt ({research})",
|
|
725
737
|
"review.reread.done": "der Eintrag jeder Angabe blind mit {model} gelesen (strom read M… --blind): übereinstimmend → Notiz an der Angabe; abweichend → ein Widerspruch mit beiden Lesungen",
|
|
@@ -1124,6 +1136,7 @@
|
|
|
1124
1136
|
"ui.tidy.no": "Nichts wurde gelöscht.",
|
|
1125
1137
|
"ui.consent.tidy": "Etwa {size} neben der Forschung {name} freigeben (alte Sitzungsprotokolle, Ansichten von Scans, längst geschriebene Sendungen)? Die Forschung und ihre Scans bleiben.",
|
|
1126
1138
|
"ui.tidy.first": "Neben der Forschung hat sich angesammelt, was freigegeben werden kann, etwa {size} (Protokolle, Ansichten von Scans und Ähnliches – nie die Forschung). Wird hier einmal gezeigt; später im Menü Einstellungen → Wartung → Speicherplatz.",
|
|
1139
|
+
"ui.tidy.again": "Was strom neben der Forschung hält, ist auf {strom} angewachsen (die Forschung selbst: {research}); davon lassen sich etwa {size} freigeben (vor allem Protokolle der Arbeit – nie die Forschung). Wird hier noch ein letztes Mal gezeigt; später im Menü Einstellungen → Wartung → Speicherplatz.",
|
|
1127
1140
|
"ui.tidy.hint": "Neben der Forschung hält strom {strom}, davon lassen sich {size} freigeben: strom tidy (im Menü Einstellungen → Wartung → Speicherplatz)",
|
|
1128
1141
|
"ui.error.consent": "dafür braucht es eine Zustimmung – {question}",
|
|
1129
1142
|
"ui.error.consent.hint": "im eigenen Terminal ausführen: {set}",
|
|
@@ -1153,6 +1166,10 @@
|
|
|
1153
1166
|
"ui.recent.more": "… und {n} weitere",
|
|
1154
1167
|
"ui.recent.morechanges": "(und weitere Änderungen: {n})",
|
|
1155
1168
|
"ui.history.none": "der Verlauf ist noch leer",
|
|
1169
|
+
"ui.history.past.hidden": "Ausgeblendet: {event} – {where}",
|
|
1170
|
+
"ui.history.past.shown": "Wieder angezeigt: {event} – {where}",
|
|
1171
|
+
"ui.history.past.same": "Unverändert: {event} – {where}",
|
|
1172
|
+
"ui.history.past.redo": "Die Ereignisse von {region} werden erneut gesucht (die gefundenen bleiben).",
|
|
1156
1173
|
"ui.browse.plan": "Was der Agent als Nächstes tut",
|
|
1157
1174
|
"ui.review.new": "{name} — {n, plural, one {# neue Aufgabe} other {# neue Aufgaben}}:",
|
|
1158
1175
|
"ui.review.nothing": "{name} — nichts Neues zu prüfen",
|
|
@@ -1642,6 +1659,8 @@
|
|
|
1642
1659
|
"ui.plan.title": "Was der Agent als Nächstes tut – {name}:",
|
|
1643
1660
|
"ui.plan.now": "gerade jetzt",
|
|
1644
1661
|
"ui.plan.images": " (braucht zuerst die Scans)",
|
|
1662
|
+
"ui.plan.later": "später",
|
|
1663
|
+
"ui.plan.asleep": " (zurückgestellt bis {at}: {host} antwortet gerade nicht)",
|
|
1645
1664
|
"ui.plan.more": "… und {n, plural, one {# weitere Aufgabe} other {# weitere Aufgaben}}",
|
|
1646
1665
|
"ui.plan.stories": "Danach die Geschichten: {n} ({names})",
|
|
1647
1666
|
"ui.plan.waiting": "Wartet: {count} · im Menü: Was wartet",
|
|
@@ -1670,6 +1689,8 @@
|
|
|
1670
1689
|
"ui.run.beside.sure": "Einen weiteren daneben starten?",
|
|
1671
1690
|
"ui.run.gate": "· Bedingung: {name} — vor jeder Sitzung gefragt; sie kann den Lauf warten lassen",
|
|
1672
1691
|
"ui.run.gate.wait": "⏸ warte bis {at} — {reason} (Strg-C beendet den Lauf)",
|
|
1692
|
+
"ui.run.asleep.wait": "⏸ warte bis {at} — die übrigen Aufgaben brauchen {host}, der gerade nicht antwortet (Strg-C beendet den Lauf)",
|
|
1693
|
+
"ui.run.asleep.why": "{host} antwortet gerade nicht",
|
|
1673
1694
|
"ui.run.stop.gate": "die Bedingung „{name}“ sagte Halt — {reason}",
|
|
1674
1695
|
"ui.run.stop.gate.error": "die Bedingung „{name}“ gab keine gültige Antwort — {reason} (strom gate test)",
|
|
1675
1696
|
"ui.run.gate.once": "· Bedingung: {name} — diese Aufgaben sind von Hand gestartet: sie wird einmal gefragt, und würde sie nicht starten, wird nachgefragt",
|
|
@@ -1698,6 +1719,7 @@
|
|
|
1698
1719
|
"ui.archives.agentbrowser.off": "Zurück zum Browser nur für Archive über den Browser?",
|
|
1699
1720
|
"ui.consent.remote": "Die Claude-Code-Sitzungen, die strom öffnet, mit Remote Control starten, damit sie sich auf claude.ai oder in der Claude-App auf dem Telefon verfolgen und steuern lassen?",
|
|
1700
1721
|
"ui.consent.addons": "Dem allein arbeitenden Agenten erlauben, die persönlichen Erweiterungen aus seinen Einstellungen zu laden (Skills, Plugins, MCP-Server – auch E-Mail oder Dokumente), wie im Chat? Er arbeitet dabei unbeaufsichtigt.",
|
|
1722
|
+
"ui.consent.history": "Die Ereignisse der Geschichte an den Orten aller Forschungen auf diesem Computer suchen – Kriege, Epidemien, Volkszählungen, Änderungen des Staates? Ein Experiment: der Agent sucht sie nur, wenn die Familienforschung nichts zu tun hat, und es kostet seine Zeit und die Nutzung des Abos.",
|
|
1701
1723
|
"ui.consent.effort": "Den Sitzungen von {agent}, die strom startet, den Denkaufwand {effort} geben? Ein höherer Denkaufwand (high, xhigh) verbraucht die Limits des Abonnements schneller.",
|
|
1702
1724
|
"ui.consent.webPerHost": "Dem eigenen Webabruf des Agenten bis zu {n, plural, one {# Anfrage} other {# Anfragen}} an eine Website (ihre Server und Spiegel zusammen) in einer Sitzung erlauben (jetzt {now})? Mehr Anfragen belasten die Website stärker; mehr Seiten einer Website gehen schonender über einen Connector.",
|
|
1703
1725
|
"ui.consent.effort.run": "{agent} für diesen Lauf mit dem Denkaufwand {effort} allein arbeiten lassen, höher als in der Einstellung ({now})? Ein höherer Denkaufwand (high, xhigh) verbraucht die Limits des Abonnements schneller.",
|
|
@@ -2648,6 +2670,17 @@
|
|
|
2648
2670
|
"ui.archives.permissions.title": "Die Archive der Downloader auf diesem Computer – was für ihre Bilder gilt:",
|
|
2649
2671
|
"ui.archives.state.way": "{way}, entschieden am {date}",
|
|
2650
2672
|
"ui.link.archive.none": "Über dieses Archiv gibt es hier nichts zu entscheiden. Es ist nichts geschehen.",
|
|
2673
|
+
"ui.experiments.link": "Die Suche nach den Ereignissen der Geschichte wird nur im Terminal eingeschaltet, das der Link öffnet.",
|
|
2674
|
+
"ui.link.what.experiment.history": "die Ereignisse der Geschichte an den Orten dieses Stammbaums suchen – Kriege, Epidemien, Volkszählungen, Änderungen des Staates",
|
|
2675
|
+
"ui.link.experiment.note": "Ein Experiment: gesucht wird nur, wenn die Familienforschung nichts zu tun hat, höchstens eine Sitzung am Tag bis {minutes} Minuten.",
|
|
2676
|
+
"ui.link.experiment.note.gate": "Ein Experiment: gesucht wird nur, wenn die Familienforschung nichts zu tun hat; wann, entscheidet das Tor der Läufe, eine Sitzung dauert höchstens {minutes} Minuten.",
|
|
2677
|
+
"ui.link.experiment.all": "Es wird in den Einstellungen dieses Computers eingeschaltet: für alle Forschungen darauf (jede lässt sich einzeln ausschalten).",
|
|
2678
|
+
"ui.link.experiment.on.done": "Die Suche nach den Ereignissen der Geschichte ist für diese Forschung eingeschaltet.",
|
|
2679
|
+
"ui.link.experiment.on.already": "Die Suche nach den Ereignissen der Geschichte ist für diese Forschung schon eingeschaltet. Es ist nichts geschehen.",
|
|
2680
|
+
"ui.link.experiment.off.done": "Die Suche nach den Ereignissen der Geschichte ist für diese Forschung ausgeschaltet; was gefunden wurde, bleibt.",
|
|
2681
|
+
"ui.link.experiment.off.already": "Die Suche nach den Ereignissen der Geschichte ist für diese Forschung schon ausgeschaltet. Es ist nichts geschehen.",
|
|
2682
|
+
"ui.link.experiment.archive": "Solange die Forschung als Archiv geführt wird, wird nach Ereignissen der Geschichte nicht gesucht. Es ist nichts geschehen.",
|
|
2683
|
+
"ui.link.experiment.waiting": "An dieser Forschung wird auf diesem Computer nicht gearbeitet, daher wird nach Ereignissen der Geschichte nicht gesucht. Es ist nichts geschehen.",
|
|
2651
2684
|
"ui.error.archive.permission": "das Herunterladen von Bildern aus dem Archiv {title} ({hosts}) wartet auf eine Entscheidung – seine Bedingungen schränken das automatische Herunterladen ein; beim Archiv wurde nichts angefragt",
|
|
2652
2685
|
"ui.error.archive.permission.new": "das Herunterladen von Bildern aus dem Archiv {title} ({hosts}) wartet auf eine Entscheidung – die Lesart der Bedingungen durch den Downloader hat noch niemand bestätigt; beim Archiv wurde nichts angefragt",
|
|
2653
2686
|
"ui.error.archive.permission.hint": "im Menü von strom entscheiden (Was wartet) oder im Terminal: strom allow archive {host} --way {ways}",
|
|
@@ -29,6 +29,10 @@ the gates here. `strom config unset run.gate`: no gate.
|
|
|
29
29
|
is strom's own Node (TypeScript runs as it is) — best on every system. What
|
|
30
30
|
the user gives the gate after its name (`run.gate "my-gate 20 night"`) is
|
|
31
31
|
added to these arguments.
|
|
32
|
+
|
|
33
|
+
What a gate remembers between askings it keeps in its own folder (strom asks it
|
|
34
|
+
there): strom never touches a file there but those of the gates it ships
|
|
35
|
+
(`gate.json`, `gate.ts`).
|
|
32
36
|
- `timeout`: seconds it may take (default 120). No answer in time: an error.
|
|
33
37
|
|
|
34
38
|
## The answer
|
|
@@ -124,6 +128,13 @@ starts at once); never past the reset. Every answer says when the week resets
|
|
|
124
128
|
("weekly reset in 1.7 h"). A used-up session: until it resets. Another agent
|
|
125
129
|
than Claude Code: it lets the work go on.
|
|
126
130
|
|
|
131
|
+
Once it waited for want of points in hand, it goes again only with 2 more (at
|
|
132
|
+
15: 17 in hand; early in the week its share, as the number's), and then goes
|
|
133
|
+
until fewer than the number are in hand: several sessions in a row instead of
|
|
134
|
+
one after every wait ("until 17 in hand, then several sessions in a row"). It
|
|
135
|
+
remembers the week it waits in (`hold.json` in its folder); a new week starts
|
|
136
|
+
free.
|
|
137
|
+
|
|
127
138
|
**A cap** — your own hard stop for the week:
|
|
128
139
|
|
|
129
140
|
strom config set run.gate "claude-usage 10 --cap 95"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"interface": 1,
|
|
3
3
|
"title": "Claude usage",
|
|
4
|
-
"description": "Keeps working alone to the daily ration of your Claude subscription: a session starts only while the week's usage is at least n points behind the share of the week gone (a day ≈ 14.3; early in the week half the share gone, so a new week starts at once; in its last 2 hours what is left goes when it holds a session): strom config set run.gate \"claude-usage 10\" (without a number: 0). A cap: \"claude-usage 10 --cap 95\" — at 95 % of the week no session starts, in any run, and no \"start anyway\" goes past it.",
|
|
4
|
+
"description": "Keeps working alone to the daily ration of your Claude subscription: a session starts only while the week's usage is at least n points behind the share of the week gone (a day ≈ 14.3; early in the week half the share gone, so a new week starts at once; in its last 2 hours what is left goes when it holds a session; once it waited, it goes again only with 2 more in hand, then for several sessions in a row): strom config set run.gate \"claude-usage 10\" (without a number: 0). A cap: \"claude-usage 10 --cap 95\" — at 95 % of the week no session starts, in any run, and no \"start anyway\" goes past it.",
|
|
5
5
|
"command": [
|
|
6
6
|
"node",
|
|
7
7
|
"gate.ts"
|
|
@@ -22,6 +22,12 @@
|
|
|
22
22
|
// END_WINDOW (with room for a session), its reset (a new week starts at once) —
|
|
23
23
|
// never past the reset. A full session: until it resets.
|
|
24
24
|
//
|
|
25
|
+
// Once it waited for want of points in hand, it goes again only with RESERVE
|
|
26
|
+
// more (at 15: 17), and then goes until fewer than the number are in hand — so
|
|
27
|
+
// several sessions run in a row, not one after each wait. The reserve grows
|
|
28
|
+
// with the week as the number does. Run by strom (STROM_GATE), the gate keeps
|
|
29
|
+
// the week it waits in in its own folder (hold.json); a new week starts free.
|
|
30
|
+
//
|
|
25
31
|
// A cap (strom config set run.gate "claude-usage 15 --cap 95"): at 95 % of the
|
|
26
32
|
// week used no session starts — the user's own hard stop, asked before every
|
|
27
33
|
// session of every run, and no "start anyway" goes past it; a session at work
|
|
@@ -31,6 +37,7 @@
|
|
|
31
37
|
//
|
|
32
38
|
// strom writes this file; a copy of your own goes into a folder of its own name.
|
|
33
39
|
|
|
40
|
+
import fs from "node:fs";
|
|
34
41
|
import { spawnSync } from "node:child_process";
|
|
35
42
|
|
|
36
43
|
const DAY = 86_400_000;
|
|
@@ -49,6 +56,14 @@ const END_WINDOW = 2 * 3_600_000;
|
|
|
49
56
|
const SESSION_POINTS = 10;
|
|
50
57
|
/** After the reset the gate asks again this much later, so the new week is what Claude Code says. */
|
|
51
58
|
const AFTER_RESET = 60_000;
|
|
59
|
+
/**
|
|
60
|
+
* Once it waited for want of points in hand, this many more are needed before it goes again (with the full number;
|
|
61
|
+
* early in the week its share, as the number's): a session takes about a point of the week, so the work goes on in
|
|
62
|
+
* runs of a few sessions instead of one after every wait — each session reads its brief anew. With no number too.
|
|
63
|
+
*/
|
|
64
|
+
const RESERVE = 2;
|
|
65
|
+
/** The week it waits in for the reserve, in the gate's own folder — only when strom asks it (STROM_GATE). */
|
|
66
|
+
const HOLD = process.env.STROM_GATE ? "hold.json" : undefined;
|
|
52
67
|
const lang = (process.env.STROM_LANG ?? "en").slice(0, 2);
|
|
53
68
|
|
|
54
69
|
const T: Record<string, Record<string, string>> = {
|
|
@@ -58,7 +73,7 @@ const T: Record<string, Record<string, string>> = {
|
|
|
58
73
|
head: "week {used} % used, {gone} % gone, {behind} in hand (at least {min} needed{early})",
|
|
59
74
|
early: " — half the week gone, early in the week",
|
|
60
75
|
resetIn: "; weekly reset in {reset}",
|
|
61
|
-
|
|
76
|
+
hold: " — until {target} in hand, then several sessions in a row; weekly reset in {reset}",
|
|
62
77
|
last: " — until the last {window} before the weekly reset in {reset}",
|
|
63
78
|
reset: " — until the weekly reset in {reset}",
|
|
64
79
|
end: "week {used} % used, weekly reset in {reset} — the {room} % left is enough for a session",
|
|
@@ -78,7 +93,7 @@ const T: Record<string, Record<string, string>> = {
|
|
|
78
93
|
head: "týden: využito {used} %, uplynulo {gone} %, náskok {behind} (potřeba aspoň {min}{early})",
|
|
79
94
|
early: " – na začátku týdne polovina uplynulého",
|
|
80
95
|
resetIn: "; týden se obnoví za {reset}",
|
|
81
|
-
|
|
96
|
+
hold: " — čeká na náskok {target}, pak víc sezení za sebou; týden se obnoví za {reset}",
|
|
82
97
|
last: " — do posledních {window} před obnovením týdne za {reset}",
|
|
83
98
|
reset: " — do obnovení týdne za {reset}",
|
|
84
99
|
end: "týden: využito {used} %, obnoví se za {reset} — zbylých {room} % stačí na sezení",
|
|
@@ -98,7 +113,7 @@ const T: Record<string, Record<string, string>> = {
|
|
|
98
113
|
head: "Woche: {used} % genutzt, {gone} % vergangen, Vorsprung {behind} (mindestens {min} nötig{early})",
|
|
99
114
|
early: " – am Wochenanfang die Hälfte des Vergangenen",
|
|
100
115
|
resetIn: "; Wochen-Reset in {reset}",
|
|
101
|
-
|
|
116
|
+
hold: " — wartet auf Vorsprung {target}, dann mehrere Sitzungen am Stück; Wochen-Reset in {reset}",
|
|
102
117
|
last: " — bis zu den letzten {window} vor dem Wochen-Reset in {reset}",
|
|
103
118
|
reset: " — bis zum Wochen-Reset in {reset}",
|
|
104
119
|
end: "Woche: {used} % genutzt, Wochen-Reset in {reset} — die übrigen {room} % reichen für eine Sitzung",
|
|
@@ -188,22 +203,56 @@ const reset = inTime(resets - now);
|
|
|
188
203
|
// shown rounded down: never "15 in hand (at least 15 needed)" for 14.6 — and gone − used stays what it says; the
|
|
189
204
|
// need early in the week is a fraction: rounded down when it goes, up when it waits, so the two never seem to disagree
|
|
190
205
|
const v = { used: Math.floor(week.used), gone: Math.floor(gone), behind: Math.floor(behind), early, reset };
|
|
206
|
+
// the reserve once it waited: grown with the week as the number is (its share of the need), whole with no number
|
|
207
|
+
const reserve = min > 0 ? (RESERVE * need) / min : RESERVE;
|
|
208
|
+
const held = holding(resets);
|
|
191
209
|
if (session && session.used >= 100) answer(1, say("session", { reset }), session.resets ? new Date(session.resets.getTime() + AFTER_RESET) : undefined);
|
|
192
|
-
if (behind >= need
|
|
210
|
+
if (behind >= need + (held ? reserve : 0)) {
|
|
211
|
+
hold(undefined);
|
|
212
|
+
answer(0, say("head", { ...v, min: Math.floor(need) }) + say("resetIn", { reset }));
|
|
213
|
+
}
|
|
193
214
|
// what is left before the reset: (to the cap, else to 100 %) enough for a session — in the week's last stretch it goes
|
|
194
215
|
const room = (cap ?? 100) - week.used;
|
|
195
216
|
const fits = room >= SESSION_POINTS;
|
|
196
217
|
if (fits && resets - now <= END_WINDOW) answer(0, say("end", { used: v.used, reset, room: Math.floor(room) }));
|
|
197
|
-
//
|
|
198
|
-
|
|
218
|
+
// it waits for want of points in hand: from now on it goes again only with the reserve too
|
|
219
|
+
if (!held) hold(resets);
|
|
220
|
+
// else it waits for the first of: the week caught up with the reserve (gone − used ≥ need + reserve = k·need,
|
|
221
|
+
// k = 1 + RESERVE/n: with the full number gone = used + n + RESERVE, early in the week gone·(1 − k/2) = used — never
|
|
222
|
+
// when k ≥ 2), the week's last stretch (with room for a session), the reset — a new week at 0 % goes at once, so
|
|
199
223
|
// never past it
|
|
200
|
-
const
|
|
224
|
+
const k = 1 + RESERVE / min;
|
|
225
|
+
const byHalf = min > 0 && k < 2 ? week.used / (1 - k / 2) : Infinity;
|
|
226
|
+
const caught = start + (Math.min(week.used + min + RESERVE, byHalf) / 100) * WEEK;
|
|
201
227
|
const last = fits ? resets - END_WINDOW : Infinity;
|
|
202
228
|
const after = resets + AFTER_RESET;
|
|
203
229
|
const at = Math.min(caught, last, after);
|
|
204
|
-
const tail =
|
|
230
|
+
const tail =
|
|
231
|
+
at === caught ? say("hold", { reset, target: Math.ceil(need + reserve) }) : at === last ? say("last", { reset, window: say("hours", { n: END_WINDOW / 3_600_000 }) }) : say("reset", { reset });
|
|
205
232
|
answer(1, say("head", { ...v, min: Math.ceil(need) }) + tail, new Date(Math.max(at, now + 5 * 60_000)));
|
|
206
233
|
|
|
234
|
+
/** It waits for the reserve in this week (the week it remembers ends within a day of this one's reset). */
|
|
235
|
+
function holding(resets: number): boolean {
|
|
236
|
+
if (!HOLD) return false;
|
|
237
|
+
try {
|
|
238
|
+
const week = Date.parse((JSON.parse(fs.readFileSync(HOLD, "utf8")) as { week?: string }).week ?? "");
|
|
239
|
+
return Math.abs(week - resets) < DAY;
|
|
240
|
+
} catch {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** The week it now waits in for the reserve, or none (gone). Never fails: without it the gate only forgets. */
|
|
246
|
+
function hold(resets: number | undefined): void {
|
|
247
|
+
if (!HOLD) return;
|
|
248
|
+
try {
|
|
249
|
+
if (resets === undefined) fs.rmSync(HOLD, { force: true });
|
|
250
|
+
else fs.writeFileSync(HOLD, JSON.stringify({ week: new Date(resets).toISOString(), since: new Date().toISOString() }) + "\n");
|
|
251
|
+
} catch {
|
|
252
|
+
// a folder it may not write here: it asks as if for the first time
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
207
256
|
/** A stretch of time as a person reads it: hours to two days, then days — one decimal, in the research language. */
|
|
208
257
|
function inTime(ms: number): string {
|
|
209
258
|
const h = Math.max(0, ms) / 3_600_000;
|
package/dist/brief/brief.js
CHANGED
|
@@ -18,7 +18,7 @@ import { calibrationLine } from "../core/calibration.js";
|
|
|
18
18
|
import { taskRecordsets } from "../core/frontier.js";
|
|
19
19
|
import { reviewItems } from "../core/review.js";
|
|
20
20
|
import { byHandOnly, listConnectors, missingConsents, readyConnectors, routeOf } from "../core/connector.js";
|
|
21
|
-
import { clock, hostAllowed, hostState, REFUSED_FOREVER } from "../core/net.js";
|
|
21
|
+
import { clock, clockUp, hostAllowed, hostState, leftAloneFor, REFUSED_FOREVER } from "../core/net.js";
|
|
22
22
|
import { archiveLevel } from "../core/terms.js";
|
|
23
23
|
import { onHost, permissionQuestions, setHosts } from "../core/archivewait.js";
|
|
24
24
|
import { runs, runsArg, shellArg } from "../cli/format.js";
|
|
@@ -31,6 +31,8 @@ import { hypothesisPeople } from "../core/directions.js";
|
|
|
31
31
|
import { imagesIndex, weakScans } from "../core/mediaindex.js";
|
|
32
32
|
import { SHARPER_SCAN } from "../core/views.js";
|
|
33
33
|
import { HYPOTHESIS_LINKS_ORIGIN, recordedLinks, recordedText } from "../core/hypolinks.js";
|
|
34
|
+
import { forHistory, historyOn } from "../core/pastevents.js";
|
|
35
|
+
import { HISTORY_WEB_RULE, historySections, localEventsSection } from "./history.js";
|
|
34
36
|
export { DEFAULT_BUDGET } from "../core/config.js";
|
|
35
37
|
import { DEFAULT_BUDGET, Settings } from "../core/config.js";
|
|
36
38
|
import { bookTuned, hostTuned, readingOf, treeTuning, tuningOn } from "../core/tune.js";
|
|
@@ -762,7 +764,9 @@ function archiveLine(tree, b, repo, shared, installed, qs = []) {
|
|
|
762
764
|
try {
|
|
763
765
|
const st = hostState(net, host);
|
|
764
766
|
if (st.blockedUntil && st.blockedUntil > Date.now())
|
|
765
|
-
parts.push(`${host} left alone until ${clock(st.blockedUntil)}${st.reason ? ` (${st.reason})` : ""} — nothing to it before then
|
|
767
|
+
parts.push(`${host} left alone until ${clock(st.blockedUntil)}${st.reason ? ` (${st.reason})` : ""} — nothing to it before then${
|
|
768
|
+
// it went silent, or asked to slow down: the work goes elsewhere meanwhile, never a fetch asked again and again
|
|
769
|
+
leftAloneFor(st, Date.now()) ? `: work on what needs nothing from it, else back to the queue for later (strom session close --continue) and on after ${clockUp(st.blockedUntil)}` : ""}`);
|
|
766
770
|
}
|
|
767
771
|
catch {
|
|
768
772
|
// the host's state unreadable: the level says enough
|
|
@@ -871,7 +875,7 @@ export function buildBrief(tree, opts) {
|
|
|
871
875
|
? `Working alone (strom run): nobody answers here, but the user may read this session afterwards (the run's output, its log) — every message of yours, the last one too, in ${langName(lang)}, about the work and never addressed to the user ("waits for a check", never "waits for you"); a step only the user can take goes into strom task wait.`
|
|
872
876
|
: "",
|
|
873
877
|
STROM_ONLY,
|
|
874
|
-
webRule(new Settings(tree.env, {}).webPerHost(tree.config)),
|
|
878
|
+
task && forHistory(task) ? HISTORY_WEB_RULE : webRule(new Settings(tree.env, {}).webPerHost(tree.config)),
|
|
875
879
|
opts.deadline !== undefined ? briefClock(opts.deadline) : "",
|
|
876
880
|
].filter(Boolean).join("\n"),
|
|
877
881
|
});
|
|
@@ -902,6 +906,10 @@ export function buildBrief(tree, opts) {
|
|
|
902
906
|
...filesCame(task),
|
|
903
907
|
].filter(Boolean).join("\n"),
|
|
904
908
|
});
|
|
909
|
+
// a task of history (the experiment): its own sections, nothing of the records, the method or the queue
|
|
910
|
+
const history = forHistory(task) ? historySections(tree, task, opts.shared, alone) : undefined;
|
|
911
|
+
if (history)
|
|
912
|
+
return assemble([...sections, ...history], budget);
|
|
905
913
|
// 2. a review: what each item of the task is, as the tree has it
|
|
906
914
|
if (task.origin.startsWith("review:") && task.where.length)
|
|
907
915
|
sections.push({ name: "review", required: true, pointer: `strom task show ${task.id}`, text: ["## To review", ...reviewItems(tree, task)].join("\n") });
|
|
@@ -1243,6 +1251,12 @@ export function buildBrief(tree, opts) {
|
|
|
1243
1251
|
// a task that links hypotheses reads no records: the parts of the method and the commands it uses, whatever its level
|
|
1244
1252
|
const kind = linking ? METHOD_LINKS : task?.level;
|
|
1245
1253
|
sections.push({ name: "method", first: true, pointer: "strom guide", text: methodFor(kind, conditions) });
|
|
1254
|
+
// 8'. the experiment of history on: a session that reads records may write a local event they tell of
|
|
1255
|
+
if (task && ["link", "verify", "intake", "enrich"].includes(kind ?? "") && historyOn(tree)) {
|
|
1256
|
+
const local = localEventsSection();
|
|
1257
|
+
if (local)
|
|
1258
|
+
sections.push(local);
|
|
1259
|
+
}
|
|
1246
1260
|
// 8 bis. the search beyond the registers: its budget of pages, printed pages for the user's model for print where the
|
|
1247
1261
|
// agent hands work to another model, and what the research has written of the person's places already
|
|
1248
1262
|
if (task?.origin === STORY_SOURCES_ORIGIN) {
|
|
@@ -1325,6 +1339,12 @@ export function buildBrief(tree, opts) {
|
|
|
1325
1339
|
"- a command you need: strom help <command> (short, with examples) — the full guide: strom guide",
|
|
1326
1340
|
].filter(Boolean).join("\n"),
|
|
1327
1341
|
});
|
|
1342
|
+
return assemble(sections, budget);
|
|
1343
|
+
}
|
|
1344
|
+
/**
|
|
1345
|
+
* The brief within its budget, from its sections in order.
|
|
1346
|
+
*/
|
|
1347
|
+
function assemble(sections, budget) {
|
|
1328
1348
|
// Assemble within the budget: required sections always, then the first ones whole when they fit, then the others in
|
|
1329
1349
|
// order — those in parts in short —, a first one that did not fit whole cut after them, and last the parts given in
|
|
1330
1350
|
// short made whole while they fit (UPGRADES); each written where it stands. Everything written counts: the blank line
|