llmnav 0.5.1
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/CHANGELOG.md +113 -0
- package/LICENSE +21 -0
- package/README.md +294 -0
- package/ROADMAP.md +71 -0
- package/bin/llmnav.js +16 -0
- package/docs/agent-integration.md +114 -0
- package/docs/api.md +290 -0
- package/docs/architecture.md +286 -0
- package/docs/benchmarking.md +164 -0
- package/docs/ci.md +196 -0
- package/docs/cli.md +233 -0
- package/docs/configuration.md +117 -0
- package/docs/editor-integration.md +29 -0
- package/docs/faq.md +59 -0
- package/docs/graph.md +92 -0
- package/docs/language-examples.md +130 -0
- package/docs/migration.md +130 -0
- package/docs/performance-v0.2.md +42 -0
- package/docs/provider-neutral-integration.md +66 -0
- package/docs/publishing.md +86 -0
- package/docs/quickstart.md +139 -0
- package/docs/research.md +31 -0
- package/docs/spec.md +424 -0
- package/examples/provider-neutral-host.d.mts +17 -0
- package/examples/provider-neutral-host.mjs +40 -0
- package/package.json +79 -0
- package/schema/config.schema.json +296 -0
- package/src/agent-protocol.js +117 -0
- package/src/agent-tools.js +61 -0
- package/src/agents.js +127 -0
- package/src/boundaries.js +50 -0
- package/src/changes.js +168 -0
- package/src/cli.js +459 -0
- package/src/config.js +305 -0
- package/src/contracts.js +70 -0
- package/src/declaration.js +334 -0
- package/src/doctor.js +124 -0
- package/src/editor.js +107 -0
- package/src/evaluation.js +67 -0
- package/src/files.js +81 -0
- package/src/formatter.js +23 -0
- package/src/generator.js +528 -0
- package/src/graph-input.js +157 -0
- package/src/graph.js +403 -0
- package/src/incremental.js +262 -0
- package/src/index.d.ts +673 -0
- package/src/index.js +115 -0
- package/src/initializer.js +137 -0
- package/src/inverted-index.js +350 -0
- package/src/parser.js +449 -0
- package/src/project.js +65 -0
- package/src/prompt-bundle.js +108 -0
- package/src/registry.js +107 -0
- package/src/sarif.js +70 -0
- package/src/search-shards.js +75 -0
- package/src/search.js +636 -0
- package/src/spec.d.ts +27 -0
- package/src/spec.js +237 -0
- package/src/tokenizer.js +37 -0
- package/src/transaction.js +557 -0
- package/src/util.js +256 -0
- package/src/validator.js +635 -0
- package/templates/file-card.txt +8 -0
- package/templates/lexicon.json +7 -0
- package/templates/line-card.txt +9 -0
- package/templates/module-card.txt +9 -0
- package/templates/queries.jsonl +1 -0
- package/templates/symbol-card.txt +10 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Publishing `llmnav` to npm
|
|
2
|
+
|
|
3
|
+
The repository is release-ready except for owner-specific metadata and npm account configuration.
|
|
4
|
+
|
|
5
|
+
## 1. Claim the names
|
|
6
|
+
|
|
7
|
+
Create the GitHub repository named `llmnav`, then check the npm registry immediately before the first release:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm view llmnav
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
An `E404` means no public package is visible through the registry you queried at that moment. It is not a reservation. The name remains claimable by someone else until publication succeeds.
|
|
14
|
+
|
|
15
|
+
## 2. Replace release metadata
|
|
16
|
+
|
|
17
|
+
Update only the owner-specific URLs in `package.json` and `.github/ISSUE_TEMPLATE/config.yml`.
|
|
18
|
+
Do not run a repository-wide replacement: the release checker and doctor intentionally keep the literal `OWNER` sentinel in source code.
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
npm pkg set repository.url="git+https://github.com/YOUR_GITHUB_OWNER/llmnav.git"
|
|
22
|
+
npm pkg set bugs.url="https://github.com/YOUR_GITHUB_OWNER/llmnav/issues"
|
|
23
|
+
npm pkg set homepage="https://github.com/YOUR_GITHUB_OWNER/llmnav#readme"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Then replace `OWNER` only in `.github/ISSUE_TEMPLATE/config.yml` and run:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
npm run release:check
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 3. Configure npm authentication
|
|
33
|
+
|
|
34
|
+
The supplied release workflow uses npm provenance and GitHub's OIDC token. In npm package settings, configure the GitHub repository and `.github/workflows/release.yml` as a trusted publisher.
|
|
35
|
+
|
|
36
|
+
The workflow references a GitHub environment named `npm`. Create that environment for release protection, or remove the `environment` line when no environment gate is desired.
|
|
37
|
+
|
|
38
|
+
A classic or granular access token can be used for a manual first publication. Do not commit `.npmrc` credentials or an npm token.
|
|
39
|
+
|
|
40
|
+
## 4. Validate the exact package payload
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
npm ci
|
|
44
|
+
npm run check
|
|
45
|
+
npm run release:check
|
|
46
|
+
npm run smoke:pack
|
|
47
|
+
npm pack --dry-run
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Inspect the tarball list. The package intentionally includes the CLI, source API, type declarations, schema, templates, documentation, the typed provider-neutral host example, README, changelog, roadmap, and license. Tests, benchmark harnesses, and development scripts remain in GitHub but are not installed into consumer projects. `npm run smoke:pack` verifies the exact tarball and example export in a clean temporary project.
|
|
51
|
+
|
|
52
|
+
## 5. Publish the first release
|
|
53
|
+
|
|
54
|
+
Manual publication:
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
npm login
|
|
58
|
+
npm publish --provenance --access public
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Automated publication:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
git tag v0.5.1
|
|
65
|
+
git push origin v0.5.1
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The release workflow rejects a tag that does not match `package.json`.
|
|
69
|
+
|
|
70
|
+
## 6. Verify from a clean directory
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
mkdir llmnav-smoke
|
|
74
|
+
cd llmnav-smoke
|
|
75
|
+
npm init -y
|
|
76
|
+
npm install --save-dev llmnav
|
|
77
|
+
npx llmnav --version
|
|
78
|
+
npx llmnav init --agents all --package-scripts
|
|
79
|
+
npx llmnav doctor
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Versioning policy
|
|
83
|
+
|
|
84
|
+
The npm package follows semantic versioning. The comment protocol is versioned separately in the header.
|
|
85
|
+
|
|
86
|
+
A CLI or API breaking change increments the npm major version. A breaking source syntax change creates a new header such as `llmnav/2`; existing `llmnav/1` parsing should remain available through an explicit migration window.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Quick start
|
|
2
|
+
|
|
3
|
+
## Install and initialize
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npm install --save-dev llmnav
|
|
7
|
+
npx llmnav init --agents all --package-scripts
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
This creates the `.llmnav` control directory, a JSON schema, the semantic ID registry, the stable order lock, deterministic generated indexes and catalogs, volatile state ignore rules, and managed instruction files for coding agents.
|
|
11
|
+
|
|
12
|
+
Review `.llmnav/config.json` before annotating code. The default scans the repository root while excluding build outputs, dependency directories, generated bundles, and common caches.
|
|
13
|
+
|
|
14
|
+
Source roots and evaluation files must remain inside the repository. The generated cache directory must remain below `.llmnav/`; parent traversal and symbolic-link control directories are rejected.
|
|
15
|
+
|
|
16
|
+
## Annotate a module boundary
|
|
17
|
+
|
|
18
|
+
Choose a boundary that an agent is likely to search for by behavior rather than by current symbol name.
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
/* llmnav/1 module
|
|
22
|
+
id=auth.session
|
|
23
|
+
role=Own refresh-token issuance, rotation, replay detection, and revocation.
|
|
24
|
+
owns=refresh-token family|session revocation
|
|
25
|
+
excludes=access-token signing|user profile storage
|
|
26
|
+
search=session lifecycle|token family|session revocation
|
|
27
|
+
invariant=One token family has at most one live refresh token.
|
|
28
|
+
stability=architecture
|
|
29
|
+
*/
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Do not begin by annotating every function. One clear module card is more valuable than dozens of generic helper cards.
|
|
33
|
+
|
|
34
|
+
## Annotate a behavioral boundary
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
/* llmnav/1 symbol
|
|
38
|
+
id=auth.session.rotate
|
|
39
|
+
role=Rotate one refresh-token family atomically and reject replayed tokens.
|
|
40
|
+
search=refresh token|token rotation|token family|replay detection
|
|
41
|
+
invariant=At most one live refresh token exists per family.
|
|
42
|
+
invariant=Replay revokes the entire token family.
|
|
43
|
+
effect=db.write(session_tokens)|event.emit(auth.session.revoked)
|
|
44
|
+
risk=auth|concurrency
|
|
45
|
+
rel=policy>auth.session.lifecycle
|
|
46
|
+
rel=test>auth.session.rotate.contract
|
|
47
|
+
stability=contract
|
|
48
|
+
*/
|
|
49
|
+
export async function rotateSession() {}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The referenced policy and test IDs must exist as source cards or registry records.
|
|
53
|
+
|
|
54
|
+
## Format and validate
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
npx llmnav format
|
|
58
|
+
npx llmnav check
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`check` exits with status 1 for errors. Warnings do not fail the command.
|
|
62
|
+
|
|
63
|
+
GitHub annotation output is available for CI:
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
npx llmnav check --format github
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Generate deterministic indexes and catalogs
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
npx llmnav generate
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The first run parses every source file and builds `index.json`, `search-index.json`, `file-state.json`, semantic catalogs, and a manifest. Later runs reuse unchanged file parses and card search documents.
|
|
76
|
+
|
|
77
|
+
Commit `.llmnav/cache`, `.llmnav/ids.jsonl`, and `.llmnav/order.lock`. Do not commit `.llmnav/state` or transaction work files.
|
|
78
|
+
|
|
79
|
+
Inspect machine-readable impact data when integrating with CI or an agent:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
npx llmnav generate --json
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`changedCards` distinguishes semantic, structure, and body changes. `affectedCatalogs` identifies only repository, module, and agent-context catalogs whose bytes changed.
|
|
86
|
+
|
|
87
|
+
CI should run:
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
npx llmnav generate --full --check
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
That command fails when generated files, the registry, or the stable order lock differ from current source. It does not replace the live cache. Normal generation stages and verifies a complete replacement before committing it.
|
|
94
|
+
|
|
95
|
+
## Search before opening source
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
npx llmnav query "where do replayed refresh tokens revoke their family" --top 5
|
|
99
|
+
npx llmnav show auth.session.rotate
|
|
100
|
+
npx llmnav context auth.session.rotate --depth 1 --budget 2500
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Queries use the persistent inverted index and do not retokenize every card. If a previous generation was interrupted, the query command restores the last committed cache before reading it.
|
|
104
|
+
|
|
105
|
+
The expected agent workflow is:
|
|
106
|
+
|
|
107
|
+
1. Query from the task language.
|
|
108
|
+
2. Inspect a few cards and generated signatures.
|
|
109
|
+
3. Open the selected declarations.
|
|
110
|
+
4. Expand one semantic hop only when policy, test, fallback, or workflow context is needed.
|
|
111
|
+
5. Use broad grep only after LLMNav fails to return a credible candidate.
|
|
112
|
+
|
|
113
|
+
## Add task-language aliases
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"version": 1,
|
|
118
|
+
"aliases": {
|
|
119
|
+
"session renewal": "auth.session.rotate",
|
|
120
|
+
"token replay attack": "auth.session.rotate",
|
|
121
|
+
"credit reservation": "billing.credit.reserve"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Aliases are evaluated before lexical ranking and receive a large deterministic score boost.
|
|
127
|
+
|
|
128
|
+
## Add search regression cases
|
|
129
|
+
|
|
130
|
+
```jsonl
|
|
131
|
+
{"query":"revoke every session in the family when a refresh token is replayed","expected":["auth.session.rotate","auth.session.revoke-family"]}
|
|
132
|
+
{"query":"reserve credits before starting an external generation job","expected":["billing.credit.reserve"]}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
```sh
|
|
136
|
+
npx llmnav eval
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Do not lower the gates simply because a new card displaced an old result. Fix ambiguous roles, overloaded search phrases, aliases, or missing semantic relations first.
|
package/docs/research.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Research basis
|
|
2
|
+
|
|
3
|
+
LLMNav is an engineering proposal built from a recurring result in repository-level code intelligence: retrieval quality depends more on selecting the right structure and context than on sending more source text to a model.
|
|
4
|
+
|
|
5
|
+
## Repository-level retrieval
|
|
6
|
+
|
|
7
|
+
[RepoCoder](https://arxiv.org/abs/2303.12570) uses an iterative retrieval and generation loop instead of treating repository context as one static prompt. That supports LLMNav's `query → show → context → source` workflow.
|
|
8
|
+
|
|
9
|
+
[Repoformer](https://arxiv.org/abs/2403.10059) studies selective retrieval and reports that retrieval can be unnecessary or harmful for some completions. LLMNav therefore keeps the first result set small and does not force a repository dump into every request.
|
|
10
|
+
|
|
11
|
+
[GraphCoder](https://arxiv.org/abs/2406.07003) combines code context with graph structure. [CodexGraph](https://arxiv.org/abs/2408.03910) exposes repository graphs to agents. These works support the separation between hand-written semantic cards and generated structural edges.
|
|
12
|
+
|
|
13
|
+
[Aider's repository map](https://aider.chat/docs/repomap.html) is a practical example of presenting selected declarations and signatures under a token budget rather than copying every file.
|
|
14
|
+
|
|
15
|
+
## What the research does not prove
|
|
16
|
+
|
|
17
|
+
None of these projects validates the exact `llmnav/1` syntax, field weights, byte limits, or CI thresholds in this repository. Those are testable design choices, not established constants.
|
|
18
|
+
|
|
19
|
+
LLMNav also makes no universal claim that comments increase model accuracy. Unbounded comments can add stale facts, duplicate code, and distort lexical retrieval. The protocol deliberately limits cards to scarce semantic facts and measures retrieval with repository-specific queries.
|
|
20
|
+
|
|
21
|
+
## Falsifiable claims
|
|
22
|
+
|
|
23
|
+
A useful LLMNav installation should demonstrate all of the following against its own baseline:
|
|
24
|
+
|
|
25
|
+
1. The correct semantic ID appears more often in the first five results.
|
|
26
|
+
2. Agents open fewer irrelevant files before reaching the target declaration.
|
|
27
|
+
3. Uncached input tokens decrease when stable catalogs are reused.
|
|
28
|
+
4. Final task success does not regress.
|
|
29
|
+
5. Stale source metadata remains at zero because volatile structure is generated.
|
|
30
|
+
|
|
31
|
+
Use [benchmarking.md](benchmarking.md) to measure those claims. Do not advertise token or latency reductions measured on another repository as expected results for yours.
|
package/docs/spec.md
ADDED
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
# LLMNav/1 specification
|
|
2
|
+
|
|
3
|
+
Status: experimental normative specification
|
|
4
|
+
|
|
5
|
+
Package implementation: `llmnav` 0.2.x
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
LLMNav/1 defines a compact semantic card embedded next to selected code boundaries. A conforming implementation extracts cards, validates stable meaning, generates volatile structure, and exposes the result to coding agents without requiring broad repository reads.
|
|
10
|
+
|
|
11
|
+
The source card is not a complete documentation record. It contains only information that is expensive to infer from code and expected to remain valid across ordinary implementation changes.
|
|
12
|
+
|
|
13
|
+
The terms MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are normative.
|
|
14
|
+
|
|
15
|
+
## Encoding and line model
|
|
16
|
+
|
|
17
|
+
A card MUST be UTF-8 text.
|
|
18
|
+
|
|
19
|
+
Each metadata line MUST contain one `key=value` pair. The first `=` separates the key and value. Multiline values are not supported.
|
|
20
|
+
|
|
21
|
+
Tabs are not meaningful. A formatter MUST emit spaces and deterministic line endings matching the containing source file.
|
|
22
|
+
|
|
23
|
+
Unknown keys are errors. Implementations MUST NOT silently index them, and formatters MUST NOT silently delete them.
|
|
24
|
+
|
|
25
|
+
## Headers and scopes
|
|
26
|
+
|
|
27
|
+
Every card starts with:
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
llmnav/1 <scope>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The valid scopes are `file`, `module`, and `symbol`.
|
|
34
|
+
|
|
35
|
+
A `file` card describes the responsibility of one source file. It SHOULD appear before imports after any shebang, license notice, or language-required package declaration.
|
|
36
|
+
|
|
37
|
+
A `module` card describes a domain, package, namespace, or architectural boundary. It SHOULD be used when one responsibility spans multiple declarations or files.
|
|
38
|
+
|
|
39
|
+
A `symbol` card attaches to the next declaration after whitespace, ordinary documentation comments, decorators, or attributes. A conforming checker MUST report a card that cannot be attached to a declaration.
|
|
40
|
+
|
|
41
|
+
## Comment encodings
|
|
42
|
+
|
|
43
|
+
### Block comments
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
/* llmnav/1 symbol
|
|
47
|
+
id=domain.capability.action
|
|
48
|
+
role=Produce one observable result.
|
|
49
|
+
stability=contract
|
|
50
|
+
*/
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### HTML comments
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
<!-- llmnav/1 file
|
|
57
|
+
id=ui.checkout.page
|
|
58
|
+
role=Render the checkout workflow and submit one payment confirmation.
|
|
59
|
+
stability=contract
|
|
60
|
+
-->
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Line comments
|
|
64
|
+
|
|
65
|
+
Line-comment cards MUST use one prefix consistently and MUST end with an explicit `/llmnav` line.
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
# llmnav/1 symbol
|
|
69
|
+
# id=domain.capability.action
|
|
70
|
+
# role=Produce one observable result.
|
|
71
|
+
# stability=contract
|
|
72
|
+
# /llmnav
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The supported prefixes in the reference implementation are `//`, `#`, and `--`.
|
|
76
|
+
|
|
77
|
+
## Canonical key order
|
|
78
|
+
|
|
79
|
+
A formatter MUST emit keys in this order:
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
id
|
|
83
|
+
role
|
|
84
|
+
owns
|
|
85
|
+
excludes
|
|
86
|
+
search
|
|
87
|
+
invariant
|
|
88
|
+
effect
|
|
89
|
+
risk
|
|
90
|
+
rel
|
|
91
|
+
stability
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Stable key order is part of the format. It makes generated catalogs deterministic and avoids semantically meaningless prompt-prefix changes.
|
|
95
|
+
|
|
96
|
+
## Field cardinality
|
|
97
|
+
|
|
98
|
+
| Key | Cardinality | Value form |
|
|
99
|
+
| --- | --- | --- |
|
|
100
|
+
| `id` | exactly one | scalar |
|
|
101
|
+
| `role` | exactly one | scalar sentence |
|
|
102
|
+
| `owns` | zero or one line | pipe-separated list |
|
|
103
|
+
| `excludes` | zero or one line | pipe-separated list |
|
|
104
|
+
| `search` | zero or one line | pipe-separated list |
|
|
105
|
+
| `invariant` | repeated, zero to four | one assertion per line |
|
|
106
|
+
| `effect` | zero or one line | pipe-separated controlled values |
|
|
107
|
+
| `risk` | zero or one line | pipe-separated controlled values |
|
|
108
|
+
| `rel` | repeated, zero to six | one relation per line |
|
|
109
|
+
| `stability` | exactly one | controlled scalar |
|
|
110
|
+
|
|
111
|
+
Empty values are invalid in every field. Empty items inside a pipe-separated list are invalid. Optional fields MUST be omitted when they have no value. Duplicate values in list or repeatable fields are invalid after Unicode normalization and case folding.
|
|
112
|
+
|
|
113
|
+
## `id`
|
|
114
|
+
|
|
115
|
+
`id` is a durable semantic identity. It MUST describe a capability, contract, policy, or workflow rather than a current file or symbol name.
|
|
116
|
+
|
|
117
|
+
The grammar is:
|
|
118
|
+
|
|
119
|
+
```text
|
|
120
|
+
id = segment "." segment *("." segment)
|
|
121
|
+
segment = lowercase-letter *(lowercase-letter / digit / "-")
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The reference validation expression is:
|
|
125
|
+
|
|
126
|
+
```regex
|
|
127
|
+
^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9-]*){1,5}$
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Examples:
|
|
131
|
+
|
|
132
|
+
```text
|
|
133
|
+
auth.session.rotate
|
|
134
|
+
billing.credit.reserve
|
|
135
|
+
privacy.export.prepare
|
|
136
|
+
game.arena.collapse-sequence
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
An ID MUST remain unchanged when a file moves, a declaration is renamed, or an implementation is replaced without changing the semantic capability.
|
|
140
|
+
|
|
141
|
+
Deleted IDs MUST NOT be reused. `.llmnav/ids.jsonl` records active, redirected, replaced, or retired identities.
|
|
142
|
+
|
|
143
|
+
```jsonl
|
|
144
|
+
{"id":"auth.session.rotate","state":"active"}
|
|
145
|
+
{"id":"auth.session.renew","state":"redirect","to":"auth.session.rotate"}
|
|
146
|
+
{"id":"billing.credit.charge","state":"replaced","by":["billing.credit.reserve","billing.credit.capture"]}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## `role`
|
|
150
|
+
|
|
151
|
+
`role` states the observable result produced by the file, module, or symbol.
|
|
152
|
+
|
|
153
|
+
It MUST NOT merely restate a name or use an empty abstraction such as “handle data”, “manage sessions”, “service utility”, or “process logic”.
|
|
154
|
+
|
|
155
|
+
It MUST be no longer than 180 characters in the reference profile.
|
|
156
|
+
|
|
157
|
+
Good:
|
|
158
|
+
|
|
159
|
+
```text
|
|
160
|
+
role=Reserve user credits before an external generation job starts.
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Bad:
|
|
164
|
+
|
|
165
|
+
```text
|
|
166
|
+
role=Handle billing data.
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## `owns` and `excludes`
|
|
170
|
+
|
|
171
|
+
`owns` lists responsibilities for which the card is authoritative.
|
|
172
|
+
|
|
173
|
+
`excludes` names adjacent responsibilities that appear related but belong elsewhere. It reduces false-positive routing in repositories with dense domain vocabulary.
|
|
174
|
+
|
|
175
|
+
```text
|
|
176
|
+
owns=refresh-token family|session revocation
|
|
177
|
+
excludes=access-token signing|user profile storage
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
These fields SHOULD appear primarily on `file` and `module` cards.
|
|
181
|
+
|
|
182
|
+
## `search`
|
|
183
|
+
|
|
184
|
+
`search` bridges task language and code language. It contains phrases that a developer or product owner is likely to use but that may not appear in current identifiers.
|
|
185
|
+
|
|
186
|
+
When present, the reference profile requires two to six phrases.
|
|
187
|
+
|
|
188
|
+
```text
|
|
189
|
+
search=refresh token|token rotation|token family|replay detection
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Generic phrases such as `service`, `manager`, `handler`, `helper`, `utility`, `data`, `process`, and `logic` are forbidden by default.
|
|
193
|
+
|
|
194
|
+
A repository SHOULD use one source-card language. Translations, abbreviations, product terminology, and historical names SHOULD be stored in `.llmnav/lexicon.json` rather than duplicated across source comments.
|
|
195
|
+
|
|
196
|
+
## `invariant`
|
|
197
|
+
|
|
198
|
+
Each `invariant` is a condition whose violation represents a bug, security failure, accounting failure, or broken contract.
|
|
199
|
+
|
|
200
|
+
```text
|
|
201
|
+
invariant=At most one live refresh token exists per family.
|
|
202
|
+
invariant=Replay revokes the entire token family.
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Descriptions, goals, implementation notes, and temporary assumptions MUST NOT be presented as invariants.
|
|
206
|
+
|
|
207
|
+
The reference profile permits at most four invariants per card. More usually indicates that the annotated boundary is too broad or that policy belongs in a separate card.
|
|
208
|
+
|
|
209
|
+
## `effect`
|
|
210
|
+
|
|
211
|
+
`effect` uses a controlled vocabulary for externally observable or nondeterministic behavior.
|
|
212
|
+
|
|
213
|
+
The base vocabulary is:
|
|
214
|
+
|
|
215
|
+
```text
|
|
216
|
+
db.read(name)
|
|
217
|
+
db.write(name)
|
|
218
|
+
cache.read(name)
|
|
219
|
+
cache.write(name)
|
|
220
|
+
event.emit(name)
|
|
221
|
+
event.consume(name)
|
|
222
|
+
net.call(name)
|
|
223
|
+
fs.read
|
|
224
|
+
fs.write
|
|
225
|
+
process.spawn
|
|
226
|
+
clock.read
|
|
227
|
+
random.read
|
|
228
|
+
lock.acquire(name)
|
|
229
|
+
cookie.write(name)
|
|
230
|
+
auth.check(name)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
The base vocabulary has fixed argument arity. `db.*`, `cache.*`, `event.*`, `net.call`, `lock.acquire`, `cookie.write`, and `auth.check` require one stable target argument. `fs.read`, `fs.write`, `process.spawn`, `clock.read`, and `random.read` accept no argument. Resource arguments identify a semantic resource rather than a path, host, timestamp, or current implementation detail.
|
|
234
|
+
|
|
235
|
+
A repository MAY extend the vocabulary in `.llmnav/config.json`. An extension declares only a lower-case effect kind such as `queue.publish`; the reference implementation accepts that custom kind with or without one target argument. Extensions MUST remain machine-parseable and SHOULD use a stable namespace.
|
|
236
|
+
|
|
237
|
+
Effects do not replace static analysis. They express semantic importance and provide retrieval signals while future enrichers compare declarations against actual sinks.
|
|
238
|
+
|
|
239
|
+
## `risk`
|
|
240
|
+
|
|
241
|
+
The base risk vocabulary is:
|
|
242
|
+
|
|
243
|
+
```text
|
|
244
|
+
auth
|
|
245
|
+
money
|
|
246
|
+
privacy
|
|
247
|
+
concurrency
|
|
248
|
+
migration
|
|
249
|
+
availability
|
|
250
|
+
performance
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Cards containing `auth`, `money`, or `privacy` MUST contain at least one invariant and at least one `test>` relation under the reference profile.
|
|
254
|
+
|
|
255
|
+
A repository MAY add controlled risk values in configuration.
|
|
256
|
+
|
|
257
|
+
## `rel`
|
|
258
|
+
|
|
259
|
+
`rel` records a semantic relation that cannot be reliably derived from imports or call syntax.
|
|
260
|
+
|
|
261
|
+
The grammar is:
|
|
262
|
+
|
|
263
|
+
```text
|
|
264
|
+
rel=<type>><target-id>
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
The base relation types are:
|
|
268
|
+
|
|
269
|
+
```text
|
|
270
|
+
policy
|
|
271
|
+
workflow
|
|
272
|
+
fallback
|
|
273
|
+
mirror
|
|
274
|
+
migration
|
|
275
|
+
test
|
|
276
|
+
replaces
|
|
277
|
+
deprecated-by
|
|
278
|
+
cross-repo
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Examples:
|
|
282
|
+
|
|
283
|
+
```text
|
|
284
|
+
rel=policy>auth.session.lifecycle
|
|
285
|
+
rel=workflow>auth.session.revoke-family
|
|
286
|
+
rel=fallback>auth.session.reauthenticate
|
|
287
|
+
rel=test>auth.session.rotate.contract
|
|
288
|
+
rel=cross-repo>zdp-core-auth/auth.session.rotate
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
The following structural relations MUST NOT be maintained by hand:
|
|
292
|
+
|
|
293
|
+
```text
|
|
294
|
+
calls
|
|
295
|
+
imports
|
|
296
|
+
references
|
|
297
|
+
implements
|
|
298
|
+
exports
|
|
299
|
+
overrides
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
They belong in generated structure indexes because source changes can invalidate them immediately.
|
|
303
|
+
|
|
304
|
+
A non-cross-repository target MUST resolve to a source card or an ID registry record.
|
|
305
|
+
|
|
306
|
+
## `stability`
|
|
307
|
+
|
|
308
|
+
`stability` controls catalog placement and cache strategy.
|
|
309
|
+
|
|
310
|
+
`architecture` describes ownership, boundaries, and responsibilities that normally survive file moves and implementation changes. Architecture cards enter the repository core catalog by default.
|
|
311
|
+
|
|
312
|
+
`contract` describes externally relevant behavior, invariants, effects, and semantic workflow links. Contract cards enter module catalogs by default.
|
|
313
|
+
|
|
314
|
+
`implementation` describes a current algorithm or optimization that may change frequently. Implementation cards remain searchable but are excluded from shared stable catalogs by default.
|
|
315
|
+
|
|
316
|
+
## Forbidden volatile data
|
|
317
|
+
|
|
318
|
+
Source cards MUST NOT contain fields for:
|
|
319
|
+
|
|
320
|
+
```text
|
|
321
|
+
path
|
|
322
|
+
line
|
|
323
|
+
span
|
|
324
|
+
commit
|
|
325
|
+
updated_at
|
|
326
|
+
owner
|
|
327
|
+
callers
|
|
328
|
+
callees
|
|
329
|
+
imports
|
|
330
|
+
references
|
|
331
|
+
implementation_count
|
|
332
|
+
test_status
|
|
333
|
+
current_signature
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Equivalent path, line, commit, and timestamp data hidden inside `role`, `search`, or `invariant` values is also invalid.
|
|
337
|
+
|
|
338
|
+
Current locations, signatures, imports, hashes, and future call-graph edges belong in generated files.
|
|
339
|
+
|
|
340
|
+
## Size profile
|
|
341
|
+
|
|
342
|
+
The reference implementation applies these default byte limits:
|
|
343
|
+
|
|
344
|
+
| Scope | Maximum bytes |
|
|
345
|
+
| --- | ---: |
|
|
346
|
+
| `file` | 400 |
|
|
347
|
+
| `module` | 1,200 |
|
|
348
|
+
| `symbol` | 900 |
|
|
349
|
+
|
|
350
|
+
For repositories with at least 50,000 scanned source bytes, LLMNav comments SHOULD remain below 1.5% of source bytes. The checker reports a warning when the configured ratio is exceeded.
|
|
351
|
+
|
|
352
|
+
These are anti-bloat limits, not targets.
|
|
353
|
+
|
|
354
|
+
## Canonicalization
|
|
355
|
+
|
|
356
|
+
A canonical formatter MUST refuse to erase malformed lines, unknown fields, overlapping blocks, or duplicate scalar values. Unsafe cards remain unchanged until the checker-reported issue is fixed.
|
|
357
|
+
|
|
358
|
+
For valid cards, a canonical formatter MUST:
|
|
359
|
+
|
|
360
|
+
* emit the standard header and terminator for the original comment style
|
|
361
|
+
* emit keys in canonical order
|
|
362
|
+
* emit list fields once with `|` separators
|
|
363
|
+
* emit one line per `invariant` and `rel`
|
|
364
|
+
* remove empty optional fields
|
|
365
|
+
* preserve the containing file's newline convention
|
|
366
|
+
* preserve source indentation
|
|
367
|
+
|
|
368
|
+
A checker MAY reject non-canonical formatting. The reference implementation does so by default.
|
|
369
|
+
|
|
370
|
+
## Generated index
|
|
371
|
+
|
|
372
|
+
The reference implementation emits `.llmnav/cache/index.json` with:
|
|
373
|
+
|
|
374
|
+
* stable card fields
|
|
375
|
+
* generated path and source line
|
|
376
|
+
* attached declaration name, kind, line, and signature when recognized
|
|
377
|
+
* generated import strings
|
|
378
|
+
* separate semantic, structure, and body SHA-256 hashes
|
|
379
|
+
|
|
380
|
+
`semantic` hashes change only when card meaning changes.
|
|
381
|
+
|
|
382
|
+
`structure` hashes change when path, declaration, signature, or import structure changes.
|
|
383
|
+
|
|
384
|
+
`body` hashes change when the containing source file changes.
|
|
385
|
+
|
|
386
|
+
Generated files MUST be deterministic. Wall-clock timestamps, absolute paths, platform-specific separators, random transaction IDs, and filesystem stat values MUST NOT be embedded in deterministic catalogs.
|
|
387
|
+
|
|
388
|
+
The reference implementation preserves `index.json` schemaVersion 1 for v0.1 consumers and emits additive generated accelerators:
|
|
389
|
+
|
|
390
|
+
* `search-index.json` contains a versioned deterministic token dictionary, normalized phrase documents, and compact posting lists
|
|
391
|
+
* `file-state.json` contains versioned deterministic parsed-file state
|
|
392
|
+
* `manifest.json` hashes every deterministic cache artifact except itself
|
|
393
|
+
|
|
394
|
+
An implementation MAY use volatile filesystem stat hints to avoid reading unchanged files, but those hints MUST remain outside deterministic cache output and MUST NOT affect generated bytes.
|
|
395
|
+
|
|
396
|
+
Incremental generation MUST produce the same deterministic artifacts as a full generation for identical source, configuration, registry, aliases, and stable order.
|
|
397
|
+
|
|
398
|
+
A generated search index MUST be treated as an accelerator rather than source truth. Implementations MUST be able to reject an incompatible accelerator and rebuild it from the primary card index.
|
|
399
|
+
|
|
400
|
+
Transactional work directories and recovery journals are not deterministic artifacts. They MUST NOT be copied into source comments or committed as semantic metadata.
|
|
401
|
+
|
|
402
|
+
## Stable order
|
|
403
|
+
|
|
404
|
+
`.llmnav/order.lock` records semantic IDs in append-only catalog order. Implementations SHOULD preserve existing lines and append new active IDs.
|
|
405
|
+
|
|
406
|
+
A deleted ID MAY remain in the lock. Removing or globally reordering entries is an explicit cache-epoch operation, not routine formatting.
|
|
407
|
+
|
|
408
|
+
## Conformance
|
|
409
|
+
|
|
410
|
+
A source parser conforms to LLMNav/1 when it recognizes all required comment encodings, field syntax, and canonical keys.
|
|
411
|
+
|
|
412
|
+
A checker conforms when it enforces required fields, controlled values, ID syntax, forbidden volatile data, relation resolution, registry state validity, and declaration attachment.
|
|
413
|
+
|
|
414
|
+
An indexer conforms when it keeps source semantics separate from generated location and emits deterministic output for identical input.
|
|
415
|
+
|
|
416
|
+
A coding-agent integration conforms when it directs the agent to query compact cards before broad repository exploration and does not treat generated paths as stable source metadata.
|
|
417
|
+
|
|
418
|
+
## Versioning
|
|
419
|
+
|
|
420
|
+
The npm package version and source specification version are independent.
|
|
421
|
+
|
|
422
|
+
Backward-compatible parser, CLI, ranking, or diagnostic improvements use normal semantic package versioning.
|
|
423
|
+
|
|
424
|
+
A breaking source grammar change requires a new header such as `llmnav/2`. Implementations MUST NOT reinterpret a `llmnav/1` card under incompatible rules.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AgentOperationResult,
|
|
3
|
+
AgentToolDefinition,
|
|
4
|
+
PromptPrefixBundle,
|
|
5
|
+
PromptPrefixPartition,
|
|
6
|
+
} from "llmnav";
|
|
7
|
+
|
|
8
|
+
export interface LlmnavHost {
|
|
9
|
+
toolDefinitions: AgentToolDefinition[];
|
|
10
|
+
basePromptPartitions: PromptPrefixPartition[];
|
|
11
|
+
selectPromptPartitions(moduleIds?: string[]): PromptPrefixPartition[];
|
|
12
|
+
execute(call: { name: string; input?: Record<string, unknown> }): Promise<AgentOperationResult>;
|
|
13
|
+
refresh(): Promise<LlmnavHost>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function createLlmnavHost(root: string): Promise<LlmnavHost>;
|
|
17
|
+
export function selectPromptPartitions(bundle: PromptPrefixBundle, moduleIds?: string[]): PromptPrefixPartition[];
|