forked from jason/echo
ver 1.5.0 — six-improvement pass: retention, routing, self-firing memory
1. capture-update keeps the whole body (was truncating to first line) 2. frontmatter completeness: kind-default status + kind-seeded tags at capture, fm create-or-replace, incomplete-frontmatter lint, sweep backfill (one data source: KIND_STATUS/KIND_REQUIRED_FM) 3. pre-write duplicate gate (exit 76, --merge-into/--force) 4. recall corpus + ranking: sessions/journal indexed (down-weighted), BM25 x freshness x status fusion, recall --json, index schema 2 5. session hooks: SessionStart auto-load, Stop reflection nudge 6. one-tap triage verb with processing-log audit; --json on read verbs +22 mock end-to-end tests; all suites green. Docs current (README, CHANGELOG, SKILL.md, commands, references, MAINTENANCE, eval README). Drops tracked .DS_Store (gitignored); retires README-gretchen.md (moved to gitignored dist/); adds the field report that drove item 2. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,71 @@
|
||||
# Changelog
|
||||
|
||||
## 1.5.0
|
||||
|
||||
Six improvements from the July 2026 review + the frontmatter-drift field report.
|
||||
|
||||
### Fixed — capture-on-update kept only the first body line (silent data loss)
|
||||
|
||||
`capture` on an existing entity appended `- <date>: <first line>` and **discarded the
|
||||
rest of the body**. It now appends the whole body as a dated block — first line on the
|
||||
bullet, continuation lines indented under it. Idempotency (bullet-per-day) unchanged.
|
||||
|
||||
### Added — frontmatter completeness (prevent → tool → detect → remediate)
|
||||
|
||||
A field audit found 18/71 entity notes missing `status`/`tags`; the drift was created
|
||||
at write time and invisible to the tooling. Four coordinated changes, driven by one
|
||||
data source (`KIND_STATUS` / `KIND_REQUIRED_FM` in `echo_index.py`):
|
||||
|
||||
- **`capture`** stamps a kind-appropriate default `status` (all kinds, not just
|
||||
projects) and seeds `tags` with the note's kind; new `--tags a,b` enriches it.
|
||||
Reflect/triage proposals accept a `"tags"` field.
|
||||
- **`echo.py fm`** is now **create-or-replace**: on `400 invalid-target` (missing key)
|
||||
it surgically inserts the one line into the frontmatter block and re-PUTs, verified —
|
||||
it previously failed on exactly the notes that needed repair.
|
||||
- **`vault_lint.py`** gains a kind-scoped `incomplete-frontmatter` check
|
||||
(missing/empty `status`/`tags` on entity notes; block-style lists handled).
|
||||
- **`sweep.py --apply`** backfills flagged notes (kind-default status + baseline tag).
|
||||
|
||||
### Added — pre-write duplicate gate in capture
|
||||
|
||||
A strong fuzzy candidate (score ≥ 0.6, env `ECHO_DUP_GATE`) now **stops** `capture`
|
||||
before it creates a near-duplicate (exit `76` + candidate list) instead of warning
|
||||
after the file exists. `--merge-into <slug>` routes the capture as an update to the
|
||||
existing entity (mention learned as an alias); `--force` creates anyway. Weak
|
||||
resemblances still create + warn as before.
|
||||
|
||||
### Changed — recall corpus + ranking (recall-index schema 2)
|
||||
|
||||
- The BM25 corpus now includes **session logs and journal notes** (down-weighted 0.5 /
|
||||
0.4 so entity notes win ties) — past discussions are findable without having been
|
||||
promoted into an entity note. `echo.py put` keeps the index current for corpus paths.
|
||||
- Ranking fuses BM25 with **freshness** (half-life decay on `updated:`, floored at 0.6,
|
||||
env `ECHO_FRESH_HALF_LIFE`) and **status** (`active` ×1.1, `on-hold` ×0.9,
|
||||
`archived` ×0.75) — a stale archived note no longer outranks the live one.
|
||||
- Hits print `updated:`/`status:`; `recall --json` emits structured results.
|
||||
- The recall index carries per-doc meta (schema 2); an old index is discarded and
|
||||
rebuilt automatically on the next recall/sweep.
|
||||
|
||||
### Added — session hooks (self-firing load & reflect)
|
||||
|
||||
New `hooks/hooks.json` + two hook scripts. **SessionStart** runs `echo.py load` and
|
||||
injects the output as context (skips resume/compact; NOT-CONFIGURED degrades to an
|
||||
instruction, never an error). **Stop** nudges once per substantive session (≥5 user
|
||||
turns, env `ECHO_REFLECT_MIN_TURNS`) when nothing was reflected or session-logged —
|
||||
reflection itself still previews and asks before writing. Both use the 1.4.2 CoWork
|
||||
path fallback and always exit 0.
|
||||
|
||||
### Added — one-tap inbox triage + `--json` on read verbs
|
||||
|
||||
New `echo.py triage`: `--list --json` parses the inbox into `{line, date, text,
|
||||
age_days}`; a proposals file (reflect schema + `"line"`) is classified → previewed →
|
||||
applied via `capture`, with the `inbox/processing-log/` audit line written per move
|
||||
(originals never deleted). `/echo-triage` rewritten around it. Also: `--json` for
|
||||
`recall`, `link`, and `scope show` (`resolve`/`capture` already had it).
|
||||
|
||||
Tests: +22 feature cases (mock end-to-end incl. hooks), patch-semantics updated for
|
||||
the new `fm` contract; all suites green. Docs: SKILL.md, README, command docs updated.
|
||||
|
||||
## 1.4.2
|
||||
|
||||
### Fixed — CoWork sandbox plugin-path resolution
|
||||
|
||||
Reference in New Issue
Block a user