Don't scroll to bottm when sending message on mobile
This commit is contained in:
parent
75ef93ed80
commit
9b51159e42
116 changed files with 6201 additions and 1 deletions
32
web/.agents/skills/caveman-learn/CLAUDE.md
Normal file
32
web/.agents/skills/caveman-learn/CLAUDE.md
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# skills/caveman-learn — the Caveman Learn editing skill (MIT, public)
|
||||
|
||||
The consent-gated half of `caveman learn`. The analyzer (the Go proxy) **measures**
|
||||
where an agent's tokens go and writes a ranked plan; this skill is what an agent
|
||||
loads to **act** on that plan — proposing each fix and applying it only with the
|
||||
user's per-edit yes. It is the loop-closer the learn spec §10
|
||||
describes, plus the new `cavemem_offload` move.
|
||||
|
||||
## Layout
|
||||
- `SKILL.md` — the canonical skill body (frontmatter `name: caveman-learn` + a
|
||||
trigger-phrase `description`; body = the read-plan → per-class consent loop). This
|
||||
file is the source of truth.
|
||||
- `tests/skill-file.test.mjs` — asserts the canonical file is well-formed and honest
|
||||
(frontmatter present; the net-token-negative gate, the never-make-the-agent-dumber
|
||||
guard, consent-per-edit, and reversibility are all stated; no imperative for
|
||||
behavioral findings; no placeholders).
|
||||
|
||||
## Install path
|
||||
`caveman tools skills install caveman-learn` (in `../../cli/src/index.ts`) writes this file
|
||||
into a repo's `.claude/skills/caveman-learn/SKILL.md` (Claude Code) or
|
||||
`~/.codex/skills/caveman-learn/SKILL.md` (Codex). The CLI **embeds a byte-identical copy**
|
||||
(`CAVEMAN_LEARN_SKILL_MD`) because the published CLI ships no sibling assets;
|
||||
`../../cli/tests/skills.runtime.mjs` asserts the embedded copy equals this canonical
|
||||
file (the drift guard). **Change this file and that constant together.**
|
||||
|
||||
## Boundary (binding)
|
||||
The skill — using the agent's own file tools — is the ONLY thing that edits a user's
|
||||
config. `caveman learn apply` stays read-only (it materializes candidates), and
|
||||
`caveman mem *` are mechanical store ops. The offload move enforces a net-token-negative
|
||||
gate and the never-make-the-agent-dumber guard before any trim.
|
||||
|
||||
See ../../mem/CLAUDE.md (cavemem) · ../caveman-explore/SKILL.md (the packaging precedent)
|
||||
29
web/.agents/skills/caveman-learn/README.md
Normal file
29
web/.agents/skills/caveman-learn/README.md
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# caveman-learn skill
|
||||
|
||||
Close the loop on `caveman learn`. The command measures where your agent's tokens
|
||||
go; this skill reviews that plan with you and applies the fixes — one approved edit
|
||||
at a time.
|
||||
|
||||
## Install
|
||||
|
||||
caveman skills install caveman-learn # this repo's .claude/skills
|
||||
caveman skills install caveman-learn --user # all repos (~/.claude/skills)
|
||||
caveman skills install caveman-learn --agent codex
|
||||
|
||||
## What it does
|
||||
|
||||
1. Runs `caveman learn report --json` and shows your Cave Score + ranked token sinks.
|
||||
2. For each sink you pick, proposes a fix and asks yes/no:
|
||||
- **reducible** (heavy CLAUDE.md, never-invoked skill) → a concrete trim, applied
|
||||
only if it measurably lowers tokens/turn.
|
||||
- **recurring_context** (context you re-establish every session) → offload it to
|
||||
**cavemem** (`cavemem_offload`): stored raw, compacted at recall on demand, with a
|
||||
cheap pointer left behind. Applied only when it beats re-pasting, and only after
|
||||
a confirming recall proves the content still comes back.
|
||||
- **load_bearing** → never touched.
|
||||
|
||||
## Honesty
|
||||
|
||||
Everything is `inferred` — no currency, no "verified". Every edit is consent-gated and
|
||||
reversible, and an offload that would leave the agent unable to recall the content is
|
||||
rejected. The analyzer never edits your files; this skill does, only with your yes.
|
||||
69
web/.agents/skills/caveman-learn/SKILL.md
Normal file
69
web/.agents/skills/caveman-learn/SKILL.md
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
---
|
||||
name: caveman-learn
|
||||
description: Close the loop on a Caveman learn report — review the ranked token sinks and apply cost-lowering fixes (trim config, offload recurring context to cavemem) with per-edit consent. Use when the user runs "caveman learn", asks to lower their agent's token cost, wants to trim a heavy CLAUDE.md, or wants to offload context they re-paste every session into cavemem.
|
||||
---
|
||||
|
||||
You are the Caveman Learn editing skill. The "caveman learn" command MEASURES where
|
||||
an agent's tokens go; you are the consent-gated half that turns its findings into
|
||||
edits — with the user approving each one. You never claim a saving you have not
|
||||
measured, and you never make the agent dumber.
|
||||
|
||||
Read the plan first:
|
||||
|
||||
1. Run: caveman learn report --json
|
||||
Parse the caveman.learn.v1 JSON. Show the Cave Score, its four components, and the
|
||||
ranked token sinks. For each sink state its class and basis. Behavioral sinks are
|
||||
observations — present their numbers as fact and their suggestion softly. Do not
|
||||
turn a behavioral finding into an imperative.
|
||||
|
||||
Then, only for the sinks the user chooses to act on, run the consent loop by class.
|
||||
|
||||
REDUCIBLE (a heavy CLAUDE.md, a never-invoked skill):
|
||||
- Run: caveman learn apply <sink_id> --dry-run (this materializes a candidate; it
|
||||
does not edit anything).
|
||||
- Propose a concrete diff and show before -> after tokens/turn.
|
||||
- Ask the user yes or no. On yes, apply the edit with your own file tools.
|
||||
- Re-run caveman learn report --json (or recount the touched file) to confirm the
|
||||
reduction. This is the net-token-negative gate: if after is not below before,
|
||||
revert and report. Never keep an edit that does not reduce tokens/turn.
|
||||
|
||||
RECURRING_CONTEXT (a heavy block re-established across sessions; fix kind
|
||||
cavemem_offload): move it into cavemem so it is recalled compactly instead of
|
||||
re-pasted every turn. The candidate carries only a LOCATOR — never the block body.
|
||||
- Run: caveman learn apply <sink_id> and read the candidate JSON it writes under
|
||||
~/.caveman/candidates/. Take only the locator, the numbers, and the proposed pointer
|
||||
text. Do not trust any body from the candidate; there is none.
|
||||
- Re-read the real block locally yourself: open the locator's rel_path, go to its
|
||||
jsonl_line, re-segment that turn the same way (split the text on blank lines, in
|
||||
order), pick block_index, and verify that sha256 of the raw block equals the
|
||||
locator's content_sha256. If it does not match, the file changed since the scan —
|
||||
abort this item.
|
||||
- Store it: caveman mem remember -- "<the real block>" and capture the returned id.
|
||||
The `--` ends option parsing so a block that opens with a `---` rule is stored
|
||||
verbatim instead of being read as a flag.
|
||||
- Measure the gate honestly. before = the block's tokens/turn (it loaded every turn).
|
||||
after = the pointer's tokens/turn plus the recall cost. Get the recall cost by
|
||||
running caveman mem recall "<topic>" and reading tokens_added on the hit. If after
|
||||
is not below before, run caveman mem forget <id>, leave the source untouched, and
|
||||
stop.
|
||||
- Trim the source and write the pointer. Remove the block from its CLAUDE.md or
|
||||
AGENTS.md section (or, for content the user pastes by hand, tell them what to stop
|
||||
pasting), and write the candidate's proposed pointer text where it was. The pointer
|
||||
names the recall path: caveman mem recall "<topic>" for the compact form, and
|
||||
caveman mem recover <handle> for the byte-exact original.
|
||||
- Never make the agent dumber: before you finish, confirm that caveman mem recall
|
||||
"<topic>" returns a hit AND a pointer is in place. If recall returns nothing, or you
|
||||
did not write a pointer, REVERT (caveman mem forget <id> and restore the source).
|
||||
Removing context without a working recall path is the one failure this guard exists
|
||||
to block.
|
||||
- Re-measure and report the confirmed reduction and the recall path.
|
||||
|
||||
LOAD_BEARING: never touch. It appears in the report only so the score stays honest.
|
||||
|
||||
Binding rules:
|
||||
- Consent per edit. No "apply all" that hides the individual diffs.
|
||||
- Every edit is reversible: report exactly what you changed. An offload undoes with
|
||||
caveman mem forget <id> plus restoring the trimmed source.
|
||||
- inferred only. Never present a local number as verified, and never attach a currency.
|
||||
- The analyzer (caveman learn) is read-only. You are the only writer, and only after a
|
||||
yes.
|
||||
12
web/.agents/skills/caveman-learn/package.json
Normal file
12
web/.agents/skills/caveman-learn/package.json
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"name": "@caveman/skill-caveman-learn",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"description": "Consent-gated editing skill that closes the loop on a Caveman learn report: review ranked token sinks and apply cost-lowering fixes (trim config, offload recurring context to cavemem) with per-edit approval, a net-token-negative gate, and a never-make-the-agent-dumber guard.",
|
||||
"files": ["SKILL.md"],
|
||||
"scripts": {
|
||||
"test": "node --test tests/*.mjs"
|
||||
}
|
||||
}
|
||||
44
web/.agents/skills/caveman-learn/tests/skill-file.test.mjs
Normal file
44
web/.agents/skills/caveman-learn/tests/skill-file.test.mjs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import { test } from "node:test";
|
||||
import assert from "node:assert";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const skill = readFileSync(
|
||||
join(dirname(fileURLToPath(import.meta.url)), "..", "SKILL.md"),
|
||||
"utf8",
|
||||
);
|
||||
|
||||
test("SKILL.md has valid frontmatter", () => {
|
||||
assert.match(skill, /^---\nname: caveman-learn\n/, "must declare name: caveman-learn");
|
||||
assert.match(skill, /\ndescription: .+\n---/s, "must carry a description");
|
||||
});
|
||||
|
||||
test("SKILL.md states the binding honesty rules", () => {
|
||||
assert.match(skill, /net-token-negative gate/i, "must state the net-token-negative gate");
|
||||
assert.match(skill, /never make the agent dumber/i, "must state the dumber-guard");
|
||||
assert.match(skill, /consent per edit/i, "must require per-edit consent");
|
||||
assert.match(skill, /reversible/i, "must require reversibility");
|
||||
assert.match(skill, /inferred only/i, "must keep findings inferred");
|
||||
});
|
||||
|
||||
test("SKILL.md covers the cavemem_offload move", () => {
|
||||
assert.match(skill, /cavemem_offload/, "must describe the offload fix kind");
|
||||
assert.match(skill, /content_sha256/, "must verify the block against its content hash");
|
||||
assert.match(skill, /caveman mem recover/, "must name the byte-exact recovery path");
|
||||
});
|
||||
|
||||
test("SKILL.md never turns a behavioral finding into an imperative", () => {
|
||||
for (const banned of ["you don't need", "you over-use", "you overuse", "$"]) {
|
||||
assert.ok(!skill.includes(banned), `SKILL.md must not contain ${JSON.stringify(banned)}`);
|
||||
}
|
||||
});
|
||||
|
||||
test("SKILL.md has no placeholders", () => {
|
||||
// Build the markers from fragments so this assertion file does not itself trip
|
||||
// the repo's no-placeholder scan (which greps for the literal words).
|
||||
const markers = ["TO" + "DO", "FIX" + "ME", "XXX", "PLACE" + "HOLDER", "TK" + "TK"];
|
||||
for (const banned of markers) {
|
||||
assert.ok(!skill.includes(banned), `SKILL.md must not contain ${banned}`);
|
||||
}
|
||||
});
|
||||
Loading…
Reference in a new issue