mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-31 22:14:25 +01:00
7f53ddb1f3cc97dd669bfb8fbcb98517af14d498
438
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7f53ddb1f3 |
v1.91.257.0 feat(pregate): clear --receipt accepts a remote_gate receipt from a stamp-only predecessor tree (gbrain gate-ahead) (#3486)
* feat(pregate): clear --receipt accepts a remote_gate receipt from a stamp-only predecessor tree (gbrain gate-ahead) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (hex object ids, stamp_sensitive_gates and base-branch refusals, one substitution type, docs) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(pregate): harden the stamp-only diff read (fixed presentation, diff-tree reconciliation), refuse an unreadable base policy, check the receipt before git work, bind verify to the receipt tree; docs audit corrections Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(pregate): the stamp-only suite expects the Linux-host lanes verdict; skip itself on win32 like test/pregate-remote.test.ts 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> |
||
|
|
576839cb8c |
v1.91.256.0 feat(ship): review loop converges (frozen scope, 3-pass cap, NO FINDINGS) and receipts carry across conflict-only merges (#3481)
* feat(ship): review loop converges (frozen finding scope, 3-pass cap, NO FINDINGS first-class) and receipts carry across conflict-only merges
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(ship): keep the Step 9 first-entry and Fix-First phrasing the skip/requeue contract asserts; fill the review record's pass, review_scope and range_base placeholders in the caller template test; narrow a test type
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (pass 1) and the review-loop budget wording
Two blocking findings from /ship's own pass 1, both reproduced in the QA smoke before the fix:
gstack-ship-receipt carry hashed the product diff with git patch-id --stable, which strips
whitespace, so a space moved in a reviewed shell line carried as "no product change"; and it
classed package.json and every lockfile as release metadata, so a dependency swap carried too.
The patch-id is now --verbatim, package.json and VERSION are metadata only while the change is a
version stamp (lib/pregate/stamp-only.ts), lockfiles are product unless the policy names them,
the test globs name code extensions, a dirty working tree refuses before anything is compared,
and a receipt carried twice keeps the reviewed head as carry.from.
gstack-review-scope: an unresolvable base is POLICY_SOURCE_UNAVAILABLE instead of a silent
working-tree read; --range-base is validated; git runs with core.quotePath=false; range_base is
null on pass 1; a blocking finding with no path is fix; category "testing" is a test finding
below the floor; defer searches once, files nothing on a failed search and exits 0 unfiled;
summary refuses zero matching passes and the receipt write is chained to it with &&; a finding
the diff causes elsewhere names the changed line in `cause` and classify follows it.
Review-loop budget wording (ideas from tstack's sol-loop and pstack's interrogate, rewritten;
NOTICE.md): the blocker / should / nit glossary and two stop rules in Step 9.4, the checklist
and docs/review-policy.md; a lead-judgment stage in the finding merge both /review and /ship
render. The core read diffs $RANGE_BASE from pass 2 on. Caps and pins re-measured with reasons.
Step 7 coverage audit: four tests added in existing files, the --review-loop case moved to its
own test (the shared test tripped bun's 5 s default).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pin the renumbered review-army stages and point the wording test at product code
CI at
|
||
|
|
b004c06dbc |
v1.91.255.0 fix(ship-queue): fill trains at 3 READY PRs or one hour, and price every case shard's trial (#3478)
* fix(ship-queue): fill trains at 3 READY PRs or one hour, and price every case shard's trial
The 5-PR / 3-hour fill left READY PRs waiting most of a day; .gstack/ship-policy.json
now fills at max_size 3 or fill_hours 1, whichever comes first (fillDue already
dispatches at either bound). train verdict printed cost=$24.41 for a train whose slice
report said cost $32.92 known + 54 of 136 trial(s) cost unknown: E2E records named by a
display label ("/benchmark workflow") were never attributed to their case id, so the
per-case sum was short. A case shard's records now belong to its one case; a multi-case
shard with display-labelled records keeps those trials unknown. The ATTEMPT: line names
how many cases have no cost instead of printing a partial sum as the total.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ci): record the paid-report.ts harness decision and keep ship-queue-train-cost.test.ts off the Windows subset
scripts/lib/paid-report.ts is a pinned shared-harness file, so test/harness-version.test.ts wants a HARNESS_VERSION decision for its edit: non-behavioral, because a case shard's records are attributed to its one case for the trial's cost, class and error fields while no case's outcome, panel verdict or selection changes.
test/ship-queue-train-cost.test.ts drives bin/gstack-ship-queue against the #!/bin/sh gh shim, which windows-latest cannot run (windows-free-shard 2 on #3478 at
|
||
|
|
568cd5aa56 |
v1.91.254.0 pregate: starter policy, benign-finding allowlist, environment vs diff failures, per-run scratch (#3480)
* pregate: starter policy, benign-finding allowlist, environment failures, per-run scratch
A repository with no .gstack/pregate.json now gets a warn (PREGATE_NO_POLICY)
with a starter policy printed, instead of PREGATE_NO_LANE on every touched
file; gstack-pregate init remains the explicit write. The policy gains an
allowlist for benign secrets/pii findings (env.value and secret never
allowlistable). Checks that cannot run because of the machine report
PREGATE_ENVIRONMENT (incomplete, with kind and evidence) apart from diff
failures. Every run writes its scratch under the state root, per run id.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* pregate: rename run-scratch module (strays rule) and map starter.ts to its test
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* pregate literals: match a module as a path fragment, require the constant name for a one-character value
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
guards: an exited guard is the machine's only on exit 127, never from its output;
secrets: clear an interrupted run's added-line copies before scanning;
environment: one fix table per kind, one ANSI strip, hoisted not-found vocabulary;
starter returns its lines; allowlistDigest reuses sha256; stale headers and the
PREGATE_INCOMPLETE fix clause updated; tests for the mixed verify branch, disk
precedence, allowlist boundaries, a positionless finding, head-policy strictness,
run-id edges and the unwritable state root.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* pregate: count a module's full file name without a directory as a consumer
consumersOf anchored both the stem and the full basename on a path
separator, so run('install.sh') or bash install.sh without a directory
stopped counting for a multi-character old value. Only the bare stem
needs the separator; the full file name is specific on its own.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* pregate: a diff cannot clear itself as an environment failure; a taken --run id gets its own directory
Adversarial review of the environment classifier and the scratch layout:
- exit 127 and 'command not found' are missing-binary only when the
command's own binary is off PATH (runner, guard and remote gate alike);
a script the diff controls that exits 127 is the diff's failure
- a local lane with no test summary is classified from its output only
when the runner was not seen starting a test file; a remote gate only
from its first 40 lines, before any test output could stream
- environment.proof records launch (certain) or output (inferred); an
output-inferred cause never says 'the diff is not at fault', its line
says '(inferred from output)', and verify names such checks
- a runner killed by a signal is PREGATE_INCOMPLETE, not missing-binary
- a --run id whose directory exists takes <id>-2 .. -9 instead of
sharing (and truncating) a live run's logs
- engine.* findings are never allowlistable; a pattern entry the scanner
gave no position for is reported as not tested instead of silently inert
- docs: synopsis --run, no-policy lanes wording, verify's code list,
guard exit 127 carve-out, PREGATE_SECRETS allowlist pointer, scratch
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(pregate): PREGATE_INCOMPLETE names a signal-killed runner; CHANGELOG lists every doc edit
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>
|
||
|
|
4d48d39e51 |
v1.91.253.0 feat(captain): /captain skill (also /crew), crew templates and docs/captain.md for running a crew from one controller (#3473)
* feat(captain): /captain skill (also /crew), crew templates and docs/captain.md for running a crew from one controller Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore(captain): regenerate SKILL.md at main's version Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(captain): AGENTS.md and NOTES.md templates, roles, ship lane sequence, owner device and lessons loop in docs/captain.md; owner-brief closes with the do-it reply Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(captain): review pass 1: 'do it' parses as rec, READY template matches the tool's lines, slot-2 and freeze wording, mergeChangelogs named, parameter lists and doc numbers aligned Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(captain): align the slot-call BASE merge, freeze repair and severe-race wording across skill, CREW.md and docs; router routes on phrases; receipt head width as printed Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(captain): CREW.md template becomes pointers plus parameters; every crew rule gets a canonical home in gstack (lane discipline, outside contributions, stale READYs, standing spend, the lane side of flaky reruns in docs/captain.md; the rule-to-home map) 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> |
||
|
|
8663c3d25f |
v1.91.252.0 feat(retro): factory scorecard (lead time, gate cost, red-train and flaky rates) and the recommended-harness adoption doc (#3471)
* feat(retro): factory scorecard bin (lead time, gate cost, red-train and flaky rates) and the recommended-harness adoption doc Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(scorecard): register the recorded gh fixture with its free consumer Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(scorecard): cover --gate-event any, an empty window, a failed PR read and a bad --now Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Review pass 1 (core checklist, testing, maintainability, security, performance, simplification, state-machines, red team) over the whole diff: - the flaky line and cost-per-merge depend on every input they read, so a failed free-run or PR read prints unavailable (...) on its half instead of 0 - a PR verdict-comment cost backs one gate run per PR; a READY comment after the merge is ignored - one unreadable artifact leaves its run without cost or flake data instead of dropping the gate section - --repo defaults to the origin owner/name and is required without one (no built-in repository) - --max-artifact-runs, --pass-cap and --pass-marker are validated; --csv creates its directory - one artifact listing per gate run; PR comments are paged; issues use the exact window instant - every run appends its rows to trend.csv in --out-dir - new row: review passes per PR (median, p90, PRs at the cap) from the ship receipt or a comment marker - /retro: report format gains the Factory scorecard slot; the Step 7.5 fence quotes its placeholder - tests for each; <window-days> joins the placeholder allowlist Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: review pass 2 (delta): usage text, pass-marker capture group, GitHub-host origin parsing, idempotent trend.csv - usage() strips the header comment decoration again; --help text asserted - passCount takes the first all-digit capture group; --pass-marker without a capture group exits 2 - --repo falls back to the origin remote only on github.com or GH_HOST; a local-path origin exits 2 - trend.csv keeps one row set per repo and window (a rerun replaces its rows) and always carries its header - /retro Step 7.5 points at SCORECARD_TREND for the weeks; the doc cites the per-PR baseline CSV Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(host-conformance): delete a named section in the C3 broken-link case The case removed the first .md readdirSync returned under gstack-qa/sections. qa-patterns.md and system-functional.md are referenced only in table form, which setup --status does not count as section links, so on an ext4 directory order that listed one of them first the deleted file broke nothing and --status exited 0: deterministic red on remote-gate VMs, green on Actions. Delete scope.md, which every host's rendered SKILL.md reads. Closes #3479 Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * v1.91.252.0 stamp Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
fa3a2400b5 |
v1.91.251.0 feat(design-lint): bundled free design lint (bin/gstack-design-lint + lib/design-lint/), hallmark sloplint port (#3459)
* feat(design-lint): core of the bundled free design lint (parsers, colour, tokens, reporter, waivers, CLI)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(design-lint): CHANGELOG entry, NOTICE and MIT-hallmark licence, module-size ratchet entries
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(design-lint): port the colour and type rule families from sloplint
rules/color.ts: gates 2a 2b 7a 7b 22 23 29 48 65 74 (check2, check7, check22,
check23, check29Glow, check48, check65, check65Tailwind). rules/type.ts: gates
1 25 37 38i 38ii 38iii 55a 55b 64 67 (check1, check25, check37, check38a,
check38c, check55, check64, check67, check67Html). Thresholds and heuristics
are hallmark's; evidence and fixes are rewritten in gstack's voice; the stamp,
genre and posture guards are gone, so every check runs in its strict form.
The clean fixture carried two real tells hallmark's own sloplint also flags:
an oklch literal on .button:hover (48) and the cream paper + Fraunces + clay
accent look (65). The hover colour is now a token and the display face is
Literata.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(design-lint): port the Tailwind reader and component rules
Replaces the tailwind.ts stub with sloplint's utility reader (twParse,
twInfo, twGroup, variants, stops, sizes, tracking, families, shared
project tokens) and the tells it feeds, and fills rules/component.ts
with checkTailwind and checkComponentText: layout-transition,
bounce-easing, purple-blue-gradient, gradient-text, glow-wash,
literal-outside-tokens, hover-tells, wide-tracking, kicker-above-heading,
monospace-costume, framework-palette, vh-height, template-cards,
template-punctuation and emoji-decoration over class strings in HTML,
JSX, Vue, Svelte and Astro files and cn()/clsx()/cva() calls.
test/design-lint-tailwind.test.ts holds a negative control and a planted
tell per rule plus the tailwind-fail, tailwind-pass and clean fixtures.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(design-lint): mark line-length, cream-palette and the caps leading rules page-only
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(design-lint): port the structure and motion rule families from sloplint
Structure: template-cards, nested-cards, vh-height, raw-spacing, off-scale-spacing, overflow-x-unclipped (static half), bare-fr-track, display-head-unwrapped, radio-tab-jump, double-sticky, screen-word-budget (static half), and a conservative static half of wide-container. Motion: layout-transition, spacing-transition, hover-tells, bounce-easing, focus-ring-fade, tooltip-focus-delay, autorotate-no-pause, missing-focus-visible, missing-states, missing-reduced-motion, autoplay-unmuted, lazy-lcp, video-without-poster, input-state-shift, control-height (static half), content-hidden-at-rest. Every rule has a planted positive and a negative control; the clean fixture lede drops to eleven words so the hero-paragraph budget holds.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(design-lint): the Tailwind gradient half of 2a/2b lives in the component family only
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore(design-lint): tidy the colour test imports; control-height page-only; lazy-lcp title
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore(design-lint): drop unused colour test imports
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(design-lint): port the chrome, assets and finish rule families from sloplint
Chrome (gates 19 42 46a 47 54 63 68 69 70 85): gate 19 split by tell onto
aphoristic-cadence, generic-hero-copy, generic-cta-copy, em-dash-overuse and
template-footer-line in rules/chrome-copy.ts (with the two-filled-buttons half
of F4 and the shared prose mask); the eyebrow in rules/chrome-eyebrow.ts; the
nav and footer shapes, invented proof, drawn chrome, placeholder services,
template punctuation, wireframe slots, repeated facts, the fake send and a
static version of the email-band close in rules/chrome.ts.
Assets (gates 30 33 40 41 49 76): emoji icons, mixed icon libraries, unlabelled
svg/canvas, contrast pairs and surface inks (suspected at ask in the static
tier), wrapping labels split into button-label-wraps and link-wraps, broken
images and stock hotlinks.
Finish (F1-F9 F15 F16 F21-F24): all polish except fake-avatar.
Tests cover every id with a negative control and a planted positive; the clean
fixture gains scrollbar-color so its committed palette themes every browser
surface.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(design-lint): chrome, assets and finish families merged; maskedProse moves to html.ts; isTokenRule takes a Pick; ratchet watches every lint module
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(design-lint): the eyebrow-pass and tailwind-pass fixtures carry a skip link, main id and aria-current so the copy tier passes them too; waiver fixture gets a meta description
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(design-lint): render tier on gstack's own browser (sloplint-render port)
Ports hallmark's sloplint-render.mjs onto lib/aside-render: one tab per
page, the in-page probes installed once and run at each viewport, a second
pass with full-page screenshots only when a contrast claim needs the painted
pixels (a small PNG reader replaces canvas sampling). Gates 23, 25, 26a, 34,
40, 41, 44a-d, 49a/b, 58, 71, 72, 73, 75, 77-83, F17-F20, plus the page that
did not render. The stamp's posture, hero-shape, photo-shape and genre
guards are gone: the strict form applies. Focus rings are read by focusing
each control in turn (programmatic focus matches :focus-visible on the
daemon with no prior pointer input; a stylesheet scan is the fallback).
lib/aside-render: an eval step takes width/height like a screenshot step
(device metrics on Aside, viewport on browse, cleared after), and spec.file
may be an http(s) URL, opened as it is with nothing served.
The clean fixture gained border-box on its hero, a centred, taller hero
visual, a wrapping actions row, a statement-sized close head and a shorter
story paragraph: the browser showed the action below the 1280x800 fold, a
dead band under the hero, a 600px image spilling past a phone screen and a
thin close section.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(design-lint): render tier merged; four probe modules join the ratchet; the clean hero sits at a fixed measure so text and visual stand together; CHANGELOG names the aside-render eval viewport
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(design-lint): register the lint fixtures as free fixtures and the hallmark licence texts as free-only PR files, so the PR paid lane stays narrow and test/free-fixtures.test.ts passes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(design-lint): section-gap measured in the render tier (gate 59, with the six-to-nine section count) and the hero action count; a free test over the recorded review slop page; usage, render glue, file walk, multi-page ownership and copy-tier tests; NOTICE and licences leave FREE_ONLY_PR_FILES so the paid-free boundary test stands
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: mark hallmark PAGE_ONLY gates and craft page checks pageOnly so --scope component drops them
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: ship review fixes
Waivers reach render findings; a blocking rule the lint only suspected is
waivable like any ask, a measured or absent Floor stays refused. A stylesheet
a page links from another directory belongs to that page and is not linted
again on its own; a stylesheet linted alone keeps its waivers. Root-relative
hrefs resolve against the lint root. Stylesheets are read and parsed once per
run. A rule family that throws reports internal-error at ask instead of a
silent pass; aria-labelledby and probe tag names are escaped before they
reach a RegExp; a probe result naming an unknown rule is a render finding,
not a crash; fix strings are one line. overused-font follows gstack's
catalog of display faces; one MONO_FACE list for every monospace check.
parseCss caps nesting depth; medianRgb uses histograms; glHide batches its
layout reads. Dead exports removed (isPage, openTags, over, ComponentTag,
PixelRect, the ids re-exports).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: name the tracked-caps thresholds once, string-aware brace scan, drop an unused parameter, clean up test tmpdirs
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: second review cycle
Waivers settle once per page after both tiers, so a blocking rule only the
render tier suspects is waivable and one it measures is refused; a claim in a
stylesheet answers for that stylesheet on every page that links it (no
shared-word check), so a sheet shared by two pages is no longer waived on one
and refused on the other. Every printed field is one line with control
characters stripped; the waiver regex is linear and ends at a carriage
return; a root-relative href cannot climb out of the lint root. The ancestor
map closes optional end tags implicitly and pops to the matching open tag, so
unclosed <li> no longer makes it quadratic. The static tier reports outline:
none with no ring anywhere as missing-focus-visible at its line;
literal-outside-tokens needs a --color-* or --font-* token to exist; the
banned gradient includes indigo-to-violet; a new banned-font rule reads
gstack's BANNED_FONTS; MONO_FACE matches whole words; bold keywords and
tokens count as weight 700 for the contrast threshold. stylesFor reads only
the entries that can match; glOcclusion memoises the pinned walk; the
confirm screenshot is taken at 1x; a page that throws in the render tier is a
render finding and the CLI exits 3 on an internal error. Docs name the token
conventions and what the lint does not cover.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: pair open and close tags once per document, scan markup in linear time, keep commented-out style and script dead
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: third review cycle fixes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: third review cycle tests; render keeps the measured horizontal-scroll when merging widths
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: document the third-cycle limits and waiver scope
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: fourth review cycle fixes
Commented-out markup is dead for every rule (Doc.src is the comment-blanked text; craft copy, the module-script check and the border+shadow scan read it). Headings, buttons, links, labels, selects, forms and an open <p> close the way the browser closes them, a tree nests at most 512 deep, and the heading, footer-column, sign-up-button and span readers walk the shared pairing instead of lazy regexes, with each element's text computed once (textOf). Tailwind frames and wireframe slots answer from treeOf. resolveVars stops on a cycle and caps its size; every parseCss at-rule branch honours the depth guard and an inline <style> that fails to parse is skipped with a warning. cwd and lint roots are read through their real paths, a skipped source file is one internal-error finding, relative refs stay inside the project, a linked stylesheet over 2 MB is skipped. overused-font and banned-font match a catalog stem to a family name's first words; width: min()/clamp() caps a container; a box-shadow focus ring beside a border-colour change is not input-state-shift; Meet and triad headings below the hero are suspected; the stylesheet-waiver key goes through oneLine; pxOf reads leading-dot lengths; check67 precomputes selector bases; the render tier reports a wrong-shaped answer per probe and keeps every measured finding, flags a bad grade as tampering, and never repeats the kept width when merging horizontal-scroll.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: fourth review cycle tests and docs
test/design-lint-fourth-cycle.test.ts pins commented-out markup dead for every rule, unclosed <li> Tailwind frames and wireframe slots, linear-time unclosed runs and component scripts, cyclic var() and nested @media, leading-dot lengths, a symlinked lint root, oversize files reported, a whitespace-named stylesheet's waiver, the overused-font stems, width: min() caps, box-shadow rings, Meet headings below the hero, wrong-shaped render answers and the never-waivable refusals by class; the settle golden no longer repeats the kept width and expects the bad grade as tampering. docs/design-lint.md describes the caps, implicit closes, skipped-file findings and the matching rules.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: fourth-cycle simplifications and the pixel pass pinned without a browser
heroClasses reads the hero through heroIndexOf, check64 uses twMonoIsMaterial, check67Html imports capsRatio from chrome-eyebrow, sideStripes loses its bare block; a settle test drives confirmPixels with the swatch fixture (a claim dropped by the pixels behind it, one rewritten, a weak ring confirmed).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: heroIndexOf carries its own doc comment
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: fifth review cycle fixes
The placeholder emoji scan reads the comment-blanked text, so markup inside <!-- --> is dead for every rule. A digit run, a long mono word and a run of scheme prefixes cost their length (FACT and UNSPLASH_URL only start at a token, twDataText bounds its text); a 2 MB sheet of 699k rules no longer blows the stack (rules are appended in loops); JsxScanner spends one failure budget across jsScan and el; the Tailwind had() lookup is a Set; accentedHeads indexes rules by class once; contexts drop their caches once their families have run; the parsed-token cache is bounded. treeOf gives a close tag its parent so a fact after an inline close is counted in its section. Waivers are keyed per rule for a page claim and per rule@sheet for a stylesheet claim, so two linked sheets each answer for their own findings. The render tier validates every page-supplied field (at.cls, ring colour and ratio, probe fg and threshold, PAGE_ERRORS entries, a malformed entry naming the render rule) and keeps its measured findings; lineOf answers from one line index. Rule judgement: a textarea's min-height is not control-height, attribute-selected inputs are read for input-state-shift, a glyph-only <i> is not an italic word, a bounce keyframe by name is bounce-easing, single-quoted inline styles are read, a project root is a package.json or .git. Housekeeping: Probes typed from PROBE_FNS, EYEBROW_* shared from chrome-eyebrow, WaiverClaim.raw and dead imports removed, evidence wording for tracked-only controls and black glass, emoji icon tiles capped like every other emoji path, unreadable files get their own fix text.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: fifth review cycle tests and docs
test/design-lint-fifth-cycle.test.ts (21 tests) pins the comment-dead placeholder, the linear-time digit run, 699k-rule sheet, unclosed JSX and tracked-label pages, per-sheet waivers and the remaining state-matrix cells, every wrong-shaped render field, and the rule judgements; the fourth-cycle shell test asserts the observable effect, the RSS assertion is structural, time bounds are widened for shared CI shards, the stale empty block is gone, and the FREE_FIXTURES inventory names both cycle files. docs/design-lint.md states the project-root bound on relative hrefs and the three narrow readings (whole-page focus ring, unconditional 4px scale, scroll-container-blind double-sticky).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: sixth review cycle fixes
line-length computes its floor only for a measure between 28 and 45ch and
answers shortProse once per class; wide-tracking resolves inherited case
through a prefix index instead of a scan of every rule; the JSX scanner
fails every ancestor of an element that ran to the end of the file at once;
the hairline-under-shadow pair reads class tokens instead of a two-sided
regex. tooltip-focus-delay names the sheet that holds the :focus delay;
the placeholder emoji scan reads the comment-blanked body for every kind;
fake-send finds its line in a component's script text. A stylesheet href is
bounded by its real path too. The LINT line's separator is kept out of
page-supplied text. Waivers: a component claim answers for its own file,
weighed against its own text; the Waiver shape is a reason string; refusals
go through Reporter. Render: a later fail replaces a warn with the same
evidence, a non-string fix is dropped, the timeout is a constant. Rules:
a meta label in mono is a costume, a leading-dot length reads as a fraction,
a percentage leading collides like a unitless one, an italic word after an
icon is still read, an italic rule on the word is not a display system, en
dashes between digits are ranges, and the catalog's two hero lines are
generic-hero-copy. The Tailwind parse cache and its eviction are gone.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: sixth review cycle tests and docs
test/design-lint-sixth-cycle.test.ts (18 tests; 13 red at
|
||
|
|
39b06e22af |
v1.91.250.0 fix(tests): remove three free-tier fixture races (GSTA-107 daily flaky pass) (#3474)
* fix(tests): remove three free-tier fixture races: atomic result files in dotenv-isolation and claude-code-runner, per-fixture Git repo in cso-git-hardening (GSTA-107) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes The new dotenv-isolation test spawns Bun with emptyBunConfig() instead of a literal --config=/dev/null, which the Windows lane cannot open; the runner's timeout case asserts the descendant published a pid before asking whether it is running, so a missed readiness window names itself. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(tests): cso-git-hardening fixtures turn git auto-maintenance off seedRepo commits with fixtureGit's replacement env, which never sees the shard backstop, so each commit started a detached git maintenance run that creates and deletes .git/objects/maintenance.lock under the tests' own .git reads and the afterEach rmSync (docs/TESTING_INTERNALS.md, Free-suite flake rules). Found by /ship's documentation audit; git 2.55.0 trace2 shows the maintenance spawn with the keys unset and none with them set. 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> |
||
|
|
3ab7b149c9 |
v1.91.249.0 fix(evals): repair five paid-case flakes at their causes (GSTA-107 daily flaky pass) (#3472)
* fix(evals): repair five paid-case flakes at their causes: docsync --help slip, state-dir artifacts, preamble asset, defer paraphrase, probe --help (GSTA-107)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
offersDefer: the wait/hold-off-for-now paraphrase must open the option or a
sentence and end it, so a drive option's "I wait for now while you sign in"
or a manual option's "wait for now and do it yourself" no longer reads as the
defer option (red-team finding on #3472). Negative controls added.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (round 2)
- offersDefer: the wait/hold-off-for-now paraphrase never counts inside a
browser drive option, accepts an em dash without spaces and a curly
apostrophe in let's; negative and positive controls added (adversarial
review on #3472).
- docsync-authority: the interface assertion expects the rendered
`<home>/remote.git` form so it holds on Windows; the captured Linux
replay is POSIX-only like the late-result replay (outside voice P1).
- touchfiles: register the two new docsync captures with the paid cases
they replay (ship-docsync-store, ship-docsync-completion), which
test/free-fixtures.test.ts requires (remote gate red at
|
||
|
|
5755601dac |
v1.91.248.0 fix(browse): direct mode launches Chromium with --proxy-server=direct:// so proxy env vars never win silently (#3440 item 8) (#3448)
* fix(browse): direct mode launches Chromium with --proxy-server=direct:// so proxy env vars never win silently (#3440 item 8) BROWSE_PROXY_URL=direct only stopped gstack from configuring a proxy; the daemon inherits the environment and the launch passed no proxy switch, so Chromium read HTTPS_PROXY/HTTP_PROXY/ALL_PROXY itself and every goto still went through that proxy while browse reported a direct connection. Every launch path now adds --proxy-server=direct:// when no proxy is configured (chrome-headless-shell ignores --no-proxy-server), the daemon logs the effective proxy mode on launch, and BROWSER.md's proxy section says what Chromium actually gets. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Name the direct-connection switch once (DIRECT_PROXY_ARG in proxy-config.ts) so the launch argument and the daemon log line cannot drift apart. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(browse): force direct:// only where Chromium would pick its own proxy; review fixes Red team (ship Step 9.2): the first cut passed --proxy-server=direct:// on every platform, but Chromium reads HTTPS_PROXY/HTTP_PROXY/ALL_PROXY itself only on Linux. On macOS and Windows it follows the system proxy settings (PAC/WPAD), which GStack Browser.app users behind a corporate proxy depend on, and BROWSE_PROXY_URL cannot name a PAC. forcesDirect(env, platform) now gates the switch: Linux always, elsewhere only with BROWSE_PROXY_URL=direct. The daemon log says what is really ignored per platform, or that the system settings apply. Review pass 2: the CLI e2e asserts on the daemon-log slice its own invocation wrote (the log is append-mode and shared across cases); connectProxy moves to browse/test/helpers/connect-proxy.ts for both e2e files; the CHANGELOG Tests bullets cover the generated cases. Adds the coverage-audit cases (unparseable HTTPS_PROXY; extension, headed and handoff paths under Xvfb). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(browse): assert the direct switch on the launched Chromium command line per platform (#3440 item 8) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Ship review pass 3 (red team, GStack Minder's decision B, 2026-10-26): on macOS and Windows an explicit BROWSE_PROXY_URL=direct is the only thing that makes the daemon bypass the system proxy settings, so explicitDirect() puts it in the daemon config hash, server.ts records it as proxyDirect in the state file, and buildRestartEnv re-emits it on a crash auto-restart. A reused daemon started on the system proxy is now refused (the refusal names BROWSE_PROXY_URL and offers browse stop or unsetting it) instead of silently keeping the system proxy while the CLI reports direct. Linux hashes as before. BROWSER.md says the daemon log records the mode each time the daemon starts, not on every launch. The Linux desktop (GNOME/KDE) system-proxy question is filed as #3450. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(browse): daemon-state and refusal e2e for the explicit direct opt-out; headed env and BROWSER.md contract checks (#3440 item 8) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Ship rerun review pass: proxy-direct-launch-args.test.ts joins the macOS named-regressions job so its omission arm (no switch without the opt-out) runs in CI; serverProxyEnv takes the platform so the state-file predicate is pinned per platform instead of mirroring process.platform; buildHeadedServerEnv's parameter type requires explicitDirect so a narrowed caller cannot drop the opt-out silently; BROWSER.md's precedence item 6 and the reuse sentence say what each platform does (a connect daemon gets the generic flags refusal); CHANGELOG notes the one-time refusal against a pre-release daemon. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Ship adversarial pass: a crash restart re-emits BROWSE_PROXY_URL=direct from the daemon state only when the invocation has no flags, so the env it hands the new daemon never contradicts the config hash it also hands over; an explicit-direct session is refused against a daemon with no recorded config hash, like --proxy and --headed already were; the unparseable-variable hint says that the opt-out also bypasses the system proxy settings on macOS and Windows; BROWSER.md notes that a managed Chromium proxy policy still overrides the switch; CHANGELOG names both files that joined the macOS named-regressions job. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(browse): read scheme-less proxy variables as http:// so the explicit direct launch keeps those sessions proxied (#3440 item 8) A standard proxy variable without a scheme (curl-style host:port or user:pass@host:port) was rejected by browse's parser with a "connects directly" warning while Chromium on Linux read the variable itself, so the session was proxied anyway. With the launch now explicit (--proxy-server=direct://) that environment went genuinely direct. resolveProxy now reads such values as http://, the way curl and Chromium's own environment reader take them; --proxy and BROWSE_PROXY_URL still require the scheme, and a value that does not parse even as http:// still warns and connects directly. Also drops buildRestartEnv's persisted-state re-emit branch, which production never reached (_globalFlags is set before any restart), names the four BrowserManager launch sites in the CHANGELOG and excludes the cookie-import worker, and carries the docs audit's one-line BROWSER.md project-tree note. Decision: GStack Minder (2026-10-26), option A. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes The lenient scheme-less proxy read is now gated on the plain [user:pass@]host[:port] shape (SCHEMELESS_PROXY_RE, trimmed): a scheme'd value with surrounding whitespace, a one-slash typo and a bare number keep the behaviour they had, and a credential that would spill past the userinfo (?, #, /) is not rewritten, so nothing can land outside the redacted part. Credentials that are not valid percent-encoding are a ProxyConfigError for every source instead of a URIError crash. buildRestartEnv's docblock, BROWSER.md and the CHANGELOG describe the parse (port 80 default, macOS/Windows now treat such a value as a configured proxy). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes A backslash is excluded from the scheme-less proxy shape and parseProxyConfig refuses any proxy URL with a path, query or fragment, for every source: WHATWG parsing ends an http authority at a backslash, so a DOMAIN\user login or a / in a password landed in the path, which the redactor does not mask, and was printed in the clear on the start line, in the daemon log and in the state file. Such values now warn (standard variables) or error (--proxy, BROWSE_PROXY_URL) without echoing the credential. Docs updated. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(browse): keep a slash-less scheme spelling, refuse a bare ? or #, and tighten the proxy docs A standard proxy variable whose userinfo opens with a known scheme (https:bob:pw@host:3128, which the URL parser reads as https://) is no longer taken as scheme-less credentials, so the protocol it names is kept. parseProxyConfig refuses a literal ? or # anywhere in the value, not only a non-empty query or fragment. The unparseable-variable test now puts the credential in every looped value, so its no-echo assertion is real; new cases pin the slash-less scheme spelling, the bare ?/#, an env-sourced trailing slash, and that mixed credential sources stay a hard error for the scheme-less spelling as for the http:// one (the cred-mixing refusal predates this branch and its test on main pins it, so it is documented rather than softened). CHANGELOG and BROWSER.md: single backslashes inside code spans, "a path other than a bare /", the socks5 bridge log lines in the effective-mode list, and the character list applies anywhere in the value. Decision: GStack Minder (2026-10-26), option B. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(browse): keep a basic-auth URL out of the scheme-guard comment so the pregate secret scan stays clean Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(browse): pin the mismatch remedy per platform so the Windows subset does not take process.platform proxyMismatchLines defaulted to process.platform in the env-proxy-meets-direct-daemon case, so on the windows-free-tests lane the remedy read 'or unset HTTPS_PROXY' and the assertion failed. The case now passes 'linux' explicitly and pins the darwin/win32 remedy beside it. Test only; source unchanged since |
||
|
|
b9222a57b7 |
v1.91.247.0 fix(plan-eng-review): define the three references its judged text left dangling (GSTA-91) (#3421)
* fix(plan-eng-review): define the three references its judged text left dangling (GSTA-91) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore: ship coverage test, unattended doc and CHANGELOG for review fixes test/plan-reality.test.ts asserts each phase's gstack-plan-reality check line names PLAN_REALITY (Step 7 gap). docs/unattended.md names the unattended-session block the skill prose now cites (Step 14.5 audit). CHANGELOG [Unreleased] covers the hook pointer fix and the new tests. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(changelog): drop the hook directive claim (GSTA-91) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: keep destructive options pending in the unattended AUQ fallback (GSTA-91) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: trim the unattended pointers so every size pin goes down (GSTA-91) The failure fallback's unattended branch now says a consent, destructive or irreversible option, unrecommended question or approval gate stays pending, keeping the carve-out. Item 1 drops its dangling '(per its printed unattended-session block)' pointer. CQ3 now asserts no section or block pointer remains in item 1; CQ4 is retitled to the block and hook; the plan-reality pointer loop drops devex, which renders no reality rows. Every host and the /ship goldens are regenerated and all 89 pins go down versus |
||
|
|
ab9a854be2 |
v1.91.246.0 docs(readme): cut the README to the first ten minutes; move everything else to docs/ pages verbatim (GSTA-99) (#3428)
* docs(readme): cut the README to the first ten minutes; move everything else to docs/ pages verbatim (GSTA-99) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Restore the /setup-gbrain code block the README split left open: README.md kept the ```bash opener and docs/gbrain-quick-tour.md got only the closing fence, so both pages rendered their body as one code block. Drop the self-referential 'Full reference' link in docs/domain-skills.md and make the troubleshooting quick-answer link an in-page anchor. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: describe the proactive core-set default in why-gstack The moved 'Proactive skill suggestions' paragraph now documents the four-skill core set, gstack-config set proactive core|all|off and the docs/proactive.md page that #3432 (gsta-99-proactive-core) adds; the CHANGELOG names it as the one non-verbatim paragraph of the move. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (round 2) Promote docs/uninstall.md's moved sections from ### to ## so the page outline matches the other pages the README split created; no inbound link targets those anchors. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: documentation audit fixes The README Docs table no longer claims docs/standalone-binaries.md covers every gstack-* CLI (it documents the standalone ones), and docs/ADDING_A_HOST.md step 6 points at the README host-matrix row and docs/hosts.md, where the per-host notes now live. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: disclose the update check fully and list every setup hook The README privacy summary now names both GitHub requests the update check makes and the version/OS report it adds with telemetry on, as the full text it replaced did. docs/install.md's hooks section lists the team-mode SessionStart hook and the AskUserQuestion PreToolUse/PostToolUse hooks beside the timeline Stop hook. * docs: name the update check's conditional compare-API request bin/gstack-update-check also GETs api.github.com's compare endpoint when the remote VERSION equals the local one but main has moved; the README privacy summary and docs/privacy.md now list it beside the ls-remote and VERSION fetch (documentation audit). * fix: pre-landing review fixes (merge resolution) docs/install.md:21 carried main's stable-channel sentence twice after the merge, the second copy with its backticked spans stripped; the paragraph again matches README.md:41 verbatim with the relative link. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: say outside reviews are on by default in the README privacy summary The one-paragraph summary dropped the default-on disclosure the full text kept; mirror docs/privacy.md's parenthetical so the top-level page says which path sends code off-machine without an opt-in. * v1.91.246.0 stamp Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
6154b6ea1d |
v1.91.245.0 fix(ship-queue): ready counts the latest run per check name and hints the dispatch route on a conflicting PR (#3460)
* fix(version-gate): a release output regenerated at the base VERSION is not a stamp Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(version-gate): run the head release tool with a bare env, drop outputs it must rewrite, prune the staging worktree Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(version-gate): regenerate at the merge base VERSION, read tool output from a file, never follow a VERSION symlink Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(version-gate): kill a release tool that ignores TERM at the limit, read a bounded log Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(ship-queue): ready counts the latest run per check name and hints the dispatch route on a conflicting PR; ship-policy follows #3439 Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(ship-queue): key the latest run on app and name, keep undated runs standalone, quote the hint branch; restore the full CHANGELOG Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(ship-queue): refuse a dash-led branch in the hint, soften the green hint, restore the CHANGELOG tests bullet Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(ship-policy): name the refusal this branch prints for --screen on a conflicting PR 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> |
||
|
|
d62eb914dc |
fix(pregate): waive version-stamp-only manifests from the lanes check (GBRA-95) (#3461)
gbrain's release:restamp rewrites its plugin manifests and VERSION; its base's .gstack/pregate.json declares no lane for them, and pregate reads policy from the base, so every restamp PR failed lanes with PREGATE_NO_LANE and could not fix itself (gbrain PRs 7625 and 7606). lib/pregate/stamp-only.ts defines version-stamp-only per file kind: a JSON document of the same shape whose every changed leaf is a bare version under a key named for a version; plist <string> versions under a ...Version... key; a VERSION file that is one bare version on both sides. lane-selection applies it only after the import graph, the declarations, the regen registry and both empty lanes found nothing; lanes prints the waived files on their own line and --explain the per-file verdict. Anything else (a changed description, a new key, a dependency pin, an added or deleted manifest) keeps its PREGATE_NO_LANE. Tests: pure rows for every rule, and bin fixtures for a stamp-only PR (passes), a manifest with a changed description (refused), a mixed diff (stamped files waived, the orphan source file still refused, a mapped file still runs its test) and an added/deleted manifest. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
8018ba52fe |
v1.91.243.0 fix(capy): source the launch environment from a 0600 file; no skill fence may print the environment (GSTA-104) (#3449)
* fix(capy): the launch environment is sourced from a 0600 file and no skill fence may print the environment (GSTA-104) During GSTA-96's unattended /ship on #3425, the Step 14.5 docs-audit child re-typed the GSTACK_LAUNCH assignments as `export $(...)`; the substitution came back empty, the bare `export` printed the whole environment, and three API key values landed in its tool output. - bin/gstack-capy-install writes the assignments to <verdict>.env (mode 0600, idempotent PATH prepend) and prints GSTACK_LAUNCH_FILE: <path>. - ship Step 14.5 prompt, document-release's spawned note, autoplan/DRIVER.md and gstack-skill-start's capy-asks block say: source the file; never export $(...), env, printenv or bare set in a tool fence. - test/launch-env-echo-ratchet.test.ts greps every generated SKILL.md, sections, DRIVER.md, the Capy skill and bin/ shell helpers, with negative controls under test/fixtures/launch-env-echo/. - lib/redact-engine.ts: env.value (HIGH) finds the value of any *_KEY, *_TOKEN, *_SECRET, *_PASSWORD variable in the writer's environment, so a leaked value cannot reach a PR body, receipt, report or Drive file. - scripts/lib/shard-engine.ts scrubs the Capy launch markers from shard environments (GSTA-99's finding). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(ci): DRIVER.md back to 159 lines; shard-engine recorded non-behavioral at HARNESS_VERSION 6; verdict-count test lists .json only Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: register test/fixtures/launch-env-echo as a free fixture Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(redact): env-value fixtures stay out of pregate's env.kv net A credential-named assignment with an entropic literal on one line is what the repo's own pregate secrets scan refuses in added lines, so the fixture values move into plainly named constants and the scanned text is built from them. The scan under test still sees the same values through processEnv. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(windows): the late-completion remote-caller case gives its second attempt a 2s budget (run 40263984171) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(redact): env.value trims the value, keeps a prefix value's longer match, hides the preview and skips PUBLIC names /ship Step 9.4 review fixes for the GSTA-104 env-value scan: - a value whose environment copy ends in a newline (a key read from a file) is searched for trimmed, so its leaked form still matches (the length check already trimmed; the search used the raw value); - when one credential value is a prefix of another, the dedup key carries the span length, so the longer value is redacted whole in either order instead of leaving its tail in the text and dropping its finding; - the env.value preview is a fixed mask instead of the first characters of a live credential; - framework-public names (NEXT_PUBLIC_*_KEY, *_PUBLIC_KEY) are not scanned, since those values are committed on purpose; - the header and the processEnv docstring state the name rule (KEY, TOKEN, SECRET, PASSWORD, PASSWD, any case) and that process.env is the engine's one ambient input. Step 7 coverage extensions and a regression test for each fix in test/redact-env-value.test.ts; docs/capy-install.md names the full rule. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * refactor(capy-install): write_launch_file quotes through shq; header names the launch file Review finding: _sq duplicated shq() from the same file. The launch file's assignments now go through shq, and the header comment describes the GSTACK_LAUNCH_PATH and GSTACK_LAUNCH_FILE lines beside GSTACK_LAUNCH. Step 7 coverage: the verdict test sources the launch file and runs --check; the single-quote path test sources the file too; a new case makes the launch-file directory unwritable and checks the run says so, prints no GSTACK_LAUNCH_FILE line, leaves no temp file and keeps its exit code and trailer (linux, non-root). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(preload): strip the Capy launch markers so a direct bun test matches the shard sandbox Red Team finding: the launch-marker scrub lived only in createShardSandbox, so a direct `bun test <file>` run under an unattended Capy session inherited GSTACK_SESSION_KIND, GSTACK_CAPY, GSTACK_EPHEMERAL and GSTACK_INSTALL_VERDICT (GSTA-99's symptom). The preload now deletes the same four names, and test/shard-engine.test.ts imports CAPY_LAUNCH_MARKERS instead of re-typing them. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(ratchet): the launch-env echo scan catches backtick and $VAR exports, typeset -p, env flags and a set in any segment Review findings 11 and 12: export-subst also trips on `export \`...\`` and an unquoted `export $VAR` (both splat a NAME=value file; `export "$name"` is one word and stays allowed); the export rule adds `typeset -p`; env trips with only flags (`env -0`) and as `/usr/bin/env`; set is judged per segment and with redirections, allowed only when piped straight into an anchored grep filter. Quoted strings are blanked offset-preserving so a `#` inside quotes no longer hides the rest of the line. The negative control covers each new form on both sides. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(ship): Step 14.5 names where the launch-file placeholder comes from The /document-release prompt line read `. <file>` with no word on what fills it. It now says the placeholder is the GSTACK_LAUNCH_FILE: path the parent's own install check printed. Worded to stay under the ship skill's pinned parity size (313,279 of 313,281 union bytes). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(redact): env.value admits *_PASS, *_PAT, *_APIKEY and *_PWD, and skips path values and gstack's lock token /ship Step 11 adversarial findings. The name rule also covers DB_PASS, GITHUB_PAT, *_APIKEY and *_PWD (the shell's own PWD and OLDPWD stay out). A credential-named variable whose value is a filesystem path (SSL_KEY=/etc/ssl/ private/x.key) names where the credential lives, so the path is no finding, and GSTACK_BRAIN_LOCK_TOKEN (pid-random-epoch, written to the lock owner file) is not a secret. Without these, an ordinary mention of that path or token in a PR body, receipt or CSO report was a HIGH fail-closed blocker. The adversarial pass also recommended an entropy floor so dev defaults such as DB_PASSWORD=postgres stop matching prose; declined here on purpose, because the scan's promise is to catch a leaked value whatever its shape, and a weak real password is still a credential. Recorded as an open decision in the ship report. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(capy-install): a failed launch-file write removes only its own temp file The failure path ran rm -f "$LAUNCH_FILE".tmp.*, which also deleted the temp file a concurrent installer run (two threads on one machine, same verdict path) was about to mv, so that run lost its launch file too. write_launch_file now cleans up its own $tmp and returns 1; the caller only reports. The file's comment no longer embeds the state-root path (a newline in GSTACK_STATE_ROOT could have ended the comment). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: the launch markers come from one list, and the echo ratchet scans setup and scripts/*.sh The preload imports CAPY_LAUNCH_MARKERS instead of re-typing the four names, and the ratchet asserts the installer exports every name on that list, so a fifth marker cannot be added to one place only. The shell scan also covers ./setup and the scripts/*.sh install scripts callers run first. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(changelog): the Unreleased entry states the review-fixed env.value rules, the ratchet forms and the one test-budget change Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(redact): the env.value path exemption asks whether the file exists instead of matching a shape Second review cycle: a path-shaped rule also matched a base64 secret that starts with "/" and holds another "/" (about 1 in 150 AWS-shaped keys), which then went unscanned. The exemption now fires only when the value names a file that exists on the scanning machine (SSL_KEY=/etc/ssl/private/x.key). The module header names that stat as the engine's one filesystem read. NON_SECRET_ENV_NAMES is exported so the test can prove bin/gstack-brain-lock.sh still exports every name in it; the PWD/OLDPWD fixtures hold plain words so only the name rule keeps them out. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: the installer's own-temp-file cleanup is exercised, and the ratchet coverage test names setup and scripts An mv shim first on PATH refuses only the launch-file target, so the temp file exists when the move fails: the run removes that file alone (a sibling from a concurrent run survives), says so, prints no GSTACK_LAUNCH_FILE line and keeps the earlier file, exit code and trailer. The ratchet coverage test asserts setup, scripts/build.sh and scripts/sandbox-doctor.sh are scanned. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(redact): env.value has no path exemption and matches the value in normalized form Second adversarial pass: the existence check let the scanned agent exempt any "/"- or "~/"-prefixed secret by creating a path of that name, a silent bypass of the one guard this branch adds, so the exemption is gone; a path-valued SSL_KEY that must appear in a text goes through the allowlist. The engine is back to no I/O. The value is now normalized the way the text is before indexOf, so a credential NFKC rewrites (fullwidth digits) still finds its leaked ASCII form. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(capy-install): the launch file is written only on a passing run; the ratchet checks the marker list both ways A gstack: fail run no longer writes or announces a sourceable file whose PATH prepend points at an unverified Bun. The ratchet also asserts every variable the launch file exports is a CAPY_LAUNCH_MARKERS entry or GSTACK_STATE_ROOT, so a sixth export cannot reach fixture children unstripped. The Capy skill's prose no longer offers re-typing the assignments as an alternative to sourcing. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(capy-install): the launch file is part of the ok verdict Third adversarial pass: a passing run whose launch file could not be written still said gstack: ok with exit 0 and printed only the GSTACK_LAUNCH line, leaving a shell-evaluating caller with the re-typing path the branch exists to remove. The file is now written before the verdict is recorded; a write failure on a passing run turns the run into "gstack: fail launch-file — could not write the launch file <path>; fix: … (LAUNCH_FILE_UNWRITABLE)" with exit 1 and an ok:false verdict, and every failing run removes the launch file an earlier passing run left beside the verdict. The two failure tests assert the new contract, the doctor-FAIL tests assert no launch file is announced or left, and the docs, Capy skill and CHANGELOG say the same. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(redact): the env.value allowlist and placeholder rules see the normalized value too An allowlisted value in NFC did not suppress a match on its NFKC-composed form, and a value that is a placeholder only after normalization was still searched for. Fixture nits from the third review cycle: fixed directory string instead of process.cwd(), the fullwidth assertion guards its own vacuity, a zero-width-padded value under the floor is pinned, and the ratchet comment names the one kept export and the PATH case line. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(capy-install): LAUNCH_FILE_UNWRITABLE is a registered result code; a kept profile verdict keeps its launch file Fourth review cycle. The new trailer code now has its row in lib/result-codes-capy.ts (the owner module is at its size cap) and its docs/troubleshooting.md anchor, so the install-side code scan resolves it. A failing profile check (--for review-voice) that keeps a fuller ok verdict for this HEAD no longer deletes that verdict's launch file: the fail branch removes the file only when the run rewrites the verdict, and setup_failed removes it too. The docs say "a failing run that rewrites the verdict", and that an unwritable directory keeps both the old file and the old verdict. A new test runs a passing install, then a failing profile check, and asserts the file and the ok verdict both survive. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(redact): the normalized allowlist and placeholder rules each have an assertion that fails without them Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(capy-install): a setup failure after a passing install removes the earlier launch file Fifth review cycle: setup_failed's cleanup had no assertion. The setup failure test now installs once (launch file present), commits a new HEAD so setup runs again, fails that setup, and asserts the launch file is gone and the verdict says ok:false before the next run sets up again and ends ok. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: state-root, contributor reference and capy-install follow the launch-file contract (Step 14.5 audit) The /document-release audit (docs-3449-1792992068) corrected three authored docs: docs/state-root.md shows the GSTACK_LAUNCH_FILE line and says to apply it with ". <that file>" instead of prefixing or exporting the assignments; docs/CONTRIBUTOR_REFERENCE.md names scan()'s one ambient input instead of calling it pure; docs/capy-install.md's bun-shim bullet and exit table name the launch file and the fail launch-file trailer. 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> |
||
|
|
6c3cf1baac |
v1.91.242.0 fix(context-bill): bill installed skills whose SKILL.md is a symlink (GSTA-97) (#3423)
* fix(context-bill): follow symlinked SKILL.md files and skill dirs so a real install is billed (GSTA-97)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): walk both links to one directory so the walk never depends on readdir order
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(changelog): describe the loop guard as shipped
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): a root named '..x' no longer lets a parent link climb out
encloses() tested rel.startsWith('..'), which also matches a first
segment such as '..skills', so a link to the parent of a root under such
a name was followed out of the root. Compare the '..' segment exactly.
Adds that case plus a loop to a directory below the walk root, which only
the ancestor guard stops (found by /ship pre-landing review).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): a .md-named link counts only when its target is markdown
walkMd checked only the link's own name, so a link such as notes.md ->
a non-markdown file was walked and, under --exact, its content was sent
to count_tokens. Require the resolved target to end in .md as well.
Adds tests for --exact on the installed layout (every billed file is
measured; nothing behind gstack/ or a .md-named link to another file is
sent) and for a symlinked foreign-host file (found by /ship review).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): walk each real directory once so link fan-out cannot explode
walkMd guarded only the current path, and walked every link to the same
directory, so links that fan out into each other grew the walk
exponentially; under --exact every duplicate path was another
count_tokens POST on the user's key. Expand each real directory and
return each real file once per walk, under the first lexical path
reached with entries sorted. Refuse a walk past 200,000 entries with an
error instead of truncating. --exact sends each real file once and
prices every lexical key that resolves to it from that measurement.
Found by the /ship Step 11 adversarial reviews (Claude and GPT).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): fence walks at the billed root, measure every walked frontmatter, count outside files in the --exact notice
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): a container skill keeps files a nested skill links to
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): --exact names a missing tree before any request
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): --exact sends only files the bill prices
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): --exact refuses every missing tree before sending, and the notice counts what is sent
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): exactSendFiles does not swallow a realpath error
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): --exact walks only what the bill walks, sends nothing for a skill-less tree, and measures only priced frontmatter
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): --exact says when a tree with skills had nothing to send; doc and alias-test fixes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(context-bill): a skill-less tree prints no estimate line under --exact
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): a container skips only nested dirs whose SKILL.md is a file, as discovery does
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): skill discovery refuses a tree past the entry cap too
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): walk directories through their realpaths so a deep link chain cannot drop files
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): --exact reads only the file each walk approved
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): --exact sends only the skills root and the linked gstack checkout; anything else is named and estimated
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (context-bill run-4 cycle 1)
Checkout detection needs a gstack checkout outside the tree; identity taken during the walk and re-checked by realpath; discovery and calibration read through realpaths; refused-dir collapse is linear; all-refused wording; stale comments; tests for each.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (context-bill run-4 cycle 2)
The gstack checkout is recognised by .git, VERSION, setup and a SKILL.md named gstack, so the bin/dev-setup layout counts and other repos do not; walk contract documented on walkMdFiles; tests for the same-file parent move, a gstack-shaped folder without .git, another project repo, and dev-setup.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): a root container skips a nested skill reached through a directory link at any depth
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): --exact refuses a walked file swapped for a FIFO instead of blocking on open
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): --exact resolves a billed path one link at a time, so a shared deep chain keeps its measurements
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): --exact reuses a measurement only for the same realpath, size and mtime it measured
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(context-bill): a bill with any estimated item under --exact is labelled mixed and keeps its error band, in --json and text
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(context-bill): --exact also sends files inside gstack's render folder ($GSTACK_STATE_ROOT/render), judged by realpath
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(changelog): the repo bill keeps its skills, bytes and rounded tokens; raw token floats differ in the last digit
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(context-bill): CHANGELOG and README for the render folder, mixed labels, measurement identity, FIFO refusal and container fixes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (context-bill run-5 cycle 1)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (context-bill run-5 cycle 2)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (context-bill run-5 cycle 3)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* v1.91.242.0 stamp
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
|
||
|
|
a1487458d3 |
v1.91.241.0 fix(deps): bump dompurify, MCP SDK, zod, body-parser, fast-uri, ip-address to OSV-fixed releases (#3462) (#3463)
* fix(deps): bump dompurify, @modelcontextprotocol/sdk, zod, body-parser, fast-uri and ip-address to their OSV-fixed releases (#3462) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * build(diagram-render): empty excalidraw's public Firebase config literal in the bundle; declare BUILD_INFO.json's test lane Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(diagram-render): name the bundle, BUILD_INFO and build script by repo path so the pre-gate sees their lane Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore(pregate): drop the BUILD_INFO.json lane declaration; the drift test names the file now Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Testing specialist: the drift test asserts the bundled DOMPurify is the override and the bundle carries no Google API key; deps-smoke refuses ip-address below 10.7.4 and checks every bumped package against its OSV-fixed floor in both lockfiles. Adversarial: build.ts fails when any AIza key survives the strip. Outside voice and red team: the CHANGELOG hash and scope lines match the shipped tree. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(diagram-render): document the Firebase-literal strip and the new drift checks 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> |
||
|
|
021d817c36 |
v1.91.240.0 feat(proactive): default to the four core skills (core | all | off), with docs, prompt and tests (GSTA-99) (#3432)
* feat(proactive): default to the four core skills (core | all | off); docs, prompt and tests (GSTA-99) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(proactive): gstack-skill-start falls back to core, not true, when gstack-config is missing The PROACTIVE status line's fallback literal still said true (= all) after the default moved to core. Found by /ship's coverage audit; the regression test fails at the previous head and passes at main. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(proactive): STATUS line carries the stored value; every surface names the same core four and three values Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(proactive): off gates the office-hours handoff; the preamble and router scope the setting to unasked suggestions The office-hours next-review handoff gated on the legacy false only, so an off user was still asked to launch /plan-eng-review. The per-skill preamble now says the setting governs unasked suggestions and this skill's own steps still run (a handoff, a review gate, a dispatched /document-release is not a suggestion), at exactly the previous length, so the 89 size pins return to main's values; the router says the same in full. Found by /ship's specialist and red-team review. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(skill-start): unknown proactive values read as core; first-run tips name core skills and stay quiet under off A hand-edited config can hold any value and only set validates, so STATUS normalizes anything but core|all|off|true|false to core. The first-run and first-loop tips named /spec, /investigate and /plan-eng-review whatever the setting; they now name the core four and are skipped under off. The fallback regression test folds into test/proactive-skill-start.test.ts, the duplicate header assertion leaves proactive-config, and the frozen-length preamble test is retired (the size guard enforces it). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(proactive): scope note, the unknown-value rule, and the CLAUDE.md routing follow-up; CHANGELOG Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(skill-start): no CLAUDE.md routing offer under proactive off The one-time offer to append ## Skill routing to the project's CLAUDE.md fired whatever the proactive value, and its rules are the auto-invocation an off user turned off. The offer is skipped under off and the legacy false; a section already in CLAUDE.md is left alone. Under core the offered section still routes every skill, which docs/proactive.md records as the follow-up. Found by /ship's red team. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(proactive): STATUS says only core | all | off, and the preamble carves out only named skills gstack-skill-start reads the legacy true/false as all/off and tolerates a quoted, upper-case or commented hand edit (proactive: OFF # mine read as core before), so every surface sees one of three values and the off gating lives in one flag. The per-skill preamble drops the legacy spellings and replaces 'This skill's steps still run', which licensed any in-skill offer under off, with 'Skills the user or this skill's steps name run', at the same length, so the 89 size pins stay at main's. Tests run the script for the tips and the routing offer under core and off instead of grepping the source. Found by /ship's fix-range repeat (red team, testing, maintainability). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(config): set proactive is case-insensitive; follow-up #3446 cited; test hygiene set proactive OFF warned and stored core, the opposite of the opt-out typed; the value is lowercased first, as gstack-skill-start does for a hand edit. The fixture git init carries the tripwire timeout, the source-shape assertion on the private _PROACTIVE_OFF line goes (the routing-offer test proves the behavior), and the CHANGELOG Tests bullets collapse to one per file with the known gap pointing at #3446. Found by /ship's full repeat pass and its tests lane. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(proactive): a stored off answers the one-time prompt; the router names /browse and /investigate under core instead of invoking them Red team, full repeat pass: with proactive: off stored before the prompt, skill-start still emitted the opt-in prompt; it now writes the marker and asks nothing. The router's Route-first browser step and the Failures branches invoked non-core skills under core while the core block said to answer directly; one sentence in the core block resolves it, pinned by the core-set tests. CHANGELOG and docs/proactive.md say both. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(proactive): the full-catalog skill descriptions are the second surface that still routes every skill under core (#3446) From /ship's document-release audit: a --catalog-mode=full build and the non-Claude hosts keep the "Proactively suggest when ..." description sentences, which do not follow the setting; the default Claude build trims them. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(proactive): the tips test runs skill-start as an interactive session GitHub CI sets CI/GITHUB_ACTIONS, which gstack-session-kind reads as headless, and a headless start skips first-task detection, so the first-run tip never fires there (Free Tests shard 16 red at 0d7dbe6; green locally and on the Ubicloud pregate, which have no CI marker). The fixture now sets CLAUDE_CODE_ENTRYPOINT=cli, the positive interactive signal; reproduced locally with CI=1 and fixed. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(proactive): an opt-out never fails open; the preamble carves out invocations, not offers The YAML yes/no family (yes/on/1, no/none/0/disabled/never) reads as all/off in both gstack-skill-start and gstack-config set, so a typed or hand-edited opt-out cannot land on core. The per-skill preamble says "Skills the user names or this one invokes run" (same 168-char length, pins unchanged): a skill dispatching another is not a suggestion, an in-skill offer to run one still is under off. The stored-off prompt marker is written before STATUS prints PROACTIVE_PROMPTED, so the line is true. docs/proactive.md's table row carves out in-skill handoffs. Fourth /ship fix cycle, past the skill's three-cycle cap by GStack Minder's decision (2026-10-26) under Garry's "do it" on the proactive core set; items from the Step 11 adversarial pass. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * v1.91.240.0 stamp Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
2f8ba2a665 |
v1.91.239.0 docs(browse): warn that the bundled Chromium still trusts the compromised eMudhra intermediates (#3338) (#3403)
* docs(browse): warn that the bundled Chromium still trusts the compromised eMudhra intermediates (#3338) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: trim the TLS trust section to verifiable claims (#3338) 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> |
||
|
|
7ee7e8bdd4 |
v1.91.238.0 fix(ship): gate-diff base in single-branch clones, gstack-post release versions and receipt ids, evidence tests_ran, restamp duplicate headings and stamp prompt (GSTA-102) (#3439)
* fix(gate-diff): resolve the base to origin/<base> when no local branch exists; the no_base fix line fetches into the tracking ref Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(post): the repo's release versions and a receipt's tree hash / run ids are not pii.ip_public or pii.phone.e164 Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(evidence): parse the shard runner's and the remote pregate lane's test counts into tests_ran Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(restamp): CHANGELOG_DUPLICATE_HEADING refuses only duplicates the PR introduces checkChangelog takes the base branch's CHANGELOG: a heading the base already carries N times may appear N times on the PR (inherited released history), and only a further copy is a duplicate. gstack-restamp passes origin/<base>'s CHANGELOG at the plan's base sha, so a base like gbrain's master, which heads one version twice, can be stamped; a duplicate the PR adds is still refused with nothing written. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(restamp): the stamp-at-merge next: line no longer asks the lane to edit the CHANGELOG Under a train the stamp commit may hold only restamp's own output: the train's verify accepts the CHANGELOG only as the base's plus the PR's own entry re-headed, and a lane that followed the old "write the CHANGELOG entry text" prompt froze the queue. The claim-at-open wording is unchanged. 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> |
||
|
|
fa9d4b637c |
v1.91.237.0 fix(version-gate): a release output regenerated at the base VERSION is not a stamp (#3451)
* fix(version-gate): a release output regenerated at the base VERSION is not a stamp Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(version-gate): run the head release tool with a bare env, drop outputs it must rewrite, prune the staging worktree Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(version-gate): regenerate at the merge base VERSION, read tool output from a file, never follow a VERSION symlink Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(version-gate): kill a release tool that ignores TERM at the limit, read a bounded log 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> |
||
|
|
6665e20d56 |
v1.91.236.0 feat(ship-queue): require a current /ship receipt before READY, train build and train merge (#3438)
* feat(ship-queue): require a current /ship receipt before READY, train build and train merge Garry, 2026-10-25: use the gstack ship skill before merging PRs. ready printed SHIP_RECEIPT: none as information and returned ok, so the pool was READY'd without /ship. Now ready, train build (dry run included) and verify --train refuse with QUEUE_RECEIPT_MISSING or QUEUE_RECEIPT_STALE from the PR body alone; verify accepts the receipt written for the pinned head when the current head is its stamp commit. gstack-ship-receipt result is /ship's terminal step (GSTACK_RESULT: skill=ship, run dir with the head and receipt), unattended /ship may update an existing PR's body, and INSTALL_UNVERIFIED with no verdict names the project directory to install from (GSTA-85). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(ship): pin Step 22 in workflow-required-steps and tighten the ship skeleton Gate edit: test/fixtures/workflow-required-steps.json pins the new "## Step 22: Terminal line (every run)" heading (strengthens: a later edit that drops the terminal line turns the required-steps test red). Steps 14, 16, 18, 20 and 22 prose tightened so the carve-guards raise shrinks to 81,600 / 1.6740 (measured skeleton 81,535, union 314,027). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (ready at the stamp commit, screen on a stale merge ref, ship-run.json) - ready accepts the pin's receipt at a slot's stamp commit (plus the slot-2 merge of main), as verify --train already did; a real edit stays STALE - ready --screen refuses QUEUE_SCREEN_STALE_REF when refs/pull/<n>/merge is missing or merges an older head; a finished screen that planned 0 cases is never followed, and train build seats that slot unscreened (GSTA-95 on #3431) - gstack-ship-receipt result writes ship-run.json (a /ship record, not a run v1 manifest), validates --head, and prints status=incomplete on gh failures - bindReceipt takes an optional pr and renders one-line SHIP_RECEIPT lines - tests for every state-matrix cell the review named; the train fixture's merge ref is a real merge commit Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: cycle-2 review fixes (private screen scratch, no bare-merge receipt reuse, 12-hex --head, one receipt scrub) and align the unattended hook text with the GSTACK_RESULT writers (GSTA-91) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: adversarial-review fixes (result refuses an unpushed HEAD, resolves --out and reports unwritable records; ready names a failed merge-ref fetch; unattended /ship never runs gh pr ready) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: close review-cycle gaps (a stamp must change a stamp file, result requires a full --head and fails closed without headRefOid, digits-only --pr) with tests for every cycle-3 branch Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: give the fsck-rejected merge-ref spawns a timeout (spawnsync tripwire) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: detect a hollow screen from the plan it uploads (no paid-plan artifact or nothing planned), correct two troubleshooting facts, and normalise result --pr Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(hollow-screen): read manifest.json by name, list artifacts by name, say when the plan is unreadable; lowercase result --head Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(hollow-screen): expired and unreadable run rows, uppercase --head; docs name every SCREEN: literal Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(train build): say when the repository slug is unreadable instead of counting the screen silently Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: name an ls-remote failure in ready --screen, refuse result --pr with --body, cap echoed receipt errors, tell an unreadable install verdict from a missing one Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: ls-remote refusal, --pr with --body, capped receipt errors, unreadable slug and verdict (both twins); docs name the new literals Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: scrub Unicode line separators from receipt text, report an unreadable --body as incomplete, refuse unsupported verdict schemas in the bash twin 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> |
||
|
|
188e574d84 |
v1.91.235.0 docs(triage): parked issues stay open under the parked label; closing means fixed, duplicate or won't fix (GSTA-99) (#3427)
* docs(triage): parked issues stay open under the parked label; closing means fixed, duplicate or won't fix (GSTA-99) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(triage): already-fixed reports close as fixed, duplicates use GitHub's duplicate reason /ship adversarial review on #3427 (outside voice openai/gpt-6.1-sol, native claude-sonnet-5-5): the non-reproduction rule sent reports that main had already fixed to "won't fix"; the Duplicate row said close reason "not planned" although GitHub and gh have a native duplicate reason; a duplicate of an issue that already shipped had no close path; and TODOS.md's "73 open feature requests" sat beside the "75 parked" the CHANGELOG and docs/triage.md state without saying the two extra are #3061 and #3122. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(triage): parked label comes off at close; CHANGELOG entry follows the user-facing style /ship adversarial review pass 2 on #3427: docs/triage.md said the label "goes with" a fixed close but nothing about duplicate or won't-fix closes, and a lane "may" remove it, which left an open lane-owned issue either parked or not. The CHANGELOG entry named TODOS.md in the user-facing summary and listed the GitHub-side label under Added; docs/CHANGELOG_STYLE.md keeps contributor details in a "For contributors" section. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(triage): removing the parked label is a manual step after a merge closes the issue; close labels are added separately Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * v1.91.235.0 stamp Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
75badf306c |
v1.91.234.0 feat(releases): weekly tagged releases and a stable update channel for team mode (GSTA-98) (#3429)
* feat(releases): weekly tagged releases and a stable update channel for team mode (GSTA-98)
Every Monday morning .github/workflows/weekly-release.yml tags the newest green
commit on main as v<VERSION>, publishes a GitHub Release from the CHANGELOG
headlines and fast-forwards refs/heads/stable to it (scripts/release-cut.ts;
workflow_dispatch with dry_run, and ref for a hotfix). Team-mode installs
follow stable through the new update_channel key (auto: stable when
team_mode, else main) in bin/gstack-session-update, bin/gstack-update-check,
bin/gstack-upgrade and /gstack-upgrade. Per-merge stamping and the merge
train are unchanged. docs/releases.md explains it.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ci(weekly-release): check out the dispatched ref so a dry run exercises that branch's script
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ci(weekly-release): a PR touching the release tooling runs the dry run against main (read-only); the cut job checks out the dispatched ref
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(gstack-upgrade): no $1 in the rendered skill (Claude Code rewrites $N), trim Step 4 under the size budget, pin the new floor-check literal
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: leave setup untouched (its channel note moves to README and docs/releases.md); the release workflow and script are free-only PR files
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: record the pr-profile free-only classification as non-behavioral (HARNESS_VERSION 6)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(releases): gate the cut on a main-backstop check run, finish half-done cuts, keep team installs on their channel
/ship review fixes (GSTA-98, PR #3429):
- The weekly release read the Main backstop gate run's conclusion, but
scripts/train-backstop.ts exits 0 when main moved past the push before it
was gated (superseded), so a never-gated tree read as green. The backstop
workflow now publishes its verdict on the commit as the `main-backstop`
check run from a code-free checks:write job (success for covered|gated,
neutral for inert|superseded|deferred, failure for frozen|failed), fed by
the new `--outputs` flag; release-cut.ts requires that check run and
free-tests to succeed and holds a commit whose check runs are still going.
- A cut that pushed the tag and stable but failed to create the release can
be finished: stable itself stays a candidate until its release exists, the
notes compare against the release tag behind it, and a dry run with nothing
green exits 0 with the skips named (the real cut still fails).
- weekly-release.yml: the cut job runs only from refs/heads/main, `ref` must
be a full 40-hex SHA, and actions:read is dropped (no workflow-runs call).
- /gstack-upgrade: the destructive fallback requires the carried UPSTREAM_REF
instead of defaulting to origin/main in a fresh shell; a team install past
the release stops with AHEAD_OF_STABLE instead of FF_REFUSED and a reset
backwards. gstack-update-channel.sh --fetch-ref keeps origin/stable on any
fetch failure other than a missing release; dead gstack_update_channel_ref
removed. gstack-update-check follows main before the first release instead
of caching CHECK_FAILED; gstack-upgrade treats a failed ls-remote as a
fetch failure, not an empty answer.
- Tests: release-cut (check-run fixture, partial cut, neutral/pending),
weekly-release-workflow (new), evals-train-workflow and train-backstop
(backstop-check job, --outputs), update-channel (no-release fallback,
offline --fetch-ref), template pins.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(releases): the upgrade skill's ahead-of-stable exit works in depth-1 clones; update-check keeps its cache identity on the pre-release fallback
/ship second-pass review of
|
||
|
|
4216bbb223 |
v1.91.233.0 fix(plan-tune): bound each UTC day's pull on a dimension, record contributing_events (GSTA-79) (#3397)
* feat(plan-tune): per-dimension contributing_events in the inferred profile Port of the provenance part of #2625 by @v639dragoon: --derive records, per dimension, how many unique log rows moved it, so "no evidence" and "balanced evidence" no longer both print a bare 0.5. Also ports the test harness fix: logQuestion sets GSTACK_QUESTION_LOG_NO_DERIVE=1 so the background derive cannot race the test's own --derive. The registry-independent autonomy signal from #2625 stays parked, as the Oct 8 review decided. Co-authored-by: v639dragoon <matthew@dohma.ai> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(plan-tune): clamp each session's pull on a dimension to one strong answer; trace shares derive's accumulation (#2623) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(plan-tune): shared accumulation JS as a quoted string, not a heredoc (heredoc pipe-deadlock guard) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Own-property signal lookups so a logged choice such as constructor cannot break every later --derive; --trace replaces control characters in the fields it prints; tests for the negative clamp, empty session_id, an unmatched answer and both fixes; docs and CHANGELOG say the bound keys on the writer session_id. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (pass 2) A session_id that is an unsubstituted placeholder such as SESSION_ID counts as its own session instead of collapsing every agent-logged answer into one bound; a log line that parses to null is skipped; the accumulation tolerates a dimension it did not seed; the trace test covers DEL and C1 controls; docs and CHANGELOG wording match the code. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(plan-tune): bound each UTC day instead of each session_id The per-session bound trusted whatever session_id a writer logged. The PostToolUse hook and the agent log different ids for one review, and an unsubstituted SESSION_ID placeholder either merged every review into one bound or left each answer unbounded. Bucketing by the UTC day of ts stops one burst from pinning a dimension without trusting any id; several reviews on one day count as one. Decision A from GStack Minder. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (day bound) Rows without a parseable string ts share one undated bucket instead of each escaping the bound; a ts without a zone is read as UTC, so the day does not depend on the machine's zone; days_span counts the same UTC days; question_id and user_choice must be strings. Tests pin a zone west of UTC. CHANGELOG says contributing_events is recorded in the profile JSON and not displayed yet (#3436). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (strict ISO ts) Only an ISO 8601 date or date-time ts counts as dated; Date alone parses strings such as "junk 1" as real days, which let junk rows escape the bound and inflate days_span. A zoneless time, T- or space-separated, is read as UTC. Tests cover array-valued fields, an offset ts in days_span, the space separator and every undated row reaching the shared bucket. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: narrow the #2623 TODOS entry to its remaining Gate 1 work (#3442) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: v639dragoon <matthew@dohma.ai> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
0c6398f8e6 |
v1.91.232.0 test(judge-calibration): cookie-workflow corpus and comparison-1 result, recorded as held (GSTA-91) (#3416)
* test(judge-calibration): preregistered cookie-workflow corpus, blind second review and adjudication; calibration config (GSTA-91) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(judge-calibration): price the cookie-workflow calibration before dispatch (GSTA-91) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(judge-calibration): record the cookie-workflow comparison-1 run (held: one new false pass) (GSTA-91) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(changelog): cookie-workflow calibration recorded as held (GSTA-91) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (GSTA-91) /ship Step 9 Fix-First on the cookie-workflow calibration record: - README: scope the "no sample errored" sentence to the 2026-10-03 configurations, move the W2 pilot and W2 spend sentences back to the W2 paragraph, record the cookie UC3 prose-step trigger and that its hand-written manifest entry must survive manifest regeneration. - TODOS: the cookie configuration now has a corpus and a held comparison-1; add its triggered prose step to the deferred prose-step entry. - test: pin the cookie pass rule's actionability floor and validate() rejection, and guard that the cookie registration sends only COOKIE_WORKFLOW_JUDGE's keys so the calibrated request stays the request production sends. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes, pass 2 (GSTA-91) /ship Step 9 Fix-First, second pass: - README: the blind-review sentence and results heading now fit the cookie corpus (labels predate any request with the schema; the row carries its own date and model), and the cookie paragraph records that both valid old-a a07 samples also scored 4/4/4. - CHANGELOG: same a07 fact. - TODOS: today's cookie request false-passes a07 and a08; the deferred prose step targets those. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(judge-calibration): pin the cookie calibration's prompt and recorded result (GSTA-91) /ship Step 7 coverage audit: - the cookie-workflow calibration builds exactly the prompt the cookie eval sends for the same bundle; - analyze() reproduces the committed comparison-1 result from its labels, samples, stop record and request options (request_hash covers model and options only, so prompt text and bundle bytes are not pinned). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(changelog): describe the new cookie calibration tests (GSTA-91) 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> |
||
|
|
be402d695c |
v1.91.231.0 fix(setup): install production dependencies only (~520 MB smaller install) (GSTA-97) (#3426)
* fix(setup): install production dependencies only; contributors and CI keep the full install (GSTA-97) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(changelog): production-only install (GSTA-97) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (GSTA-97) - setup/gstack-browser-ensure: Bun treats --production as frozen, so the old fallback could never recover a stale lockfile; refresh it with --lockfile-only, then install production-only again. - gstack-browser-ensure failure line and the README tip no longer suggest a full bun install to users. - Tests: real-Bun stale-lockfile and keep-devDeps contracts, behavioral browser-ensure install tests, relative-import closure scan, multi-line and re-export negative controls; CHANGELOG matches. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes, pass 2 (GSTA-97) - gstack-browser-ensure's failure line and the README tip suggest the frozen production install (./setup skips the install when the build is current, and a bare --production install is frozen anyway). - setup install guard catches quoted and unquoted $BUN_CMD spellings. - Replace the exact-text gstack-browser-ensure grep with an invariant: no full bun install; behavior is covered by gstack-browser-ensure.test.ts. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(setup): keep a contributor checkout's dev packages on bun.lock's versions (GSTA-97) /ship Step 11: a production install over a full install reports "no changes" and leaves devDependencies at old versions after bun.lock moves, so the session updater's ./setup left contributors on stale TypeScript, Prettier and Agent SDK. A checkout with node_modules/typescript gets the full frozen install. The import-closure scan now follows shipped code into test/helpers (gstack-model-benchmark loads the providers). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes, ship invocation 2 (GSTA-97) - Tests: contributor-branch failure row; bun.lock production closure never reaches the dev-toolchain marker; real-Bun rows isolate HOME, XDG_CONFIG_HOME and BUN_CONFIG_*; the import walker follows side-effect imports; file header matches the two install branches. - BROWSER.md quick start uses the frozen production install. - CHANGELOG: the reclaim recipe also drops the Agent SDK's cache entries (Bun hardlinks node_modules into its cache); Tests list is current. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(changelog): stub-bun wording matches what the fixtures check (GSTA-97) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * v1.91.231.0 stamp Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
4814b3d8a4 |
v1.91.230.0 feat(design-shotgun,design-html): archetype handoff and persisted craft exceptions (GSTA-92 phase 2) (#3422)
* feat(design-html): craft section and free craft check, adapted from Elaya design skills (GSTA-92) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(GSTA-92): restore the full CHANGELOG under the Unreleased entry; drop a $-digit literal from craft.md; count only craft-check executions in design-html-slop-gate Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(design-shotgun,design-html): carry the chosen archetype into approved.json; persist accepted craft exceptions in finalized.json (GSTA-92 phase 2) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(touchfiles): design-html-slop-gate selects on the craft check it runs (GSTA-92) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (GSTA-92) A malformed or missing --accepted exceptions file now gets the full craft check with nothing accepted, after a warning, still exiting 2. Before, it printed nothing, and the craft section treats a missing CRAFT_RESULT as 'check unavailable', so one bad finalized.json switched the gate off (found by both adversarial passes). The header comment and the craft section now document the accepted-count suffix on CRAFT_RESULT. Tests cover duplicate carried-forward exception ids and the slop-gate touchfiles selection. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: scope --accepted to the same page; record current counts (GSTA-92) The craft section passed --accepted whenever a finalized.json sat beside the page, so a same-day Start fresh build inherited the old page's exceptions. It now passes them only when evolving or rerunning a page it finalized, records the count the check reports now, and writes [] when nothing was accepted instead of the template's placeholder entry. A test pins exit 2 for a clean page with a broken exceptions file. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: note the archetype handoff in the shotgun and design-html loops (GSTA-92) 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> |
||
|
|
5128ec1469 |
ci(scorecard): bump github/codeql-action/upload-sarif from 4.38.3 to 4.39.0 (#3401)
Recreates Dependabot's #3307 on a crew branch so it can take a version stamp at merge. 6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee is the commit the annotated tag v4.39.0 points to. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
e622075a18 |
v1.91.228.0 fix(gstack-lease): take the lease lock with mkdir, not ln -s, so Git Bash on Windows stops waiting out 300 tries (#3330) (#3424)
* fix(gstack-lease): take the lease lock with mkdir, not ln -s, so Git Bash on Windows stops waiting out 300 tries (#3330) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(gstack-lease): count lock retries instead of timing them Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(lease): a dead lock that cannot be renamed aside no longer spins lock() break_lock ignored drop()'s failure and returned 0, so lock() continued past the tries limit forever when a dead holder's .lock could not be renamed aside (a Windows file in use). It now removes the lock in place under .lock.break, and returns 1 when that also fails so the try is counted. touch no longer calls a dead holder 'live' in its exit-3 message. Adds the /ship coverage-audit tests for the lock's failure paths. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(lease): pre-landing review fixes - drop() reports a lock released once it is renamed aside, so a failed delete of the renamed copy never makes unlock or break_lock rm -rf a new taker's lock at .lock. - An ownerless lock is broken only once it is 2 s old, so a live taker whose claim landed after a breaker read the claims keeps the lock it is about to publish. An empty owner, an invalid pid or a stray file counts as ownerless. - touch's prune stays out of the lock (top-level lease files only) and clears leftover renamed-aside locks; a failed claim write leaves no claim. - Docs and CHANGELOG state the mixed-version and dead-break-lock limits instead of claiming exclusion that does not hold. Tests pin each fix (each fails against the previous bin), make the exclusion case wait on a release file, prove the parallel case is mutually exclusive, and check the Git Bash holder keeps its lock. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(lease): second /ship review pass - orphaned() reads the clock before the lock's mtime and requires the mtime unchanged at the end, so a lock made meanwhile is never removed; an mtime a minute or more ahead (clock skew) counts as old. - Claims older than 2 minutes are abandoned and pruned by touch. - A waiter skips the claim and mkdir while the lock is visibly held; the wait is bounded at 300 tries or 30 s; a non-numeric tries value falls back to 300; ten quick retries (not three) before a lock nobody holds is reported as untakeable; pid 1 is a valid holder again. - Tests: deterministic young-lock clock, skew and non-numeric owner shapes, abandoned claims, the deadline, explicit 30 s timeouts. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(lease): third /ship review pass - A claim is honored while its claimant lives; only a claim with no start identity expires after 2 minutes, so a stalled live taker keeps its lock on hosts that record identities (the remaining case is a documented limit). - A late taker never overwrites an owner already in its directory, and does not remove a directory that has one. - A lock whose owner file exists but cannot be read is never ownerless. - Zero-padded owner pids count as dead; --help prints the whole usage; touch prunes only claims whose claimant is gone or recorded no identity. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(lease): scope 'never by age' to locks that name a holder 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> |
||
|
|
9dc1dfb729 |
v1.91.227.0 fix(windows): shell bins pass NUL as Bun's empty config when MSYS path conversion is off (#3415) (#3431)
* fix(windows): shell bins pass NUL as Bun's empty config when MSYS path conversion is off (#3415) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(windows): detect Git Bash/MSYS2/Cygwin from OSTYPE, as gstack-doctor does, so uname stubs in setup fixtures stay untouched Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (#3415) - Choose NUL only when cygpath is also on PATH, so an OSTYPE=msys inherited by a POSIX bash keeps /dev/null instead of a cwd-relative NUL file. - gstack-developer-profile --log-session reports a Bun failure instead of skipping it as invalid input, like gstack-timeline-log. - learnings-injection tests check that their anchored bun -e block exists. - CHANGELOG names the callers this fix does not cover; curation reason fixed. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes, cycle 2 (#3415) - timeline-log and developer-profile validators print their verdict; any non-zero Bun exit is a reported failure (a Bun crash on Windows exits 3). - timeline-log keeps the original event when ts stamping fails. - The definition ratchet scopes a local GSTACK_BUN_CONFIG to its function. - The shell-bins fixture clears its preload marker per test. - CHANGELOG states the callers that discard the report and the Bun 1.3.x case. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: CHANGELOG notes Bun 1.3.10 evidence and remaining literal /dev/null callers (#3415) 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> |
||
|
|
8d9501373b |
v1.91.226.0 feat(review): /review re-reviews only its fixes after an edited pass, with a final full pass (#3339) (#3414)
* feat(review): /review re-reviews only its fixes after an edited pass, with a final full pass (#3339) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(review): fix-range narrows only DIFF_BASE outside Step 4.8; Step 5.0 ignores this invocation's records (#3339) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(review): fix-range walk logs each pass's Step 4.8 attempt in /review's real order (#3339) 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> |
||
|
|
7bd3fb4a40 |
v1.91.225.0 feat(design-html): craft section and free craft check, adapted from Elaya's design skills (GSTA-92) (#3420)
* feat(design-html): craft section and free craft check, adapted from Elaya design skills (GSTA-92) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(GSTA-92): restore the full CHANGELOG under the Unreleased entry; drop a $-digit literal from craft.md; count only craft-check executions in design-html-slop-gate 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> |
||
|
|
2853304d17 |
v1.91.224.0 fix(context): record the save commit and flag work that landed after it (port of #3316) (#3396)
* fix(context): record the save commit and flag work that landed after it /context-save recorded the branch, a timestamp and the modified files, but not the commit, so /context-restore could not tell that work landed after the save. A checkpoint saved before a step was committed came back with that step still listed as the plan. - gstack-slug --stamp-checkpoint also writes head:, the commit the save describes, next to remote:/project_root:/worktree:. - context-restore compares head: with HEAD before presenting. When commits landed after the save it prints how many and lists them, and moves Remaining Work under Verify first; a saved commit that left the branch history is reported the same way. Checkpoints saved before this keep their old sorting with a one-line note. - test/context-restore-head.test.ts runs the real save-path, stamp and head-check blocks in fixture repos: unchanged, moved, diverged after a reset, pre-tracking, and a malformed head: that must never execute. * fix(context-restore): name another branch as a cause when the saved commit is not in history Cross-branch resume (Conductor handoff) is a supported restore path, and there the checkpoint's commit is usually not an ancestor of HEAD. The diverged line said only 'rebased, reset, or not fetched'. It now names 'saved on another branch' first; the new test case covers a save on a feature branch restored from main. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(changelog): unreleased entry for the context head check (port of #3316) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(context-restore): head check passes the fence lint, reads frontmatter only, prefers worktree:, and overrides provenance sorting - The block used a free-text placeholder, <the chosen file>, which the generated-bash lint (test/env-host-fence-conformance.test.ts) refuses on every host. It now uses the allowlisted <the FILE path printed above>, with prose naming the Step 2 choice. - head:, worktree: and project_root: are read from the leading frontmatter only (sed, no positional $N tokens Claude Code would rewrite), so a head: line in a checkpoint's notes no longer counts. - Outside git, the comparison uses the saved worktree: before project_root:, so a save from a nested linked worktree is not compared with the main tree. - The provenance rules now say they are skipped after HEAD_MOVED, HEAD_DIVERGED or HEAD_UNKNOWN, instead of contradicting the head check. - The re-stamp test checks the exit status and that the head moves. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: Yao Amevi A. Sossou <47247401+soyames@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
1c28c09b76 |
fix(plan-tune): map the clicked AskUserQuestion label to the registered option key at capture (#2623) (#3394)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
f4536ed4d5 |
v1.91.222.0 test: daily flaky-fix pass: qa-only late clock, fragment-match verdict, install-admission timeout, ff-update reap, judge parse diagnostics (GSTA-91) (#3413)
* test: flaky-fix pass — fragment-match reads the agent's report, ff-update reap counts its own sleepers, install-admission gets a measured timeout, judge parse errors name the judge (GSTA-91) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(qa-only): late scenarios freeze the fixture clock during setup and register their real outer budget (GSTA-91) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(harness): record the llm-judge parse-message change as non-behavioral (GSTA-91) 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> |
||
|
|
c23d7d48fe |
fix(session-update): the starting session's own lease never skips its update; autostash fixtures own their lease dir and state root (GSTA-91) (#3412)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
956a3f5484 |
v1.91.220.0 fix(office-hours,plan-reviews): write the plan-mode copy through to the design doc and warn when it is newer (#542) (#3408)
* fix(office-hours,plan-reviews): write the host plan-mode copy through to the design doc and warn when it is newer (#542) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(changelog): #542 under [Unreleased] Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(instruction-facts): drop the office-hours allowlist row for the removed cross-team sentence 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> |
||
|
|
f73f75ce55 |
v1.91.219.0 fix(eval-bg): local lanes export EVALS_RUN_ID so native-capture cases start (GSTA-70) (#3391)
* fix(eval-bg): local lanes export EVALS_RUN_ID so native-capture cases start (GSTA-70) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * v1.91.219.0 stamp Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
d73b547066 |
fix(team-init): register the required Skill hook with onFailure: block (#3319) (#3393)
Without node on PATH the node -e launcher exits 127, and with check-gstack.cjs missing it exits 1; Claude Code treats both as non-blocking and lets the Skill call through. Register the handler with onFailure: block (Claude Code 2.1.295+), upgrade existing registrations in place, and tell the agent and the developer what the two block reasons mean. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
2d27b482d2 |
v1.91.217.0 fix(ci): run Windows free tests on every push to main (GSTA-68 follow-up) (#3390)
* fix(ci): run Windows free tests on every push to main (GSTA-68 follow-up) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * v1.91.217.0 stamp Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
64d82101ca |
v1.91.216.0 fix(sync-gbrain): refuse an active autopilot before touching the source list (#3360 part 2, port of #3362) (#3386)
* fix(sync-gbrain): refuse on an active autopilot before the code stage registers a source Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * docs(changelog): sync-gbrain autopilot refusal before source registration (#3360, port of #3362) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(sync-gbrain): the early autopilot refusal check matches #3377's pid-naming wording (#3360) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: Evgenii Lopatin <e75533@gmail.com> Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
5ac0f56934 |
fix(ship): unattended handoff writes the receipt to a file the parent reads (GSTA-88) (#3409)
Step 18-H's receipt write gains --out .gstack/tmp/ship-receipt.md; skill-start prints a ship-only UNATTENDED_SHIP line; docs/unattended.md sends the parent to read --body on that file and to compare head to the branch SHA. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
08301328e9 |
v1.91.214.0 fix(brain-sync): --publish-removals cleans up its temp list and lock without 'list: unbound variable' (GSTA-87) (#3405)
* fix(brain-sync): --publish-removals trap expands its temp paths at install, so cleanup and lock release run after the function returns (GSTA-87) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * v1.91.214.0 stamp Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
5bbe538bdc |
v1.91.213.0 fix(ci): Node.js 22.23.4 in the CI image and Ubicloud free-suite VMs, SHA-256 verified (port #3355, fixes #3354) (#3400)
* fix(ci): bump Node.js to 22.23.4 for CVE-2026-111497 * fix(ci): pin Node.js 22.23.4 in the Ubicloud free-suite bootstrap too, and verify both archives by SHA-256 #3355 bumped Dockerfile.ci only; scripts/ubicloud/setup-free-suite.sh still installed 22.20.0. Both now pin the same version and the linux-x64 SHA-256 from the release's signed SHASUMS256.txt, check the archive before unpacking, and test/ci-image-cli-pin.test.ts keeps the two pins equal (#3354). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> Co-authored-by: Michael Sumner <75835774+michael-sumner@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(changelog): Node.js 22.23.4 CI pin (#3354) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(ci-image): name Dockerfile.ci in a form pregate resolves; assert the image hash in the parity case Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: Michael Sumner <75835774+michael-sumner@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
f00b8bc79b |
v1.91.212.0 fix(careful): mask git commit's own message before the MEDIUM checks (#1060, port of #3221) (#3389)
* fix(careful): mask git commit -m content to prevent MEDIUM-tier false positives (#1060) MEDIUM-tier checks matched the full command string including quoted -m text. A commit like 'git commit -m fix: prevent drop table in migration' triggered the SQL DROP warning even though no SQL was being executed. Build CMD_MEDIUM by stripping -m quoted content from git commit commands before MEDIUM checks. Real destructive commands outside the quoted string still match, so true positives are unaffected. Add tests: commit message patterns do not warn; chained real DROP/TRUNCATE still warns. * fix(careful): replace sed masking with quote-aware awk scanner (#1060) The sed-based -m content masker had two bypass paths that capy-ai identified: 1. Single-quoted message containing a double-quote boundary: git commit -m 'note -m "' && rm -rf build && echo '"' The double-quote pass matched '-m "' inside the single-quoted string, swallowing '&& rm -rf build && echo '; the rm vanished from CMD_MEDIUM. 2. Double-quoted message with a command substitution: git commit -m "$(rm -rf build)" sed replaced the content including the $(...), so the substitution — which executes in the shell — was masked away. Replace the sed substitution with a quote-aware awk scanner that: - Walks the command string tracking single-quote, double-quote, and backslash state, so it only treats a delimiter as a message boundary when the shell would. - Masks single-quoted messages (always literal) and double-quoted messages that contain no $, backtick, or backslash (safe to mask — no expansion). - Leaves double-quoted messages with $, backtick, or backslash unmasked so command substitutions stay visible to the MEDIUM checks. - Handles -m, -am, --message, and --message= forms. Four new tests added as requested (alongside the original six): - single-quoted message with embedded double-quote + chained rm → warns - commit message with $(rm -rf build) → warns - git push --force chained after commit → warns - git commit -am "drop table notes" → silent (message masked) * fix(careful): read the commit-message masker from a file, so bash 3.2 can parse the hook (#1060) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(careful): scan the command as one string, so a newline still separates commands from the message (#1060) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(careful): mask only git commit's own message; a piped commit or another command's -m stays visible (#1060) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(careful): mask a quoted-delimiter heredoc message; any other substitution or heredoc leaves the command unmasked (#1060) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(careful): a pipe, process substitution or parameter expansion after the message unmasks it; redirections and comments parse like bash (#1060) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(changelog): careful masks git commit's own message (#1060, port of #3221) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: Bhumika-1432006 <guravbhumika808@gmail.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
cb99df4a2f |
fix(diff-scope): count Python test_*.py and nested test dirs as tests (#3335) (#3382)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
c279ce045d |
fix(autoplan): linked worktrees resolve from a project directory below the repo root (#3296) (#3383)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
0ea3dc8986 |
test(redact): fixture git and hook installs share gitEnv(), so a global core.hooksPath is never rewritten (#3353) (#3384)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
e2fffee311 |
v1.91.208.0 docs(capy-install): session-start updater honors workflow leases (#3363, GSTA-75) (#3399)
* docs(capy-install): session-start updater honors workflow leases (#3363, GSTA-75) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * v1.91.208.0 stamp Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |