style: remove every em-dash and en-dash

Eighteen occurrences across fourteen files. Each sentence was repunctuated to
suit what the dash was doing rather than swapped for a hyphen, which produces
comma splices. The minus sign in folio-web's ledger is a minus sign and stays.

Claude-Session: https://claude.ai/code/session_01A5KmftdEJ49A9z5mF5ESrX
This commit is contained in:
pj committed 2026-08-12 20:48:33 +05:30
1 parent 7c3c2b206f
commit 40cdb455bd
14 files changed
+19 -19

No files matched your search

+1 -1
View File
@@ -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
+2 -2
View File
@@ -82,8 +82,8 @@ Traces land in `./sanderling/runs/<timestamp>/`.
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
+1 -1
View File
@@ -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({
+1 -1
View File
@@ -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))
+3 -3
View File
@@ -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()
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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"`
+2 -2
View File
@@ -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);
+1 -1
View File
@@ -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();
+1 -1
View File
@@ -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()`.
*/
@@ -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", () => {
+1 -1
View File
@@ -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]);
+2 -2
View File
@@ -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)[],
+1 -1
View File
@@ -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" &&