Releases: Jerry0022/dotclaude
Release list
v0.149.0
Added
-
The
/conceptdecision panel never hides its call-to-action below the fold again. The panel was one scrolling column — iteration chips, a flat table of contents, the connection pill, then the two submit buttons — so a concept with eight rounds and twenty-odd sections pushed "Zur nächsten Iteration" off the screen, and the user scrolled the menu to find the decision. The status area was noise at rest ("Claude verbunden") and silent about the one thing the reviewer wanted to know: is my work saved, and did it go through? The panel is now a flex column with three regions: a pinned "Hier bist du" header (round + section under the reading line), a scrolling middle, and a pinned foot that is hard-capped at 120 px in the smallest and the largest case alike. The foot holds one status line with six mutually exclusive states — saved, saving, connecting, not delivered (a warning background, categorically different from the rest), submitted with progress dots, and read-only round — driven by the draft mirror and the heartbeat, and a split-button: the primary "Zur nächsten Iteration" plus a caret that opens "Mit Feedback implementieren" one level deeper, so the misclick barrier is a menu rather than a 2rem gap. The hint paragraphs moved into tooltips; the cache hint,#panel-frozenand the progress list stay real DOM. In design mode the foot keeps a gutter for the 💬 FAB; on mobile the panel caps at 60vh so the split still holds.Iterations and table of contents merged into one tree ("Kompass"). Every round is a node; exactly the round on screen is open and its body is that round's section list — there is no code path that closes it, switching tabs moves it. Older rounds cost one line each ("Iteration 3 · 14 Einträge · 2 verworfen") and fold into an archive only from four previous rounds, which auto-opens whenever a frozen round is viewed. Sections group into Kontext / Varianten only when at least two kinds meet more than twelve entries — kinds are inferred from the existing
eval-{id}radios with adata-nav-groupoverride, never from an attribute the author has to remember — and one-open applies inside the TOC only. The scroll spy may open the group that holds the active entry and never closes one; a manual close is honoured for four seconds. Every collapsible element is absent from the DOM below its threshold, so a one-round, three-section concept renders exactly as before, minus nothing. The tab bar keeps its contract — one.iteration-tabper round, appended by string edit — so the append checklist is unchanged. Decided on a two-round concept page (three directions, then three foot variants of the chosen one), red-teamed against the scroll-spy, tab-switch, persistence and wizard contracts before implementation, and pinned by 42 new jsdom tests plus validation-gate entries 56–61.
Fixed
-
The concept port registry had silted up to 1159 entries with no bridge alive. 1131 of them came from the test suites, which spawn real bridge servers and tear them down with SIGKILL — skipping
/shutdown, the watchdog, atexit and any signal handler — so everynpm testrun left dozens of entries in the user's real registry; the rest were bridges lost to hard kills and power cuts.picknow sweeps first: an entry is deleted when its port no longer accepts a TCP connect (or the file is not JSON), and a bound port is never touched, so a live foreign bridge stays protected. The recorded pid is deliberately not a keep criterion — Windows reuses pids within days, and 35 weeks-old entries survived a pid-based sweep for exactly that reason. Server and picker honourCONCEPT_BRIDGE_REGISTRY_DIR, which the three server-spawning suites point at a temp directory; the server also drops its entry on SIGINT/SIGTERM/SIGBREAK, where the default SIGTERM action used to skip atexit. -
The bridge launch procedure resolved the plugin scripts from the oldest cached version.
ls -d ~/.claude/plugins/cache/dotclaude/devops/*/scripts/… | head -1returns the lexically first version directory, and several coexist after updates — so a session ran a 0.145.1 bridge server and watcher beside hooks already on 0.148.0, and the resume hook generated the same stale prefix into the cron. Every occurrence now version-sorts and takes the highest (sort -V | tail -1), preferring$CLAUDE_PLUGIN_ROOTwhen the shell has it; CONVENTIONS.md carries the rule.
Install: /plugin marketplace add Jerry0022/dotclaude
v0.148.0
Added
-
A concept card no longer counts its own plumbing as unfinished work. While a
/conceptpage is open, three detached Bash tasks run for the whole session — the bridge server, the keepalive pulser and the pickup waker. They never yield a result; they are the waiting. The pending gate counted them anyway, so every card rendered mid-concept read "⏳ NOCH NICHT FERTIG. 3 Tasks (Start the concept bridge server on port 8840, Launch the keepalive pulser …) laufen — ich MELDE mich", naming infrastructure where the only true statement was "waiting for your decisions". The transcript scanner now recognizes those tasks — by the script they run or the role their launch description names — and never opens them, sostop.flow.guardignores them; a real agent ornpm testlaunched alongside is still reported. The PostToolUse reminder that fires on a background launch says[concept]for these instead of[pending], so the model is not steered into listing them.The card gained a
conceptfield for the state a concept can actually be in.concept: { phase }—waiting(default),iteratingorimplementing— replaces the CTA of every variant, and outrankspending, with "🧭 CONCEPT läuft. Warte auf deine Entscheidungen auf der Seite / Arbeite an der nächsten Iteration / Arbeite an der Implementierung — ich MELDE mich". Real content work still goes intopendingand is folded into that line rather than replacing it —Arbeite an der Implementierung mit Agent \devops:frontend`,… mit 1 Workflow + 2 Agenten— while the pending block and the dim name row keep naming each item. A JSON string, a bare phase string and an object are all accepted; an open concept with an unknown phase reads as waiting, because the only wrong card here is one that asks for a SHIP. The concept skill documents the mid-concept cards and that the final card, rendered after cleanup, carries noconcept` at all.
Install: /plugin marketplace add Jerry0022/dotclaude
v0.147.0
Added
-
The completion card's pending layer knew agents and Bash tasks, so a whole
Workflowrun counted as one agent — or as nothing at all. A workflow fans out to dozens of agents of its own, so reporting three of them as "3 Agenten" understated the work by an order of magnitude, and the Stop gate never saw a workflow launch at all: a card that forgot to declare one was not blocked, because the transcript scanner only knew two launch markers. What looked like working support was the model typing "Workflow x" into an agent item by hand.workflowis now its ownkindend to end — detected fromWorkflow launched in background. Task ID: <id>, named from the script'smeta.name(anchored to theexport const metaliteral, since a barename:match happily picks up an agent label defined earlier in the same script), else the script path, else the launch summary, and closed by the matching task-notification.The names moved out of the CTA. Three names plus two counts in one heading is a line that wraps, so the CTA now carries the shape —
3 Workflows + 1 Agent + 1 Task laufen— and the names sit one row above it, in the same dim blockquote style as the version and branch rows: the first three, then a+Ntail counting every remaining item. Both+Non a card cut at the same three, so the block above and the row below can never disagree about the rest. A single item is still named in the CTA itself and gets no row, because repeating one name is not information.
Fixed
-
Quoted text was treated as an event: one
grepcould block every later card in the session. The transcript scanner matched launch markers in any tool result and task-notifications in any line, so a Grep hit on the hook's own source, a Read of a transcript, or a script printing a launch line opened a phantom item that no notification would ever close — and an item that never closes blocks the Stop gate forever. This was not hypothetical: running the scanner over a live session transcript found two, both produced by ordinary work in this repo. Three guards now separate event from quotation: a launch counts only from a tool that can announce that kind of launch (bound per marker — Bash may announce its own task but also prints everybody else's), only when the announcement is the tool result rather than a line inside somebody's output, and a completion counts only when the notification is a real transcript entry rather than the payload of atool_result. -
Pending labels reached three places that read text as structure, unsanitized. A name arrives as model-authored text — a workflow's
meta.name, an agent description — and lands inside a markdown code span, inside a JSON example, and inside the Stop hook'sreason, which Claude reads as instructions. A backtick ended the code span early, a newline split the card's tightest row, and an unbounded name turned it into a wall of text. Labels are now stripped of structural characters and clamped at one choke point on each side.
Install: /plugin marketplace add Jerry0022/dotclaude
v0.146.0
Added
-
/conceptnow re-checks an approved plan against the default branch before implementing it. A concept session lives for hours or days whilemainkeeps moving — other sessions, other PRs, other ships. Clicking "Mit Feedback implementieren" implemented the plan as approved, so a renamed file, a changed contract or work somebody had already done reached the diff unremarked and was found in review, if at all. The implement path now runs a reality check before writing a single line: on material drift it does not implement, it appends one extra round — mechanically an ordinary iteration, markeddata-reality-check, with its own "Realitäts-Check" tab and an explainer naming the commits that landed — carrying every decision the drift raises. Submitting that round with implement writes the code.The hard requirement was that this must never become a trap, so it has two independent guards. The marker on the section short-circuits the check, which is exact: implementing from a reality-check round always implements. And the baseline advances on every submission of such a round — iterate as well as implement — so the same drift cannot force a second one even if the marker were lost to a bad rewrite, a legacy page or a resumed session working from a page it did not write. Both would have to fail on the same round to produce two forced rounds in a row. An ordinary iterate round re-arms the check, which is the user opting back in rather than a deadlock: the next implement is measured against the advanced baseline, so only drift that landed since can raise it again.
The split between code and judgment is deliberate.
scripts/concept-drift.jsproduces facts only — the commits, the changed paths (a rename contributes both sides, which is the drift class that matters most), and their intersection with the paths the concept names — while the force classes stay with the model: a file deleted or renamed, a contract changed, the functionality already built, a user decision that lost its basis. Version bumps, CHANGELOG, docs, tests-only changes and formatting never force a round, and no drift card may be shown without the SHA and path it comes from. Every unresolvable condition fails safe — no repo, no remote, a default branch that is not calledmain, a detached HEAD, an offline or slow fetch, a shallow clone, a baseline erased by a force-push — and lets the implement through; a network hiccup must never block an implement order. The check announces itself as its own progress step before the fetch, so the added wait cannot read as a stalled submission, and it never reportsphase: "implemented"on that path — a panel showing "Implementierung abgeschlossen" over an empty diff would be worse than the problem being solved.
Install: /plugin marketplace add Jerry0022/dotclaude
v0.145.1
Fixed
-
/setup-cleanup's "active sessions are UNTOUCHABLE" rule protected branches but not the sessions themselves. The rule was written as a list of forbidden commands —git branch -D,git push origin --delete, checkout — and a list of verbs silently permits every verb it forgot to name. A cross-repo sweep obeyed it exactly: it refused to delete a live session's branch, then removed that session's worktree anyway, becausegit worktree removewas not on the list. The session kept running and lost nothing, but only because the branch it had already committed to survived elsewhere.The protected set is now a set of subjects — the branch, its worktree directory, the repo it lives in, and any process running inside it — with the commands demoted to examples, and it must be rebuilt immediately before each destructive action rather than once at classification time, because a sweep across many repos outlives the session state it was classified against.
deep-knowledge/git-hygiene.mdgains the general rule and the four operation classes a guard has to cover (ref, worktree, file, and process mutation), plus the reason a partial guard is worse than none: it reads as coverage. Detection was widened in the same pass — agit worktree list --porcelainscan that only collectsbranch refs/heads/lines misses detached worktrees entirely, and scanning the.claude/worktrees/directory misses worktrees registered outside it; both were live blind spots, not hypotheticals.
Install: /plugin marketplace add Jerry0022/dotclaude
v0.143.0
Fixed
-
Switching between
/conceptiteration tabs could destroy every comment on the page. Four independent single lines caused it, and two of them fired precisely when things were already going wrong.restorePanelToReady()ended inlocalStorage.removeItem(STORAGE_KEY)— deleting every comment, rating and selection — and it runs both when the bridge answers 507 (nothing was persisted anywhere, so the local copy was the last one) and after the five-minute safety timeout, i.e. exactly when Claude has stopped responding because of a usage limit. The submit handler emptied the feedback dock, although the submitted round stays live until Claude appends the next section: a detour into an older tab came home to a blank dock on a round that had not even been answered yet.saveState()persisted frozen rounds and the frozen-painted dock, so browsing a past tab — which is what the tabs are for, and which ends everyshowScreen()in asaveState()— wrote the old round's submitted answers over the live round's unsent ones. AndrestoreState()deleted the whole blob on TTL expiry and on a page-version change.Typed keys are now namespaced per round (
text:i3:d1-s1) — screen ids,{decisionId}-notekeys and annotation ids all repeat across rounds, and the dock is one shared overlay outsidesection[data-iteration]— which is what makes keeping the text both safe and unambiguous. Nothing deletes the state blob any more: TTL and version changes prune it key by key, keep everytext:entry, archive the original, and say so on the page. The dock is marked read-only on submit instead of emptied, and re-armed byunmarkDockSubmitted()on every path that hands control back.
Added
-
A concept page's unsent comments are now mirrored to disk, fsynced, on every autosave.
journal.jsonlonly ever saw a payload the user pressed submit on; everything typed before that lived exclusively inlocalStorage, which does not survive a wiped profile, a private window, a quota error or a power cut — and which nothing else had a copy of. The bridge gains a draft store (POST /draft,GET /draft): an append-only revision log plus an atomically replaced snapshot per page, written with the same never-ack-what-is-not-on-disk rule as a submission. Because the log is append-only,GET /draftcan answerrecovered— the per-key union of the last non-empty value ever posted, minus the keys the page reported as deliberately cleared — so even a client that posts a blank blob, the shape every past data-loss bug took, cannot destroy anything. The page flushes withsendBeacononpagehideand mergesrecoveredback on load into any key it is missing or holds empty. The bridge is a plain Python process with no dependency on Claude, so it keeps accepting drafts long after a usage limit has silenced the session.GET /recoverylists the drafts, so a resumed session can tell "the user typed nothing" from "the user typed for an hour". Verified end to end in a browser: the bridge was SIGKILLed,localStoragewiped completely, the bridge restarted — every comment came back from disk. Gate entries 49–53 pin all of it as engine entries, so an existing page picks them up on its next iteration append. -
Two suites that execute rather than read:
comment-durability.test.jsruns the shipped engine text in jsdom and reproduces all four losses (19 of its 20 tests fail against the previous code), anddraft-durability.test.jsSIGKILLs a real bridge, corrupts its log and restarts it. A torn final journal line — the signature of a power cut mid-append — also used to swallow the next record; the store now terminates it once per process, and_durable_writefsyncs the directory after the atomic replace. -
The ship gate stopped failing on contention. These suites test hooks, the bridge server and git-sync by spawning them, so one vitest worker is never one process; the default (~cores-1) put 30+ runnable processes on a 12-core machine and the one that lost the scheduler was vitest's own main process, whose workers'
onTaskUpdateRPC then timed out and exited the run 1 beside 2466 passing tests. Worker count is capped at a third of the cores.
Install: /plugin marketplace add Jerry0022/dotclaude
v0.142.0
Added
-
/claude-strict— the deliverable is exactly what the prompt names, and only the attributes the prompt leaves open are Claude's call. "Make the box border thinner" used to invite a padding fix, a doc update and a tidy-up of the two neighbouring borders; nothing in the plugin held the line, and several always-on mandates (docs in the same change, pre-mortem guards, "make reasonable decisions independently") pushed the other way. The new skill fixes the scope in the vocabulary of the request — a visual request closes the set of visible things that may change, a technical request closes the set of symbols — while unnamed attributes (colour, pixel value, wording) are chosen and reported in a four-line strict report (requested / done / chosen / untouched). Grey zones are settled, not left to mood: a syntactic companion (import, export entry) is in scope, an assertion pinning the exact old value may follow, any other test failure reverts and reports, an ambiguous object is asked about interactively and assumed (and led with) autonomously.Two modes, one state file per worktree:
/claude-strict <task>binds the turn and every workflow it starts (a concept session or an autonomous run is auto-bound to its state file and released when that file disappears);/claude-strict on|offbinds the current worktree + branch, never the whole project — a branch switch deactivates it with a single notice. Enforcement is mechanical:prompt.strict.enforceinjects the ≤1.4 KB contract once per turn (also on cron and waker turns, so concept iterations stay strict without re-typing),pre.strict.agent-gaterefuses an Agent spawn whose prompt lacks the block and says how to fix it (recursive — plugin hooks run inside subagents; worktree agents inherit via<parent>-<role>), andstop.strict.releasebinds or releases inline modes.code-defaults.md§ Strict Mode states the precedence over doc-maintenance and pre-mortem outputs; the agent prompt template gains item 9 (forward the block verbatim). Spec:docs/superpowers/specs/2026-09-04-claude-strict-design.md.
Install: /plugin marketplace add Jerry0022/dotclaude
v0.139.1
Fixed
-
A
/conceptpage still stacked one 📎 attachment bar per hidden dock field after the fix that was meant to end it, scrolled the dock behind a raw platform scrollbar, and let the page header shine through frozen design iterations. Measured on a real four-iteration page: twelve visible attachment bars for three visible textareas, 1062px of dock content in a 430px box, and the document<h1>plus the iteration intro painted through the mockup right under the screen indicator after every ☰ switch. Three causes. The page's attachment engine predated the earlier fix (parentElement.appendChild(bar), no.attach-barhalf in the hiding rule) and still passed the validation gate, because entry 44 grepped a single literal that the page happened to contain; and an iteration append re-uses the page's existing engine forever, so the defect survived every later round of the same concept. In design mode a page that started as a decision round keeps its document header and each iteration's intro in normal flow while the design section paints over themposition: absolute; inset: 0— and the generic frozen-iterationopacity: 0.85turned that into bleed-through.The attachment engine now injects its own visibility CSS once (
#attach-visibility-styles), so a page that copies the JavaScript without the layout rule still hides a bar with its field. Gate entry 44 requires both hiding literals, theafterendmount and the injected style, and rejects the legacyparentElement.appendChild(bar)andattach-hintshapes; new entries 46 and 47 pin the design-mode rules that hide the document header and intro and keep a frozen design iteration fully opaque, and entry 48 warns on a missing scrollbar skin. The three scroll boxes (.feedback-dock,.concept-decision-panel,section[data-screen]) carry a thin border-coloured scrollbar in every template. Step 5c of the skill gains an engine drift check before every append: the gate runs over the whole existing page and any failing shared block is re-synced from the reference before the new iteration lands — so a page generated before a template fix picks the fix up on its next round instead of never.
Install: /plugin marketplace add Jerry0022/dotclaude
v0.139.0
Backlog run 2026-09-03/04 (PR #325, eight issues). The plugin's own ship server was unreachable while this work was made — the very defect fixed first below — so the eight fixes landed as one integration PR and this entry versions them.
Fixed
-
The plugin's MCP servers timed out at session start, and the plugin itself was the reason. Claude Code starts every SessionStart hook concurrently with every stdio MCP server and gives each server thirty seconds to answer
initialize. On 2026-09-03 all three plugin servers — and unrelated third-party ones — hit that timeout in session after session, although each of them boots in under two and a half seconds on its own. The thirty seconds were being consumed by the plugin's own start-up work: fourgit fetchcalls, annpm install, a ten-thousand-file copy ofnode_modulesinto the very directory the servers use as their working directory, a recursive scan of the repository and a process sweep, all at once, all with Windows Defender inspecting every write. The issues server made it worse by runninggh issue listsynchronously before it had even created its transport. A session that losesdotclaude-shipcannot ship at all. (#324)Nothing runs before
connectin any server any more; the issues warm-up is asynchronous and happens afterwards. Every server answers ahealth_check, a stdout-discipline test keeps the JSON-RPC wire clean, and a boot probe (scripts/mcp-boot-probe.js) fails the suite when any server takes longer than five seconds to answer. The plugin updater and the dependency installer now sit behind cooldowns (six and twenty-four hours) that an explicit/auto-update, the post-ship sync, or a genuinely broken cache bypass;node_modulesis never copied again but linked and refreshed only when the dependency manifest changes; a repair of a version directory a live session is standing on is handed to a detached child that waits out the connect window; the git check and the changelog hook lost an unbounded and a duplicated fetch; and every SessionStart hook carries an explicit timeout. The rule behind all of it is written down inCONVENTIONS.mdunder "Boot Discipline".MCP_TIMEOUT=60000remains the documented stopgap for a slow machine. -
/setup-cleanupsilently dropped removable branches whose name is a prefix of a worktree branch. The protected set was matched by substring, sofeat/x-abc123counted as protected wheneverfeat/x-abc123-def456had a worktree — conservative, but invisible: the candidate list was simply one entry short. Membership is now exact full-ref equality, prefix and substring tests are forbidden, and a mandatory count check at the end of the classification (candidates plus protected set must equal all local branches) turns any future gap into a visible warning. (#323) -
/setup-cleanuplocked almost every worktree on a squash-merge workflow as "work in progress". Being ahead oforigin/maincounted as having changes, and a squash-merged branch is ahead forever. In one real repository that classified 34 of 41 worktrees as untouchable while two of them carried unsaved work.has-changesis now decided solely bygit status --porcelain; commits ahead become the separate, non-blockingcommits_aheadattribute together with anown_contentbadge from the same two-dot check the skill already used for branches. (#322) -
/claude-batch <free text>no longer disappears, and a dead marker repairs itself. The routing table gains an explicit row for a free-text argument — it becomes note #1 and switches the mode on — and a marker pre-check now runs on every route: a stored marker that cannot work asks the marker question immediately instead of being re-reported on eachstatusrun and never fixed. (#306) -
The committed project map no longer carries a random worktree slug as its title.
gen-project-mapresolves a stable name —package.jsonnameof the main checkout, else the main checkout's directory, and only for non-git trees the given root — so a map regenerated from.claude/worktrees/<slug>/is byte-identical to one generated from the main checkout. (#303) -
A
/conceptdesign page could go completely blank after switching designs and using the panel. The screen navigation compared against the design that was active when the navigation was built, never re-built on a design switch, andshowScreen()hid every screen when handed an id that belonged to no screen of the active design. The handler now resolves the active design at click time andshowScreen()falls back to the first screen; gate invariant P15b requires exactly one visible screen after any switch and insists ongetClientRects()rather thangetComputedStyle().displayfor the assertion. Verified with a fifty-four-click sweep across two iterations, three designs and every navigation entry. (#299) -
Feedback typed into a
/conceptdesign-page dock was destroyed by a reload or a design switch. The state restore ran before the dock textareas existed, and the next save then rewrote the stored blob without them. The restore now runs immediately after the dock is built and before anything can save;saveState()merges over the stored blob and never blanks a note the user has not touched since load. Browser QA caught a second ordering defect in the first fix (the load handler's ownshowScreen()saved before the restore) — fixed and re-verified: a note survives a reload, three design switches, an iteration round trip and a second note. (#297)
Added
- Both floating buttons on a
/conceptdesign page now say what they are. The feedback button was a bare emoji circle that users could not find. Both buttons carry locale-sourcedtitleandaria-labelthat swap witharia-expanded, and the feedback button pulses three times until it is first used (disabled underprefers-reduced-motion). The shared-shape invariant is untouched — the labels are tooltips only, and the pulse rule declares nothing butanimation. (#298)
Install: /plugin marketplace add Jerry0022/dotclaude
v0.138.1
Fixed
-
A post-merge watcher that died took its result with it, and announced itself as still running for a day afterwards. The watcher is spawned detached, so a machine shutdown or a killed session ends it without any of its terminal writes ever happening, and its state file stays on
status: "watching"withfinishedAt: nullforever. The only defence was a flat twenty-four hour staleness constant in the SessionStart reader — a number with no relationship to the watcher's own lifetime, which is at most five minutes of run detection plus--max-waitplus the deploy probe. For the whole of that day the reader greeted every session with "Ship verify still running", counting up: the reported figure had reached 1205 minutes for a process that had been dead since minute forty. Then, on expiry, it setacknowledged: truewhile leavingstatus: "watching"— so the entry was never reported at all, the outcome of that ship was silently lost, and because the status never changed the branch was re-entered at every subsequent session, re-stampingstaleAtwith a fresh timestamp each time. Eight entries were sitting in that state here, the oldest since 2026-08-17, all carrying the same current-daystaleAt.Every state file now carries
maxWaitSecanddeadlineAt, so a reader decides "working" or "died" from the run's own numbers rather than a constant. Past that instant the entry is treated as abandoned and reconciled againstgh run list --commit <merge-sha>, which answers the counterfactual the watcher can no longer answer itself; the result is written as a terminal state, surfaced exactly once, and cannot re-enter the watching branch. Reconciliation trusts only the per-commit query — the branch-scoped fallback misses tag-triggered runs entirely, so an empty result there yieldsinconclusivewith agh pr checkshint rather than a fabricated "no workflow ran". Matches are further restricted to runs created before the deadline, because in this repo the Release workflow fires on the barevX.Y.Ztag that/promotelater adds to the already-merged commit: without that restriction a promotion's CI would be reported as the ship's own. The watcher additionally writes a terminalinconclusivewhen it is terminated gracefully; a hard kill remains the reader's problem, which is what the deadline is for.
Install: /plugin marketplace add Jerry0022/dotclaude