fux-engine 0.1.0__tar.gz
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.
- fux_engine-0.1.0/LICENSE +21 -0
- fux_engine-0.1.0/PKG-INFO +186 -0
- fux_engine-0.1.0/README.md +147 -0
- fux_engine-0.1.0/fux/__init__.py +6 -0
- fux_engine-0.1.0/fux/__main__.py +4 -0
- fux_engine-0.1.0/fux/assets/fux-icon.svg +61 -0
- fux_engine-0.1.0/fux/assets/fux-lockup.svg +69 -0
- fux_engine-0.1.0/fux/assets/fux-mark.svg +26 -0
- fux_engine-0.1.0/fux/assets/graph_boot.js +214 -0
- fux_engine-0.1.0/fux/assets/graph_template.html +111 -0
- fux_engine-0.1.0/fux/astextract.py +410 -0
- fux_engine-0.1.0/fux/bench.py +34 -0
- fux_engine-0.1.0/fux/build.py +29 -0
- fux_engine-0.1.0/fux/capture.py +99 -0
- fux_engine-0.1.0/fux/check.py +143 -0
- fux_engine-0.1.0/fux/cli.py +139 -0
- fux_engine-0.1.0/fux/clicmds.py +162 -0
- fux_engine-0.1.0/fux/cligraph.py +69 -0
- fux_engine-0.1.0/fux/cliquery.py +157 -0
- fux_engine-0.1.0/fux/cliutil.py +13 -0
- fux_engine-0.1.0/fux/community.py +50 -0
- fux_engine-0.1.0/fux/config.py +85 -0
- fux_engine-0.1.0/fux/context.py +31 -0
- fux_engine-0.1.0/fux/costledger.py +119 -0
- fux_engine-0.1.0/fux/coverage.py +43 -0
- fux_engine-0.1.0/fux/data/global/README.md +37 -0
- fux_engine-0.1.0/fux/data/global/rules/async-everywhere.md +22 -0
- fux_engine-0.1.0/fux/data/global/rules/doc-per-code-change.md +23 -0
- fux_engine-0.1.0/fux/data/global/rules/files-max-100-lines.md +20 -0
- fux_engine-0.1.0/fux/data/global/rules/no-secrets-in-vcs.md +21 -0
- fux_engine-0.1.0/fux/data/hooks/_common.sh +12 -0
- fux_engine-0.1.0/fux/data/hooks/post_tool_use.sh +7 -0
- fux_engine-0.1.0/fux/data/hooks/session_start.sh +7 -0
- fux_engine-0.1.0/fux/data/hooks/stop.sh +7 -0
- fux_engine-0.1.0/fux/data/hooks/user_prompt_submit.sh +7 -0
- fux_engine-0.1.0/fux/data/packs/indian-markets-tax/pack.toml +6 -0
- fux_engine-0.1.0/fux/data/packs/indian-markets-tax/rules/capital-gains-equity.md +22 -0
- fux_engine-0.1.0/fux/data/packs/indian-markets-tax/rules/market-hours-nse.md +21 -0
- fux_engine-0.1.0/fux/data/schema.json +48 -0
- fux_engine-0.1.0/fux/data/skills/adr/SKILL.md +37 -0
- fux_engine-0.1.0/fux/data/skills/distill/SKILL.md +66 -0
- fux_engine-0.1.0/fux/data/skills/fetch-rules/SKILL.md +147 -0
- fux_engine-0.1.0/fux/data/skills/fux/SKILL.md +154 -0
- fux_engine-0.1.0/fux/data/skills/plan/SKILL.md +67 -0
- fux_engine-0.1.0/fux/data/skills/savings/SKILL.md +56 -0
- fux_engine-0.1.0/fux/data/skills/trace/SKILL.md +38 -0
- fux_engine-0.1.0/fux/drift.py +27 -0
- fux_engine-0.1.0/fux/embed.py +67 -0
- fux_engine-0.1.0/fux/explain.py +64 -0
- fux_engine-0.1.0/fux/fetchrules.py +122 -0
- fux_engine-0.1.0/fux/findings.py +26 -0
- fux_engine-0.1.0/fux/fix.py +54 -0
- fux_engine-0.1.0/fux/fmwrite.py +46 -0
- fux_engine-0.1.0/fux/frontmatter.py +88 -0
- fux_engine-0.1.0/fux/gate.py +65 -0
- fux_engine-0.1.0/fux/gitutil.py +69 -0
- fux_engine-0.1.0/fux/globs.py +38 -0
- fux_engine-0.1.0/fux/governance.py +55 -0
- fux_engine-0.1.0/fux/graph.py +137 -0
- fux_engine-0.1.0/fux/graphhtml.py +14 -0
- fux_engine-0.1.0/fux/graphquery.py +113 -0
- fux_engine-0.1.0/fux/hookio.py +34 -0
- fux_engine-0.1.0/fux/hooks.py +99 -0
- fux_engine-0.1.0/fux/hybrid.py +78 -0
- fux_engine-0.1.0/fux/importer.py +86 -0
- fux_engine-0.1.0/fux/index.py +45 -0
- fux_engine-0.1.0/fux/initcmd.py +58 -0
- fux_engine-0.1.0/fux/lint.py +96 -0
- fux_engine-0.1.0/fux/loader.py +62 -0
- fux_engine-0.1.0/fux/mcpserver.py +179 -0
- fux_engine-0.1.0/fux/mine.py +96 -0
- fux_engine-0.1.0/fux/model.py +82 -0
- fux_engine-0.1.0/fux/narrative.py +35 -0
- fux_engine-0.1.0/fux/pack.py +53 -0
- fux_engine-0.1.0/fux/parity.py +156 -0
- fux_engine-0.1.0/fux/paths.py +85 -0
- fux_engine-0.1.0/fux/recall.py +131 -0
- fux_engine-0.1.0/fux/report.py +63 -0
- fux_engine-0.1.0/fux/savings.py +192 -0
- fux_engine-0.1.0/fux/scaffold.py +58 -0
- fux_engine-0.1.0/fux/scalars.py +32 -0
- fux_engine-0.1.0/fux/schema.py +54 -0
- fux_engine-0.1.0/fux/seal.py +142 -0
- fux_engine-0.1.0/fux/serve.py +77 -0
- fux_engine-0.1.0/fux/settings.py +52 -0
- fux_engine-0.1.0/fux/stats.py +132 -0
- fux_engine-0.1.0/fux/templates/formula.md +22 -0
- fux_engine-0.1.0/fux/templates/spec.md +29 -0
- fux_engine-0.1.0/fux/touch.py +37 -0
- fux_engine-0.1.0/fux/tour.py +34 -0
- fux_engine-0.1.0/fux/usage.py +60 -0
- fux_engine-0.1.0/fux/verify.py +75 -0
- fux_engine-0.1.0/fux/vexamples.py +144 -0
- fux_engine-0.1.0/fux_engine.egg-info/PKG-INFO +186 -0
- fux_engine-0.1.0/fux_engine.egg-info/SOURCES.txt +128 -0
- fux_engine-0.1.0/fux_engine.egg-info/dependency_links.txt +1 -0
- fux_engine-0.1.0/fux_engine.egg-info/entry_points.txt +2 -0
- fux_engine-0.1.0/fux_engine.egg-info/requires.txt +15 -0
- fux_engine-0.1.0/fux_engine.egg-info/top_level.txt +1 -0
- fux_engine-0.1.0/pyproject.toml +70 -0
- fux_engine-0.1.0/setup.cfg +4 -0
- fux_engine-0.1.0/tests/test_ast_backend.py +88 -0
- fux_engine-0.1.0/tests/test_astextract.py +71 -0
- fux_engine-0.1.0/tests/test_bm25f_expand.py +38 -0
- fux_engine-0.1.0/tests/test_capture_governance.py +90 -0
- fux_engine-0.1.0/tests/test_centrality.py +36 -0
- fux_engine-0.1.0/tests/test_check_fix.py +31 -0
- fux_engine-0.1.0/tests/test_costledger.py +51 -0
- fux_engine-0.1.0/tests/test_crossfile_calls.py +35 -0
- fux_engine-0.1.0/tests/test_embed_rerank.py +30 -0
- fux_engine-0.1.0/tests/test_examples.py +52 -0
- fux_engine-0.1.0/tests/test_fetch_rules.py +191 -0
- fux_engine-0.1.0/tests/test_frontmatter.py +49 -0
- fux_engine-0.1.0/tests/test_fuzz_mine.py +43 -0
- fux_engine-0.1.0/tests/test_globs.py +21 -0
- fux_engine-0.1.0/tests/test_graphhtml.py +18 -0
- fux_engine-0.1.0/tests/test_hybrid.py +55 -0
- fux_engine-0.1.0/tests/test_lint_stats_gate.py +76 -0
- fux_engine-0.1.0/tests/test_mcp.py +60 -0
- fux_engine-0.1.0/tests/test_mcp_extra.py +48 -0
- fux_engine-0.1.0/tests/test_pack.py +54 -0
- fux_engine-0.1.0/tests/test_parity_import.py +117 -0
- fux_engine-0.1.0/tests/test_recall_build_verify.py +64 -0
- fux_engine-0.1.0/tests/test_recall_eval.py +124 -0
- fux_engine-0.1.0/tests/test_resolution.py +37 -0
- fux_engine-0.1.0/tests/test_savings.py +60 -0
- fux_engine-0.1.0/tests/test_schema_scaffold_init.py +43 -0
- fux_engine-0.1.0/tests/test_seal.py +87 -0
- fux_engine-0.1.0/tests/test_serve_sanitize.py +60 -0
- fux_engine-0.1.0/tests/test_verify_hardening.py +68 -0
fux_engine-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 arpit arya
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fux-engine
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Fux — a portable, Claude-aware knowledge engine: rules, memory, narrative, and graph in one frontmatter substrate.
|
|
5
|
+
Author-email: arpit arya <arpitarya.me@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/arpitarya/fux
|
|
8
|
+
Project-URL: Repository, https://github.com/arpitarya/fux
|
|
9
|
+
Project-URL: Documentation, https://github.com/arpitarya/fux/blob/main/docs/guide.md
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/arpitarya/fux/issues
|
|
11
|
+
Keywords: knowledge,rules,graph,claude,frontmatter,llm,memory,mcp
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
22
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
24
|
+
Requires-Python: >=3.11
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Provides-Extra: embeddings
|
|
28
|
+
Requires-Dist: sentence-transformers>=2.2; extra == "embeddings"
|
|
29
|
+
Provides-Extra: ast
|
|
30
|
+
Requires-Dist: tree-sitter>=0.23; extra == "ast"
|
|
31
|
+
Requires-Dist: tree-sitter-language-pack>=0.7; extra == "ast"
|
|
32
|
+
Provides-Extra: pdf
|
|
33
|
+
Requires-Dist: pypdf>=4.0; extra == "pdf"
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
36
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
37
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# Fux
|
|
41
|
+
|
|
42
|
+
> A portable, Claude-aware **knowledge engine**. One frontmatter substrate →
|
|
43
|
+
> derived **index**, **graph**, and **memory** views. `$0` deterministic
|
|
44
|
+
> maintenance — no mandatory LLM calls. Continuously referenced, cheaply
|
|
45
|
+
> maintained.
|
|
46
|
+
|
|
47
|
+
Named after *Johann Joseph Fux*, author of *Gradus ad Parnassum* (1725) — the
|
|
48
|
+
counterpoint treatise every composer learned the rules from. A tool that codifies
|
|
49
|
+
and enforces rules, named after the man who wrote *the* rulebook. Sits beside
|
|
50
|
+
`wagner`, `bach`, `orff`.
|
|
51
|
+
|
|
52
|
+
Fux **unifies and replaces** three things a project usually runs separately — the
|
|
53
|
+
structural graph (graphify), cross-session memory, and the narrative docs — and
|
|
54
|
+
adds the **business-rules layer** none of them held. See [docs/fux-plan.md](docs/fux-plan.md).
|
|
55
|
+
|
|
56
|
+
## In plain words (the 5-year-old version)
|
|
57
|
+
|
|
58
|
+
Think of your code as a big LEGO city. The *reasons* things are built a certain
|
|
59
|
+
way — why the bridge is red, why you add the towers before the walls — usually
|
|
60
|
+
live only in one builder's head. When they go home, nobody remembers why.
|
|
61
|
+
|
|
62
|
+
**Fux is a notebook for those reasons.** You write each important rule down once —
|
|
63
|
+
*what* it is and *why* — and Fux sticks a tiny one-line list on the cover so your
|
|
64
|
+
helper (Claude) can flip straight to the right page instead of searching the whole
|
|
65
|
+
city every time. Fux also **draws a map** showing which notes belong to which
|
|
66
|
+
buildings, and **checks** that the notes still match the city — and it does all of
|
|
67
|
+
that for free, without phoning anyone for help.
|
|
68
|
+
|
|
69
|
+
So: write the *why* down once → it's found fast, stays correct, and never gets lost.
|
|
70
|
+
|
|
71
|
+
## Why
|
|
72
|
+
|
|
73
|
+
The *why* behind a formula — why current value not invested cost, why
|
|
74
|
+
INR-normalize first, which cost-basis method — usually lives only as an inline
|
|
75
|
+
comment, invisible until someone greps for it. Fux makes that knowledge
|
|
76
|
+
**first-class**: one entry, authored once, served back through a tiny index (read
|
|
77
|
+
first) plus lazily-opened rules (read only when relevant). Lookups run ~5–10×
|
|
78
|
+
cheaper and more correct on every later session — and you don't have to take that
|
|
79
|
+
on faith: **`fux savings`** measures the multiplier from your own file sizes.
|
|
80
|
+
|
|
81
|
+
## Install
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
git clone git@github.com:arpitarya/fux.git && cd fux
|
|
85
|
+
./install.sh # → ~/.claude/fux/{engine,global,packs,hooks} + /fux skill
|
|
86
|
+
fux --version
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Requires Python ≥ 3.11 (stdlib only — zero third-party dependencies).
|
|
90
|
+
|
|
91
|
+
## Use
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
cd your-project
|
|
95
|
+
fux init # scaffold .fux/ + wire 3 hooks + CLAUDE.md pointer
|
|
96
|
+
fux new formula day-pnl # scaffold a rule; fill **Rule:/Why:/Edge cases:**
|
|
97
|
+
fux build # regenerate INDEX.md + rules.json + graph ($0)
|
|
98
|
+
fux check --fix # validate; repair mechanical drift ($0)
|
|
99
|
+
fux why day-pnl [--history] # explain a rule (+ how its *why* evolved, via git)
|
|
100
|
+
fux refs src/aggregator.py # which rules govern this file
|
|
101
|
+
fux recall "how is day P&L computed" --hybrid # BM25F; RRF-fuse lexical+semantic+graph
|
|
102
|
+
fux seal --all # bind rules to an AST fingerprint of their code
|
|
103
|
+
fux coverage # % of important files with a governing rule
|
|
104
|
+
fux verify --fuzz # run invariant `check:`; boundary-fuzz for div-by-zero
|
|
105
|
+
fux mine # surface candidate rules latent in the code (drafts)
|
|
106
|
+
fux savings "how is day P&L computed" # measured token-cost win (+ cumulative ledger)
|
|
107
|
+
fux lint # rule *quality*: missing why / code_refs / edges
|
|
108
|
+
fux stats # knowledge-health dashboard + score
|
|
109
|
+
fux gate --install # wire a git pre-commit enforcement hook
|
|
110
|
+
fux mcp # serve the substrate to agents over MCP (stdio)
|
|
111
|
+
fux capture # queue this session's changes for `fux distill`
|
|
112
|
+
fux serve # local dashboard over the generated views
|
|
113
|
+
fux import docs/ # migrate existing markdown → narrative entries
|
|
114
|
+
fux parity # is it safe to retire the old graph/docs/memory?
|
|
115
|
+
fux tour # ordered ONBOARDING.md
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Complete, example-driven guide to everything Fux does:
|
|
119
|
+
[docs/guide.md](docs/guide.md).** Full command reference: [docs/cli.md](docs/cli.md).
|
|
120
|
+
Authoring a rule: [docs/rule.guide.md](docs/rule.guide.md). Writing a spec:
|
|
121
|
+
[docs/spec.guide.md](docs/spec.guide.md).
|
|
122
|
+
|
|
123
|
+
## How it works
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
Tier 0 CLAUDE.md pointer ........ 1 line, always in context
|
|
127
|
+
Tier 1 .fux/out/INDEX.md ........ ~1 line/rule, read FIRST ← cheap
|
|
128
|
+
Tier 2 .fux/rules/<id>.md ....... opened ONLY when relevant ← lazy
|
|
129
|
+
Tier 3 .fux/out/{rules,graph}.json machine lookup + browsing
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
You maintain **only** the source frontmatter. INDEX, `rules.json`, and the
|
|
133
|
+
interactive `graph.html` regenerate on `fux build`. Three hooks keep it live:
|
|
134
|
+
SessionStart injects the INDEX, PostToolUse reminds you when an edited file's rule
|
|
135
|
+
drifted, Stop validates before the turn ends.
|
|
136
|
+
|
|
137
|
+
The **graph** merges your rules with code symbols and call edges extracted across
|
|
138
|
+
**Python** (via the stdlib `ast`) and **JS/TS, Go, and Rust** (a brace-matched
|
|
139
|
+
heuristic by default, or **real tree-sitter ASTs** with the optional
|
|
140
|
+
`pip install fux-engine[ast]` extra — same schema, more accuracy, still $0 by
|
|
141
|
+
default), now including **cross-file** `calls` (symbol→symbol) — one navigable
|
|
142
|
+
map of *which rule governs which code*, with community clustering, **PageRank
|
|
143
|
+
centrality** (architectural chokepoints, not just raw degree), and a
|
|
144
|
+
`GRAPH_REPORT.md`. The interactive `graph.html` is built for review *and* agents:
|
|
145
|
+
node/edge-type filters, colour-by (type/community/layer/degree), focus +
|
|
146
|
+
neighbour highlighting, a details panel, and one-click **markdown export** of a
|
|
147
|
+
node's neighbourhood or the visible sub-graph.
|
|
148
|
+
|
|
149
|
+
`fux recall` is lexical **BM25F** (`$0`) by default, with opt-in **query expansion**
|
|
150
|
+
(glossary synonyms + 1-hop graph neighbours), an opt-in **local** re-rank, and an
|
|
151
|
+
opt-in **RRF hybrid** that fuses lexical ⊕ local-semantic ⊕ graph proximity (no
|
|
152
|
+
API); `fux verify [--fuzz]` runs a rule's invariant `check:` and worked `examples:`,
|
|
153
|
+
optionally boundary-fuzzing for unguarded div-by-zero. **Proof-carrying rules:**
|
|
154
|
+
`fux seal` binds a rule to a normalized-AST fingerprint of its code, so `fux check`
|
|
155
|
+
flags `unsealed` when the governed code changes *structure* (not just its mtime).
|
|
156
|
+
Beyond authoring, Fux **enforces and reports**: `fux lint` grades rule quality,
|
|
157
|
+
`fux stats` scores knowledge health, `fux gate` blocks drift at commit/CI time,
|
|
158
|
+
and `fux mcp` exposes the whole substrate to agents over MCP.
|
|
159
|
+
|
|
160
|
+
For cross-session memory it stays **authored, not captured**: an opt-in `capture`
|
|
161
|
+
hook queues *which* files changed for `fux distill` (human-confirmed) rather than
|
|
162
|
+
auto-summarising, and `type: memory` entries **decay** after a TTL so stale notes
|
|
163
|
+
stop costing context — with opt-in **usage-weighted decay** (a memory still being
|
|
164
|
+
recalled stays alive; an unused one decays). Every path `$0` and deterministic.
|
|
165
|
+
|
|
166
|
+
### Layered rules (maintain once, inherit everywhere)
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
effective ruleset = ~/.claude/fux/global/ (cross-project best practices)
|
|
170
|
+
⊕ ~/.claude/fux/packs/* (opt-in shareable domain packs)
|
|
171
|
+
⊕ ./.fux/rules/ (this project's domain rules)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`project` overrides `pack` overrides `global`. `fux check` flags conflicts
|
|
175
|
+
instead of silently shadowing.
|
|
176
|
+
|
|
177
|
+
## Guarantee
|
|
178
|
+
|
|
179
|
+
Every maintenance command is shell/AST/parse — **no LLM calls**. The only paths
|
|
180
|
+
that call the LLM are the `plan` / `adr` skills, and they ride the session you are
|
|
181
|
+
already in (no background spend). The same "$0, deterministic" promise that made
|
|
182
|
+
graphify trustworthy.
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Fux
|
|
2
|
+
|
|
3
|
+
> A portable, Claude-aware **knowledge engine**. One frontmatter substrate →
|
|
4
|
+
> derived **index**, **graph**, and **memory** views. `$0` deterministic
|
|
5
|
+
> maintenance — no mandatory LLM calls. Continuously referenced, cheaply
|
|
6
|
+
> maintained.
|
|
7
|
+
|
|
8
|
+
Named after *Johann Joseph Fux*, author of *Gradus ad Parnassum* (1725) — the
|
|
9
|
+
counterpoint treatise every composer learned the rules from. A tool that codifies
|
|
10
|
+
and enforces rules, named after the man who wrote *the* rulebook. Sits beside
|
|
11
|
+
`wagner`, `bach`, `orff`.
|
|
12
|
+
|
|
13
|
+
Fux **unifies and replaces** three things a project usually runs separately — the
|
|
14
|
+
structural graph (graphify), cross-session memory, and the narrative docs — and
|
|
15
|
+
adds the **business-rules layer** none of them held. See [docs/fux-plan.md](docs/fux-plan.md).
|
|
16
|
+
|
|
17
|
+
## In plain words (the 5-year-old version)
|
|
18
|
+
|
|
19
|
+
Think of your code as a big LEGO city. The *reasons* things are built a certain
|
|
20
|
+
way — why the bridge is red, why you add the towers before the walls — usually
|
|
21
|
+
live only in one builder's head. When they go home, nobody remembers why.
|
|
22
|
+
|
|
23
|
+
**Fux is a notebook for those reasons.** You write each important rule down once —
|
|
24
|
+
*what* it is and *why* — and Fux sticks a tiny one-line list on the cover so your
|
|
25
|
+
helper (Claude) can flip straight to the right page instead of searching the whole
|
|
26
|
+
city every time. Fux also **draws a map** showing which notes belong to which
|
|
27
|
+
buildings, and **checks** that the notes still match the city — and it does all of
|
|
28
|
+
that for free, without phoning anyone for help.
|
|
29
|
+
|
|
30
|
+
So: write the *why* down once → it's found fast, stays correct, and never gets lost.
|
|
31
|
+
|
|
32
|
+
## Why
|
|
33
|
+
|
|
34
|
+
The *why* behind a formula — why current value not invested cost, why
|
|
35
|
+
INR-normalize first, which cost-basis method — usually lives only as an inline
|
|
36
|
+
comment, invisible until someone greps for it. Fux makes that knowledge
|
|
37
|
+
**first-class**: one entry, authored once, served back through a tiny index (read
|
|
38
|
+
first) plus lazily-opened rules (read only when relevant). Lookups run ~5–10×
|
|
39
|
+
cheaper and more correct on every later session — and you don't have to take that
|
|
40
|
+
on faith: **`fux savings`** measures the multiplier from your own file sizes.
|
|
41
|
+
|
|
42
|
+
## Install
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
git clone git@github.com:arpitarya/fux.git && cd fux
|
|
46
|
+
./install.sh # → ~/.claude/fux/{engine,global,packs,hooks} + /fux skill
|
|
47
|
+
fux --version
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Requires Python ≥ 3.11 (stdlib only — zero third-party dependencies).
|
|
51
|
+
|
|
52
|
+
## Use
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
cd your-project
|
|
56
|
+
fux init # scaffold .fux/ + wire 3 hooks + CLAUDE.md pointer
|
|
57
|
+
fux new formula day-pnl # scaffold a rule; fill **Rule:/Why:/Edge cases:**
|
|
58
|
+
fux build # regenerate INDEX.md + rules.json + graph ($0)
|
|
59
|
+
fux check --fix # validate; repair mechanical drift ($0)
|
|
60
|
+
fux why day-pnl [--history] # explain a rule (+ how its *why* evolved, via git)
|
|
61
|
+
fux refs src/aggregator.py # which rules govern this file
|
|
62
|
+
fux recall "how is day P&L computed" --hybrid # BM25F; RRF-fuse lexical+semantic+graph
|
|
63
|
+
fux seal --all # bind rules to an AST fingerprint of their code
|
|
64
|
+
fux coverage # % of important files with a governing rule
|
|
65
|
+
fux verify --fuzz # run invariant `check:`; boundary-fuzz for div-by-zero
|
|
66
|
+
fux mine # surface candidate rules latent in the code (drafts)
|
|
67
|
+
fux savings "how is day P&L computed" # measured token-cost win (+ cumulative ledger)
|
|
68
|
+
fux lint # rule *quality*: missing why / code_refs / edges
|
|
69
|
+
fux stats # knowledge-health dashboard + score
|
|
70
|
+
fux gate --install # wire a git pre-commit enforcement hook
|
|
71
|
+
fux mcp # serve the substrate to agents over MCP (stdio)
|
|
72
|
+
fux capture # queue this session's changes for `fux distill`
|
|
73
|
+
fux serve # local dashboard over the generated views
|
|
74
|
+
fux import docs/ # migrate existing markdown → narrative entries
|
|
75
|
+
fux parity # is it safe to retire the old graph/docs/memory?
|
|
76
|
+
fux tour # ordered ONBOARDING.md
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Complete, example-driven guide to everything Fux does:
|
|
80
|
+
[docs/guide.md](docs/guide.md).** Full command reference: [docs/cli.md](docs/cli.md).
|
|
81
|
+
Authoring a rule: [docs/rule.guide.md](docs/rule.guide.md). Writing a spec:
|
|
82
|
+
[docs/spec.guide.md](docs/spec.guide.md).
|
|
83
|
+
|
|
84
|
+
## How it works
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
Tier 0 CLAUDE.md pointer ........ 1 line, always in context
|
|
88
|
+
Tier 1 .fux/out/INDEX.md ........ ~1 line/rule, read FIRST ← cheap
|
|
89
|
+
Tier 2 .fux/rules/<id>.md ....... opened ONLY when relevant ← lazy
|
|
90
|
+
Tier 3 .fux/out/{rules,graph}.json machine lookup + browsing
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
You maintain **only** the source frontmatter. INDEX, `rules.json`, and the
|
|
94
|
+
interactive `graph.html` regenerate on `fux build`. Three hooks keep it live:
|
|
95
|
+
SessionStart injects the INDEX, PostToolUse reminds you when an edited file's rule
|
|
96
|
+
drifted, Stop validates before the turn ends.
|
|
97
|
+
|
|
98
|
+
The **graph** merges your rules with code symbols and call edges extracted across
|
|
99
|
+
**Python** (via the stdlib `ast`) and **JS/TS, Go, and Rust** (a brace-matched
|
|
100
|
+
heuristic by default, or **real tree-sitter ASTs** with the optional
|
|
101
|
+
`pip install fux-engine[ast]` extra — same schema, more accuracy, still $0 by
|
|
102
|
+
default), now including **cross-file** `calls` (symbol→symbol) — one navigable
|
|
103
|
+
map of *which rule governs which code*, with community clustering, **PageRank
|
|
104
|
+
centrality** (architectural chokepoints, not just raw degree), and a
|
|
105
|
+
`GRAPH_REPORT.md`. The interactive `graph.html` is built for review *and* agents:
|
|
106
|
+
node/edge-type filters, colour-by (type/community/layer/degree), focus +
|
|
107
|
+
neighbour highlighting, a details panel, and one-click **markdown export** of a
|
|
108
|
+
node's neighbourhood or the visible sub-graph.
|
|
109
|
+
|
|
110
|
+
`fux recall` is lexical **BM25F** (`$0`) by default, with opt-in **query expansion**
|
|
111
|
+
(glossary synonyms + 1-hop graph neighbours), an opt-in **local** re-rank, and an
|
|
112
|
+
opt-in **RRF hybrid** that fuses lexical ⊕ local-semantic ⊕ graph proximity (no
|
|
113
|
+
API); `fux verify [--fuzz]` runs a rule's invariant `check:` and worked `examples:`,
|
|
114
|
+
optionally boundary-fuzzing for unguarded div-by-zero. **Proof-carrying rules:**
|
|
115
|
+
`fux seal` binds a rule to a normalized-AST fingerprint of its code, so `fux check`
|
|
116
|
+
flags `unsealed` when the governed code changes *structure* (not just its mtime).
|
|
117
|
+
Beyond authoring, Fux **enforces and reports**: `fux lint` grades rule quality,
|
|
118
|
+
`fux stats` scores knowledge health, `fux gate` blocks drift at commit/CI time,
|
|
119
|
+
and `fux mcp` exposes the whole substrate to agents over MCP.
|
|
120
|
+
|
|
121
|
+
For cross-session memory it stays **authored, not captured**: an opt-in `capture`
|
|
122
|
+
hook queues *which* files changed for `fux distill` (human-confirmed) rather than
|
|
123
|
+
auto-summarising, and `type: memory` entries **decay** after a TTL so stale notes
|
|
124
|
+
stop costing context — with opt-in **usage-weighted decay** (a memory still being
|
|
125
|
+
recalled stays alive; an unused one decays). Every path `$0` and deterministic.
|
|
126
|
+
|
|
127
|
+
### Layered rules (maintain once, inherit everywhere)
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
effective ruleset = ~/.claude/fux/global/ (cross-project best practices)
|
|
131
|
+
⊕ ~/.claude/fux/packs/* (opt-in shareable domain packs)
|
|
132
|
+
⊕ ./.fux/rules/ (this project's domain rules)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`project` overrides `pack` overrides `global`. `fux check` flags conflicts
|
|
136
|
+
instead of silently shadowing.
|
|
137
|
+
|
|
138
|
+
## Guarantee
|
|
139
|
+
|
|
140
|
+
Every maintenance command is shell/AST/parse — **no LLM calls**. The only paths
|
|
141
|
+
that call the LLM are the `plan` / `adr` skills, and they ride the session you are
|
|
142
|
+
already in (no background spend). The same "$0, deterministic" promise that made
|
|
143
|
+
graphify trustworthy.
|
|
144
|
+
|
|
145
|
+
## License
|
|
146
|
+
|
|
147
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120" width="120" height="120">
|
|
2
|
+
<defs>
|
|
3
|
+
<!-- tile backgrounds -->
|
|
4
|
+
<linearGradient id="ic-bg" x1="0" y1="0" x2=".6" y2="1">
|
|
5
|
+
<stop offset="0%" stop-color="#16140f"/>
|
|
6
|
+
<stop offset="100%" stop-color="#0a0908"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
<radialGradient id="ic-glow" cx="50%" cy="18%" r="70%">
|
|
9
|
+
<stop offset="0%" stop-color="#9ed94a1a"/>
|
|
10
|
+
<stop offset="100%" stop-color="rgba(0,0,0,0)"/>
|
|
11
|
+
</radialGradient>
|
|
12
|
+
<linearGradient id="ic-shine" x1="0" y1="0" x2="0" y2="1">
|
|
13
|
+
<stop offset="0%" stop-color="rgba(255,255,255,.06)"/>
|
|
14
|
+
<stop offset="100%" stop-color="rgba(255,255,255,0)"/>
|
|
15
|
+
</linearGradient>
|
|
16
|
+
<!-- mark gradient -->
|
|
17
|
+
<linearGradient id="ic-mg" x1="0" y1="0" x2="1" y2="1">
|
|
18
|
+
<stop offset="0%" stop-color="#D2F58F"/>
|
|
19
|
+
<stop offset="55%" stop-color="#8FD13F"/>
|
|
20
|
+
<stop offset="100%" stop-color="#4C8A1B"/>
|
|
21
|
+
</linearGradient>
|
|
22
|
+
<clipPath id="ic-mc">
|
|
23
|
+
<rect x="12" y="10" width="40" height="44" rx="10"/>
|
|
24
|
+
</clipPath>
|
|
25
|
+
<filter id="ic-drop" x="-30%" y="-30%" width="160%" height="160%">
|
|
26
|
+
<feGaussianBlur in="SourceGraphic" stdDeviation="2.5" result="blur"/>
|
|
27
|
+
<feComposite in="SourceGraphic" in2="blur" operator="over"/>
|
|
28
|
+
</filter>
|
|
29
|
+
</defs>
|
|
30
|
+
|
|
31
|
+
<!-- tile base -->
|
|
32
|
+
<rect width="120" height="120" rx="28" fill="url(#ic-bg)" stroke="rgba(255,255,255,.08)" stroke-width="1"/>
|
|
33
|
+
<!-- accent glow overlay -->
|
|
34
|
+
<rect width="120" height="120" rx="28" fill="url(#ic-glow)"/>
|
|
35
|
+
<!-- top-edge shine -->
|
|
36
|
+
<rect width="120" height="60" rx="28" fill="url(#ic-shine)"/>
|
|
37
|
+
|
|
38
|
+
<!-- mark: size=78, centred → offset=(120-78)/2=21 -->
|
|
39
|
+
<svg x="21" y="21" width="78" height="78" viewBox="0 0 64 64">
|
|
40
|
+
<defs>
|
|
41
|
+
<linearGradient id="ic-mg2" x1="0" y1="0" x2="1" y2="1">
|
|
42
|
+
<stop offset="0%" stop-color="#D2F58F"/>
|
|
43
|
+
<stop offset="55%" stop-color="#8FD13F"/>
|
|
44
|
+
<stop offset="100%" stop-color="#4C8A1B"/>
|
|
45
|
+
</linearGradient>
|
|
46
|
+
<clipPath id="ic-mc2">
|
|
47
|
+
<rect x="12" y="10" width="40" height="44" rx="10"/>
|
|
48
|
+
</clipPath>
|
|
49
|
+
</defs>
|
|
50
|
+
<g filter="url(#ic-drop)">
|
|
51
|
+
<rect x="12" y="10" width="40" height="44" rx="10" fill="url(#ic-mg2)"/>
|
|
52
|
+
<g clip-path="url(#ic-mc2)">
|
|
53
|
+
<polygon points="12,10 32,10 12,30" fill="#fff" opacity=".15"/>
|
|
54
|
+
<polygon points="52,54 52,34 32,54" fill="#000" opacity=".17"/>
|
|
55
|
+
</g>
|
|
56
|
+
<path d="M26 10 L38 10 L38 33 L32 28 L26 33 Z" fill="#000" opacity=".26"/>
|
|
57
|
+
<rect x="19" y="42" width="26" height="3" rx="1.5" fill="#000" opacity=".24"/>
|
|
58
|
+
<rect x="19" y="48" width="17" height="3" rx="1.5" fill="#000" opacity=".24"/>
|
|
59
|
+
</g>
|
|
60
|
+
</svg>
|
|
61
|
+
</svg>
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 440 110" width="440" height="110">
|
|
2
|
+
<defs>
|
|
3
|
+
<!-- background -->
|
|
4
|
+
<linearGradient id="lk-bg" x1="0" y1="0" x2="0" y2="1">
|
|
5
|
+
<stop offset="0%" stop-color="#121110"/>
|
|
6
|
+
<stop offset="100%" stop-color="#0a0a09"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
<!-- vertical rule -->
|
|
9
|
+
<linearGradient id="lk-rule" x1="0" y1="0" x2="0" y2="1">
|
|
10
|
+
<stop offset="0%" stop-color="rgba(255,255,255,0)"/>
|
|
11
|
+
<stop offset="50%" stop-color="rgba(255,255,255,.14)"/>
|
|
12
|
+
<stop offset="100%" stop-color="rgba(255,255,255,0)"/>
|
|
13
|
+
</linearGradient>
|
|
14
|
+
<!-- mark gradient -->
|
|
15
|
+
<linearGradient id="lk-mg" x1="0" y1="0" x2="1" y2="1">
|
|
16
|
+
<stop offset="0%" stop-color="#D2F58F"/>
|
|
17
|
+
<stop offset="55%" stop-color="#8FD13F"/>
|
|
18
|
+
<stop offset="100%" stop-color="#4C8A1B"/>
|
|
19
|
+
</linearGradient>
|
|
20
|
+
<clipPath id="lk-mc">
|
|
21
|
+
<rect x="12" y="10" width="40" height="44" rx="10"/>
|
|
22
|
+
</clipPath>
|
|
23
|
+
<filter id="lk-glow" x="-40%" y="-40%" width="180%" height="180%">
|
|
24
|
+
<feGaussianBlur in="SourceGraphic" stdDeviation="3" result="blur"/>
|
|
25
|
+
<feComposite in="SourceGraphic" in2="blur" operator="over"/>
|
|
26
|
+
</filter>
|
|
27
|
+
<style>
|
|
28
|
+
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@700&family=Space+Mono&display=swap');
|
|
29
|
+
.lk-eyebrow { font: 8.5px 'Space Mono', 'Courier New', monospace; letter-spacing: .34em; fill: #7a756b; }
|
|
30
|
+
.lk-name { font: 700 30px 'Space Grotesk', 'Helvetica Neue', Arial, sans-serif; letter-spacing: .16em; fill: #f2efe9; }
|
|
31
|
+
.lk-role { font: 10px 'Space Mono', 'Courier New', monospace; letter-spacing: .26em; fill: #9ed94a; }
|
|
32
|
+
</style>
|
|
33
|
+
</defs>
|
|
34
|
+
|
|
35
|
+
<!-- plate -->
|
|
36
|
+
<rect width="440" height="110" rx="14" fill="url(#lk-bg)" stroke="rgba(255,255,255,.07)" stroke-width="1"/>
|
|
37
|
+
|
|
38
|
+
<!-- mark: 74×74, vertically centred → y=18 -->
|
|
39
|
+
<svg x="34" y="18" width="74" height="74" viewBox="0 0 64 64" overflow="visible">
|
|
40
|
+
<defs>
|
|
41
|
+
<linearGradient id="lk-mg2" x1="0" y1="0" x2="1" y2="1">
|
|
42
|
+
<stop offset="0%" stop-color="#D2F58F"/>
|
|
43
|
+
<stop offset="55%" stop-color="#8FD13F"/>
|
|
44
|
+
<stop offset="100%" stop-color="#4C8A1B"/>
|
|
45
|
+
</linearGradient>
|
|
46
|
+
<clipPath id="lk-mc2">
|
|
47
|
+
<rect x="12" y="10" width="40" height="44" rx="10"/>
|
|
48
|
+
</clipPath>
|
|
49
|
+
</defs>
|
|
50
|
+
<g filter="url(#lk-glow)">
|
|
51
|
+
<rect x="12" y="10" width="40" height="44" rx="10" fill="url(#lk-mg2)"/>
|
|
52
|
+
<g clip-path="url(#lk-mc2)">
|
|
53
|
+
<polygon points="12,10 32,10 12,30" fill="#fff" opacity=".15"/>
|
|
54
|
+
<polygon points="52,54 52,34 32,54" fill="#000" opacity=".17"/>
|
|
55
|
+
</g>
|
|
56
|
+
<path d="M26 10 L38 10 L38 33 L32 28 L26 33 Z" fill="#000" opacity=".26"/>
|
|
57
|
+
<rect x="19" y="42" width="26" height="3" rx="1.5" fill="#000" opacity=".24"/>
|
|
58
|
+
<rect x="19" y="48" width="17" height="3" rx="1.5" fill="#000" opacity=".24"/>
|
|
59
|
+
</g>
|
|
60
|
+
</svg>
|
|
61
|
+
|
|
62
|
+
<!-- vertical rule: x=130, margin 22px top+bottom → y=22..88 -->
|
|
63
|
+
<rect x="130" y="22" width="1" height="66" fill="url(#lk-rule)"/>
|
|
64
|
+
|
|
65
|
+
<!-- text block: x=153, centred on y=55 -->
|
|
66
|
+
<text x="153" y="30" class="lk-eyebrow">ALPHA FORGE</text>
|
|
67
|
+
<text x="153" y="68" class="lk-name">FUX</text>
|
|
68
|
+
<text x="153" y="88" class="lk-role">KNOWLEDGE INDEX</text>
|
|
69
|
+
</svg>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="fux-g" x1="0" y1="0" x2="1" y2="1">
|
|
4
|
+
<stop offset="0%" stop-color="#D2F58F"/>
|
|
5
|
+
<stop offset="55%" stop-color="#8FD13F"/>
|
|
6
|
+
<stop offset="100%" stop-color="#4C8A1B"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
<clipPath id="fux-c">
|
|
9
|
+
<rect x="12" y="10" width="40" height="44" rx="10"/>
|
|
10
|
+
</clipPath>
|
|
11
|
+
<filter id="fux-glow" x="-30%" y="-30%" width="160%" height="160%">
|
|
12
|
+
<feGaussianBlur in="SourceGraphic" stdDeviation="2.5" result="blur"/>
|
|
13
|
+
<feComposite in="SourceGraphic" in2="blur" operator="over"/>
|
|
14
|
+
</filter>
|
|
15
|
+
</defs>
|
|
16
|
+
<g filter="url(#fux-glow)">
|
|
17
|
+
<rect x="12" y="10" width="40" height="44" rx="10" fill="url(#fux-g)"/>
|
|
18
|
+
<g clip-path="url(#fux-c)">
|
|
19
|
+
<polygon points="12,10 32,10 12,30" fill="#fff" opacity=".15"/>
|
|
20
|
+
<polygon points="52,54 52,34 32,54" fill="#000" opacity=".17"/>
|
|
21
|
+
</g>
|
|
22
|
+
<path d="M26 10 L38 10 L38 33 L32 28 L26 33 Z" fill="#000" opacity=".26"/>
|
|
23
|
+
<rect x="19" y="42" width="26" height="3" rx="1.5" fill="#000" opacity=".24"/>
|
|
24
|
+
<rect x="19" y="48" width="17" height="3" rx="1.5" fill="#000" opacity=".24"/>
|
|
25
|
+
</g>
|
|
26
|
+
</svg>
|