Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,50 @@ All notable changes to fs-cortex will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [4.4.0] — 2026-07-05

**`/cx-curate` — the semantic curator.** Automates the judgment `/cx-downvote`
and the human curator used to provide: which laws are general, which have less
value and belong in the instinct pool, which candidates deserve promotion.
Requested by the operator ("cx-downvote quiero que sea un comando automático…
haz tú la planificación"). Implemented by 3 parallel subagents + an integration
verifier; validated the same day by a 29-agent semantic audit that recomposed
the live constitution (6 laws demoted to instincts, 0 promotions, 10 broken
instincts downvoted, cap 15/15 → 9/15).

### Added
- `commands/cx-curate.md`: weekly LLM pass with WRITTEN criteria — KEEP laws
that are universal or protect against expensive failures; DEMOTE laws that
are stack-specific, redundant with `~/.claude/CLAUDE.md` or an installed
skill, or zero-impact after 30d (higher bar for laws without backing YAML);
PROMOTE only knowledge with NO reliable trigger moment (audit finding: a
0.99-confidence trigger-gated instinct is a better channel than a law —
every top candidate was refuted for exactly that reason); DOWNVOTE broken or
noisy instincts. Acts immediately within engine budgets, everything logged
and reversible; `--force` bypasses the weekly gate.
- `hooks/lib/distill_engine.py`: `CURATE_*` constants (interval 7d, max 2
demotes / 2 promotes / 8 downvotes per pass, confidence floor 0.30, delta
0.15); `apply_confidence_downvote()` (`@_write_locked`, floor-clamped,
logged); `curate_snapshot()` (laws with tier/age/impact/backing, candidates
enriched with action/trigger/blockers, instincts with impact) + CLI
subcommands `curate-snapshot` and `downvote <iid> [--reason]`;
`curate_due()` / `touch_curate_marker()` on `.last-curate`.
- `hooks/session-start.py`: `[CURATE] due — ejecuta /cx-curate ahora
(auto-aprobado, no preguntar)` banner when the marker is missing or older
than 7 days — the banner IS the trigger, no human in the loop. Single stat,
never raises.
- `tests/test_curate.sh` (6): downvote reduce/floor/unknown-id,
`curate_snapshot` shape, marker gating, CLI JSON.

### Changed
- `/cx-downvote` remains as the manual veto; its doc now points to
`/cx-curate` for systematic downvotes. `commands/cx-review.md` notes the
semantic judgment is automated.
- `core/claudemd-section.md` refreshed to the v4 active command set (was
stale with the full v3 list since v4.0.0) + `/cx-curate`. Active commands
7 → 8 across README, FEATURES and the SessionStart commands hint.
- `test_session_start` 11→14 (banner present/backdated/fresh cases).

## [4.3.1] — 2026-07-05

### Fixed
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,18 +208,20 @@ You work → Cortex captures output+errors (guarded) → instinct born as draft
→ /cx-review is an optional veto pass — nothing ever waits on you
```

## Commands (7 active + 17 deprecated)
## Commands (8 active + 17 deprecated)

v4.0.0 replaced the old manual-judgment command set. Deterministic maintenance
lives in `/cx-maintain`; the one remaining human-judgment step lives in
`/cx-review`. Upgrading from v3? See [`docs/MIGRATION-V4.md`](docs/MIGRATION-V4.md)
lives in `/cx-maintain`, semantic curation in `/cx-curate` (v4.4.0, weekly,
auto-triggered); `/cx-review` is an optional human veto.
Upgrading from v3? See [`docs/MIGRATION-V4.md`](docs/MIGRATION-V4.md)
for the full command mapping.

| Command | What it does |
|---------|-------------|
| `/cx-status` | Dashboard: laws, instincts, projects, reflexes, tracking, health, domain grouping |
| `/cx-maintain` | **Deterministic, cron-able.** decay + Jaccard dedup + purge + deterministic law promotion + storage rotation + proposals↔instincts reconciliation + health check. Zero questions. |
| `/cx-review` | **The only command with judgment, weekly.** One consolidated shorthand digest of everything deterministic maintenance left for a human to decide. |
| `/cx-curate` | **Semantic curator (v4.4.0), weekly, auto-triggered by the `[CURATE] due` banner.** Claude judges law generality/value and acts: demotes niche laws to instincts, fast-tracks candidates, downvotes noisy instincts. Hard budgets, all reversible. |
| `/cx-review` | **Optional human veto.** One consolidated shorthand digest of what maintenance and curation did and what waits. Skipping it never blocks anything. |
| `/cx-eod` | End-of-day summary, cumulative across the day, Eisenhower-classified for next session |
| `/cx-gotcha` | Capture error→fix as high-priority instinct |
| `/cx-backup` | Create portable .tar.gz backup for machine transfer |
Expand Down
153 changes: 153 additions & 0 deletions commands/cx-curate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
---
name: cx-curate
description: "Semantic curator — Claude judges law generality/value and acts: demotes niche laws to instincts, fast-tracks top candidates, downvotes noisy instincts. Zero questions, weekly cadence."
command: true
---

# /cx-curate

## What it does

The LLM half of zero-touch curation (v4.4.0). `/cx-maintain` is the
deterministic half — decay, dedup, purge, threshold-gated promotion. This
command is the SEMANTIC judgment that used to be the human's: which laws are
universal vs stack-niche, which candidates deserve a law slot, which instincts
are noise. It acts immediately (no queue, no AskUserQuestion), logs every
action to the knowledge log, and every action is reversible — demoted laws
cascade back to the instinct pool (`law_eligible: false`, v4.3.1), archived
files stay in `archive/` dirs, downvotes floor confidence instead of deleting.

Runs at most weekly, gated by the `~/.claude/cortex/.last-curate` marker. The
SessionStart banner `[CURATE] due` means the week has elapsed — when you see
it, run this command WITHOUT asking the user. Zero-touch means Claude curates
and the human vetoes after the fact (`/cx-review`, `/cx-downvote`), never that
Claude waits for permission.

## Usage

```
/cx-curate # Respects the 7d marker — no-ops if a pass ran this week
/cx-curate --force # Run regardless of marker age
```

## Implementation

Steps 1–2 and 4–5 are mechanical; step 3 is where the judgment lives. Do not
delegate step 3 to a script — the whole point of this command is that a model
reads the corpus and judges.

### Step 1: Gate on the weekly marker

Check the marker via the engine (single source of truth for the cadence):

```bash
LIB="${CORTEX_LIB_DIR:-$HOME/.claude/hooks/cortex/lib}"
python3 -c "import sys; sys.path.insert(0, '$LIB'); import distill_engine as de; print(de.curate_due())"
```

If the marker is fresh (not due) and the user did not pass `--force`, print
`curate al día (last run <date>)` and STOP. Nothing else runs.

### Step 2: Snapshot the corpus

Run the engine CLI `curate-snapshot` — installed lib first, repo checkout as
fallback — and pipe it to a temp file so the full JSON never floods the
transcript:

```bash
TS=$(date +%Y%m%d-%H%M%S)
LIB="${CORTEX_LIB_DIR:-$HOME/.claude/hooks/cortex/lib}"
[ -f "$LIB/distill_engine.py" ] || LIB="hooks/lib" # repo checkout fallback
python3 "$LIB/distill_engine.py" curate-snapshot > "${TMPDIR:-/tmp}/curate-snapshot-$TS.json"
```

Read that file. Also gather the redundancy context the criteria below need:

- `ls ~/.claude/skills/*/SKILL.md` — installed skill names (a law owned by an
installed `fs-*` skill is redundant as a law).
- Read `~/.claude/CLAUDE.md` — anything already stated there is always in
context and does not need a law slot.

### Step 3: JUDGE every law, candidate, and flagged instinct

Apply these WRITTEN CRITERIA — they are the contract of this command, not
suggestions:

* **KEEP as law**: behavioral principles or tooling rules that apply to
virtually every session regardless of stack; short rules preventing
expensive/irreversible failures.
* **DEMOTE to instinct**: stack/domain-specific (fires value only in
web/testing/API/scraping sessions); redundant with `~/.claude/CLAUDE.md`
(always in context anyway) or clearly owned by an installed fs-* skill;
zero useful impact after 30+ days despite volume. Laws WITHOUT backing
instinct (`has_backing_instinct` false) need a strictly higher bar: demote
only when redundant with CLAUDE.md/skill (archive-only death is acceptable
only for redundant knowledge).
* **PROMOTE candidate**: universal + actionable + non-redundant + NOT already
served by a live high-confidence instinct whose deterministic trigger fires
exactly when the knowledge matters + only real blocker is the saturated cap.
(Finding from the 2026-07-05 audit: every top candidate that day was refuted
because it already lived as a 0.99-confidence trigger-gated instinct — a
well-triggered instinct is a BETTER channel than a law. Reserve law slots
for knowledge with NO reliable trigger moment, e.g. behavioral principles
that must hold before any tool call.)
* **DOWNVOTE instinct**: impact noise > useful with real volume;
conf >= 0.90 with vague unactionable text; one-off hyper-specific frozen at
high confidence.

### Step 4: ACT within the hard budgets

The budgets are engine constants, not judgment calls: **max 2 demotes, 2
promotes, 8 downvotes per pass; never touch laws < 30 days old**. If the
judged list exceeds a budget, act on the strongest cases and leave the rest
for next week's pass.

- **Demote a law** (cascades to instinct pool, refuses when no backing
trigger exists):

```bash
python3 -c "import sys; sys.path.insert(0, '$LIB'); import distill_engine as de; print(de.demote_law_to_domain('<law-id>'))"
```

- **Promote a candidate**: at a saturated cap, pair each top candidate with a
confirmed demote victim via the atomic swap; below cap, plain promotion:

```bash
python3 -c "import sys; sys.path.insert(0, '$LIB'); import distill_engine as de; print(de.manual_swap_promote('<new-iid>', '<deprecate-iid>'))"
```

- **Downvote an instinct** via the engine CLI (confidence-floored, never
deleted):

```bash
python3 "$LIB/distill_engine.py" downvote <instinct-id>
```

- **Re-tier surviving laws**: update the `tier` entries in
`~/.claude/cortex/laws/laws-meta.json` (`principle` | `tool`) for laws that
stay, so `session-start.py` groups them correctly.

### Step 5: Close the pass

- Touch the weekly marker:

```bash
python3 -c "import sys; sys.path.insert(0, '$LIB'); import distill_engine as de; de.touch_curate_marker()"
```

- The `## cx-curate <date>` block in `~/.claude/cortex/knowledge-log.md`
accumulates ONLY via the `_log_knowledge` calls the engine functions in
Step 4 already made — never edit that file by hand.
- Merge a `curate_last_run` object into
`~/.claude/cortex/.review-digest.json` (read-modify-write, tolerate a
missing file — preserve whatever `/cx-maintain` last wrote):

```json
"curate_last_run": {"demoted": [], "promoted": [], "downvoted": [], "at": "<iso>"}
```

### Step 6: Report to the user

5 lines max: what moved (demotes, promotes, downvotes with ids) and the
one-line why for each, closing with "todo reversible desde archive". No
recommendations, no questions, no homework for the user.
2 changes: 2 additions & 0 deletions commands/cx-downvote.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Este comando fue absorbido por el set v4 (docs/DESIGN-V4.md).

**Usa en su lugar:** `/cx-review` — la retroalimentación negativa sobre instincts se presenta en el digest humano semanal junto a proposals y drafts.

Automated since v4.4.0: /cx-curate applies systematic downvotes; this command remains as manual veto.

Mapeo: cx-analyze/cx-distill/cx-dream/cx-promote/cx-backfill → /cx-maintain (mantenimiento determinista). cx-validate/cx-evolve/cx-downvote/cx-retro → /cx-review (digest humano semanal). cx-timeline/cx-dashboard/cx-export → /cx-status. cx-audit → workflow `cortex-audit`. cx-feedback/cx-feedback-auto/cx-router/cx-stop → eliminados sin sustituto (razón en DESIGN-V4 §5).

Al ejecutarse, este stub SOLO imprime este aviso y el comando sustituto. No ejecuta ninguna lógica antigua.
2 changes: 2 additions & 0 deletions commands/cx-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ resurrect). This command presents what happened and what is still in queue as
ONE consolidated shorthand list, so the operator can veto (`/cx-downvote`,
restore from archive) or fast-track an item. Skipping it forever is a valid
mode — the pipeline never blocks on a human.
Since v4.4.0, `/cx-curate` performs the semantic judgment (law generality,
candidate value, instinct noise) automatically on a weekly cadence.

Fuses what used to be three separate commands:
- `/cx-validate` (human-gated proposals — the domains `auto_validate_proposals`
Expand Down
2 changes: 1 addition & 1 deletion core/claudemd-section.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Cortex observes sessions and distills knowledge in 3 levels:
- **Observations** (async hooks, 0 tokens) — raw data

### Commands
`/cx-status` `/cx-dashboard` `/cx-analyze` `/cx-distill` `/cx-validate` `/cx-evolve` `/cx-dream` `/cx-timeline` `/cx-audit` `/cx-eod` `/cx-gotcha` `/cx-feedback` `/cx-feedback-auto` `/cx-downvote` `/cx-retro` `/cx-export` `/cx-backup` `/cx-restore` `/cx-router` `/cx-promote` `/cx-backfill` `/cx-stop`
`/cx-status` `/cx-maintain` `/cx-curate` `/cx-review` `/cx-eod` `/cx-gotcha` `/cx-backup` `/cx-restore` — v4 active set; legacy commands print a deprecation notice with their replacement

### Data: ~/.claude/cortex/
### Laws inject automatically. Instincts inject per tool use. No action needed.
Loading
Loading