Commit Graph

380 Commits

Author SHA1 Message Date
Benjamin D. Smith 2e15f49ea7
Merge 7d0a136515 into a3259400a3 2026-07-19 01:38:06 +00:00
Benjamin D. Smith 7d0a136515 perf(build): mark 36 slash-only skills disable-model-invocation
📝 Summary:
• add `disable-model-invocation: true` to the frontmatter of every
  gstack skill that is only ever user-invoked, so their descriptions
  drop out of Claude Code's always-loaded prompt (~1,050 tokens per
  request on this machine)
• flag lives in each `SKILL.md.tmpl`; generated `SKILL.md` files
  regenerated via `bun run gen:skill-docs` (claude host is denylist
  frontmatter mode, so the key passes through untouched)

🔧 Technical Improvements:
• flagged (36): benchmark, benchmark-models, canary, careful, codex,
  cso, design-html, design-shotgun, devex-review, diagram,
  document-generate, document-release, freeze, gstack-upgrade,
  guard, health, ios-clean, ios-design-review, ios-fix, ios-qa,
  ios-sync, landing-report, make-pdf, open-gstack-browser
  (covers the connect-chrome alias), pair-agent, plan-devex-review,
  plan-tune, pr-prep, retro, scrape, setup-browser-cookies,
  setup-deploy, setup-gbrain, skillify, spec, unfreeze
• kept model-invocable on purpose — every skill named in the
  CLAUDE.md skill-routing tables (here and in consumer repos):
  autoplan, browse, context-restore/save, design-consultation,
  design-review, investigate, land-and-deploy, learn, office-hours,
  plan-ceo/design/eng-review, qa, qa-only, review, ship,
  sync-gbrain, plus the `_gstack-command` router
• verified: `bun test` tier-1 suites green (733 pass, 0 fail);
  `browse/test/sidebar-ux.test.ts` failures reproduce with this
  change stashed (73/176 fail on the base tree — pre-existing,
  needs a live browse daemon)

📊 Code Changes: 72 insertions, 0 deletions (net +72)

📦 Files Modified:
• 36 × `<skill>/SKILL.md.tmpl` (minor updates — one frontmatter line)
• 36 × `<skill>/SKILL.md` (minor updates — regenerated)
2026-07-18 14:18:04 +00:00
Benjamin D. Smith 5c37e4a933 chore(build): regenerate skill docs to current generator output
📝 Summary:
• re-run `bun run gen:skill-docs` on unmodified templates and commit
  the drift — the working tree had stale generated output (blank-line
  churn) left uncommitted by an earlier regen
• 326 deletions across 10 SKILL.md + 6 sections files, whitespace and
  section-render drift only; no template changed in this commit

📊 Code Changes: 0 insertions, 326 deletions (net -326)
2026-07-18 14:06:50 +00: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
Benjamin D. Smith 2311e32d63 docs(workspace): mandate single-select default in AskUserQuestion format
📝 Summary:
• Add a `multiSelect` rule to the shared AskUserQuestion decision-brief
  preamble, plus a matching self-check bullet
• Regenerate the 44 SKILL.md surfaces that inline the preamble

🔧 Technical Improvements:
• `generate-ask-user-format.ts` now states that options are mutually
  exclusive by DEFAULT, and `multiSelect: true` is legal only when
  every option is an independently-selectable atom whose pro/con and
  effort stand alone
• Bundles or combinations of the same underlying items (`E1+E3`,
  `All three`, `E1 only`, `Defer all`) are mutually exclusive by
  construction, so they take `multiSelect: false` and score
  `Completeness:` per option LETTER, not per sub-item
• Names the diagnostic tell: a defer/none option or a do-everything
  option sitting in the list proves the question is single-select
• Routes 5+ independent atoms to the existing split chain rather than
  to `multiSelect`, so the 4-option cap is never silently exceeded

🏗 Architecture:
• The rule lives in the preamble resolver, not in any one skill, so
  every skill that renders a decision brief inherits it from one
  source; the 44 regenerated `SKILL.md` files are build output

🧾 Reports:
• Regenerated with `gen:skill-docs:user` to match how this branch's
  `SKILL.md` were produced (gbrain blocks inlined); the pure-form
  `gen:skill-docs` variant strips them and would have carried 326
  unrelated deletions
• `bun test test/host-config.test.ts test/skill-validation.test.ts
  test/audit-compliance.test.ts test/question-log-hook.test.ts
  test/gstack-question-preference.test.ts` — 387 pass, 0 fail across
  the four non-golden files
• The three `golden-file regression` tests were ALREADY red at HEAD:
  `test/fixtures/golden/*-ship-SKILL.md` are pure-form while the
  committed `ship/SKILL.md` is brain-form. Left untouched — a
  pre-existing defect, not this change

📊 Code Changes:
• 138 insertions, 0 deletions (net +138)

📦 Files Modified:
• `scripts/resolvers/preamble/generate-ask-user-format.ts`
  (substantial changes) — add the single-select rule paragraph and
  the `multiSelect: false` self-check bullet
• 44 × `**/SKILL.md` (minor updates) — regenerated preamble
2026-07-10 23:38:53 +10:00
Benjamin D. Smith 779b12a261 chore(build): regenerate SKILL.md after v1.60.1.0 upstream merge
📝 Summary:
• `./setup` re-rendered 49 `SKILL.md` files from their `.tmpl`
  sources after merging `upstream/main` (v1.58.5.0 → v1.60.1.0)
• Additive only — 304 insertions, 0 deletions; picks up the new
  preamble blocks shipped upstream

📦 Files Modified:
*/SKILL.md (minor updates) — regenerated from templates
2026-07-10 22:10:46 +10:00
Benjamin D. Smith b4bcbc7267 Merge remote-tracking branch 'upstream/main' into feat/pr-prep-skill 2026-07-10 22:08:44 +10:00
Benjamin D. Smith 6205b5e05b WIP: pre-v1.60.1.0 upgrade checkpoint — uncommitted local edits 2026-07-10 22:08:44 +10: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
Garry Tan bb4de3926f
fix(test-harness): return promptly when a timed-out child leaves pipe-holding orphans
proc.kill() only signals the sh -c wrapper; the claude child survives as an
orphan that inherited our stdout/stderr pipes, blocking the stream drain until
it exits (observed: a 600s spawn timeout stretching to 1431s and tripping bun's
per-test timeout with no result). On timeout, cancel the stdout reader; race
the stderr drain against child exit + 5s grace. Streamed transcript lines
survive the cancel, so callers still get their evidence.

Regression test: test/session-runner-timeout.test.ts (fake claude spawns a
pipe-holding orphan; fails in 30s without the fix, passes in 8s with it).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 23:49:09 -07:00
Benjamin D. Smith 823aaecfb5 docs(docs): add preamble-bloat findings — trim deferred to upstream
📝 Summary:
• Investigated 46KB `{{PREAMBLE}}` injected into every generated
  `SKILL.md` by `scripts/gen-skill-docs.ts` resolvers
• Upstream churns resolvers + generated files every release (51
  files / 1,469 insertions in one delta) — fork-side trim would
  conflict on every rebase, so no edit made
• Documented safe path: upstream PR extending the existing
  `sections/` carve to relocate ~20.5KB of tier-2+ interaction
  prose on-demand (~5.1k tokens saved per invocation)

 Files Added:
• `PREAMBLE-BLOAT-NOTES.md` (per-tier preamble sizes, section
  breakdown, top-10 offender table, trim strategy A/B/C)
2026-07-05 17:02:28 +10:00
Benjamin D. Smith 29e4c17bfa test(pr-prep): extract + unit-test the collision scorer
The Step 4 bucketing (title/file Jaccard, state weighting, EXACT_DUP /
OVERLAP / SIBLING / CLEAN precedence) lived only as inline bash in the
skill, so it had no behavioral coverage. Extract it into a pure,
deterministic CLI, `bin/gstack-pr-prep-score`, and pin every bucket
threshold in `test/pr-prep-score.test.ts` (13 cases, free, gate-tier).
The skill's Step 4 now points at the scorer as the canonical
implementation rather than re-deriving the thresholds inline, and the
coverage matrix gates pr-prep on the new behavioral test. This is the
v0.2.0 extraction the skill flagged, scoped to the scoring core.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 21:56:32 +10:00
Benjamin D. Smith e0e666454b test(tests): add /pr-prep to the skill coverage matrix
The coverage gate (skill-coverage-matrix + skill-coverage-floor)
requires every skill on disk to have a registry entry with at least one
gate-tier test. The new pr-prep skill had none, failing both checks.
Register it with the structural floor test as its gate-tier minimum,
matching how other audit/report skills (qa-only, investigate) are
covered until a behavioral E2E is written.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 21:56:32 +10:00
Benjamin D. Smith 7abb529e66 test(tests): refresh ship golden baselines for the Step 1.5 gate
The golden-file regression check pins the generated per-host ship skill
(Claude, Codex, Factory) against committed snapshots. Adding the Step
1.5 pr-prep gate to `ship/SKILL.md.tmpl` changed all three generated
outputs, so the snapshots no longer matched. Regenerate them via
`gen:skill-docs --host all` and re-capture; the diff is exactly the
Step 1.5 block, identical across hosts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 21:56:31 +10:00
Benjamin D. Smith de4f62a317 feat(pr-prep): check commits against the upstream commit-message style
Add Step 4.6: a per-commit conformance check that holds the branch's
commit messages to the UPSTREAM repo's convention, not the
contributor's own house style. A fork PR whose commits read in a
different voice than the project reads as a drive-by and burns reviewer
goodwill before the diff is read.

The authoritative style is resolved once (Step 1.4): the upstream
CONTRIBUTING.md commit rules if present, else the de-facto shape sampled
from `git log upstream/$BASE_BRANCH --no-merges`, else the
conventional-commits baseline. Step 4.6 then flags subject-shape drift,
a personal body template (emoji/bullets) where upstream uses prose, a
subject that promises content it lacks (e.g. "+ tests" with no tests),
and a missing-or-extra trailer relative to upstream (e.g. a
`Co-Authored-By:` line upstream carries on every commit). Surfaced as a
soft warning in the report, never a block — style is not a duplicate,
but it is the cheapest goodwill win in the audit and far cheaper to fix
before the PR exists.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 21:56:31 +10:00
Benjamin D. Smith b1edc82e7d chore(pr-prep): add /pr-prep to the proactive-suggestions registry
Adding the skill left its entry in `scripts/proactive-suggestions.json`
unwritten. Regenerate the registry so `/pr-prep` is wired into
proactive routing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 21:56:31 +10:00
Benjamin D. Smith 3b1079897b chore(pr-prep): regenerate SKILL.md against current resolvers
The committed `pr-prep/SKILL.md` was generated against an older
preamble and had drifted from `bun run gen:skill-docs` output.
Regenerate it so it picks up the current shared resolvers: the
`SESSION_KIND` and `GSTACK_PLAN_MODE` preamble lines, the `/spec`
routing entry, the AskUserQuestion failure fallback, the 5+-option
split rule, and the Boil-the-Ocean rename.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 21:56:31 +10:00
Benjamin D. Smith 1b2451d773 docs: register /pr-prep in skill inventories
The doc-inventory cross-check requires every skill directory to appear
in both `AGENTS.md` and `docs/skills.md`. Add a `/pr-prep` row to each
so the new skill is documented and the check passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 21:56:31 +10:00