mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-06 21:05:21 +02:00
43354eb389069d9e5cbacee7cd7a144f707f5d45
5
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
38d8f37172 |
fix(build): enforce Node 24 across Paperclip (#11792)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Paperclip runs across the CLI, server, adapters, plugins, CI, and container images. > - These surfaces declared different Node.js versions from 20 through 24. > - A newer `@types/node` major can expose APIs that the supported runtime does not provide. > - Node.js 20 is no longer a suitable project baseline, and Node.js 24 is the current LTS line. > - This pull request sets Node.js 24.11.0 as one repository-wide baseline, adds a drift check, and gives users actionable startup guidance when their runtime is too old. > - The benefit is one clear runtime contract for development, release, installation, and published packages. ## Linked Issues or Issue Description Refs #2734 Refs #11727 Refs #739 ## What Changed - Require Node.js 24.11.0 or newer in all 42 package manifests and runtime checks. - Use Node.js 24 in GitHub Actions, Docker images, smoke images, sandbox setup, portable installs, and esbuild targets. - Align every direct `@types/node` declaration on `^24.0.0`. - Prevent Dependabot from opening major `@types/node` upgrades without a matching runtime decision. - Add `.nvmrc` and a CI policy check for Node version drift. - Update ACP version gates, tests, and user documentation for the new minimum. - Print a non-blocking warning on CLI and server startup when Node is unsupported, with remediation through a version manager or the documented downloaded `install.sh` workflow. - Deduplicate that warning when `paperclipai run` boots the CLI and server in the same process. ## Verification - `node scripts/check-node-version-policy.mjs` - `node --check scripts/check-node-version-policy.mjs` - `node --check cli/esbuild.config.mjs` - `node --check scripts/generate-npm-package-json.mjs` - `bash -n scripts/install.sh scripts/test-install-sh-docker.sh scripts/e2e-install-lifecycle.sh` - Parsed all 42 package manifests and confirmed `engines.node` is `>=24.11.0`. - `git diff --check` - `vitest run packages/adapter-utils/src/sandbox-install-command.test.ts` passed with 3 tests. - `vitest run cli/src/node-version.test.ts` passed with 4 tests. - Directly exercised the shared warning helper for unsupported-version messaging and same-process deduplication. - The focused exe.dev suite could not resolve the locally unbuilt plugin SDK from this isolated worktree. A full offline workspace install was also blocked because the package-manager signature verifier requires registry access. The full suite was not run locally; draft CI performs a clean install and evaluates the wider impact. ## Risks - This is a breaking runtime change for users, plugins, and deployments that still use Node.js 20 or 22. - Published workspace packages will now produce an engine warning or failure in strict package managers on older Node.js releases. - Node.js 24 can reveal dependency, native module, Playwright, or agent CLI compatibility issues in CI. - The bootstrap installer now installs Node.js 24 when the current runtime is older than 24.11.0. - The portable sandbox fallback is pinned to Node.js 24.11.0 and depends on that upstream tarball remaining available. - Unsupported runtimes continue booting after a warning, so a later incompatibility can still fail at its point of use. - The CLI and server share the warning policy through the published `@paperclipai/shared` package; packaging checks must keep that subpath export available. - This PR does not commit `pnpm-lock.yaml` because repository policy assigns lockfile generation to CI. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex based on GPT-5. The exact deployment ID and context window are not exposed in this session. Reasoning, repository tools, shell execution, and GitHub tools were enabled. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
7083c275c8 |
refactor(sandbox): retire the dead noProfile flag from the exec path (#10461)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The sandbox exec path starts agent commands and passes runtime options to the server and plugin layers > - This path kept a noProfile flag after the exec wrappers stopped sourcing a login profile > - The flag no longer changed behavior, so it left dead API surface in the protocol and runtime helpers > - This pull request removes that dead flag from the plugin protocol, the server drivers, and the managed-runtime helpers > - It also updates the tests and points the agent runtime README at the sandbox requirements file > - The benefit is a smaller and clearer exec-path contract with no behavior change ## Linked Issues or Issue Description - No public GitHub issue exists. ### What happened? The sandbox exec path kept a `noProfile` field after the exec wrappers stopped sourcing a login profile. ### Expected behavior The plugin protocol, server drivers, and managed-runtime helpers should not expose or forward a dead field. ### Steps to reproduce 1. Run a managed-runtime command through the sandbox exec path. 2. Inspect the protocol payload and runtime helper inputs. 3. Observe that `noProfile` is present even though it no longer changes behavior. ### Paperclip version or commit `60c7da86fc7a6c1dbf37bbcd86e25ecaaff01607` ### Deployment mode Built from source (pnpm dev / pnpm build) ### Additional context This pull request removes the dead field, updates the affected tests, and updates the README note for the sandbox profile path. ## What Changed - Removed noProfile from the plugin protocol and the server exec-path call sites. - Updated the managed-runtime helpers to use the narrower exec-path contract. - Updated the affected tests and added the README pointer to SANDBOX-REQUIREMENTS.md. ## Verification - `git grep -n "noProfile" -- packages/ server/` returns zero matches. - `tsc --noEmit` passed for `@paperclipai/adapter-utils`, `@paperclipai/plugin-sdk`, and `@paperclipai/server`. - `command-managed-runtime.test.ts` passed: 22/22. - `environment-runtime.test.ts` passed: 24/24. ## Risks - Low risk. The flag was already a no-op. - A hidden external caller may still send the removed field. ## Model Used - OpenAI GPT-5, tool-enabled. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes: #` / `Refs: #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
4f539625f7 |
build(agent-runtime): ship ripgrep in the base image (#8976)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agents execute inside sandboxed runtime containers built from `docker/agent-runtime/Dockerfile.base` > - OpenCode's skill tooling shells out to ripgrep; when `rg` is not on PATH it tries to download a pinned build from `github.com/BurntSushi/ripgrep/releases` at run time > - In a sandbox with locked-down egress that download hangs ~127s and then fails, burning run budget on every agent run before the agent reaches its actual work > - The root repo `Dockerfile` already installs ripgrep; the agent-runtime base image drifted without it > - This pull request adds `ripgrep` to the base image's apt install so OpenCode uses the system binary and never reaches for the network > - The benefit is that every sandboxed agent run stops wasting ~2 minutes on a doomed download and spends its budget on real work ## Linked Issues or Issue Description No existing issue — problem described here per the bug report template: - **What happened:** Sandboxed agent runs using OpenCode stall for ~127 seconds at startup, then log `Transport error ... BurntSushi/ripgrep/releases/download/...` before continuing degraded. - **Expected behavior:** The agent starts working immediately; skill tooling finds `rg` on PATH. - **Root cause:** The agent-runtime base image (`docker/agent-runtime/Dockerfile.base`) does not ship ripgrep, so OpenCode falls back to downloading a pinned build at run time, which egress-restricted sandboxes block. - **Reproduction:** Run any OpenCode-backed agent in a sandbox with locked-down egress using the current agent-runtime image; observe the startup hang and transport error. Supersedes #8859. ## What Changed - Added `ripgrep` to the existing `apt-get install --no-install-recommends` list in `docker/agent-runtime/Dockerfile.base` - Added an explanatory comment documenting why ripgrep must be present (run-time download fallback + egress-restricted sandboxes), restoring parity with the root repo `Dockerfile` ## Verification - `docker build -f docker/agent-runtime/Dockerfile.base .` then `docker run --rm <image> rg --version` — prints the ripgrep version from the system package - Run an OpenCode-backed agent in an egress-restricted sandbox on the new image: no `BurntSushi/ripgrep` download attempt, no ~127s startup stall ## Risks - Low risk: no behavior change beyond shipping one additional apt package in the base image; slightly larger image size > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - Claude (Anthropic), model ID `claude-fable-5` (Fable 5), agentic coding via Claude Code with tool use; original change authored with Claude Opus 4.8 (1M context) and re-based/re-verified with Fable 5 ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
eedc7ddef2 |
Make ACP the default engine for local adapters (#9238)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Adapter packages are the bridge between the control plane and local agent harnesses such as Claude Code, Codex, and Gemini CLI. > - ACP support was concentrated in a separate `acpx_local` adapter, which made ACP feel like a separate agent choice instead of an execution capability of the harness adapters. > - Claude, Codex, and Gemini now have ACP-capable harnesses, so the native adapter should own ACP selection, fallback, config, transcript parsing, and environment diagnostics. > - The standalone ACPX adapter still needs a compatibility path for existing rows, but it should not be offered as an active adapter for new agents. > - This pull request moves the shared ACP runtime into `@paperclipai/acpx-engine`, wires Claude/Codex/Gemini local adapters to prefer ACP when prerequisites are available, and retires `acpx_local` to a tombstone. > - The benefit is one adapter per harness, richer ACP transcripts by default where possible, and a migration path for existing Claude/Codex ACPX agents. ## Linked Issues or Issue Description Closes #5932 — the broken default `acpx_local` Claude path is replaced by native `claude_local` ACP support, existing Claude/Codex ACPX rows migrate to native adapters, and new agents no longer choose the standalone ACPX adapter. Refs #4893 — original merged ACPX local adapter runtime that this PR replaces with native per-harness ACP engines. Refs #6590 — prior ACPX-Claude seamlessness work folded into the new native Claude ACP path. Refs #197 — related open generic ACP/Kiro adapter work; this PR does not close it because Kiro/custom generic ACP remains a separate adapter decision. Refs #7018 — related Kimi-specific `acpx_local` shell failure; this PR retires the built-in standalone adapter but does not add a native Kimi adapter. Refs #8864 — related ACPX prompt/API guidance PR; this PR moves runtime guidance into the shared/native ACP engine path instead of the old standalone adapter. Refs #8881 — related `acpx_local` POSIX shell failure from the old `acpx` pin; this PR updates ACP dependencies but does not claim custom/OMP ACP support as a first-class native adapter. Refs #8964 — related open `acpx_local` stderr cleanup PR; this PR makes the old runtime path obsolete for new agents but keeps it as a non-closing reference. Problem description: - The standalone `acpx_local` adapter duplicates Claude/Codex agent choices that already have first-class local adapters. - ACP should be an execution engine capability of each harness adapter when the underlying harness supports ACP. - Existing `acpx_local` agents should either migrate to native harness adapters or fail with an explicit retirement message instead of silently falling back to the process adapter. ## What Changed - Added `@paperclipai/acpx-engine` as the shared ACP execution, session-codec, CLI formatter, and UI parser package. - Wired `claude_local`, `codex_local`, and `gemini_local` to auto-select ACP by default when prerequisites pass, with `engine=cli` opt-out and `engine=acp` strict mode. - Added ACP config schema/UI fields, environment checks, session-codec preservation, transcript parsing, and adapter capability metadata for the native adapters. - Retired `acpx_local` to a server tombstone, removed its UI/package/runtime image surface, and added a migration for existing Claude/Codex ACPX agents. - Updated package manifests, lockfile, release tooling, docs, Kubernetes sandbox defaults, and tests. ## Verification - `corepack pnpm --filter @paperclipai/acpx-engine typecheck` - `corepack pnpm --filter @paperclipai/adapter-claude-local typecheck` - `corepack pnpm --filter @paperclipai/adapter-codex-local typecheck` - `corepack pnpm --filter @paperclipai/adapter-gemini-local typecheck` - `corepack pnpm --filter @paperclipai/acpx-engine exec vitest run` - `corepack pnpm --filter @paperclipai/adapter-claude-local exec vitest run src/server/acp.test.ts src/server/execute.acp-fallback.test.ts src/ui/build-config.test.ts` - `corepack pnpm --filter @paperclipai/adapter-codex-local exec vitest run src/server/acp.test.ts src/ui/build-config.test.ts` - `corepack pnpm --filter @paperclipai/adapter-gemini-local exec vitest run src/server/acp.test.ts src/ui/build-config.test.ts src/ui/parse-stdout.test.ts` - `corepack pnpm --filter @paperclipai/plugin-sdk ensure-build-deps && corepack pnpm --filter @paperclipai/server exec tsc --noEmit` - `corepack pnpm --filter @paperclipai/server exec vitest run src/__tests__/adapter-routes.test.ts src/__tests__/adapter-session-codecs.test.ts src/__tests__/adapter-models.test.ts` - `corepack pnpm --filter @paperclipai/ui typecheck` - `corepack pnpm --filter @paperclipai/ui exec vitest run src/adapters/metadata.test.ts src/adapters/adapter-display-registry.test.ts src/components/AgentConfigForm.test.ts src/components/AgentConfigForm.render.test.tsx src/components/transcript/RunTranscriptView.test.tsx` - `node --test scripts/bootstrap-npm-package.test.mjs scripts/release-package-map.test.mjs scripts/verify-release-registry-state.test.mjs` Note: the server typecheck script calls `pnpm` internally; this dev shell exposes pnpm through Corepack only, so I ran the two script steps manually with `corepack pnpm`. ## Risks - Migration changes existing `acpx_local` Claude/Codex agents to native adapter types and clears old ACPX task sessions/runtime state. - Custom ACP commands remain on the retired tombstone and will need a separate future adapter/plugin path. - ACP auto-selection depends on local Node and ACP server command prerequisites; remote and unsupported environments fall back to CLI unless `engine=acp` is explicit. - `@paperclipai/acpx-engine` is a new public package and needs npm trusted-publishing bootstrap before release automation can publish it. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI GPT-5 via Codex coding agent. Exact hosted model build and context-window size are not exposed in this runtime. Tool use included shell execution, repository editing, GitHub CLI operations, and local test/typecheck execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
398d746093 |
build(agent-runtime): harness runtime images for sandboxed execution (stage 3/3) (#7934)
> [!NOTE] > This is **stage 3 of 3** of the staged Kubernetes contribution: stage 1 is the kubernetes sandbox-provider plugin (#5790), stage 2 is the provider backend/hardening refresh filed separately, and this stage ships the runtime images those sandboxes run. ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Sandboxed agent execution (Refs #248) runs each agent turn in an isolated environment; the kubernetes sandbox provider (stage 1, #5790) schedules those runs as hardened pods > - A sandbox pod needs a runtime image with the harness CLI preinstalled: installing CLIs at run start is slow, flaky, and needs network egress the sandbox should not have > - There is no first-party image family for this, so every deployer would have to hand-roll Ubuntu + Node + CLI images per harness and solve signal handling, non-root, and image chaining themselves > - This PR ships the agent-runtime image family: a hardened base (non-root uid 1000, tini, git, the agent shim) plus one derived image per harness, a buildx bake file that chains them, and a publish workflow with cosign keyless signing > - The benefit is that any sandbox infrastructure, the kubernetes provider or otherwise, gets ready-made, signed, security-hardened per-harness runtime images that are verified in production across five harnesses ## Linked Issues or Issue Description Refs #248 (sandboxed agent execution proposal) and #5790 (the kubernetes sandbox provider, stage 1 of this contribution, which consumes these images as per-run runtime images via its adapter defaults). No issue covers the image gap itself, described in-PR: sandbox providers reference `ghcr.io/paperclipai/agent-runtime-*` images, but the repository contains neither the Dockerfiles nor the workflow that builds and publishes them. Without this, self-deployers cannot reproduce or audit the images their agent runs execute in. ## What Changed - `docker/agent-runtime/Dockerfile.base`: foundation image. Ubuntu 22.04 + Node 22 + git + tini (PID 1, signal propagation) + non-root `paperclip` user (uid/gid 1000) + the agent shim compiled in a Go build stage. `WORKDIR /workspace`, entrypoint `tini -- paperclip-agent-shim`. - One derived Dockerfile per harness: `opencode` (opencode-ai), `pi` (@mariozechner/pi-coding-agent), `codex` (@openai/codex), `gemini` (@google/gemini-cli, plus headless auth-mode settings), `claude` (@anthropic-ai/claude-code, symlinked as `claude-code`). Each installs the CLI as root, returns to uid 1000, and asserts the binary is on PATH at build time. - `acpx` and `hermes` Dockerfiles are included in the bake group but are not in the default publish scope (hermes is a stub until a CLI package exists). - `docker/agent-runtime/buildx-bake.hcl`: builds the whole family in one pass. Derived targets chain off the `base` target through bake `contexts` (the literal registry in each `FROM` is overridden to `target:base` at build time, so no intermediate push is needed). `REGISTRY` (default `ghcr.io/paperclipai`) and `VERSION` are overridable variables. - `tools/agent-shim/`: a small Go shim that runs as the container command. It reads `/run/paperclip/runtime-command.json` (`{ "command", "args" }`), resolves the harness CLI on PATH, and `syscall.Exec`s it so SIGTERM from the kubelet reaches the harness directly. Harness-agnostic, with unit tests. - `.github/workflows/agent-runtime-images.yml`: builds and pushes the default scope (base, opencode, pi, codex, gemini, claude) for linux/amd64 on `workflow_dispatch` (explicit version tag) or pushes to `master` touching these paths, then signs every digest with cosign keyless OIDC. Uses only `GITHUB_TOKEN`; no extra secrets. - `docker/agent-runtime/README.md`: image lineup, base contents, local build instructions, the runtime-command contract, and the security model. Additive only: nothing in the product loads these images. Deployments opt in via their sandbox provider configuration (for example the kubernetes plugin's image settings). ## Verification - `cd tools/agent-shim && go build ./... && go test ./... && go vet ./...`: all passing. - `docker buildx bake -f docker/agent-runtime/buildx-bake.hcl --print base opencode pi codex gemini claude`: resolves cleanly; every tag and build context lands on `ghcr.io/paperclipai/agent-runtime-*` and derived targets map the base ref to `target:base`. - Workflow YAML validated (parses, single job, no org-specific secrets). - This exact image family (built from these Dockerfiles, bake file, and workflow) is what runs agent execution in production on paperclip.inc, verified end-to-end across five harnesses (opencode, pi, codex, gemini, claude): each as a full loop from assigned issue to per-run runtime image in a sandboxed pod to completed run. ## Risks - Low risk: purely additive, nothing in paperclip-server or the UI references these files. The workflow only triggers on its own paths. - Derived images install harness CLIs `@latest` at build time; a broken upstream CLI release would surface at image build, not at run time, and the PATH assertion fails the build rather than shipping a broken image. - The hermes image is an explicit stub (documented in its Dockerfile) until a hermes CLI package exists; it is outside the default publish scope. - cosign signing is keyless OIDC with the workflow identity; no long-lived signing keys are introduced. ## Model Used Claude Opus 4.8 (claude-opus-4-8, 1M context, extended thinking, tool use via Claude Code). ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots (no UI changes) - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |