You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Mask mode now redacts the scan-root paths shown under the garden and in the multi-root scan progress UI. Pre-fix, hitting m to mask names left the configured base directories visible in plaintext, leaking the same path information the per-repo masking was hiding.
Journal vibe-change entries read as transitions, not status snapshots. Each from → to pair now picks a verb that describes the change (back in flow, hit a blocker, wound down, settled, back at it, stirred, …) instead of falling through to the destination state. Pre-fix, blocked → happy rendered as happy: clean, which read like a status line. The reason text gets a small cleanup pass too: the redundant blocker: prefix is stripped when the verb already says it, and trailing periods are dropped before the em-dash join.
Garden creature labels no longer collide with neighbouring sprites. Placement now sizes each grid slot to fit the full footprint (sprite body + rendered name label), and reserves room for the label row below each sprite. Pre-fix, two sprites whose bodies didn't overlap could still have their name labels painted over each other or into an adjacent sprite, and a long name on row N could clip into the sprite on row N+1.
Wandering creatures no longer land on dragged neighbours.syncVisualPlacements now resolves manually-offset creatures first so wanderers iterated before them check against the dragged neighbour's actual visual position, not an anchor footprint that excluded it.
Added
Per-repo activity drives animation cadence. A continuous 0–1 activity scalar derived from "days since last commit" (7-day half-life exponential decay) now biases each creature's wiggle frame-cycle and wander idle gaps within its vibe-bucket's range. Fresh-commit repos sit at the fast end of their cadence range with full drift radius; long-quiet repos sit at the slow end with ~25% drift. A repo blocked by a current blocker note still gets its activity from commit recency, so a freshly-broken build keeps bustling visibly while a stalled-for-a-month one barely moves.
Closed eyes + blink animation. Awake creatures keep their original sub-pixel-derived eye look (the corner-cut quadrant chars from the body grid). Sleepy creatures and the brief blink window for awake creatures paint a face panel: a body-coloured cell with ▂ (lower one-quarter block) cut into it as a closed eyelid. Each awake creature blinks briefly every 3.5–7s (interval shrinks with activity) on a per-identity phase so the swarm doesn't blink in unison. Reduced-motion mode skips the blink entirely. Sleepy creatures hold their body at rest — no bob — so the closed eye sits on a stationary face; awake creatures still bob and the eye cells track the per-frame shift. Sprite generation guarantees at least one cell of body between the two eyes (so closed-eye glyphs read as two distinct eyes, not one connected bar) and at least one cell row of body below the eye row (so the closed-eye glyph sits on a face instead of dangling).
Background observer for live commit + new-repo backfill. fs.watch on each repo's .git/logs/HEAD catches commits / amends / pulls / resets within ~250 ms; a non-recursive watch on each scan-root catches new repos dropped into a tracked folder within ~500 ms. The existing 30 s safety-net poll still runs underneath so updates arrive on filesystems where fs.watch is unreliable. Default-on; the settings screen exposes o as a persistent toggle, and REPOGARDEN_DISABLE_OBSERVER=1 still wins for single-run launches. Closes the §4.1 "flagged for recovery" item in docs/legacy-not-ported.md.
Pull from the workbench (fast-forward only). PORTRAIT exposes u as a two-press confirm (first arms, second runs); the command palette has a "pull from remote" entry that runs immediately. Result lands as a sticky banner on failure / non-zero and as a transient success banner otherwise. Preflight blocks the action when the tree is dirty, HEAD is detached, the branch has no upstream, or scan errored. Each attempt appends a pull event to the journal — payload carries ok, exitCode, branch, beforeSha, afterSha, commitsPulled, summary, durationMs, timedOut. Closes the §7.3 "flagged for recovery" item in docs/legacy-not-ported.md.
Internal
New computeActivity + ACTIVITY_HALF_LIFE_DAYS exports in src/lib/vibe.ts; VibeResult now carries activity: number. buildWiggleProfile and a new per-creature WanderProfile (built once in createWanderState and stored on GardenWanderState) replace the previous direct VIBE_WANDER reads in step functions, so activity-baked timing flows through the whole tick path without re-resolving on every frame.
generateCreatureFrames now returns eyeCells: { left, right } alongside frame data. GardenSpriteInfo carries those cells plus an eyesClosed flag (gated on vibe === "sleepy" in buildScene) and a per-creature BlinkProfile (interval scales with activity, randomised phase). The render loop in src/garden/render.ts only short-circuits to a composited face panel ({ char: "▂", fg: theme.background, bg: info.body }) when eyes should be shut (sleepy or in the blink window); otherwise the body grid's natural quadrant char paints unchanged. New blinkClosedAt helper in src/garden/model.ts returns the closed/open state from (now + phaseMs) % intervalMs.
New spriteFullFootprint helper in src/lib/garden-layout.ts covers the rendered name label below each sprite; placeCreatures now sizes slots from max(maxSpriteCols, maxLabelCols) horizontally and maxSpriteRows + NAME_GAP_ROWS + NAME_H vertically. syncVisualPlacements in src/garden/model.ts resolves manually-offset placements first so wanderers see their actual visual positions. New vibeTransitionVerb + trimVibeReason helpers in src/lib/event-summary.ts cover all 12 from-to transitions with a defensive fallback for unknown vibe pairs. Test count: 318 → 345.
New module src/lib/observer.ts (per-handle debounce, watch budget cap at 150, error-tolerant per the subscribeToEventsFile pattern). New observer field on TuiConfig and observerEnabled() helper honoring the env override. cli.tsx adds one useEffect keyed on the set of repo paths so commit-driven state updates don't churn the watcher list.
New module src/lib/git-pull.ts (async git pull --ff-only with 60 s timeout, line-streaming onLine callback, and small sync sha helpers). New event-summary kind pull. New single-repo refresh helper refreshOneCreature in src/lib/creature.ts re-inspects one repo and re-runs enrichScans so the snapshot reconcile fires.
Contributor workflow migrated from npm to pnpm (pinned via packageManager: "pnpm@10.32.1"). package-lock.json removed; pnpm-lock.yaml is the lockfile. CI (.github/workflows/ci.yml) runs pnpm install --frozen-lockfile and pnpm scripts; the pack-smoke job still installs the produced tarball with npm install -g so the same path real users hit (npm install -g @outsideheaven/repogarden) stays exercised. prepare and prepack now inline the build command instead of calling npm run build, so neither lifecycle hook depends on a particular package manager being present. chalk@^5.6.2 is now a declared direct dependency (was previously imported by src/garden/diff.ts but only available via npm's hoisted layout).