diff --git a/CLAUDE.md b/CLAUDE.md index 0299e96..0f7ffe5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,7 +17,7 @@ ## PR Rules - - Simple PR title, few-line description. Never write a wall of text — nobody reads it. + - Simple PR title, few-line description. Never write a wall of text. Nobody reads it. - Everything lowercase in PR titles, descriptions, and comments. ### PR Description Rules diff --git a/examples/folio/README.md b/examples/folio/README.md index 8e539ce..e96158f 100644 --- a/examples/folio/README.md +++ b/examples/folio/README.md @@ -82,8 +82,8 @@ Traces land in `./sanderling/runs//`. The same `sanderling/spec.ts` runs under either generator: `--generator seeded` (the default weighted fuzzer) or `--generator llm`, where a vision model picks -from the SAME weighted candidate set — reading the screenshot plus a numbered, -weight-annotated list of concrete actions — and returns one number. The spec's +from the SAME weighted candidate set (reading the screenshot plus a numbered, +weight-annotated list of concrete actions) and returns one number. The spec's `generator = llm({ model, instructions })` export configures it. ```sh diff --git a/examples/folio/sanderling/spec.ts b/examples/folio/sanderling/spec.ts index 4316613..051c97f 100644 --- a/examples/folio/sanderling/spec.ts +++ b/examples/folio/sanderling/spec.ts @@ -192,7 +192,7 @@ export const actionsRoot = weighted( // The LLM generator is orthogonal to actionsRoot: with `--generator llm` a model // picks from the SAME weighted candidate set above, reading the screenshot and a // numbered, weight-annotated list; the default `--generator seeded` ignores it. -// instructions describe only WHAT the app is, never HOW to test it — the model +// instructions describe only WHAT the app is, never HOW to test it. The model // figures out how to surface bugs on its own. With a plain OpenAI key, drop the // vendor prefix from the model id. export const generator = llm({ diff --git a/internal/driver/chrome/translate.go b/internal/driver/chrome/translate.go index 091c0a7..5883a44 100644 --- a/internal/driver/chrome/translate.go +++ b/internal/driver/chrome/translate.go @@ -68,7 +68,7 @@ func TranslateStringSelector(selector string) (string, bool, error) { // - everything else passes through, including non-ASCII // // Callers should not pass this output into identifier contexts (class names, -// tag names) — use an attribute selector form (`[class~="..."]`) instead. +// tag names). Use an attribute selector form (`[class~="..."]`) instead. func cssEscape(value string) string { var builder strings.Builder builder.Grow(len(value)) diff --git a/internal/ltl/evaluator_test.go b/internal/ltl/evaluator_test.go index a17d6c0..dd2304a 100644 --- a/internal/ltl/evaluator_test.go +++ b/internal/ltl/evaluator_test.go @@ -45,9 +45,9 @@ func TestThunk_TransitionFromHoldToViolate(t *testing.T) { wantSequence := []Verdict{ VerdictHolds, // true VerdictHolds, // true - VerdictViolated, // false — latches - VerdictViolated, // true after violation — still violated - VerdictViolated, // true after violation — still violated + VerdictViolated, // false: latches + VerdictViolated, // true after violation: still violated + VerdictViolated, // true after violation: still violated } for index, want := range wantSequence { got := evaluator.Observe() diff --git a/internal/runner/llm_source.go b/internal/runner/llm_source.go index ac0c172..368722b 100644 --- a/internal/runner/llm_source.go +++ b/internal/runner/llm_source.go @@ -34,7 +34,7 @@ const ( // screenshot, picks ONE number, and echoes that action so a mismatch can be // caught. The app-specific description (spec instructions) is appended. const llmSystemPrompt = "You are exercising a UI to find bugs. Each turn you get a screenshot and a numbered list of concrete actions, each with a weight hinting how much the test author wants it exercised (higher = more). " + - "Pick the ONE action most likely to make progress or expose a defect. Bugs often hide in repeated or rapid actions, so once a screen works, deliberately stress it — for example submitting the same form twice in a row to check it is not applied more than once — rather than only advancing. " + + "Pick the ONE action most likely to make progress or expose a defect. Bugs often hide in repeated or rapid actions, so once a screen works, deliberately stress it (for example submitting the same form twice in a row to check it is not applied more than once) rather than only advancing. " + "Respond with your reasoning, the chosen number, and chosen_action copied verbatim from that line. For a typing action, also provide the text to enter." // llmSource selects each step's action with an OpenAI-compatible vision model diff --git a/internal/trace/writer.go b/internal/trace/writer.go index 6e74414..52f9809 100644 --- a/internal/trace/writer.go +++ b/internal/trace/writer.go @@ -92,7 +92,7 @@ type Action struct { // LLMChoice is the 1-based number the model picked from the candidate list; // LLMChosenAction is the action description it echoed for that number. The // runner strict-skips when the echo disagrees with the numbered entry, so on - // a recorded action the two always agree — the replay UI shows them to + // a recorded action the two always agree; the replay UI shows them to // confirm the reasoning matched the executed action. LLMChoice int `json:"llm_choice,omitempty"` LLMChosenAction string `json:"llm_chosen_action,omitempty"` diff --git a/pkg/spec/src/ltl.ts b/pkg/spec/src/ltl.ts index e0fff27..3ef5b63 100644 --- a/pkg/spec/src/ltl.ts +++ b/pkg/spec/src/ltl.ts @@ -12,8 +12,8 @@ export function next(predicate: () => boolean): Formula { return globalThis.__sanderling__.next(predicate); } -// An unbounded `eventually` never forces a violation within a finite run — -// prefer `.within(n, unit)` when you want the verifier to fail a property +// An unbounded `eventually` never forces a violation within a finite run. +// Prefer `.within(n, unit)` when you want the verifier to fail a property // that stalls. export function eventually(predicate: () => boolean): EventuallyFormula { return globalThis.__sanderling__.eventually(predicate); diff --git a/pkg/spec/src/runtime-entry.ts b/pkg/spec/src/runtime-entry.ts index 8d10eda..23114d9 100644 --- a/pkg/spec/src/runtime-entry.ts +++ b/pkg/spec/src/runtime-entry.ts @@ -151,7 +151,7 @@ export function installRuntime( defineLockedGlobal("__sanderlingExtractors__", () => evaluateExtractors()); // __sanderlingSetupAction__ walks ONLY the setup generator once, for the LLM // action generator (Go), which drives selection itself and must not run the - // seeded action root — but still wants setup's precondition steps (e.g. login) + // seeded action root, but still wants setup's precondition steps (e.g. login) // to run first. Returns null when setup is unset or yields nothing. defineLockedGlobal("__sanderlingSetupAction__", () => { resolveRoot(); diff --git a/pkg/spec/src/types.ts b/pkg/spec/src/types.ts index 62d7ed2..f748d83 100644 --- a/pkg/spec/src/types.ts +++ b/pkg/spec/src/types.ts @@ -113,7 +113,7 @@ export interface State { /** * State as observed inside a web (V8/browser) extractor. Adds the live - * `document` and `window` handles. `state.document` is V8-only — goja-side + * `document` and `window` handles. `state.document` is V8-only, so goja-side * predicates do not see it; if you need DOM data in a predicate, surface it * via an `extract()`. */ diff --git a/replay-ui/src/__tests__/action-format.test.ts b/replay-ui/src/__tests__/action-format.test.ts index fc65fa6..87fb9e2 100644 --- a/replay-ui/src/__tests__/action-format.test.ts +++ b/replay-ui/src/__tests__/action-format.test.ts @@ -7,7 +7,7 @@ import { } from "../lib/action-format"; import { summary } from "./fixtures"; -// Bug class: selector parsing mislabels every action row — splitting on the +// Bug class: selector parsing mislabels every action row. Splitting on the // wrong colon, treating a value-with-colon as the kind, or dropping the prefix // ellipsis would render the wrong target tag for every step. describe("parseSelector", () => { diff --git a/replay-ui/src/hooks/useTheme.ts b/replay-ui/src/hooks/useTheme.ts index 9471c6b..b4ae6f0 100644 --- a/replay-ui/src/hooks/useTheme.ts +++ b/replay-ui/src/hooks/useTheme.ts @@ -28,7 +28,7 @@ export function useTheme(): { theme: ThemeMode; toggle: () => void } { try { window.localStorage.setItem(STORAGE_KEY, theme); } catch { - // private mode or storage disabled — theme still applies for the session. + // private mode or storage disabled. Theme still applies for the session. } }, [theme]); diff --git a/replay-ui/src/lib/run-history.ts b/replay-ui/src/lib/run-history.ts index 09e925f..2dc986f 100644 --- a/replay-ui/src/lib/run-history.ts +++ b/replay-ui/src/lib/run-history.ts @@ -18,8 +18,8 @@ export interface RunHistory { // that armed it, so the checker records the violation on the DETECTION step // while its witness names the CAUSE step. The timeline dot (the backend's // markViolations) already sits on the cause step; mirror that here so the -// Violations tab and property lanes light up on the same step — the guilty -// action — not the unrelated action that happened to be running when the +// Violations tab and property lanes light up on the same step: the guilty +// action, not the unrelated action that happened to be running when the // obligation resolved. Steps are cloned, never mutated in place. export function relocateViolationsToCause( steps: (Step | null)[], diff --git a/sidecar/build.gradle.kts b/sidecar/build.gradle.kts index 022cc14..968b7da 100644 --- a/sidecar/build.gradle.kts +++ b/sidecar/build.gradle.kts @@ -26,7 +26,7 @@ val maestroVersion = "2.4.0" // Maestro 2.4.0 still declares grpc-netty:1.50.2 and grpc-okhttp:1.50.2 which // were compiled against AbstractManagedChannelImplBuilder removed in grpc-core 1.64+. // Force them to the version we pin so they stay binary-compatible. -// Also exclude GraalVM JS — not used by our sidecar and causes shadow JAR expansion errors. +// Also exclude GraalVM JS: not used by our sidecar and causes shadow JAR expansion errors. configurations.all { resolutionStrategy.eachDependency { if (requested.group == "io.grpc" &&