Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
cb633da
docs: stop a dead review subagent stalling the self-review loop
vivek7405 Jul 28, 2026
2355981
docs: fix the liveness check to name a mechanism that works
vivek7405 Jul 28, 2026
6b32c9e
docs: name a background reviewer's real status signal, not TaskOutput
vivek7405 Jul 28, 2026
bf3a7e9
docs: close the paths that still stall or pass a non-review as a round
vivek7405 Jul 28, 2026
edf3505
chore: allow the Agent tool so review spawns stop prompting
vivek7405 Jul 28, 2026
f226f41
docs: order the blocked-reviewer rules and drop the stale duplicates
vivek7405 Jul 28, 2026
8eb522c
docs: give the reviewer a way to say it could not review
vivek7405 Jul 28, 2026
0f7fb74
docs: re-spawn a broken reviewer instead of interrupting the user
vivek7405 Jul 28, 2026
a20475f
docs: keep the loop fast and stop restating the review-posting rules
vivek7405 Jul 28, 2026
7c69315
docs: resync the three readers of the re-spawn rule
vivek7405 Jul 28, 2026
65607f8
docs: shape the loop as a parallel fan-out plus delta verification
vivek7405 Jul 28, 2026
d476e63
docs: convert the per-round machinery to the fan-out shape
vivek7405 Jul 28, 2026
544dc2c
docs: close the last two seams in the fan-out conversion
vivek7405 Jul 28, 2026
2c092df
docs: state the delta scope identically in all three places it appears
vivek7405 Jul 28, 2026
f204f87
docs: give the all-rejected round a delta scope too
vivek7405 Jul 28, 2026
65f5cc9
docs: trigger step 3's fallback on the mechanism, not two of its causes
vivek7405 Jul 28, 2026
1b6bd8c
docs: state the no-fix-commits condition mechanism-only, everywhere
vivek7405 Jul 28, 2026
ecf2c42
docs: delta rounds narrow the question, never the evidence
vivek7405 Jul 28, 2026
bbee353
docs: convert step 3 and the intro to the question-evidence model
vivek7405 Jul 28, 2026
97dd65f
docs: scale review depth with risk, richest for shipped source
vivek7405 Jul 28, 2026
06f56b6
docs: single-source the lens list and the fan-out re-run trigger
vivek7405 Jul 28, 2026
3d42859
docs: adversarial refutation, model diversity, and a deep-review tier
vivek7405 Jul 28, 2026
3a6519d
docs: actually commit deep-review, generic and safely spawned
vivek7405 Jul 28, 2026
a19e170
docs: pin two distinct models and fix the workflow's rough edges
vivek7405 Jul 28, 2026
194db5d
docs: pin every deep-review lens, half opus and half fable
vivek7405 Jul 28, 2026
78f9195
docs: let a scout propose dynamic lenses per PR in deep-review
vivek7405 Jul 28, 2026
2b8e100
docs: deep-review is round 1 for every task, no risk bifurcation
vivek7405 Jul 28, 2026
5c4c199
docs: convert the per-round machinery to a workflow-shaped round 1
vivek7405 Jul 28, 2026
99971fb
docs: finish converting the three spawn-era recaps
vivek7405 Jul 28, 2026
5c98045
docs: async reviewer spawns with a transcript watchdog
vivek7405 Jul 28, 2026
360bb5d
docs: watchdog checks the reviewer transcript every 30 seconds
vivek7405 Jul 28, 2026
f9a4cba
docs: one watchdog for both reviewer kinds, with a locatable path
vivek7405 Jul 28, 2026
8dffa7f
docs: use async and multi-agent features across the four heavy skills
vivek7405 Jul 28, 2026
d088e68
docs: the watchdog's mtime probe is meaningless for isolated agents
vivek7405 Jul 28, 2026
99e188a
docs: parallel investigation and verification in the last two skills
vivek7405 Jul 28, 2026
5efc510
docs: two watchdog modes, decided by what the output file is
vivek7405 Jul 28, 2026
71ade5a
docs: the headline promises bounded, not blind-free, like the rules u…
vivek7405 Jul 28, 2026
80b484d
docs: hard-cap deep-review at 24 agents per run
vivek7405 Jul 28, 2026
cd4c685
docs: the args comment and error message name every accepted key
vivek7405 Jul 28, 2026
0869a29
docs: one task per git worktree, always, hook-enforced
vivek7405 Jul 28, 2026
13d709f
fix: the worktree gate now guards subdirectories, not just the root
vivek7405 Jul 28, 2026
43edc48
docs: teardown re-derives its variables, recovery anchors its checkout
vivek7405 Jul 28, 2026
104f392
docs: cap fable-pinned reviewers at three per deep-review run
vivek7405 Jul 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .claude/hooks/require-worktree-for-edits.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
# PreToolUse hook (Write|Edit|MultiEdit|NotebookEdit): BLOCK editing a TRACKED
# file that resides in a repo's PRIMARY checkout. Task work always happens in
# a linked worktree (AGENTS.md: one task per git worktree, ALWAYS); the
# primary checkout stays an untouched mirror of main. Untracked and gitignored
# files (session state, scratch, settings.local.json) stay editable.
# The predicate runs against the FILE's directory, never the session cwd: the
# harness resets cwd to the primary checkout between commands while edits
# legitimately target worktree files by absolute path.
# Contract: exit 0 = allow, exit 2 = block (message on stderr).
# Escape hatch: WEBJS_NO_WORKTREE_GATE=1.

if [ "${WEBJS_NO_WORKTREE_GATE:-0}" = "1" ]; then exit 0; fi
if ! command -v jq >/dev/null 2>&1; then exit 0; fi

input=$(cat)
fp=$(printf '%s' "$input" | jq -r '.tool_input.file_path // .tool_input.notebook_path // empty')
if [ -z "$fp" ]; then exit 0; fi

dir=$(dirname "$fp")
if [ ! -d "$dir" ]; then exit 0; fi
if ! git -C "$dir" rev-parse --is-inside-work-tree >/dev/null 2>&1; then exit 0; fi

# Both paths ABSOLUTE, or the comparison lies: invoked via -C on a SUBDIR of
# the primary, git prints --git-dir absolute and --git-common-dir relative
# (../../.git), so a raw string compare misclassifies the primary as a linked
# worktree and the gate fails open for the whole source tree (caught in
# review; the tests only covered root-level files).
gd=$(git -C "$dir" rev-parse --path-format=absolute --git-dir 2>/dev/null) || exit 0
gcd=$(git -C "$dir" rev-parse --path-format=absolute --git-common-dir 2>/dev/null) || exit 0
if [ -z "$gd" ] || [ -z "$gcd" ]; then exit 0; fi
# Linked worktree: --git-dir carries /worktrees/<name> and differs from the
# common dir. Only the primary checkout has them equal.
if [ "$gd" != "$gcd" ]; then exit 0; fi

# Untracked or gitignored files are session-local and stay editable.
if ! git -C "$dir" ls-files --error-unmatch -- "$fp" >/dev/null 2>&1; then exit 0; fi

top=$(git -C "$dir" rev-parse --show-toplevel 2>/dev/null || echo "this repo")
{
echo "BLOCKED: '$fp' is a tracked file in the PRIMARY checkout ($top)."
echo "Task work always happens in a linked worktree (AGENTS.md: one task per git worktree, ALWAYS):"
echo " git worktree add -b <prefix>/<slug> ../<repo>-<slug> origin/main"
echo "Work there by absolute path; the primary checkout stays on main untouched."
echo "Escape hatch for a deliberate exception: WEBJS_NO_WORKTREE_GATE=1."
} >&2
exit 2
14 changes: 14 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"permissions": {
"allow": [
"Agent"
]
},
"hooks": {
"UserPromptSubmit": [
{
Expand All @@ -11,6 +16,15 @@
}
],
"PreToolUse": [
{
"matcher": "Write|Edit|MultiEdit|NotebookEdit",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/require-worktree-for-edits.sh"
}
]
},
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/webjs-blog-write/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ The test before you ship: read the draft aloud and ask whether the author would
## Process: from topic to a published, true post

1. **Pick an SEO topic backed by shipped work.** Mine the git history, the merged PRs, the per-package changelog, and the closed issues for a real, shipped capability that a developer would search for and that no existing post already covers. High-intent angles (migration from another framework, a concrete how-to) rank best.
2. **De-duplicate against EVERY existing post, directly AND indirectly.** Read the titles and skim the bodies of all `blog/*.md`. A new post must not restate a published one, even partially. If two candidate topics overlap, either merge them or sharpen each to a distinct angle and cross-link rather than repeat. Two posts that share a mechanism should each own a different facet and reference the other, not re-explain it.
3. **For a feature post, verify every factual claim by dogfooding before you publish.** This is not optional for a post that describes runtime behaviour. Scaffold a real app (`webjs create`), boot it (on Node AND Bun where the claim is runtime-sensitive), and confirm each claim with a real probe: `curl` for HTTP and header behaviour, a browser for hydration, streaming, client-router, and a11y. If a claim turns out false, FIX the post to state the truth, and file a framework issue via `webjs-file-issue` if the framework itself is wrong. A blog post that states a behaviour the framework does not have is the failure this step exists to prevent. Do not report a post done off unverified claims.
2. **De-duplicate against EVERY existing post, directly AND indirectly.** Delegate the sweep to one read-only `Explore` agent over `blog/*.md` returning per-post topic-and-angle summaries (the corpus is small, so the win is keeping your context clean rather than parallelism), then judge overlap yourself against its return. A new post must not restate a published one, even partially. If two candidate topics overlap, either merge them or sharpen each to a distinct angle and cross-link rather than repeat. Two posts that share a mechanism should each own a different facet and reference the other, not re-explain it.
3. **For a feature post, verify every factual claim by dogfooding before you publish.** This is not optional for a post that describes runtime behaviour. Scaffold a real app (`webjs create`) and run the verification's independent parts as ONE batch of background Bash tasks: the Node boot and the Bun boot in parallel (BOTH stay mandatory where a claim is runtime-sensitive, one never satisfies the other), with the per-claim `curl` probes against whichever boot they need, and EVERY task's result collected before the post is called verified, since a forgotten background probe is an unverified claim shipping. Browser-dependent probes (hydration, streaming, client-router, a11y) stay in the main session, where the browser tooling lives. Confirm each claim with a real probe: `curl` for HTTP and header behaviour, a browser for hydration, streaming, client-router, and a11y. If a claim turns out false, FIX the post to state the truth, and file a framework issue via `webjs-file-issue` if the framework itself is wrong. A blog post that states a behaviour the framework does not have is the failure this step exists to prevent. Do not report a post done off unverified claims.
4. **Write the post** in the voice from Step 0, obeying the hard rules.
5. **Place the file** at repo-root `blog/<slug>.md`. Do not put it under `website/`. Confirm the front matter has `title` and `date` (the index drops files missing either).
6. **Self-check before committing.** Grep your own draft: `grep -nE '#[0-9]{3,4}' blog/<slug>.md` must return nothing, and scan for process tells ("dogfood", "self-review", "verified by"). Confirm no em-dash or banned pause punctuation. Read the whole post once as a reader who has never seen the codebase.
Expand Down
4 changes: 4 additions & 0 deletions .claude/skills/webjs-doc-sync/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ applies, then update or consciously skip each.

## Per-change sync procedure

The surface checks below are independent reads, so run them fanned out: one read-only `Explore` agent per doc surface, spawned in ONE message, each answering "does this surface describe the changed behavior, and does it still tell the truth at head?". The agents REPORT; the edits stay in the main session, because parallel writers on overlapping docs collide. A single-surface change needs no fan-out.

1. Identify the change's IDENTIFYING TOKENS: the export name, CLI flag, config
key, file-convention string, or feature phrase a doc would mention.
2. Grep those tokens across every surface to see where the feature is (or should
Expand All @@ -103,6 +105,8 @@ applies, then update or consciously skip each.

## Audit-mode procedure (sweep shipped work for drift)

An audit is the fan-out's best case: every surface of the map gets its own read-only `Explore` agent, all spawned in one message, so the sweep costs the slowest surface rather than the sum. Reads fan out, writes stay here.

Use this to find existing gaps (for example, across the Done items on the project
board):

Expand Down
2 changes: 2 additions & 0 deletions .claude/skills/webjs-file-issue/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ If the user's description is very thin (e.g. "track adding dark mode as a todo")

A few greps now save the implementing agent a cold-start investigation later, and the difference is visible in the filed issue.

**For an issue touching more than one area, fan the grounding out instead of hunting serially.** The four collections above are independent reads, so spawn parallel READ-ONLY `Explore` agents in ONE message, one per concern (where-to-edit paths; landmines via `git log` and prior-issue search; invariants from AGENTS.md; test and doc surfaces), then synthesize their returns into the Implementation-notes section yourself. Explore agents cannot write, which is the point: nothing edits the repo mid-filing. Inline grounding stays fine for a small single-area issue. Either way the gate is unchanged: a body that fails the cold-start test is unready, however it was researched.

**Cold-start test, apply it to your own draft before filing.** Reread the body as if you had never seen this conversation. Could you start work from it alone, without asking a single clarifying question and without first having to find where the relevant code lives? If not, it is not ready. Two concrete failure signs: the body names an area ("the router", "the prefetch logic") rather than a path, or it describes the symptom without saying where the fix goes.

The user should never have to ask for this. If they do, the skill was not followed.
Expand Down
17 changes: 12 additions & 5 deletions .claude/skills/webjs-instagram-post/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,12 @@ only has to exist for that one call, then it is deleted.
```sh
SLUG=works-without-javascript # match the post topic
BR=chore/ig-social-$SLUG
git worktree add -b "$BR" ../webjs-ig-social origin/main
mkdir -p ../webjs-ig-social/website/public/social
cp "$OUT" ../webjs-ig-social/website/public/social/$SLUG.jpg
( cd ../webjs-ig-social
PRIMARY=$(git worktree list --porcelain | sed -n 's/^worktree //p' | head -1) # every path below roots here, so nothing nests under a task worktree or lands beside the session cwd (sed, not awk: awk splits a path containing spaces)
git -C "$PRIMARY" worktree add -b "$BR" ../webjs-ig-social origin/main
IG="$PRIMARY/../webjs-ig-social"
mkdir -p "$IG/website/public/social"
cp "$OUT" "$IG/website/public/social/$SLUG.jpg"
( cd "$IG"
git add website/public/social/$SLUG.jpg
git commit -q -m "chore: add $SLUG Instagram social card asset"
git push -q -u origin "$BR" )
Expand All @@ -126,7 +128,12 @@ IMG="https://raw.githubusercontent.com/webjsdev/webjs/$BR/website/public/social/
After the post is published in Step 4, tear the branch down so nothing lingers:

```sh
git worktree remove ../webjs-ig-social --force
# Shell state does NOT survive across tool calls, and Step 4's user
# confirmation sits between setup and here, so re-derive BOTH variables
# (an empty $PRIMARY silently degrades `git -C ""` to cwd-relative).
PRIMARY=${PRIMARY:-$(git worktree list --porcelain | sed -n 's/^worktree //p' | head -1)}
BR=${BR:-chore/ig-social-<slug>} # fill the slug if the variable is gone
git -C "$PRIMARY" worktree remove ../webjs-ig-social --force
git branch -D "$BR"
git push origin --delete "$BR"
```
Expand Down
4 changes: 4 additions & 0 deletions .claude/skills/webjs-research-record/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ The framework's reference docs (the skill at `.agents/skills/webjs/`) exist ONLY

A research record has **no code diff**. A PR is a "merge this diff" object, so a research PR needs an empty-commit hack and leaves a dangling branch behind (see the now-deleted branch from #559). An issue is the native home for a writeup with threaded discussion. It is filterable by the `research` label, and it fits the project model where the GitHub Project board backed by issues is the source of truth. Earlier records used closed PRs (#546, #553); the convention going forward is a labeled issue. Do not convert the old PRs unless asked.

## Investigate in parallel

A comparison or options analysis is multi-angle work, and each angle is an independent read: one option's codebase evidence, the prior art, the project's own constraints in AGENTS.md, what the ecosystem does. For a multi-option or multi-angle investigation, spawn one read-only `Explore` agent per option or angle in ONE message, each returning evidence with concrete file paths and citations, then synthesize yourself. Reads fan out; the writeup and its judgment stay with you, because the record's voice and conclusions are the caller's, not an agent vote. A single-question spike needs no fan-out. Nothing here changes WHERE the record lands (the closed `research`-labeled issue below).

## Lifecycle: backlog item then findings in the SAME issue

Research often starts as a planned **backlog item**, an OPEN `research`-labeled issue ("research whether X") sitting in the board's Todo column. When an agent actually does the research, the findings go into **that same issue**, NOT a new PR:
Expand Down
4 changes: 4 additions & 0 deletions .claude/skills/webjs-scaffold-sync/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ it applies, then update or consciously skip each.

## Per-change sync procedure

Run the mandatory generate + boot + check verifications in PARALLEL when more than one template is affected: each verification is its own background Bash task, launched in one batch, with EVERY task's result collected before the sync is declared done (a forgotten background boot is a silently unverified template). Prefer the in-process harness (`createRequestHandler` + `Request` objects, the dogfood boot-check pattern in the start-work skill): it binds no port, so parallel runs cannot collide. When a real `webjs dev` listen is unavoidable, give each boot a distinct `--port`.

1. Identify the change's IDENTIFYING TOKENS: the demo route (`app/features/<x>`,
`app/api/features/<x>`), the template name, the generated file path, the
convention phrase, or the scoping phrase (e.g. "full-stack only").
Expand Down Expand Up @@ -213,6 +215,8 @@ it applies, then update or consciously skip each.

## Audit-mode procedure (sweep the scaffold for drift)

Fan the sweep out like the doc-sync audit: one read-only `Explore` agent per surface of the map, spawned in one message; the agents report and the edits stay in the main session.

1. List the shipped scaffold changes (new demos, new template, scoping changes,
changed generated files).
2. For each, pull its tokens and run the surface grep above.
Expand Down
Loading
Loading