Commit Graph

381 Commits

Author SHA1 Message Date
David Grant 66640a4efa
Merge 72cae55a72 into a3259400a3 2026-07-16 06:26:01 +00:00
David Grant 72cae55a72 docs: update CHANGELOG and TODOS to match the trimmed scope
CHANGELOG no longer claims plan-ceo-review changes (bullets were dropped
entirely) and reflects the Data Model Review's promotion to its own section
instead of 11 checklist items + 3 cognitive patterns. Removed the P2 TODO
for /plan-ceo-review data-model-bias E2E coverage — moot now that
plan-ceo-review carries none of these bullets to test.
2026-07-15 23:25:29 -07:00
David Grant b39da77129 test: simplify matchesUnnegated, drop its dedicated unit test file
Per PR review feedback: the negation-aware matcher these E2E evals rely on
had accumulated real complexity (sentence-boundary scanning, markdown-bullet
clause detection, curly-apostrophe contraction matching, idiom exclusions)
across four rounds of specialist/adversarial review during this branch's own
/ship — each finding was real, but chasing all of them was disproportionate
for a periodic-tier, non-gating eval. An occasional missed edge case there
just means a rare, visible false read, not a missed real regression.

Reverted to a plain fixed-window lookback (60 chars, accounting for the
patterns' own internal gaps) with a short negation word list. Kept the
generic [a-z]+n't contraction match (can't/won't/aren't) since it's one
regex alternative, not meaningful added complexity.

Removed test/helpers/e2e-helpers.test.ts — a dedicated unit-test file for a
best-effort text-matching heuristic used only by 4 paid, periodic-tier evals
was more test infrastructure than the actual ask (3-4 new eval cases)
warranted.
2026-07-15 23:25:22 -07:00
David Grant 54a50e4b67 fix(plan-eng-review,plan-ceo-review): trim scope per PR review — drop CEO bullets, own section, fewer patterns
PR review feedback on #1071:

- Dropped the data-model exception + JSONField bullets from plan-ceo-review
  entirely. CEO review should stay high-level on "right-sized diff"; data-model
  pushback belongs to plan-eng-review, which already carries the full checklist.
  plan-ceo-review/SKILL.md(.tmpl) are now byte-identical to origin/main.
- Trimmed both remaining plan-eng-review bullets (data-model exception,
  JSONField) to single-sentence terseness, matching the style of sibling
  preferences instead of reading like a paragraph.
- Removed cognitive patterns 11-13 (normalize-first, SRP-for-models,
  structure-beats-blobs) from the numbered "Cognitive Patterns" list — they
  were more tactical/lower-level than the rest of that list (Larson, McKinley,
  Conway-style instincts), and duplicated what the Data Model Review now
  covers operationally. Renumbered 14-18 down to 11-15.
- Promoted the Data Model Review Checklist from a "####" subsection tacked
  onto Architecture Review to its own "### Data model review" section with
  its own AskUserQuestion/STOP gate, matching Architecture/Code
  Quality/Test/Performance as a peer rather than an afterthought. Did not
  renumber the existing 1-4 sections (Architecture/Code Quality/Test/
  Performance) since those numbers are referenced elsewhere (carve-guards.ts,
  the main SKILL.md.tmpl's section-order prose).

Updated test/skill-validation.test.ts's static guardrails to match: removed
the plan-ceo-review assertions (nothing left to guard there), removed the
three now-deleted cognitive-pattern assertions, updated the contiguity check
from 1-18 to 1-15, and updated the checklist-subsection test to check for
the new "### Data model review" heading.

Tightened test/helpers/carve-guards.ts budgets back down now that content
shrank: plan-ceo-review reverted fully to its original 90_000/1.08 (content
is byte-identical to baseline again); plan-eng-review tightened from
70_000/1.15 to 67_500/1.13 (down from the prior over-generous bump, though
not fully back to the original 67_000/no-ratio since the trimmed bullets are
still a small net addition).

bun test test/skill-validation.test.ts test/parity-suite.test.ts
test/touchfiles.test.ts test/gen-skill-docs.test.ts — all pass.
2026-07-15 23:25:08 -07:00
David Grant f3c54078aa docs: clarify new E2E evals are scoped to /plan-eng-review only
Codex cross-model doc review (via /document-release, run as part of /ship
Step 18) flagged that the CHANGELOG's contributor bullet about the new
periodic-tier E2E evals didn't scope them to /plan-eng-review — could be
misread as covering /plan-ceo-review too, which still only has static text
coverage (tracked as a P2 follow-up in TODOS.md).
2026-07-15 22:16:25 -07:00
David Grant c58e1b073b chore: bump version and changelog (v1.61.0.0)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-15 22:05:31 -07:00
David Grant 1820f58f69 fix: drop bare "no" as a negation trigger, treat markdown bullets as boundaries
Codex structured review (large-diff gate, Step 11) found 3 more real gaps:

- matchesUnnegated's bare "no" trigger over-fired on common positive-framing
  idioms: "No blocker here: create a separate tier model" and "there is no
  downside to promoting the payload" both got misread as negated, even
  though they're endorsements of the recommendation that follows, not
  rejections. Removed bare "no" from the negation list — "not"/"never"/
  "cannot"/the "-n't" family are far more reliable negation signals and
  don't share this idiom-collision problem.
- SENTENCE_END only recognized period-followed-by-capital as a boundary, so
  a bulleted recommendation like "I would not keep this inline.\n- Separate
  tier model" (very common LLM output formatting) let the earlier "not"
  leak into the bullet below it. Added a second alternative: a newline
  followed by a markdown bullet or numbered-list marker now also counts as
  a clause boundary. Fixed the boundary-index arithmetic to use the full
  match length (em[0].length) instead of a bare +1, since this new
  alternative can match more than one character ("\n- ", "\n1. ").
- The minimal-change eval's own hardcoded doesn't-pattern only matched the
  ASCII apostrophe (`doesn'?t`), missing the curly one — inconsistent with
  matchesUnnegated's own apostrophe handling a few lines away in the same
  file.

Added 3 regression tests reproducing each directly.

bun test test/helpers/e2e-helpers.test.ts test/skill-e2e-plan.test.ts
test/skill-validation.test.ts test/parity-suite.test.ts test/touchfiles.test.ts
test/gen-skill-docs.test.ts — 788 pass, 42 skip (paid E2E), 0 fail.
2026-07-15 18:45:43 -07:00
David Grant 02e312c057 fix: harden data-model E2E fixtures against reading the operator's real gstack install
Codex adversarial review (Step 11) flagged that these 4 tests were not
hermetic: the prompt only said "Read plan-eng-review/SKILL.md" (relative,
unpinned), and the copied SKILL.md's own STOP-Read directive references an
ABSOLUTE path (~/.claude/skills/gstack/plan-eng-review/sections/review-sections.md)
for its carved sections file. On any machine with gstack actually installed
at that location — which includes the maintainer's own dev machine — the
agent could read and get graded against the REAL globally-installed skill
instead of this branch's sandboxed copy, silently defeating the point of
the isolated fixture. This is the exact failure mode
test/helpers/auq-sdk-capture.ts's setupSkillDir()/captureSectionReads()
already guards against for other carved-skill tests; these 4 blocks
predated that pattern and didn't use it.

Fixed with a targeted change rather than a full migration to the
auq-sdk-capture harness: extracted planEngReviewDataModelPrompt() into
e2e-helpers.ts, pinning the sandboxed SKILL.md's absolute path and
explicitly forbidding the agent from reading any other SKILL.md ("especially
nothing under ~/.claude or /Users") — matching auq-sdk-capture.ts's own
phrasing. This also resolves the maintainability specialist's earlier DRY
finding (the identical prompt string was duplicated across all 4 blocks) in
the same change, since all 4 now call the one shared function.

Also fixed a second Codex finding: touchfiles.ts only listed
plan-eng-review/** as these tests' dependency, but their actual behavior
lives partly in test/helpers/e2e-helpers.ts (setupPlanEngReviewFixture,
matchesUnnegated) — a future bug there wouldn't have gotten these 4 tests
re-selected by the diff-based selector. Added the file to each test's
touchfile entry (scoped to just these 4, not GLOBAL_TOUCHFILES, since the
new exports aren't used elsewhere yet).

Two other Codex findings reviewed and accepted as-is, not fixed:
- matchesUnnegated can still mis-score idiom-based false negation ("no
  doubt", "not only... but also") — a genuine lexical-heuristic limitation,
  but these idioms are exceedingly unlikely to co-occur with the specific
  verb+object patterns these checks require in real review prose; chasing
  every conceivable idiom is diminishing returns for a best-effort matcher.
- The new evals are periodic tier, not gate — consistent with this
  repo's existing convention for all Opus-model E2E tests (documented in
  CLAUDE.md's two-tier system), not a gap introduced by this branch.

bun test test/helpers/e2e-helpers.test.ts test/skill-e2e-plan.test.ts
test/skill-validation.test.ts test/parity-suite.test.ts test/touchfiles.test.ts
test/gen-skill-docs.test.ts — 786 pass, 42 skip (paid E2E), 0 fail.
2026-07-15 18:38:49 -07:00
David Grant b3acffdf58 fix: catch can't/won't-style contractions, guard data-model-bias against negation
Maintainability specialist re-dispatch found the standalone n't alternative
in NEGATION was unreachable: \b n't \b can never match mid-word (no word
boundary exists between the letters immediately before "n" and "n" itself
in "can't", "won't", "aren't", "hasn't"), so only the explicitly-spelled-out
contractions (don't, doesn't, didn't, shouldn't, wouldn't, isn't) were ever
detected — very common ones like "can't"/"won't"/"cannot" fell through
silently. Replaced with a generic [a-z]+n't pattern plus an explicit
"cannot" alternative (which has no apostrophe to match generically).

Also brought the original data-model-bias test's recommendsSeparateModel
check in line with its three newer sibling counterexample tests by routing
it through matchesUnnegated — it was the one E2E block still un-guarded
against a negated false-positive ("I would NOT recommend a separate tier
model" would previously have registered as a pass).

Did not touch rejectsAsUnjustified (measured-denorm test) — it directly
models rejection language ("instead of denormalizing" IS the signal, not a
positive claim needing negation-checking), so wrapping it in
matchesUnnegated would conflict with its own tuned alternatives for no
clear benefit. Did not extract a shared prompt-string constant across the
4 E2E blocks (maintainability finding) — the identical prompt string already
appears verbatim in 3 pre-existing, untouched blocks in this same file;
extracting a constant for only the 4 new blocks would create inconsistency
rather than resolve it, and touching the pre-existing blocks is outside
this PR's scope.

Added unit tests reproducing both contraction gaps directly.

bun test test/helpers/e2e-helpers.test.ts test/skill-e2e-plan.test.ts
test/skill-validation.test.ts test/parity-suite.test.ts test/touchfiles.test.ts
test/gen-skill-docs.test.ts — 783 pass, 42 skip (paid E2E), 0 fail.
2026-07-15 18:23:13 -07:00
David Grant aa49339b27 fix: widen matchesUnnegated to sentence boundary, catch contrastive phrasing
Ship-workflow review re-dispatched the testing specialist against the full
updated diff (including the new minimal-change eval) and found 3 more real
bugs in the same family as the earlier fix pass:

- matchesUnnegated's fixed 20-char negation lookback was too narrow: the
  patterns it guards have their own internal gaps up to 80 chars, so "I do
  not think it's worth extracting the payload into columns" (negation >20
  chars before the match) would be misread as an unnegated recommendation.
  Now scans back to the start of the current sentence (last ./!/? before the
  match) instead of a fixed count — matches the same period-bounded
  assumption the calling patterns already make.
- Verified during the fix: neither "not"/"never"/etc. nor the wider window
  catches contrastive phrasing ("add this field to the model RATHER THAN
  create a separate table") — the rejected alternative matches the pattern
  just as strongly as a genuine recommendation, with no negation word
  anywhere nearby. Added "rather than"/"instead of" to the shared negation
  list, benefiting all four callers, not just the new eval.
- The new minimal-change eval's acceptsInlineAddition check was missing the
  matchesUnnegated guard entirely on its first alternative (unlike its
  sibling recommendsSeparateModel a few lines above), and
  recommendsSeparateModel's verb list missed common recommendation phrasings
  (introduce, build, spin out, break out) — deliberately did NOT add "add",
  since "add this new field to the existing model" is exactly how the
  CORRECT answer gets phrased.

Added 3 unit tests reproducing the sentence-boundary and contrastive-phrasing
fixes directly (not just via the paid E2E path).

bun test test/helpers/e2e-helpers.test.ts test/skill-e2e-plan.test.ts
test/skill-validation.test.ts test/parity-suite.test.ts test/touchfiles.test.ts
test/gen-skill-docs.test.ts — 781 pass, 42 skip (paid E2E), 0 fail.
2026-07-15 18:16:50 -07:00
David Grant a9124bd15b test: add minimal-change counterexample eval, unit-test matchesUnnegated
garrytan/gstack#1048 comment asked for concrete evaluations covering three
cases: normalized models, justified JSON fields, and minimal-change cases.
The prior commits covered the first two (data-model-bias, legitimate-json,
measured-denorm) but not the third — a plan where keeping a single trivial
field inline (not extracting a new model) is the correct call. This was
independently flagged by the ship-workflow coverage audit as the highest-
severity gap in this branch's test coverage.

Adds plan-eng-review-data-model-minimal-change: a synthetic plan adding one
nullable timestamp field to an existing model, no polymorphism, no JSON, no
independent query pattern or consumer. Asserts the skill does NOT reflexively
recommend extracting a separate model for it — exercising the "unless the
extra job is a single trivial field..." exception added to cognitive pattern
#12 and the SRP checklist item in 5374987c.

Also adds test/helpers/e2e-helpers.test.ts: free, deterministic unit tests
for matchesUnnegated() and setupPlanEngReviewFixture(), which were previously
only exercised indirectly by the paid, EVALS=1-gated E2E tests (also flagged
by the coverage audit — a bug in either could silently flip an eval's
pass/fail verdict and look like ordinary LLM wording variance). Along the
way, found and documented a real limitation: the negation-window check
correctly handles multiple sentences (period-bounded), but a single
comma-spliced sentence containing both a negated and a positive match can
still be absorbed into one greedy match — accepted as a known edge case,
since real review prose reliably separates points with periods/bullets.

bun test test/skill-validation.test.ts test/parity-suite.test.ts
test/touchfiles.test.ts test/skill-e2e-plan.test.ts test/helpers/e2e-helpers.test.ts
test/gen-skill-docs.test.ts — all pass, 0 fail.
2026-07-15 18:08:11 -07:00
David Grant 09ad6fb1ef fix: harden new data-model eval regexes, dedupe E2E fixture setup
Ran /review on this branch's diff against main. The always-on testing
specialist found real correctness bugs in the two eval blocks added in
33fbb58b:

- pushesToSplitTheField (legitimate-JSON eval) was negation-blind: a
  CORRECT "I would NOT extract the payload into columns" answer contains
  the same verb+payload+column proximity as an incorrect one, so it could
  fail the test on a passing review. Also missing "normalize" from its verb
  list, so a real regression phrased as "normalize this payload into
  columns" would slip through undetected.
- rejectsAsUnjustified (measured-denorm eval) missed common rejection
  phrasings ("instead of denormalizing", "rather than snapshotting"), and
  its normali[sz]e-instead/back/it clause was loose enough to false-positive
  on approving language ("stays normalized elsewhere; keep it that way").
- recommendsSeparateModel (pre-existing data-model-bias eval, touched by
  this branch to fix its fixture) broke on backtick-wrapped model names, a
  common LLM markdown convention.

Added matchesUnnegated() to test/helpers/e2e-helpers.ts — walks every regex
match and checks the ~20 chars before it for a negation word before counting
it as a positive signal — and used it for the split-detector. Broadened the
rejection regex and tightened its false-positive-prone clause. Stripped
markdown formatting before the backtick-affected check. Verified all four
fixes against representative sentences (correct-negative, actual-positive,
previously-missed-regression, and previously-false-positive cases) before
committing — all passed as expected.

Also extracted the maintainability specialist's DRY finding: the three
data-model E2E blocks (bias, legitimate-json, measured-denorm) each
duplicated the same ~20-line mkdtemp/git-init/write-plan/copy-skill fixture
setup. Extracted into setupPlanEngReviewFixture() in e2e-helpers.ts.

bun test test/skill-validation.test.ts test/parity-suite.test.ts
test/touchfiles.test.ts test/gen-skill-docs.test.ts test/skill-e2e-plan.test.ts
— 768 pass, 39 skip (paid E2E), 0 fail.
2026-07-15 17:37:23 -07:00
David Grant d7567453c8 chore: drop mid-branch VERSION/CHANGELOG bump
PR review feedback (garrytan/gstack#1071) flagged this as release metadata
that doesn't belong in a feature PR, and Copilot separately flagged that the
bump had already drifted (VERSION at 1.1.2.0, package.json still at
1.1.1.0). Per this repo's own CHANGELOG convention, the version bump and
changelog entry belong at /ship time — covering every commit that actually
landed on the branch — not mid-review while the content is still being
revised. Reverts VERSION and package.json to match main's current
1.60.1.0 and drops the premature CHANGELOG entry; /ship will add the real
one once this branch is ready to merge.
2026-07-15 17:20:42 -07:00
David Grant 33fbb58b13 test: resolve terminology drift, rebase E2E fixture to carved templates, add positive/counterexample evals
PR review feedback (garrytan/gstack#1071), resolving the three Copilot
review threads plus the "add positive and counterexample evaluations" ask:

- test/skill-validation.test.ts: renamed the two tests still named "...to
  minimal diff..." to "...to right-sized diff..." to match the actual bullet
  text the assertions check (Copilot review comment).
- test/skill-e2e-plan.test.ts: updated the Data-Model Bias regression test's
  header comment from "minimal diff" to "right-sized diff" (Copilot review
  comment); fixed the same test's fixture setup to also copy plan-eng-review's
  sections/ directory — main's carve refactor moved the Architecture Review
  and Data Model Review Checklist out of SKILL.md into
  sections/review-sections.md after this test was written, so the sandbox
  was missing the very file the skill's STOP-Read directive points at.
- Added two new periodic-tier E2E cases exercising the counterexamples the
  templates now document: "plan-eng-review-data-model-legitimate-json"
  (a Stripe-webhook-style JSONField the skill should NOT push back on) and
  "plan-eng-review-data-model-measured-denorm" (a scoped denormalization
  backed by a stated APM/load-test measurement the skill should NOT insist
  on normalizing away). Both registered in test/helpers/touchfiles.ts
  (periodic tier, same classification as the existing bias regression test).

Verified: bun test test/skill-validation.test.ts test/parity-suite.test.ts
test/touchfiles.test.ts test/skill-e2e-plan.test.ts — 768 pass, 39 skip
(paid E2E, requires EVALS=1), 0 fail.
2026-07-15 17:20:32 -07:00
David Grant 5374987c6c fix(plan-eng-review,plan-ceo-review): narrow absolute schema-bias language, add legitimate-JSON and measured-denormalization counterexamples
PR review feedback (garrytan/gstack#1071): the data-model bias guidance was
overly absolute ("diff size is NOT a goal", "three clean models... in all
respects", "JSONField is not an escape hatch") and lacked counterexamples for
cases where JSON columns or denormalization are the right call.

- "Data model exception to right-sized diff" bullet (both skills): reframes
  from an absolute rule to "don't let diff size alone decide the shape",
  explicitly allows denormalization backed by a measurement, and adds the
  counterexample of a field that would only ever be read through one FK join
  with no independent consumer.
- JSONField bullet (both skills): keeps the core diagnostic but adds concrete
  legitimate uses — third-party webhook/OAuth payload caching, open-ended
  preference bags, event payloads shaped by an external producer, and
  schemas still being discovered.
- plan-eng-review cognitive patterns #11 (normalize first) and #13
  (structure beats blobs) get the same measured-reason / known-polymorphism
  counterexamples.
- Architecture Review's "Data model honesty" bullet and the "Single
  Responsibility" and "JSONField as polymorphism escape hatch" checklist
  items (now living in sections/review-sections.md.tmpl per main's carve
  refactor) get matching nuance.

Bumps carve-guards.ts skeleton-size budgets for plan-eng-review (69_000 ->
70_000) and plan-ceo-review (91_000 -> 92_000) to cover the added prose;
verified against test/parity-suite.test.ts (13/13 pass) and
test/skill-validation.test.ts's load-bearing-bullet guardrails (still pass —
none of the anchor phrases the static tests check were removed).
2026-07-15 17:20:19 -07:00
David Grant fe3f0d6d6c merge: sync upstream main (v1.60.2.0)
Merges origin/main (a3259400) into fix-schema-consolidation-bias. Resolves
conflicts in CHANGELOG.md, VERSION, and plan-eng-review/SKILL.md(.tmpl):
main refactored plan-eng-review's review body into an on-demand section
file (sections/review-sections.md), so the schema-normalization Data Model
Review Checklist added by this branch's fix (abafb381) was re-homed there
instead of staying inline. Bumped VERSION/package.json/CHANGELOG to
1.60.2.0 on top of main's 1.60.1.0. Updated two stale assertions in
test/skill-validation.test.ts that still checked SKILL.md directly instead
of the carved sections file, and widened two parity-suite size budgets in
test/helpers/carve-guards.ts to account for the legitimate content growth.
2026-07-15 17:07:05 -07:00
Joshua France a3259400a3
Merge pull request #2264 from time-attack/time-attack/wave-test-infra-isolated-review
fix: harden test infrastructure and iOS device QA
2026-07-14 18:33:46 -07:00
t 4ad55e2eef Merge remote-tracking branch 'origin/main' into time-attack/wave-test-infra-isolated-review 2026-07-14 16:51:31 -07:00
Joshua France 2beb636f7c
Merge pull request #2234 from time-attack/time-attack/issue-2194-pglite-lock
fix(gbrain): distinguish PGLite locks from malformed config
2026-07-14 16:47:26 -07:00
Joshua France 050abc7aae
Merge pull request #2222 from time-attack/fix-brain-trust-policy-reject
fix(gstack-config): accept @local endpoint ids for brain_trust_policy
2026-07-14 16:46:17 -07:00
Joshua France 15c069631b
Merge pull request #2221 from time-attack/fix-gstack-issue
fix(benchmark): gemini stream-json content/stats parse (#2159)
2026-07-14 16:38:04 -07:00
Joshua France e284c8e0cd
Merge pull request #2218 from time-attack/plan-daily-gstack-pr
fix(repo-mode): reuse canonical cached project slug (#2212)
2026-07-14 16:35:41 -07:00
t 7efb596ced docs(ios-qa): document regeneration and device verification flow 2026-07-14 16:35:30 -07:00
t c378074ab7 fix(ios-qa): recover device tunnels safely after relaunch 2026-07-14 16:35:30 -07:00
t 145fe2d4d1 fix(ios-qa): make SwiftUI device taps observable and reliable 2026-07-14 16:35:30 -07:00
t 8e25d1583d fix(ios-qa): generate app-owned bridge accessors deterministically 2026-07-14 16:35:30 -07:00
Joshua France 490c5ad8ba
Merge pull request #2227 from time-attack/fix/basic-ftp-cve-2026-39983
fix(deps): pin basic-ftp to 5.3.1 to fully clear CVE-2026-39983 and 3 sibling HIGH advisories
2026-07-14 16:34:24 -07:00
Joshua France bf6e823f2f
Merge pull request #2228 from time-attack/case-insensitive-domain-blocklist
fix(browse): case-insensitive exfiltration-domain blocklist matching (#2190)
2026-07-14 16:32:52 -07:00
t ea648b7dff fix(careful): fail closed for compound recursive deletes 2026-07-14 12:56:22 -07:00
t a2a447a117 fix(safety): classify credential actions consistently 2026-07-14 12:56:10 -07:00
t 239d73afc4 fix(hosts): validate suppressed resolver names 2026-07-14 12:56:10 -07:00
t 0b869898ed fix(ios-qa): make generated Swift manifests valid on first run 2026-07-14 12:56:09 -07:00
t 1aa5283ddd fix(gbrain): canonicalize remotes with trailing slashes 2026-07-14 12:56:09 -07:00
t 7e23aecfc5 fix(gbrain): parse nested context query filters 2026-07-14 12:56:08 -07:00
t 45d0fb2b54 fix(eval): validate eval list limit 2026-07-14 12:56:08 -07:00
t aa3bd6f042 fix(test-harness): spawn claude without shell interpolation 2026-07-14 12:56:07 -07:00
t 5cb8761d36 fix(test-harness): measure first response on first NDJSON line 2026-07-14 12:56:07 -07:00
Sinabina cbf8a2bec2 fix(gbrain): classify PGLite connect locks 2026-07-10 16:51:16 -07:00
t 279fda4dc5 fix(browse): case-insensitive exfiltration-domain blocklist matching
urlBlocklistFilter compared URLs against the exfiltration blocklist with
case-sensitive substring checks, so an uppercased sink (https://WEBHOOK.SITE/x)
bypassed the guard and reached the scoped browser agent. Normalize the page URL
and extracted content URLs to lowercase before comparing, and make URL
extraction scheme-insensitive so HTTPS:// links are still caught.

Fixes #2190

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 14:39:32 -07:00
t 8b53302983 test(deps): tripwire that no basic-ftp < 5.3.1 resolves in bun.lock
Parses package.json overrides + every resolved basic-ftp specifier in bun.lock
(including nested paths like get-uri/basic-ftp) and fails if any is below 5.3.1.
Deterministic and offline. Fires on the pre-fix tree (basic-ftp@5.2.0) and would
also catch a direct-dependency-only bump that leaves a nested vulnerable copy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 13:58:07 -07:00
t f55e27097c fix(deps): override basic-ftp to 5.3.1 to clear CVE-2026-39983 + 3 sibling HIGH advisories
basic-ftp reaches the tree only transitively:
  puppeteer-core > @puppeteer/browsers > proxy-agent > pac-proxy-agent > get-uri > basic-ftp

Versions <= 5.3.0 carry four HIGH advisories, all fixed in 5.3.1:
- GHSA-chqc-8p9q-pq6q (CVE-2026-39983) FTP command injection via CRLF
- GHSA-6v7q-wjvx-w8wg incomplete CRLF protection (USER/PASS + MKD bypass)
- GHSA-rpmf-866q-6p89 DoS via unbounded multiline control-response buffering
- GHSA-rp42-5vxx-qpwr DoS via unbounded memory in Client.list()

Pin via a bun `overrides` entry rather than a phantom direct dependency.
Overriding forces every basic-ftp in the tree to 5.3.1, including get-uri's
nested copy; `bun audit` then reports zero basic-ftp advisories (total 37 -> 33,
HIGH 13 -> 9). A direct-dependency bump leaves get-uri/basic-ftp at the
vulnerable version and audit still flags all four.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 13:58:07 -07:00
Sina db149a6162 fix(gstack-config): accept @local endpoint ids for brain_trust_policy
endpoint-hash returns "local" for stdio/PGLite, but validators only
allowed hex suffixes, so setup-gbrain could not persist trust policy.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-10 11:21:19 -07:00
Sina c7e182baa2 fix(benchmark): skip-trust for headless gemini + drop release metadata
Pass --skip-trust so temp/untrusted workdirs work in headless
benchmarks (mirrors Codex --skip-git-repo-check). Revert VERSION,
CHANGELOG, and package.json bumps — leave release bookkeeping to
maintainers / /ship, matching community PR practice.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-10 10:38:46 -07:00
Sina 5d93ce278d test(benchmark): full post-CLI gemini e2e + GEMINI_API_KEY auth path
Exercise resultFromGeminiStream against current stream-json fixtures
(including empty-success hardening). Recognize GEMINI_API_KEY and map
IneligibleTierError to auth — personal OAuth free-tier is no longer
supported by gemini CLI.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-10 09:38:06 -07:00
Sina f155481b78 chore: bump version and changelog (v1.60.2.0)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-10 09:28:48 -07:00
Sina 58e9881d6e fix(benchmark): parse current gemini stream-json content/stats shape
GeminiAdapter was reading message.text and result.usage, so current CLI
content/stats events produced empty $0 success rows. Accept content with
an assistant role guard, stats token fallbacks, init model, and treat
empty exit-0 output as an error (#2159).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-10 09:28:48 -07:00
Sina 8aab6dfb7e fix(repo-mode): reuse canonical cached project slug (#2212)
gstack-repo-mode was re-deriving slugs from origin and writing twin project dirs; consume gstack-slug's cached sanitized slug instead.
2026-07-10 03:09:13 -07:00
Garry Tan 7c9df1c568
chore(release): v1.60.1.0
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 23:49:09 -07:00
Garry Tan 80d944a2df
docs(todos): periodic CI matrix covers 9 of ~66 e2e files — file the coverage decision
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 23:49:09 -07:00
Garry Tan 88dec06907
fix(test): autoplan-dual-voice sandbox registers skills + assertions read real stream-json
Root cause of months of silent local failure: the sandbox copied skill dirs to
the repo root, but claude >= 2.x resolves slash commands strictly from
registered skills, so /autoplan short-circuited with 'Unknown command' (0
turns, ~1s) on every attempt. Install /autoplan + review skills at
project-level .claude/skills/ (same pattern as skill-routing-e2e).

Also: the transcript filter matched entry.type === 'tool_use', a shape that
never appears at the top level of raw stream-json, so assertions only ever saw
the final result text; filter on assistant/user events instead. Hang
protection accepts the Phase 1 review dispatch (Agent/Task tool call carrying
review instructions) as progress evidence, since full Phase 1 completion is
15+ min of subagent work. Budget raised to 10 min / 40 turns.

Invisible in CI: the file is in neither evals.yml nor evals-periodic.yml
matrices (coverage decision filed in TODOS.md).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 23:49:09 -07:00