mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-06 08:54:04 +01:00
4b4cadcb9cd02b85235cecdfd7bb77eb2cf79ae5
186
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4b4cadcb9c |
Merge origin/main into feat/design-lint; stamp 1.91.251.0
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
fd67b88c5e |
design-lint: adversarial review fixes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
e997d6fb4d |
design-lint: thirteenth review cycle fix
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
734e07f0a5 |
design-lint: twelfth review cycle fixes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
7c9dab30ef |
design-lint: eleventh review cycle fixes
A nested rule under a parent longer than the selector cap falls back to the parent's first part cut to 256 characters, the :is() wrapper is built only on the expanding path, and every stored selector is cut at MAX_SELECTOR; the limited stripTags counts visibility with the whitespace class its callers collapse on and never cuts a surrogate pair; glWords slides its window by innerHeight. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
e4a6adbf3a |
design-lint: tenth review cycle fixes
tooltip-focus-delay splits the transition value at top-level commas, so a delay after cubic-bezier() or steps() is still read; nestSelector budgets one substitution per '&' before expanding; stripTags with a limit stops reading at the limit instead of after the next tag; accentedHeads reads each span's text once and covers classes from one map; a JSX close tag with no '>' is text, not a failure every ancestor rescans; selectorNames reads the tag that opens an :is()/:where() list; a linked sheet that cannot be read is unreadable, not unparseable; the space probes read their viewport from the page; the internal-error title covers a page or stylesheet the lint could not read. 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> |
||
|
|
5afec19d5c |
design-lint: ninth review cycle performance fixes
css.ts selectorNames reads the tag and class names a selector list mentions once, so nowrap coverage, wrapping coverage and the roman-em check answer per element in constant time; shortProseOf reads elements by class from an index built once per document; font-family-count keeps a Set of family keys; the import scan gives the optional paren its own whitespace; a JSX expression that runs to the end of the file fails every ancestor at once; the render locator reads class and not data-class; tooltip-focus-delay reads the delay slot of the transition shorthand, so 200ms is a duration like 0.2s. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
b101f64951 |
design-lint: ninth review cycle fixes
nestSelector stops expanding a comma list nested in a comma list past an 8 KB selector, resolveVars never substitutes a token over MAX_RESOLVED and stops growing a value past it, a stylesheet or <style> block the lint could not parse (or a linked sheet over the size cap) is an internal-error finding through the Skipped list, which now carries a kind; stripTags takes a visible character limit so the emoji and label reads do not pay for an element that runs to the end of the file; assets.ts records every quoted emoji finding and component.ts splices the one at its line; columnCount drops named lines inside repeat(); doc.text is built from the stray-blanked source; Reporter.report returns the finding; the 1280 probes read their viewport from the page; openTags loses its unused limit; the CHANGELOG hero-fold note matches what the probe measures. 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> |
||
|
|
a84b030ca0 |
design-lint: eighth review cycle fixes
Waivers follow the context's shape, not the --scope flag: one html page keeps page semantics under either scope (its claim reaches the sheet it links) and a lone component beside an unlinked stylesheet answers for its own file only. Every '<' that starts no tag is a stray spaced out of doc.src (a '<!' or '<?' with a '>' ahead stays), an unclosed comment runs to the end of the file, the three bare /<[^>]*>/ strips use stripTags, the copy tier drops open script, style, template and nav tags nothing closes, component tags are paired once per document, columnCount counts repeat() arithmetically, an unclosed @starting-style block is read once, the import scan matches import shapes only, the render locator refuses a non-letter tag and reads the class attribute linearly, tickers are answered from the tree, a tooltip duration is not a delay, class tokens are appended in a loop, the emoji dedupe is keyed by the icon, the emoji classes spell U+FE0F and U+200D as escapes, the contrast and focus viewports are named once, and the hero-fold title matches what the probe measures. 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> |
||
|
|
7da881d6e3 |
design-lint: seventh review cycle fixes
A tag start the scanner finds no '>' for is spaced out of doc.src, so every '[^>]*>' scan over a page (the lint's and the craft check's) costs the page its length; render's line lookup reads the same text. The JSX scanner skips a generic element's type arguments and closes every element under a close tag that names an open ancestor, as a browser would; a closer naming nothing open is text. The token table is read in one colour mode: the base block's last declaration wins and a prefers-color-scheme or data-theme override only fills tokens the base never declares; a custom property declared in any scope is a token definition, not a literal; a token finding points at the declaration that won. In a directory of components, under either scope, each file's claims answer for that file alone with its own suspected rules. The Tailwind dedupe keys files the way Reporter prints them. outline: none is not a ring for input-state-shift; a form with a password or a sign-in button is not an email band; one CONTROL_TRACK_MAX_EM (0.04) for both halves of wide-tracking; one CONTRAST_SLACK; hairline-under-shadow splits layers with splitTop; a missing linked stylesheet is warned about; TwItem.toks and the controlHeight scope guard are gone; zero-chroma-neutrals is titled for what it reads. aside-render sets the device override or viewport only when a sized step's size changes and clears it before an un-sized step. 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>
|
||
|
|
be4086e03b |
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> |
||
|
|
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> |
||
|
|
1595ff68c2 |
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> |
||
|
|
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> |
||
|
|
6a29e7e47e |
design-lint: heroIndexOf carries its own doc comment
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
c0422db7f2 |
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> |
||
|
|
f5134ae2db |
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> |
||
|
|
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> |
||
|
|
6100d6e94d |
design-lint: third review cycle fixes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
ddaeabe1f4 |
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> |
||
|
|
df6cd725c2 |
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> |
||
|
|
2bf81ad1f1 |
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> |
||
|
|
31682440fe |
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> |
||
|
|
54d415bd2d |
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> |
||
|
|
a088fc3d8c |
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> |
||
|
|
5232f86770 | Merge remote-tracking branch 'origin/feat/design-lint-render' into feat/design-lint | ||
|
|
07b2aa6527 |
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> |
||
|
|
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> |
||
|
|
22d39449d1 |
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> |
||
|
|
69a7ec0e82 | Merge remote-tracking branch 'origin/feat/design-lint-chrome-assets-finish' into feat/design-lint | ||
|
|
6dda84e531 |
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> |
||
|
|
95eee7e4e1 |
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> |
||
|
|
95b19fdbca | Merge remote-tracking branch 'origin/feat/design-lint-structure-motion' into feat/design-lint | ||
|
|
aed2b149e6 |
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> |
||
|
|
3113f54d55 |
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> |
||
|
|
dfd6693d51 | Merge remote-tracking branch 'origin/feat/design-lint-tailwind' into feat/design-lint | ||
|
|
ab8bb491ac |
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> |
||
|
|
69ac84f2e4 |
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> |
||
|
|
3807370452 |
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> |
||
|
|
1ba2ae0425 |
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
669e59d65b |
v1.91.206.0 feat(pregate): user-owned policy file and local lanes (port of #3286) (#3398)
* feat(pregate): user-owned policy file and local lanes
A repo that keeps .gstack/ out of git can hold its pregate policy at
<GSTACK_HOME>/projects/<slug>/pregate.json. gstack-pregate run reads it only
under --policy-from base when the base carries no .gstack/pregate.json, so a
reviewed base copy always wins and a PR still cannot reach the policy. A
missing file falls back; any other read error, and a non-null sealed or
price_file (read only from the git copies), refuse with PREGATE_CONFIG_INVALID
and a fix that names the file.
A new `local` key lists <workflow.yml>/<job> lanes a local run satisfies: a
platform lane named there runs here (tier unit) instead of becoming a
requires-remote obligation. Lane ids share one LANE_ID check with selection.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(pregate): the user-owned policy file and local lanes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(pregate): policy fixes name the user-owned file when it is the active policy
With no .gstack/pregate.json on the base, an edit to that path is never read,
so the no-lane, runner, stall_timeout_s, remote_gate and strays fixes now name
ctx.configFile: the user-owned path when it is the active policy.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(pregate): the remote_gate, strays and stall fixes name the active policy file
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(pregate): pre-landing review fixes for the user-owned policy
Ignore a user policy path that is relative or inside the checkout, fingerprint
the active user file into check inputs, name the user file in its JSON errors
and the refusal lead, add --explain lines for an absent user file and an
unknown local id, and document the state-root location and slug lookup.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(pregate): containment edges and explain wording for the user policy
A state root under an in-repo directory named ..something passed the
inside-the-repo check, and realpath kept the caller's casing on macOS.
The unknown-local explain line now says workflow lane, and the state-root
chain in explain and docs names every source.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(pregate): a base copy git cannot read, or a dangling user symlink, refuses
Any git show failure read as no base policy, which now hands the run to
the unreviewed user file; it is absent only when cat-file says so, and a
spawn error (stdout cut at the buffer limit) counts as a failure. A user
pregate.json that is a dangling symlink refuses instead of reading as
absent.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(pregate): decide a missing base policy from the tree, and catch dangling parent links
cat-file -e checks the blob, so a missing or corrupt object still read as
no base copy; ls-tree reads the tree entry, and any failure refuses. The
dangling-symlink check now covers every path component, not just the file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(result-codes): POLICY_SOURCE_UNAVAILABLE names an unreadable committed pin file
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(pregate): the active policy may be the user-owned file; new refusals
Guards, remote_gate, stall timeouts and lane fixes name the user-owned file
when it is the active policy; the trust boundary says run alone reads it;
the dangling-symlink and unreadable-base-copy refusals are documented, and
state-root lists the bucket's pregate.json.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(pregate): a checkout's .env cannot pick the user policy; verify re-checks it
Bun loads .env from the working directory, so a branch could set
GSTACK_PROJECT_SLUG or a state root and choose which pregate.json governs
it. The shebang now passes --no-env-file, scriptInvocation carries that
flag over when it launches the bin as bun <script>, and a bare bun launch
beside any dotenv file refuses (POLICY_SOURCE_UNAVAILABLE).
A recorded pass also outlived its policy: pregate.json now records the
user file's digest (or, under the defaults, the path that was absent), and
verify and the ship receipt treat an edited, deleted or newly present user
file as PREGATE_STALE, reading both paths from the record.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(pregate): keep the POLICY_SOURCE_UNAVAILABLE summary's pin-files wording
The added '(or .gstack/pregate.json)' broke describeRefusal's rewrite to
'the reviewed pin files cannot be read', which pregate-wtree-refusal pins.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(pregate): pick the host-foreign lane in the user-policy local-lane test
On a Windows host the windows lane is native, so it never became
requires-remote and the test failed on the Windows shards.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(pregate): Rust crate lanes and nested JS package runners
lanes reported PREGATE_NO_LANE for every touched .rs file and ran a nested
pnpm+vitest package's tests as `bun test` from the repo root.
- Rust: a .rs file of a crate (nearest Cargo.toml with [package]) is a test
under <crate>/tests/ or when it holds a #[cfg(test)]; every .rs file of a
crate and its Cargo.toml select the crate's tests and those of every crate
depending on it (lib/pregate/rust.ts). Selected tests run per crate as
`cargo test -p <name>` from the workspace root, judged on the summed
`test result:` lines (doc-tests included); zero tests stays ZERO-RUN and a
missing cargo is incomplete, like a missing Dart SDK.
- JS/TS: a test owned by a nested package.json that declares vitest or jest
runs from that package with package-relative paths, through the package
manager its packageManager field or nearest lockfile names (pnpm exec,
yarn, bun x, else npx). Root detection and a declared runner are unchanged.
- init notes that Rust tests run per crate; docs/pregate.md updated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(pregate): parse Cargo manifests as TOML; follow workspace membership
The line scan of Cargo.toml missed dependents (a false green) and picked the
wrong workspace:
- an inherited renamed dependency (`base = { workspace = true }` with
`[workspace.dependencies] base = { package = "alpha", path = ... }`);
- dotted keys (`alpha.path = "../a"`), `[dependencies.<name>]` tables and
target-specific tables, matched by key name only;
- a crate the workspace excludes ran `cargo test -p` from the workspace root.
Manifests are now parsed with Bun.TOML. A dependency resolves by path
(relative to the manifest declaring it, or to the workspace root when
inherited), else by package name. A crate runs from the workspace it is a
member of under Cargo's rules (package.workspace, the nearest [workspace],
members globs, exclude, literal members, path dependencies of members),
else from its own directory. Nothing runs cargo.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(pregate): the Rust fixture's cargo shim wins PATH on Windows and beside a real cargo
windows-free-shard (5) failed 'a touched src file runs its crate...' and
'zero tests is ZERO-RUN...' deterministically: the shim PATH was joined with
':' so Git Bash never saw the shim dir, and the runner's real cargo ran
against the fixture (exit 1, no test result lines). On POSIX hosts where
Bun and cargo share a directory (/usr/local/bin on Capy's image), the lane
puts Bun's directory first and the real cargo wins the same way.
Join with path.delimiter, add cargo.cmd for Bun.which on Windows, and on
POSIX put the shim first again in the lane's own bash through BASH_ENV.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(pregate): quote the crate name in cargoRunner
The crate name is read from the repo's Cargo.toml and was interpolated into
'cargo test -p <name>', which the lane runs through bash. A name like
'evil;touch pwned' ran the second command. Quote it like every file and cwd
the lane already passes; a new end-to-end case checks the name reaches cargo
as one argument and runs nothing.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(pregate): the nested-package pnpm shim wins PATH beside a real pnpm
'a touched file in a nested pnpm+vitest package runs vitest there' ran the
host's real pnpm wherever Bun and pnpm share a directory (/usr/local/bin on
Capy's image): the lane puts Bun's directory first, so pnpm installed vitest
from the network, dirtied the fixture tree and the check came back
incomplete. Put the shim first again in the lane's bash through BASH_ENV,
as the Rust fixture does.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(changelog): pregate Rust crate lanes and nested package runners (#3344)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(pregate): a crate name Cargo would reject never reaches the lane's shell
Port review (outside voice): quoting alone was not enough, because the lane
expands {files} after the runner string is built, so a crate named
'evil{files}' spliced the quoted file list into the quoted name and a file
name like tests/$(cmd).rs then ran. A name outside Cargo's grammar
(letters, digits, _ and -) now gets no runner: its files are unclaimed and
the lane is incomplete, as Cargo itself would refuse the manifest. A valid
name, Unicode included, still runs quoted.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(pregate): match Cargo members globs per path component, without a backtracking regex
Port review (outside voice): members globs went through ship-policy's
matchesAny, which escapes [...] classes (crates/[ab] matched nothing, so the
crate was no member, lost its inherited [workspace.dependencies] path and its
dependents' tests were never selected: a false green) and backtracks
exponentially on a hostile glob such as '*a*a...*ab' (over 5 s for one crate,
before any runner deadline). A small dynamic-programming matcher handles *,
?, [..] with negation and ranges, and ** across components, in
O(pattern x path).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(pregate): a plain #[test] in src is a Rust test; bound the cfg attribute scan
Port review (outside voice): only #[cfg(test)] modules and tests/ files
counted, so a dependent crate whose tests are plain #[test] or #[tokio::test]
functions in src never ran when its dependency changed (a false green). The
cfg scan also went quadratic on a run of unclosed '#[cfg(' (about 3 s on
120 KB). Test attributes now count, and the cfg predicate and its strings are
length-bounded so the scan stays linear.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(pregate): Rust test attributes, workspace membership and rejected crate names; changelog for the port review fixes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(pregate): match members globs by code point in one pass, and admit every crate past a size cap
Second port review round (outside voice): the matcher counted UTF-16 units, so
'crates/?' missed a crate directory named with a supplementary character and
dropped its inherited dependencies (a false green); and each unmatched '['
rescanned the rest of the glob (5 s for one crate with a million of them).
Tokenize by code point with a precomputed next-']' table, and past 4096
characters of members globs admit every crate under the workspace: a wrong
member fails loudly in cargo, a dropped one is silent. The new supervised
probe kills a super-linear matcher at 30 s instead of hanging the file.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(pregate): scan cfg attributes once without truncating them; an unclosable one counts as a test
Second port review round (outside voice): the length bound from the first
round dropped a valid cfg(any(test, feature = "<257 chars>")), so its crate's
tests were no longer selected (a false green). Read each attribute once to
its closing ']' and resume after it, which keeps the scan linear without a
bound; an attribute the scan cannot close (an unterminated string, no ']')
counts as a test, which selects more, never fewer.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(changelog): second port review round (code-point member globs, unbounded linear cfg scan)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(pregate): past the members size cap, a crate's run root is undecided and its tests unclaimed
Third port review round (outside voice): admitting every crate past the cap
made a non-member run as 'cargo test -p <name>' from the workspace root,
where a same-named member answered and its passing tests stood in for the
orphan's failing one (a false green). Keep the conservative membership for
dependency edges, but leave such a crate's workspace undecided (null):
planRuns leaves its files unclaimed and the lane incomplete.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(pregate): the Rust end-to-end runs put the cargo shim under Windows' own Path key
windows-free-shard (5) still failed both end-to-end cases at
|
||
|
|
072d073b12 |
v1.91.205.0 feat(ship): Step 9 fix-range re-review, with a mandatory final full pass (#3339) (#3404)
* feat(ship): Step 9 fix-range re-review with a mandatory final full pass (#3339) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(review-log): fix-range base is the commit the fixing pass started from; follow Step 9.4's real order (#3339 review) 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> |
||
|
|
f2ddc495dd |
fix(cso): report a go.mod repository as Go (unsupported), not Python (#3263) (#3378)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |