Skip to content

feat(check): one finding when call sites in several workspaces trace to one declaration - #51

Merged
lucasbraum merged 2 commits into
mainfrom
fix/check-shared-root-causes
Oct 9, 2026
Merged

lucasbraum merged 2 commits into
mainfrom
fix/check-shared-root-causes

Conversation

@lucasbraum

Copy link
Copy Markdown
Collaborator

What and why

Engine item from the #45 thread: cause not traced across workspaces. A mismatch at an argument traces to the repository parameter it lands on (parameterCause), but the compile signal anchored the finding there only when two or more sites in the same workspace tripped it. tldraw's useTransform(ref) is called from three workspaces; apps/examples and packages/tldraw have one site each, so check reported those two as findings of their own beside the anchor in packages/editor, the one place upstream edited (useTransform.ts:6). Those two were the last breaking false positives of the react pack.

Now, when diagnostics in different workspaces trace back to the same local declaration (same file and symbol), check emits one breaking finding anchored at that declaration and lists the call sites under it as evidence.

  • Tracer (adapters/typescript/compile.ts): a diagnostic keeps the declaration it traces to as root, whether or not enough sites in its workspace share it for cause to be set. parameterCause itself is unchanged.
  • Findings (check/unattributed.ts): a call-site finding carries Finding.root (workspace-relative, like usage.file); an in-workspace parameter anchor carries it too.
  • Merge (check/check.ts → check/root-cause.ts foldSharedRoots): after the workspaces are merged and roots are prefixed to repository paths, two or more sites at one root, or a site plus the anchor another workspace already produced, become (or join) one anchored finding: anchorOnly, downstream = the sites (each with its workspace), details opening with N call sites in M workspaces, fixability: assisted, the pack rule the sites agreed on. The anchor counts as one site in the verdict.
  • Report model: JSON gains root on call-site and anchored findings and workspace on downstream entries; nothing is renamed or removed. The terminal --details prints N call sites in M workspaces, for example with up to 8 sites under the anchor (instead of evidence: N errors at the target for a declaration root; config anchors keep that wording). The HTML report lists the call sites with their workspaces under the anchor site.
  • Scorer (packs/tooling/pack-test.ts predictedSites): the anchor is the predicted site, so a ground-truth finding at the declaration matches it; a call site listed as evidence under an anchored finding is neither a true nor a false positive, even when another finding lands on that line.

On tldraw the merged finding reads: packages/editor/src/lib/hooks/useTransform.ts:6 · 7 call sites in 3 workspaces (5 in packages/editor, 1 in apps/examples, 1 in packages/tldraw).

No pack rule, expectation, ground truth or companion was edited.

How it was verified

New tests: adapters/typescript/cause.test.ts (a single site keeps its root), check/root-cause.test.ts (fold across workspaces, join an existing anchor, a lone site stays, the call-sites line), check/check.test.ts (mergeAcrossWorkspaces prefixes ../editor/... roots from two workspaces to one repository path and folds them), packs/tooling/pack-test.test.ts (anchor scored, evidence excluded even under another finding), format-check-details.test.ts and html/render.test.ts (the N call sites line and the listed sites).

pnpm lint && pnpm typecheck && pnpm test pass (core 917 tests, cli 349).

Pack tests, before (main at 2e5c510) and after, run in a scratch worktree with the react pack from #45's branch (claude/pensive-galileo-mw5yx8) copied in uncommitted; breaking findings:

pack before: precision / recall, breaking FP after: precision / recall, breaking FP
react (candidate) 98% / 69%, 2 (the two useTransform sites) 100% / 69%, 0
zod 100% / 71%, 0 100% / 71%, 0, identical
stripe 100% / 90%, 0 100% / 90%, 0, identical
ai 100% / 36%, 0 100% / 36%, 0, identical

react overall (every severity): 91% / 70% → 93% / 70%; the 7 remaining non-breaking false positives (6 deprecated, 1 unverified) are unchanged. pack test react still exits non-zero only because #45's verification.json records 96% / 4 false positives and no longer matches; it is not edited here.

Checklist

  • Tests for the change (a bug fix starts with a failing test)
  • pnpm lint && pnpm typecheck && pnpm test pass
  • README and docs updated if behavior changed (docs/architecture.md, docs/cli.md)
  • Changeset added if a user would notice (pnpm changeset): minor
  • No new dependency, or it was agreed in an issue
  • No private code, names or paths in fixtures, tests or docs
  • The rules in CONTRIBUTING.md ("Rules that do not bend") still hold

🤖 Generated with Claude Code

https://claude.ai/code/session_018u9b3Pp5H68DdYZGp5Qg1U


Generated by Claude Code

Lucas Braum and others added 2 commits October 9, 2026 15:45
…to one declaration

A mismatch at an argument traces to the repository parameter it lands on (parameterCause);
the compile signal anchored the finding there only when two or more sites in the same
workspace tripped it. tldraw's useTransform(ref) is called from three workspaces, each with
one site, so check reported three findings beside the one at the hook's parameter that
upstream actually edited.

- The diagnostic keeps the declaration it traces to (`root`), and so does the call-site
  finding (`Finding.root`, repository-relative), whether or not its workspace folds it.
- After the workspaces are merged, foldSharedRoots (check/root-cause.ts) compares roots
  across them: two or more sites at one declaration, or a site plus the anchor another
  workspace already produced, become one anchored finding at the declaration, with the
  sites as `downstream` (each with its `workspace`) and `details` opening with
  "N call sites in M workspaces"; the pack rule the sites agreed on is kept.
- The terminal (--details) prints that line with a few sites as examples; the HTML report
  lists the call sites with their workspaces under the anchor; the JSON report only gains
  fields (`root`, `downstream[].workspace`).
- The pack test scorer counts the anchor as the predicted site and never the evidence under
  it, even when another finding lands on an evidence line.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018u9b3Pp5H68DdYZGp5Qg1U
Signed-off-by: Lucas Braum <lucas.braum@deskfy.io>
…fixes it once

A root was prefixed by the workspace when the finding was made and again when the
workspaces were merged (apps/examples/packages/editor/...), so roots never matched across
workspaces. It is now kept like usage.file, and prefixed and normalized by the merge alone.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018u9b3Pp5H68DdYZGp5Qg1U
Signed-off-by: Lucas Braum <lucas.braum@deskfy.io>
@lucasbraum
lucasbraum marked this pull request as ready for review October 9, 2026 16:56
@lucasbraum
lucasbraum merged commit a18bebd into main Oct 9, 2026
7 checks passed
@lucasbraum
lucasbraum deleted the fix/check-shared-root-causes branch October 9, 2026 17:00
@uptide-release uptide-release Bot mentioned this pull request Oct 9, 2026
@lucasbraum lucasbraum mentioned this pull request Oct 9, 2026
8 tasks done
lucasbraum pushed a commit that referenced this pull request Oct 9, 2026
…g precision 100%)

pack test react --write: excalidraw and tldraw, 0 false positives among breaking
findings. queue.json: react verified. The two cli fix tests that used react as their
example of a package without a pack now use vitest.

Known: packages/core/src/fix/isolate.test.ts:600 still uses react as the no-pack package and fails.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CECy7agtzRrX4SJWSAUHfS
Signed-off-by: Claude <noreply@anthropic.com>
lucasbraum added a commit that referenced this pull request Oct 9, 2026
## Pack

`react`, `>=18 <19` → `>=19 <20`. Companions move with it: `react-dom`,
`@types/react` and `@types/react-dom`, as the engine's companion rules
decide (not listed by the pack). Supersedes #45: same pack and ground
truth, brought onto current main (merge of `main` at 0de525c, no
conflict), with the changeset, the README table and a test fixed up.

## Sources

- React 19 Upgrade Guide:
https://react.dev/blog/2024/04/25/react-19-upgrade-guide
- React 19.0.0 changelog:
https://github.com/facebook/react/blob/main/CHANGELOG.md#1900-december-5-2024
- types-react-codemod (preset-19):
https://github.com/eps1lon/types-react-codemod

## Rules and behavior notes

Rewrites by rule:
- `use-ref-argument`: `useRef<T>()` → `useRef<T>(undefined)`.
- `ref-callback-return`: `ref={(el) => (x = el)}` → a block body (sites
from `detect`).
- `mutable-ref-object`: `React.MutableRefObject` → `React.RefObject`.

To the agent, with a guide:
- `ref-object-nullable`: a parameter or prop typed `RefObject<T>` once
`useRef` returns `RefObject<T | null>`.
- `global-jsx-namespace`: the removed global `JSX` namespace (one
finding at the tsconfig's `jsx` line, the elements as evidence).
- `element-props-unknown`: untyped `element.props`.
- `removed-react-dom`: `ReactDOM.render`, `hydrate`,
`unmountComponentAtNode`, `findDOMNode`.
- `props-with-ref`.

Behavior notes, listed for review (the compiler cannot see them):
`errors-not-rethrown`, `removed-legacy-apis`, `act-moved-to-react`,
`element-ref-deprecated`, `strict-mode-memoization`,
`suspense-fallback-first`, `umd-removed`, `javascript-urls-blocked`,
`use-reducer-types`.

## Ground-truth repositories

| Repository | Pinned commit (before the upgrade) | Upgrade | With |
Expected findings |
|---|---|---|---|---|
| excalidraw/excalidraw | 9ee0b8ffcbd3664a47748a93262860321a203821 |
react 18.2.0 → 19.0.0 | react-dom 19.0.0, @types/react 19.0.10,
@types/react-dom 19.0.4 | 73 |
| tldraw/tldraw | 5957867a9c5c205a0b0c3665be443138b8014a79 | react
18.3.1 → 19.2.1 | react-dom 19.2.1, @types/react 19.2.7,
@types/react-dom 19.2.3 | 60 |

Expected findings were drafted with `pnpm packs:truth` from each
repository's own TypeScript and its upgrade commit, and read by hand;
tldraw's 1,745 JSX element diagnostics are one site at the tsconfig that
causes them (#45). Rules, expectations, ground truth and companions are
unchanged from #45's last state.

## `uptide pack test` output

`verification.json` on this branch records the run on main after #51
(commit 8573cc0); `pack test react` was not rerun here, since the merge
touched neither `packages/core/src/check` nor the pack. That run:

```
uptide pack test react · verified
fixtures      3 cases, 6 sites · pass
ground truth
  excalidraw/excalidraw@9ee0b8ffcbd3           react 18.2.0 → 19.0.0  predicted 60, expected 73, false positives 1, false negatives 14
  tldraw/tldraw@5957867a9c5c                   react 18.3.1 → 19.2.1  predicted 39, expected 60, false positives 6, false negatives 26

  rule                         precision  recall    tp   fp   fn
  element-props-unknown             100%     60%     6    0    4
  generic                             4%     33%     1   26    2
  global-jsx-namespace              100%     51%    20    0   19
  mutable-ref-object                100%    100%     2    0    0
  props-with-ref                    100%    100%     1    0    0
  ref-callback-return               100%    100%     1    0    0
  ref-object-nullable               100%     37%    20    0   34
  removed-react-dom                 100%    100%    18    0    0
  use-ref-argument                  100%     80%     4    0    1
  overall (sites)                    93%     70%    92    7   40
  breaking (sites)                  100%     69%    89    0   40
```

Breaking findings: precision 100% (89 sites, none false), recall 69%, on
2 public repositories. The 7 non-breaking false positives are deprecated
or unverified findings and do not count toward the verdict.

## What is not covered

- Recall on breaking sites is 69%: 40 expected sites are missed, most of
them `ref-object-nullable` (34) and `global-jsx-namespace` (19 in the
per-rule table, counted at the tsconfig anchor) sites the compiler does
not reach, plus 4 `element-props-unknown` and 1 `use-ref-argument`. They
are listed by `pack test react` as false negatives.
- Behavior changes the compiler cannot see are reported as notes for
review, never rewritten.
- The engine links one copy of the target types; a nested second
`@types/react` copy, as a real install can keep, is not modeled.

## This PR on top of #45

- `.changeset/react-pack.md` is `minor` (a new verified pack) and opens
with the two repositories; numbers unchanged.
- README "Verified packs" regenerated with `pnpm docs:packs`; `pnpm
docs:packs --check` and `pnpm docs:links` pass.
- `packages/core/src/fix/isolate.test.ts` used react as its example of a
package without a pack; it is vitest now, like the two `cli.test.ts`
cases. No other test did.
- `pnpm lint`, `pnpm typecheck`, core (919 tests) and CLI (350 tests)
pass.

## Checklist

- [x] Every rule and note comes from a source listed in `meta.sources`
- [x] Every rule that rewrites or detects has a fixture case, with a
site it must leave alone (`keep`)
- [x] Ground truth: public repositories at the commit before their
upgrade; expected findings read from their own upgrade commit and the
compiler, never copied from Uptide's output
- [x] At least two public repositories for `verified`; otherwise the
pack ships as a candidate
- [x] `pnpm uptide pack test <package>` passes and its output is pasted
above; `verification.json` written with `--write`
- [x] `pnpm lint && pnpm typecheck && pnpm test` pass
- [x] Changeset added (`pnpm changeset`): a new pack is something users
notice
- [x] No private code, names or paths anywhere: fixtures are synthetic,
ground truth is public

Supersedes #45.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_018u9b3Pp5H68DdYZGp5Qg1U

---
_Generated by [Claude
Code](https://claude.ai/code/session_018u9b3Pp5H68DdYZGp5Qg1U)_

---------

Signed-off-by: Claude <noreply@anthropic.com>
Signed-off-by: Lucas Braum <lucas.braum@deskfy.io>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Lucas Braum <lucas.braum@deskfy.io>
lucasbraum pushed a commit that referenced this pull request Oct 9, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and publish to npm
yourself or [setup this action to publish
automatically](https://github.com/changesets/action#with-publishing). If
you're not ready to do a release yet, that's fine, whenever you add more
changesets to main, this PR will be updated.


# Releases
## uptide@0.6.0

### Minor Changes

- [#46](#46)
[`458aa14`](458aa14)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - What changed in
`check`:
  
- **Breaking means confirmed.** A type-surface change is reported as
breaking only when the
compiler rejects your code against the target at that site, the runtime
probe saw the
export go, or a migration pack found it, in the verified tier as in the
generic one. What
nothing confirmed is listed as "possible impact", apart from the
breaking count.
- **Coverage, under every package.** `compiled 355 of 356 files in 5
workspaces; skipped:
<reason (count)>` says how much of the code that uses the package the
compiler judged, and
    the verdict says "types partly verified" when not every file was.
- **TypeScript-version-aware defaults.** A repository on TypeScript 5 is
read with
TypeScript 5's defaults for what its tsconfig leaves unset (`strict`
off, automatic
`@types`), not the bundled TypeScript 6's. Monorepos compile far more of
their files:
workspace packages declared `workspace:*` under Yarn and npm resolve to
their source,
scoped programs keep the tsconfig's ambient declaration files, and a
workspace that only
    peer-depends on a package finds the hoisted copy.
- **Companions.** `check` and `fix` move `@types/<pkg>` with `<pkg>`,
and a package released
in lockstep with it (react-dom with react): `check react` 18 → 19 moves
react-dom,
    @types/react and @types/react-dom together.
- **One finding for a root cause that is one edit.** A compiler option
(the global `JSX`
namespace `@types/react` 19 removes, read by `"jsx": "preserve"`) and a
repository
parameter several call sites trip are each one finding at the place to
edit, with the
    compiler errors as evidence.

- [#51](#51)
[`a18bebd`](a18bebd)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - `check` reports
one breaking finding when call sites in different workspaces trace back
to
the same local declaration (a parameter or prop whose type names
something from the upgraded
package): the finding is anchored at the declaration, where the one edit
is, and the call
sites are listed under it as evidence with an `N call sites in M
workspaces` line, in the
terminal, the HTML report and the JSON report. Before, a site alone in
its workspace stayed a
finding of its own, so a hook typed `RefObject<HTMLElement>` and called
from three
workspaces was three findings plus the one that mattered. The JSON
report gains `root` on
call-site findings and `workspace` on evidence sites; nothing is renamed
or removed. The pack
test scorer counts the anchor as the predicted site and never the
evidence under it.

- [#49](#49)
[`2e5c510`](2e5c510)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - Two fixes to
`check`:
  
- **A project whose tsconfig cannot be resolved is not compiled.** A
tsconfig that `extends` a
package or file that is not installed describes options the repository
never builds with, so
what a compiler reports there is not a place to change. `check` skips
it, never turns its
diagnostics into findings, and says so in the coverage line (a file
governed by such a
nested project is dropped from the workspace that happens to reach it):
`compiled 5 of 7 files in 2 workspaces; not compiled: docs/tsconfig.json
(extends "@tsconfig/docusaurus/tsconfig.json" cannot be resolved)`.
- **A package that only peers on the package is left in place when its
peer range rejects the
target.** What always moves with the package stays as before: the
release group published at
the target's own version (`react-dom`), `@types/*`, the exact pins of
the target, and the
packages a pack names in `companions` (each with the official page that
says so), even when their installed range already accepts the
target. Any other package whose installed peer range rejects the target
is not moved and not
compiled at another version; `check` lists it under possible impact,
never as breaking:
`? possible impact, peer conflict: next-mdx-remote-client 1.1.2 declares
react >= 18.3.0 < 19.0.0`.

- [#53](#53)
[`d33bdd0`](d33bdd0)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - A verified
migration pack for React 18 → 19, scored against excalidraw/excalidraw
and
tldraw/tldraw at the commit before their own upgrade. Rewrites by rule:
`useRef<T>()` →
`useRef<T>(undefined)`, `ref={(el) => (x = el)}` → a block body, and
`React.MutableRefObject`
→ `React.RefObject`. `RefObject<T | null>`, the removed global `JSX`
namespace, untyped
`element.props`, the removed react-dom APIs and `PropsWithRef` go to the
agent with the guide;
what the compiler cannot see (errors no longer re-thrown, removed legacy
APIs, `act` moved to
"react", Strict Mode and Suspense changes) is listed for review. 2
public repositories, 100%
precision on breaking findings (89 sites, none false), recall 69% on
breaking sites; the
  sites it misses are listed in the pack test output.

### Patch Changes

- [#48](#48)
[`94611a9`](94611a9)
Thanks [@lucasbraum](https://github.com/lucasbraum)! - `check` compiles
your code with the repository's own TypeScript (the
`node_modules/typescript`
its build uses, found the way `fix` has found it since verification),
and falls back to the
bundled compiler only when the repository installs none. Errors and
their positions are the
ones your `tsc` would print: a repository on TypeScript 4.9 is no longer
judged by TypeScript
6's rules. The coverage line says which compiler judged: `compiled 355
of 356 files in 5
  workspaces with the repo's TypeScript 4.9.5`.
  
A workspace without a tsconfig of its own is now configured by the
nearest one above it (a
monorepo root whose `include` covers the workspace), for its options
only; synthetic defaults
  apply only when no tsconfig exists anywhere.

Co-authored-by: uptide-release[bot] <338861287+uptide-release[bot]@users.noreply.github.com>
lucasbraum added a commit that referenced this pull request Oct 10, 2026
…n a repository augmentation (#60)

## What and why

**1. Shared root through a setup or declaration file.** In the vitest
pack test (#57, ground truth votingworks/vxsuite), `check` reported a
breaking finding at `libs/image-utils/src/jest_pdf_snapshot.ts:42`
(TS2551, `toMatchImageSnapshot` missing on `Assertion`) beside the
declaration at `libs/image-utils/src/vitest_setup.ts:10` the pack
already reports. The tracer did not link them: #51 handles parameters
only, and this is a global augmentation. Two things turned out to be
true on inspection:

- The failing member is not a parameter and not declared in the setup
file either: `toMatchImageSnapshot` comes from `jest-image-snapshot`'s
own types, which declare it on the global `jest.Matchers`. The setup
file augments that same interface (`declare global { namespace jest {
interface Matchers<R> { toMatchImage…; toMatchPdfSnapshot… } } }`) and
registers all three matchers with `expect.extend`. Vitest 5 stops
reading the global namespace, so every matcher on it has to move to
`Matchers<R, T>` of "vitest" together, and the repository's augmentation
is where that edit goes.

The cause tracer (`adapters/typescript/cause.ts`, `augmentationCause`)
now handles missing-member diagnostics (TS2339, TS2551): the member is
resolved in the baseline program, where it still exists, and

- when its declaration is in a repository file, the diagnostic is
anchored there: a `declare global` block at the block, a `declare module
"x"` augmentation at the interface inside it, any other repository
declaration at itself;
- when its declaration is a package's (or another fixture's) on an
interface the repository augments, it is anchored at the repository's
augmentation of that interface, this workspace's first, with the package
named in the reason;
- one site is enough, unlike a parameter: the edit is never at the call.
The anchor is also the diagnostic's `root`, so sites in other workspaces
fold with it after the merge (#51's model, same report fields:
`anchorOnly`, `downstream`, `root`, "N call sites").

It is tried after the compiler-option cause and before the parameter
cause. On vxsuite the finding is now one site at `vitest_setup.ts:10`,
with the `jest_pdf_snapshot.ts` call as evidence.

**2. README line limit.** `readme.test.ts` capped the file at 150 lines
and every pack row pushed against it. The test now excludes the
generated block between `<!-- packs:start -->` and `<!-- packs:end -->`
from the count. #57's two joined documentation lines are not on `main`
(that change lives on #57's branch), so there is nothing to restore
here; once this merges, #57 can drop that edit.

No pack's rules, expectations or ground truth were edited.

## How it was verified

Unit tests in `cause.test.ts` on a new fixture pair,
`fixtures/deps/matchers-v1` (an assertion that reads the global
`checks.Matchers`) and `matchers-v2` (its own `Matchers<R, T>`, the
global no longer read), plus `matchers-extra-v1` (a package declaring a
matcher on that global):

- three call sites in two files, for a matcher the setup file declares,
fold into one anchor at the setup file's `declare global` line, each
site carrying the cause and the root;
- a call site for a matcher another package declares on the interface
the setup file augments anchors at that augmentation, naming the
package;
- a member the package itself dropped is left at the site.

`pnpm lint`, `pnpm typecheck`, `pnpm docs:links`, `pnpm docs:packs
--check`, the private-material guard, core (930 tests) and CLI (350
tests) pass.

Pack tests, before (main at 45677eb) and after (this branch), breaking
findings; vitest run in a scratch worktree with #57's pack copied in
uncommitted:

| pack | before: precision / recall, breaking FP | after: precision /
recall, breaking FP |
|---|---|---|
| vitest (#57, candidate) | 94% / 50%, 1 (`jest_pdf_snapshot.ts:42`) |
**100% / 50%, 0** |
| zod | 100% / 71%, 0 | 100% / 71%, 0, identical |
| stripe | 100% / 90%, 0 | 100% / 90%, 0, identical |
| ai | 100% / 36%, 0 | 100% / 36%, 0, identical |
| react | 100% / 69%, 0 | 100% / 69%, 0, identical |

vitest per rule after: `matcher-types` 100% / 100% (3 of 3), was 75% /
100%. `pack test vitest` still exits non-zero on this branch only
because #57's `verification.json` records 94% / 1 false positive and no
longer matches; that file is #57's to rewrite with `--write`. Its 16
false negatives and the 18,900-odd `generic (unverified)` sites (not
breaking) are unchanged.

## Checklist

- [x] Tests for the change (a bug fix starts with a failing test)
- [x] `pnpm lint && pnpm typecheck && pnpm test` pass
- [x] README and docs updated if behavior changed
(`docs/architecture.md`, `docs/concepts.md`)
- [x] Changeset added if a user would notice (`pnpm changeset`): minor
- [x] No new dependency, or it was agreed in an issue
- [x] No private code, names or paths in fixtures, tests or docs
- [x] The rules in CONTRIBUTING.md ("Rules that do not bend") still hold

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_018u9b3Pp5H68DdYZGp5Qg1U

---
_Generated by [Claude
Code](https://claude.ai/code/session_018u9b3Pp5H68DdYZGp5Qg1U)_

---------

Signed-off-by: Lucas Braum <lucas.braum@deskfy.io>
Co-authored-by: Lucas Braum <lucas.braum@deskfy.io>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant