@wrenautomation/knowledge 0.0.0-stage → 0.59.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.md +61 -0
- package/README.md +94 -2
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +234 -0
- package/dist/cli.js.map +1 -0
- package/dist/git.d.ts +20 -0
- package/dist/git.js +83 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/lint.d.ts +13 -0
- package/dist/lint.js +56 -0
- package/dist/lint.js.map +1 -0
- package/dist/push.d.ts +15 -0
- package/dist/push.js +52 -0
- package/dist/push.js.map +1 -0
- package/dist/record-index.d.ts +458 -0
- package/dist/record-index.js +247 -0
- package/dist/record-index.js.map +1 -0
- package/dist/records.d.ts +263 -0
- package/dist/records.js +162 -0
- package/dist/records.js.map +1 -0
- package/dist/render.d.ts +6 -0
- package/dist/render.js +37 -0
- package/dist/render.js.map +1 -0
- package/dist/repo.d.ts +30 -0
- package/dist/repo.js +75 -0
- package/dist/repo.js.map +1 -0
- package/dist/write.d.ts +51 -0
- package/dist/write.js +175 -0
- package/dist/write.js.map +1 -0
- package/package.json +46 -3
package/dist/records.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A record: one markdown file, frontmatter + body. Design: wren/designs/2026-11-09-knowledge-repo.md.
|
|
3
|
+
* Unknown frontmatter keys are kept (never drop data); key order on write is fixed, so diffs stay small.
|
|
4
|
+
*/
|
|
5
|
+
import { randomBytes } from "node:crypto";
|
|
6
|
+
import matter from "gray-matter";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
export const TYPES = ["source", "finding", "verdict", "rule", "guide"];
|
|
9
|
+
export const DIRS = {
|
|
10
|
+
source: "sources",
|
|
11
|
+
finding: "findings",
|
|
12
|
+
verdict: "verdicts",
|
|
13
|
+
rule: "rules",
|
|
14
|
+
guide: "guides",
|
|
15
|
+
};
|
|
16
|
+
// readable ids: a source keeps its natural one (youtube-uSTGNHGFOAo); new ones are slug + random tail
|
|
17
|
+
export const Id = z
|
|
18
|
+
.string()
|
|
19
|
+
.regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/, "id: letters, digits, . _ -");
|
|
20
|
+
// YAML reads a bare timestamp as a Date; every stamp is stored as a full UTC ISO string
|
|
21
|
+
const Stamp = z.preprocess((v) => (v instanceof Date ? v.toISOString() : v), z.string().refine((s) => !Number.isNaN(Date.parse(s)), "not a date"));
|
|
22
|
+
const Text = z.preprocess((v) => (typeof v === "number" ? String(v) : v), z.string());
|
|
23
|
+
const base = {
|
|
24
|
+
id: Id,
|
|
25
|
+
title: z.string().min(1),
|
|
26
|
+
status: z.enum(["live", "retired"]),
|
|
27
|
+
version: z.number().int().positive(),
|
|
28
|
+
by: z.string().min(1),
|
|
29
|
+
why: z.string().min(1),
|
|
30
|
+
cites: z.array(Id).default([]),
|
|
31
|
+
tags: z.array(z.string()).default([]),
|
|
32
|
+
created: Stamp,
|
|
33
|
+
updated: Stamp,
|
|
34
|
+
};
|
|
35
|
+
export const SOURCE_KINDS = [
|
|
36
|
+
"site",
|
|
37
|
+
"page",
|
|
38
|
+
"video",
|
|
39
|
+
"reel",
|
|
40
|
+
"post",
|
|
41
|
+
"person",
|
|
42
|
+
"tool",
|
|
43
|
+
"doc",
|
|
44
|
+
"paper",
|
|
45
|
+
"feed",
|
|
46
|
+
"repo",
|
|
47
|
+
"list",
|
|
48
|
+
"other",
|
|
49
|
+
];
|
|
50
|
+
export const Source = z.looseObject({
|
|
51
|
+
...base,
|
|
52
|
+
type: z.literal("source"),
|
|
53
|
+
kind: z.enum(SOURCE_KINDS),
|
|
54
|
+
url: z.url().optional(),
|
|
55
|
+
handle: z.string().optional(),
|
|
56
|
+
// 1 (low) to 9: how much a build leans on it
|
|
57
|
+
priority: z.number().int().min(1).max(9).optional(),
|
|
58
|
+
// a file in the media bucket, by content hash
|
|
59
|
+
media: z.object({ sha256: z.string().regex(/^[0-9a-f]{64}$/), type: z.string() }).optional(),
|
|
60
|
+
});
|
|
61
|
+
export const Finding = z.looseObject({
|
|
62
|
+
...base,
|
|
63
|
+
type: z.literal("finding"),
|
|
64
|
+
source: Id,
|
|
65
|
+
// the source's own words; a point extracted in paraphrase has none
|
|
66
|
+
quote: z.string().min(1).optional(),
|
|
67
|
+
page: z.url().optional(),
|
|
68
|
+
// where in the source: a time (0:16), a page, a slide
|
|
69
|
+
at: Text.optional(),
|
|
70
|
+
run: z.string().optional(),
|
|
71
|
+
});
|
|
72
|
+
export const Verdict = z.looseObject({
|
|
73
|
+
...base,
|
|
74
|
+
type: z.literal("verdict"),
|
|
75
|
+
from: z.enum(["vireo", "orrery", "owner", "other"]),
|
|
76
|
+
// the producer's own handle: a Vireo batch ref (hero:3), a lane id
|
|
77
|
+
ref: z.string().min(1),
|
|
78
|
+
score: z.number().optional(),
|
|
79
|
+
});
|
|
80
|
+
export const Rule = z.looseObject({
|
|
81
|
+
...base,
|
|
82
|
+
type: z.literal("rule"),
|
|
83
|
+
topic: z.string().regex(/^[a-z0-9][a-z0-9-]*$/, "topic: lowercase slug"),
|
|
84
|
+
order: z.number().optional(),
|
|
85
|
+
});
|
|
86
|
+
const Topic = z.string().regex(/^[a-z0-9][a-z0-9-]*$/, "topic: lowercase slug");
|
|
87
|
+
// a procedure (an SOP) as one doc: body cites [n] or [n 0:16], n = 1-based index into cites
|
|
88
|
+
export const Guide = z.looseObject({
|
|
89
|
+
...base,
|
|
90
|
+
type: z.literal("guide"),
|
|
91
|
+
topic: Topic,
|
|
92
|
+
// one line: what the guide is for (a skill's description)
|
|
93
|
+
description: z.string().optional(),
|
|
94
|
+
});
|
|
95
|
+
export const Frontmatter = z.discriminatedUnion("type", [Source, Finding, Verdict, Rule, Guide]);
|
|
96
|
+
/** Where a record lives in the repo. A rule sits under its topic. */
|
|
97
|
+
export function pathOf(fm) {
|
|
98
|
+
const dir = DIRS[fm.type];
|
|
99
|
+
return fm.type === "rule" ? `${dir}/${String(fm.topic)}/${fm.id}.md` : `${dir}/${fm.id}.md`;
|
|
100
|
+
}
|
|
101
|
+
/** `[n]` and `[n 0:16]` in a guide's body: n is the place in its cites. */
|
|
102
|
+
export const CITE_NUMBER = /\[(\d+)((?: (?:\d{1,2}:\d{2}(?::\d{2})?(?:, \d{1,2}:\d{2}(?::\d{2})?)*|caption))?)\]/g;
|
|
103
|
+
/** The ids a record leans on: its cites, and a finding's source. */
|
|
104
|
+
export function edgesOf(fm) {
|
|
105
|
+
return [...new Set(fm.type === "finding" ? [...fm.cites, fm.source] : fm.cites)];
|
|
106
|
+
}
|
|
107
|
+
const B32 = "0123456789abcdefghjkmnpqrstvwxyz";
|
|
108
|
+
export function newId(title) {
|
|
109
|
+
const slug = title
|
|
110
|
+
.toLowerCase()
|
|
111
|
+
.normalize("NFKD")
|
|
112
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
113
|
+
.replace(/^-+|-+$/g, "")
|
|
114
|
+
.slice(0, 40)
|
|
115
|
+
.replace(/-+$/, "");
|
|
116
|
+
const tail = [...randomBytes(6)].map((b) => B32[b % 32]).join("");
|
|
117
|
+
return slug ? `${slug}-${tail}` : tail;
|
|
118
|
+
}
|
|
119
|
+
export function parse(text) {
|
|
120
|
+
let m;
|
|
121
|
+
try {
|
|
122
|
+
// options object: gray-matter caches option-less calls by text and hands back one shared object
|
|
123
|
+
m = matter(text, {});
|
|
124
|
+
}
|
|
125
|
+
catch (e) {
|
|
126
|
+
return { ok: false, error: `frontmatter: ${e.message.split("\n")[0]}` };
|
|
127
|
+
}
|
|
128
|
+
const r = Frontmatter.safeParse(m.data);
|
|
129
|
+
if (!r.success)
|
|
130
|
+
return {
|
|
131
|
+
ok: false,
|
|
132
|
+
error: r.error.issues
|
|
133
|
+
.map((i) => `${i.path.join(".") || "frontmatter"}: ${i.message}`)
|
|
134
|
+
.join("; "),
|
|
135
|
+
};
|
|
136
|
+
const fm = r.data;
|
|
137
|
+
fm.created = new Date(fm.created).toISOString();
|
|
138
|
+
fm.updated = new Date(fm.updated).toISOString();
|
|
139
|
+
return { ok: true, doc: { fm, body: m.content.replace(/^\n+/, "").replace(/\s+$/, "") } };
|
|
140
|
+
}
|
|
141
|
+
const HEAD = ["id", "type", "title", "status", "version", "by", "why", "cites", "tags"];
|
|
142
|
+
const TAIL = ["created", "updated"];
|
|
143
|
+
export function serialize(doc) {
|
|
144
|
+
const fm = doc.fm;
|
|
145
|
+
const out = {};
|
|
146
|
+
const put = (k) => {
|
|
147
|
+
const v = fm[k];
|
|
148
|
+
if (v === undefined || (Array.isArray(v) && v.length === 0))
|
|
149
|
+
return;
|
|
150
|
+
out[k] = v;
|
|
151
|
+
};
|
|
152
|
+
for (const k of HEAD)
|
|
153
|
+
put(k);
|
|
154
|
+
for (const k of Object.keys(fm)
|
|
155
|
+
.filter((k) => !HEAD.includes(k) && !TAIL.includes(k))
|
|
156
|
+
.sort())
|
|
157
|
+
put(k);
|
|
158
|
+
for (const k of TAIL)
|
|
159
|
+
put(k);
|
|
160
|
+
return matter.stringify(doc.body ? `\n${doc.body}\n` : "", out);
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=records.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"records.js","sourceRoot":"","sources":["../src/records.ts"],"names":[],"mappings":"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"}
|
package/dist/render.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Doc, type Frontmatter } from "./records.js";
|
|
2
|
+
/** One record by id: the flat folders first, else a walk (a rule sits under its topic). */
|
|
3
|
+
export declare function readRecord(root: string, id: string): Doc | null;
|
|
4
|
+
/** `n. id, "title", handle, url`: the line a cite gets in the list. */
|
|
5
|
+
export declare function citeLine(n: number, id: string, fm: Frontmatter | undefined): string;
|
|
6
|
+
export declare function render(root: string, id: string): string;
|
package/dist/render.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A record as one markdown doc for a reader or a skill: the body, then its cites as a numbered
|
|
3
|
+
* `## Sources` list (a guide's `[n]` points into it). Reads the working tree, only the files it needs.
|
|
4
|
+
*/
|
|
5
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { DIRS, parse } from "./records.js";
|
|
8
|
+
import { loadWorking } from "./repo.js";
|
|
9
|
+
/** One record by id: the flat folders first, else a walk (a rule sits under its topic). */
|
|
10
|
+
export function readRecord(root, id) {
|
|
11
|
+
for (const dir of Object.values(DIRS)) {
|
|
12
|
+
const f = join(root, dir, `${id}.md`);
|
|
13
|
+
if (!existsSync(f))
|
|
14
|
+
continue;
|
|
15
|
+
const p = parse(readFileSync(f, "utf8"));
|
|
16
|
+
if (p.ok && p.doc.fm.id === id)
|
|
17
|
+
return p.doc;
|
|
18
|
+
}
|
|
19
|
+
return loadWorking(root).docs.find((d) => d.doc.fm.id === id)?.doc ?? null;
|
|
20
|
+
}
|
|
21
|
+
/** `n. id, "title", handle, url`: the line a cite gets in the list. */
|
|
22
|
+
export function citeLine(n, id, fm) {
|
|
23
|
+
const f = (fm ?? {});
|
|
24
|
+
const parts = [id, f.title ? `"${f.title}"` : "", f.handle, f.url].filter((x) => typeof x === "string" && x !== "");
|
|
25
|
+
return `${n}. ${parts.join(", ")}`;
|
|
26
|
+
}
|
|
27
|
+
export function render(root, id) {
|
|
28
|
+
const doc = readRecord(root, id);
|
|
29
|
+
if (!doc)
|
|
30
|
+
throw new Error(`no record ${id}`);
|
|
31
|
+
const { fm, body } = doc;
|
|
32
|
+
if (!fm.cites.length)
|
|
33
|
+
return `${body}\n`;
|
|
34
|
+
const lines = fm.cites.map((c, i) => citeLine(i + 1, c, readRecord(root, c)?.fm));
|
|
35
|
+
return `${body}\n\n## Sources\n\n${lines.join("\n")}\n`;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,IAAI,EAA8B,KAAK,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,2FAA2F;AAC3F,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,EAAU;IACjD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QACtC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,SAAS;QAC7B,MAAM,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QACzC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE;YAAE,OAAO,CAAC,CAAC,GAAG,CAAC;IAC/C,CAAC;IACD,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,IAAI,CAAC;AAC7E,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,QAAQ,CAAC,CAAS,EAAE,EAAU,EAAE,EAA2B;IACzE,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAA4B,CAAC;IAChD,MAAM,KAAK,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CACvE,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,EAAE,CACtD,CAAC;IACF,OAAO,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,IAAY,EAAE,EAAU;IAC7C,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACjC,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IAC7C,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC;IACzB,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,GAAG,IAAI,IAAI,CAAC;IACzC,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAClF,OAAO,GAAG,IAAI,qBAAqB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AAC1D,CAAC"}
|
package/dist/repo.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type Doc } from "./records.js";
|
|
3
|
+
export declare const CONFIG = "knowledge.json";
|
|
4
|
+
export declare const RECORD_DIRS: string[];
|
|
5
|
+
export declare const Config: z.ZodObject<{
|
|
6
|
+
owner: z.ZodDefault<z.ZodString>;
|
|
7
|
+
push: z.ZodDefault<z.ZodBoolean>;
|
|
8
|
+
remote: z.ZodDefault<z.ZodString>;
|
|
9
|
+
}, z.core.$loose>;
|
|
10
|
+
export type Config = z.infer<typeof Config>;
|
|
11
|
+
/** The repo root: `dir`, else the nearest folder up from cwd with a knowledge.json. */
|
|
12
|
+
export declare function findRoot(dir?: string): string;
|
|
13
|
+
export declare function loadConfig(root: string): Config;
|
|
14
|
+
export interface Loaded {
|
|
15
|
+
path: string;
|
|
16
|
+
doc: Doc;
|
|
17
|
+
}
|
|
18
|
+
export interface Broken {
|
|
19
|
+
path: string;
|
|
20
|
+
error: string;
|
|
21
|
+
}
|
|
22
|
+
export interface Tree {
|
|
23
|
+
docs: Loaded[];
|
|
24
|
+
broken: Broken[];
|
|
25
|
+
}
|
|
26
|
+
/** The working tree's records (uncommitted edits included). */
|
|
27
|
+
export declare function loadWorking(root: string): Tree;
|
|
28
|
+
/** The records at a commit: what the index and a server hook see. */
|
|
29
|
+
export declare function loadAt(root: string, rev: string): Tree;
|
|
30
|
+
export declare function readPathsAt(root: string, rev: string, paths: string[]): Tree;
|
package/dist/repo.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/** A repo's records, read from the working tree or from a commit, and its config. */
|
|
2
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join, relative, resolve } from "node:path";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { lsTree, readAt } from "./git.js";
|
|
6
|
+
import { DIRS, parse } from "./records.js";
|
|
7
|
+
export const CONFIG = "knowledge.json";
|
|
8
|
+
export const RECORD_DIRS = Object.values(DIRS);
|
|
9
|
+
export const Config = z.looseObject({
|
|
10
|
+
// who may write a rule with no cites: the person whose own word is the evidence
|
|
11
|
+
owner: z.string().default("owner"),
|
|
12
|
+
// write commands push after their commit
|
|
13
|
+
push: z.boolean().default(false),
|
|
14
|
+
remote: z.string().default("origin"),
|
|
15
|
+
});
|
|
16
|
+
/** The repo root: `dir`, else the nearest folder up from cwd with a knowledge.json. */
|
|
17
|
+
export function findRoot(dir) {
|
|
18
|
+
if (dir)
|
|
19
|
+
return resolve(dir);
|
|
20
|
+
let at = process.cwd();
|
|
21
|
+
for (;;) {
|
|
22
|
+
if (existsSync(join(at, CONFIG)))
|
|
23
|
+
return at;
|
|
24
|
+
const up = dirname(at);
|
|
25
|
+
if (up === at)
|
|
26
|
+
throw new Error(`no ${CONFIG} here or above; pass --repo or set KNOWLEDGE_DIR`);
|
|
27
|
+
at = up;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export function loadConfig(root) {
|
|
31
|
+
const p = join(root, CONFIG);
|
|
32
|
+
return Config.parse(existsSync(p) ? JSON.parse(readFileSync(p, "utf8")) : {});
|
|
33
|
+
}
|
|
34
|
+
function collect(files) {
|
|
35
|
+
const docs = [];
|
|
36
|
+
const broken = [];
|
|
37
|
+
for (const [path, text] of files) {
|
|
38
|
+
const r = parse(text);
|
|
39
|
+
if (r.ok)
|
|
40
|
+
docs.push({ path, doc: r.doc });
|
|
41
|
+
else
|
|
42
|
+
broken.push({ path, error: r.error });
|
|
43
|
+
}
|
|
44
|
+
return { docs, broken };
|
|
45
|
+
}
|
|
46
|
+
const isRecord = (p) => p.endsWith(".md") && !p.split("/").pop()?.startsWith("_");
|
|
47
|
+
/** The working tree's records (uncommitted edits included). */
|
|
48
|
+
export function loadWorking(root) {
|
|
49
|
+
const files = new Map();
|
|
50
|
+
const walk = (dir) => {
|
|
51
|
+
if (!existsSync(dir))
|
|
52
|
+
return;
|
|
53
|
+
for (const e of readdirSync(dir, { withFileTypes: true })) {
|
|
54
|
+
const full = join(dir, e.name);
|
|
55
|
+
if (e.isDirectory())
|
|
56
|
+
walk(full);
|
|
57
|
+
else {
|
|
58
|
+
const rel = relative(root, full);
|
|
59
|
+
if (isRecord(rel))
|
|
60
|
+
files.set(rel, readFileSync(full, "utf8"));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
for (const d of RECORD_DIRS)
|
|
65
|
+
walk(join(root, d));
|
|
66
|
+
return collect(files);
|
|
67
|
+
}
|
|
68
|
+
/** The records at a commit: what the index and a server hook see. */
|
|
69
|
+
export function loadAt(root, rev) {
|
|
70
|
+
return collect(readAt(root, rev, lsTree(root, rev, RECORD_DIRS).filter(isRecord)));
|
|
71
|
+
}
|
|
72
|
+
export function readPathsAt(root, rev, paths) {
|
|
73
|
+
return collect(readAt(root, rev, paths.filter(isRecord)));
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=repo.js.map
|
package/dist/repo.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo.js","sourceRoot":"","sources":["../src/repo.ts"],"names":[],"mappings":"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"}
|
package/dist/write.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type Problem } from "./lint.js";
|
|
2
|
+
import { type RecordType } from "./records.js";
|
|
3
|
+
import { type Loaded } from "./repo.js";
|
|
4
|
+
export type Change = {
|
|
5
|
+
op: "add";
|
|
6
|
+
type: RecordType;
|
|
7
|
+
title: string;
|
|
8
|
+
body?: string;
|
|
9
|
+
id?: string;
|
|
10
|
+
[k: string]: unknown;
|
|
11
|
+
} | {
|
|
12
|
+
op: "edit";
|
|
13
|
+
id: string;
|
|
14
|
+
body?: string;
|
|
15
|
+
[k: string]: unknown;
|
|
16
|
+
} | {
|
|
17
|
+
op: "retire";
|
|
18
|
+
id: string;
|
|
19
|
+
};
|
|
20
|
+
export interface Who {
|
|
21
|
+
by: string;
|
|
22
|
+
why: string;
|
|
23
|
+
}
|
|
24
|
+
export declare class LintError extends Error {
|
|
25
|
+
readonly problems: Problem[];
|
|
26
|
+
name: string;
|
|
27
|
+
constructor(problems: Problem[]);
|
|
28
|
+
}
|
|
29
|
+
/** Serialize work on one checkout: writes, syncs, and reads of a PGlite index. */
|
|
30
|
+
export declare function withLock<T>(root: string, fn: () => Promise<T>): Promise<T>;
|
|
31
|
+
export interface Written {
|
|
32
|
+
commit: string;
|
|
33
|
+
records: {
|
|
34
|
+
id: string;
|
|
35
|
+
type: RecordType;
|
|
36
|
+
path: string;
|
|
37
|
+
version: number;
|
|
38
|
+
op: Change["op"];
|
|
39
|
+
}[];
|
|
40
|
+
warnings: Problem[];
|
|
41
|
+
}
|
|
42
|
+
export declare function apply(docs: Loaded[], changes: Change[], who: Who, now?: Date): {
|
|
43
|
+
next: Loaded[];
|
|
44
|
+
touched: {
|
|
45
|
+
id: string;
|
|
46
|
+
op: Change["op"];
|
|
47
|
+
from?: string;
|
|
48
|
+
}[];
|
|
49
|
+
};
|
|
50
|
+
/** Apply, lint, write, commit. Throws LintError (nothing written) or the commit's error (files restored). */
|
|
51
|
+
export declare function write(root: string, changes: Change[], who: Who): Promise<Written>;
|
package/dist/write.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One write = one commit. Changes apply to the tree in memory, the whole tree is linted, then the files
|
|
3
|
+
* land and commit together; a failed commit puts every file back. A lock serializes writers in one
|
|
4
|
+
* checkout; across checkouts, push is the compare-and-swap (push.ts).
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { dirname, join } from "node:path";
|
|
8
|
+
import lockfile from "proper-lockfile";
|
|
9
|
+
import { git, head } from "./git.js";
|
|
10
|
+
import { errors, lint } from "./lint.js";
|
|
11
|
+
import { Frontmatter, newId, pathOf, serialize } from "./records.js";
|
|
12
|
+
import { loadConfig, loadWorking } from "./repo.js";
|
|
13
|
+
export class LintError extends Error {
|
|
14
|
+
problems;
|
|
15
|
+
name = "LintError";
|
|
16
|
+
constructor(problems) {
|
|
17
|
+
super(problems.map((p) => `${p.path}: ${p.msg}`).join("\n"));
|
|
18
|
+
this.problems = problems;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// fields the store owns: a change never sets them
|
|
22
|
+
const OWNED = new Set(["op", "type", "version", "created", "updated", "by", "why", "status"]);
|
|
23
|
+
/** Serialize work on one checkout: writes, syncs, and reads of a PGlite index. */
|
|
24
|
+
export async function withLock(root, fn) {
|
|
25
|
+
const gitDir = join(root, git(root, ["rev-parse", "--git-dir"]));
|
|
26
|
+
const release = await lockfile.lock(root, {
|
|
27
|
+
lockfilePath: join(gitDir, "knowledge.lock"),
|
|
28
|
+
retries: { retries: 120, minTimeout: 50, maxTimeout: 1000 },
|
|
29
|
+
stale: 60_000,
|
|
30
|
+
});
|
|
31
|
+
try {
|
|
32
|
+
return await fn();
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
await release();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export function apply(docs, changes, who, now = new Date()) {
|
|
39
|
+
const stamp = now.toISOString();
|
|
40
|
+
const byId = new Map(docs.map((l) => [l.doc.fm.id, l]));
|
|
41
|
+
const touched = [];
|
|
42
|
+
for (const c of changes) {
|
|
43
|
+
if (c.op === "add") {
|
|
44
|
+
const { op: _op, body, ...rest } = c;
|
|
45
|
+
const id = c.id ?? newId(c.title);
|
|
46
|
+
if (byId.has(id))
|
|
47
|
+
throw new Error(`add: ${id} is already in the repo`);
|
|
48
|
+
const fields = Object.fromEntries(Object.entries(rest).filter(([k]) => !OWNED.has(k)));
|
|
49
|
+
const fm = Frontmatter.parse({
|
|
50
|
+
...fields,
|
|
51
|
+
id,
|
|
52
|
+
type: c.type,
|
|
53
|
+
status: "live",
|
|
54
|
+
version: 1,
|
|
55
|
+
by: who.by,
|
|
56
|
+
why: rest.why ?? who.why,
|
|
57
|
+
created: stamp,
|
|
58
|
+
updated: stamp,
|
|
59
|
+
});
|
|
60
|
+
byId.set(id, { path: pathOf(fm), doc: { fm, body: (body ?? "").trim() } });
|
|
61
|
+
touched.push({ id, op: "add" });
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const cur = byId.get(c.id);
|
|
65
|
+
if (!cur)
|
|
66
|
+
throw new Error(`${c.op}: no record ${c.id}`);
|
|
67
|
+
const old = cur.doc.fm;
|
|
68
|
+
let fm;
|
|
69
|
+
let body = cur.doc.body;
|
|
70
|
+
if (c.op === "retire") {
|
|
71
|
+
if (old.status === "retired")
|
|
72
|
+
throw new Error(`retire: ${c.id} is already retired`);
|
|
73
|
+
fm = Frontmatter.parse({ ...old, status: "retired" });
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
const { op: _op, id: _id, body: b, ...patch } = c;
|
|
77
|
+
for (const k of Object.keys(patch))
|
|
78
|
+
if (OWNED.has(k) || k === "id")
|
|
79
|
+
throw new Error(`edit: ${k} is set by the store`);
|
|
80
|
+
// null drops an optional field
|
|
81
|
+
const merged = { ...old, ...patch };
|
|
82
|
+
for (const [k, v] of Object.entries(merged))
|
|
83
|
+
if (v === null)
|
|
84
|
+
delete merged[k];
|
|
85
|
+
fm = Frontmatter.parse(merged);
|
|
86
|
+
if (typeof b === "string")
|
|
87
|
+
body = b.trim();
|
|
88
|
+
}
|
|
89
|
+
fm.version = old.version + 1;
|
|
90
|
+
fm.updated = stamp;
|
|
91
|
+
fm.by = who.by;
|
|
92
|
+
fm.why = who.why;
|
|
93
|
+
byId.set(c.id, { path: pathOf(fm), doc: { fm, body } });
|
|
94
|
+
touched.push({ id: c.id, op: c.op, from: cur.path });
|
|
95
|
+
}
|
|
96
|
+
return { next: [...byId.values()], touched };
|
|
97
|
+
}
|
|
98
|
+
function message(changes, touched, who) {
|
|
99
|
+
const first = touched[0];
|
|
100
|
+
const subject = touched.length === 1 && first
|
|
101
|
+
? `knowledge: ${first.op} ${first.id}`
|
|
102
|
+
: `knowledge: ${touched.length} changes (${[...new Set(changes.map((c) => c.op))].join(", ")})`;
|
|
103
|
+
const lines = touched.length > 1 ? `\n${touched.map((t) => `- ${t.op} ${t.id}`).join("\n")}\n` : "";
|
|
104
|
+
return `${subject}\n\n${who.why}\n${lines}\nKnowledge-By: ${who.by}`;
|
|
105
|
+
}
|
|
106
|
+
/** Apply, lint, write, commit. Throws LintError (nothing written) or the commit's error (files restored). */
|
|
107
|
+
export async function write(root, changes, who) {
|
|
108
|
+
if (!changes.length)
|
|
109
|
+
throw new Error("no changes");
|
|
110
|
+
if (!who.by.trim() || !who.why.trim())
|
|
111
|
+
throw new Error("--by and --why are required");
|
|
112
|
+
return withLock(root, async () => {
|
|
113
|
+
const tree = loadWorking(root);
|
|
114
|
+
const { next, touched } = apply(tree.docs, changes, who);
|
|
115
|
+
const problems = lint({ docs: next, broken: tree.broken }, loadConfig(root).owner);
|
|
116
|
+
// a fault already elsewhere in the tree does not block this write; one in a record it touches does
|
|
117
|
+
const mine = new Set(touched.map((t) => t.id));
|
|
118
|
+
const blocking = errors(problems).filter((p) => p.id && mine.has(p.id));
|
|
119
|
+
if (blocking.length)
|
|
120
|
+
throw new LintError(blocking);
|
|
121
|
+
const byId = new Map(next.map((l) => [l.doc.fm.id, l]));
|
|
122
|
+
const paths = new Set();
|
|
123
|
+
const backup = new Map();
|
|
124
|
+
const keep = (p) => {
|
|
125
|
+
if (backup.has(p))
|
|
126
|
+
return;
|
|
127
|
+
const full = join(root, p);
|
|
128
|
+
backup.set(p, existsSync(full) ? readFileSync(full, "utf8") : null);
|
|
129
|
+
paths.add(p);
|
|
130
|
+
};
|
|
131
|
+
for (const t of touched) {
|
|
132
|
+
const l = byId.get(t.id);
|
|
133
|
+
if (!l)
|
|
134
|
+
continue;
|
|
135
|
+
if (t.from && t.from !== l.path) {
|
|
136
|
+
keep(t.from);
|
|
137
|
+
rmSync(join(root, t.from), { force: true });
|
|
138
|
+
}
|
|
139
|
+
keep(l.path);
|
|
140
|
+
mkdirSync(dirname(join(root, l.path)), { recursive: true });
|
|
141
|
+
writeFileSync(join(root, l.path), serialize(l.doc));
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
const list = [...paths];
|
|
145
|
+
git(root, ["add", "-A", "--", ...list]);
|
|
146
|
+
git(root, ["commit", "-q", "-m", message(changes, touched, who), "--", ...list]);
|
|
147
|
+
}
|
|
148
|
+
catch (e) {
|
|
149
|
+
for (const [p, text] of backup) {
|
|
150
|
+
const full = join(root, p);
|
|
151
|
+
if (text === null)
|
|
152
|
+
rmSync(full, { force: true });
|
|
153
|
+
else {
|
|
154
|
+
mkdirSync(dirname(full), { recursive: true });
|
|
155
|
+
writeFileSync(full, text);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
git(root, ["reset", "-q", "--", ...paths]);
|
|
160
|
+
}
|
|
161
|
+
catch { }
|
|
162
|
+
throw e;
|
|
163
|
+
}
|
|
164
|
+
const commit = head(root);
|
|
165
|
+
return {
|
|
166
|
+
commit,
|
|
167
|
+
records: touched.map((t) => {
|
|
168
|
+
const l = byId.get(t.id);
|
|
169
|
+
return { id: t.id, type: l.doc.fm.type, path: l.path, version: l.doc.fm.version, op: t.op };
|
|
170
|
+
}),
|
|
171
|
+
warnings: problems.filter((p) => p.level === "warn" && (!p.id || mine.has(p.id))),
|
|
172
|
+
};
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../src/write.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,49 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrenautomation/knowledge",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.59.0",
|
|
4
|
+
"description": "Knowledge as files: sources, findings, verdicts and rules as markdown records in a git repo, each linked to its evidence. One commit is one transaction; a lint guards every write; a Postgres (or PGlite) index built from the commits answers queries, backlinks and stale marks.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/wrenautomation/engine.git",
|
|
8
|
+
"directory": "packages/knowledge"
|
|
9
|
+
},
|
|
10
|
+
"license": "PolyForm-Strict-1.0.0",
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"!dist/**/*.test.*",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE.md"
|
|
16
|
+
],
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"type": "module",
|
|
21
|
+
"bin": {
|
|
22
|
+
"knowledge": "dist/cli.js"
|
|
23
|
+
},
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=24"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@electric-sql/pglite": "0.5.11",
|
|
35
|
+
"commander": "15.0.0",
|
|
36
|
+
"drizzle-orm": "0.45.4",
|
|
37
|
+
"gray-matter": "4.0.3",
|
|
38
|
+
"postgres": "3.4.9",
|
|
39
|
+
"proper-lockfile": "4.1.2",
|
|
40
|
+
"zod": "4.6.5"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/proper-lockfile": "4.1.4"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
47
|
+
"build": "sh ../../scripts/build.sh cli.js"
|
|
48
|
+
}
|
|
6
49
|
}
|