Skip to content

Commit 3a0790c

Browse files
committed
feat!: macro attrs, trait refinements, redis TLS split, store APIs (next major)
Next-major batch (after the redb DiskCache rewrite). Bundles a set of breaking and additive changes plus the doc/test follow-ups. Macros: - `ttl_millis` attribute for sub-second TTLs, mutually exclusive with `ttl` (#149); rejected alongside a `create` block like the other store-builder attributes - `force_refresh` attribute to bypass the cache per call, on all three macros (`#[cached]` / `#[concurrent_cached]` / `#[once]`); on `#[once]` it overwrites the single shared value (no per-call key, so no key-exclusion caveat). Combined with `result_fallback`, a force-refreshed `Err` still serves the previously cached `Ok`, and capturing that fallback leaves no read side effects on the bypassed entry (no TTL renewal, recency update, or hit-counter change) on both `#[cached]` and `#[concurrent_cached]` (#146) - `in_impl` attribute to cache methods inside `impl` blocks; `self`-receiver methods require `in_impl` (a `convert` block alone cannot rescue them, since the cache static cannot live at `impl` scope) and emit a `{fn}_no_cache` cache-bypass sibling, hidden from rustdoc via `#[doc(hidden)]` (#16, #140) - reference arguments (`&T`, `Option<&T>`) form the default key without `convert` (#202, #203) - generated code resolves the crate path via `proc-macro-crate`, so a renamed or re-exported `cached` dependency works (#157) - macro-introduced bindings are hygienically named, so arguments named `key` / `cache` / `result` no longer collide with generated code (#230, #114) - clear compile error for generic functions used without `key` + `convert` (#80) - the shared `force_refresh` guard builder is factored into one helper Traits and stores: - `get_or_set_with` / `try_get_or_set_with` (and the async variants) now return `&V` instead of `&mut V`, with new `*_mut` variants preserving the old behavior (#179) - new additive `SerializeCached` / `SerializeCachedAsync` traits (`cache_set_ref`) for serialize-backed stores; `#[concurrent_cached]` routes its set through an autoref shim that uses the borrowed setter for any store implementing the trait (built-in redis/disk or a custom `ty`/`create` store), avoiding a value clone (#196, #195) - `RedisCache` / `AsyncRedisCache` gain `cache_clear` / `async_cache_clear`, with `cache_reset` delegating to `cache_clear`; `RedisCacheBuilder` / `AsyncRedisCacheBuilder` `build()` reject an empty namespace+prefix scope (`EmptyScope`) so `cache_clear` cannot `SCAN MATCH *` the whole database (#200) - `RedbCacheBuilder::build()` validates `cache_name` as a filename component, returning `InvalidCacheName` for a path separator (`/` or `\`) or a path-traversal component (`.` / `..`) - `LruCache::set_max_size` / `try_set_max_size` for resizing a live cache, with matching methods on `LruTtlCache` and `ExpiringLruCache` (#180) - `ConcurrentCloneCached` gains a non-renewing `cache_peek_with_expiry_status` (used to capture a `result_fallback` stale value without read side effects) Redis: - TLS features split so rustls is selectable; `redis_tokio` / `redis_smol` no longer imply native-tls (add `*_native_tls` or `*_rustls`) (#231) Docs and process: - document floats as the canonical `convert` case (#78); add cache-invalidation and struct-method examples (#21, #236), the latter demonstrating `in_impl` - release workflow tags and creates a GitHub release for each published workspace crate on publish, via `bin/tag-release.sh` (root `cached` -> `vX.Y.Z`, subcrates -> `<crate-name>-vX.Y.Z`) (#245); the CI tag-release git identity is scoped to `--local` - fix a doctest under `--no-default-features` (#260) - exclude internal dev tooling (.agents, .claude, .github, bin, docs/dev, AGENTS.md, CLAUDE.md) from the published crate via Cargo `exclude` - dev tooling: pr-review shards reviewers across model-sized, randomized chunks (multiple of each type); pr-cycle fans fix application across disjoint sub-agents; AGENTS.md states README is generated from src/lib.rs via cargo-readme - documentation accuracy pass: `ttl_millis` is valid with `result_fallback` and (on the in-memory path) needs `time_stores`; on `#[cached]` the "honored exactly" claim is scoped to the default in-memory store; Redis rounds `ttl_millis` up to the next whole second (500ms -> 1s, 1500ms -> 2s); `in_impl` emits a `#[doc(hidden)]` `{fn}_no_cache` sibling (documented on all three macros); `#[concurrent_cached]` `force_refresh` documents the `result_fallback` interaction; the `#[concurrent_cached]` attribute table reaches parity with `#[cached]` (ttl_millis / force_refresh / in_impl rows); wasm is incompatible with `redis_connection_manager` / `redis_async_cache`; the `in_impl` shared-cache footgun; the async `V: Sync` clone-elision asymmetry, including how a `Send + !Sync + !Clone` value surfaces at the generated set site; `CachedAsync` shared-ref default Send bounds; `Cached::cache_get_or_set_with` / `cache_try_get_or_set_with` flagged as provided defaults; migration-guide `&mut V` -> `&V` coercion caveat - added coverage: async clone-elision clone-count assertions; `#[concurrent_cached]` `result_fallback` + `force_refresh` (including the no-read-side-effects bypass); `#[once]` `force_refresh`; `force_refresh` + `in_impl`; generic `in_impl` rejection goldens for `#[cached]` (free fn) and `#[concurrent_cached]` (in_impl method); compile-fail goldens for `force_refresh`-unparseable on `#[once]` / `#[concurrent_cached]`, generic `#[concurrent_cached]` without `convert`, and `ttl_millis` + `create` conflict; `_mut` trait coverage on `ExpiringCache` / `TtlSortedCache`; redis `cache_clear` / `cache_set_ref` and redb `cache_set_ref` round-trips; `TtlSortedCache` shared-ref get-or-set delegation - macro-output polish: ASCII-only macro diagnostics; no dead `#[doc]` on the function-local `in_impl` cache static; documented rationale for `#[allow(dead_code)]` on the generated prime companion and for the `crate_path()` `::cached` fallback See docs/migrations/2.0-to-unreleased.md and the CHANGELOG for migration details.
1 parent 35d07c3 commit 3a0790c

114 files changed

Lines changed: 7052 additions & 715 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/skills/pr-cycle/SKILL.md

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ judgment core and push everything else to cheaper models or to no model at all.
6464
| Tier | What | Steps | Model |
6565
|------|------|-------|-------|
6666
| 0 — mechanical | All GitHub API ops, `make ci`, README regen, push preamble | 1, 5, 6, 8(preamble), 9, 10 | script (`pr.py`) |
67-
| 1 — cheap delegation | Local review via `pr-review` (read-only sub-agents); mechanical/repetitive fix application | 2, 4b, 11 | Sonnet (pinned in agent def; review sub-agents overridable per-run, e.g. to opus — see [Input](#input)) |
68-
| 2 — judgment core | Classify findings; write explicit fix specs + test assertions; sync audit | 3, 4a, 7 | Opus (session model) |
67+
| 1 — cheap delegation | Local review via `pr-review` (read-only sub-agents); fix application, fanned out across disjoint sub-agents | 2, 4b, 11 | Sonnet by default; per-group `model` override to Opus for harder groups (see 4b); review sub-agents overridable per-run (see [Input](#input)) |
68+
| 2 — judgment core | Classify findings; write explicit fix specs + test assertions; partition the fan-out; sync audit | 3, 4a, 7 | Opus (session model) |
6969

7070
A Sonnet session can drive the whole cycle; only Tier-2 actually needs strong
7171
reasoning, so consider switching the session to a cheaper model once the judgment
@@ -107,8 +107,9 @@ review-agent model override from the Input if one was given. `pr-review` will:
107107

108108
- acquire the diff (`.agents/skills/pr-cycle/pr.py PR_NUMBER diff`, equivalent to
109109
`git diff origin/master`),
110-
- spawn `pr-code-reviewer` and `pr-consumer-reviewer` in parallel (read-only, each
111-
carrying its own rubric; Sonnet by default, or the overridden model on **both**
110+
- shard the changed material into appropriately sized, randomized chunks and spawn one
111+
`pr-code-reviewer` and one `pr-consumer-reviewer` per shard in parallel (read-only,
112+
each carrying its own rubric; Sonnet by default, or the overridden model on **all**
112113
spawns), and
113114
- return a consolidated findings report with severity and a per-finding verdict.
114115

@@ -157,19 +158,46 @@ Common fix types:
157158
- Trybuild golden file regeneration: `TRYBUILD=overwrite cargo test --no-default-features --features "proc_macro,time_stores" compile_fail_macro_arg_validation`
158159
- Macro code changes: `cached_proc_macro/src/`
159160

160-
#### 4b. Apply fixes (route per fix)
161-
162-
For each spec, choose the routing:
163-
164-
- **Delegate to `pr-fix-implementer` (Sonnet)** when the fix is **mechanical or
165-
repetitive across multiple files** (e.g. the same change in all six sharded stores,
166-
a doc-string pattern replicated across store modules). State "delegating because:
167-
<reason>". Spawn the `pr-fix-implementer` agent with the fix spec as the prompt.
168-
- **Apply inline** when the fix is **a one-off, subtle, or logic/macro change**.
169-
For small one-off edits the spec-writing + verification round-trip costs more than
170-
editing directly. State "applying inline because: <reason>".
171-
172-
After all fixes are applied, verify with:
161+
#### 4b. Partition the fixes and fan out across disjoint sub-agents
162+
163+
Once every valid finding has a spec, apply them by **fanning out across as many
164+
parallel sub-agents as the specs allow**, rather than applying them serially in the
165+
orchestrator. Two rules govern the fan-out:
166+
167+
**Disjoint partitioning (correctness).** Parallel agents share one working tree, so two
168+
agents must never write the same file — concurrent edits to one file race and corrupt
169+
each other. Partition the specs into groups whose **written-file sets do not overlap**:
170+
171+
- For each spec, compute the full set of files it writes — the Target file(s) *and* the
172+
test file its Test clause adds to (often `tests/cached.rs`).
173+
- Any two specs that share a written file MUST land in the same group. A common sink
174+
like `tests/cached.rs` therefore pulls every test-adding spec into one group — that is
175+
expected; keep that group together rather than risking a race.
176+
- Otherwise split into as many groups as possible — ideally one spec per group — to
177+
maximize parallelism. More disjoint groups means more concurrency.
178+
179+
**Appropriate model per group (cost).** Each group is handled by a `pr-fix-implementer`
180+
agent spawned with the Agent tool's `model` parameter set to the tier the group's
181+
*hardest* fix needs:
182+
183+
- `model: sonnet` (the agent's default) — mechanical or repetitive groups: doc/comment
184+
updates, a pattern replicated across the sharded stores, golden-file regen, simple
185+
test additions.
186+
- `model: opus` — groups containing a subtle logic change, a macro change in
187+
`cached_proc_macro/src/`, or any fix whose application still needs real reasoning. The
188+
spec from 4a is already precise enough to hand off (it must be, to be valid); raising
189+
the implementer's model buys more careful application, not more decision latitude.
190+
191+
Spawn all groups **in a single message** (multiple Agent calls) so they run concurrently.
192+
Each agent's prompt is the verbatim fix spec(s) for its group. Before spawning, state the
193+
partition: list each group, the files it owns, its model, and why that model.
194+
195+
**Inline fallback.** Skip the fan-out and edit directly only in the degenerate case where
196+
it cannot pay off: a single spec, or a few tiny one-off edits that all touch one
197+
overlapping region (so they cannot be partitioned anyway). State "applying inline because:
198+
<reason>".
199+
200+
After all agents report back, verify with:
173201

174202
```bash
175203
.agents/skills/pr-cycle/pr.py PR_NUMBER ci

.agents/skills/pr-review/SKILL.md

Lines changed: 91 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: pr-review
3-
description: Targeted, read-only review of a PR or checked-out branch. Acquires the diff (a PR number, or the current branch vs origin/master), spawns an independent code-review sub-agent and a library-consumer sub-agent in parallel, then aggregates their findings into a single report with severity and a valid / already-fixed / invalid verdict for each. Read-only — it does not edit files, commit, push, or touch the GitHub PR conversation. The review sub-agents default to Sonnet but can be overridden per run (e.g. to opus). Use when asked to "review this PR", "review the branch", "what's wrong with this diff", "do a code review", or "review with opus". For the full review → fix → push → resolve loop, use `pr-cycle` (which delegates its review step here).
3+
description: Targeted, read-only review of a PR or checked-out branch. Acquires the diff (a PR number, or the current branch vs origin/master), shards the changed material into appropriately sized, randomized chunks, and spawns multiple read-only code-review and library-consumer sub-agents in parallel (one per shard), then aggregates and de-duplicates their findings into a single report with severity and a valid / already-fixed / invalid verdict for each. Read-only — it does not edit files, commit, push, or touch the GitHub PR conversation. The review sub-agents default to Sonnet but can be overridden per run (e.g. to opus). Use when asked to "review this PR", "review the branch", "what's wrong with this diff", "do a code review", or "review with opus". For the full review → fix → push → resolve loop, use `pr-cycle` (which delegates its review step here).
44
allowed-tools: Bash, Read, Agent
55
---
66

@@ -13,8 +13,9 @@ findings, then goes on to address, push, and resolve them.
1313

1414
## Scope — what this does and does not do
1515

16-
**Does:** acquire the diff, spawn the two read-only review sub-agents, evaluate
17-
their findings, and report them with severity and a verdict.
16+
**Does:** acquire the diff, shard it into appropriately sized chunks, spawn the
17+
read-only review sub-agents (one per shard, multiple of each type), evaluate and
18+
de-duplicate their findings, and report them with severity and a verdict.
1819

1920
**Does NOT:** edit files, run `make ci`, regenerate the README, commit, or push; and
2021
it does **not** interact with the GitHub PR conversation — it does not read existing
@@ -29,8 +30,8 @@ This skill is purely advisory: its output is a findings report for a human (or f
2930

3031
| Tier | What | Step | Model |
3132
|------|------|------|-------|
32-
| 1 — cheap delegation | Read-only review sub-agents | 2 | Sonnet (pinned in agent def; overridable per-run, e.g. to opus — see [Input](#input)) |
33-
| 2 — judgment core | Classify findings into valid / already-fixed / invalid | 3, 4 | session model (use Opus for the verdict pass) |
33+
| 1 — cheap delegation | Read-only review sub-agents, one per shard | 3 | Sonnet (pinned in agent def; overridable per-run, e.g. to opus — see [Input](#input)) |
34+
| 2 — judgment core | Shard the material; de-duplicate and classify findings into valid / already-fixed / invalid | 2, 4, 5 | session model (use Opus) |
3435

3536
## Input
3637

@@ -41,63 +42,116 @@ A target and an optional review-agent model override, in any order.
4142
`gh pr view --json number` (run with the sandbox disabled — see below), but a PR is
4243
**not required**: a plain checked-out branch is reviewed by diffing against
4344
`origin/master`.
44-
- **Review-agent model**: the model used by the two sub-agents (`pr-code-reviewer`,
45+
- **Review-agent model**: the model used by the two reviewer types (`pr-code-reviewer`,
4546
`pr-consumer-reviewer`) **defaults to `sonnet`**, but can be overridden. If the input
4647
names a model (e.g. "review with opus", "opus reviewers", "model=opus"), pass that
47-
model to the Agent tool's `model` parameter when spawning **both** sub-agents in
48-
step 2. With no override, omit `model` so each agent uses its pinned Sonnet default.
48+
model to the Agent tool's `model` parameter when spawning **all** shard sub-agents in
49+
step 3. With no override, omit `model` so each agent uses its pinned Sonnet default.
50+
- **Shard sizing (optional)**: by default the orchestrator sizes shards automatically
51+
from the review-agent model — smaller shards for cheaper models, larger for stronger
52+
ones (see step 2). Override with an explicit target in the input if you want finer or
53+
coarser splitting, e.g. "shards of ~4 files", "one file per shard", or "single shard"
54+
(the latter restores the old whole-diff-per-reviewer behavior).
4955

5056
Announce the resolved target and review-agent model at the start — e.g. "Reviewing
5157
the current branch with **opus** reviewers" or "Reviewing PR #264 with Sonnet
52-
reviewers" — before spawning anything.
58+
reviewers" — before spawning anything. After sharding (step 2), announce the shard
59+
counts (e.g. "3 code shards, 2 consumer shards") before spawning the reviewers.
5360

5461
## Steps
5562

56-
### 1. Acquire the diff
63+
### 1. Acquire the diff and build the review inventory
5764

5865
The diff is `git diff origin/master`, which works for any checked-out branch whether
5966
or not it has a PR:
6067

6168
```bash
6269
git diff origin/master
70+
git diff origin/master --stat
6371
```
6472

6573
If you are targeting a specific PR, the `pr-cycle` helper prints the identical diff
66-
and is equivalent:
74+
and is equivalent (`.agents/skills/pr-cycle/pr.py PR_NUMBER diff`).
6775

68-
```bash
69-
.agents/skills/pr-cycle/pr.py PR_NUMBER diff
70-
```
76+
From the changed-file list, build an inventory of **review units**. A unit is normally
77+
one changed file, with one exception: keep **atomic couplings** together as a single
78+
unit — a trybuild `tests/ui/<case>.rs` and its matching `<case>.stderr` (and any paired
79+
source) must travel together, since reviewing one without the other is meaningless.
80+
81+
Tag each unit with the reviewer type(s) it needs:
82+
- **Code-review set** — all code: `cached_proc_macro/src/`, `src/`, `tests/`, examples.
83+
Essentially every changed `.rs` file and golden file.
84+
- **Consumer-review set** — public-facing surface only: `src/lib.rs`, the public APIs in
85+
`src/stores/`, `cached_proc_macro/src/lib.rs` (the macro attribute surface),
86+
`README.md`, `CHANGELOG.md`, `docs/migrations/`, and `examples/`. Internal macro
87+
plumbing and internal test helpers are not consumer-relevant.
88+
89+
A unit may belong to both sets (e.g. `src/lib.rs`).
90+
91+
### 2. Shard each set into appropriately sized, randomized chunks
7192

72-
Capture the full diff text — it is fed verbatim to both sub-agents.
93+
The code set and the consumer set are sharded **independently**. Sharding has two jobs:
94+
keep each shard small enough that the review model attends to every line, and vary the
95+
grouping between rounds so repeated reviews surface different findings.
7396

74-
### 2. Spawn two independent sub-agents in parallel
97+
**a. Pick the target shard size from the review-agent model.** Cheaper models get
98+
smaller shards; stronger models absorb more per shard without losing attention:
7599

76-
**Agent A — code reviewer**: Spawn with the `pr-code-reviewer` agent type. Prompt must
77-
include:
78-
- The PR number (or branch name, if there is no PR)
79-
- The full diff (from step 1)
100+
| Review model | Target per shard |
101+
|--------------|------------------|
102+
| sonnet (default) | ~600-900 changed diff lines, or ~4-6 units |
103+
| opus | ~1500-2500 changed diff lines, or ~10-15 units |
80104

81-
**Agent B — library consumer**: Spawn with the `pr-consumer-reviewer` agent type. Prompt
82-
must include:
83-
- The PR number (or branch name)
84-
- The full diff
85-
- The current `src/lib.rs` doc comments and `README.md` (or relevant excerpts covering
86-
the changed APIs)
105+
An explicit shard-size override from the Input wins over this table. Use the
106+
`--stat` line counts from step 1 for packing.
107+
108+
**b. Randomize the grouping, then pack.** Produce a fresh random ordering of the units
109+
each run — `shuf` reseeds from the OS on every invocation, so each round yields a
110+
different permutation:
111+
112+
```bash
113+
git diff origin/master --name-only | shuf
114+
```
87115

88-
Both agents are read-only (no Edit/Write tools) and carry their full rubrics in their
116+
Pack the shuffled unit list greedily: add units to the current shard until adding the
117+
next would exceed the target size, then start a new shard. Because the order is
118+
reshuffled every round, a given file lands with different neighbors each time — reviewers
119+
see different cross-file context and surface different cross-cutting findings. Do **not**
120+
re-sort the shuffled list into a tidy order; the randomness is the point. (Atomic
121+
couplings from step 1 stay intact as one unit through the shuffle.)
122+
123+
This yields some number of code shards and consumer shards (each typically a handful).
124+
Announce the counts before spawning.
125+
126+
### 3. Spawn one sub-agent per shard, in parallel
127+
128+
For each **code shard**, spawn a `pr-code-reviewer`. For each **consumer shard**, spawn a
129+
`pr-consumer-reviewer`. Every agent's prompt must include:
130+
- The target (PR number, or branch name if there is no PR)
131+
- The explicit list of files in its shard
132+
- An instruction to **scope its review to those files**: acquire its slice with
133+
`git diff origin/master -- <files...>` and Read those files in full for context, but
134+
report findings only on the assigned files.
135+
- (consumer shards only) a pointer to the current `src/lib.rs` doc comments and
136+
`README.md` for the APIs its files touch.
137+
138+
Both agent types are read-only (no Edit/Write) and carry their full rubrics in their
89139
agent definitions — do not re-specify the rubric in the prompt.
90140

91141
**Model override:** if the input requested a review-agent model (see [Input](#input)),
92-
pass it to the Agent tool's `model` parameter on **both** spawns (e.g. `model: "opus"`).
142+
pass it to the Agent tool's `model` parameter on **every** spawn (e.g. `model: "opus"`).
93143
With no override, omit `model` so each agent uses its pinned Sonnet default.
94144

95-
Launch both agents in parallel. Wait for both to complete before proceeding.
145+
Spawn **all** shard agents in a single message so they run concurrently, and wait for all
146+
to complete before proceeding. (Harness concurrency is capped; excess agents queue and
147+
still complete.)
96148

97-
### 3. Evaluate all findings
149+
### 4. Evaluate all findings (de-duplicate across shards)
98150

99-
Collect both sub-agent reports. For each finding, assign a verdict and explain your
100-
reasoning:
151+
Collect every shard's report. Shards are disjoint, so most findings are unique, but a
152+
cross-cutting issue can be reported by more than one shard (or by both a code and a
153+
consumer reviewer) — **merge duplicates into one finding** before judging. For each
154+
finding, assign a verdict and explain your reasoning:
101155

102156
- **Valid** — the concern is real and the code should change.
103157
- **Already fixed** — the concern was valid in principle but the current code already
@@ -110,13 +164,15 @@ This verdict pass is the judgment core; run it on the session model (use Opus).
110164
soften or pad — an invalid finding called valid sends `pr-cycle` (or a human) chasing a
111165
non-issue.
112166

113-
### 4. Report
167+
### 5. Report
114168

115169
Present a single consolidated report:
116170

117171
- The target reviewed (PR number or branch name) and the review-agent model used.
118-
- **Code-reviewer findings**: total count, broken down by severity (high / medium / low),
119-
and by verdict (valid / already-fixed / invalid).
172+
- **Sharding**: how many code shards and consumer shards ran, and the target shard size
173+
used.
174+
- **Code-reviewer findings**: total count (after de-dup), broken down by severity
175+
(high / medium / low), and by verdict (valid / already-fixed / invalid).
120176
- **Consumer-reviewer findings**: the same breakdown.
121177
- For each **valid** finding: a one-line summary, the `file:line` (or area), and why it
122178
matters — enough that `pr-cycle` or a human can act on it without re-reading the agent

.github/workflows/release.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,23 @@ jobs:
1010
environment: release # Optional: for enhanced security
1111
permissions:
1212
id-token: write # Required for OIDC token exchange
13+
contents: write # Required for pushing tags and creating GitHub releases
1314
steps:
1415
- uses: actions/checkout@v6
16+
with:
17+
fetch-depth: 0 # Full history needed so tag push has full context
1518
- uses: rust-lang/crates-io-auth-action@v1
1619
id: auth
1720
- name: Publish to crates.io
21+
id: publish
1822
run: bash bin/publish.sh
1923
env:
2024
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
25+
- name: Tag and create GitHub releases
26+
# Tags every workspace crate whose version is newly published; idempotent
27+
# (skips tags that already exist on the remote).
28+
if: steps.publish.outcome == 'success'
29+
env:
30+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31+
run: bash bin/tag-release.sh
2132

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ _tmp_readme.md
77
local/
88
!local/.gitkeep
99
.antigravitycli/
10+
.claude/worktrees/

0 commit comments

Comments
 (0)