Self-healing autopoietic shell: f(), tests, docs, interactive demo, fx fix-source layer
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
# fx — automated, selectable fix sources for f()
|
||||
|
||||
`fx` automates the `[LEARN] ... Enter a fix:` prompt in `f()` by gathering
|
||||
candidate fixes from a directory of small, pluggable scripts and letting
|
||||
you pick one (or auto-picking) before it's piped into `f`'s stdin.
|
||||
|
||||
**Zero changes to `../../src/f.sh`.** `f()`'s `read -r n` already doesn't
|
||||
care whether that line comes from a human or a program — `fx` just
|
||||
decides what to type there.
|
||||
|
||||
## Usage
|
||||
|
||||
```sh
|
||||
. ../../src/f.sh
|
||||
. fx.sh
|
||||
fx some-command --that --might --fail
|
||||
```
|
||||
|
||||
Set `FX_AUTO=1` to skip the picker and take the top-ranked candidate
|
||||
automatically. Without it, `fx` uses `fzf` if installed, or a plain
|
||||
numbered prompt otherwise.
|
||||
|
||||
## Default sources (`sources.d/`, run in filename order)
|
||||
|
||||
| File | What it offers |
|
||||
|---|---|
|
||||
| `10-known.sh` | Fixes already taught for a command that *starts* the same way, since `f()`'s own lookup only matches the exact string. |
|
||||
| `20-history.sh` | The closest-looking command you've actually run before, read from `$HISTFILE`. |
|
||||
| `30-selfdiag.sh` | Re-runs the command once, and if the tool's own error output suggests a corrected invocation (git's `--set-upstream` hint, etc.), emits a **function that re-derives the suggestion live on every future call** — not a frozen snapshot. This distinction matters: an earlier version of this source cached the literal suggested line and it silently broke on the second branch it saw (`git ls-remote` showed the second branch never got pushed). Re-diagnosing on every call is what makes one taught fix generalize correctly. |
|
||||
| `40-pathfuzzy.sh` | If the first word isn't a real command, offers a **function** (not an alias — aliases don't expand in non-interactive shells without `shopt -s expand_aliases`) wrapping the closest-spelled real command, using transposition-aware edit distance so `gti` scores closer to `git` than to unrelated same-length commands like `ftp`. |
|
||||
| `50-thefuck.sh` | Bridges to `thefuck --yes`, if installed, as one more opinion. Note `--yes` executes its own suggestion, so this candidate is often already-applied by the time you see it. |
|
||||
| `90-team-shared.sh` | Off by default (no-ops unless `FX_TEAM_URL` is set) — see below, this one *is* the extension example. |
|
||||
|
||||
## Adding a custom source
|
||||
|
||||
Drop a new executable file into `sources.d/`. Nothing else to register.
|
||||
|
||||
Contract:
|
||||
- invoked as `sourcefile "$CMD"` where `$CMD` is the whole failing command line
|
||||
- may read `$FX_OUTPUT` — captured stdout+stderr of one real attempt (empty if `FX_NO_PROBE` is set)
|
||||
- prints zero or more candidate fix lines to stdout, one per line
|
||||
- non-zero exit or no output = "no opinion," silently skipped
|
||||
- filename prefix (`NN-name`) sets consideration/display order — lower runs first
|
||||
|
||||
`90-team-shared.sh` is a real, working example of this contract: it pulls
|
||||
a shared `p`-format corrections file from `$FX_TEAM_URL` and offers
|
||||
exact-key matches. It's a template, not a dependency — treat a URL you
|
||||
point it at the same way you'd treat an rc file you `source`: a match
|
||||
becomes `eval`'d code the moment you select it.
|
||||
|
||||
## Known cost
|
||||
|
||||
`fx` runs the command once itself before consulting sources (so
|
||||
`30-selfdiag.sh` has real output to read). That's one extra execution
|
||||
beyond what plain `f()` does. Set `FX_NO_PROBE=1` to skip it for
|
||||
commands with side effects you don't want repeated — the output-aware
|
||||
source just has no opinion in that case, and the others still work.
|
||||
Reference in New Issue
Block a user