Commit Graph

4 Commits

Author SHA1 Message Date
Garry Tan
8ab733471b v0.41.17.0 feat: --workers N on every bulk command + facts dim doctor parity (#1519)
* feat(worker-pool): shared sliding pool + bounded semaphore + PGLite-clamp wrapper

T1 + T2 of the v0.41.16.0 workers cathedral. New src/core/worker-pool.ts is
the canonical primitive every --workers N bulk command in this wave (and
future bulk commands) builds on. Atomic-claim invariant enforced by
scripts/check-worker-pool-atomicity.sh (wired into bun run verify).
BudgetExhausted bypass + AbortSignal composition baked into the helper so
budget caps are a structural ceiling under concurrency, not a per-caller
convention.

The new resolveWorkersWithClamp wrapper composes existing autoConcurrency
with PGLite-clamp + per-(command, requested) stderr dedup. Deliberately
NOT a modification to shared autoConcurrency (silent today, used by sync
+ import); embed.ts keeps GBRAIN_EMBED_CONCURRENCY || 20 default per
codex #13.

23 + 12 + 9 = 44 hermetic tests pin every contract.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: structural + dim-check regression suites for v0.41.16.0 wave

- test/embed-helper-migration.test.ts (T3): asserts embed.ts's two
  sliding-pool sites are migrated to runSlidingPool, pre-migration
  shapes (let nextIdx = 0, Promise.all(Array.from(...))) are gone,
  GBRAIN_EMBED_CONCURRENCY || 20 default preserved, failureLabel
  threads page.slug. Per codex #16/#17 these are invariant assertions,
  not byte-equality on progress event ORDERING.
- test/embedding-dim-check-facts.test.ts (T6): readFactsEmbeddingDim
  covers vector(N) + halfvec(N), halfvec-before-vector regex ordering
  pinned (codex #19), buildFactsAlterRecipe emits DROP INDEX + ALTER
  USING + CREATE INDEX (codex #18, not bare REINDEX),
  FactsEmbeddingDimMismatchError tagged class shape,
  assertFactsEmbeddingDimMatchesConfig PGLite skip + Postgres absent-
  column skip, doctor check + insert-cast wiring assertions.
- test/extract-conversation-facts-workers.test.ts (T5): helper
  exports (extractConversationFactsLockId, PER_PAGE_LOCK_TTL_MINUTES),
  structural wiring (runSlidingPool, resolveWorkersWithClamp,
  withRefreshingLock, LockUnavailableError, delete-orphans-first
  before segment loop, preflight before pool, exit 3 when lock_skipped
  > 0), Minion handler round-trip.
- test/extract-workers.test.ts (T7): --workers wiring on all 3 inner
  fs-walk loops (extractForSlugs, extractLinksFromDir,
  extractTimelineFromDir) + CLI parse + opts threading through
  runExtractCore.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: rebump v0.41.16.0 → v0.41.17.0 (queue collision with PR #1510)

PR #1510 (garrytan/dynamic-regex-conversation-formats) claimed v0.41.16.0
on master in parallel. Advancing this wave to v0.41.17.0 so both can land
cleanly. Pure mechanical version bump:

- VERSION + package.json → 0.41.17.0
- CHANGELOG.md header + "To take advantage of v0.41.17.0" block
- TODOS.md section header + v0.41.18+ forward references
- CLAUDE.md inline version tags
- Regenerated llms-full.txt / llms.txt

No code changes. The actual workers cathedral feature set is unchanged
from the two prior commits in this branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(test): search-image-column probes column dim at runtime

CI shard 5 failed on `searchVector column routing (v0.27.1)` with:
  error: expected 1280 dimensions, not 1536

The test had a hardcoded `fakeText1536` helper that seeded chunks at
1536-d vectors. Master's default embedding model switched from OpenAI
text-embedding-3-large (1536) to ZeroEntropy zembed-1 (1280) so a fresh
PGLite brain on CI now sizes content_chunks.embedding at 1280; the
test's 1536-d INSERT trips pgvector's CheckExpectedDim.

Fix: probe `content_chunks.embedding` width via
`readContentChunksEmbeddingDim(engine)` in `beforeAll`, store in
`TEXT_DIM`, and build `fakeTextDefault(seed)` at that width. The test
now passes regardless of which default ships (the model has flipped
twice and may flip again). Local dev (1536 from older config) and CI
fresh-install (1280 from new default) both pass.

Image-side vectors stay at 1024 (matches Voyage multimodal-3 + the
column's fixed width on the image side).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(test): bump PGLite hook timeout for shard-4 deep-process files

facts-anti-loop.test.ts and ingest-capture.test.ts were timing out in CI
shard 4 with "beforeEach/afterEach hook timed out" after the v0.41.16.0
master merge brought migration count to 99. When these files run deep in
a shard process that has already created ~20 PGLite engines, the WASM
cold-start + 95-migration replay legitimately exceeds bun's 5s default
hook timeout (observed 5.6s and 7.3s locally when reproducing).

Bun's --timeout=60000 from scripts/test-shard.sh covers TEST timeouts
but NOT hook timeouts; those default to 5s and must be set per-hook via
the optional 2nd arg to beforeAll/afterAll.

Reproduced locally by running the first 21 shard-4 files via
  head -21 /tmp/shard4-list.txt | xargs bun test
  → 179 pass, 2 fail (both with hook-timeout error)

After fix:
  → 198 pass, 0 fail (the 4 anti-loop + 15 ingest-capture tests recover)

Full shard 4 with fix:  955 pass, 0 fail.
Full shard 5 with fix:  1261 pass, 0 fail.

Also added a defensive diagnostic to the two put_page tests: if
facts_backstop is missing in the response payload, throw with the full
payload + isError so future failures surface the actual handler error
instead of a bare "expected {...} got undefined" assertion. No-op when
the test passes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 18:29:03 -07:00
Garry Tan
f702ec053b v0.41.16.0 feat: conversation parser cathedral + progressive-batch primitive (closes #1461) (#1510)
* v0.41.15.0 feat: conversation parser cathedral + progressive-batch primitive (closes #1461)

Replaces PR #1461's single-format Telegram regex with a 12-pattern
built-in registry covering iMessage/Slack, Telegram (×2), Discord
(×2), WhatsApp (×2 locales), Signal, Matrix/Element, IRC (×2), Teams.
Each pattern is hand-vetted from public format docs (signal-cli,
DiscordChatExporter, Telegram Desktop, WhatsApp export docs, Element
matrix-archive, irssi/weechat defaults); module-load validation runs
test_positive[] + test_negative[] for every pattern at startup so a
typo makes gbrain refuse to start.

PR #1461 contributor's BRACKET_TIME_RX + cleanSpeaker survive verbatim
as the `telegram-bracket` built-in pattern + DEFAULT_SPEAKER_CLEAN
export. All 33 of their test cases pass against the new orchestrator.

Three layers per page (orchestrator chooses):
  1. Built-in pattern registry (zero-cost, deterministic)
  2. User-declared simple_pattern via config (deferred to v0.42+)
  3. Opt-IN LLM polish + fallback (privacy-first; chat content goes
     to Anthropic only when user explicitly enables)

D18 priority scoring picks the highest-match-rate pattern across the
first 10 lines (not first-wins) so overlapping formats don't silently
mis-route. D5 multi_line per-pattern + D11 quick_reject prefix screen
+ D19 timezone_policy per-pattern complete the registry shape.

Companion: src/core/progressive-batch/ primitive (rule of three
satisfied across 12+ ad-hoc cost-prompt sites). Wintermute-inspired
ramp shape (trial 10 → 100 → 500 → full with verification at each
stage), productionized with verifier+policy injection (callers
describe HOW TO MEASURE SUCCESS, not WHEN TO WAIT FOR CTRL-C). D3
fail-closed budget gate: null tracker + null Policy.maxCostUsd →
abort_cost_cap reason='no_budget_safety_net'. D20 discriminated
Verifier union (output_count | idempotent_mutation | noop).
extract-conversation-facts is the one proven consumer in v0.41.15.0;
9-site retrofit deferred to v0.41.16.0+ per TODOS.md.

Codex outside-voice review absorbed 8 substantive findings:
  - Privacy posture (LLM polish/fallback flipped to opt-IN)
  - ReDoS theater (dropped arbitrary user regex; v0.42+ uses RE2)
  - LLM-inferred-regex persistence as silent-corruption machine
  - Pattern priority scoring across first 10 lines
  - Timezone policy on every PatternEntry
  - Verifier shape discriminated union
  - Behavior parity for sites that "jumped straight to full"
  - Real-corpus-redacted fixture gap (v0.42+ TODO)

CI gates:
  - bun run check:conversation-parser (13 fixtures, --no-llm, deterministic)
  - bun run check:fixture-privacy (banned-token grep)

Doctor surfaces 3 new checks: conversation_format_coverage,
progressive_batch_audit_health, conversation_parser_probe_health.

Tests: 198/198 across primitive + parser + LLM + nightly probe + eval
CLI + debug CLI + doctor checks + migration v97 round-trip + E2E
parser ↔ engine integration. Real bug caught + fixed during gap audit:
IdempotentMutationVerifier was comparing absolute mutated-count vs
per-stage expected (failed silently on stage 2+); now uses per-stage
delta semantics matching OutputCountVerifier.

Schema migration v97: conversation_parser_llm_cache table with
(content_sha256, model_id, call_shape) composite key. NO
inferred_patterns table (D17: silent-corruption machine).

Plan + 23 decisions + codex outside-voice absorption at
~/.claude/plans/system-instruction-you-are-working-cuddly-hollerith.md.

Co-Authored-By: garrytan-agents (PR #1461) <noreply@github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(check-privacy): allowlist scripts/check-fixture-privacy.sh

The new sibling privacy guard literally names the banned tokens in its
BANNED_TOKENS array — same meta-exception that check-privacy.sh itself
gets. Without this allowlist entry, bun run verify rejects the file
post-merge because the banned name appears in the rule-definition script.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore: renumber v0.41.15.0 → v0.41.16.0 (queue drift)

Mechanical rename across all surfaces: VERSION, package.json,
CHANGELOG (header + body refs), CLAUDE.md, TODOS.md, src/core/
migrate.ts (migration v98 comment), all src/core/conversation-parser/*
and src/core/progressive-batch/* file headers, all test/ headers,
scripts/check-privacy.sh allowlist comment, llms-full.txt regenerated.

Audit clean: VERSION + package.json + CHANGELOG header all show
0.41.16.0. verify 24/24, touched tests 179/179.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: garrytan-agents (PR #1461) <noreply@github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 17:31:48 -07:00
Garry Tan
32f8be96c2 v0.41.14.0 fix(#1451): close RESOLVER.md drift bug class structurally (#1458)
* feat(core): loadSkillTriggerIndex shared primitive (closes #1451 drift class)

Single loader that unions per-skill SKILL.md frontmatter triggers: with
curated RESOLVER.md / AGENTS.md rows. UNION semantics — explicit
RESOLVER.md rows ADD to frontmatter triggers for the same skill (don't
replace). Dedup keyed on (skillPath, normalized trigger string) so case
or whitespace drift between the two surfaces collapses to one entry.

This is the structural foundation for #1451: pre-fix, gbrain skills
declared triggers in two places (per-skill frontmatter and a curated
RESOLVER.md table) that could silently drift. Three consumers
(checkResolvable, routing-eval CLI, mounts-cache.composeResolvers) each
built their own resolver index from RESOLVER.md only, so fixing
frontmatter would have closed doctor's warning without closing the
other two surfaces. This primitive becomes the single join point for
all three; consumers are wired in the next commit.

Tests: 18 hermetic cases pinning frontmatter auto-registration,
RESOLVER.md/AGENTS.md merge, case-insensitive dedupe, OpenClaw
workspace-root layout (../AGENTS.md), graceful skip of conventions /
deprecated skills / non-directory entries / missing skillsDir, plus
synthesis round-trip and findPrimaryResolverPath.

Plan: ~/.claude/plans/system-instruction-you-are-working-tidy-storm.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: wire 3 consumers through loadSkillTriggerIndex (#1451)

Replace the three independent resolver-content loaders with calls to
the v0.41.11 shared primitive so frontmatter triggers propagate to
every dispatch surface, not just doctor.

Before: checkResolvable, runRoutingEvalCli, and mounts-cache each
walked RESOLVER.md / AGENTS.md files separately. Adding frontmatter
triggers to one consumer (e.g. checkResolvable) wouldn't have reached
the routing-eval CLI or cross-brain composed dispatchers — the same
drift bug class as #1451 in cross-consumer form. Codex caught this in
plan-eng-review.

After: all three consumers fold through loadSkillTriggerIndex. UNION
semantics across both surfaces means new skills with frontmatter
triggers are reachable everywhere without editing RESOLVER.md.

Also updates:
- check-resolvable action text on routing_miss to point at the
  canonical surface (SKILL.md frontmatter triggers) first, with
  RESOLVER.md row as secondary.
- test/resolver-merge.test.ts to test BOTH the legacy
  RESOLVER.md-only authority path (skills with no frontmatter
  triggers) AND the new auto-registration path (skills reachable via
  frontmatter alone, no RESOLVER.md needed).
- 3 routing-eval.jsonl fixtures (voice-note-ingest, brain-taxonomist,
  strategic-reading) gain `ambiguous_with` declarations for skill
  overlaps that auto-registration newly exposes. These overlaps are
  legitimate (voice-note vs idea-ingest on audio notes,
  brain-taxonomist vs repo-architecture on filing, strategic-reading
  vs idea-ingest on reading-through-a-lens) — the agent picks based
  on context.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(#1451): broaden skillpack-harvest triggers + negative fixtures + tighten gate

Closes the 7 residual routing_miss warnings on skillpack-harvest that
gbrain doctor reported on every fresh install (resolver_health: WARN,
~5 health-score points).

Three changes:

1. Broaden skills/skillpack-harvest/SKILL.md frontmatter triggers from
   5 narrow to 10 realistic phrasings. Each new trigger is a
   contiguous substring of one of the 7 shipped routing-eval.jsonl
   intents (per kylma-code's design in PR #1331; moved from
   RESOLVER.md to frontmatter under the v0.41.11 frontmatter-
   authoritative contract). Existing RESOLVER.md row stays for
   human-readability of the dispatcher map.

2. Add 4 negative-fixture cases to skills/skillpack-harvest/
   routing-eval.jsonl with expected_skill=null to defend against
   false positives the broader triggers might introduce
   ("publish this report to the team", "promote my role on
   LinkedIn", "bundle these screenshots into a deck", "lift weights
   at the gym"). Two candidate negatives ("save this report as PDF",
   "share this article with the channel") were excluded — they trip
   idea-ingest's existing "save this"/"share" triggers, a real
   overlap but a separate v0.42+ concern.

3. Tighten test/check-resolvable.test.ts's "repo skills/ pass cleanly"
   assertion: the v0.25.1 carve-out that allowed routing_miss as
   informational is removed. The contract is back to zero errors AND
   zero warnings — the CI gate (next commit) enforces this for PRs
   so future drift fails the build instead of degrading user-install
   resolver_health silently.

Co-Authored-By: kylma-code <noreply@github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(cli): register reindex in CLI_ONLY so --help works (closes part of #1354)

Pre-fix: src/cli.ts had a `case 'reindex':` handler at line 1334 that
dispatched to reindex-multimodal or reindex.ts based on flags, but
'reindex' was missing from the CLI_ONLY Set at line 38. The dispatcher
rejected the command with "Unknown command: reindex" before the handler
ever ran.

Post-fix: 'reindex' is in CLI_ONLY (recognized as a registered command).
NOT added to CLI_ONLY_SELF_HELP — the handler doesn't have its own
--help branch, so the dispatcher's generic printCliOnlyHelp() shows
"gbrain reindex - run gbrain --help for the full command list."
Polishing this to per-flag help text (--multimodal, --markdown, --code)
is a follow-up TODO.

Regression test in test/cli.test.ts asserts `'reindex'` is in the
CLI_ONLY Set source string. Mirrors the existing pattern for
'reinit-pglite' in test/v0_37_fix_wave.serial.test.ts:284 and
'book-mirror' in test/book-mirror.test.ts:73.

Cherry-picked from lost9999's PR #1354 (which bundled this fix with
their fixture-rewrite approach to #1451 — the routing-eval half of
that PR was superseded by kylma-code's trigger-broadening direction
in #1331, which we took structurally in the previous commits).

Co-Authored-By: lost9999 <noreply@github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(ci): wire check:resolver into bun run verify

Adds `bun run check:resolver` (= `bun src/cli.ts check-resolvable
--strict --skills-dir skills/`) to package.json scripts and registers
it in scripts/run-verify-parallel.sh's CHECKS array.

This gates PR CI on resolver health: any future drift between a
skill's frontmatter triggers and its routing-eval.jsonl fixtures
fails the build, instead of silently degrading the resolver_health
score on user installs after merge. The --strict flag exits non-zero
on warnings (not just errors), so routing_miss / routing_ambiguous /
routing_false_positive all block.

Closes the CI half of #1451's structural fix: doctor catches drift
at runtime, this gate catches drift at PR time.

Local pre-flight: `bun run check:resolver`.

Codex finding #9 from plan review: scripts/run-verify-parallel.sh
invokes entries as `bun run <script-name>`, not raw shell. The
package.json script name + CHECKS-array entry is the correct shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(test): update CLI unreachable test for v0.41.11 contract change

The prior fixture used `triggers: ['alpha']` + `inResolver: false` to
simulate an unreachable skill. Under v0.41.11's structural fix,
frontmatter triggers auto-register the skill independently of
RESOLVER.md, so this skill is reachable now — the assertion
`errors.length > 0` failed.

Drop the `triggers:` array from the fixture so the skill is genuinely
unreachable (neither frontmatter nor RESOLVER.md row), preserving the
test's regression-guard intent: doctor/check-resolvable still exits 1
when a manifest skill is truly unreachable.

Caught by the full unit test suite after the merge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: CLAUDE.md Key Files note for skill-trigger-index + regen llms.txt

Document the v0.41.11 shared primitive (loadSkillTriggerIndex) in
the Key Files section so future contributors find it before they
reach for parseResolverEntries directly. Notes the 3 consumers
(checkResolvable, runRoutingEvalCli, mounts-cache.composeResolvers),
the UNION semantics, skip rules, parseSkillFrontmatter dependency,
test coverage, and the CI gate wiring.

Regenerated llms.txt + llms-full.txt per the CLAUDE.md edit rule.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* v0.41.14.0 fix(#1451): close RESOLVER.md drift bug class structurally

Frontmatter triggers + RESOLVER.md / AGENTS.md rows now union into one
unified index via the new loadSkillTriggerIndex primitive, consumed by
all three dispatch surfaces (checkResolvable, routing-eval CLI,
mounts-cache.composeResolvers). Closes the 7 residual routing_miss
warnings #1451 reported on every fresh install, and the drift bug class
that produced them.

Highlights:
- New shared primitive src/core/skill-trigger-index.ts (252 lines + 361
  lines of tests across 18 cases). UNION semantics, case-insensitive
  dedupe keyed on (skillPath, normalized trigger).
- Three consumers wired through the primitive — fixing frontmatter
  triggers for doctor now also fixes routing-eval CLI and
  cross-brain mounted dispatch (codex outside-voice catch).
- skillpack-harvest frontmatter broadened from 5 to 10 triggers per
  kylma-code's design in #1331, plus 4 negative-fixture cases for
  false-positive defense.
- reindex CLI added to CLI_ONLY set so `gbrain reindex --help` works
  instead of "Unknown command: reindex" (lost9999's #1354 hunk).
- check:resolver wired into bun run verify CI gate so future drift
  fails PR CI instead of silently degrading user-install
  resolver_health.
- check-resolvable's repo skills/ test tightened from "warn-tolerant"
  to "zero errors AND zero warnings" — the carve-out was a stop-gap
  pre-structural-fix.

Plan + 5 decisions + codex outside-voice recalibration captured at
~/.claude/plans/system-instruction-you-are-working-tidy-storm.md.

Co-Authored-By: kylma-code <noreply@github.com>
Co-Authored-By: lost9999 <noreply@github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: update project documentation for v0.41.14.0

- CLAUDE.md: tag skill-trigger-index entry with correct shipped version
  (v0.41.14.0, closes #1451) instead of the stale v0.41.11 draft tag.
- CONTRIBUTING.md: list the new `check:resolver` gate in the `bun run
  verify` chain so contributors know to expect resolver-drift failures
  in PR CI.
- llms-full.txt: regenerated from updated CLAUDE.md (mandatory per
  CLAUDE.md's auto-derived files rule; CI shard 1 fails the build
  otherwise).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: kylma-code <noreply@github.com>
2026-05-25 20:00:03 -07:00
Garry Tan
3a2605e9a0 v0.41.6.0 feat(ci): CI test speedup — 23min → ~9min via matrix 4→6 + weight-aware sharding + auto SHA cache + parallel verify (#1444)
* feat(ci): scripts/run-verify-parallel.sh — parallel verify dispatcher

Fans out the 21 pre-test grep guards via & + wait, captures per-check
exit codes in a tempdir, aggregates failures with named check + log
tail to stderr on miss. Wallclock 27s sequential → 13s parallel
locally (2x). Bigger CI win is shard 1 deload (workflow restructure
in a later commit).

Pinned by test/scripts/run-verify-parallel.test.ts (6 cases: CLI
contract + synthetic dispatcher failure-surfacing).

* feat(ci): weight-aware LPT bin-packer + auto SHA cache hash

scripts/sharding.ts (NEW) — pure TypeScript LPT bin-packer. Sort
weights desc, assign each file to the shard with current minimum total.
Worst-case makespan within 4/3 of optimal, O(n log n). Missing weights
fall back to corpus median (not 0). New test file → ships immediately
without regenerating weights. Pinned by test/scripts/sharding.test.ts
(23 cases).

scripts/mine-shard-weights.ts (NEW) — scrapes per-file timing from
gh run view --log via timestamp delta between ##[group]test/foo.test.ts:
headers within a shard. Three input modes: --run <ID>, --from-file
<PATH>, stdin. Stable JSON output (sorted keys). Initial weights mined
from run 26398061007. Pinned by test/scripts/mine-shard-weights.test.ts
(15 cases).

scripts/ci-cache-hash.sh (NEW) — deterministic 16-char sha256 over
git ls-files -s minus deny-list (CHANGELOG/TODOS/README/LICENSE/
docs/**/*.md). CLAUDE.md, AGENTS.md, skills/**/* deliberately
INCLUDED (8+ test files read them; deny-listing would create
false-pass holes). ~40ms on 1891 files. Pinned by
test/scripts/ci-cache-hash.test.ts (24 cases: 8 CRITICAL false-pass
guards + 7 SAFE deny-list invariants + 9 edge cases).

scripts/test-weights.json (NEW) — 712 weights. Total 3306s observed
runtime; median 30ms; max 6 min outlier.

* chore: bump version and changelog (v0.41.6.0)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 13:15:11 -07:00