mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-03 07:18:03 +01:00
main
2
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
+22 |
8bb6d65270 |
v1.91.66.0 fix: /autoplan without permission prompts after background reviewers, 34 contributor PRs from the backlog triage (#3087)
* docs: fix CONTRIBUTING.md test-tiers link in TESTING_INTERNALS The link resolved relative to docs/, pointing at a nonexistent docs/CONTRIBUTING.md. Adopts #3070. Co-authored-by: thearbajonart <334330110+thearbajonart@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * ci: refresh GitHub Actions SHA pins (setup-buildx 4.4.1, build-push 7.4.0, attest 4.2.2, setup-node 7.0.0) Rewrite of dependabot #2988. Every bumped `uses:` stays pinned to the full commit SHA (verified against the upstream tags) and now carries its exact version comment, including the lines that had none. setup-node 6.5.0 -> 7.0.0 is a major bump; its notes list an ESM migration, cache outputs and removal of a dummy NODE_AUTH_TOKEN export, none of which affect our node-version-only use. actionlint 1.7.11 (CI image) and 1.7.12 are clean. Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(openclaw): stop advising a per-spawn env for spawned sessions OpenClaw's sessions_spawn has no env argument (openclaw/openclaw#51654 was closed without adding one), so the documented env: { OPENCLAW_SESSION: "1" } silently did nothing. Point users at the ACP harness or Gateway environment instead and guard the old advice. Adopts #2749. Co-authored-by: DanCanadian <211164803+DanCanadian@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(benchmark): scope /benchmark routing to web page performance /benchmark claimed the bare words "benchmark" and "performance", so model and eval benchmark requests could route to the web performance skill instead of /benchmark-models. Narrow the description, Use-when list and triggers to web-specific phrases, point model/skill benchmarks at /benchmark-models, and split the root router line the same way. The catalog lead stays within the discovery budget ("Web performance ..."). Adopts #2302 and closes duplicate #2083 (rewritten on current main). Co-authored-by: Nader Helmy <31414549+creatornader@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(llms.txt): link skills by generated path, drop host-skipped skills gen-llms-txt built every skill link as <name>/SKILL.md, so the router pointed at a nonexistent gstack/SKILL.md (it is the root SKILL.md) and /claude-code pointed at a SKILL.md the Claude host never generates. Links now use the template's generated output path, and skills the Claude host skips are left out of the index. Adopts #2279. Co-authored-by: Nader Helmy <creator.nader@gmail.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(ci): install Bun from the SHA-256-verified release archive in GitLab CI and Ubicloud setup Rewrite of #1713. .gitlab-ci.yml's .setup-bun anchor and scripts/ubicloud/setup-free-suite.sh still piped https://bun.sh/install into bash. Both now download the bun-v$BUN_VERSION linux-x64 release zip, check it against the same SHA-256 Dockerfile.ci uses (#1706) before unzipping, install it to ~/.bun/bin and assert `bun --version`. test/ci-image-cli-pin.test.ts runs curlPipedToShell over both files and binds their hash and BUN_VERSION to Dockerfile.ci's amd64 arm and package.json's engines floor, so a Bun bump has to move all of them together. Verified by running the GitLab anchor in debian:stable-slim (bash and sh) and the Ubicloud block in a temp HOME. Co-authored-by: Zee Zheng <228040220+spacegeologist@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(browse): viewport auto unpins a pinned viewport without a restart `viewport WxH` pinned the page with no way back short of `browse restart`, which also drops a headed /connect-chrome session. `viewport auto` (aliases `reset`, `unpin`) now undoes the pin: - headed: the context already launches with `viewport: null`, but Playwright cannot drop a page's emulated size (and re-applies it on new frame sessions), so the active tab gets a fresh page in the same context at the same URL or load-html content. Cookies and storage persist, the tab id and ownership stay, refs reset as on navigation, and the page follows the real window again. - headless: back to the 1280x720 launch default, tracked viewport included. `auto` with --scale is rejected. Fixes #1059. Adopts #2782 and #1881. Co-authored-by: Jack Thomas <17882510+loulanyue@users.noreply.github.com> Co-authored-by: Jayesh Betala <jayesh.betala7@gmail.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(browse): screenshot accepts --clip=x,y,w,h and --selector=<css> Agent-generated commands often use the GNU `--flag=value` form, which threw "Unknown screenshot flag". Both value flags now accept it, through the same validation and conflict checks as the space-separated form. Adopts #1563. Co-authored-by: techcenter68 <75930234+techcenter68@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(benchmark): price Codex cached input at the cache rate, stop calling Gemini OAuth ready Codex reports cached_input_tokens as a subset of input_tokens, but the adapter billed all of input_tokens at the full input rate. Split them into disjoint uncached and cached counts (what estimateCostUsd expects) and show new+cached input in the table and Markdown reports. A stored Gemini OAuth file alone is now reported as not ready, with a reason naming GEMINI_API_KEY; key-based auth stays ready. Adopts the focused subset of #2283; the capacity error code and stdin change are left out (no captured failure or reproduced hang). Co-authored-by: Mattias Petersson <mattias.petersson@gmail.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(review): catch loosened-input consumers and stale user-facing strings The Enum & Value Completeness check fired only on newly added values, so a diff that widens what a validator, parser or guard accepts, and breaks an unchanged downstream consumer outside the diff, was a blind spot. Widen the check's trigger (heading unchanged) and add a consumer-grep bullet. Teach the maintainability specialist to flag user-facing strings whose guarding condition changed while the text did not. Adopts #2141 (rewritten on current main; the section heading is kept). Co-authored-by: Arno V <38716+aversini@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(global-discover): bucket Codex sessions by originator Every Codex rollout counted as one undifferentiated codex bucket, so /retro global could not tell interactive Codex Desktop work from codex_exec runs or Claude Code-driven calls. Normalize session_meta.payload.originator into desktop, exec, claude_code or other (missing, unknown and non-string values), report the split per repo as codex_originators and globally as tools.codex.originators, and print it in the summary. Existing totals are unchanged. Adopts #1488. Refs #1315. Co-authored-by: 0xDevNinja <manmit0x@gmail.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(hook-check): cover skill frontmatter hooks, sourced helpers, conflict markers and the caller's tsconfig Rewrite of #3066. bin/gstack-hook-check only listed setup's hooks plus /autoplan's by name, so the /careful and /freeze PreToolUse checks (also run by /guard and /investigate), /plan-ceo-review's hand-off hook and the helpers they source were never parse-checked before Claude Code ran them. - The hook list is setup's _hook_command_path arguments plus every gstack path on a `command:` line in a generated */SKILL.md frontmatter (9 hooks, up from 6). The generated files are read rather than the .tmpl sources because the /autoplan and /plan-ceo-review commands come from resolvers. - Each shell hook's gstack-tree helpers (`.`/`source` lines, assignments and shellcheck source= directives, followed transitively) are parsed too: careful/bin/hook-extract.sh and bin/gstack-state-root.sh for /careful and /freeze. - The shim, its helpers, each TypeScript entry and every local module the bundle used (bun build --metafile; entry only when bun lacks it) are scanned for conflict-marker lines, which still parse inside heredocs, strings and template literals. - bun build runs from the gstack root, so the caller's broken tsconfig.json or bunfig.toml no longer fails every TypeScript hook. Lists are newline separated, so a root with spaces works. Tests in test/setup-hook-syntax-gate.test.ts cover each case; the gstack-doctor fixture now copies autoplan/SKILL.md, whose frontmatter registers the hook its hooks-row test breaks. docs/troubleshooting.md describes the wider check. Co-authored-by: Benjamin D. Smith <7134745+BenjaminDSmithy@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(review): extend defensive-security framing to the security specialist and Red Team The "authorized defensive-security review" framing and fixture summary mode lived only in the adversarial subagent prompt. The security specialist and the Red Team also reason adversarially over the full diff, so repos whose test corpus is attack payloads could still get those passes refused. Move both paragraphs into scripts/resolvers/defensive-review.ts (the adversarial render stays byte-identical), state them once in the specialist dispatch for the security specialist and the Red Team, and have the Red Team prompt start from them. Testing and the other specialists keep full fixture reads; the codex host still strips Review Army. Parity caps for ship and review rise by the measured 1,380 bytes each (carve-guards notes). Adopts #1921 (rewritten on current main). Co-authored-by: Brian Majewski <1693720+bmajewski@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(team-init): make the required-mode hook shell-neutral (node CommonJS, no shell variables) Rewrite of #2217. Required team mode wrote a bash check-gstack.sh and registered it as "$CLAUDE_PROJECT_DIR/.claude/hooks/check-gstack.sh", which only works when the hook runner is a POSIX shell. Under cmd.exe or PowerShell (Windows, Copilot CLI) the variable is not expanded and the .sh cannot run, so an intended allow or deny became a hook error. - The hook is now .claude/hooks/check-gstack.cjs: the same root search (GSTACK_ROOT, every host's global root, the migrated repo), with the home directory from HOME, then USERPROFILE, then os.homedir(). It prints {} when gstack resolves and the PreToolUse deny JSON with exit 2 when not. - The registered command is `node -e "require(require('path').resolve( process.env.CLAUDE_PROJECT_DIR || '.', '.claude', 'hooks', 'check-gstack.cjs'))"`: no `$` or `%`, so sh, cmd.exe and PowerShell all pass it through unchanged. - An existing check-gstack registration (matcher Skill or Skill|skill) is replaced in place; duplicates are dropped and unrelated hooks in the same entry kept. The legacy .sh is deleted only after the settings write succeeds (a tracked one joins the suggested git add), and is kept when bun is missing or the write fails, which now reports instead of claiming success. Tests: team-mode and the hook-schema test run the command as registered; test/team-init-hook-shell-neutral.test.ts runs it through the platform's default shell (cmd.exe on the Windows lane, which curates it in) and through PowerShell when installed (verified here in the pwsh 7 container). The routing-probe check for the bash `_GSTACK_ROOT` gate now pins the same contract in the .cjs: every host root probed, block only when none resolves. Co-authored-by: neallee2012 <1499497+neallee2012@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(setup-gbrain): register the gbrain MCP through bun.exe on Windows so no console window opens Rewrite of #2007, folding #1963's MCP notes. On Windows the local stdio registration stored the bun `gbrain` binstub; gbrain.exe starts bun in a new console, so every Claude Code session opened a visible terminal for the MCP (the contributor's process trees show it; bun.exe launched directly attaches to Claude Code's headless ConPTY). Under MINGW/MSYS/Cygwin the skill now resolves BUN_ROOT from BUN_INSTALL or ~/.bun and registers `$BUN_ROOT/bin/bun.exe <global node_modules gbrain/src/cli.ts> serve`. That path also covers a `bun link`ed clone, whose global node_modules entry links to it; gstack-gbrain-install records no other clone location. When bun.exe or the entry is missing it registers `$BUN_ROOT/bin/gbrain.exe` by its full name, because Claude Code does not apply PATHEXT to a stored path (#1963). POSIX keeps the binstub line. The skill also notes that `claude mcp list` can show "Failed to connect" while a live session holds a local PGLite brain's single-writer lock (#1963). test/setup-gbrain-windows-mcp.test.ts runs the generated fence under bash with stub uname/claude and a temp HOME for MINGW64, MSYS with BUN_INSTALL, a missing entry, and Linux. It is listed as Windows-incompatible (POSIX stubs); the console behavior needs a manual Windows check. Co-authored-by: Max Hogan <max@maxhogan.dev> Co-authored-by: maxpetrusenkoagent <280464918+maxpetrusenkoagent@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(hosts): rewrite every "Agent tool" phrasing for agent-runtime hosts The Agent-tool rewrite for hermes, gbrain, openclaw and factory keyed only on "use the Agent tool", but templates mostly say "via the Agent tool", "with the Agent tool", "multiple Agent tool calls" or "Use the Agent tool", so the Claude tool name leaked into those hosts' skills and sections. Add ordered rules after the existing key (possessive, "the Agent tool", then bare "Agent tool") mapping to sessions_spawn (gbrain/openclaw), delegate_task (hermes) and delegation (factory). No goldens change. Adopts #1935 (rewritten on current main, without the new goldens). Co-authored-by: katlun-lgtm <264247399+katlun-lgtm@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(setup-deploy): Vercel auto-deploys only when connected to the Git repo /setup-deploy stated that Vercel always deploys on push, which is false for CLI-only projects with no Git integration, and its nothing-detected path did not say why such a project is invisible to detection. Qualify the Vercel trigger (ask for and record the CLI deploy command otherwise) and note that `vercel link` creates .vercel/ so a re-run detects the project. Adopts the Vercel accuracy part of #2992 (rewritten on current main); the third-party bring-up tool pointer is not adopted. Co-authored-by: mikehasa <91774998+mikehasa@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(retro): persist recommendations so the next retro detects follow-through /retro produced "3 Things to Improve" but never saved them in its JSON snapshot, so the next retro could not tell whether last week's recommendations were acted on. Step 13 now drafts the items before saving and always writes a `recommendations` array ({category, text}, [] when empty); Step 12 scores each prior recommendation addressed/partial/open against this window's commits, files and metrics and renders a follow-through line, skipping silently for snapshots without the key. The report format ties the items to the saved array. Global mode is unchanged. Adopts #1853 (rewritten on current main). Refs #1834. Co-authored-by: Jayesh Betala <jayesh.betala7@gmail.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(global-discover): count the interactive Codex CLI (codex_cli_rs) in its own cli bucket * feat(developer-profile): --reconcile backfills office-hours tenure from timeline.jsonl sessions[] is written only at office-hours Phase 4.5, so runs that ended earlier never counted toward tenure and the tier undercounted. Add a manual `--reconcile` that scans projects/*/timeline.jsonl for office-hours `completed` events and appends a count-only row ({date, mode, project_slug, signal_count: 0, signals: [], backfilled: true}) for each run with no sessions[] entry for the same project within 60 minutes, extended back by a duration_s under 8h. It is idempotent, skips malformed lines, and leaves the file untouched on a no-op. `--read` counts backfilled rows for SESSION_COUNT and TIER but takes LAST_*, DESIGN_*, CROSS_PROJECT and the nudge from logged sessions only. Not wired into the preamble yet; the office-hours greeting guard for backfill-only profiles is left to the office-hours owner. Adopts #2668 (rewritten on current main). Closes part (b) of #2657. Co-authored-by: Briac <137724549+briacSck@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(autoplan): the publication hook approves /autoplan's own Reads after the skill turn Claude Code applies a skill's allowed-tools only to the turn that invoked it. On 2.1.292 the default fork-subagent mode runs reviewers in the background, and the completion notice starts a new turn, so later Reads outside the working directory (the next phase's section file, the close packet) raised permission cards. Skill hooks stay registered for the session, and a PreToolUse "allow" skips the card (reproduced in a PTY on 2.1.292). autoplan/bin/owned-read.ts approves a parent Read only when the guard itself returned no output, and only for this installation's autoplan/sections/*.md (canonical path or the gbrain :user render) or an immutable phase artifact in <repo>/.gstack/tmp/autoplan/autoplan-<phase>-*/ whose repo is the session's project directory or contains it. Denials, unverified allows, child calls and every other path are unchanged. renderSectionBase and userRenderRoot move there with it. Tests that asserted a verified driver Read as {} now expect the approval; autoplan-owned-read covers the shipped shim, the close packet without a journal, verified artifacts through the guard, look-alikes (foreign install, writable copy, symlink alias, other repository, other names) and a guard denial staying a denial. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(autoplan): restore point and phase artifacts live in the project's .gstack/tmp/autoplan/ Skill hooks do not run inside subagents, so a reviewer launched after a background completion notice raised a card for its own input (native-prompt.md under the state root). Step 1 now puts RESTORE_PATH in the repository's git-excluded .gstack/tmp/autoplan/ (added to .git/info/exclude, mode 700), and the snapshot tool writes every phase artifact beside it, so /autoplan and its reviewers read them from the working directory without a card. The guard's bindings are unchanged: they anchor on the restore point's directory. Step 1 still prints the slug, which the old RESTORE_PATH carried. A free test runs the generated Step 1 block twice from a repository subdirectory: the restore point lands in <repo>/.gstack/tmp/autoplan/, the exclude line is written once and git status stays clean. The autoplan parity cap rises by the measured bytes (115,270 / 101,979 = 1.1303). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(evals): autoplan-guard-pty fails on any permission card after the reviewer's notice turn The scripted boundary now mirrors Step 1's layout (restore point and artifacts in the project's .gstack/tmp/autoplan/) and continues past the Phase 2 entry to dispatch the Phase 2 reviewer after the CEO reviewer's completion notice. The case asserts four verified guard allows, that the close packet Read, the Phase 2 section Read and the Phase 2 dispatch came after a task-notification turn, that the Phase 2 reviewer read its input, and that no permission card appeared at all. Still one trial on haiku, about 75-85 seconds. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(autoplan): permission cards after a background reviewer, and where /autoplan keeps its files Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(outside-review): read a trailing '— Medium.' or '(High)' severity on a finding line, the shape Codex now writes * feat(design): honor OPENAI_BASE_URL for every design API call One resolver, openaiUrl() in design/src/auth.ts, now builds every OpenAI URL the design binary, its prototype and its live model check use. Setting OPENAI_BASE_URL sends image generation and screenshot analysis to an OpenAI-compatible gateway; unset or blank keeps api.openai.com. The prototype script now goes through receiptedFetch, so its egress is receipted like the rest, and receipts already record the gateway host. A source scan keeps any design file outside auth.ts from hardcoding an OpenAI API URL again, and a request-shape test proves the gateway reaches both the vision and image endpoints. Co-authored-by: JackJin <1037461232@qq.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * review: testing specialist treats negative assertions as decisions A new assertion that something is absent records a behavior removal and needs cited intent. A rename or removal in the diff can empty a standing negative assertion so it passes forever; the specialist now greps the suite for negative assertions naming the old value. Adopted from the testing-specialist part of a community PR; the scope-check hunk targeted text that no longer exists. Co-authored-by: EmilianoU26 <314541067+EmilianoU26@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * review: security specialist checks authorization a route-guard read misses Four access-control classes where the guard is correct and the object still leaks: error pages composed outside the guard, ownership surviving a role downgrade, list/detail/download paths checked as one, and a session mutated before the identity-switch callback is validated. Adopted to review/specialists/security.md only; the /cso hunk targeted a bullet list that is now an OWASP/ASVS table. Co-authored-by: EmilianoU26 <314541067+EmilianoU26@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * review: zero findings is valid; suppress six common false positives The checklist now says a clean diff may come back clean, and suppresses framework-owned error handling, long exhaustive switches, null derefs a type guard already narrows, N+1 on fixed-cardinality loops, hardcoded test fixture values and non-cryptographic Math.random(). The contributor's "missing input validation on an internal function" and "missing await on fire-and-forget" suppressions are left out: both can hide real bugs. Co-authored-by: frosimanuel <frosimanuel@gmail.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(todos): parked contributor ideas by theme; /autoplan permission follow-ups * design-review: capture code tokens before universal principles /design-review read only DESIGN.md and otherwise fell back to universal principles, so a project whose system lives in CSS custom properties, tailwind.config or a theme file got audited and mocked up against an invented aesthetic. The skill now reads code tokens before falling back, and the target-mockup brief reuses the captured colors, fonts, radii and spacing, changing layout only. The contributor's optional microcopy checks (domain vocabulary, human register) are not adopted here. Co-authored-by: Tom Lam <tomlam0811@berkeley.edu> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(sidebar): add a terminal text-size picker to the toolbar The sidebar terminal toolbar gets an XS-XL text-size picker beside Restart. SM (13px) stays the default, so nothing changes until a user picks a size; the choice persists in chrome.storage.local and applies to the live terminal, re-fitting xterm and re-sending the PTY size two frames later so the new character cell is measured first. A VM test runs the real sidepanel-terminal.js through one auto-connect and checks the creation size, the stored-size fallback, persistence and the live resize. Co-authored-by: Yotam <yotsurfing@gmail.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(design-shotgun): generate with Codex's built-in $imagegen on Codex On the Codex host, /design-shotgun now generates and edits mockups with Codex's documented $imagegen skill in its default built-in mode (the image_gen tool), so users signed in with ChatGPT need no OPENAI_API_KEY. The design binary stays for the local comparison board only, images are published with gstack-design-claim as before, and screenshot evolution loads the captured page with view_image before an $imagegen edit. Step 3c-3d moved into a DESIGN_SHOTGUN_GENERATION resolver that returns the existing design-binary text unchanged for every other host; the Claude output differs only in two host-neutral rewordings of the evolve-from-screenshot pointers. DESIGN_SETUP and the regenerate step of the board loop gain matching Codex-only text for design-shotgun. Co-authored-by: Jinzhe <hwang.phy@gmail.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * voice: ban the "load-bearing" stock phrase Models overuse "load-bearing"; it joins the AI-vocabulary ban line in both voice tiers. The tier-2 voice directive is also tightened (the meta "compressed for runtime" tag and the bounded closer's restated exemption clause) so the shared preamble shrinks by 163 bytes per tier-2+ skill, which also pays for the reply-language rule that follows. The ship goldens are refreshed for the new render. Co-authored-by: Nader Helmy <creator.nader@gmail.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * voice: reply in the language of the user's latest message Every skill's voice directive now tells the agent to reply in the language of the user's latest message unless asked otherwise, so long English skill text no longer drags a Chinese (or any non-English) session into English. Mixed-language sessions follow the latest message. Code, commands, paths, identifiers and quoted output stay verbatim, and at tier 2+ so do the machine-read question markers (D<N>, option letters, (recommended)). The rule costs 205 bytes per tier-2+ skill and 144 per tier-1 skill. A further 25-byte cut to the bounded closer's exemption list leaves the net for this wave at +17 bytes per tier-2+ skill and +158 per tier-1 skill. review, qa and browse caps rise with measured notes; the ship goldens are refreshed. Co-authored-by: Xianying Tan <shrektan@126.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(redact-prepush): committed exact-span allowlist at .gstack-redact-allowlist The pre-push hook never fed the engine's allowlist option, so a reviewed, known-benign value (a public dev-compose URL, a documented sample key) warned or blocked every push, and the only ways out were a bypass or reshaping code until the detector stopped matching. The hook now reads the repo-root .gstack-redact-allowlist from each pushed commit (never the working tree), one exact matched span per line with # comments. Only a finding whose matched text equals an entry is suppressed: a password alone, a substring, or a different key still reports and still blocks, and engine.* unscanned findings are untouched. Every push that carries entries prints the entry count and each suppressed finding's rule and file line. Oversized files (over 64 KiB) are ignored. gstack.redact.allowEmail keeps working as before. Co-authored-by: Boyard Engels <boyard.engels@gmail.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(brain-sync): opt-in removal publishing with a bulk-removal valve gstack-brain-sync never published a removal: a deleted synced file, or the old directory after a project slug migration, stayed on the remote forever and gbrain indexed both copies. New setting artifacts_sync_removals (off by default). When on, each drain commits and pushes, receipted like every push, the removal of tracked files that are gone from disk and match the sync allowlist. Transcript pages are never removed here, and a decision log goes only together with its active snapshot. One valve: a drain that would remove more than 20 files at once publishes none and says so. `gstack-brain-sync --publish-removals` lists the pending removals and `--publish-removals --yes` publishes them on demand, whatever the setting. Co-authored-by: Jey2311 <5177215+Jey2311@users.noreply.github.com> * feat(windows): setup.ps1 checks prerequisites and runs ./setup in Git Bash A PowerShell entry point for Windows users. It checks that Git for Windows, Bun and Node.js are on PATH (printing the winget command for each missing one and changing nothing), finds Git Bash from git.exe rather than a PATH bash that may be WSL's, and runs ./setup from the checkout with every argument passed as its own argv entry to a constant bash script. No argument is interpolated into shell source. ./setup itself is unchanged. Co-authored-by: Jim McKeeth <jim@mckeeth.org> * v1.91.63.0: CHANGELOG, version * fix(ci): link bunx after the SHA-verified Bun install in GitLab CI and the Ubicloud setup * fix(redact-prepush): strip every parent column from combined-diff lines, so a merged release bump is exempt like any other * fix(hook-check): treat a Windows drive path as absolute (cygpath when present), so --list finds the skill hooks from a native caller * fix(windows): owned-read requires the read-only attribute on Windows; setup.ps1 passes arguments NUL-separated through a private file; Windows-only tests expect the owned-read approval * perf(hook-check): bundle every hook's TypeScript entries in one bun process instead of two bun starts per entry (seconds each on Windows) * perf(hook-check): read all skill frontmatter in one awk and scan conflict markers with one grep per hook (half the process starts) --------- Co-authored-by: thearbajonart <334330110+thearbajonart@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: DanCanadian <211164803+DanCanadian@users.noreply.github.com> Co-authored-by: Nader Helmy <31414549+creatornader@users.noreply.github.com> Co-authored-by: Nader Helmy <creator.nader@gmail.com> Co-authored-by: Zee Zheng <228040220+spacegeologist@users.noreply.github.com> Co-authored-by: Jack Thomas <17882510+loulanyue@users.noreply.github.com> Co-authored-by: Jayesh Betala <jayesh.betala7@gmail.com> Co-authored-by: techcenter68 <75930234+techcenter68@users.noreply.github.com> Co-authored-by: Mattias Petersson <mattias.petersson@gmail.com> Co-authored-by: Arno V <38716+aversini@users.noreply.github.com> Co-authored-by: 0xDevNinja <manmit0x@gmail.com> Co-authored-by: Benjamin D. Smith <7134745+BenjaminDSmithy@users.noreply.github.com> Co-authored-by: Brian Majewski <1693720+bmajewski@users.noreply.github.com> Co-authored-by: neallee2012 <1499497+neallee2012@users.noreply.github.com> Co-authored-by: Max Hogan <max@maxhogan.dev> Co-authored-by: maxpetrusenkoagent <280464918+maxpetrusenkoagent@users.noreply.github.com> Co-authored-by: katlun-lgtm <264247399+katlun-lgtm@users.noreply.github.com> Co-authored-by: mikehasa <91774998+mikehasa@users.noreply.github.com> Co-authored-by: Briac <137724549+briacSck@users.noreply.github.com> Co-authored-by: JackJin <1037461232@qq.com> Co-authored-by: EmilianoU26 <314541067+EmilianoU26@users.noreply.github.com> Co-authored-by: frosimanuel <frosimanuel@gmail.com> Co-authored-by: Tom Lam <tomlam0811@berkeley.edu> Co-authored-by: Yotam <yotsurfing@gmail.com> Co-authored-by: Jinzhe <hwang.phy@gmail.com> Co-authored-by: Xianying Tan <shrektan@126.com> Co-authored-by: Boyard Engels <boyard.engels@gmail.com> Co-authored-by: Jey2311 <5177215+Jey2311@users.noreply.github.com> Co-authored-by: Jim McKeeth <jim@mckeeth.org> |
||
|
|
f67c478f05 |
v1.91.34.0 fix: /autoplan on current Claude Code and long sessions, quieter pre-push and sync guards, gstack-post, gstack-doctor (#3069)
* docs: Oct 7 follow-up wave plan (pre-review) * docs: Oct 7 follow-up wave plan, reviewed through /autoplan * docs: Oct 7 wave plan, record final gate decisions (UC1 accepted, UC2 rejected) * docs: credit #1822 to @Mike-E-Log and #1743 to @habassa5 (v1.64.0.0) The v1.64.0.0 CHANGELOG entry credited the extension token fix (#1822) and the polyfill exited promise (#1743) to the wrong handle, and the extension-sender-auth test header repeated the first slip. Commit history is not rewritten. Fixes #3054. Co-authored-by: Mike Ilog <48659643+Mike-E-Log@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(context-restore): offer newer checkpoints from nested repos and task worktrees /context-restore could present an older checkpoint as the latest with no error in two layouts: 1. A session started in a non-git parent saved from a nested repo, so the checkpoint went to the nested repo's bucket. Restore in the parent now lists checkpoints of other buckets whose project_root lies below the cwd (BELOW_CWD; the 200 newest are read, and from $HOME only each project's newest). /context-save also leaves a JSON pointer (checkpoint path, bucket, project_root) in the starting directory's bucket when $CLAUDE_PROJECT_DIR is set and files elsewhere; restore lists those as POINTER, in or out of git. 2. A plan checkpoint on the main tree's branch shadowed a newer checkpoint saved in a ticket worktree. When another branch holds a newer checkpoint for the same task (a worktree below the main tree, read from the new worktree: stamp; equal normalized titles; or a shared #123 / ABC-123 token in titles or branch names), restore prints NEWER_TASK and the skill shows both and proposes the newer one. Generic titles (wip, checkpoint, save, notes, todo) never match on title alone, and the worktree rule applies only when restoring from the main tree, so sibling worktrees still never shadow each other. The branch-first ordering itself is unchanged. Refs #3065. Co-authored-by: Thomas Gernhardt <t.gernhardt@softwareprojekt.net> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(redact-prepush): list each MEDIUM finding with rule, file line and fix The pre-push hook printed only a MEDIUM count, which nobody could review without re-running the engine by hand. It now prints one line per finding: rule id, file and file line, and a fix, never the matched value. Line numbers come from the hunk headers (combined --cc headers included), so a finding in a later hunk or past a scan-chunk boundary points at the real file line. Findings from the per-commit catch-up path name the commit whose file line it is, so content removed before the pushed tip is still locatable. Plan items: CEO-7 (summary half), DX-9 (fix lines), ENG-8 (line mapping). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(redact-prepush): stop flagging your own email and already-public authors (#3060) The hook never passed the engine's selfEmail / repoPublicEmails, so every push that added the pusher's address, or a commit author's, raised a MEDIUM pii.email warning for an address the destination already shows. The hook now reads `git config user.email` and one bounded `git log` of author and committer addresses, raw and mailmapped (%ae %aE %ce %cE): the history of every pushed tip (those commits become public with the push), each remote tip being replaced, and, for a new branch or an unknown remote tip pushed to a configured remote, that remote's own tracking refs. A URL or unknown destination never borrows tracking refs, and another remote's history never counts. The read stops at 50,000 commits (the newest authors are used) and 5 seconds. An error or the timeout passes no history and, when an email finding is listed, prints one line saying suppression was limited for this push. The two inputs fail independently. HIGH findings and every other rule are untouched. Controls: a stranger's address, an address only another remote knows, a URL push next to a matching remote, and a first push of a repo with no history all still report. Plan items: A3, CEO-7, CEO-23 (A3 half), DX-9 (partial history), ENG-8 (history scope, mailmap). Co-authored-by: akmandhania <143462686+akmandhania@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(redact-prepush): per-address allowlist for pii.email (gstack.redact.allowEmail) `git config --add gstack.redact.allowEmail <address>` allows that address for MEDIUM pii.email findings only, so a team alias or support address that has to be in the repo stops warning without reaching for --no-verify. It never affects HIGH findings or any other rule, and the pii.email fix line names it. Controls: a different address still reports, and a HIGH secret next to an allowed address still blocks. Plan item: DX-17. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(troubleshooting): pre-push pii.email findings, exemptions and allowlist Plan item: DX-12 (pre-push touchpoint). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(redact-prepush): assemble fixture addresses at runtime The email fixtures were literals, so this branch's own push listed 47 pii.email findings in its test file. Build them from a helper instead, the way the neighbouring tests build credential and IP fixtures. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(browse): offer the user's signed-in tab, name silent aside repl failures Rules (rendered into every browsing skill, kept short): - Rule 1: before the first openTab, offer the user's tabs on the target origin (title and origin only; the rest of listBrowserTabs() stays private) and attach only after the user confirms one. - Rule 4: a second sign-in wall after a confirmed sign-in means the session is bound to the tab or URL; offer that tab instead of another sign-in. - Rule 6 no longer suggests an early return; rule 7 says a fast [ok without GSTACK_STEP_OK is an abort. Cookbook (browse, devex-review): a "Silent failures" list (evaluate returns only serializable values, no top-level return, locator(sel).press(key), an empty DOM read is about the selector until the screenshot and the request's response say otherwise, read toggle state before clicking) and a signed-in tab recipe that prints only target-origin tabs and never closes the user's tab. Parity caps for design-consultation, land-and-deploy, qa and the browse skeleton are raised to the measured sizes, with notes. Refs #3063, #3064. Co-authored-by: Thomas Gernhardt <t.gernhardt@softwareprojekt.net> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(codex): run gstack-codex-probe as a command, one subcommand per probe Generated skills now execute bin/gstack-codex-probe (select-model, check-auth, show-sandbox, check-sandbox, probe-model, check-version, show-first-use-notice, run-with-timeout, log-event, log-hang, help) and capture its KEY: value lines, so no helper state crosses into the calling shell and the preflight works from bash, zsh or sh. select-model keeps --model > GSTACK_CODEX_MODEL > config.toml precedence; run-with-timeout supervises with the existing gtimeout/timeout/ watchdog chain and returns 124 on a deadline; an unknown subcommand exits 64. Sourcing keeps working for skills rendered before the upgrade and prints one deprecation line naming /gstack-upgrade; it and the zsh self-locate block are removed in a release on or after 2026-10-21 (DX-18). Parity caps raised with measured notes for the longer capture lines. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(gstack-post): one argv-only, redaction-scanned write path for PR and issue text bin/gstack-post posts a PR/MR or issue comment, a review-comment reply, a PR title or body, a new PR/MR or a new issue from agent-written files. Every value reaches gh/glab as its own argv element in --flag=<value> form or on stdin, never through a shell string, and a target is a number or a URL of this repository on the same host. The helper owns the redaction scan: it reads each file once, scans those exact bytes (visibility from config, then gh/glab; the pusher's own email suppressed) and sends the same bytes. HIGH is refused with exit 1 and no confirmation can post it. MEDIUM exits 2 with RULE:/LINE:/PART: lines and a TOKEN: digest of the bytes, destination, operation and findings; only --confirm <token> for those exact bytes posts, so any edit needs a new confirmation. gh/glab failures exit 3, usage errors 64. It also carries the projectCards REST fallback and the title read-back that /ship did by hand. The logic lives in lib/gstack-post.ts behind an injectable runner, so its tests run in the Windows free lane; the stub-gh executable test is POSIX. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(autoplan): guard verifies dispatches on Claude Code 2.1.29x (schema strip, unflushed call, named causes) Cause A: Claude Code journals the model's raw Agent input but hands PreToolUse the schema-parsed input; with the fork-subagent gate on (the interactive default in 2.1.292) run_in_background is dropped, so the journal record never deep-equaled the payload. nativeToolInput now drops only that documented strip for Agent. Agent input is bound on both paths: keys limited to prompt, description, subagent_type (general-purpose) and run_in_background; a model override or any other key is denied. Cause B: when a ready journal lacks the current call, the guard evaluates the payload placed after the last journaled record instead of polling for a record that may arrive only with the tool result. A phase transition counts a report only when a later journaled record follows it (and, on the journal path, it is not in the current call's message). One batch rule covers both paths; a background reviewer keeps the invocation armed until its completion notice. Every outcome now has a stable reason code, disposition and anchor (autoplan/bin/guard-reasons.ts). UC1: Claude-Code-caused states (unrecognized shape, journal lag, rewritten journal, oversized record, unchecked-version schema strip) allow with a visible warning; integrity failures stay denials. No denial advises a bare retry. Every guarded decision appends one content-free line to analytics/autoplan-guard.jsonl, trimmed to 1,000 lines past 256 KiB. Co-authored-by: Jared <182125291+yolo-jared@users.noreply.github.com> Co-authored-by: crblabs <293123359+crblabs@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(autoplan): publish each phase report with a no-op call; foreground requests are conditional Phase-close step 6 sends the report in a message whose only tool call is the Bash no-op ': autoplan-published <phase>', and step 7 makes the next guarded call in a later message, so the guard sees the report flushed before the next phase entry regardless of Claude Code's journal timing. Every site that asked for run_in_background: false now asks for it only when the Agent schema offers it and says how to recover when a dispatch runs in the background anyway (wait for its completion notice). Parity caps rise by the measured bytes. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(ship,spec,review): PR and issue text goes out only through gstack-post /ship: Step 18 writes the title into an agent-written file. An existing PR's title is piped from gh/glab through gstack-pr-title-rewrite.sh --stdin (new), so neither the agent nor a shell string carries it; a new title is written with the file tool and its version prefix checked in the file. Step 19 composes the body as before and publishes with gstack-post pr-create, or pr-body then pr-title, which scan the exact bytes they send. The separate title and body scans, the hand-rolled REST fallback and the title self-check are gone (the helper does all three). Title preparation moved into the pr-body section, so the skeleton shrinks. /spec files its issue with gstack-post issue-create and drops the pre-issue re-scan; Greptile replies use gstack-post reply and pr-comment. scripts/resolvers/redact-doc.ts loses its PR and issue sinks, and a test keeps any template from rendering one again. Tests that pinned the old scan-then-gh wiring now pin the gstack-post wiring; the publication tests run the real compose and publish blocks against a stub gh with the real helper (HIGH in title or body refused, MEDIUM token flow). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * ci: pin Claude Code 2.1.292 in the CI image 2.1.292 is the npm latest users run. Its interactive default turns on the fork-subagent gate, which strips run_in_background from the Agent schema and backgrounds reviewers; CI on 2.1.284 never saw the /autoplan guard break. The image tag is a content hash, so every eval workflow picks up the new image without a workflow edit. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(brain-sync): one drain lock for every writer to the artifacts repo gstack-artifacts-init, gstack-brain-restore, gstack-gbrain-source-wireup and the skill-start merge ran git in $GSTACK_HOME without the drain's lock, so the drain could never tell an abandoned .git/index.lock from a live one. They now take the same mkdir lock (bin/gstack-brain-lock.sh): the drain and the skill-start merge skip when it is held, user-run writers wait for it (GSTACK_BRAIN_LOCK_WAIT, default 120 s), and a child of the holder (the drain's daily worktree advance, restore's wireup) inherits it by token. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(brain-sync): hold back only the flagged file, keep coupled artifacts whole One file with secret-shaped text used to block every push, silently. The drain now attributes scanner hits to files in one pass over the staged diff (split on its diff --git headers), holds back each flagged file with the rest of its coupled group, unstages it, and requires the remaining staged diff to re-scan clean; anything short of that falls back to a full unstage and status blocked. Held files stay queued and are re-scanned every drain. - Status file gains held_count, drainable, last_drain_at, last_push_at and held[] (path, scanner rule, dependents, both fixes); new status held. - Coupled groups come from an explicit map (decisions.jsonl and decisions.active.json): a queued member stages the whole group, a group stages only when its snapshot matches its log in the index, a skipped member stops the whole group. - --unskip-file undoes --skip-file and queues the path again. - An index lock older than 10 minutes is removed under the drain lock; a younger one, a failed git add, a failed commit (hooks included) keep the queue and report status error. A verified empty staged diff is the only "nothing to commit". git add runs once, batched. - The scanner reads bytes, so undecodable content no longer crashes it into a false clean; matched text never reaches the status file. - An empty-queue run with unpushed sync commits stays push_failed. - Privacy-held duplicate records collapse to one per path; --status counts a spool too deep for a shell glob. - --attention prints skill start's fixed attention lines from the sync status table in the usage header. Co-authored-by: v639dragoon <matthewsbrickley@gmail.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(skill-start): ARTIFACTS_SYNC attention lines for a stuck sync Skill start now prints one fixed attention line per sync-status-table row that applies (held, blocked, push_failed, error, unknown, stale-push, stale-drain), each naming gstack-brain-sync by absolute path. Values from the status file are clamped (status code to the table, counts to digits, timestamps to their shape), so the status message, file paths and scanner output never reach the line. The preamble tells the model to surface the line in one sentence and continue. Skill-start tests are generated from the table in bin/gstack-brain-sync, and docs/gbrain-sync-errors.md carries the same table. Co-authored-by: v639dragoon <matthewsbrickley@gmail.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(outside-review): severity words in label position count as findings The Oct 7 /autoplan run's Codex CEO and DX reviews labeled seven and eight findings High/Medium without [Pn] tags, and the classifier printed VERDICT: clean / FINDINGS: none for both. lib/outside-review-result.ts now reads severity words in label position (Severity: High, a leading High: / High — / [High], **High**, a table cell): critical/high block like P0/P1, medium/low are advisory. Words in prose (high-level, low-risk, no critical findings) never count. A review or structured response with neither tags, labels nor an explicit no-findings statement is unverified, never clean (DX-11, ENG-10). Design-direction proposals move to a new proposal gate so they keep needing only their Recommendation line, and review prompts ask for a severity per finding. Fixtures reproduce the CEO/DX label shapes, the eng [P1] output, a table and prose negative controls; the stored Codex panel keeps its verdicts. docs/troubleshooting.md explains how the verdict is read. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat: gstack-doctor readiness report and setup --status Codex row (B5) bin/gstack-doctor prints one row per check without starting a skill: install root (the registry rows behind ./setup --status), state root, Bun against the floor, hook parse check, Codex mode and self-locate via gstack-codex-probe subcommands, the cached model probe with its age (--live runs the paid probe-model), artifacts-sync health from the status file with the status code clamped, the browse bundle, Claude Code version, the largest session journal and the last five schema-1 guard reason codes. Rows are ok, warn, not configured or fail; only fail exits non-zero; fix lines name helpers by absolute install-root path. ./setup --status gains a read-only Codex row (bin/gstack-codex-status.sh, shared with the doctor) and ends with the doctor's absolute path. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: bug-report template asks for doctor output; README troubleshooting entry; doctor test in the Windows lane The template gives the Claude Code doctor path and a lookup for other hosts and names no bare gstack- command (asserted in test/gstack-doctor.test.ts). The doctor test runs every script through explicit bash argv, so it joins the curated Windows free subset. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(troubleshooting): readiness check section points at gstack-doctor Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(question-tuning,plan-tune,gbrain): free text reaches helpers only through agent-written files Question tuning no longer pipes the question summary through printf: a registered id needs no summary, and for an unregistered id the agent writes the summary to .gstack/tmp/qt.txt and passes --summary-file (new). The helper resolves a relative path against the git top level, removes scratch files under .gstack/tmp, and asks normally when the file is missing. /plan-tune tune events carry the user's own words again: they go into a file the agent writes and reach gstack-question-preference --write through --free-text-file (new), still behind the injection filter and the user-origin gate. docs/gbrain-write-surfaces.md drops its heredoc templates for the agent-written page file on stdin, matching the per-skill save block, and the generic save block stops showing a quoted --content argument. The tuning prose was tightened so every preamble stays within its size cap. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(evals): daily autoplan-schema-canary on the latest Claude Code A periodic rule case installs the latest published Claude Code with install scripts off, verifies registry signatures, and runs one headless session with the fork-subagent gate on whose PreToolUse hook records an Agent and a Read payload. Each payload must match its journal record under the guard's own comparison, keep the journal's key set apart from the documented run_in_background strip, and stay inside the Agent allowlist; a background Agent's completion notice must keep the shape the guard reads. evals-periodic.yml runs it daily on its own schedule and concurrency group (read-only token); the weekly census also includes it. A free test proves the comparison fails on an injected strip. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(doctor): read the artifacts sync held count from held_count, the field the drain writes * fix(artifacts sync): the init and restore pre-commit hooks catch Bearer/Basic/Token-prefixed JSON auth headers like the drain does * feat(greptile-early): detect Greptile, ask once on public repos, open the early draft, wait for the review bin/gstack-greptile-early backs /ship's early Greptile PR: - detect: a root .greptile/ folder (which takes precedence), greptile.json, or a Greptile comment on the repo in the last 90 days; triggerOnDrafts from the effective root config; repo visibility; public-repo consent. It prints the signal, that /ship will push and open a draft now, the 10-minute wait cap and the absolute gstack-config command that turns it off. - consent yes|no: the public-repo answer, remembered per repo in the project's state. - open: opens the draft through gstack-post with a body saying /ship opened it early, and posts one @greptileai comment through gstack-post when the config does not set triggerOnDrafts: true. An open PR is left alone. - wait: polls every 30 s for a completed Greptile check run, a Greptile review of the head commit or a summary naming it; each call returns within about 90 s and reports timeout 10 minutes after the PR opened. gstack-config gains ship_greptile_early (default true, invalid values rejected): on automatically whenever the repo uses Greptile, off per user. The logic is in lib/greptile-early.ts behind an injectable runner, so its fixture-repo tests run in the Windows lane; an end-to-end test drives the real helper and gstack-post against a stub gh. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(ship): early Greptile PR at Step 6.5, bounded wait at Step 10 (#3020) When the repo uses Greptile, /ship pushes and opens a draft PR right after its free tests pass (new lazy section greptile-early, Step 6.5), so Greptile reviews while Steps 7-9 run. A public repo asks once, remembered per repo; declining keeps today's order. Step 10 waits for that review with gstack-greptile-early wait and takes the existing unavailable route on a timeout, never a claim of zero comments. Step 18 replaces the provisional title, Step 19 marks the draft ready unless a draft was requested, and a /ship that stops after Step 6.5 leaves the draft open with one comment saying why. ship's union cap rises to 1.5275 with the measured note (B4 +836 bytes, B2 +4,732 bytes); the step-numbering guard allows 6.5; ship goldens are refreshed for B4 and B2. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(autoplan): the publication no-op is 'true autoplan-published <phase>' Measured on Claude Code 2.1.292 in a default-settings interactive session: a bare ':' Bash command asks for approval ('This command requires approval'), and after a background reviewer's completion notice starts a new turn the skill's allowed tools no longer cover it, so the phase-close no-op prompted the user. 'true' with arguments runs without approval and prints nothing. The guard only needs a later journaled record, so the command changes everywhere it is named. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(evals): live autoplan-guard-pty case on the pinned Claude Code A gate-tier rule case (one trial, haiku) drives an interactive PTY session with default settings through a project skill that carries /autoplan's own hook block: init, Phase 1 entry, a CEO reviewer dispatch that sends run_in_background, a prepared close packet, the report published with the no-op, and the Phase 2 entry in a later message. It reads outcomes from the guard decision log (three verified allows) and fails if the no-op raises a permission card; other cards are approved and printed. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(autoplan): bounded, append-tolerant owned-journal read (A2) The publication guard no longer reads the whole parent journal or refuses it at 32 MiB. lib/claude-owned-journal.ts streams the bytes present at open to the last complete line (pass one), keeps a content-free index per record and decides ownership, ancestry and causal order on it with the same checks and reason codes as before. Pass two reloads in full only what the evaluation reads (autoplan/bin/guard-journal.ts): every literal init and its result, the current call, and inside the invocation window (from the latest human turn at or before the bound chain's first init) guarded and close-packet Read results, structured Bash results, error results, assistant text after the first close Read and active-plan mutations, plus the earlier Read a dedup reply cites even before the window (ENG-4). - lib/claude-journal-records.ts: per-record event extraction, record metadata and the causal-order checks, shared by readPlanCountTranscript and the bounded reader. The batch reader keeps its whole-file read and cap. - Appends after open never fail a read; same device and inode and no shrink are required (identity). A second read in one hook invocation must hash bytes [0, first size) the same, or it is `rewritten` (UC1 unverified); the unrecognized-shape double read uses that prefix hash. `changing` is removed (REMOVED_CODES; its anchor stays). - OWNED_RECORD_MAX_BYTES (32 MiB): only one record over it is too_large. OWNED_RETAINED_MAX_BYTES (32 MiB): over it is the new oversized_invocation fallback denial. GSTACK_TRANSCRIPT_TEST_MAX_BYTES and GSTACK_TRANSCRIPT_TEST_RETAINED_BYTES can only lower them. - ENG-5: evaluation groups uses and results by tool id once (no per-tool rescans). CEO-25 / ENG-5 spike (120 MiB synthetic, 31,242 records, 4 vCPU Linux, Bun 1.4.2): a full streaming rescan (parse every line, small index, sha256) took 254-326 ms at 147-161 MiB peak RSS; a pass-one index cache under the state root (load cached index, verify a 64 KiB tail hash, parse the tail) took 26-29 ms at 47 MiB. The rescan meets the 1 s budget, so the cache is not adopted: it would add trusted persistent state and invalidation for no budget need. A backward tail read cannot prove competing_root or cycle, so it was not a candidate. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(autoplan): journal-read benchmark and its dispatch-only workflow (CEO-2, CEO-6) scripts/measure-journal-read.ts builds two synthetic 120 MiB parent journals around a real /autoplan invocation (mixed: ~28k records, most bytes inside the invocation; large-invocation: ~89k records with a current invocation of many small records), keeps appending while the guard reads, and measures one hook call in a fresh process (wall ms, peak RSS). The workflow runs it on ubuntu-latest and macos-latest on workflow_dispatch only. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(evals): autoplan-long-session, a resumed >100 MiB session enters Phase 1 CEO-15 with ENG-6's observer: a real session is compacted, its journal padded past 100 MiB with owned records before the compact boundary, and the resumed interactive session runs the scripted phase boundary; the guard decision log must show a verified Phase 1 allow. A free test proves that observer on a padded journal through the lower-only bound seams (the PTY counting reader refuses the same journal), with a sidechain control that must deny. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * v1.91.34.0: CHANGELOG, TODOS, version; harness decision for test-pr-profile; ship title-step test reads its new section * docs(changelog): use an example.com address in the allowEmail example * test: assemble GitHub-token fixtures at runtime in the new brain-sync and skill-start tests (CI credential scan) * fix: integration repairs across the wave (Step 6.5 fence, printed helper paths on Windows, probe usage without a heredoc) and tests pinned to the moved title and gstack-post contracts * test(doctor): the healthy fixture builds browse.exe on Windows, the name setup uses there * test(shared-libs): recognize Claude Code 2.1.292's internal git probe prefix (format.pretty and per-hook disables), with its CI receipt * fix(ship-measure): report lists v1 measurements as an older format instead of crashing --------- Co-authored-by: Mike Ilog <48659643+Mike-E-Log@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> Co-authored-by: Thomas Gernhardt <t.gernhardt@softwareprojekt.net> Co-authored-by: akmandhania <143462686+akmandhania@users.noreply.github.com> Co-authored-by: Jared <182125291+yolo-jared@users.noreply.github.com> Co-authored-by: crblabs <293123359+crblabs@users.noreply.github.com> Co-authored-by: v639dragoon <matthewsbrickley@gmail.com> |