From rocket
Update the project's semantic lexicon at .roc/rocket/lexicon.md from the current conversation. Use this skill whenever the user invokes "/rocket:context-update", asks to "update context", "refresh lexicon", "update the lexicon", "rebuild project vocabulary", "mets a jour le contexte", "mets a jour le lexique", "rafraichis le lexique", or any similar request. Auto-invoke when a major semantic shift just happened in the conversation (new domain concept, new architectural decision, redefinition of an existing term) and the lexicon should capture it before the next turn.
How this skill is triggered — by the user, by Claude, or both
Slash command
/rocket:context-updategeneral-purposeThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Maintain the project's semantic lexicon at `.roc/rocket/lexicon.md`: a compact, structured catalog of project-specific concepts, vocabulary, recurring patterns, roles, and decisions. The lexicon is read by `rocket:spec-writer`, `rocket:spec-maker`, and other agents to align their vocabulary with the user's. This skill is the only writer.
Maintain the project's semantic lexicon at .roc/rocket/lexicon.md: a compact, structured catalog of project-specific concepts, vocabulary, recurring patterns, roles, and decisions. The lexicon is read by rocket:spec-writer, rocket:spec-maker, and other agents to align their vocabulary with the user's. This skill is the only writer.
The skill runs in three modes:
Stop hook through the wrapper script plugins/rocket/hooks/update-context.sh. The wrapper runs a multi-stage pipeline (heuristic pre-filter, Haiku gate) before spawning a Sonnet subprocess with a scoped prompt containing only pre-validated candidate concepts. The summary is logged but not surfaced to the user.context-gate binary is not available, the wrapper falls back to the v1 behavior: tail 500 lines of the transcript and pipe to Sonnet directly. This ensures zero regression on platforms without the binary./rocket:context-update or auto-invoked by Claude on a semantic shift. The forked context provides the full conversation; the summary is surfaced to the user. Manual mode bypasses the toggle, heuristic, and Haiku gate entirely..roc/rocket/lexicon.md (and only that file) atomically via .roc/rocket/lexicon.md.tmp + mv, protected by an mkdir-based atomic lock at .roc/rocket/lexicon.md.lock.d/ (POSIX-portable; flock is not available by default on macOS).<!-- Auto-maintained by rocket:context-update. Edits are preserved when consistent. -->
## <Area name>
### <Concept>
- **Definition**: <one-line definition>
- **Aliases**: <comma-separated synonyms, or "none">
- **Relations**: <comma-separated concept names, or "none">
- **Source**: <free-form citation>
### <Concept>
[...]
## <Other area>
[...]
Rules enforced on every write:
Relations resolves to an existing concept name in the file.Areas are project-defined groupings (e.g. Domain, Architecture, Roles, Conventions, Decisions). Create them on first need; merge them when their meaning overlaps.
When invoked with a Candidates: block in the prompt (the Sonnet writer path from the hook pipeline), the skill operates in scoped mode:
The scoped prompt format (generated by context-gate format-writer-prompt) is:
/rocket:context-update
Integrate these candidate concepts into the project lexicon at
`.roc/rocket/lexicon.md`. The candidates were identified by a pre-classifier
from the latest conversation turn.
Candidates: <comma-separated candidate names>
Existing lexicon:
<full lexicon content>
Project conventions (from CLAUDE.md):
<CLAUDE.md content>
Run the context-update workflow (Steps 2-7) for these candidates only.
Do not re-analyze the full conversation -- the candidates are pre-validated.
When this format is detected, enter scoped mode automatically.
.roc/rocket/lexicon.md. If absent, treat the existing lexicon as empty.CLAUDE.md (root only) for tone and language conventions to match.Identify nouns and noun phrases that name:
Discard generic technical vocabulary (HTTP, SQL, REST, "webhook" in the abstract). Keep them only when the project gives them a specific local meaning.
For each candidate, compare against existing entries by semantic match, not string match:
Aliases.If a candidate contradicts an existing definition (different meaning under the same concept name, or incompatible relations):
<!-- TODO: contradiction with <description> --> to the affected entry's Definition line.After merging, render the lexicon and measure its size.
If the rendered file exceeds 300 lines OR 12 KB (whichever smaller):
Source recency (oldest first; "inferred" counts as oldest).Relations.<!-- TODO: contradiction ... --> comment.If the budget cannot be met without dropping flagged entries, stop pruning and emit a warning in the summary.
Definition / Aliases / Relations / Source.$CLAUDE_PROJECT_DIR if set, otherwise the cwd).mkdir .roc/rocket/lexicon.md.lock.d/. If the directory already exists (lock held), abort with the summary Lexicon update already in progress. rather than waiting — this matches the wrapper's skip-on-contention behaviour. Release the lock by rmdir at every successful return path..roc/rocket/lexicon.md.tmp.mv .roc/rocket/lexicon.md.tmp .roc/rocket/lexicon.md (atomic on POSIX filesystems).If the rendered content equals the previous content byte-for-byte, skip the write (idempotent no-op).
Emit a single short paragraph:
Lexicon updated: <N> added, <M> merged, <K> flagged. Flagged: <comma-separated names or "none">.
If nothing changed: No update needed.
In hook mode, the wrapper captures this summary via stderr; do not add formatting that would garble the log. In manual mode, surface the summary directly to the user.
mkdir lock on .roc/rocket/lexicon.md.lock.d/ is mandatory. Two simultaneous fires must serialize.<!-- TODO: invariant ... --> comment instead of rewriting it..roc/rocket/ directory missing: create it before writing (mkdir -p .roc/rocket/)..roc/rocket/lexicon.md and the temp/lock siblings.Lexicon updated: 2 added, 1 merged, 0 flagged. Flagged: none.
Lexicon updated: 0 added, 3 merged, 1 flagged. Flagged: Outbound webhook.
No update needed.
Hi! I added two new entries to the lexicon. The first one is about webhooks...
(Too verbose, friendly tone, restates content already in the file.)
plugins/rocket/hooks/update-context.sh orchestrates a pipeline: recursion guard, project toggle check (Background context: enabled in CLAUDE.md), debounce (300s), heuristic pre-filter (context-gate should-fire), Haiku gate classifier, then a scoped Sonnet writer. Each stage can exit early, reducing background cost by ~95% compared to v1.context-gate binary: a compiled Python binary at plugins/rocket/bin/context-gate with 7 subcommands (extract-delta, should-fire, format-gate-prompt, parse-gate-response, format-writer-prompt, update-cursor, read-cursor). Source at plugins/rocket/build/src/context_gate.py, built via plugins/rocket/build/build.sh (PyInstaller --onefile)..roc/rocket/context-gate-state.json. Each fire processes only lines added since the last fire instead of re-tailing the last 500 lines. If the cursor exceeds the transcript length (rotation/truncation), extract-delta falls back to the last 500 lines.CLAUDE.md for - Background context: enabled. If the line is absent or says disabled, the hook exits immediately (zero cost). Manual /rocket:context-update is unaffected by the toggle.context-gate binary is not found, the wrapper falls back to v1 behavior (30s debounce, tail 500 lines, pipe to Sonnet). A log warning is emitted.transcript_path field).ROCKET_CONTEXT_UPDATE_INVOKED=1 before spawning the claude -p subprocess to prevent recursion.async hook; propagating the subprocess status would risk emitting exit code 2 (the Stop-hook block signal) into the user's main session.mkdir .roc/rocket/lexicon.md.lock.d/. Concurrent fires skip rather than queue.Run these scenarios after any change to this skill, the wrapper, or the hook config. There is no automated test suite.
.roc/rocket/ directory. Run /rocket:setup. Expected: .roc/rocket/lexicon.md created with the canonical header line, ## Project semantic context block inserted in CLAUDE.md..roc/rocket/lexicon-update.log records start + end, lexicon receives a new entry, exit status 0.No update needed.; lexicon mtime unchanged; next turn fires again without infinite loop (the ROCKET_CONTEXT_UPDATE_INVOKED sentinel prevents recursion regardless of mtime).skip: debounced (...) and exits 0./rocket:context-update invocations simultaneously (or trigger one manually while a hook fire is in progress). Expected: one acquires the lock, the other logs skip: lock held by another invocation (wrapper) or emits Lexicon update already in progress. (skill).claude CLI missing — temporarily remove claude from PATH. Expected: hook exits silently, no log entry, no error surfaced to the user..roc/rocket/lexicon.md by hand to add a malformed entry (e.g. missing Aliases bullet). Run /rocket:context-update. Expected: skill flags the entry with <!-- TODO: invariant ... --> rather than rewriting it; existing valid entries untouched./rocket:context-update twice in a row on an unchanged conversation. Expected: second invocation outputs No update needed. and does not rewrite the file.start: lines without an intervening end:; never an exponential growth of log lines from a single user turn.Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub digivorefr/roc --plugin rocket