mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-31 14:06:50 +01:00
v1.91.167.0 fix(evals): plan-design focus and tpa pitch detectors accept the rewordings Opus 5.5 uses (GSTA-57) (#3320)
* fix(evals): plan-design focus and tpa pitch detectors accept the rewordings Opus 5.5 uses (GSTA-57) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * v1.91.167.0 stamp Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
a3ed43c9b3
commit
6a1b3be141
11 files changed
+227
-14
No files matched your search
+18
-1
@@ -1,5 +1,14 @@
|
||||
# Changelog
|
||||
|
||||
## [1.91.167.0] - 2026-10-20
|
||||
|
||||
**Two paid detectors now accept the rewordings Opus 5.5 actually uses, with their negative controls kept (daily flaky-fix pass, GSTA-57).** `plan-design-with-ui-scope` went red three times on the ledger with "no acknowledged Design focus" while the agent had asked Step 0D and a numbered finding; `tpa-absent-darwin` went red once on a valid download pitch.
|
||||
|
||||
### Fixed
|
||||
- **`plan-design-with-ui-scope` focus detector (test/skill-e2e-plan-design-with-ui.test.ts).** The Step 0A rating now counts as any sentence that scores design completeness out of 10 (run 39363705692 wrote "I rated this plan 4/10 for design completeness"; the 0A example says "This plan is a 3/10 on design completeness"), and the all-seven option may name the seven any way ("All 7 areas (recommended)"). The title, focus and option-order requirements are unchanged. Replays of all three ledger failures (runs 39315041557, 39344306426, 39363705692, attempt 1) and their passing reruns now pass the detector; 39363705692's captured calls are a fixture (`test/fixtures/design-ui-focus-capture-39363705692.json`). New negative controls: a score and "design completeness" in different sentences, a score out of 7, a non-design completeness score, an all-seven option without a focus title, a non-leading or issue-labelled all-seven option, a bare "All 7" option, and the run without its focus question all still fail.
|
||||
- **`tpa-absent-darwin` pitch detector (test/helpers/third-party-actions.ts).** The canonical phrase may name Aside as "it" once the macOS 15+ floor follows ("If you want to use Aside: download it (macOS 15+) at aside.com", run 39315041557, now a capture in `test/fixtures/third-party-actions-pitch-captures.json`). It keeps the canonical phrase's guards: clause start, no negation before it, no quoted or reported mention. The short forms without the floor still count only at a sentence start.
|
||||
- **Gate integrity:** test-only detector edits. No threshold, trial count, case kind, quarantine or budget changed.
|
||||
|
||||
## [1.91.166.0] - 2026-10-20
|
||||
|
||||
**Two load-sensitive free tests from the flaky ledger now measure what they test.** Daily flaky-fix pass, 2026-10-20, free and load-sensitive group.
|
||||
@@ -64,6 +73,7 @@
|
||||
- **Gate integrity (train block only):** under a `train` block, PR pushes no longer start paid slices; trains, screens and the backstop gate instead. Train and bisect runs never reuse a verdict and never bind one for reuse. No threshold, trial count, case kind or selection changed.
|
||||
- **Gate integrity (always, GSTA-48 P3-1):** when the readiness job blocks a PR head, a new `readiness-comment` job replaces an existing `## E2E Evals` comment with "NOT RUN on <head>", so an earlier PASS no longer stands beside a head that never ran. It posts nothing when no such comment exists. A slice killed before its upload step counts as incomplete.
|
||||
- **Gate integrity, widening (`plan-design-with-ui-scope` focus detector, GStack Minder-approved):** the Step 0D focus question also counts when its title names the focus (the title ends at the first line break or before `Project/branch/task:`), its body carries the step's own rating sentence ("I('ve) rated this plan N/10 on design completeness"), and it offers at least two options, one of which starts "All 7" or "All seven" (design or review) dimensions or passes. Opus 5.5 titled the question only "Review focus" in both attempts of run 39298269902, so the detector missed it. In the second attempt the finding detector also counted the focus question as the review finding, because its one-line title names hierarchy and panels. A recognized focus question can no longer count as a finding. Free replays of both captured attempts (`test/fixtures/design-ui-focus-capture-39298269902-a1.json` and `-a2.json`, registered in the case's touchfiles) pass. Every existing negative control still fails, as do these new ones: an issue-labeled finding that carries the rating, a single-option focus question, a focus question without a leading all-7 option, and a 4/7 rating. No threshold, trial count, case kind or ceiling changed.
|
||||
|
||||
## [1.91.161.0] - 2026-10-19
|
||||
|
||||
**`gstack-pregate` works on Django, Dart and Flutter repos, and on branches that only touch assets or tool config.** Before, a Django migration, an `admin.py`, a template, a font, a vendored licence or `.pre-commit-config.yaml` stopped `/ship` with `PREGATE_NO_LANE` in a repo that had never opted in, and every touched `_test.dart` file did the same. `gstack-pregate init` now drafts a policy from the repo instead of writing a fixed example. Contributed by @arlophoenix (#3285) and @szsunyuan (#3290); reported by @dgrant (#3266, #3267, #3268, #3269).
|
||||
@@ -79,7 +89,6 @@
|
||||
- **Review fixes on the Dart port.** A `cd` inside a pipeline, an alternative, a background job, shell control flow, a command substitution or a redirected subshell now leaves a CI lane's test set unknown (it may run any test) instead of resolving later paths against the wrong directory, which could drop a platform obligation. Dart directives are read to their `;` whatever the line indentation, metadata before a directive and semicolons inside a URI are handled, and nested block comments are skipped, so an unindented conditional import or a long `show` list no longer loses its edges.
|
||||
- **Gate integrity:** new free regressions in `test/pregate-non-js.test.ts` (Django, assets and licence, init, and the two review fixes, each with a negative control) and `test/pregate-dart.test.ts`. Each new positive case fails on the tree before this change. No existing test, threshold, trial count or case kind changed; `test/helpers/pregate-fixture.ts` only reports more about a failed git spawn. `test/pregate-dart.test.ts` and `test/pregate-non-js.test.ts` join the other pregate fixture files in `scripts/lib/windows-curation.ts`'s known-incompatible list: the Dart stand-ins are bash scripts on a colon-joined PATH, and the bin cases expect the Linux-host lanes verdict.
|
||||
|
||||
|
||||
## [1.91.160.0] - 2026-10-19
|
||||
|
||||
**Dart and Flutter projects get the right reviewers and the right test command.** A Dart change matched no diff-scope category except its test file, so a Flutter widget PR ran only the testing pass and skipped design, performance and security. Contributed by @arlophoenix (#3284).
|
||||
@@ -170,6 +179,7 @@
|
||||
|
||||
### Changed
|
||||
- **Gate integrity:** `browse/test/terminal-agent.test.ts` adds `activeTab` to the exact `/health` keys and updates its stub for the now-synchronous `isHealthy` and the new `probeActiveTab`; its no-token assertions are unchanged. `browse/test/busy-active-tab.test.ts` and `browse/test/command-timeout-report.test.ts` are new. No threshold, trial count or case kind changed.
|
||||
|
||||
## [1.91.154.0] - 2026-10-19
|
||||
|
||||
**/cso can verify Rails repairs in a read-only checkout, its retained Git history no longer brings back credential files the snapshot leaves out, a repair whose external assertions fail is now reported as `ASSERTION_FAILED` instead of a misleading `INCOMPATIBLE_INPUT`, and a security assertion can accept several safe rejection statuses while still requiring the secret to be absent.** The helper keeps `.env`, `master.key`, keys and agent configuration out of the readable tree, but `history.txt` captured `git log -p` in full, so a committed `.env` came back through its diff whenever the value wasn't credential-shaped enough for the redactor. Paid qualification run 39186328569 caught this when the private corpus's planted `.env` value showed up in the judge's helper state.
|
||||
@@ -214,6 +224,7 @@
|
||||
|
||||
### Added
|
||||
- **`docs/howto-bring-up-a-first-deploy.md`:** a vendor-neutral walkthrough for when /setup-deploy stops at "Nothing is deployed yet" (host, services, env and secrets, DNS, verification, and what to have ready when you rerun /setup-deploy). Linked from the README and docs/skills.md. Fixes #3150. From #3264 by @szsunyuan.
|
||||
|
||||
## [1.91.150.0] - 2026-10-19
|
||||
|
||||
**The paid evals that still pinned older models now run on the current generation, and two cases that went red on the move are repaired at their cause.** Garry's direction (2026-10-18) is to stop testing older frontier models, so these files are re-baselined as a fresh measured reference rather than held to a threshold change.
|
||||
@@ -1329,6 +1340,7 @@ The first full paid v2 baseline produced 64 receipts and 64 judge records, then
|
||||
## [1.91.83.0] - 2026-10-11
|
||||
|
||||
**gstack ships itself under `stamp-at-merge`.** `.gstack/ship-policy.json` flips `queue_mode` to `stamp-at-merge`, `bump` to `patch` and names `garrytan` under `maintainers`. The version is now allocated once, when the PR is next in the queue (`gstack-restamp --next --expect-base --expect-order`), instead of claimed at open and re-slotted on every reorder; every bump is PATCH, so unattended ships never meet the MINOR/MAJOR prompt; and `/review` contributor mode reads the maintainer set from the file instead of calling the collaborators API. `docs/ship-policy.md` gains the queue-side procedure: what a PR carries before its stamp, who runs the restamp and when, and what the merging thread verifies on the exact SHA instead of "VERSION above main".
|
||||
|
||||
## [1.91.82.0] - 2026-10-11
|
||||
|
||||
**Plan-review reality rows name their inputs.** The `{{PLAN_REALITY_ROWS}}` prose in plan-eng-review, plan-ceo-review and the autoplan CEO/Eng phases wrote `gstack-plan-reality check --phase <p> <review>` without saying what `<review>` is, and the completion summary cited a `PLAN_REALITY` line no step produced. The check now reads `<review-file|->` (the review you wrote, or stdin) and says it prints the `PLAN_REALITY:` line the summary cites. Found by the plan-eng-review workflow judge on an unrelated PR (clarity 3 / actionability 3 median, both citing these two references).
|
||||
@@ -2796,6 +2808,7 @@ Run `bun run typecheck` and `bun run typecheck:test` before you push; both are f
|
||||
- Open PRs touching `lib/cso` should run `bun run format:cso` before rebasing.
|
||||
- Builds on the typecheck work in #2447, contributed by @laddtnov.
|
||||
- Coordinated with #2994 (v1.91.8.0), which retired the never-green finding-count evals this wave had been repairing.
|
||||
|
||||
## [1.91.11.0] - 2026-09-30
|
||||
|
||||
gstack now looks up its state folder one way everywhere, and the five most copy-pasted or oversized parts of the codebase each have a single owner. Before, about 50 scripts, hooks and libraries each resolved the state folder with their own rule, and the rules disagreed. If you set `GSTACK_HOME`, `GSTACK_STATE_DIR` or `GSTACK_STATE_ROOT`, telemetry, analytics, update-check snoozes, the egress ledger and hook logs now all land in the folder you chose. Nothing is moved for you. Run `~/.claude/skills/gstack/bin/gstack-paths --explain` to see the active folder and whether `~/.gstack` still holds older state; [docs/state-root.md](docs/state-root.md) has the move recipe.
|
||||
@@ -3904,6 +3917,7 @@ Run /review on a branch you suspect is over-built and read the `[ADVISORY]` rows
|
||||
- Eval-store schema v2: harvest records carry `{insertions, deletions, net}`; `recordE2E` now populates `tokens_used`.
|
||||
- Touchfiles dep lists closed gaps (fixtures, judge helper, harness, ship render) and the context-budget ratchet fixture was re-captured, locking the AskUserQuestion reduction so it cannot silently regress.
|
||||
- New coverage: TEMP_DIRS widening + remote-serving asymmetry, shortcut-marker writer/harvester grammar joint, sandbox-doctor shell guards, GSTACK_FREE_JOBS parsing, laundered-ls-remote shims, digest freshness/budget/writer tripwires, and a real generator round-trip through the version bump.
|
||||
|
||||
## [1.74.0.0] - 2026-08-29
|
||||
|
||||
**Green now means green: every test runs somewhere, provably.**
|
||||
@@ -4516,6 +4530,7 @@ If you run gstack from a build that pulled in community or fork-ported code, thi
|
||||
|
||||
#### For contributors
|
||||
- New regression guards pin each security property against a silent revert: a static tripwire for the constant-time `validateAuth`, a table-driven suppression test over the exported `URL_PASSWORD_PLACEHOLDER_WORDS`, an unconditional-write test for the state-dir ignore, a static tripwire for the iOS Release compile-out, and the restored `Bun.spawn` contract tests.
|
||||
|
||||
## [1.67.0.0] - 2026-08-16
|
||||
|
||||
**The tracker wave: browse survives macOS, installs are complete,**
|
||||
@@ -6831,6 +6846,7 @@ A `/ship` run starts ~3x lighter and pulls in each heavy step's instructions onl
|
||||
#### For contributors
|
||||
- `setup` links `sections/` into the prefixed Claude + Kiro skill dirs; `--host all` now fails the build on any host failure, not just claude.
|
||||
- New section templates live at `<skill>/sections/*.md.tmpl`; regenerate with `bun run gen:skill-docs`.
|
||||
|
||||
## [1.53.1.0] - 2026-05-30
|
||||
|
||||
## **Workspace and scripted setup never hang on a hidden prompt again. Installing the plan-tune hooks is now flag-driven with safe defaults.**
|
||||
@@ -6938,6 +6954,7 @@ If you generate PDFs on Linux or inside a container, emoji in section headers an
|
||||
|
||||
#### Fixed
|
||||
- make-pdf no longer renders emoji as `.notdef` tofu (▯) on Linux.
|
||||
|
||||
## [1.52.1.0] - 2026-05-27
|
||||
|
||||
## **Brain-aware planning lands. Five planning skills read structured context from any personal gbrain before asking — same questions, smarter answers, no token tax.**
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# gstack digest v1.91.166.0 — regenerate/re-copy after upgrading gstack
|
||||
# gstack digest v1.91.167.0 — regenerate/re-copy after upgrading gstack
|
||||
|
||||
Behavioral rules from gstack (https://github.com/garrytan/gstack), compressed
|
||||
for agent hosts without a full skill install. The full skills add workflows,
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gstack",
|
||||
"version": "1.91.166",
|
||||
"version": "1.91.167",
|
||||
"description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
{
|
||||
"provenance": {
|
||||
"kind": "public native AskUserQuestion calls and answers only (observation.json fingerprints[].nativeCall, byte-exact)",
|
||||
"runId": 39363705692,
|
||||
"artifact": "paid-slice-4-a1",
|
||||
"headSha": "a592321668e26dcce54c1ca801d1e5eb2ba9b4aa",
|
||||
"recordedOutcome": "ceiling_reached",
|
||||
"recordedReviewCount": 1,
|
||||
"recordedStep0Count": 3,
|
||||
"recordedPassed": false,
|
||||
"note": "The Step 0D question was titled 'Review focus' and carried 'I rated this plan 4/10 for design completeness' in its body, with options 'All 7 areas (recommended)' and 'Only specific areas'. The runner reached the review ceiling on the issue-labeled D4 finding, but the focus predicate accepted only an 'on design completeness' rating sentence and an all-7 option naming dimensions or passes, so the gate failed."
|
||||
},
|
||||
"calls": [
|
||||
{
|
||||
"preReview": true,
|
||||
"observedAtMs": 69895,
|
||||
"call": {
|
||||
"sessionId": "1eaa205b-5459-4e0b-9053-5a622b1da36c",
|
||||
"toolUseId": "toolu_012Dq5ZTH6tmVbMWgpH2dzzz",
|
||||
"questions": [
|
||||
{
|
||||
"question": "D1 — Review focus\nProject/branch/task: User Dashboard plan on main, design review.\nELI10: I rated this plan 4/10 for design completeness. The biggest gaps are: no visual hierarchy or layout per screen size, no real copy or actions for the empty/loading/error states, and no design system (fonts, colors, spacing). Next I'll make visual mockups, then go through all 7 design areas. You can narrow the review to a few areas instead.\nStakes if we pick wrong: if we narrow too far, unreviewed gaps such as accessibility or responsive layout get decided ad hoc during the build.\nRecommendation: A because the plan is thin on design across the board, and a full pass costs minutes.\nCompleteness: A=10/10, B=6/10\nPros / cons:\nA) All 7 areas (recommended)\n ✅ Covers hierarchy, states, journey, slop risk, design system, responsive and a11y\n ✅ Every gap gets its own decision before anyone writes code\n ❌ More questions to answer, about one per open gap across the passes\nB) Only the areas I name\n ✅ Faster, with fewer decisions in the parts you care most about\n ✅ Lets you skip areas you plan to cover in another review\n ❌ Areas you skip go unreviewed and get decided ad hoc later\nNet: full coverage at the cost of more questions, vs speed with blind spots.",
|
||||
"header": "Focus",
|
||||
"multiSelect": false,
|
||||
"options": [
|
||||
{
|
||||
"label": "All 7 areas (recommended)",
|
||||
"description": "✅ Covers every design dimension. ✅ Each gap gets its own decision. ❌ More questions to answer."
|
||||
},
|
||||
{
|
||||
"label": "Only specific areas",
|
||||
"description": "✅ Faster, fewer decisions. ✅ Skip areas covered elsewhere. ❌ Skipped areas go unreviewed."
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"answered": true,
|
||||
"failed": false,
|
||||
"answers": {
|
||||
"D1 — Review focus\nProject/branch/task: User Dashboard plan on main, design review.\nELI10: I rated this plan 4/10 for design completeness. The biggest gaps are: no visual hierarchy or layout per screen size, no real copy or actions for the empty/loading/error states, and no design system (fonts, colors, spacing). Next I'll make visual mockups, then go through all 7 design areas. You can narrow the review to a few areas instead.\nStakes if we pick wrong: if we narrow too far, unreviewed gaps such as accessibility or responsive layout get decided ad hoc during the build.\nRecommendation: A because the plan is thin on design across the board, and a full pass costs minutes.\nCompleteness: A=10/10, B=6/10\nPros / cons:\nA) All 7 areas (recommended)\n ✅ Covers hierarchy, states, journey, slop risk, design system, responsive and a11y\n ✅ Every gap gets its own decision before anyone writes code\n ❌ More questions to answer, about one per open gap across the passes\nB) Only the areas I name\n ✅ Faster, with fewer decisions in the parts you care most about\n ✅ Lets you skip areas you plan to cover in another review\n ❌ Areas you skip go unreviewed and get decided ad hoc later\nNet: full coverage at the cost of more questions, vs speed with blind spots.": "All 7 areas (recommended)"
|
||||
},
|
||||
"unansweredQuestionIndices": [],
|
||||
"answeredAt": "2026-10-20T03:33:37.196Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"preReview": true,
|
||||
"observedAtMs": 101896,
|
||||
"call": {
|
||||
"sessionId": "1eaa205b-5459-4e0b-9053-5a622b1da36c",
|
||||
"toolUseId": "toolu_01RxhoWvhm7uZSXn5fTELSb9",
|
||||
"questions": [
|
||||
{
|
||||
"question": "Want outside design voices before the detailed review?\nD2 — Outside design voices\nProject/branch/task: User Dashboard plan on main, design review.\nELI10: Before the 7 passes I can bring in two extra reviewers. Codex checks the plan against hard design rules and a litmus scorecard. A separate Claude agent does a fresh completeness read. That cross-checks my judgment, but it takes longer.\nStakes if we pick wrong: skipping means every finding rests on one reviewer; running it adds a few minutes.\nRecommendation: B because there are no mockups to anchor a scorecard and the gaps here are mostly missing specs, which one reviewer can list.\nNote: options differ in kind, not coverage — no completeness score.\nPros / cons:\nA) Yes, run outside design voices\n ✅ Codex hard-rule + litmus scorecard plus an independent Claude completeness read\n ✅ Disagreements surface with both perspectives in the relevant pass\n ❌ Adds a few minutes; Codex may be missing here, in which case only the Claude voice runs\nB) No, proceed without (recommended)\n ✅ Straight into the 7 passes with the plan as the anchor\n ✅ Fewest steps to a fixed plan\n ❌ Findings rest on one reviewer; no cross-model check on slop risk or hierarchy\nNet: a cross-model check vs getting to the fixed plan sooner.",
|
||||
"header": "Voices",
|
||||
"multiSelect": false,
|
||||
"options": [
|
||||
{
|
||||
"label": "Yes, run outside design voices",
|
||||
"description": "✅ Codex hard-rule + litmus scorecard plus an independent Claude completeness read. ✅ Disagreements surface with both perspectives in the relevant pass. ❌ Adds a few minutes; Codex may be missing here, in which case only the Claude voice runs and it's tagged single-model."
|
||||
},
|
||||
{
|
||||
"label": "No, proceed without (recommended)",
|
||||
"description": "✅ Straight into the 7 passes with the approved mockup as anchor. ✅ Fewest steps to a fixed plan. ❌ Findings rest on one reviewer; no cross-model check on slop risk or hierarchy."
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"answered": true,
|
||||
"failed": false,
|
||||
"answers": {
|
||||
"Want outside design voices before the detailed review?\nD2 — Outside design voices\nProject/branch/task: User Dashboard plan on main, design review.\nELI10: Before the 7 passes I can bring in two extra reviewers. Codex checks the plan against hard design rules and a litmus scorecard. A separate Claude agent does a fresh completeness read. That cross-checks my judgment, but it takes longer.\nStakes if we pick wrong: skipping means every finding rests on one reviewer; running it adds a few minutes.\nRecommendation: B because there are no mockups to anchor a scorecard and the gaps here are mostly missing specs, which one reviewer can list.\nNote: options differ in kind, not coverage — no completeness score.\nPros / cons:\nA) Yes, run outside design voices\n ✅ Codex hard-rule + litmus scorecard plus an independent Claude completeness read\n ✅ Disagreements surface with both perspectives in the relevant pass\n ❌ Adds a few minutes; Codex may be missing here, in which case only the Claude voice runs\nB) No, proceed without (recommended)\n ✅ Straight into the 7 passes with the plan as the anchor\n ✅ Fewest steps to a fixed plan\n ❌ Findings rest on one reviewer; no cross-model check on slop risk or hierarchy\nNet: a cross-model check vs getting to the fixed plan sooner.": "No, proceed without (recommended)"
|
||||
},
|
||||
"unansweredQuestionIndices": [],
|
||||
"answeredAt": "2026-10-20T03:34:09.205Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"preReview": true,
|
||||
"observedAtMs": 117535,
|
||||
"call": {
|
||||
"sessionId": "1eaa205b-5459-4e0b-9053-5a622b1da36c",
|
||||
"toolUseId": "toolu_01PGCYxzQtGHn9KEyoAM7mcf",
|
||||
"questions": [
|
||||
{
|
||||
"question": "D3 — Cross-project learnings\nProject/branch/task: User Dashboard plan on main, design review.\nELI10: gstack can search what it learned in your other projects on this machine for patterns that might apply here. It stays local; no data leaves your machine. This project has no learnings yet, so the search found nothing here.\nStakes if we pick wrong: enabling it on client work can carry one client's patterns into another's review.\nRecommendation: A because for a solo developer, past pitfalls from other repos often apply here.\nNote: options differ in kind, not coverage — no completeness score.\nPros / cons:\nA) Enable cross-project learnings (recommended)\n ✅ Reviews can reuse pitfalls and patterns you already hit in other repos\n ✅ Stays fully local, and you can switch it off later with gstack-config\n ❌ Patterns from unrelated client codebases could leak into this review\nB) Keep learnings project-scoped only\n ✅ No cross-contamination between separate client codebases on this machine\n ✅ Review evidence comes only from this repo and this conversation\n ❌ Lessons from your other projects never surface here\nNet: more reusable insight vs strict isolation between codebases.",
|
||||
"header": "Learnings",
|
||||
"multiSelect": false,
|
||||
"options": [
|
||||
{
|
||||
"label": "Enable cross-project (recommended)",
|
||||
"description": "✅ Reuse pitfalls from other repos. ✅ Local only, reversible. ❌ Client patterns could cross over."
|
||||
},
|
||||
{
|
||||
"label": "Project-scoped only",
|
||||
"description": "✅ No cross-contamination. ✅ Evidence from this repo only. ❌ Other projects' lessons never surface."
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"answered": true,
|
||||
"failed": false,
|
||||
"answers": {
|
||||
"D3 — Cross-project learnings\nProject/branch/task: User Dashboard plan on main, design review.\nELI10: gstack can search what it learned in your other projects on this machine for patterns that might apply here. It stays local; no data leaves your machine. This project has no learnings yet, so the search found nothing here.\nStakes if we pick wrong: enabling it on client work can carry one client's patterns into another's review.\nRecommendation: A because for a solo developer, past pitfalls from other repos often apply here.\nNote: options differ in kind, not coverage — no completeness score.\nPros / cons:\nA) Enable cross-project learnings (recommended)\n ✅ Reviews can reuse pitfalls and patterns you already hit in other repos\n ✅ Stays fully local, and you can switch it off later with gstack-config\n ❌ Patterns from unrelated client codebases could leak into this review\nB) Keep learnings project-scoped only\n ✅ No cross-contamination between separate client codebases on this machine\n ✅ Review evidence comes only from this repo and this conversation\n ❌ Lessons from your other projects never surface here\nNet: more reusable insight vs strict isolation between codebases.": "Enable cross-project (recommended)"
|
||||
},
|
||||
"unansweredQuestionIndices": [],
|
||||
"answeredAt": "2026-10-20T03:34:24.055Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"preReview": false,
|
||||
"observedAtMs": 139591,
|
||||
"call": {
|
||||
"sessionId": "1eaa205b-5459-4e0b-9053-5a622b1da36c",
|
||||
"toolUseId": "toolu_01KBzHJkBFs2vRhBSFnmLiPv",
|
||||
"questions": [
|
||||
{
|
||||
"question": "D4 — Issue 1: what does the user see first?\nProject/branch/task: User Dashboard plan on main, Pass 1 Information Architecture.\nELI10: The plan lists Activity, Notifications and Quick actions but not their order or relative size. Without a ranking, the engineer gives each panel equal weight and the user's eye has nowhere to land. We need to pick the primary region.\nStakes if we pick wrong: users skim past unread items or hunt for the way back to work, and the dashboard turns into a page people bounce off.\nRecommendation: 1A because unread notifications are the only thing here that needs action, and the 'Hierarchy as service' principle says the actionable item goes first.\nCompleteness: A=10/10, B=9/10, C=7/10\nPros / cons:\nA) Notifications-first (recommended)\n ✅ Page header holds the greeting, unread-count line and both quick actions inline, so 'back to work' is one click from the top\n ✅ lg: Notifications in the wide left column (about 7/12), Activity on the right (5/12); below lg they stack Notifications, then Activity\n ❌ Users who come mainly to review their own recent edits scroll past notifications first\nB) Activity-first\n ✅ Activity in the wide main column, Notifications as a right sidebar; suits a team that mostly checks its own history\n ✅ Same inline-header quick actions as A\n ❌ Unread items move to a narrow sidebar, and on mobile they sit below a long feed\nC) Single column for all sizes\n ✅ Simplest build: header, Notifications, Activity in one reading column at every width\n ✅ No column-width or balance decisions to make for lg\n ❌ Wastes wide screens and puts Activity far below the fold on desktop\nNet: lead with what needs action (A), with personal history (B), or with simplicity (C).",
|
||||
"header": "Hierarchy",
|
||||
"multiSelect": false,
|
||||
"options": [
|
||||
{
|
||||
"label": "1A Notifications-first (recommended)",
|
||||
"description": "Header with greeting and inline quick actions; lg 7/12 Notifications + 5/12 Activity; stacks N then A below lg."
|
||||
},
|
||||
{
|
||||
"label": "1B Activity-first",
|
||||
"description": "Activity in the main column, Notifications as a right sidebar; same header."
|
||||
},
|
||||
{
|
||||
"label": "1C Single column",
|
||||
"description": "Header, Notifications, Activity in one column at every width."
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"answered": true,
|
||||
"failed": false,
|
||||
"answers": {
|
||||
"D4 — Issue 1: what does the user see first?\nProject/branch/task: User Dashboard plan on main, Pass 1 Information Architecture.\nELI10: The plan lists Activity, Notifications and Quick actions but not their order or relative size. Without a ranking, the engineer gives each panel equal weight and the user's eye has nowhere to land. We need to pick the primary region.\nStakes if we pick wrong: users skim past unread items or hunt for the way back to work, and the dashboard turns into a page people bounce off.\nRecommendation: 1A because unread notifications are the only thing here that needs action, and the 'Hierarchy as service' principle says the actionable item goes first.\nCompleteness: A=10/10, B=9/10, C=7/10\nPros / cons:\nA) Notifications-first (recommended)\n ✅ Page header holds the greeting, unread-count line and both quick actions inline, so 'back to work' is one click from the top\n ✅ lg: Notifications in the wide left column (about 7/12), Activity on the right (5/12); below lg they stack Notifications, then Activity\n ❌ Users who come mainly to review their own recent edits scroll past notifications first\nB) Activity-first\n ✅ Activity in the wide main column, Notifications as a right sidebar; suits a team that mostly checks its own history\n ✅ Same inline-header quick actions as A\n ❌ Unread items move to a narrow sidebar, and on mobile they sit below a long feed\nC) Single column for all sizes\n ✅ Simplest build: header, Notifications, Activity in one reading column at every width\n ✅ No column-width or balance decisions to make for lg\n ❌ Wastes wide screens and puts Activity far below the fold on desktop\nNet: lead with what needs action (A), with personal history (B), or with simplicity (C).": "1A Notifications-first (recommended)"
|
||||
},
|
||||
"unansweredQuestionIndices": [],
|
||||
"answeredAt": "2026-10-20T03:34:44.192Z"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+7
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"source": "PR #3260 paid gate runs (e2e-third-party-actions shard output field)",
|
||||
"source": "PR #3260 paid gate runs (e2e-third-party-actions shard output field); run 39315041557 (PR #3308, slice 14 attempt 1) from its transcript assistant text",
|
||||
"captures": [
|
||||
{
|
||||
"run": "39069171159",
|
||||
@@ -90,6 +90,12 @@
|
||||
"case": "tpa-present",
|
||||
"passed": true,
|
||||
"text": "The probe returned READY, so Aside is detected for this task. Per rule 2, the consent question must include the Aside drive option, and I stop here before any browsing.\n\n**Aside detection:** READY. Your Aside browser is running and reachable.\n\n**Consent question**\n\nI need to create a test-mode API token in the Acme vendor dashboard at https://dashboard.acme.test. How would you like to proceed?\n\n- **A)** I drive it in your Aside browser, using your real logged-in sessions (recommended). You handle any password entry, CAPTCHA, or identity verification yourself in the Aside window, then tell me when you're done.\n- **B)** I drive it in gstack's own visible browser. You take over for sign-in, then hand control back.\n- **C)** Manual instructions. I give you the step list and mark this step blocked on you.\n- **D)** Defer. We skip this for now.\n\nThis choice is consent for this task only. It will not be saved as standing permission.\n\nWhichever option you pick, the resulting token will never appear in chat or logs. I will write it to a local file you approve with owner-only permissions, and verify it with one non-mutating API call before reporting success.\n\nStopped here, awaiting your answer. No browsing has occurred."
|
||||
},
|
||||
{
|
||||
"run": "39315041557",
|
||||
"case": "tpa-absent-darwin",
|
||||
"passed": false,
|
||||
"text": "I ran the policy's Aside readiness probe. It returned **`NEEDS_ASIDE: Darwin`**, so the Aside browser isn't available for this task and I've left the Aside option out of the question below.\n\nIf you want to use Aside: download it (macOS 15+) at aside.com, open it, sign in, and re-run this request.\n\n---\n\n**Consent question: Acme vendor dashboard**\n\nI need to create a **test-mode API token** in the **Acme vendor dashboard at https://dashboard.acme.test**. How should I do it?\n\n- **B)** I drive it in gstack's own visible browser. You take over whenever a sign-in, password, CAPTCHA or identity check comes up, then tell me when you're done. I only touch dashboard.acme.test and only the steps for creating the token. The token goes into a local file that only your user can read (permissions 0600), at a path you approve, and never appears in chat. I then check it with one read-only API call.\n- **C)** Manual instructions. I give you step-by-step instructions to create the token yourself.\n- **D)** Defer. I mark this step as blocked until you're ready.\n\nReply with B, C or D. Your answer covers this task only. I haven't opened a browser or done anything else."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3,9 +3,11 @@
|
||||
* sentence, clause (after , : ; or a dash), bullet or line start, optionally led by "then/please/just/so/first/now" and
|
||||
* "you can/could/may/should/need to". A quoted, parenthesised or reported mention ("the line 'download Aside ...'",
|
||||
* "says to download ...") and a clause with a negation before the phrase ("you don't need to download ...", or "do not"
|
||||
* ending the previous line) never count. The short forms count only at the start of a sentence, bullet or quote.
|
||||
* ending the previous line) never count. The canonical phrase may name Aside as "it" once the macOS 15+ floor follows
|
||||
* ("If you want to use Aside: download it (macOS 15+) at aside.com", gate 39315041557). The short forms without the
|
||||
* floor count only at the start of a sentence, bullet or quote.
|
||||
*/
|
||||
const ASIDE_DOWNLOAD_PITCH = String.raw`(?:^|[.!?;:]\s*|\n)\s*(?:[>*-]\s*)*["\u201C]?download (?:it|Aside) at aside\.com\b|(?:^|[.!?;:,\u2014\u2013\n])[\s>*_-]*(?<!(?:\b(?:not|never|no|cannot)|n['\u2019]t)\s+)(?:(?:then|please|just|so|first|now)\s+)?(?:you\s+(?:can|could|may|should|need\s+to)\s+)?download Aside \(macOS 15\+\) at aside\.com\b`;
|
||||
const ASIDE_DOWNLOAD_PITCH = String.raw`(?:^|[.!?;:]\s*|\n)\s*(?:[>*-]\s*)*["\u201C]?download (?:it|Aside) at aside\.com\b|(?:^|[.!?;:,\u2014\u2013\n])[\s>*_-]*(?<!(?:\b(?:not|never|no|cannot)|n['\u2019]t)\s+)(?:(?:then|please|just|so|first|now)\s+)?(?:you\s+(?:can|could|may|should|need\s+to)\s+)?download (?:Aside|it) \(macOS 15\+\) at aside\.com\b`;
|
||||
export const asideDownloadPitch = new RegExp(ASIDE_DOWNLOAD_PITCH, 'im');
|
||||
export const asideDownloadPitchCount = (text: string): number => [...text.matchAll(new RegExp(ASIDE_DOWNLOAD_PITCH, 'gim'))].length;
|
||||
|
||||
|
||||
@@ -379,7 +379,7 @@ export const E2E_TOUCHFILES: Record<string, string[]> = {
|
||||
|
||||
|
||||
"test/fixtures/plan-scope-recovery-av.json",
|
||||
"test/fixtures/design-scope-checkpoint-at.json",'plan-design-review/**', 'test/fixtures/plans/ui-heavy-feature.md', 'test/fixtures/design-ui-focus-capture-39298269902-a1.json', 'test/fixtures/design-ui-focus-capture-39298269902-a2.json', 'test/helpers/claude-pty-runner.ts', 'test/helpers/pty/**', 'test/fixtures/design-ui-boxed-question.json', 'test/helpers/hermetic-skill-runtime.ts', 'test/helpers/pty-trust-dialog.ts', 'test/skill-e2e-plan-design-with-ui.test.ts', 'test/fixtures/eng-d2-truncated-border-0bcd.json', 'test/fixtures/eng-d1-clipped-elision-1579.json', 'test/fixtures/eng-d2-planning-prelude-4d.json', 'test/fixtures/ceo-approach-z-call.json', 'test/fixtures/ceo-approach-z-screen.txt',
|
||||
"test/fixtures/design-scope-checkpoint-at.json",'plan-design-review/**', 'test/fixtures/plans/ui-heavy-feature.md', 'test/fixtures/design-ui-focus-capture-39298269902-a1.json', 'test/fixtures/design-ui-focus-capture-39298269902-a2.json', 'test/fixtures/design-ui-focus-capture-39363705692.json', 'test/helpers/claude-pty-runner.ts', 'test/helpers/pty/**', 'test/fixtures/design-ui-boxed-question.json', 'test/helpers/hermetic-skill-runtime.ts', 'test/helpers/pty-trust-dialog.ts', 'test/skill-e2e-plan-design-with-ui.test.ts', 'test/fixtures/eng-d2-truncated-border-0bcd.json', 'test/fixtures/eng-d1-clipped-elision-1579.json', 'test/fixtures/eng-d2-planning-prelude-4d.json', 'test/fixtures/ceo-approach-z-call.json', 'test/fixtures/ceo-approach-z-screen.txt',
|
||||
|
||||
|
||||
"scripts/resolvers/preamble/generate-preamble-bash.ts", "scripts/resolvers/preamble/generate-completion-status.ts",
|
||||
|
||||
@@ -87,6 +87,10 @@ const capturedRated = JSON.parse(fs.readFileSync(${JSON.stringify(path.join(ROOT
|
||||
// "Review focus", with the rating in the body and an all-7 option (a2 on one line).
|
||||
const captured39298269902 = [1, 2].map(attempt => JSON.parse(fs.readFileSync(${JSON.stringify(ROOT)} + '/test/fixtures/design-ui-focus-capture-39298269902-a' + attempt + '.json', 'utf8'))
|
||||
.calls.map(({ preReview, observedAtMs, call }) => nativePlanCallFingerprint(call, observedAtMs, preReview)));
|
||||
// Run 39363705692 slice 4 (a592321): Opus 5.5 rated the plan "4/10 for design completeness"
|
||||
// and offered "All 7 areas (recommended)" against "Only specific areas".
|
||||
const captured39363705692 = JSON.parse(fs.readFileSync(${JSON.stringify(path.join(ROOT, 'test/fixtures/design-ui-focus-capture-39363705692.json'))}, 'utf8'))
|
||||
.calls.map(({ preReview, observedAtMs, call }) => nativePlanCallFingerprint(call, observedAtMs, preReview));
|
||||
const unnumberedFinding = fp('unnumbered-finding', "Which region is the dashboard's primary anchor, and how is the page composed?", false);
|
||||
unnumberedFinding.nativeCall.questions[0].options = nativeFinding.nativeCall.questions[0].options;
|
||||
const finding = fp('finding', 'Which loading feedback should Save show?', false);
|
||||
@@ -208,6 +212,23 @@ mock.module(${JSON.stringify(path.join(ROOT, 'test/helpers/claude-pty-runner.ts'
|
||||
expect(opts.isReviewAUQ(focusCall)).toBe(false);
|
||||
}
|
||||
expect(opts.isReviewAUQ(captured39298269902[0][4])).toBe(true);
|
||||
expect(opts.isLastStep0AUQ(captured39363705692[0])).toBe(true);
|
||||
expect(opts.isReviewAUQ(captured39363705692[0])).toBe(false);
|
||||
expect(opts.isReviewAUQ(captured39363705692[3])).toBe(true);
|
||||
const areas = ['All 7 areas (recommended)', 'Only specific areas'];
|
||||
for (const body of ['ELI10: I rated this plan 4/10 for design completeness.', 'ELI10: This plan is a 3/10 on design completeness.',
|
||||
'ELI10: Design completeness: 6.5/10. The gaps are layout and states.']) {
|
||||
expect(opts.isLastStep0AUQ(labeled('worded-rating', 'D1 — Review focus\\nProject/branch/task: main.\\n' + body, areas))).toBe(true);
|
||||
}
|
||||
for (const [label, question, labels] of [
|
||||
['rating-split-across-sentences', 'D1 — Review focus\\nELI10: I rated this plan 4/10. Design completeness matters most here.', areas],
|
||||
['rating-out-of-seven', 'D1 — Review focus\\nELI10: I rated this plan 4/7 for design completeness.', areas],
|
||||
['rating-not-design', 'D1 — Review focus\\nELI10: I rated this plan 4/10 for test completeness.', areas],
|
||||
['areas-without-focus', 'D1 — Which plan should I review?\\nELI10: I rated this plan 4/10 for design completeness.', areas],
|
||||
['areas-not-leading', 'D1 — Review focus\\nELI10: I rated this plan 4/10 for design completeness.', ['Review all 7 areas (recommended)', 'Only specific areas']],
|
||||
['issue-labeled-areas', 'D5 — Issue 1: Which panel leads the review focus?\\nELI10: I rated this plan 4/10 for design completeness.', ['1A All 7 areas first', '1B Activity first']],
|
||||
['bare-all-seven', 'D1 — Review focus\\nELI10: I rated this plan 4/10 for design completeness.', ['All 7', 'Only specific areas']],
|
||||
]) expect(opts.isLastStep0AUQ(labeled(label, question, labels)), label).toBe(false);
|
||||
const ratedBody = 'Project/branch/task: main. ELI10: I rated this plan 4/10 on design completeness.';
|
||||
const ratedFinding = labeled('rated-finding', 'D5 — Issue 1: Which panel leads the review focus? ' + ratedBody, ['1A All 7 dimensions first', '1B Activity first']);
|
||||
expect(opts.isLastStep0AUQ(ratedFinding)).toBe(false);
|
||||
@@ -263,6 +284,8 @@ mock.module(${JSON.stringify(path.join(ROOT, 'test/helpers/claude-pty-runner.ts'
|
||||
: mode === 'captured-39298269902' ? captured39298269902[0]
|
||||
: mode === 'captured-39298269902-no-focus' ? captured39298269902[0].filter((_, index) => index !== 1)
|
||||
: mode === 'captured-39298269902-focus-only' ? captured39298269902[1]
|
||||
: mode === 'captured-39363705692' ? captured39363705692
|
||||
: mode === 'captured-39363705692-no-focus' ? captured39363705692.filter((_, index) => index !== 0)
|
||||
: mode === 'captured-focus-after-finding' ? [...captured.filter((_, index) => index !== 1), captured[1]]
|
||||
: mode.startsWith('target-menu') ? [target, fp('other', 'Which artifact should I inspect?', false)]
|
||||
: mode === 'early-exit' ? [] : mode === 'focus-only' ? [chosenFocus]
|
||||
@@ -307,12 +330,12 @@ await import(${JSON.stringify(path.join(ROOT, 'test/skill-e2e-plan-design-with-u
|
||||
} finally { fs.rmSync(directory, { recursive: true, force: true }); }
|
||||
}
|
||||
|
||||
test.each(['source', 'paraphrase', 'native-sequence', 'native-unnumbered', 'native-passes', 'captured', 'captured-rated', 'captured-39298269902'])('UI gate seeds the exact target and accepts Design progress with an unselected no-UI alternative (%s)', mode => {
|
||||
test.each(['source', 'paraphrase', 'native-sequence', 'native-unnumbered', 'native-passes', 'captured', 'captured-rated', 'captured-39298269902', 'captured-39363705692'])('UI gate seeds the exact target and accepts Design progress with an unselected no-UI alternative (%s)', mode => {
|
||||
const result = exercise(mode);
|
||||
expect(result.code, result.output).toBe(0);
|
||||
}, 20_000);
|
||||
|
||||
test.each(['target-menu', 'target-menu-design-system', 'focus-only', 'captured-no-focus', 'captured-focus-after-finding', 'captured-rated-no-focus', 'captured-39298269902-no-focus', 'captured-39298269902-focus-only', 'native-setup-only', 'native-voices-only', 'early-exit', 'timeout', 'exited', 'unanswered-finding', 'failed-finding', 'no-native-finding'])('UI gate rejects %s and removes its fixture', mode => {
|
||||
test.each(['target-menu', 'target-menu-design-system', 'focus-only', 'captured-no-focus', 'captured-focus-after-finding', 'captured-rated-no-focus', 'captured-39298269902-no-focus', 'captured-39298269902-focus-only', 'captured-39363705692-no-focus', 'native-setup-only', 'native-voices-only', 'early-exit', 'timeout', 'exited', 'unanswered-finding', 'failed-finding', 'no-native-finding'])('UI gate rejects %s and removes its fixture', mode => {
|
||||
const result = exercise(mode);
|
||||
expect(result.code, result.output).toBe(1);
|
||||
expect(result.output).toContain('plan-design-review with UI scope FAILED');
|
||||
|
||||
@@ -32,16 +32,21 @@ const designFocusBoundary = (fp: AskUserQuestionFingerprint): boolean =>
|
||||
// count may be a numeral or a word; the title must name design, unless the
|
||||
// body carries the step's own design-completeness rating (run 39199692993).
|
||||
const title = text.split(/\r?\n/, 1)[0]!;
|
||||
const rated = /\bI(?:['’]ve| have)? rated this plan (?:10(?:\.0+)?|[0-9](?:\.\d+)?)\/10 on design completeness\b/i;
|
||||
// Step 0A's rating is a sentence that scores design completeness out of 10,
|
||||
// however it is worded ("rated this plan 4/10 for design completeness", run
|
||||
// 39363705692; "This plan is a 3/10 on design completeness", the 0A example).
|
||||
const rated = (body: string) => body.split(/(?<=[.!?])\s+|\r?\n/).some(sentence =>
|
||||
/\bdesign completeness\b/i.test(sentence) && /(?<![\d./])(?:10(?:\.0+)?|[0-9](?:\.\d+)?)\/10(?!\d|\.\d)/.test(sentence));
|
||||
// Runs 39298269902 a1/a2: a title that only names the focus ("Review focus.",
|
||||
// on one line before Project/branch/task:), with the step's own rating in the
|
||||
// body and an option that offers all seven dimensions against a narrower one.
|
||||
// The option leads with all seven, whatever it calls them ("All 7 areas", run 39363705692).
|
||||
const lead = text.split(/\r?\n|\s+(?=Project\/branch\/task:)/, 1)[0]!;
|
||||
return /^I(?:['’]ve| have) rated this plan (?:10(?:\.0+)?|[0-9](?:\.\d+)?)\/10 on design completeness\.[\s\S]*\bWant me to focus on specific areas instead(?: of all (?:7|seven))?\?/i.test(text)
|
||||
|| (/\ball (?:7|seven) (?:design )?(?:dimensions|passes)\b/i.test(title) && /\bfocus\b/i.test(title)
|
||||
&& (/\bdesign\b/i.test(title) || rated.test(text.slice(title.length))) && /\?\s*$/.test(title))
|
||||
|| (/\bfocus\b/i.test(lead) && rated.test(text) && options.length >= 2
|
||||
&& options.some(({ label }) => /^\s*all (?:7|seven) (?:design |review )?(?:dimensions|passes)\b/i.test(label)));
|
||||
&& (/\bdesign\b/i.test(title) || rated(text.slice(title.length))) && /\?\s*$/.test(title))
|
||||
|| (/\bfocus\b/i.test(lead) && rated(text) && options.length >= 2
|
||||
&& options.some(({ label }) => /^\s*all (?:7|seven)\s+[a-z]/i.test(label)));
|
||||
});
|
||||
|
||||
// Require a choice about the supplied UI, not a workflow offer after focus.
|
||||
|
||||
@@ -434,7 +434,20 @@ describe("NEEDS_ASIDE: Darwin download pitch detector", () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("the captured 4daad22 pitch (gate 39315041557) counts: the canonical phrase naming Aside as 'it'", () => {
|
||||
const red = pitchCaptures.captures.find(c => c.case === 'tpa-absent-darwin' && c.run === '39315041557')!;
|
||||
expect(red.passed).toBe(false);
|
||||
expect(red.text).toContain('If you want to use Aside: download it (macOS 15+) at aside.com');
|
||||
expect(asideDownloadPitchCount(red.text)).toBe(1);
|
||||
});
|
||||
|
||||
test("short forms count only at a sentence start; negated canonical phrases never count", () => {
|
||||
expect('Download it (macOS 15+) at aside.com; open, sign in, re-run.').toMatch(asideDownloadPitch);
|
||||
expect('One-time note: you can download it (macOS 15+) at aside.com.').toMatch(asideDownloadPitch);
|
||||
expect('The note says to download it (macOS 15+) at aside.com, but this is Linux.').not.toMatch(asideDownloadPitch);
|
||||
expect("Don't download it (macOS 15+) at aside.com").not.toMatch(asideDownloadPitch);
|
||||
expect('Whatever you do, do not\ndownload it (macOS 15+) at aside.com').not.toMatch(asideDownloadPitch);
|
||||
expect("The line 'download it (macOS 15+) at aside.com' is macOS-only.").not.toMatch(asideDownloadPitch);
|
||||
expect('you can download it at aside.com').not.toMatch(asideDownloadPitch);
|
||||
expect('you can download Aside at aside.com').not.toMatch(asideDownloadPitch);
|
||||
expect('Download it at aside.com').toMatch(asideDownloadPitch);
|
||||
|
||||
Reference in new issue
Block a user