@time-machine-lab/tmlbrain 0.1.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 (42) hide show
  1. package/README.md +152 -0
  2. package/bin/tmlbrain.js +1653 -0
  3. package/docs/.gitkeep +0 -0
  4. package/docs/api/.gitkeep +0 -0
  5. package/docs/architecture.md +84 -0
  6. package/docs/backup.md +76 -0
  7. package/docs/decisions/.gitkeep +1 -0
  8. package/docs/decisions/0001-core-runtime.md +18 -0
  9. package/docs/design/.gitkeep +0 -0
  10. package/docs/fixtures/knowledge-sample/alpha-reference.md +14 -0
  11. package/docs/fixtures/knowledge-sample/project-alpha.md +18 -0
  12. package/docs/fixtures/patches/update-alpha-reference.patch +9 -0
  13. package/docs/indexing.md +32 -0
  14. package/docs/install.md +166 -0
  15. package/docs/preview/.gitkeep +0 -0
  16. package/docs/roadmap.md +27 -0
  17. package/docs/runtime.md +95 -0
  18. package/docs/server-api.md +120 -0
  19. package/docs/spec/.gitkeep +0 -0
  20. package/docs/spikes/cocoindex-local-indexing.md +31 -0
  21. package/docs/spikes/lightrag-retrieval.md +27 -0
  22. package/docs/sql/.gitkeep +0 -0
  23. package/docs/sync.md +110 -0
  24. package/knowledge/README.md +71 -0
  25. package/knowledge/_templates/area.md +18 -0
  26. package/knowledge/_templates/decision.md +18 -0
  27. package/knowledge/_templates/meeting.md +18 -0
  28. package/knowledge/_templates/project.md +18 -0
  29. package/knowledge/_templates/reference.md +18 -0
  30. package/knowledge/_templates/resource.md +18 -0
  31. package/package.json +41 -0
  32. package/scripts/README.md +12 -0
  33. package/scripts/backup/server-to-github.ps1 +20 -0
  34. package/scripts/backup/server-to-github.sh +13 -0
  35. package/scripts/docker/server-entrypoint.sh +84 -0
  36. package/scripts/install/install.ps1 +44 -0
  37. package/scripts/install/install.sh +41 -0
  38. package/scripts/release/parse-auto-release.js +166 -0
  39. package/scripts/sync/.gitkeep +1 -0
  40. package/scripts/sync/post-receive.sample +8 -0
  41. package/skills/tmlbrain/SKILL.md +192 -0
  42. package/skills/tmlbrain/agents/openai.yaml +7 -0
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+
5
+ function parseArgs(argv) {
6
+ const args = {
7
+ messageFile: null,
8
+ githubOutput: null,
9
+ githubEnv: null,
10
+ json: false,
11
+ };
12
+
13
+ for (let i = 0; i < argv.length; i += 1) {
14
+ const arg = argv[i];
15
+ if (arg === "--message-file") {
16
+ args.messageFile = argv[++i];
17
+ } else if (arg === "--github-output") {
18
+ args.githubOutput = argv[++i];
19
+ } else if (arg === "--github-env") {
20
+ args.githubEnv = argv[++i];
21
+ } else if (arg === "--json") {
22
+ args.json = true;
23
+ } else {
24
+ throw new Error(`Unknown argument: ${arg}`);
25
+ }
26
+ }
27
+
28
+ return args;
29
+ }
30
+
31
+ function readStdin() {
32
+ return fs.readFileSync(0, "utf8");
33
+ }
34
+
35
+ function findFlagValue(message, flag) {
36
+ const prefix = `-${flag}:`;
37
+ const start = message.indexOf(prefix);
38
+ if (start === -1) {
39
+ return null;
40
+ }
41
+
42
+ let cursor = start + prefix.length;
43
+ while (message[cursor] === " " || message[cursor] === "\t") {
44
+ cursor += 1;
45
+ }
46
+
47
+ const first = message[cursor];
48
+ if (first === "<") {
49
+ const end = message.indexOf(">", cursor + 1);
50
+ if (end === -1) {
51
+ throw new Error(`Missing closing ">" for -${flag}: value`);
52
+ }
53
+ return message.slice(cursor + 1, end).trim();
54
+ }
55
+
56
+ if (first === '"' || first === "'") {
57
+ const end = message.indexOf(first, cursor + 1);
58
+ if (end === -1) {
59
+ throw new Error(`Missing closing quote for -${flag}: value`);
60
+ }
61
+ return message.slice(cursor + 1, end).trim();
62
+ }
63
+
64
+ const rest = message.slice(cursor);
65
+ const match = rest.match(/^[^\s]+/);
66
+ return match ? match[0].trim() : "";
67
+ }
68
+
69
+ function parseReleaseMessage(message) {
70
+ const auto = message.includes("<Auto>");
71
+ const result = {
72
+ auto,
73
+ version: "",
74
+ runtimePort: "7389",
75
+ dockerExtraArgs: "",
76
+ };
77
+
78
+ if (!auto) {
79
+ return result;
80
+ }
81
+
82
+ const version = findFlagValue(message, "v");
83
+ if (!version) {
84
+ throw new Error('Auto release commit messages must include "-v:<version>"');
85
+ }
86
+
87
+ const semverPattern = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
88
+ if (!semverPattern.test(version)) {
89
+ throw new Error(`Invalid -v version "${version}". Expected a Docker-compatible semver value such as 0.1.0`);
90
+ }
91
+
92
+ const runtimePort = findFlagValue(message, "rp") || result.runtimePort;
93
+ const parsedPort = Number.parseInt(runtimePort, 10);
94
+ if (!Number.isInteger(parsedPort) || parsedPort < 1 || parsedPort > 65535 || String(parsedPort) !== runtimePort) {
95
+ throw new Error(`Invalid -rp port "${runtimePort}". Expected an integer from 1 to 65535`);
96
+ }
97
+
98
+ const dockerExtraArgs = findFlagValue(message, "de") || "";
99
+ if (/[\r\n]/.test(dockerExtraArgs)) {
100
+ throw new Error("-de value must be a single-line docker runtime argument string");
101
+ }
102
+
103
+ result.version = version;
104
+ result.runtimePort = runtimePort;
105
+ result.dockerExtraArgs = dockerExtraArgs;
106
+ return result;
107
+ }
108
+
109
+ function appendOutput(file, pairs) {
110
+ if (!file) {
111
+ return;
112
+ }
113
+
114
+ const lines = [];
115
+ for (const [key, value] of Object.entries(pairs)) {
116
+ lines.push(`${key}=${value}`);
117
+ }
118
+ fs.appendFileSync(file, `${lines.join("\n")}\n`);
119
+ }
120
+
121
+ function appendEnv(file, result) {
122
+ if (!file) {
123
+ return;
124
+ }
125
+
126
+ fs.appendFileSync(
127
+ file,
128
+ [
129
+ `TMLBRAIN_RELEASE_VERSION=${result.version}`,
130
+ `TMLBRAIN_RELEASE_RUNTIME_PORT=${result.runtimePort}`,
131
+ `TMLBRAIN_RELEASE_DOCKER_EXTRA_ARGS=${result.dockerExtraArgs}`,
132
+ "",
133
+ ].join("\n"),
134
+ );
135
+ }
136
+
137
+ function main() {
138
+ const args = parseArgs(process.argv.slice(2));
139
+ const message = args.messageFile ? fs.readFileSync(args.messageFile, "utf8") : readStdin();
140
+ const result = parseReleaseMessage(message);
141
+
142
+ appendOutput(args.githubOutput, {
143
+ auto: result.auto ? "true" : "false",
144
+ version: result.version,
145
+ runtime_port: result.runtimePort,
146
+ docker_extra_args: result.dockerExtraArgs,
147
+ });
148
+ appendEnv(args.githubEnv, result);
149
+
150
+ if (args.json) {
151
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
152
+ }
153
+ }
154
+
155
+ if (require.main === module) {
156
+ try {
157
+ main();
158
+ } catch (error) {
159
+ console.error(error.message);
160
+ process.exit(1);
161
+ }
162
+ }
163
+
164
+ module.exports = {
165
+ parseReleaseMessage,
166
+ };
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env sh
2
+ set -eu
3
+
4
+ WORKTREE="${TMLBRAIN_WORKTREE:-/srv/tmlbrain-worktree}"
5
+ REPO_DIR="${TMLBRAIN_REPO_DIR:-/srv/tmlbrain.git}"
6
+
7
+ mkdir -p "$WORKTREE"
8
+ env -u GIT_DIR -u GIT_WORK_TREE git --git-dir="$REPO_DIR" --work-tree="$WORKTREE" checkout -f
@@ -0,0 +1,192 @@
1
+ ---
2
+ name: tmlbrain
3
+ description: Use when an AI agent needs to search, read, update, classify, validate, index, or synchronize the TMLBrain team knowledge base; invoke for TMLBrain knowledge questions, local-first retrieval, server-side knowledge writes, Markdown knowledge edits, conflict-aware updates, and dedicated knowledge repository backup workflows where clients must not operate remote Git repositories directly.
4
+ ---
5
+
6
+ # TMLBrain Skill
7
+
8
+ Use this skill when an AI agent needs to search, update, classify, or maintain
9
+ the TMLBrain knowledge base.
10
+
11
+ ## Core Principles
12
+
13
+ - Treat Markdown files under `knowledge/` as the source of truth.
14
+ - Use TMLBrain commands and tools instead of asking normal users to run raw Git commands.
15
+ - Run `tmlbrain capabilities --json` first when the available command surface is unclear.
16
+ - Search local knowledge before answering knowledge-base questions.
17
+ - Prefer exact search first, deterministic metadata/graph indexes second, and LightRAG semantic retrieval when enabled.
18
+ - Clients use read-only local snapshots for search and indexing.
19
+ - Clients MUST NOT push to the server Git repository or dedicated knowledge repository.
20
+ - Add, update, and ingest requests MUST go through the TMLBrain server API with `tmlbrain remote ...` commands.
21
+ - The server is the only runtime that mutates Markdown files, validates them, commits repository changes, and pushes backup state.
22
+ - Ask the server to update the smallest useful Markdown region, usually a front matter field, heading section, block, or link context.
23
+ - Show or summarize server-returned diffs after write requests.
24
+ - Never silently overwrite remote knowledge.
25
+ - Avoid deletion unless the user explicitly asks for it; prefer marking content stale.
26
+ - Normal users do not need to know the internal archive folder/status.
27
+
28
+ ## User-Facing Terms
29
+
30
+ - When a user says "archive to the knowledge base", "store this", "save this",
31
+ "record this", or similar, treat it as "save this knowledge into TMLBrain".
32
+ - Use `tmlbrain save` for that user-facing save path. Do not set
33
+ `status: archived` or choose `knowledge/90-archive/` unless the user
34
+ explicitly means inactive historical content.
35
+ - Explain available actions as save, search, update, and sync. Avoid exposing
36
+ internal names such as archive, ingest, Git, commit, or backup unless the user
37
+ asks about implementation details.
38
+
39
+ ## Knowledge Structure
40
+
41
+ Use the approved folder taxonomy:
42
+
43
+ - `knowledge/00-inbox/`: temporary or unclassified notes.
44
+ - `knowledge/10-projects/`: project-specific documents, plans, decisions, and retrospectives.
45
+ - `knowledge/20-areas/`: long-lived responsibility areas.
46
+ - `knowledge/30-resources/`: reusable research, notes, methods, and learning material.
47
+ - `knowledge/40-references/`: stable reference material and checklists.
48
+ - `knowledge/90-archive/`: inactive historical content kept for future search.
49
+
50
+ Documents outside `00-inbox/` must include:
51
+
52
+ ```yaml
53
+ ---
54
+ title: Example
55
+ type: project|area|resource|reference|meeting|decision
56
+ status: draft|active|stale|archived
57
+ owner: TML
58
+ tags: []
59
+ updated: YYYY-MM-DD
60
+ ---
61
+ ```
62
+
63
+ Archive reason is optional. A document in `90-archive/` must use
64
+ `status: archived`. This is an internal lifecycle state, not the default place
65
+ for newly saved knowledge.
66
+
67
+ ## Default Workflow
68
+
69
+ 1. Run `tmlbrain capabilities --json` to confirm the installed command surface.
70
+ 2. Run `tmlbrain sync --pull` to refresh the local read-only snapshot from the TMLBrain server.
71
+ 3. Search with `tmlbrain find "<query>"` or `tmlbrain search "<query>"`.
72
+ 4. If needed, use `tmlbrain index` and inspect `.tmlbrain/index/` outputs.
73
+ 5. If graph retrieval is enabled, use CocoIndex-derived metadata/graph indexes and LightRAG retrieval after exact search.
74
+ 6. Read relevant local source documents.
75
+ 7. For new knowledge, use `tmlbrain save`.
76
+ 8. For updates, use `tmlbrain remote update --file <path> --replace <old> --with <new>` or a content-file update when a full document replacement is explicitly intended.
77
+ 9. Show or summarize the server-returned diff and result.
78
+ 10. Run `tmlbrain sync --pull` again so the local snapshot and indexes reflect the accepted server commit.
79
+
80
+ ## Command Recipes
81
+
82
+ Initialize or repair local runtime:
83
+
84
+ ```text
85
+ npx @time-machine-lab/tmlbrain client install
86
+ ```
87
+
88
+ Run local CLI after global/package installation:
89
+
90
+ ```text
91
+ tmlbrain client install
92
+ ```
93
+
94
+ Enable optional graph runtime:
95
+
96
+ ```text
97
+ tmlbrain graph setup
98
+ ```
99
+
100
+ Validate metadata and links:
101
+
102
+ ```text
103
+ tmlbrain validate
104
+ ```
105
+
106
+ Search exact local Markdown:
107
+
108
+ ```text
109
+ tmlbrain find "keyword"
110
+ ```
111
+
112
+ Rebuild deterministic local index:
113
+
114
+ ```text
115
+ tmlbrain index
116
+ ```
117
+
118
+ Save new knowledge:
119
+
120
+ ```text
121
+ tmlbrain save --title "Title" --content "Content"
122
+ ```
123
+
124
+ Save an existing local file through the server:
125
+
126
+ ```text
127
+ tmlbrain save ./note.md
128
+ ```
129
+
130
+ Update a precise server-side text region:
131
+
132
+ ```text
133
+ tmlbrain remote update --file knowledge/00-inbox/note.md --replace "old text" --with "new text"
134
+ ```
135
+
136
+ Refresh local snapshot from the server:
137
+
138
+ ```text
139
+ tmlbrain sync --pull
140
+ ```
141
+
142
+ Show or change the configured server:
143
+
144
+ ```text
145
+ tmlbrain config show
146
+ tmlbrain config set-server http://server-host:7389 --token <token>
147
+ ```
148
+
149
+ Start the server API from the server worktree:
150
+
151
+ ```text
152
+ tmlbrain serve --host 0.0.0.0 --port 7389
153
+ ```
154
+
155
+ Deploy the server with Docker:
156
+
157
+ ```text
158
+ docker run -d --name tmlbrain-server -p 7389:7389 -e TMLBRAIN_SERVER_TOKEN=<token> -e TMLBRAIN_KNOWLEDGE_REPO=<git-url> -v tmlbrain-data:/data <DOCKER_REPO>:latest
159
+ ```
160
+
161
+ Back up server state:
162
+
163
+ ```text
164
+ tmlbrain backup --dry-run --remote backup
165
+ ```
166
+
167
+ ## Conflict Policy
168
+
169
+ If TMLBrain reports a conflict package:
170
+
171
+ 1. Read the package with `tmlbrain conflict show <id>`.
172
+ 2. Summarize the base, local, and remote differences in user-facing language.
173
+ 3. Propose a merged Markdown result.
174
+ 4. Ask the user to confirm the merged result.
175
+ 5. Apply the confirmed merge through `tmlbrain conflict resolve <id> --merged-file <path>`.
176
+
177
+ Do not ask the user to interpret raw Git conflict markers. Do not force-push or
178
+ silently overwrite remote content.
179
+
180
+ ## Forbidden Client Actions
181
+
182
+ Do not run these as a normal client workflow:
183
+
184
+ ```text
185
+ tmlbrain sync --push
186
+ git push
187
+ git pull from the server repository
188
+ git push to dedicated knowledge repository backup
189
+ ```
190
+
191
+ If a workflow needs repository mutation, call the TMLBrain server through
192
+ `tmlbrain remote ...` instead.
@@ -0,0 +1,7 @@
1
+ interface:
2
+ display_name: "TMLBrain"
3
+ short_description: "Search, edit, and sync the TMLBrain knowledge base."
4
+ default_prompt: "Use $tmlbrain to search or update the team knowledge base."
5
+
6
+ policy:
7
+ allow_implicit_invocation: true