`normalizeAgent` rewrote the first `model:` frontmatter line when one was
present, so an agent that pins a model in one toolchain and omits it in another
normalized to different text and looked like body drift.
The bug is latent here rather than firing: every agent whose `.claude` copy
omits `model:` currently has a `.cursor` copy that omits it too. Pinning a
Cursor-only model on any of them turns the gate red for a non-reason —
reproduced by adding `model: composer-2.5-fast` to
`.cursor/agents/code-quality.md`, which fails before this change and passes
after it. The same defect was failing on seedit's master, where those Cursor
copies do pin a model.
Strip the frontmatter `model:` line instead of rewriting it. Scoping the strip
to the leading frontmatter block keeps a body line that begins with "model:"
comparable, so it is still reported as drift. Verified that injected body drift
is still caught.
`lock_root` dereferenced `$HOME` unconditionally, so under `set -u` the script
died with "HOME: unbound variable" in any environment that starts without it —
even when `PLAYWRIGHT_RESOURCE_LOCK_DIR` made HOME irrelevant. Surfaced by
running the suite under vitest's node environment, where `process.env` is
patched and spreading it does not carry HOME through to the child.
Resolve the lock path in order (explicit override, XDG_CACHE_HOME, HOME) and
fail with a clear message only when none of them is set. The test now names
PATH and HOME explicitly instead of spreading process.env.
`src/lib/__tests__/math-tags.test.ts` was committed unformatted in #1170, so
`yarn prettier` rewrote it on every unrelated run and contributors had to
remember to revert the churn. The assertion collapses to 153 characters, well
under the configured printWidth of 170.
No other file under `src/**` or `electron/**` is formatter-dirty. Neither
`.oxfmtrc.json` nor the oxfmt version has changed since that commit, so the
drift came from a bypassed lint-staged pre-commit hook rather than a config
change.
Playwright disables normal background throttling, so a hidden 5chan page keeps
doing P2P and rendering work after a check finishes. Agents verifying in
parallel across worktrees stacked whole browser engines on one machine.
Add scripts/pw-session.sh, a wrapper that permits one active Playwright browser
at a time and records who holds it:
- The lock is machine-wide, not per-repository, because the contended resource
is RAM and CPU. Every worktree and checkout shares one slot.
- Acquisition is an atomic mkdir. Stale locks clear themselves: `open` reclaims
any slot whose recorded browser is no longer `status: open` in
`playwright-cli list --all`, so an interrupted workflow cannot strand the
budget. When that list cannot be read the lock is left alone, so a broken CLI
never silently disables the budget.
- `open` exits 75 when the slot is busy; `--wait[=SECONDS]` blocks instead.
- `close` always stops the browser, even when the lock was already lost, and
never releases a slot held by a different session.
- `status` reports the holder and whether its browser is still alive.
Agent policy now runs browser engines and profiler batches sequentially, uses
Chrome/Blink during iteration and the full engine matrix only for final
verification, and never uses `close-all` or `kill-all` while other agents may
own sessions.
Covered by scripts/pw-session.test.js.
Clears GHSA-wrjc-x8rr-h8h6 (open redirect via backslash in <Link>/useNavigate)
and GHSA-337j-9hxr-rhxg (arbitrary constructor injection in deserializeErrors),
neither of which has a 6.x backport. Drops the now-unused @remix-run/router
resolution, since v7 no longer depends on it.
Drop the pinned `model: sonnet` from the reasoning-heavy subagents so they
follow the session model instead of being forced down to Sonnet. Running an
Opus session now gets Opus subagents; deliberately dropping to a cheaper
session model is respected too.
Mechanical agents (browser-check, profiler, translator) keep their haiku pin
— that pin is a capability statement, not a stale default, and should hold
regardless of session model.
GitHub Projects are no longer used in this repo. Remove issue/project
finalization from review-and-merge-pr and the project-board step from
make-closed-issue in all three toolchain mirrors, record the surprise
in known-surprises.md, and regenerate llms files.
Fetch the comment community from the CID payload for initial useComment hints, and redirect directory thread URLs to the authoritative community instead of 404.
Gate document theme and favicon side effects behind GlobalLayout, restore the default favicon after leaving not-found, and treat valid mod and trailing-slash routes as recognized views.
TypeScript 7's own tsc is the Go-native compiler, so the separate tsgo
binary from the dev-preview package is redundant. yarn type-check now
runs tsc --noEmit. Bump tsconfig target to ES2018 and add types: [node]
to fix the pre-existing NodeJS namespace, global, and /s regex flag
errors that stable tsc reports but tsgo did not.
The unmaintained decompress package (<=4.2.1) allows archive extraction
outside the target directory. Migrate electron before-pack to the patched
@xhmikosr/decompress fork (11.1.3) to resolve Dependabot alert #301.
* fix(post ids): never display account identity as a post user id
In per-post pseudonymity mode, local account comment data is overlaid on
published comments so author edit/delete controls keep working, but the
overlay also replaced the displayed User ID with the account author
address in logged-in thread views.
Split the two concerns: getCommentUserID now reads only the published
author.shortAddress, and preservePublishedUserID mirrors the published
ID back onto comments after any local account/edit overlay.
* test(post): cover published user id restore over edited comment overlay
Corrects the react-doctor PR-check command and workflow filename, marks the
superseded hooks-tarball surprises now that bitsocial-react-hooks comes from
npm, rewrites hooks-setup.md around the real per-harness entry points and drops
its drifted inline script copies, points the Task Router translations row at
the translate skill, and adds a committed skills/subagents index so agents can
discover the tooling that already exists.
Claude Code never reads a standalone .claude/hooks.json, so the PostToolUse and
Stop pipeline is moved into .claude/settings.json and hooks.json is removed;
.cursor/hooks.json is rewritten in Cursor's version+afterFileEdit/stop schema;
.codex/hooks.json is already Codex-valid and stays. The shared scripts now
parse both the Cursor file_path and Claude/Codex tool_input.file_path stdin
shapes and normalize absolute paths, so the format, yarn-install, and
react-pattern-review hooks stop being silent no-ops. verify.sh blocks with
exit 2 plus a stderr reason, guards stop_hook_active, and skips clean trees;
react-pattern-review surfaces its reminder via hookSpecificOutput on
PostToolUse; sync-git-branches no longer misreports open PRs as merged. The
validator now checks that the three harness-specific entry points wire the
same hook scripts instead of requiring byte-identical hooks.json copies.
browser-check and profiler get an explicit read-only tools list mirroring the
Codex sandbox_mode, and test-apk no longer hardcodes one contributor's
ANDROID_HOME and project paths.
Fixes deslop diffing against nonexistent main, an invalid rg --type tsx flag
in fix-merge-conflicts, a Codex-specific phrase leaking into the Claude/Cursor
inspect-elements description, and aligns commit-format with the required-scope
convention the commit skill and git history already use. Rewrites the readme
skill from 764 lines of Rails-specific guidance to a lean version matching
this Vite/Capacitor/Electron repo.
* feat(mod queue): transfer posts across boards
* fix(mod queue): polish transfer modal and reason
* fix(mod queue): recover abandoned transfer challenges
* fix(mod queue): address transfer review feedback
* fix(mod queue): hide transfer for unavailable posts
* fix(mod queue): prevent repeat transfer submit
* fix(mod queue): sync transfer state with queue actions
* fix(mod queue): omit transfer temp index
* fix(mod queue): harden transfer failure states
* fix(mod queue): keep hidden transfer lock
* fix(mod queue): release hidden transfer lock
Dragged reply modal positions persist in sessionStorage for the tab and restore on the next desktop open, while mobile viewports still center the modal.
YouTube thumbnail conversion now inserts links at the textarea caret instead of prepending, runs in reply modals even when media links are optional, and preserves the YouTube brand label on desktop posts.
Explain why emoji render as raw Unicode but get no picker, shortcode/emote system, or Twemoji styling: imageboard expressive norms (greentext, reaction images, kaomoji/ASCII art), emoji as an outsider marker, and structural-not-cosmetic differentiation from 4chan. Add the matching DESIGN.md guardrail and regenerate the LLM index.
Enable [code] tag parsing for both /g/ and /q/ rendering paths, show the post-form hint on code-enabled boards, and preserve whitespace in BBCode previews.