daftari 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.
Files changed (101) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/LICENSE +21 -0
  3. package/README.md +259 -0
  4. package/dist/access/locks.d.ts +19 -0
  5. package/dist/access/locks.d.ts.map +1 -0
  6. package/dist/access/locks.js +112 -0
  7. package/dist/access/locks.js.map +1 -0
  8. package/dist/access/rbac.d.ts +18 -0
  9. package/dist/access/rbac.d.ts.map +1 -0
  10. package/dist/access/rbac.js +48 -0
  11. package/dist/access/rbac.js.map +1 -0
  12. package/dist/cli.d.ts +4 -0
  13. package/dist/cli.d.ts.map +1 -0
  14. package/dist/cli.js +216 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/curation/lint.d.ts +20 -0
  17. package/dist/curation/lint.d.ts.map +1 -0
  18. package/dist/curation/lint.js +176 -0
  19. package/dist/curation/lint.js.map +1 -0
  20. package/dist/curation/provenance.d.ts +21 -0
  21. package/dist/curation/provenance.d.ts.map +1 -0
  22. package/dist/curation/provenance.js +80 -0
  23. package/dist/curation/provenance.js.map +1 -0
  24. package/dist/curation/staleness.d.ts +19 -0
  25. package/dist/curation/staleness.d.ts.map +1 -0
  26. package/dist/curation/staleness.js +67 -0
  27. package/dist/curation/staleness.js.map +1 -0
  28. package/dist/curation/tension.d.ts +20 -0
  29. package/dist/curation/tension.d.ts.map +1 -0
  30. package/dist/curation/tension.js +134 -0
  31. package/dist/curation/tension.js.map +1 -0
  32. package/dist/frontmatter/parser.d.ts +10 -0
  33. package/dist/frontmatter/parser.d.ts.map +1 -0
  34. package/dist/frontmatter/parser.js +29 -0
  35. package/dist/frontmatter/parser.js.map +1 -0
  36. package/dist/frontmatter/schema.d.ts +7 -0
  37. package/dist/frontmatter/schema.d.ts.map +1 -0
  38. package/dist/frontmatter/schema.js +115 -0
  39. package/dist/frontmatter/schema.js.map +1 -0
  40. package/dist/frontmatter/types.d.ts +41 -0
  41. package/dist/frontmatter/types.d.ts.map +1 -0
  42. package/dist/frontmatter/types.js +8 -0
  43. package/dist/frontmatter/types.js.map +1 -0
  44. package/dist/index.d.ts +4 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +94 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/search/bm25.d.ts +19 -0
  49. package/dist/search/bm25.d.ts.map +1 -0
  50. package/dist/search/bm25.js +115 -0
  51. package/dist/search/bm25.js.map +1 -0
  52. package/dist/search/hybrid.d.ts +38 -0
  53. package/dist/search/hybrid.d.ts.map +1 -0
  54. package/dist/search/hybrid.js +162 -0
  55. package/dist/search/hybrid.js.map +1 -0
  56. package/dist/search/reindex.d.ts +15 -0
  57. package/dist/search/reindex.d.ts.map +1 -0
  58. package/dist/search/reindex.js +189 -0
  59. package/dist/search/reindex.js.map +1 -0
  60. package/dist/search/vector.d.ts +9 -0
  61. package/dist/search/vector.d.ts.map +1 -0
  62. package/dist/search/vector.js +128 -0
  63. package/dist/search/vector.js.map +1 -0
  64. package/dist/server.d.ts +6 -0
  65. package/dist/server.d.ts.map +1 -0
  66. package/dist/server.js +72 -0
  67. package/dist/server.js.map +1 -0
  68. package/dist/storage/index-db.d.ts +37 -0
  69. package/dist/storage/index-db.d.ts.map +1 -0
  70. package/dist/storage/index-db.js +145 -0
  71. package/dist/storage/index-db.js.map +1 -0
  72. package/dist/storage/local.d.ts +6 -0
  73. package/dist/storage/local.d.ts.map +1 -0
  74. package/dist/storage/local.js +57 -0
  75. package/dist/storage/local.js.map +1 -0
  76. package/dist/tools/curation.d.ts +22 -0
  77. package/dist/tools/curation.d.ts.map +1 -0
  78. package/dist/tools/curation.js +202 -0
  79. package/dist/tools/curation.js.map +1 -0
  80. package/dist/tools/read.d.ts +74 -0
  81. package/dist/tools/read.d.ts.map +1 -0
  82. package/dist/tools/read.js +254 -0
  83. package/dist/tools/read.js.map +1 -0
  84. package/dist/tools/search.d.ts +13 -0
  85. package/dist/tools/search.d.ts.map +1 -0
  86. package/dist/tools/search.js +190 -0
  87. package/dist/tools/search.js.map +1 -0
  88. package/dist/tools/write.d.ts +18 -0
  89. package/dist/tools/write.d.ts.map +1 -0
  90. package/dist/tools/write.js +465 -0
  91. package/dist/tools/write.js.map +1 -0
  92. package/dist/utils/config.d.ts +12 -0
  93. package/dist/utils/config.d.ts.map +1 -0
  94. package/dist/utils/config.js +94 -0
  95. package/dist/utils/config.js.map +1 -0
  96. package/dist/utils/git.d.ts +23 -0
  97. package/dist/utils/git.d.ts.map +1 -0
  98. package/dist/utils/git.js +114 -0
  99. package/dist/utils/git.js.map +1 -0
  100. package/package.json +69 -0
  101. package/templates/config.yaml +31 -0
@@ -0,0 +1,20 @@
1
+ import { type Result } from "../frontmatter/types.js";
2
+ export declare const DEFAULT_TENSION_STATUS = "unresolved";
3
+ export interface TensionEntry {
4
+ date: string;
5
+ title: string;
6
+ sourceA: string;
7
+ claimA: string;
8
+ sourceB: string;
9
+ claimB: string;
10
+ status: string;
11
+ loggedBy: string;
12
+ }
13
+ export type TensionInput = Omit<TensionEntry, "date" | "status"> & {
14
+ date?: string;
15
+ status?: string;
16
+ };
17
+ export declare function tensionsPath(vaultRoot: string): string;
18
+ export declare function addTension(vaultRoot: string, input: TensionInput): Promise<Result<TensionEntry, Error>>;
19
+ export declare function listTensions(vaultRoot: string, status?: string): Promise<Result<TensionEntry[], Error>>;
20
+ //# sourceMappingURL=tension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tension.d.ts","sourceRoot":"","sources":["../../src/curation/tension.ts"],"names":[],"mappings":"AAaA,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAE/D,eAAO,MAAM,sBAAsB,eAAe,CAAC;AAEnD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,QAAQ,CAAC,GAAG;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtD;AAiBD,wBAAsB,UAAU,CAC9B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,CA2BtC;AAsDD,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,KAAK,CAAC,CAAC,CAoBxC"}
@@ -0,0 +1,134 @@
1
+ // Tension log — the cross-domain-connection half of the curation engine.
2
+ //
3
+ // A "tension" is a recorded contradiction or pull between two documents: two
4
+ // sources that say things which sit uneasily together. Daftari records the
5
+ // tension; it never resolves it. Resolution is a human/curatorial act, so an
6
+ // entry just carries a Status the curator updates by hand.
7
+ //
8
+ // The log is a human-readable markdown file, .daftari/tensions.md — append-only
9
+ // from this module's side. Each entry is one `## ` block.
10
+ import { mkdirSync } from "node:fs";
11
+ import { appendFile, readFile } from "node:fs/promises";
12
+ import { join } from "node:path";
13
+ import { err, ok } from "../frontmatter/types.js";
14
+ export const DEFAULT_TENSION_STATUS = "unresolved";
15
+ export function tensionsPath(vaultRoot) {
16
+ return join(vaultRoot, ".daftari", "tensions.md");
17
+ }
18
+ // Renders one entry in the canonical block format. The blank trailing line
19
+ // keeps consecutive entries visually separated in the file.
20
+ function renderEntry(entry) {
21
+ return (`## ${entry.date} — ${entry.title}\n` +
22
+ `- **Source A:** ${entry.sourceA} says ${entry.claimA}\n` +
23
+ `- **Source B:** ${entry.sourceB} says ${entry.claimB}\n` +
24
+ `- **Status:** ${entry.status}\n` +
25
+ `- **Logged by:** ${entry.loggedBy}\n`);
26
+ }
27
+ // Appends a tension entry to .daftari/tensions.md. Date defaults to today and
28
+ // status to "unresolved" — a freshly logged tension is unresolved by
29
+ // definition.
30
+ export async function addTension(vaultRoot, input) {
31
+ for (const field of ["title", "sourceA", "claimA", "sourceB", "claimB", "loggedBy"]) {
32
+ if (typeof input[field] !== "string" || input[field].trim().length === 0) {
33
+ return err(new Error(`addTension requires a non-empty '${field}'`));
34
+ }
35
+ }
36
+ const entry = {
37
+ date: input.date ?? new Date().toISOString().slice(0, 10),
38
+ title: input.title.trim(),
39
+ sourceA: input.sourceA.trim(),
40
+ claimA: input.claimA.trim(),
41
+ sourceB: input.sourceB.trim(),
42
+ claimB: input.claimB.trim(),
43
+ status: input.status ?? DEFAULT_TENSION_STATUS,
44
+ loggedBy: input.loggedBy.trim(),
45
+ };
46
+ try {
47
+ mkdirSync(join(vaultRoot, ".daftari"), { recursive: true });
48
+ // A leading blank line keeps this block separated from the previous one.
49
+ await appendFile(tensionsPath(vaultRoot), `\n${renderEntry(entry)}`);
50
+ return ok(entry);
51
+ }
52
+ catch (e) {
53
+ const reason = e instanceof Error ? e.message : String(e);
54
+ return err(new Error(`cannot append to tension log: ${reason}`));
55
+ }
56
+ }
57
+ // `- **Source A:** <path> says <claim>` → { path, claim }. The path is
58
+ // everything before the first " says "; the claim is the rest.
59
+ function parseSourceLine(value) {
60
+ const marker = value.indexOf(" says ");
61
+ if (marker === -1)
62
+ return { path: value.trim(), claim: "" };
63
+ return {
64
+ path: value.slice(0, marker).trim(),
65
+ claim: value.slice(marker + " says ".length).trim(),
66
+ };
67
+ }
68
+ function parseBlock(block) {
69
+ const lines = block.split("\n");
70
+ const header = lines[0]?.replace(/^##\s+/, "") ?? "";
71
+ const headerMatch = header.match(/^(\d{4}-\d{2}-\d{2})\s+—\s+(.+)$/);
72
+ if (!headerMatch)
73
+ return null;
74
+ const entry = {
75
+ date: headerMatch[1],
76
+ title: headerMatch[2].trim(),
77
+ sourceA: "",
78
+ claimA: "",
79
+ sourceB: "",
80
+ claimB: "",
81
+ status: DEFAULT_TENSION_STATUS,
82
+ loggedBy: "",
83
+ };
84
+ for (const line of lines.slice(1)) {
85
+ const m = line.match(/^-\s+\*\*(.+?):\*\*\s*(.*)$/);
86
+ if (!m)
87
+ continue;
88
+ const label = m[1].toLowerCase();
89
+ const value = m[2];
90
+ if (label === "source a") {
91
+ const s = parseSourceLine(value);
92
+ entry.sourceA = s.path;
93
+ entry.claimA = s.claim;
94
+ }
95
+ else if (label === "source b") {
96
+ const s = parseSourceLine(value);
97
+ entry.sourceB = s.path;
98
+ entry.claimB = s.claim;
99
+ }
100
+ else if (label === "status") {
101
+ entry.status = value.trim();
102
+ }
103
+ else if (label === "logged by") {
104
+ entry.loggedBy = value.trim();
105
+ }
106
+ }
107
+ return entry;
108
+ }
109
+ // Reads back every logged tension, optionally filtered to one status. A
110
+ // missing log is not an error — it just means no tensions have been logged.
111
+ export async function listTensions(vaultRoot, status) {
112
+ let raw;
113
+ try {
114
+ raw = await readFile(tensionsPath(vaultRoot), "utf-8");
115
+ }
116
+ catch (e) {
117
+ if (e.code === "ENOENT")
118
+ return ok([]);
119
+ const reason = e instanceof Error ? e.message : String(e);
120
+ return err(new Error(`cannot read tension log: ${reason}`));
121
+ }
122
+ const entries = [];
123
+ // Each entry starts at a line beginning with "## ".
124
+ for (const block of raw.split(/(?=^## )/m)) {
125
+ const trimmed = block.trim();
126
+ if (!trimmed.startsWith("## "))
127
+ continue;
128
+ const entry = parseBlock(trimmed);
129
+ if (entry)
130
+ entries.push(entry);
131
+ }
132
+ return ok(status ? entries.filter((e) => e.status === status) : entries);
133
+ }
134
+ //# sourceMappingURL=tension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tension.js","sourceRoot":"","sources":["../../src/curation/tension.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { type Frontmatter, type Result, type ValidationReport } from "./types.js";
2
+ export interface ParsedDocument {
3
+ frontmatter: Frontmatter;
4
+ content: string;
5
+ raw: Record<string, unknown>;
6
+ validation: ValidationReport;
7
+ hasFrontmatter: boolean;
8
+ }
9
+ export declare function parseDocument(source: string): Result<ParsedDocument, Error>;
10
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/frontmatter/parser.ts"],"names":[],"mappings":"AASA,OAAO,EAAO,KAAK,WAAW,EAAM,KAAK,MAAM,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE3F,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,UAAU,EAAE,gBAAgB,CAAC;IAC7B,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,cAAc,EAAE,KAAK,CAAC,CAmB3E"}
@@ -0,0 +1,29 @@
1
+ // Parses a markdown document into its frontmatter and body.
2
+ //
3
+ // gray-matter does the YAML extraction; validateFrontmatter coerces and checks
4
+ // it. Parsing fails (Result.err) only when the YAML itself is malformed.
5
+ // Frontmatter that parses but violates the schema is NOT a failure — the
6
+ // validation report carries those issues so a read can still return content.
7
+ import matter from "gray-matter";
8
+ import { validateFrontmatter } from "./schema.js";
9
+ import { err, ok } from "./types.js";
10
+ export function parseDocument(source) {
11
+ let extracted;
12
+ try {
13
+ extracted = matter(source);
14
+ }
15
+ catch (e) {
16
+ const reason = e instanceof Error ? e.message : String(e);
17
+ return err(new Error(`malformed YAML frontmatter: ${reason}`));
18
+ }
19
+ const raw = (extracted.data ?? {});
20
+ const { frontmatter, report } = validateFrontmatter(raw);
21
+ return ok({
22
+ frontmatter,
23
+ content: extracted.content,
24
+ raw,
25
+ validation: report,
26
+ hasFrontmatter: Object.keys(raw).length > 0,
27
+ });
28
+ }
29
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/frontmatter/parser.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,EAAE;AACF,+EAA+E;AAC/E,yEAAyE;AACzE,yEAAyE;AACzE,6EAA6E;AAE7E,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,GAAG,EAAoB,EAAE,EAAsC,MAAM,YAAY,CAAC;AAU3F,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,IAAI,SAAwC,CAAC;IAC7C,IAAI,CAAC;QACH,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,MAAM,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC1D,OAAO,GAAG,CAAC,IAAI,KAAK,CAAC,+BAA+B,MAAM,EAAE,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,EAAE,CAA4B,CAAC;IAC9D,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAEzD,OAAO,EAAE,CAAC;QACR,WAAW;QACX,OAAO,EAAE,SAAS,CAAC,OAAO;QAC1B,GAAG;QACH,UAAU,EAAE,MAAM;QAClB,cAAc,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC;KAC5C,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type Frontmatter, type ValidationReport } from "./types.js";
2
+ export interface FrontmatterValidation {
3
+ frontmatter: Frontmatter;
4
+ report: ValidationReport;
5
+ }
6
+ export declare function validateFrontmatter(data: Record<string, unknown>): FrontmatterValidation;
7
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/frontmatter/schema.ts"],"names":[],"mappings":"AAQA,OAAO,EAKL,KAAK,WAAW,EAMhB,KAAK,gBAAgB,EACtB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,WAAW,CAAC;IACzB,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,qBAAqB,CAqGxF"}
@@ -0,0 +1,115 @@
1
+ // Hand-rolled, dependency-free frontmatter validator.
2
+ //
3
+ // Validation is advisory and best-effort: it always produces a complete
4
+ // Frontmatter object (filling defaults for anything missing or malformed) so
5
+ // downstream readers never crash, and it returns a ValidationReport listing
6
+ // every structural problem. It does NOT enforce curation rules (staleness,
7
+ // tension, superseded_by consistency) — that is the curation engine's job.
8
+ import { CONFIDENCES, DOMAINS, PROVENANCES, STATUSES, } from "./types.js";
9
+ export function validateFrontmatter(data) {
10
+ const issues = [];
11
+ const requireString = (field) => {
12
+ const v = data[field];
13
+ if (typeof v === "string" && v.length > 0)
14
+ return v;
15
+ if (v === undefined || v === null || v === "") {
16
+ issues.push({ field, message: "missing required field" });
17
+ }
18
+ else {
19
+ issues.push({ field, message: `expected string, got ${typeof v}` });
20
+ }
21
+ return "";
22
+ };
23
+ const requireEnum = (field, allowed, fallback) => {
24
+ const v = data[field];
25
+ if (typeof v === "string" && allowed.includes(v)) {
26
+ return v;
27
+ }
28
+ if (v === undefined || v === null) {
29
+ issues.push({ field, message: "missing required field" });
30
+ }
31
+ else {
32
+ issues.push({
33
+ field,
34
+ message: `expected one of [${allowed.join(", ")}], got ${JSON.stringify(v)}`,
35
+ });
36
+ }
37
+ return fallback;
38
+ };
39
+ const requireDate = (field) => {
40
+ const v = data[field];
41
+ // js-yaml parses unquoted ISO dates into Date objects.
42
+ if (v instanceof Date && !Number.isNaN(v.getTime())) {
43
+ return v.toISOString().slice(0, 10);
44
+ }
45
+ if (typeof v === "string") {
46
+ if (/^\d{4}-\d{2}-\d{2}$/.test(v))
47
+ return v;
48
+ issues.push({ field, message: `expected YYYY-MM-DD date, got "${v}"` });
49
+ return v;
50
+ }
51
+ if (v === undefined || v === null) {
52
+ issues.push({ field, message: "missing required field" });
53
+ }
54
+ else {
55
+ issues.push({ field, message: `expected date, got ${typeof v}` });
56
+ }
57
+ return "";
58
+ };
59
+ // Optional arrays default to []; only malformed values are flagged.
60
+ const optionalStringArray = (field) => {
61
+ const v = data[field];
62
+ if (v === undefined || v === null)
63
+ return [];
64
+ if (Array.isArray(v)) {
65
+ const out = [];
66
+ v.forEach((item, i) => {
67
+ if (typeof item === "string")
68
+ out.push(item);
69
+ else
70
+ issues.push({ field, message: `element ${i} is not a string` });
71
+ });
72
+ return out;
73
+ }
74
+ issues.push({ field, message: `expected array, got ${typeof v}` });
75
+ return [];
76
+ };
77
+ const optionalString = (field) => {
78
+ const v = data[field];
79
+ if (v === undefined || v === null)
80
+ return null;
81
+ if (typeof v === "string")
82
+ return v;
83
+ issues.push({ field, message: `expected string or null, got ${typeof v}` });
84
+ return null;
85
+ };
86
+ const optionalNumber = (field) => {
87
+ const v = data[field];
88
+ if (v === undefined || v === null)
89
+ return null;
90
+ if (typeof v === "number" && Number.isFinite(v))
91
+ return v;
92
+ issues.push({ field, message: `expected number or null, got ${typeof v}` });
93
+ return null;
94
+ };
95
+ const frontmatter = {
96
+ title: requireString("title"),
97
+ domain: requireEnum("domain", DOMAINS, "accumulation"),
98
+ collection: requireString("collection"),
99
+ status: requireEnum("status", STATUSES, "draft"),
100
+ confidence: requireEnum("confidence", CONFIDENCES, "low"),
101
+ created: requireDate("created"),
102
+ updated: requireDate("updated"),
103
+ updated_by: requireString("updated_by"),
104
+ provenance: requireEnum("provenance", PROVENANCES, "inferred"),
105
+ sources: optionalStringArray("sources"),
106
+ superseded_by: optionalString("superseded_by"),
107
+ ttl_days: optionalNumber("ttl_days"),
108
+ tags: optionalStringArray("tags"),
109
+ };
110
+ return {
111
+ frontmatter,
112
+ report: { valid: issues.length === 0, issues },
113
+ };
114
+ }
115
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/frontmatter/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ export type Result<T, E = Error> = {
2
+ ok: true;
3
+ value: T;
4
+ } | {
5
+ ok: false;
6
+ error: E;
7
+ };
8
+ export declare const ok: <T>(value: T) => Result<T, never>;
9
+ export declare const err: <E = Error>(error: E) => Result<never, E>;
10
+ export declare const DOMAINS: readonly ["accumulation", "generative"];
11
+ export type Domain = (typeof DOMAINS)[number];
12
+ export declare const STATUSES: readonly ["draft", "canonical", "deprecated", "superseded", "archived"];
13
+ export type Status = (typeof STATUSES)[number];
14
+ export declare const CONFIDENCES: readonly ["low", "medium", "high"];
15
+ export type Confidence = (typeof CONFIDENCES)[number];
16
+ export declare const PROVENANCES: readonly ["direct", "synthesized", "inferred"];
17
+ export type Provenance = (typeof PROVENANCES)[number];
18
+ export interface Frontmatter {
19
+ title: string;
20
+ domain: Domain;
21
+ collection: string;
22
+ status: Status;
23
+ confidence: Confidence;
24
+ created: string;
25
+ updated: string;
26
+ updated_by: string;
27
+ provenance: Provenance;
28
+ sources: string[];
29
+ superseded_by: string | null;
30
+ ttl_days: number | null;
31
+ tags: string[];
32
+ }
33
+ export interface ValidationIssue {
34
+ field: string;
35
+ message: string;
36
+ }
37
+ export interface ValidationReport {
38
+ valid: boolean;
39
+ issues: ValidationIssue[];
40
+ }
41
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/frontmatter/types.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,IAAI;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC;AAEpF,eAAO,MAAM,EAAE,GAAI,CAAC,EAAE,OAAO,CAAC,KAAG,MAAM,CAAC,CAAC,EAAE,KAAK,CAA0B,CAAC;AAC3E,eAAO,MAAM,GAAG,GAAI,CAAC,GAAG,KAAK,EAAE,OAAO,CAAC,KAAG,MAAM,CAAC,KAAK,EAAE,CAAC,CAA2B,CAAC;AAErF,eAAO,MAAM,OAAO,yCAA0C,CAAC;AAC/D,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9C,eAAO,MAAM,QAAQ,yEAA0E,CAAC;AAChG,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/C,eAAO,MAAM,WAAW,oCAAqC,CAAC;AAC9D,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtD,eAAO,MAAM,WAAW,gDAAiD,CAAC;AAC1E,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAItD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAID,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B"}
@@ -0,0 +1,8 @@
1
+ // Core shared types for Daftari: the Result pattern and the frontmatter schema.
2
+ export const ok = (value) => ({ ok: true, value });
3
+ export const err = (error) => ({ ok: false, error });
4
+ export const DOMAINS = ["accumulation", "generative"];
5
+ export const STATUSES = ["draft", "canonical", "deprecated", "superseded", "archived"];
6
+ export const CONFIDENCES = ["low", "medium", "high"];
7
+ export const PROVENANCES = ["direct", "synthesized", "inferred"];
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/frontmatter/types.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAMhF,MAAM,CAAC,MAAM,EAAE,GAAG,CAAI,KAAQ,EAAoB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC3E,MAAM,CAAC,MAAM,GAAG,GAAG,CAAY,KAAQ,EAAoB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;AAErF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,cAAc,EAAE,YAAY,CAAU,CAAC;AAG/D,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,CAAU,CAAC;AAGhG,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAU,CAAC;AAG9D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAU,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function parseFlag(argv: string[], name: string): string | null;
2
+ export declare function parseVaultArg(argv: string[]): string | null;
3
+ export declare function main(argv?: string[]): Promise<void>;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmBA,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASrE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAE3D;AAED,wBAAsB,IAAI,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CA6DhF"}
package/dist/index.js ADDED
@@ -0,0 +1,94 @@
1
+ // Daftari MCP server entry point.
2
+ //
3
+ // Parses `--vault <path>`, verifies the vault directory exists, loads the RBAC
4
+ // config, builds the search index, then serves the tools over stdio under the
5
+ // access identity given by `--user` / `--role`. Diagnostics go to stderr so
6
+ // they never corrupt the stdio JSON-RPC stream on stdout.
7
+ //
8
+ // `--reindex` rebuilds the search index and exits without starting the server.
9
+ import { resolve } from "node:path";
10
+ import { pathToFileURL } from "node:url";
11
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
12
+ import { GUEST_ROLE, resolveAccess } from "./access/rbac.js";
13
+ import { reindexVault } from "./search/reindex.js";
14
+ import { createServer } from "./server.js";
15
+ import { directoryExists } from "./storage/local.js";
16
+ import { loadConfig } from "./utils/config.js";
17
+ // Reads `--name value` or `--name=value` from argv; null if absent.
18
+ export function parseFlag(argv, name) {
19
+ const flag = `--${name}`;
20
+ const flagIndex = argv.indexOf(flag);
21
+ if (flagIndex !== -1 && flagIndex + 1 < argv.length) {
22
+ return argv[flagIndex + 1] ?? null;
23
+ }
24
+ const inline = argv.find((a) => a.startsWith(`${flag}=`));
25
+ if (inline)
26
+ return inline.slice(`${flag}=`.length);
27
+ return null;
28
+ }
29
+ export function parseVaultArg(argv) {
30
+ return parseFlag(argv, "vault");
31
+ }
32
+ export async function main(argv = process.argv.slice(2)) {
33
+ const vaultArg = parseVaultArg(argv);
34
+ if (!vaultArg) {
35
+ process.stderr.write("daftari: missing required --vault <path> argument\n");
36
+ process.exitCode = 1;
37
+ return;
38
+ }
39
+ const vaultRoot = resolve(vaultArg);
40
+ if (!(await directoryExists(vaultRoot))) {
41
+ process.stderr.write(`daftari: vault directory not found: ${vaultRoot}\n`);
42
+ process.exitCode = 1;
43
+ return;
44
+ }
45
+ // Load the RBAC config. A malformed config fails loud: the server must not
46
+ // start serving content under a policy it could not parse.
47
+ const config = loadConfig(vaultRoot);
48
+ if (!config.ok) {
49
+ process.stderr.write(`daftari: ${config.error.message}\n`);
50
+ process.exitCode = 1;
51
+ return;
52
+ }
53
+ // Resolve the access identity. With no --role the server runs as the
54
+ // deny-all guest; an unknown role name resolves the same way.
55
+ const user = parseFlag(argv, "user") ?? "guest";
56
+ const roleName = parseFlag(argv, "role") ?? GUEST_ROLE;
57
+ const access = resolveAccess(config.value, user, roleName);
58
+ if (access.role === null && roleName !== GUEST_ROLE) {
59
+ process.stderr.write(`daftari: warning: role '${roleName}' not found in config — running as deny-all guest\n`);
60
+ }
61
+ // Build (or rebuild) the search index. With --reindex this is the whole job.
62
+ const reindexed = await reindexVault(vaultRoot);
63
+ if (reindexed.ok) {
64
+ const r = reindexed.value;
65
+ process.stderr.write(`daftari: indexed ${r.documentCount} docs, ${r.chunkCount} chunks ` +
66
+ `(vectors ${r.vectorEnabled ? "on" : "off"})\n`);
67
+ }
68
+ else {
69
+ // A failed index is not fatal: lexical search still works and the search
70
+ // tools retry indexing lazily on first use.
71
+ process.stderr.write(`daftari: warning: index build failed: ${reindexed.error.message}\n`);
72
+ }
73
+ if (argv.includes("--reindex")) {
74
+ if (!reindexed.ok)
75
+ process.exitCode = 1;
76
+ return;
77
+ }
78
+ const server = createServer(vaultRoot, access);
79
+ const transport = new StdioServerTransport();
80
+ await server.connect(transport);
81
+ process.stderr.write(`daftari: serving vault at ${vaultRoot} (stdio) — ` +
82
+ `user=${access.user} role=${access.roleName}\n`);
83
+ }
84
+ // Auto-run only when this module is the process entry point (e.g. `tsx
85
+ // src/index.ts`). When imported (by cli.ts or tests) it stays inert.
86
+ const entryUrl = pathToFileURL(process.argv[1] ?? "").href;
87
+ if (import.meta.url === entryUrl) {
88
+ main().catch((e) => {
89
+ const reason = e instanceof Error ? (e.stack ?? e.message) : String(e);
90
+ process.stderr.write(`daftari: fatal: ${reason}\n`);
91
+ process.exitCode = 1;
92
+ });
93
+ }
94
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export declare function tokenize(text: string): string[];
2
+ export interface Bm25Document {
3
+ path: string;
4
+ tokens: string[];
5
+ }
6
+ export interface Bm25Model {
7
+ termFreqs: Map<string, Map<string, number>>;
8
+ docFreqs: Map<string, number>;
9
+ docLengths: Map<string, number>;
10
+ docCount: number;
11
+ avgDocLength: number;
12
+ }
13
+ export declare function buildBm25(docs: Bm25Document[]): Bm25Model;
14
+ export interface Bm25Hit {
15
+ path: string;
16
+ score: number;
17
+ }
18
+ export declare function searchBm25(model: Bm25Model, queryTokens: string[]): Bm25Hit[];
19
+ //# sourceMappingURL=bm25.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bm25.d.ts","sourceRoot":"","sources":["../../src/search/bm25.ts"],"names":[],"mappings":"AA4DA,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAK/C;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IAExB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAE5C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE9B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,SAAS,CA0BzD;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAKD,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,CAsB7E"}