Installs into .claude/skills of the current project.
Are you the author of Thrum Update Project?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/thrum-team-thrum-update-project)
---
name: thrum-update-project
description: Update project state with session summary and mechanical state
# source: claude-plugin/commands/update-project.md
---
# Thrum Update Project
Use this skill when the user explicitly wants the `update-project` Thrum
workflow. Prefer the umbrella `thrum` skill when the request spans multiple
commands or needs broader coordination judgment.
Update `.thrum/context/project_state.md` with fresh project state so a new
session can pick up exactly where this one left off.
**Do this IN YOUR OWN CONTEXT. Do NOT delegate it to a subagent.**
This is a named exception to the general dispatch discipline in your role
preamble ("delegate essentially all investigation to sub-agents to preserve your
context"). That rule is correct and stays — it protects your context from
repetitive investigation a subagent can do just as well. update-project is
different in kind: it is not investigation, it is the **serialisation of context
that exists only in your own head**. A subagent works from a brief you hand it
and can only render what the brief contains. What gets lost is exactly what
makes the artifact worth having — the rulings and their reasoning, the
corrections and _why_, which claims were VERIFIED versus merely assumed, and
which of this session's confident statements turned out WRONG. If you could
summarize those faithfully into a brief, you would already have written the
state yourself. Two more reasons this delegation is pure downside here
specifically: (1) you are already live with the session loaded — a subagent
re-processes context you already hold, at extra cost, from a summary instead of
the full session; (2) update-project runs only at session end, immediately
before a restart — there is no "later work" this session to protect, so the
usual token-saving justification for delegating does not apply.
### Step 0: Owner and Tier Check
1. If you are not the coordinator responsible for this repo's project state,
stop. Only that coordinator runs this command.
2. Detect the tier:
```bash
thrum license status
```
3. Take the **licensed path** (see Licensed Path below) only when all three
hold: the output has a line `license: active` exactly; it has a line starting
` tier:` whose value is `paid`, `comp`, `trial` or `enterprise`; and it has
no `DEVICE DEACTIVATED` line. Any other output, or a non-zero exit, prints
`license state unknown; using the free path` and takes the **free path**
(Steps 1–6). The free path skips the memory step; the index line in
`project_state.md`'s Recent Sessions is the only session record.
### Step 1: Compose Your Session Summary
From YOUR context (what you already know), write a brief summary covering:
- **Session number**: Increment from the current project_state.md's session
number (check `Phase` line or latest session heading)
- **What you worked on**: Key tasks, epics, beads progressed or closed
- **What changed**: Files modified, features shipped, bugs fixed
- **Key decisions**: Architecture choices, approach changes, investigations done
- **Current state**: What's in progress, what's blocked, what's next
This is the most valuable input — only you have the session narrative. Keep it
concise but complete (10-30 lines). You gather the mechanical state yourself in
the next step.
### Step 2: Gather Mechanical State Yourself
Run this ONE compound command directly in your own turn — do not dispatch it to
a subagent:
```bash
cd REPO_ROOT && \
echo "=== GIT LOG ===" && git --no-pager log --oneline -15 && \
echo "=== GIT STATUS ===" && git branch --show-current && git status --short && \
echo "=== BEADS STATS ===" && bd stats 2>&1 && \
echo "=== OPEN EPICS ===" && (bd list --status=open --type=epic 2>/dev/null || echo "(none)") && \
echo "=== READY ISSUES ===" && (bd ready -n 5 2>/dev/null || echo "(none)")
```
(Replace `REPO_ROOT` with the absolute path to the project root.)
### Licensed Path (after Step 2; replaces Steps 3–5, then Step 6)
Live facts move to `thrum state`, work to `thrum queue`, and session history to
`thrum memory`.
1. **Live facts.** For each changed fact in Current State Summary, read its
kind, then set it. Kinds: `deploy_state`, `topology`, `worktree`,
`agent_pool`, `ruling`.
```bash
thrum state list --kind <kind>
thrum state set --kind <kind> --scope <scope> --value '<json>'
```
2. **Work.** Reconcile your queue. Add each in-flight, blocked or pending item,
then set its status. Drop only done bundles you do not keep for this session.
```bash
thrum queue list
thrum queue add --title "<title>" --ref bead:<id>
thrum queue start <bundle-id> # or: thrum queue block <bundle-id>, thrum queue done <bundle-id>
thrum queue drop <bundle-id>
```
3. **Session history.** Once, for the session being closed:
```bash
thrum memory record-session --session-number <N> --title "Session <N> — <title>" --oneline "<headline>" --short "<2-4 sentences>" --full "<session body>"
```
4. **Pointer file.** Read `project_state.md`, then edit it to the source table,
Phase, Durable rules and Stable references. Keep `## Recent Sessions`. Remove
the live content of Current State Summary, Architecture Health and open-epic
lists.
5. **Verify.** Record `wc -l` and `wc -w` before and after, and confirm the
`thrum state`, `thrum queue` and record-session writes are visible.
### Step 3: Read the Current File
Read `REPO_ROOT/.thrum/context/project_state.md` in full, yourself, using the
Read tool.
### Step 3.5: Staleness Check First (Parallel Fan-Out)
Before you edit anything, verify what's actually still true. Stale rows in this
file are how a coordinator ends up citing a merged bead as open or a torn-down
worktree as active — the fan-out below catches that before you write, not after.
This is narrower than the no-delegation rule above and does not conflict with
it: these sub-agents verify facts, they do not compose the session narrative and
they do not edit the file. You still write every Edit call yourself in Step 4.
Dispatch one **read-only**, background sub-agent per section, each scoped to
exactly one section and returning only a verified-stale delete-list plus an
unsure-list (unsure ⇒ keep, never delete on a guess):
1. `## Current State Summary` — for each cited SHA,
`git merge-base --is-ancestor <sha> origin/<merge_target>`; for each cited
bead, `bd show <id>`.
2. `## Open Epics / Active Work` — `bd show` each bead ID; rows whose bead is
CLOSED are stale.
Consolidate the delete-lists yourself, then fold the confirmed-stale rows into
the section edits in Step 4. Fan-out keeps this fast without sacrificing
thoroughness — a single-threaded pass over independent sections is the slow
path, not the safe one.
**Deploy state, fleet topology, worktree layout, agent pool, and standing
rulings are NOT maintained here anymore** — they live in `thrum state`
(`--kind deploy_state|topology|worktree|agent_pool|ruling`), a cheap
`thrum state set` upsert done at the moment a fact changes, not part of this
end-of-session ritual. Staleness for those kinds is read-time (`as_of` +
per-kind threshold), not something this command curates.
### Step 4: Edit the File In-Place, Yourself
Use the **Edit tool** directly to make targeted updates. Do NOT rewrite the
entire file with the Write tool. Make one Edit call per section that needs
updating.
#### Sections to Update (use Edit tool for each)
1. **Header line** — Update `Last Updated` date and `Phase` status summary. Also
derive and insert the Authored-against stamp, placing it immediately after
the `Last Updated` line (see the $thrum:stamp-protocol skill for the exact
two-line format).
2. **Current State Summary — LIVE STATE ONLY, SUPERSEDED EACH SESSION.** Update
version, branch, beads counts, and hold _only_ what is currently in flight,
owed, blocked, or pending the owner's decision. It carries **no session
narrative** — no "what we did", no "why", no derivation.
- **This is a SUPERSESSION, not an append.** Rewrite it to reflect current
reality; do not add this session's items on top of last session's.
- **Resolved items are DELETED, not annotated.** Do not leave a "~~fixed in
S42~~" line — remove the line entirely. The line's absence _is_ the record
that it's resolved; the memory record (rule 4 below) is where the
resolution's story lives.
- Bounding only the session-index entries (rule 4/5 below) is a point fix: if
narrative is merely blocked from `## Recent Sessions`, it reappears here
under a different heading with no cap at all — the identical growth, one
section over. This rule closes that sibling surface.
3. **Architecture Health table** (STRICT 10-row rolling window):
- The table has a **Session / Date** column — format: `S<N> · YYYY-MM-DD`
(e.g. `S32 · 2026-04-14`)
- Add new rows for work done this session at the TOP of the table
- Then TRIM: keep only the 10 most recent rows PLUS any row currently in a
broken/regressed state (statuses like BROKEN, REGRESSED, BLOCKED, or a note
explicitly describing ongoing breakage). Drop all other historical
COMPLETE/FIXED/MOVED/UPDATED rows — they live in git history + Recent
Sessions below
- This is a rolling window, not an append log. If the table is at 10 and you
add 2 new rows, remove 2 of the oldest non-broken rows
- Do NOT add rows for routine work already covered in Recent Sessions — only
genuinely new capabilities, architectural shifts, or broken state
4. **Recent Sessions** — EVERY session, including the one you are closing right
now, is exactly ONE LINE. No session ever gets a prose block.
- Append a **single index line** to the `## Recent Sessions` block in
project_state.md — no body prose, ever:
```text
- Session N (YYYY-MM-DD) — <what changed, ≤30 words>
```
- **The cap is on WORDS, not on newlines.** A 200-word run-on sentence
crammed onto one physical line VIOLATES this rule just as much as a
multi-line prose block does. Count words; keep the line ≤30 of them.
- **What goes where** — the mechanical tell for sorting content: if a
sentence contains "because", "I verified", "the mechanism was", "caught
by", or "control fired", that sentence is DERIVATION, not state, and it
never goes in project_state.md. | Content | Destination | | --- | --- | |
What changed | The one-line session index entry | | How you concluded it /
verified it / why an earlier claim was wrong / what it taught |
`## Recent Sessions` in project_state.md, index line only (no derivation) |
| What's currently in flight, owed, blocked, or pending the owner |
`## Current State Summary` (rule 2 above) |
**NOTE:** the old `update-agent-state` / `update-state` skills (State.md
surface, MI1) were retired — superseded by `thrum state` (personal_state
kind). This command (`update-project`) is unaffected; it always governed
`project_state.md`, a separate surface.
5. **Session History Update Rule** (CRITICAL — keeps this cheap):
- **At most TEN index entries in `## Recent Sessions`.** Older entries are
**DELETED**, not archived in-file or moved to another section — the memory
record IS the archive, so deleting the 11th line loses nothing.
- **Adding this session's line and deleting the overflow line happen in the
SAME edit / SAME commit.** Do not split "append now, trim later" into two
steps; there is no later step. Emit the memory record, append the new index
line, and delete the 11th-oldest line (if present) together.
- Do NOT re-write or re-consolidate the other index lines you keep — they are
frozen once written. The section stays compact indefinitely because it is
bounded at 10, not because entries shrink over time.
6. **Open Epics / Active Work** — Replace with current epic list from beads.
7. **What's Queued / Next Steps** — Update priorities based on current state.
#### Edit Rules
- Use the Edit tool's old_string / new_string to target specific sections
- Each Edit should replace a clearly bounded section (between headings)
- Do NOT touch sections that haven't changed
- Do NOT re-write frozen `## Recent Sessions` index lines you are keeping
- Preserve all markdown formatting and heading hierarchy
- Use ABSOLUTE paths for all file operations
### Step 5: Verify Before Finishing
Run these checks yourself before reporting done — this is a required step, not
advice you may skip:
- `wc -l` the file BEFORE your edits and AFTER — report both counts.
- Count the entries under `## Recent Sessions` — must be **≤10**.
- Word-count the newly added session index line — must be **≤30 words**.
- Confirm no `## Sxxx` (or any other) prose block exists for any session — every
entry in `## Recent Sessions` is a single index line.
- If the file GREW, state the reason. Growth is not automatically wrong (a
legitimately new structural section can grow it), but an update that grows the
file with no stated reason is a defect, not a style choice.
### Step 6: Report What You Changed
State directly (no subagent summary to relay):
- Which sections were edited
- Architecture Health: N rows dropped, N rows added, final count
- Recent Sessions: entry count before/after (must be ≤10), and the word count of
the new entry (must be ≤30)
- Line count before/after (Step 5)
- Any issues encountered
## CRITICAL Rules
- Use the EDIT tool, not the Write tool — targeted changes only
- Architecture Health table is a **strict 10-row rolling window** + broken rows.
Never let it grow beyond that
- **`## Recent Sessions` — every session is ONE LINE, no exceptions, including
the session you are closing right now.** At most **10** entries; older ones
are **deleted**, not archived in-file — the memory record is the archive.
Deletion of the overflow entry happens in the **same edit** as the addition of
the new one; it is one step, never two. The line cap is **≤30 words**,
measured on words, not physical newlines — a long run-on sentence on one line
still violates this.
- **`## Current State Summary` is superseded each session, never appended to.**
It holds only what is in flight/owed/blocked/pending the owner. Resolved items
are deleted outright, not annotated as resolved. Session narrative and
derivation NEVER belong here — that is what `thrum memory` is for.
- Do NOT touch stable sections (Key Architecture Files, etc.) unless they
changed
- Target total file size: ~150-300 lines for a SMALL project. A mature project
will legitimately be larger and that is not bloat to be trimmed. The bounded
part is SESSION HISTORY — those bodies now live in `session_summary` memories
with a one-line index entry for the ~10 most recent, and older sessions are
recoverable via `thrum memory search`. The rest (schema-compat contract, merge
protocol, architecture decisions) is DURABLE STRUCTURAL DATA that a restarting
agent needs in order to act safely; shrinking it costs more than it saves. Do
not trim structural sections to hit a line count. (Deploy state, fleet
topology, worktree layout, agent pool, and standing rulings are no longer in
this file at all — see the note above Step 4's section list.)
- **Do not delegate any part of this to a subagent.** See the reasoning at the
top of this file — it is a deliberate, named exception, not an oversight.