Commit Graph
8 Commits
Author SHA1 Message Date
Priya RamanandPaperclip df0bea2da7 fix(runner): recognize private-field property access in the wait guard
A private field named `#await` made the regex-literal check extract
the bare word `await`, so the scanner classified the `/` after it as
a regex start instead of division. That let the fake regex literal
mask a real `vi.waitFor(` or `expect.poll(` call on the same line.

Widen the word extraction to include a leading `#`, so a private
field's token (`#await`) never equals the bare keyword `await`.

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-04 02:16:24 +00:00
Priya RamanandPaperclip fdc16817d7 fix(runner): require a standalone await token in the wait guard
The regex-literal-start check treated an await-named property, such
as obj.await, as the await keyword. Code that divides after such a
property, like ${obj.await / divisor + (await vi.waitFor(...))},
could then mask the real vi.waitFor( call as part of a false regex
literal and hide it from the guard.

The check now looks at the character before the matched keyword. A
dot there means the word is a property name, not the keyword, so the
slash after it divides.

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-04 02:00:34 +00:00
Priya RamanandPaperclip 11836700be fix(runner): treat await as a regex-literal prefix in the wait guard
The scanner did not list await as a keyword that expects an
expression next, so it read the / in an await-prefixed regex
literal as division. A closing brace inside that regex then closed
template interpolation tracking early and hid a real vi.waitFor(
call from the guard. Add await to the keyword set and add a
regression test for this exact form.

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-04 01:55:58 +00:00
Priya RamanandPaperclip 627c244963 fix(runner): mask regex literals in the real-process wait guard
Inside a template's `${...}` expression, the interpolation scanner
counted every `{` and `}` toward the depth that finds the
interpolation's own closing brace. A regex literal like `/}/` or
`/^a{2,4}$/` carries a brace that belongs to the pattern, not to the
surrounding code, so the scanner closed the interpolation early and
hid a real wait call written after the regex.

Mask each regex literal to spaces before this depth count sees any of
its characters, the same way a string or template literal is already
masked. A short heuristic based on the character before the opening
`/` tells a regex literal from a division operator. Add tests for a
regex with a closing brace, a regex with a quantifier's paired braces,
and a wait-call pattern written only inside a regex literal's own
text.

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-04 01:44:21 +00:00
Priya RamanandPaperclip 2fbf9b5f95 fix(runner): scan template interpolations in the real-process wait guard
The source-masking step treated a backtick template's `${...}`
expression as plain text and masked it, so a wait call written inside
an interpolation never matched. The step now masks only the literal
text of a template and scans the code inside `${...}` the same way it
scans code outside any literal.

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-04 01:35:32 +00:00
Priya RamanandPaperclip f7612c8a55 fix(runner): close the Greptile gaps on the real-process wait guard
Race each waitForCapabilityLiveProcess attempt against the deadline's
remaining time, so a callback that never settles fails at the stated
10,000ms envelope instead of running past it. Keep the same deadline
diagnostic (label, elapsed time, last observed error).

Make the bare-real-process-wait guard inspect only a wait call's own
options argument for an explicit timeout, not the whole argument list,
so a same-shaped timeout option nested in the callback body no longer
exempts a bare wait. Mask comments and string or template literals
before the guard scans for vi.waitFor( or expect.poll(, so source text
that only mentions those patterns can no longer trigger a false
violation. Add regression tests for both gaps.

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-04 01:16:42 +00:00
Priya RamanandPaperclip 140dbc8bf0 test(runner): close the real-process wait gap in the second live test file
The Rust and TypeScript interpretation test in
runnerd-codex-transport.test.ts spawned the real paperclip-runnerd binary
and a real fake-codex-app-server process, ran one turn, and polled two
provider trace files for a terminal status with vitest's default 1,000ms
expect.poll deadline. Measurement showed the real envelope for this path
(534ms to 640ms across 12 uncontended samples) sits inside that default,
so the poll could time out under load even though the trace files would
still arrive.

Move the real-process wait helper out of live-session.test.ts into a
shared test/ module and export it, so both real-process test files import
the same helper and deadline instead of one file re-declaring a marker
meant only for waits that settle in-process. Replace the bare expect.poll
with the shared helper, keeping the same toEqual/objectContaining
assertion. Extend the bare-real-process-wait check script to also reject
a bare expect.poll( in src/live/**, on the same terms as vi.waitFor(:
accept the in-process marker or an explicit timeout option that already
states its own envelope.

Rewrite the deadline's evidence comment with the reliable, uncontended
measurements for both real-process waits it now covers (163ms-187ms and
534ms-640ms) and correct file:line anchors, and state the actual margin
the deadline keeps (over 15 times the larger observed maximum) instead of
an inflated one.

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-04 00:43:13 +00:00
Dotta 560e7e48b5 feat(runner): add SDK and developer tooling (#12608)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The runner package already provides the production protocol and
execution spine.
> - Contributors still need stable SDK surfaces, deterministic test
tools, and local inspection tools.
> - Those surfaces share generated contracts and must change as one
package boundary.
> - This pull request adds the package-local SDK, labs, examples, and
drift checks.
> - The benefit is a reviewable developer platform that does not change
application execution selection.

## Linked Issues or Issue Description

**Subsystem affected**

`packages/paperclip-runner` — runner SDK, conformance tools, and
developer tooling.

**Problem or motivation**

The production runner spine is present, but package consumers cannot
build deterministic integrations, inspect sessions, or verify
provider-neutral behavior through supported surfaces.

**Proposed solution**

Add browser, React, standalone, live-session, scenario, conformance, and
evaluation surfaces. Add generated contract inventories and
package-local verification scripts. Keep production application routing
unchanged.

**Alternatives considered**

We considered splitting each generated catalog, SDK surface, and demo
into separate pull requests. Those changes share exports, fixtures, and
drift gates. Splitting them would create intermediate package states
that do not build.

**Roadmap alignment**

No overlapping item appears in `ROADMAP.md`. This work extends the
runner package that is already on `master`.

## What Changed

- Add browser, React, standalone, live-session, and issue-thread SDK
surfaces.
- Add deterministic mock control-plane, scenario, conformance, replay,
and evaluation tools.
- Add bounded Codex, OpenCode, and ACPX development transports and
fixtures.
- Keep deferred managed-provider execution fail-closed. Persisted
compatibility data remains readable.
- Add generated capability inventories with their source files and drift
checks.
- Add examples, package documentation, browser checks, and
clean-consumer checks.
- Preserve the reviewed protocol bounds, replay compatibility aliases,
process environment isolation, and semantic redaction limits.
- Update the ACPX package patch that the existing workspace patch
registry already tracks.
- Do not change `pnpm-lock.yaml`, repository workflows, server runtime
selection, or the application UI.

## Verification

GitHub Actions is the verification authority for this pull request. The
repository CI, package TypeScript and Rust checks, package tests,
generated-output drift checks, browser checks, security scans, and
Greptile review must pass on the exact head.

Local test suites were not run because this series uses parallel GitHub
Actions for verification.

## Risks

This is a large greenfield package change. The main risks are public
export drift, generated-output drift, and optional React consumer
compatibility. Package boundary checks, clean-consumer checks, and
browser tests cover those risks. Production adapter selection and server
execution are outside this pull request.

## Stack

1. **This PR:** runner SDK and developer tooling.
2. [Codex production server
integration](https://github.com/paperclipai/paperclip/pull/12616).
3. [Provider-neutral task-thread
UI](https://github.com/paperclipai/paperclip/pull/12617).

## Model Used

OpenAI Codex, GPT-5, high-reasoning mode, with tool use and code
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 described the issue in-PR following the feature request
template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change and contains no internal
Paperclip ticket id
- [ ] 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 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
2026-08-31 21:33:11 -05:00