lat.md 0.5.0 → 0.7.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 (39) hide show
  1. package/dist/src/cli/check.d.ts +7 -5
  2. package/dist/src/cli/check.js +243 -74
  3. package/dist/src/cli/context.d.ts +3 -7
  4. package/dist/src/cli/context.js +15 -1
  5. package/dist/src/cli/expand.d.ts +7 -0
  6. package/dist/src/cli/expand.js +92 -0
  7. package/dist/src/cli/gen.js +11 -4
  8. package/dist/src/cli/hook.d.ts +1 -0
  9. package/dist/src/cli/hook.js +147 -0
  10. package/dist/src/cli/index.js +77 -28
  11. package/dist/src/cli/init.js +148 -120
  12. package/dist/src/cli/locate.d.ts +2 -2
  13. package/dist/src/cli/locate.js +9 -4
  14. package/dist/src/cli/refs.d.ts +20 -4
  15. package/dist/src/cli/refs.js +64 -42
  16. package/dist/src/cli/search.d.ts +25 -3
  17. package/dist/src/cli/search.js +87 -47
  18. package/dist/src/cli/section.d.ts +26 -0
  19. package/dist/src/cli/section.js +133 -0
  20. package/dist/src/code-refs.js +2 -1
  21. package/dist/src/config.js +3 -2
  22. package/dist/src/context.d.ts +21 -0
  23. package/dist/src/context.js +11 -0
  24. package/dist/src/format.d.ts +4 -3
  25. package/dist/src/format.js +16 -20
  26. package/dist/src/init-version.d.ts +10 -0
  27. package/dist/src/init-version.js +49 -0
  28. package/dist/src/lattice.d.ts +11 -5
  29. package/dist/src/lattice.js +87 -38
  30. package/dist/src/mcp/server.js +27 -279
  31. package/dist/src/search/index.js +5 -4
  32. package/dist/src/source-parser.d.ts +23 -0
  33. package/dist/src/source-parser.js +720 -0
  34. package/package.json +3 -1
  35. package/templates/AGENTS.md +38 -6
  36. package/templates/cursor-rules.md +11 -5
  37. package/templates/lat-prompt-hook.sh +2 -2
  38. package/dist/src/cli/prompt.d.ts +0 -2
  39. package/dist/src/cli/prompt.js +0 -60
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lat.md",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "A knowledge graph for your codebase, written in markdown",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.30.2",
@@ -50,6 +50,7 @@
50
50
  "@folder/xdg": "^4.0.1",
51
51
  "@libsql/client": "^0.17.0",
52
52
  "@modelcontextprotocol/sdk": "^1.27.1",
53
+ "@repomix/tree-sitter-wasms": "^0.1.16",
53
54
  "chalk": "^5.6.2",
54
55
  "commander": "^14.0.3",
55
56
  "ignore-walk": "^8.0.0",
@@ -58,6 +59,7 @@
58
59
  "remark-stringify": "^11.0.0",
59
60
  "unified": "^11.0.0",
60
61
  "unist-util-visit": "^5.0.0",
62
+ "web-tree-sitter": "^0.26.6",
61
63
  "zod": "^4.3.6"
62
64
  }
63
65
  }
@@ -1,7 +1,7 @@
1
1
  # Before starting work
2
2
 
3
3
  - Run `lat search` to find sections relevant to your task. Read them to understand the design intent before writing code.
4
- - Run `lat prompt` on user prompts to expand any `[[refs]]` — this resolves section names to file locations and provides context.
4
+ - Run `lat expand` on user prompts to expand any `[[refs]]` — this resolves section names to file locations and provides context.
5
5
 
6
6
  # Post-task checklist (REQUIRED — do not skip)
7
7
 
@@ -23,7 +23,7 @@ This project uses [lat.md](https://www.npmjs.com/package/lat.md) to maintain a s
23
23
  lat locate "Section Name" # find a section by name (exact, fuzzy)
24
24
  lat refs "file#Section" # find what references a section
25
25
  lat search "natural language" # semantic search across all sections
26
- lat prompt "user prompt text" # expand [[refs]] to resolved locations
26
+ lat expand "user prompt text" # expand [[refs]] to resolved locations
27
27
  lat check # validate all links and code refs
28
28
  ```
29
29
 
@@ -33,9 +33,10 @@ If `lat search` fails because no API key is configured, explain to the user that
33
33
 
34
34
  # Syntax primer
35
35
 
36
- - **Section ids**: `path/to/file#Heading#SubHeading` — full form uses vault-relative path (e.g. `tests/search#RAG Replay Tests`). Short form uses bare file name when unique (e.g. `search#RAG Replay Tests`, `cli#search#Indexing`).
37
- - **Wiki links**: `[[target]]` or `[[target|alias]]` — cross-references between sections
38
- - **Code refs**: `// @lat: [[section-id]]` (JS/TS) or `# @lat: [[section-id]]` (Python) ties source code to concepts
36
+ - **Section ids**: `lat.md/path/to/file#Heading#SubHeading` — full form uses project-root-relative path (e.g. `lat.md/tests/search#RAG Replay Tests`). Short form uses bare file name when unique (e.g. `search#RAG Replay Tests`, `cli#search#Indexing`).
37
+ - **Wiki links**: `[[target]]` or `[[target|alias]]` — cross-references between sections. Can also reference source code: `[[src/foo.ts#myFunction]]`.
38
+ - **Source code links**: Wiki links in `lat.md/` files can reference functions, classes, constants, and methods in TypeScript/JavaScript/Python/Rust/Go/C files. Use the full path: `[[src/config.ts#getConfigDir]]`, `[[src/server.ts#App#listen]]` (class method), `[[lib/utils.py#parse_args]]`, `[[src/lib.rs#Greeter#greet]]` (Rust impl method), `[[src/app.go#Greeter#Greet]]` (Go method), `[[src/app.h#Greeter]]` (C struct). `lat check` validates these exist.
39
+ - **Code refs**: `// @lat: [[section-id]]` (JS/TS/Rust/Go/C) or `# @lat: [[section-id]]` (Python) — ties source code to concepts
39
40
 
40
41
  # Test specs
41
42
 
@@ -48,7 +49,12 @@ lat:
48
49
  ---
49
50
  # Tests
50
51
 
52
+ Authentication and authorization test specifications.
53
+
51
54
  ## User login
55
+
56
+ Verify credential validation and error handling for the login endpoint.
57
+
52
58
  ### Rejects expired tokens
53
59
  Tokens past their expiry timestamp are rejected with 401, even if otherwise valid.
54
60
 
@@ -56,7 +62,7 @@ Tokens past their expiry timestamp are rejected with 401, even if otherwise vali
56
62
  Login request without a password field returns 400 with a descriptive error.
57
63
  ```
58
64
 
59
- Every section MUST have a description — at least one sentence explaining what the test verifies and why. Empty sections with just a heading are not acceptable.
65
+ Every section MUST have a description — at least one sentence explaining what the test verifies and why. Empty sections with just a heading are not acceptable. (This is a specific case of the general leading paragraph rule below.)
60
66
 
61
67
  Each test in code should reference its spec with exactly one comment placed next to the relevant test — not at the top of the file:
62
68
 
@@ -71,3 +77,29 @@ def test_handles_missing_password():
71
77
  ```
72
78
 
73
79
  Do not duplicate refs. One `@lat:` comment per spec section, placed at the test that covers it. `lat check` will flag any spec section not covered by a code reference, and any code reference pointing to a nonexistent section.
80
+
81
+ # Section structure
82
+
83
+ Every section in `lat.md/` **must** have a leading paragraph — at least one sentence immediately after the heading, before any child headings or other block content. The first paragraph must be ≤250 characters (excluding `[[wiki link]]` content). This paragraph serves as the section's overview and is used in search results, command output, and RAG context — keeping it concise guarantees the section's essence is always captured.
84
+
85
+ ```markdown
86
+ # Good Section
87
+
88
+ Brief overview of what this section documents and why it matters.
89
+
90
+ More detail can go in subsequent paragraphs, code blocks, or lists.
91
+
92
+ ## Child heading
93
+
94
+ Details about this child topic.
95
+ ```
96
+
97
+ ```markdown
98
+ # Bad Section
99
+
100
+ ## Child heading
101
+
102
+ Details about this child topic.
103
+ ```
104
+
105
+ The second example is invalid because `Bad Section` has no leading paragraph. `lat check` validates this rule and reports errors for missing or overly long leading paragraphs.
@@ -1,7 +1,7 @@
1
1
  # Before starting work
2
2
 
3
3
  - Use the `lat_search` tool to find sections relevant to your task. Read them to understand the design intent before writing code.
4
- - Use the `lat_prompt` tool on user prompts to expand any `[[refs]]` — this resolves section names to file locations and provides context.
4
+ - Use the `lat_expand` tool on user prompts to expand any `[[refs]]` — this resolves section names to file locations and provides context.
5
5
 
6
6
  # Post-task checklist (REQUIRED — do not skip)
7
7
 
@@ -23,7 +23,7 @@ You have access to the following MCP tools from the `lat` server:
23
23
 
24
24
  - **lat_locate** — find a section by name (exact, fuzzy)
25
25
  - **lat_search** — semantic search across all sections
26
- - **lat_prompt** — expand `[[refs]]` in text to resolved locations
26
+ - **lat_expand** — expand `[[refs]]` in text to resolved locations
27
27
  - **lat_check** — validate all wiki links and code refs
28
28
  - **lat_refs** — find what references a section
29
29
 
@@ -31,9 +31,10 @@ If `lat_search` fails because `LAT_LLM_KEY` is not set, explain to the user that
31
31
 
32
32
  # Syntax primer
33
33
 
34
- - **Section ids**: `path/to/file#Heading#SubHeading` — full form uses vault-relative path (e.g. `tests/search#RAG Replay Tests`). Short form uses bare file name when unique (e.g. `search#RAG Replay Tests`, `cli#search#Indexing`).
35
- - **Wiki links**: `[[target]]` or `[[target|alias]]` — cross-references between sections
36
- - **Code refs**: `// @lat: [[section-id]]` (JS/TS) or `# @lat: [[section-id]]` (Python) ties source code to concepts
34
+ - **Section ids**: `lat.md/path/to/file#Heading#SubHeading` — full form uses project-root-relative path (e.g. `lat.md/tests/search#RAG Replay Tests`). Short form uses bare file name when unique (e.g. `search#RAG Replay Tests`, `cli#search#Indexing`).
35
+ - **Wiki links**: `[[target]]` or `[[target|alias]]` — cross-references between sections. Can also reference source code: `[[src/foo.ts#myFunction]]`.
36
+ - **Source code links**: Wiki links in `lat.md/` files can reference functions, classes, constants, and methods in TypeScript/JavaScript/Python/Rust/Go/C files. Use the full path: `[[src/config.ts#getConfigDir]]`, `[[src/server.ts#App#listen]]` (class method), `[[lib/utils.py#parse_args]]`, `[[src/lib.rs#Greeter#greet]]` (Rust impl method), `[[src/app.go#Greeter#Greet]]` (Go method), `[[src/app.h#Greeter]]` (C struct). `lat check` validates these exist.
37
+ - **Code refs**: `// @lat: [[section-id]]` (JS/TS/Rust/Go/C) or `# @lat: [[section-id]]` (Python) — ties source code to concepts
37
38
 
38
39
  # Test specs
39
40
 
@@ -46,7 +47,12 @@ lat:
46
47
  ---
47
48
  # Tests
48
49
 
50
+ Authentication and authorization test specifications.
51
+
49
52
  ## User login
53
+
54
+ Verify credential validation and error handling for the login endpoint.
55
+
50
56
  ### Rejects expired tokens
51
57
  Tokens past their expiry timestamp are rejected with 401, even if otherwise valid.
52
58
 
@@ -3,14 +3,14 @@
3
3
  # Injected by `lat init` — reminds the agent to consult lat.md before working.
4
4
  #
5
5
  # This hook fires on every user prompt submission. It adds a short instruction
6
- # telling the agent to run `lat search` and `lat prompt` so that lat.md context
6
+ # telling the agent to run `lat search` and `lat expand` so that lat.md context
7
7
  # is consulted before any code changes.
8
8
 
9
9
  cat <<'HOOK_JSON'
10
10
  {
11
11
  "hookSpecificOutput": {
12
12
  "hookEventName": "UserPromptSubmit",
13
- "additionalContext": "Before starting work on this task:\n1. Run `lat search` with a query relevant to the task and read the results to understand the design intent.\n2. If the prompt contains [[refs]], run `lat prompt` on the full prompt text to resolve them.\n3. After completing work, run `lat check` to validate all links and code refs.\nDo not skip these steps."
13
+ "additionalContext": "Before starting work on this task:\n1. Run `lat search` with a query relevant to the task and read the results to understand the design intent.\n2. If the prompt contains [[refs]], run `lat expand` on the full prompt text to resolve them.\n3. After completing work, run `lat check` to validate all links and code refs.\nDo not skip these steps."
14
14
  }
15
15
  }
16
16
  HOOK_JSON
@@ -1,2 +0,0 @@
1
- import type { CliContext } from './context.js';
2
- export declare function promptCmd(ctx: CliContext, text: string): Promise<void>;
@@ -1,60 +0,0 @@
1
- import { relative } from 'node:path';
2
- import { loadAllSections, findSections, } from '../lattice.js';
3
- const WIKI_LINK_RE = /\[\[([^\]]+)\]\]/g;
4
- function formatLocation(section, latDir) {
5
- const relPath = relative(process.cwd(), latDir + '/' + section.file + '.md');
6
- return `${relPath}:${section.startLine}-${section.endLine}`;
7
- }
8
- export async function promptCmd(ctx, text) {
9
- const allSections = await loadAllSections(ctx.latDir);
10
- const refs = [...text.matchAll(WIKI_LINK_RE)];
11
- if (refs.length === 0) {
12
- process.stdout.write(text);
13
- return;
14
- }
15
- const resolved = new Map();
16
- for (const match of refs) {
17
- const target = match[1];
18
- if (resolved.has(target))
19
- continue;
20
- const matches = findSections(allSections, target);
21
- if (matches.length >= 1) {
22
- resolved.set(target, {
23
- target,
24
- best: matches[0],
25
- alternatives: matches.slice(1),
26
- });
27
- continue;
28
- }
29
- console.error(ctx.chalk.red(`No section found for [[${target}]] (no exact, substring, or fuzzy matches).`));
30
- console.error(ctx.chalk.dim('Ask the user to correct the reference.'));
31
- process.exit(1);
32
- }
33
- // Replace [[refs]] inline
34
- let output = text.replace(WIKI_LINK_RE, (_match, target) => {
35
- const ref = resolved.get(target);
36
- return `[[${ref.best.section.id}]]`;
37
- });
38
- // Append context block as nested outliner
39
- output += '\n\n<lat-context>\n';
40
- for (const ref of resolved.values()) {
41
- const isExact = ref.best.reason === 'exact match';
42
- const all = isExact ? [ref.best] : [ref.best, ...ref.alternatives];
43
- if (isExact) {
44
- output += `* \`[[${ref.target}]]\` is referring to:\n`;
45
- }
46
- else {
47
- output += `* \`[[${ref.target}]]\` might be referring to either of the following:\n`;
48
- }
49
- for (const m of all) {
50
- const reason = isExact ? '' : ` (${m.reason})`;
51
- output += ` * [[${m.section.id}]]${reason}\n`;
52
- output += ` * ${formatLocation(m.section, ctx.latDir)}\n`;
53
- if (m.section.body) {
54
- output += ` * ${m.section.body}\n`;
55
- }
56
- }
57
- }
58
- output += '</lat-context>\n';
59
- process.stdout.write(output);
60
- }