@any-nav/scan 0.1.0 → 0.2.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/CHANGELOG.md +62 -0
- package/README.md +39 -12
- package/dist/budget.d.ts +26 -0
- package/dist/budget.js +25 -0
- package/dist/budget.js.map +1 -0
- package/dist/description.d.ts +24 -13
- package/dist/description.js +46 -27
- package/dist/description.js.map +1 -1
- package/dist/engine-mapping.d.ts +48 -0
- package/dist/engine-mapping.js +127 -0
- package/dist/engine-mapping.js.map +1 -0
- package/dist/hydration.d.ts +49 -0
- package/dist/hydration.js +181 -0
- package/dist/hydration.js.map +1 -0
- package/dist/index.d.ts +17 -6
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/scan.d.ts +6 -42
- package/dist/scan.js +39 -488
- package/dist/scan.js.map +1 -1
- package/dist/tree-replay.d.ts +61 -0
- package/dist/tree-replay.js +256 -0
- package/dist/tree-replay.js.map +1 -0
- package/dist/types.d.ts +18 -6
- package/package.json +11 -3
- package/dist/gitignore.d.ts +0 -9
- package/dist/gitignore.js +0 -128
- package/dist/gitignore.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,67 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0 — 2026-10-31
|
|
4
|
+
|
|
5
|
+
- The walk engine is delegated to `@catheadowl/pathscope` (facade
|
|
6
|
+
transition): `walkScope` answers "which files are in scope" — the
|
|
7
|
+
gitignore cascade (now inherited above the scan root, git-native), the
|
|
8
|
+
mounted exclusion floor, the dot category, boundary stones — while every
|
|
9
|
+
Markdown-shaped concern (the tree, the maxFiles budget and its fact-safe
|
|
10
|
+
cut, pruning, description chains) stays here. Public API and behavior
|
|
11
|
+
stand; the delegation ends the package split's zero-dependency premise —
|
|
12
|
+
`@catheadowl/pathscope` (^0.1.1) is now the package's one runtime
|
|
13
|
+
dependency.
|
|
14
|
+
- Accepted semantic increments with the delegation: the default floor now
|
|
15
|
+
also excludes `vendor/` and `coverage/` (engine presets; a `.gitignore`
|
|
16
|
+
negation naming the directory is the exit key), gitignore inheritance
|
|
17
|
+
reaches above the scan root, a subtree carrying its own `.git` is foreign
|
|
18
|
+
territory (truncated whole; `boundaryExempt` registers named subtrees
|
|
19
|
+
back in, below), and `unreadable-directory` diagnostics are gone
|
|
20
|
+
(unreadable directories are skipped engine-side). A narrowed terminal
|
|
21
|
+
floor keeps exact name semantics — nothing is force-mounted.
|
|
22
|
+
- `boundaryExempt`: `[scan]` and `ScanConfig` gain the named-subtree
|
|
23
|
+
core-stone exemption key — gitignore-style patterns anchored at the scan
|
|
24
|
+
root (e.g. `deepseek-harness/`) naming subtrees whose own nested `.git`
|
|
25
|
+
no longer cuts them from the view, passed verbatim to the engine's
|
|
26
|
+
`boundaryStones.exempt` (git's submodule-registration face: the subtree
|
|
27
|
+
descends as a native subtree with its nested `.gitignore` rules honored,
|
|
28
|
+
deeper embedded repos inside it still cut, registration is not rescue).
|
|
29
|
+
`ResolvedScanOptions.boundaryExempt?` is an optional field —
|
|
30
|
+
pre-existing terminal callers compile unchanged, and the default
|
|
31
|
+
behavior is byte-identical (no exemptions).
|
|
32
|
+
- The in-package gitignore engine (`gitignore.ts` and the
|
|
33
|
+
traversal-boundary family exports `GitignoreRule`,
|
|
34
|
+
`readInheritedGitignoreRules`, `readGitignoreRules`, `isGitignored`) is
|
|
35
|
+
removed outright, no deprecation window — breaking: after the delegation
|
|
36
|
+
it had zero importing consumers, and its fixture corpus has already been
|
|
37
|
+
absorbed into the shared engine's conformance suite. If a "read boundary
|
|
38
|
+
rules without a scan" consumption form ever materializes, the right home
|
|
39
|
+
is a public `@catheadowl/pathscope` API, not a private engine copy
|
|
40
|
+
inside a consumer.
|
|
41
|
+
- Folder descriptions now read standardized carriers in descending order
|
|
42
|
+
of standardization: the directory's own `package.json` `description`
|
|
43
|
+
first, then its `manifest.yml` `metadata.description`, else its own
|
|
44
|
+
`README.md` as before. Per stage, present-but-empty or key-less falls
|
|
45
|
+
through to the next; an unreadable or invalid carrier fires the
|
|
46
|
+
maintainer diagnostic `description-carrier-unreadable` and falls
|
|
47
|
+
through the same way. The carriers are never Markdown, so they never
|
|
48
|
+
enter the tree or consume the maxFiles budget. Export face:
|
|
49
|
+
`DIR_SIDECAR_NAMES` / `isDirSidecarName` become
|
|
50
|
+
`DIR_DESCRIPTION_CARRIERS` / `isDirDescriptionCarrier` — breaking for
|
|
51
|
+
direct importers of the renamed exports.
|
|
52
|
+
- `NavNode.markdown`: dir nodes, root included, carry the representative
|
|
53
|
+
README child's POSIX-relative path, present iff that README is in the
|
|
54
|
+
tree — consumers read a folder's front page without re-deriving which
|
|
55
|
+
child is the README.
|
|
56
|
+
- `scan.ts` is split into its four identifiable responsibilities:
|
|
57
|
+
`engine-mapping.ts` (the options/preset mapping and the walkScope
|
|
58
|
+
bridge), `tree-replay.ts` (the name-sorted DFS replay with pruning and
|
|
59
|
+
the fact-safe-cut chain), `budget.ts` (the maxFiles state shape and cut
|
|
60
|
+
diagnostics), and `hydration.ts` (the bounded read pipeline and the
|
|
61
|
+
description-provider face), while `scan.ts` keeps the dual entry points
|
|
62
|
+
and their output faces. Pure internal move — the public API and the
|
|
63
|
+
byte-level replay promises are untouched.
|
|
64
|
+
|
|
3
65
|
## 0.1.0 — 2026-10-21
|
|
4
66
|
|
|
5
67
|
First registry release: the zero-dependency scan engine, split out of
|
package/README.md
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
# @any-nav/scan
|
|
2
2
|
|
|
3
|
-
> Walk any Markdown folder into a navigation tree.
|
|
3
|
+
> Walk any Markdown folder into a navigation tree.
|
|
4
4
|
|
|
5
5
|
`@any-nav/scan` is the lean scan engine behind Any-Nav: it reads a folder of
|
|
6
6
|
Markdown files and produces a navigation tree — names, one-line descriptions,
|
|
7
7
|
and file locators — ready for listings, indexes, and agent navigation
|
|
8
|
-
surfaces.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
surfaces. The walk's scope resolution — gitignore cascade, exclusion floors,
|
|
9
|
+
the dot category, boundary stones — is delegated to
|
|
10
|
+
[`@catheadowl/pathscope`](https://www.npmjs.com/package/@catheadowl/pathscope)
|
|
11
|
+
(one runtime dependency); everything Markdown-shaped — the tree, the budget,
|
|
12
|
+
pruning, description chains — lives here. The full SDK (config, budget guard,
|
|
13
|
+
rendering, query) lives in `@any-nav/core`, which composes and re-exports
|
|
14
|
+
this package's full face.
|
|
12
15
|
|
|
13
16
|
## Install
|
|
14
17
|
|
|
@@ -64,10 +67,20 @@ read, at a fraction of the bytes.
|
|
|
64
67
|
|
|
65
68
|
- **Additive exclusions** — `excludeDirs` / `excludeFiles` append to an
|
|
66
69
|
always-on built-in floor (e.g. `AGENTS.md`, `CLAUDE.md`, `node_modules`,
|
|
67
|
-
`dist
|
|
68
|
-
|
|
70
|
+
`dist`, and — with the engine delegation — `vendor` and `coverage`); stating
|
|
71
|
+
one never drops the defaults. Dot entries are skipped by default. Empty
|
|
72
|
+
directories are pruned from the tree.
|
|
69
73
|
- **gitignore inheritance** — `respectGitignore` (default on): traversal
|
|
70
|
-
honors `.gitignore`
|
|
74
|
+
honors the `.gitignore` cascade, nested files and the chain above the scan
|
|
75
|
+
root alike (git-native; the exit key for a floor entry is naming it in a
|
|
76
|
+
`.gitignore` negation, e.g. `!vendor/`).
|
|
77
|
+
- **Registered subtrees** — `boundaryExempt`: gitignore-style patterns
|
|
78
|
+
anchored at the scan root (e.g. `deepseek-harness/`) naming subtrees whose
|
|
79
|
+
own nested `.git` no longer cuts them from this view — git's
|
|
80
|
+
submodule-registration face (an unregistered embedded repo is foreign
|
|
81
|
+
territory; a registered one participates). Registration is not rescue:
|
|
82
|
+
the subtree still passes every exclusion floor, and deeper embedded
|
|
83
|
+
repositories inside it still cut. Default: none.
|
|
71
84
|
- **A loud budget** — `maxFiles` (default 2000) caps markdown entries per
|
|
72
85
|
source walk; hitting the cap fires diagnostics, never a silent truncation:
|
|
73
86
|
folders whose descent was cut carry floor counts (`countIncompletePaths`
|
|
@@ -81,19 +94,33 @@ read, at a fraction of the bytes.
|
|
|
81
94
|
walks emit them per hydrated file, so a lazy view warns about the rows it
|
|
82
95
|
renders).
|
|
83
96
|
- **Folder descriptions** — a directory describes itself via its
|
|
84
|
-
|
|
85
|
-
the same extraction over
|
|
97
|
+
standardized carriers in order: its `package.json` `description`, else
|
|
98
|
+
its `manifest.yml` `metadata.description`, else the same extraction over
|
|
99
|
+
its own `README.md`; an unreadable or invalid carrier fires a
|
|
100
|
+
`description-carrier-unreadable` diagnostic and falls through.
|
|
101
|
+
- **Representative README locator** — dir nodes carry `markdown`, the
|
|
102
|
+
POSIX-relative path of the folder's representative `README.md`; present
|
|
103
|
+
iff that README is a node in the tree (file nodes never carry it).
|
|
86
104
|
- **Read-only** — scanning never modifies source files. The map is not the
|
|
87
105
|
territory.
|
|
88
106
|
|
|
89
107
|
## Boundaries this package keeps
|
|
90
108
|
|
|
91
|
-
-
|
|
92
|
-
|
|
109
|
+
- One runtime dependency by ruling — `@catheadowl/pathscope`, the shared
|
|
110
|
+
file-scope engine the walk delegates to; nothing else may join it.
|
|
93
111
|
- `ResolvedScanOptions` is terminal: callers hand the scanner final values;
|
|
94
112
|
`resolveScanOptions` is an additive default floor, not an obligation.
|
|
95
113
|
- `DescriptionProvider` is a port — the built-in chain is the default; a
|
|
96
114
|
custom provider (e.g. an LLM-backed one) plugs into the same interface.
|
|
115
|
+
- API shell policy: the public surface exports what real
|
|
116
|
+
consumption forms need — someone importing today, a local fork being the
|
|
117
|
+
unwired equivalent — and never speculative breadth; each future export
|
|
118
|
+
passes a light ruling first. The former traversal-boundary family
|
|
119
|
+
(`GitignoreRule`, `readInheritedGitignoreRules`, `readGitignoreRules`,
|
|
120
|
+
`isGitignored`) was removed with the in-package engine it belonged to: it
|
|
121
|
+
had no importing consumer, and reading boundary rules without a scan is
|
|
122
|
+
engine territory — the right home is a future `@catheadowl/pathscope`
|
|
123
|
+
API, not this package.
|
|
97
124
|
|
|
98
125
|
## License
|
|
99
126
|
|
package/dist/budget.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Budget cut — the nav-denominated maxFiles replay layer: the budget's
|
|
3
|
+
* unit is a TREE ENTRY and its
|
|
4
|
+
* arithmetic stays synchronous inside the replay (that is what keeps the cut
|
|
5
|
+
* point identical to the serial walk), so this module owns the shared state
|
|
6
|
+
* shape and the diagnostic vocabulary of the fact-safe cut — a partial count
|
|
7
|
+
* must never present as the total.
|
|
8
|
+
*/
|
|
9
|
+
import type { ScanDiagnostic } from './types.ts';
|
|
10
|
+
/**
|
|
11
|
+
* Shared mutable budget state (routes FileLimitState, ported): set when the
|
|
12
|
+
* maxFiles budget stops iteration while entries remain unexamined, so the
|
|
13
|
+
* caller reports the truncation loudly instead of silently dropping entries.
|
|
14
|
+
*/
|
|
15
|
+
export interface FileBudget {
|
|
16
|
+
files: number;
|
|
17
|
+
limitHit: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare function fileLimitDiagnostic(maxFiles: number): ScanDiagnostic;
|
|
20
|
+
/**
|
|
21
|
+
* Per-row disclosure for one floor-count folder: the budget
|
|
22
|
+
* cut this folder's descent mid-way, so the count a view renders for it is
|
|
23
|
+
* a floor. Consumer audience — it is view fidelity, same class as
|
|
24
|
+
* file-limit-reached.
|
|
25
|
+
*/
|
|
26
|
+
export declare function countTruncatedDiagnostic(rel: string): ScanDiagnostic;
|
package/dist/budget.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export function fileLimitDiagnostic(maxFiles) {
|
|
2
|
+
return {
|
|
3
|
+
code: 'file-limit-reached',
|
|
4
|
+
severity: 'warning',
|
|
5
|
+
message: `Markdown file limit (${maxFiles}) reached while scanning; entries past the limit were not examined — folders whose descent was cut carry ≥ counts (a floor, not the total) and later folders are absent. Raise scan.maxFiles for the full tree.`,
|
|
6
|
+
path: '.',
|
|
7
|
+
audience: 'consumer',
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Per-row disclosure for one floor-count folder: the budget
|
|
12
|
+
* cut this folder's descent mid-way, so the count a view renders for it is
|
|
13
|
+
* a floor. Consumer audience — it is view fidelity, same class as
|
|
14
|
+
* file-limit-reached.
|
|
15
|
+
*/
|
|
16
|
+
export function countTruncatedDiagnostic(rel) {
|
|
17
|
+
return {
|
|
18
|
+
code: 'count-truncated-at-limit',
|
|
19
|
+
severity: 'warning',
|
|
20
|
+
message: `The maxFiles budget cut this folder's descent short; its shown count is a floor (at least that many), and entries past the cut point are absent.`,
|
|
21
|
+
path: rel,
|
|
22
|
+
audience: 'consumer',
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"AAoBA,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,OAAO;QACL,IAAI,EAAE,oBAAoB;QAC1B,QAAQ,EAAE,SAAS;QACnB,OAAO,EAAE,wBAAwB,QAAQ,iNAAiN;QAC1P,IAAI,EAAE,GAAG;QACT,QAAQ,EAAE,UAAU;KACrB,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAAC,GAAW;IAClD,OAAO;QACL,IAAI,EAAE,0BAA0B;QAChC,QAAQ,EAAE,SAAS;QACnB,OAAO,EAAE,kJAAkJ;QAC3J,IAAI,EAAE,GAAG;QACT,QAAQ,EAAE,UAAU;KACrB,CAAC;AACJ,CAAC"}
|
package/dist/description.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* One-line description extraction, ported verbatim from the
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* paid on production corpora; do not "simplify" it).
|
|
2
|
+
* One-line description extraction, ported verbatim from the dsh-extras
|
|
3
|
+
* routes module (absorption is porting — every boundary handling here is
|
|
4
|
+
* tuition already paid on production corpora; do not "simplify" it).
|
|
6
5
|
*
|
|
7
6
|
* Priority: ① frontmatter `description:`, ② an explicit `description:` line
|
|
8
7
|
* in the document head, ③ the first substantive body line as a fallback.
|
|
@@ -17,17 +16,29 @@ export declare const BODY_HEAD_LINE_LIMIT = 15;
|
|
|
17
16
|
*/
|
|
18
17
|
export declare function extractDescription(content: string): string | null;
|
|
19
18
|
/**
|
|
20
|
-
* Directory
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
19
|
+
* Directory description carriers: the folder chain sources from standardized carriers in
|
|
20
|
+
* descending order of standardization — ① the directory's own npm
|
|
21
|
+
* `package.json` `description` (nearly always present by ecosystem
|
|
22
|
+
* discipline), ② its `manifest.yml` `metadata.description` (the
|
|
23
|
+
* manifest-authoring directory-contract gloss — optional by that contract,
|
|
24
|
+
* present-only). Present-but-empty or absent falls through to the next
|
|
25
|
+
* stage; neither fabricates a description. The README stage lives in
|
|
26
|
+
* tree-replay (the chain's tail, not a carrier).
|
|
27
27
|
*/
|
|
28
|
-
export type
|
|
28
|
+
export type CarrierRead = {
|
|
29
29
|
description: string | null;
|
|
30
30
|
} | {
|
|
31
31
|
error: string;
|
|
32
32
|
};
|
|
33
|
-
|
|
33
|
+
/** Carrier ①: proper JSON parse; a non-object payload is as broken as invalid JSON (npm itself cannot read it — maintainer-visible). */
|
|
34
|
+
export declare function extractPackageJsonDescription(content: string): CarrierRead;
|
|
35
|
+
/**
|
|
36
|
+
* Carrier ②: the `metadata.description` gloss under the `metadata:` block —
|
|
37
|
+
* the only description key the closed manifest v1 schema defines, so the
|
|
38
|
+
* scan is anchored to that parent (a stray top-level or sibling-block
|
|
39
|
+
* `description:` is not read). YAML reuses the frontmatter ① key reader over
|
|
40
|
+
* the block (its `decription` typo tolerance rides along; manifest faces
|
|
41
|
+
* have their own validator). Lenient by nature — never errors, a shape
|
|
42
|
+
* without the key reads as `{ description: null }`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function extractManifestDescription(content: string): CarrierRead;
|
package/dist/description.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* One-line description extraction, ported verbatim from the
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* paid on production corpora; do not "simplify" it).
|
|
2
|
+
* One-line description extraction, ported verbatim from the dsh-extras
|
|
3
|
+
* routes module (absorption is porting — every boundary handling here is
|
|
4
|
+
* tuition already paid on production corpora; do not "simplify" it).
|
|
6
5
|
*
|
|
7
6
|
* Priority: ① frontmatter `description:`, ② an explicit `description:` line
|
|
8
7
|
* in the document head, ③ the first substantive body line as a fallback.
|
|
@@ -72,7 +71,7 @@ function isStructuralLine(line) {
|
|
|
72
71
|
if (/^\d{1,3}\.\s/u.test(text))
|
|
73
72
|
return true; // ordered list
|
|
74
73
|
// table row / language-switch ("English | [中文]"); inline code spans are
|
|
75
|
-
// masked first — marked-up code is never table structure
|
|
74
|
+
// masked first — marked-up code is never table structure
|
|
76
75
|
const outsideCodeSpans = text.replace(/`[^`]*`/gu, '');
|
|
77
76
|
if (outsideCodeSpans.startsWith('|') || /\s\|\s/u.test(outsideCodeSpans))
|
|
78
77
|
return true;
|
|
@@ -191,30 +190,50 @@ function stripHtmlComments(lines) {
|
|
|
191
190
|
}
|
|
192
191
|
return openLines;
|
|
193
192
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
193
|
+
/** Carrier ①: proper JSON parse; a non-object payload is as broken as invalid JSON (npm itself cannot read it — maintainer-visible). */
|
|
194
|
+
export function extractPackageJsonDescription(content) {
|
|
195
|
+
let parsed;
|
|
196
|
+
try {
|
|
197
|
+
parsed = JSON.parse(content);
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
return { error: `invalid JSON: ${err.message}` };
|
|
201
|
+
}
|
|
202
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
203
|
+
return { error: 'package.json must be a JSON object' };
|
|
204
|
+
}
|
|
205
|
+
const description = parsed.description;
|
|
206
|
+
return {
|
|
207
|
+
description: typeof description === 'string' && description.trim() !== '' ? description.trim() : null,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Carrier ②: the `metadata.description` gloss under the `metadata:` block —
|
|
212
|
+
* the only description key the closed manifest v1 schema defines, so the
|
|
213
|
+
* scan is anchored to that parent (a stray top-level or sibling-block
|
|
214
|
+
* `description:` is not read). YAML reuses the frontmatter ① key reader over
|
|
215
|
+
* the block (its `decription` typo tolerance rides along; manifest faces
|
|
216
|
+
* have their own validator). Lenient by nature — never errors, a shape
|
|
217
|
+
* without the key reads as `{ description: null }`.
|
|
218
|
+
*/
|
|
219
|
+
export function extractManifestDescription(content) {
|
|
220
|
+
const lines = content.split(/\r?\n/u);
|
|
221
|
+
const metadataIndex = lines.findIndex((line) => /^metadata:\s*$/u.test(line));
|
|
222
|
+
if (metadataIndex === -1)
|
|
223
|
+
return { description: null };
|
|
224
|
+
const block = [];
|
|
225
|
+
for (let index = metadataIndex + 1; index < lines.length; index++) {
|
|
226
|
+
const line = lines[index];
|
|
227
|
+
if (line.trim().length === 0) {
|
|
228
|
+
if (block.length > 0)
|
|
229
|
+
break;
|
|
230
|
+
continue;
|
|
205
231
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (top !== null)
|
|
210
|
-
return { description: top };
|
|
211
|
-
const link = typeof obj.link === 'object' && obj.link !== null && !Array.isArray(obj.link)
|
|
212
|
-
? obj.link
|
|
213
|
-
: undefined;
|
|
214
|
-
const nested = link === undefined ? null : fromKey(link.description);
|
|
215
|
-
return { description: nested };
|
|
232
|
+
if (!/^\s+/u.test(line))
|
|
233
|
+
break; // dedent — the metadata block ended
|
|
234
|
+
block.push(line);
|
|
216
235
|
}
|
|
217
|
-
return { description: readDescriptionKey(
|
|
236
|
+
return { description: block.length > 0 ? readDescriptionKey(block) : null };
|
|
218
237
|
}
|
|
219
238
|
function parseYamlLikeFrontmatter(content) {
|
|
220
239
|
const lines = content.split(/\r?\n/u);
|
package/dist/description.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"description.js","sourceRoot":"","sources":["../src/description.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"description.js","sourceRoot":"","sources":["../src/description.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ScanConfig } from './types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Agent-instruction files harnesses load on their own; they carry no
|
|
4
|
+
* navigation value (the agent already has them) so they never appear in
|
|
5
|
+
* navigation (routes DEFAULT_EXCLUDE_FILES, ported).
|
|
6
|
+
*/
|
|
7
|
+
export declare const DEFAULT_EXCLUDE_FILES: readonly string[];
|
|
8
|
+
/** routes DEFAULT_EXCLUDE_DIRS, ported verbatim. Always on (the safety
|
|
9
|
+
* floor); user excludeDirs entries append to it, never replace it — a
|
|
10
|
+
* generate-era 'any-nav' entry was retired with `list --write` (the
|
|
11
|
+
* materialization target is now any file the caller names). */
|
|
12
|
+
export declare const DEFAULT_EXCLUDE_DIRS: readonly string[];
|
|
13
|
+
export interface ResolvedScanOptions {
|
|
14
|
+
excludeDirs: readonly string[];
|
|
15
|
+
excludeFiles: readonly string[];
|
|
16
|
+
excludeDotEntries: boolean;
|
|
17
|
+
respectGitignore: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Named-subtree core-stone exemptions, passed verbatim to the
|
|
20
|
+
* engine's `boundaryStones.exempt`: gitignore-style patterns anchored at
|
|
21
|
+
* the scan root. Optional — absent means no exemptions (every embedded
|
|
22
|
+
* repo stays foreign territory, exactly as before the key existed); the
|
|
23
|
+
* field stays optional so pre-existing terminal callers keep compiling.
|
|
24
|
+
*/
|
|
25
|
+
boundaryExempt?: readonly string[];
|
|
26
|
+
maxFiles: number;
|
|
27
|
+
}
|
|
28
|
+
export declare function resolveScanOptions(config?: ScanConfig): ResolvedScanOptions;
|
|
29
|
+
/** One trie level over the engine's in-scope set: files sit at their direct
|
|
30
|
+
* parent, directory segments carry the levels beneath them. Only levels with
|
|
31
|
+
* in-scope content exist — an empty directory (or one whose content is all
|
|
32
|
+
* out of scope) never enters the trie, which is the empty-directory pruning
|
|
33
|
+
* the old walk computed by hand. */
|
|
34
|
+
export interface ScopeLevel {
|
|
35
|
+
files: Set<string>;
|
|
36
|
+
dirs: Map<string, ScopeLevel>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The one engine query — "which files are in scope". Unbounded on purpose: the
|
|
40
|
+
* budget's unit is a TREE ENTRY (a Markdown file surviving the consumer
|
|
41
|
+
* filters), so the engine's raw-file budget never fires here and the
|
|
42
|
+
* replay below owns the fact-safe cut, its ordering, and its diagnostics.
|
|
43
|
+
* (Engine diagnostics beyond the budget do not exist in 0.1.0.)
|
|
44
|
+
* boundaryExempt rides boundaryStones.exempt verbatim: naming a
|
|
45
|
+
* subtree registers its participation — its own .git no longer cuts it,
|
|
46
|
+
* while deeper embedded repos inside it and un-named siblings keep the cut.
|
|
47
|
+
*/
|
|
48
|
+
export declare function scopeLevels(root: string, opts: ResolvedScanOptions): Promise<ScopeLevel>;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine mapping face — everything crossing the boundary into
|
|
3
|
+
* @catheadowl/pathscope (the facade face): the
|
|
4
|
+
* resolved-options face (the additive default floor), the preset mounts, the
|
|
5
|
+
* policy-channel patterns, the walkScope query itself, and the scope trie the
|
|
6
|
+
* replay descends. "Which files are in scope" is the engine's question; the
|
|
7
|
+
* Markdown layer that turns the scope into a tree lives in tree-replay.ts.
|
|
8
|
+
*/
|
|
9
|
+
import { walkScope } from '@catheadowl/pathscope';
|
|
10
|
+
/**
|
|
11
|
+
* Agent-instruction files harnesses load on their own; they carry no
|
|
12
|
+
* navigation value (the agent already has them) so they never appear in
|
|
13
|
+
* navigation (routes DEFAULT_EXCLUDE_FILES, ported).
|
|
14
|
+
*/
|
|
15
|
+
export const DEFAULT_EXCLUDE_FILES = ['AGENTS.md', 'CLAUDE.md'];
|
|
16
|
+
/** routes DEFAULT_EXCLUDE_DIRS, ported verbatim. Always on (the safety
|
|
17
|
+
* floor); user excludeDirs entries append to it, never replace it — a
|
|
18
|
+
* generate-era 'any-nav' entry was retired with `list --write` (the
|
|
19
|
+
* materialization target is now any file the caller names). */
|
|
20
|
+
export const DEFAULT_EXCLUDE_DIRS = [
|
|
21
|
+
'.git',
|
|
22
|
+
'.hg',
|
|
23
|
+
'.svn',
|
|
24
|
+
'node_modules',
|
|
25
|
+
'.pnpm',
|
|
26
|
+
'dist',
|
|
27
|
+
'build',
|
|
28
|
+
'lib',
|
|
29
|
+
'out',
|
|
30
|
+
];
|
|
31
|
+
export function resolveScanOptions(config) {
|
|
32
|
+
// Additive ruling: the built-in tables are the
|
|
33
|
+
// always-on floor, user entries append — "the file states only exceptions"
|
|
34
|
+
// must not mean restating the defaults to add one. Duplicates are harmless
|
|
35
|
+
// (membership checks only), so a plain concat stays honest. boundaryExempt
|
|
36
|
+
// has no floor to append to — an absent key means no exemptions.
|
|
37
|
+
return {
|
|
38
|
+
excludeDirs: [...DEFAULT_EXCLUDE_DIRS, ...(config?.excludeDirs ?? [])],
|
|
39
|
+
excludeFiles: [...DEFAULT_EXCLUDE_FILES, ...(config?.excludeFiles ?? [])],
|
|
40
|
+
excludeDotEntries: config?.excludeDotEntries ?? true,
|
|
41
|
+
respectGitignore: config?.respectGitignore ?? true,
|
|
42
|
+
boundaryExempt: config?.boundaryExempt ?? [],
|
|
43
|
+
maxFiles: config?.maxFiles ?? 2000,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The engine-mounted exclusion floor: when the caller resolved
|
|
48
|
+
* the built-in floor (resolveScanOptions output, or an equivalent terminal
|
|
49
|
+
* list), its dir table rides the engine's preset form — vcs/deps/build carry
|
|
50
|
+
* the old nine-entry DEFAULT_EXCLUDE_DIRS table plus vendor/ and coverage/
|
|
51
|
+
* (the accepted preset increment) — and agentDocs carries the built-in
|
|
52
|
+
* AGENTS.md/CLAUDE.md file exclusion. A terminal caller that narrowed the
|
|
53
|
+
* floor (BASE_SCAN-style excludeDirs: []) keeps exact name semantics via
|
|
54
|
+
* the policy channel and the replay's literal check: nothing is
|
|
55
|
+
* force-mounted. (The preset increment is negatable by a repo's .gitignore
|
|
56
|
+
* — engine front-seat semantics; the floor names on the policy channel are
|
|
57
|
+
* not, exactly as before.)
|
|
58
|
+
*/
|
|
59
|
+
function engineMounts(opts) {
|
|
60
|
+
const mounts = [];
|
|
61
|
+
if (DEFAULT_EXCLUDE_DIRS.every((name) => opts.excludeDirs.includes(name))) {
|
|
62
|
+
mounts.push('vcs', 'deps', 'build');
|
|
63
|
+
}
|
|
64
|
+
if (DEFAULT_EXCLUDE_FILES.every((name) => opts.excludeFiles.includes(name))) {
|
|
65
|
+
mounts.push('agentDocs');
|
|
66
|
+
}
|
|
67
|
+
return mounts;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The resolved excludeDirs ride the engine's policy channel as dir-only
|
|
71
|
+
* patterns at the rear seat of the rule table — exactly the old floor's
|
|
72
|
+
* independence from gitignore (a repo's `!node_modules/` cannot resurrect a
|
|
73
|
+
* floor entry). Entries that are not plain names (separators, globs, a
|
|
74
|
+
* leading '!') stay out of the channel: the old engine compared directory
|
|
75
|
+
* names by literal equality, and those entries keep that semantics in the
|
|
76
|
+
* replay instead of acquiring pattern meaning.
|
|
77
|
+
*/
|
|
78
|
+
function excludeChannelPatterns(excludeDirs) {
|
|
79
|
+
return excludeDirs
|
|
80
|
+
.filter((name) => /^[^/\\!*?[\]!#]+$/u.test(name))
|
|
81
|
+
.map((name) => `${name}/`);
|
|
82
|
+
}
|
|
83
|
+
function buildScopeLevel(paths) {
|
|
84
|
+
const root = { files: new Set(), dirs: new Map() };
|
|
85
|
+
for (const path of paths) {
|
|
86
|
+
const segments = path.split('/');
|
|
87
|
+
let level = root;
|
|
88
|
+
for (let index = 0; index < segments.length - 1; index += 1) {
|
|
89
|
+
const segment = segments[index];
|
|
90
|
+
if (segment === undefined)
|
|
91
|
+
continue;
|
|
92
|
+
let child = level.dirs.get(segment);
|
|
93
|
+
if (child === undefined) {
|
|
94
|
+
child = { files: new Set(), dirs: new Map() };
|
|
95
|
+
level.dirs.set(segment, child);
|
|
96
|
+
}
|
|
97
|
+
level = child;
|
|
98
|
+
}
|
|
99
|
+
const file = segments[segments.length - 1];
|
|
100
|
+
if (file !== undefined && file !== '')
|
|
101
|
+
level.files.add(file);
|
|
102
|
+
}
|
|
103
|
+
return root;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The one engine query — "which files are in scope". Unbounded on purpose: the
|
|
107
|
+
* budget's unit is a TREE ENTRY (a Markdown file surviving the consumer
|
|
108
|
+
* filters), so the engine's raw-file budget never fires here and the
|
|
109
|
+
* replay below owns the fact-safe cut, its ordering, and its diagnostics.
|
|
110
|
+
* (Engine diagnostics beyond the budget do not exist in 0.1.0.)
|
|
111
|
+
* boundaryExempt rides boundaryStones.exempt verbatim: naming a
|
|
112
|
+
* subtree registers its participation — its own .git no longer cuts it,
|
|
113
|
+
* while deeper embedded repos inside it and un-named siblings keep the cut.
|
|
114
|
+
*/
|
|
115
|
+
export async function scopeLevels(root, opts) {
|
|
116
|
+
const boundaryExempt = opts.boundaryExempt ?? [];
|
|
117
|
+
const scope = await walkScope(root, {
|
|
118
|
+
mountPresets: engineMounts(opts),
|
|
119
|
+
exclude: excludeChannelPatterns(opts.excludeDirs),
|
|
120
|
+
excludeDotEntries: opts.excludeDotEntries,
|
|
121
|
+
respectGitignore: opts.respectGitignore,
|
|
122
|
+
...(boundaryExempt.length > 0 ? { boundaryStones: { exempt: [...boundaryExempt] } } : {}),
|
|
123
|
+
maxFiles: Number.MAX_SAFE_INTEGER,
|
|
124
|
+
});
|
|
125
|
+
return buildScopeLevel(scope.files);
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=engine-mapping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-mapping.js","sourceRoot":"","sources":["../src/engine-mapping.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,SAAS,EAAmB,MAAM,uBAAuB,CAAC;AAInE;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAsB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AAEnF;;;+DAG+D;AAC/D,MAAM,CAAC,MAAM,oBAAoB,GAAsB;IACrD,MAAM;IACN,KAAK;IACL,MAAM;IACN,cAAc;IACd,OAAO;IACP,MAAM;IACN,OAAO;IACP,KAAK;IACL,KAAK;CACN,CAAC;AAkBF,MAAM,UAAU,kBAAkB,CAAC,MAAmB;IACpD,+CAA+C;IAC/C,2EAA2E;IAC3E,2EAA2E;IAC3E,2EAA2E;IAC3E,iEAAiE;IACjE,OAAO;QACL,WAAW,EAAE,CAAC,GAAG,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC;QACtE,YAAY,EAAE,CAAC,GAAG,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,IAAI,EAAE,CAAC,CAAC;QACzE,iBAAiB,EAAE,MAAM,EAAE,iBAAiB,IAAI,IAAI;QACpD,gBAAgB,EAAE,MAAM,EAAE,gBAAgB,IAAI,IAAI;QAClD,cAAc,EAAE,MAAM,EAAE,cAAc,IAAI,EAAE;QAC5C,QAAQ,EAAE,MAAM,EAAE,QAAQ,IAAI,IAAI;KACnC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,YAAY,CAAC,IAAyB;IAC7C,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,IAAI,oBAAoB,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QAC1E,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IACD,IAAI,qBAAqB,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QAC5E,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,sBAAsB,CAAC,WAA8B;IAC5D,OAAO,WAAW;SACf,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SACjD,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC;AAC/B,CAAC;AAYD,SAAS,eAAe,CAAC,KAAwB;IAC/C,MAAM,IAAI,GAAe,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;IAC/D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,KAAK,GAAG,IAAI,CAAC;QACjB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YAC5D,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;YAChC,IAAI,OAAO,KAAK,SAAS;gBAAE,SAAS;YACpC,IAAI,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACpC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,KAAK,GAAG,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;gBAC9C,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACjC,CAAC;YACD,KAAK,GAAG,KAAK,CAAC;QAChB,CAAC;QACD,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC3C,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE;YAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,IAAyB;IACvE,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,IAAI,EAAE,CAAC;IACjD,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE;QAClC,YAAY,EAAE,YAAY,CAAC,IAAI,CAAC;QAChC,OAAO,EAAE,sBAAsB,CAAC,IAAI,CAAC,WAAW,CAAC;QACjD,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;QACzC,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;QACvC,GAAG,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,cAAc,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzF,QAAQ,EAAE,MAAM,CAAC,gBAAgB;KAClC,CAAC,CAAC;IACH,OAAO,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { NavItem, NavNode, ScanDiagnostic } from './types.ts';
|
|
2
|
+
export interface ScannedFile {
|
|
3
|
+
path: string;
|
|
4
|
+
content: string;
|
|
5
|
+
}
|
|
6
|
+
/** Port: built-in chain is the ported routes extraction; LLM providers arrive in v1.x. */
|
|
7
|
+
export interface DescriptionProvider {
|
|
8
|
+
extract(file: ScannedFile): Promise<string | null>;
|
|
9
|
+
}
|
|
10
|
+
export declare const builtinDescriptionProvider: DescriptionProvider;
|
|
11
|
+
/** One started read awaiting its settle: item attaches blank at kick-off,
|
|
12
|
+
* the description lands at the settle. */
|
|
13
|
+
export interface PendingRead {
|
|
14
|
+
rel: string;
|
|
15
|
+
content: Promise<string | null>;
|
|
16
|
+
item: NavItem;
|
|
17
|
+
}
|
|
18
|
+
/** Walk-order diagnostic events: directory diagnostics record where they
|
|
19
|
+
* fired; file events settle at the drain — the flattened order equals the
|
|
20
|
+
* serial walk's emission order. Structure walks emit diag events only. */
|
|
21
|
+
export type DiagnosticEvent = {
|
|
22
|
+
kind: 'diag';
|
|
23
|
+
diagnostic: ScanDiagnostic;
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'file';
|
|
26
|
+
read: PendingRead;
|
|
27
|
+
};
|
|
28
|
+
/** Structure-walk file record: the node exists without an item; describe()
|
|
29
|
+
* attaches the item after extraction. */
|
|
30
|
+
export interface FileRecord {
|
|
31
|
+
rel: string;
|
|
32
|
+
abs: string;
|
|
33
|
+
node: NavNode;
|
|
34
|
+
}
|
|
35
|
+
/** Bounded in-flight read window: kicks never reject (read errors resolve
|
|
36
|
+
* null — the unreadable-file path), and the gate waits for the next settle
|
|
37
|
+
* before kicking past the ceiling. gate() then start() keeps the started
|
|
38
|
+
* promise unwrapped for fire-and-continue callers. */
|
|
39
|
+
export declare class BoundedReads {
|
|
40
|
+
private readonly pending;
|
|
41
|
+
/** Wait for a window slot (no-op while under the ceiling). */
|
|
42
|
+
gate(): Promise<void>;
|
|
43
|
+
/** Start one read and return its still-running promise. */
|
|
44
|
+
start(abs: string): Promise<string | null>;
|
|
45
|
+
}
|
|
46
|
+
/** Settle one started read: the description lands on the item and any
|
|
47
|
+
* per-file diagnostic (unreadable-file / no-description placeholder) goes
|
|
48
|
+
* to the sink at the caller's position. */
|
|
49
|
+
export declare function settleDescription(read: PendingRead, provider: DescriptionProvider, sink: ScanDiagnostic[]): Promise<void>;
|