A base pregate.json with gbrain's dependencies and remote_gate
"bun run ci:ubicloud" (a package script whose stub needs UBICLOUD_API_KEY,
names VMs from UBI_OWNER and prints PREGATE_REMOTE). Under 8 cores the test
tier is one obligation naming the command; --remote passes the caller's
UBI_OWNER and key through and clears it on the report; without the key the
gate's own error shows and the obligation stays uncleared. #3190's path
needed no change.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
(cherry picked from commit 4d69ff02df)
Unmarked Markdown that no test depends on is a docs/no-tests empty lane.
A file a test reads, including a fixture, still selects that test through
the import graph. Unmapped source and unreferenced test-tree files still
fail closed.
Co-authored-by: Nick <surlymo@apache.org>
(cherry picked from commit 7aabbddf3d)
A docs-only diff with no .gstack/pregate.json failed lanes as
PREGATE_NO_LANE. Planning and evidence Markdown is now a docs/no-tests
empty lane. Unmapped source files still fail closed.
Co-authored-by: Nick <surlymo@apache.org>
(cherry picked from commit e8793e59e8)
When VERSION matches but ls-remote's main SHA differs from this checkout's
HEAD, bin/gstack-update-check asks the GitHub compare API (status, ahead_by)
through the existing receipted curl and prints
UPGRADE_AVAILABLE <ver> <ver>+<n> <sha>; a diverged or unreadable compare is
CHECK_FAILED (unknown), and behind/identical is up to date. Never fetches.
The cache gains an IDENTITY line (head, compared remote SHA, upstream): an
outcome replays only for the same HEAD and upstream, a same-remote refresh
reuses it without another compare, and a git checkout ignores a legacy
one-line cache (non-git installs keep the one-line format). The snooze is
keyed by the SHA. gstack-upgrade's question, snooze note and What's New step
handle the four-field line; gstack-skill-end reports it.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
(cherry picked from commit 421e66d2a4)
lib/pregate/checks/timing.ts prints TIMING_ASSERTION: <file>:<line> <pattern>
and a TIMING_ASSERTIONS summary; gstack-timing-ok: <reason> in any comment
syntax on the line or the line above escapes one. It warns
(PREGATE_TIMING_ASSERTION): measured on gstack (9 of 47 test-touching
commits, 263 hits in the tree) and gbrain (37 of 95 commits; 31 of 38 sites
of the five timing-flake fixes), blocking would stop a fifth to two fifths
of test changes. Adds the /review checklist rule and the /investigate
timing-flake playbook.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
(cherry picked from commit a3b86b10b2)
* fix(cso): --paths scopes an audit and reports every skipped path
A repo over the 64 MiB cap was audited on hand-trimmed copies, so the
verdict read assessed over partial input. --paths records out-of-scope
files unread as snapshot-inputs gaps (coverage partial), keeps --diff
fail-closed, and carries the scope through submit, recheck and replay.
Field list 2 item 12; related #2993.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(cso): close /review findings on --paths scoping
- Comparison mode hashes out-of-scope files in bounded 1 MiB chunks and
re-hashes them in both stability passes instead of reading whole files.
- --diff --paths refuses every changed path outside the scope except host
dependency trees, including credential and agent configuration.
- --paths prefixes that report persistence would rewrite are refused.
- In-scope gaps sort first; out-of-scope files and deletions share the
skipped tier and are dropped from transformations.
- History is limited to --paths, reported as partial, and history queries
on out-of-scope paths are refused.
- A --diff recheck refused for out-of-scope changes says to start a new audit.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(cso): troubleshooting names --paths for the source cap
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(changelog): /cso --paths entry
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* v1.91.112.0 fix(cso): --paths scopes an audit and reports every skipped path (#3230)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(evals): three PR-gate background reds were a detector, an interface and a helper defect
- docsync-fault-eval: a conditional mention (until/unless/once/when/before/if) of
'Documentation is current' is not a false current claim; replay corpus for
ship-docsync-launch-failure from PR run 38336400566 with derived refusals.
- gstack-skill-start/gstack-skill-end: --help prints usage and exits before any
side effect (it used to start a session); the docsync interface admits the
lifecycle helpers' own --help; captured run 38969924945 replays clean.
- qa deadline policy: listing the owned qa-reports/screenshots directory is
bookkeeping (qa-only-no-fix, run 38969924945).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(evals): the launch-failure corpus is a row in the docsync corpus test that owns docsync-fault-eval
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(evals): register the launch-failure corpus and docsync-store capture in their contracts
The B1 corpus contract wants its own detector-corpus-<case> replay test, so the
launch-failure corpus keeps one, listed in the test-of-test baseline beside its
sibling corpora; FREE_FIXTURES names both new fixtures' free consumers.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(review-army): the scope block prints the SCOPE_* signals specialist selection reads
The Detect stack and scope block sourced gstack-diff-scope silently, so an
agent that needed SCOPE_FRONTEND to pick specialists appended its own echo and
left the declared caller interface (ship-exploratory-plan-checks red in run
38981523623). The block now lists the sourced signals itself.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* v1.91.111.0 fix(evals): four PR-gate background reds were a detector, an interface, a helper and a workflow-block defect
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(capy): install and launch the project's pinned Node; launch Bun through a bun-only directory
gbrain pins node 24.18.0 in CI while the Capy image ships 24.21.0 in
/usr/local/bin, so a full install still ended with fail pins (GBRA-117).
The installer now resolves the project's exact Node pins the way it resolves
Bun's (required non-CI pins, CI pins in different jobs as alternatives): the
node first on PATH, then gstack's store copy and nvm's copy of each wanted
version, then any other node on PATH. With no match, install mode downloads the
pinned release into <state root>/runtimes/node and checks it against
SHASUMS256.txt. The resolution is recorded in the install verdict
(node_path, node_version, node_rule), and --check reuses it.
The launch PATH no longer prepends a shared bin directory. When the resolved
Bun was /usr/local/bin/bun, the image's node there shadowed every other node
(GBRA-122). A store Bun still launches from its own version directory; any
other Bun, and a Node the launch needs, launch through a gstack-owned
directory of symlinks beside the verdict. The pregate's lanes use the
recorded launch directory.
The doctor's pins row names the node it read and, for a Node mismatch, the
installer command that installs the pinned Node (or nvm install <v> off
Capy).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: v1.91.109.0
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(egress): exempt the Node installer's two release downloads with their reason
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: restamp v1.91.110.0 (1.91.109.0 is #3225's slot)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(doctor): make the Node pin case platform-neutral (an any-lane CI pin, bash's spelling of the stub path)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(upgrade): accept a Git Bash checkout whose toplevel Git spells C:/…
bin/gstack-upgrade compared `git rev-parse --show-toplevel` (C:/x from Git
for Windows) with `pwd -P` (/c/x in Git Bash) as strings, so every Windows
Git Bash install was refused as "not a gstack checkout", and the doctor's
recovery line points at this command. Compare the two through
gstack_path_same (bin/gstack-path-spelling.sh); a tree nested inside another
repository is still refused.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(redact): a catalog field named <schema word>_key is not a credential (#3208)
env.kv accepted every separated name ending in _key, so a catalog entry
`"input_key": "expected_media_rate_bits_per_second_ingress"` failed
pregate's never-downgradable secrets check as MEDIUM env.kv [secret]. The
camelCase twins (cacheKey, sortKey, partitionKey, idempotencyKey) were already
rejected for having no credential prefix; the snake/kebab/dotted forms of
those data-model words now are too. ALL-CAPS env names (INPUT_KEY=) and
credential-word names (signing_key, stripe_key, input_secret) still fire.
Reported by @brentyates-swx.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(cso): build the git-hardening fixture repo once per file
Each test built its fixture repo with five /usr/bin/git spawns inside
its own 5 s budget. On macOS that binary is the Xcode shim, and on a cold
runner those spawns cost far more than the code under test: in run
38800592772 the first test timed out at 5 s before readGitMetadata got
past its first lstat, and afterEach then tore the fixture down under it.
Build the repo once in beforeAll, under the same 30 s bound each fixture
spawn already declares, and give every test a fresh copy. The assertions
and the code under test are unchanged, and each test keeps its full 5 s
for the code under test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(browse): rule 3 treats wizard steps as writes and reads back sets before saving (#3216)
On a non-local target a wizard or dialog step (Next, Step N, a menu item
that opens a dialog) now counts as mutating until its handler or network
effect shows otherwise, and its Cancel proves nothing. Before any Save or
Submit, every programmatic set is read back and the flow stops on a
mismatch. The cookbook's silent-failures list adds the skip-path
precondition probe. Redundant clauses in rules 2, 3, 7, 8, 9, 10 and
READY are tightened so the shared setup grows by 3 bytes and every
browsing skill stays under its parity cap.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(plan-design-review): keep the Completion Summary out of the regenerated report (#3219)
The design review saved its Completion Summary inside the terminal
GSTACK REVIEW REPORT section, which the next plan review deletes from
its heading to the next "## " heading. The summary, deferred list and
unresolved decisions now go in their own "## Design Review Completion
Summary" section above the report, and the template says everything
under the report heading is regenerated by the next review.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(redact): exempt a schema field only when its name and value both say so (#3208)
Review (GPT-6.1 Sol outside voice): the name-only exemption also silenced
real secrets, e.g. Azure's cosmosdb_primary_key and any longer name such as
api_cache_key. Now the whole name must be one data-model word plus _key
(primary/secondary dropped) and the value two or more lowercase identifier
words; an entropic value, a longer name or a credential name still fires in
.env, YAML, JSON and TOML.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(upgrade): the Git shim delegates with the unshimmed PATH
A PATH-searching git wrapper found the shim again and recursed until the
test timed out. The shim now restores the host PATH before running git.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(pregate): secrets scans each file with its type and never reads an emptied diff as clean (#3211)
addedLines() flattened every file into one added.txt, so gstack-redact never
saw a .ts path and the #3048 source-expression exemption never ran: TS
properties such as `token: credentials.token,` failed the gate as MEDIUM
env.kv. Two false negatives predate this wave: the `+++` header filter
dropped added content lines that begin with "++", and `git diff` honoured
diff.external/textconv, so an external driver that prints nothing made a
branch carrying a real AWS key pass with "no added lines".
Added lines are now parsed hunk-aware per file (the pre-push hook's rules),
with --no-ext-diff --no-textconv, and each file is scanned as
<tmp>/<i>/<basename> so its type survives; findings name the file.
Reported by @brentyates-swx.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(plan-devex-review): keep the DX Scorecard out of the regenerated report (#3219)
The DX Scorecard had the same placement gap as the design Completion
Summary: with no rule, it could land inside GSTACK REVIEW REPORT, which the
next plan review deletes. It now goes in its own "## DX Review Scorecard"
section above the report.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* v1.91.109.0 fix: wave 5 — pregate secrets false negatives (#3211), Windows gstack-upgrade, env.kv schema keys (#3208), browse rule 3 (#3216), review summaries (#3219)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Co-authored-by: Scott Gigante <scott@gethubflow.ai>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>