strom-research 1.0.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.
- package/LICENSE +373 -0
- package/README.md +142 -0
- package/assets/lang/cs.json +302 -0
- package/assets/lang/de.json +302 -0
- package/assets/method/core.md +43 -0
- package/assets/method/enrich.md +11 -0
- package/assets/method/intake.md +30 -0
- package/assets/method/link.md +28 -0
- package/assets/method/locate.md +28 -0
- package/assets/method/narrate.md +13 -0
- package/assets/method/reading.md +62 -0
- package/assets/method/recording.md +59 -0
- package/assets/method/request.md +10 -0
- package/assets/method/verify.md +17 -0
- package/assets/plugins/README.md +23 -0
- package/assets/plugins/connectors/DISCOVERY.md +159 -0
- package/assets/plugins/connectors/README.md +376 -0
- package/assets/plugins/connectors/sdk.ts +168 -0
- package/assets/plugins/connectors/template.ts +38 -0
- package/assets/plugins/gitignore +4 -0
- package/dist/agents/files.js +313 -0
- package/dist/agents/global.js +257 -0
- package/dist/agents/launch.js +36 -0
- package/dist/agents/profiles.js +95 -0
- package/dist/brief/brief.js +345 -0
- package/dist/cli/commit.js +44 -0
- package/dist/cli/context.js +311 -0
- package/dist/cli/execute.js +154 -0
- package/dist/cli/fixes.js +78 -0
- package/dist/cli/format.js +53 -0
- package/dist/cli/help.js +59 -0
- package/dist/cli/main.js +152 -0
- package/dist/cli/menu.js +212 -0
- package/dist/cli/registry.js +96 -0
- package/dist/cli/ui.js +266 -0
- package/dist/cli/wizard.js +142 -0
- package/dist/cli.js +14 -0
- package/dist/commands/analysis.js +622 -0
- package/dist/commands/batch.js +181 -0
- package/dist/commands/checks.js +153 -0
- package/dist/commands/connectors.js +1377 -0
- package/dist/commands/guide.js +160 -0
- package/dist/commands/index.js +19 -0
- package/dist/commands/intake.js +234 -0
- package/dist/commands/media.js +406 -0
- package/dist/commands/meta.js +195 -0
- package/dist/commands/output.js +117 -0
- package/dist/commands/people.js +664 -0
- package/dist/commands/read.js +199 -0
- package/dist/commands/research.js +139 -0
- package/dist/commands/session.js +605 -0
- package/dist/commands/setup.js +465 -0
- package/dist/commands/sources.js +634 -0
- package/dist/commands/start.js +383 -0
- package/dist/commands/story.js +75 -0
- package/dist/commands/tasks.js +436 -0
- package/dist/commands/trees.js +128 -0
- package/dist/core/actions.js +852 -0
- package/dist/core/age.js +95 -0
- package/dist/core/apps.js +74 -0
- package/dist/core/assets.js +34 -0
- package/dist/core/awake.js +33 -0
- package/dist/core/browser.js +281 -0
- package/dist/core/calibration.js +48 -0
- package/dist/core/check.js +112 -0
- package/dist/core/chromium.js +88 -0
- package/dist/core/config.js +348 -0
- package/dist/core/connector.js +811 -0
- package/dist/core/deps.js +73 -0
- package/dist/core/dialog.js +61 -0
- package/dist/core/errors.js +89 -0
- package/dist/core/evidence.js +58 -0
- package/dist/core/frontier.js +219 -0
- package/dist/core/gdate.js +77 -0
- package/dist/core/git.js +300 -0
- package/dist/core/guard.js +124 -0
- package/dist/core/http2.js +76 -0
- package/dist/core/import.js +541 -0
- package/dist/core/install.js +28 -0
- package/dist/core/integrity.js +219 -0
- package/dist/core/json.js +87 -0
- package/dist/core/lang.js +70 -0
- package/dist/core/live.js +244 -0
- package/dist/core/lock.js +112 -0
- package/dist/core/logins.js +67 -0
- package/dist/core/media.js +223 -0
- package/dist/core/model.js +101 -0
- package/dist/core/net.js +366 -0
- package/dist/core/open.js +29 -0
- package/dist/core/paths.js +84 -0
- package/dist/core/people.js +283 -0
- package/dist/core/phrases.js +85 -0
- package/dist/core/queue.js +113 -0
- package/dist/core/reader.js +76 -0
- package/dist/core/records.js +105 -0
- package/dist/core/roles.js +30 -0
- package/dist/core/schema.js +261 -0
- package/dist/core/seal.js +77 -0
- package/dist/core/self.js +40 -0
- package/dist/core/session.js +155 -0
- package/dist/core/shortcut.js +90 -0
- package/dist/core/stories.js +61 -0
- package/dist/core/stromapp.js +138 -0
- package/dist/core/text.js +104 -0
- package/dist/core/tree.js +507 -0
- package/dist/core/uninstall.js +128 -0
- package/dist/core/update.js +193 -0
- package/dist/core/validate.js +260 -0
- package/dist/core/views.js +164 -0
- package/dist/core/which.js +51 -0
- package/dist/core/workers.js +42 -0
- package/dist/gedcom/export.js +454 -0
- package/dist/gedcom/labels.js +103 -0
- package/dist/gedcom/lines.js +91 -0
- package/dist/gedcom/parse.js +53 -0
- package/dist/gedcom/validate.js +183 -0
- package/dist/image/image.js +223 -0
- package/dist/image/index.js +114 -0
- package/dist/image/jpeg-decode.js +552 -0
- package/dist/image/jpeg-encode.js +254 -0
- package/dist/image/png.js +241 -0
- package/dist/runners/antigravity.js +70 -0
- package/dist/runners/claude.js +179 -0
- package/dist/runners/codex.js +45 -0
- package/dist/runners/index.js +13 -0
- package/dist/runners/jsonl.js +86 -0
- package/dist/runners/opencode.js +50 -0
- package/dist/runners/runner.js +63 -0
- package/dist/runners/script.js +58 -0
- package/package.json +44 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// export gedcom · gedcom validate — the automated output.
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { register } from "../cli/registry.js";
|
|
5
|
+
import { lines, table } from "../cli/format.js";
|
|
6
|
+
import { exportGedcom, GED_PROFILES } from "../gedcom/export.js";
|
|
7
|
+
import { hasGedErrors, validateGedcom } from "../gedcom/validate.js";
|
|
8
|
+
import { writeFileAtomic } from "../core/json.js";
|
|
9
|
+
import { verifyFast } from "../core/integrity.js";
|
|
10
|
+
import { ancestorGenerations, familiesAsChild, familiesAsPartner } from "../core/people.js";
|
|
11
|
+
import { resolveResearch } from "./research.js";
|
|
12
|
+
import { UsageError } from "../core/errors.js";
|
|
13
|
+
function findingRows(f) {
|
|
14
|
+
return table(f.slice(0, 30).map((x) => [x.level === "error" ? "ERROR" : "warn", `line ${x.line}`, x.message]));
|
|
15
|
+
}
|
|
16
|
+
/** People in scope of a research: the focus, its ancestors, their partners, and any adoptive/step parents. */
|
|
17
|
+
function researchScope(tree, r) {
|
|
18
|
+
const ids = new Set(ancestorGenerations(tree, r.focus, r.limits?.generations ?? 50).keys());
|
|
19
|
+
for (const id of [...ids]) {
|
|
20
|
+
for (const f of familiesAsPartner(tree, id))
|
|
21
|
+
for (const p of f.partners)
|
|
22
|
+
ids.add(p);
|
|
23
|
+
for (const f of familiesAsChild(tree, id))
|
|
24
|
+
for (const p of f.partners)
|
|
25
|
+
ids.add(p);
|
|
26
|
+
}
|
|
27
|
+
return ids;
|
|
28
|
+
}
|
|
29
|
+
/** output/tree.ged (any program) or output/tree-strom.ged (the Strom app); a research's own file is named after it. */
|
|
30
|
+
export function gedFile(tree, profile, research) {
|
|
31
|
+
return path.join(tree.root, "output", `${research ? research.id : "tree"}${profile === "strom" ? "-strom" : ""}.ged`);
|
|
32
|
+
}
|
|
33
|
+
/** Write one GEDCOM file and validate it by the rules of its reader. */
|
|
34
|
+
export function writeTreeGed(tree, opts) {
|
|
35
|
+
const persons = opts.research ? researchScope(tree, opts.research) : undefined;
|
|
36
|
+
const result = exportGedcom(tree, { for: opts.for, stromVersion: opts.stromVersion, ...(persons ? { persons } : {}) });
|
|
37
|
+
const findings = validateGedcom(result.text, opts.for === "standard" ? { strict: true } : {});
|
|
38
|
+
const file = opts.out ?? gedFile(tree, opts.for, opts.research);
|
|
39
|
+
if (!hasGedErrors(findings) && !tree.dryRun)
|
|
40
|
+
writeFileAtomic(file, result.text);
|
|
41
|
+
return { ...result, findings, file, for: opts.for };
|
|
42
|
+
}
|
|
43
|
+
/** The GEDCOM files the settings ask for (both by default), from the same evidence. Used after sessions. */
|
|
44
|
+
export function writeGedcoms(ctx, tree, research) {
|
|
45
|
+
return ctx.settings.gedcomFor(tree.config).map((p) => writeTreeGed(tree, { for: p, stromVersion: ctx.settings.stromVersion(tree.config), ...(research ? { research } : {}) }));
|
|
46
|
+
}
|
|
47
|
+
register({
|
|
48
|
+
path: ["export", "gedcom"],
|
|
49
|
+
summary: "Generate the GEDCOM files, validated: output/tree.ged for any program, output/tree-strom.ged for the Strom app",
|
|
50
|
+
group: "output",
|
|
51
|
+
tree: true,
|
|
52
|
+
description: "Both come from the same evidence (GEDCOM 5.5.1, UTF-8). The standard one uses no extension tags; the Strom\n" +
|
|
53
|
+
"one is shaped to what the Strom app reads (_WITN, _STORY, _FREL/_MREL, a source per page). QUAY is the\n" +
|
|
54
|
+
"quality of each citation's evidence; leads say so in a note; retracted and disproven facts are left out;\n" +
|
|
55
|
+
"of several facts of a kind the best supported comes first. Which files: --for or the setting gedcom.for.",
|
|
56
|
+
options: [
|
|
57
|
+
{ name: "for", type: "string", value: "<reader>", description: "standard (any program), strom (the Strom app) or both (default: the setting gedcom.for, both)" },
|
|
58
|
+
{ name: "research", type: "string", value: "<G…>", description: "only the people of one research (focus, ancestors, partners)" },
|
|
59
|
+
{ name: "out", type: "string", value: "<file>", description: "write here instead of output/ (with --for standard or strom)" },
|
|
60
|
+
],
|
|
61
|
+
examples: ["strom export gedcom", "strom export gedcom --research G0001", "strom export gedcom --for standard --out ~/Desktop/novak.ged"],
|
|
62
|
+
run(ctx, { opts }) {
|
|
63
|
+
const tree = ctx.tree();
|
|
64
|
+
const research = typeof opts.research === "string" ? resolveResearch(tree, opts.research) : undefined;
|
|
65
|
+
const out = typeof opts.out === "string" ? ctx.resolvePath(opts.out) : undefined;
|
|
66
|
+
const which = typeof opts.for === "string" ? opts.for.toLowerCase() : undefined;
|
|
67
|
+
if (which && which !== "both" && !GED_PROFILES.includes(which))
|
|
68
|
+
throw new UsageError(`invalid --for "${opts.for}"`, { hint: "standard, strom or both" });
|
|
69
|
+
const profiles = which === "both" ? [...GED_PROFILES] : which ? [which] : ctx.settings.gedcomFor(tree.config);
|
|
70
|
+
if (out && profiles.length > 1)
|
|
71
|
+
throw new UsageError("--out writes one file", { hint: "add --for standard or --for strom" });
|
|
72
|
+
const results = profiles.map((p) => writeTreeGed(tree, { for: p, stromVersion: ctx.settings.stromVersion(tree.config), ...(research ? { research } : {}), ...(out ? { out } : {}) }));
|
|
73
|
+
const bad = results.filter((r) => hasGedErrors(r.findings));
|
|
74
|
+
if (bad.length) {
|
|
75
|
+
return {
|
|
76
|
+
text: lines(...bad.map((r) => `GEDCOM ${r.for} NOT written — validation error(s):\n${findingRows(r.findings)}`), "→ this is a bug in strom; please report it"),
|
|
77
|
+
data: { ok: false, results: results.map((r) => ({ for: r.for, file: r.file, findings: r.findings })) },
|
|
78
|
+
exitCode: 1,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// Commit the output when it lives in the tree and the evidence is intact.
|
|
82
|
+
const inTree = results.filter((r) => r.file.startsWith(tree.root + path.sep));
|
|
83
|
+
let committed = false;
|
|
84
|
+
if (inTree.length && !tree.dryRun && verifyFast(tree).findings.every((f) => f.level !== "error")) {
|
|
85
|
+
const s0 = results[0].stats;
|
|
86
|
+
tree.withTreeLock(() => tree.commit(`Export ${inTree.map((r) => path.basename(r.file)).join(", ")}: ${s0.persons} persons, ${s0.families} families`, inTree.map((r) => tree.relative(r.file))));
|
|
87
|
+
committed = true;
|
|
88
|
+
}
|
|
89
|
+
const text = lines(...results.map((r) => {
|
|
90
|
+
const s = r.stats;
|
|
91
|
+
return lines(`${ctx.display(r.file)} (${r.for === "strom" ? "for the Strom app" : "standard, any program"}) — ${s.persons} persons · ${s.families} families · ${s.events} facts · ${s.sources} sources${s.skipped ? ` · ${s.skipped} retracted/disproven left out` : ""}`, ` valid GEDCOM 5.5.1${r.findings.length ? ` (${r.findings.length} warning(s))` : ""}`, r.findings.length ? findingRows(r.findings) : undefined);
|
|
92
|
+
}), committed ? "committed" : undefined);
|
|
93
|
+
const first = results[0];
|
|
94
|
+
return { text, data: { ok: true, file: first.file, stats: first.stats, findings: first.findings, files: results.map((r) => ({ for: r.for, file: r.file, stats: r.stats, findings: r.findings })) } };
|
|
95
|
+
},
|
|
96
|
+
}, {
|
|
97
|
+
path: ["gedcom", "validate"],
|
|
98
|
+
summary: "Check any GEDCOM file: structure, tags in context, references, dates, line lengths",
|
|
99
|
+
group: "output",
|
|
100
|
+
args: [{ name: "file", description: "the .ged file", required: true }],
|
|
101
|
+
options: [{ name: "for", type: "string", value: "<reader>", description: "standard: also reject extension tags (_WITN, _STORY); strom (default): allow them" }],
|
|
102
|
+
run(ctx, { args, opts }) {
|
|
103
|
+
// A path like output/tree.ged is also found from outside the tree folder.
|
|
104
|
+
let file = ctx.resolvePath(args[0]);
|
|
105
|
+
if (!fs.existsSync(file) && !path.isAbsolute(args[0]) && ctx.hasTree())
|
|
106
|
+
file = path.join(ctx.tree().root, args[0]);
|
|
107
|
+
if (!fs.existsSync(file))
|
|
108
|
+
throw new UsageError(`no such file: ${args[0]}`);
|
|
109
|
+
const findings = validateGedcom(fs.readFileSync(file, "utf8"), opts.for === "standard" ? { strict: true } : {});
|
|
110
|
+
const errors = findings.filter((f) => f.level === "error").length;
|
|
111
|
+
return {
|
|
112
|
+
text: findings.length ? lines(findingRows(findings), "", `${errors} error(s), ${findings.length - errors} warning(s)`) : "ok — valid GEDCOM 5.5.1",
|
|
113
|
+
data: { ok: errors === 0, findings },
|
|
114
|
+
exitCode: errors ? 1 : 0,
|
|
115
|
+
};
|
|
116
|
+
},
|
|
117
|
+
});
|