@fux-engine/reader 0.0.0-stage → 4.0.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/README.md CHANGED
@@ -1,3 +1,110 @@
1
- # Temporary Holding Version
1
+ # fux-engine — the Node read plane
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Read a [fux](https://github.com/arpitarya/fux) index from Node. **The command
4
+ is `fux`; the package is `fux-engine`** — `fux` was taken on npm in 2016.
5
+
6
+ > **This file ships twice**, on purpose: it is the npm package's page, and
7
+ > `fux setup` vendors it into your repository at `.fux/node/README.md`. So it is
8
+ > written for whoever finds it, in either place.
9
+
10
+ ## Run it
11
+
12
+ **In a repository that has a fux index, always through the shim:**
13
+
14
+ ```console
15
+ $ .fux/fux find rollback
16
+ $ .fux/fux ask "how do we roll back a release" --band
17
+ $ .fux/fux answer "retry policy" --json
18
+ ```
19
+
20
+ 🔴 **`.fux/fux` is the one entry point that is correct in every shape**, which
21
+ is why it is the only one documented. It resolves the reader in three rungs —
22
+ the vendored bundle, then `.fux/node/node_modules/.bin/fux`, then every
23
+ ancestor's `node_modules/.bin/fux` — because npm and Yarn hoist that binary to
24
+ the workspace root and **pnpm and bun do not**. Naming a path instead would be
25
+ right for half the ecosystem and silently wrong for the other half.
26
+
27
+ **Without a repository, or to try it:**
28
+
29
+ ```console
30
+ $ npx fux-engine --version
31
+ ```
32
+
33
+ **As a library:**
34
+
35
+ ```js
36
+ import { open } from 'fux-engine'
37
+ const ix = await open('.')
38
+ await ix.find('rollback', { top: 5 })
39
+ ```
40
+
41
+ ## What is in `.fux/node/`
42
+
43
+ `fux setup` writes one of two shapes, and it detects which:
44
+
45
+ | | what is there | offline | how it runs |
46
+ |---|---|---|---|
47
+ | **the default** | `fux.mjs` (one generated file) · `package.json` · `mcp-tools.json` · this file | **yes** — nothing to install | `.fux/fux …` |
48
+ | **a monorepo** | `package.json` only, declaring `fux-engine@<version>` | after an install | `.fux/fux …`, once your package manager has run |
49
+
50
+ In the monorepo shape `.fux/node` is declared as a **workspace member** in your
51
+ root manifest — `fux setup` adds that one line, says so, and never adds it
52
+ twice. Run your package manager's `install` afterwards; `fux doctor` tells you
53
+ if you have not.
54
+
55
+ 🔴 **`fux.mjs` is GENERATED. Do not edit it.** It is rebuilt from fux's sources
56
+ at publish time and overwritten whenever the engine version changes. To see what
57
+ it does, read `node/fux.mjs` and `node/src/**` in the fux repository at the
58
+ matching tag — or regenerate it and compare bytes:
59
+
60
+ ```console
61
+ $ python -m fux.store.nodebundle node node/dist
62
+ ```
63
+
64
+ ## What it is
65
+
66
+ A fux index is a small, plain-text index committed to git — statistics about
67
+ your documents, never the documents. Python writes it; **Python or Node reads
68
+ it, and the two are held byte-equal by a differential law.**
69
+
70
+ - **Zero dependencies, and no build step *for you*.** There is no
71
+ `dependencies` key in the published `package.json` at all. Fux's own release
72
+ pipeline has a bundler; nobody running `fux setup` does, and nothing is
73
+ compiled on your machine.
74
+ - **One artefact, not a module tree.** What lands in your repository is one
75
+ generated file, so a fux upgrade is a one-file diff and a tampered reader is
76
+ detectable by rebuilding it. Before 2026-09-12 it was 47 of fux's own `.mjs`
77
+ files in your tree; `fux setup` deletes them when it upgrades you.
78
+ - **It never fetches, and it writes one thing: the derived plane.** `fux
79
+ build` rebuilds the gitignored `.fux/runtime/` from the committed index,
80
+ byte-identical to Python's build, under the same write lock, and `--fast`
81
+ then answers from it. `ingest`, `add`, `enrich` and every other write verb
82
+ belongs to Python fux, and typing one here tells you so rather than saying
83
+ *unknown command*.
84
+ - **Same answers as Python.** Same ids, same order, same locators, same band;
85
+ scores equal after `round(9)`, which is the sort key's own resolution.
86
+ - **Two things it deliberately does not do.** It cannot read a document that
87
+ needs a decoder (a `.pdf`, a `.xlsx`, your own `.fux/decoders/*.py`), so
88
+ `answer` **declines** to cite one rather than quoting line numbers into text
89
+ the index never held; and it never touches the network.
90
+
91
+ ## Two `fux` commands on one PATH
92
+
93
+ Python's `fux-engine` installs a `fux` too, with a **different verb set**.
94
+ `--version` names the runtime, so no bug report is ever ambiguous:
95
+
96
+ ```console
97
+ $ fux --version
98
+ fux 2.0.0 (node 24.13.0)
99
+ ```
100
+
101
+ `fux doctor` (Python's) reports when a Node `fux` sits earlier on your PATH.
102
+
103
+ ## Verbs
104
+
105
+ `find` · `ask` · `answer` · `explain` · `graph` · `path` · `mcp`
106
+
107
+ `fux mcp` serves the index over the Model Context Protocol on stdio —
108
+ `fux_search`, `fux_passage`, `fux_related` — so an agent can query it with no
109
+ glue. `verify`, `--why`, `--receipt` and `--journal` have no Node twin; they are
110
+ Python's.
package/fux.mjs ADDED
Binary file
package/mcp-tools.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "_comment": "The MCP tool descriptions, the authored text for node/src/verbs/mcp.mjs, held equal to src/fux/mcp.py's literal by tests/test_mcp.py. A description is what an agent reads to decide whether to call a tool, so two hand-maintained copies would drift into two products wearing one name. {{TOP}} is substituted with the connection's resolved [mcp] top.",
3
+ "tools": [
4
+ {
5
+ "name": "fux_search",
6
+ "description": "Search the committed index for documents relevant to a natural-language question. Returns ranked documents with content hashes and the headings that match your query -- section-level, not line-level; call fux_passage for the lines. This is the call to make first for any 'where is X' or 'why did we decide Y' question about this repository. READ THE `confidence` BLOCK BEFORE USING THE RESULTS. If `confidence.answerable` is false, do not answer from these results at all -- say what was searched and stop. If `confidence.band` is 'partial', answer but name every term in `confidence.missing`: those are words from the question that appear in no document here. If it is 'weak', the ranking could not separate the top hits -- that is a SIGNAL and not a refusal (`answerable` stays true): read the near-tied candidates and judge, and if neither answers, say the documents do not say and report what was searched rather than a conclusion. The payload also carries `related`: documents that NO query word matched, returned because the ranked results above LINK to them, each with the `route` it was reached by. They are not matches and must never be cited as one -- read a related document with fux_passage before you use it, and say that you followed a link to it rather than found it.",
7
+ "inputSchema": {
8
+ "type": "object",
9
+ "properties": {
10
+ "query": {
11
+ "type": "string",
12
+ "description": "A natural-language question."
13
+ },
14
+ "k": {
15
+ "type": "integer",
16
+ "description": "Maximum results (default {{TOP}}; this repository's .fux/output.toml may set a different default under [mcp]).",
17
+ "default": "{{TOP}}"
18
+ },
19
+ "expand": {
20
+ "type": "string",
21
+ "description": "OPTIONAL. Words you expect the document to use, when they differ from the question's. Scored at a lower weight than the question's own terms, and a document matching ONLY these is never returned. Use it after a search comes back `partial` with a non-empty `missing`: re-search with the vocabulary the corpus would use for the missing term."
22
+ }
23
+ },
24
+ "required": [
25
+ "query"
26
+ ]
27
+ }
28
+ },
29
+ {
30
+ "name": "fux_passage",
31
+ "description": "Read the verbatim text of a cited span, addressed as returned by fux_search. Use this instead of reading a whole file when you already have a citation: it returns only the cited lines and the hash they were read at, as `path`, `line_start`, `line_end`, `sha` and `text`.",
32
+ "inputSchema": {
33
+ "type": "object",
34
+ "properties": {
35
+ "path": {
36
+ "type": "string"
37
+ },
38
+ "line_start": {
39
+ "type": "integer"
40
+ },
41
+ "line_end": {
42
+ "type": "integer"
43
+ }
44
+ },
45
+ "required": [
46
+ "path"
47
+ ]
48
+ }
49
+ },
50
+ {
51
+ "name": "fux_related",
52
+ "description": "The neighbourhood around a document: what it links to, what links to it, what it supersedes or is superseded by, and whether it is archived. Use when a result raises 'what else was decided with this?' It returns `path`, `title`, `archived`, `superseded`, `outbound` and `inbound`.",
53
+ "inputSchema": {
54
+ "type": "object",
55
+ "properties": {
56
+ "path": {
57
+ "type": "string"
58
+ }
59
+ },
60
+ "required": [
61
+ "path"
62
+ ]
63
+ }
64
+ }
65
+ ]
66
+ }
package/package.json CHANGED
@@ -1,6 +1,42 @@
1
1
  {
2
2
  "name": "@fux-engine/reader",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "4.0.1",
4
+ "description": "Read a fux index from Node. Ranked, cited answers from a small index committed to git — no server, no model, no Python.",
5
+ "type": "module",
6
+ "engines": {
7
+ "node": ">=22"
8
+ },
9
+ "bin": {
10
+ "fux": "./fux.mjs"
11
+ },
12
+ "exports": {
13
+ ".": "./fux.mjs"
14
+ },
15
+ "files": [
16
+ "fux.mjs",
17
+ "mcp-tools.json",
18
+ "README.md"
19
+ ],
20
+ "license": "MIT",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/arpitarya/fux.git"
24
+ },
25
+ "homepage": "https://github.com/arpitarya/fux#readme",
26
+ "bugs": {
27
+ "url": "https://github.com/arpitarya/fux/issues"
28
+ },
29
+ "keywords": [
30
+ "knowledge",
31
+ "documentation",
32
+ "search",
33
+ "index",
34
+ "bm25",
35
+ "adr",
36
+ "runbook"
37
+ ],
38
+ "publishConfig": {
39
+ "access": "public",
40
+ "tag": "alpha"
41
+ }
42
+ }