CI 'Check VERSION is not stale vs queue' classified #3434 as stamped because it touched
agents-digest/gstack-AGENTS.md (a release_outputs path), while regenerating only the
generator fails the digest freshness test. The first-run intro rewording stays.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
The preamble-hoist.ts docblock and ARCHITECTURE.md still said the shared
preamble is re-read only when its id is absent; since 2acf1a44a the pointer
requires the skill's own earlier Read of the file.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
preamble-hoist: on every host, tier and render option the pointer allows the
skip only when the skill's own Read is in context. agents-digest and
gstack-skill-start: the digest bullet and the lake intro say complete
coverage, minimal code, never the retired phrasing. Each fails at 9af36d010.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
The pointer skipped the shared file when any text carrying its id was in context, so a
page or file with that heading could stand in for the anti-spoofing rules (security,
red team and adversarial review, ship run 2). It now requires the skill's own earlier
Read. The digest's Boil the Ocean bullet and the first-run intro still said 'AI makes
completeness cheap, so do the complete thing' (docs audit blocker); both now carry
Garry's 'complete coverage, minimal code' (2026-10-25: '1/ yes fix this').
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
host-conformance: --status still finds a broken bare sections/ pointer when a
carved Claude skill's installed sections/ is a directory symlink (fails at the
pre-repair 0e5d11fd9). gen-skill-docs: the house rule review/specialists/
simplification.md quotes from ETHOS.md still appears in ETHOS.md.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
plan-ceo-review's parity cap moves 1.0999 -> 1.1006 for the approved COMPLETENESS IS
COVERAGE bullet (Garry 2026-10-25: "do it", parity caps to measured size; applied by
GStack Minder).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
The growth ceiling now measures SKILL.md plus the shared preamble, the same
measure as the shrink floor; the docblock said SKILL.md only.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
- setup: follow a symlinked sections/ dir in the carved-pointer status check
- touchfiles: select preamble-hoist.ts alongside every preamble.ts entry
- section-manifest: exempt sections/preamble.md only for skills whose SKILL.md
carries the shared-preamble pointer
- skill-size-budget: growth ceiling measures SKILL.md plus its shared preamble
- host-conformance: tolerate a missing sections/ dir, as setup does
- skill-validation: read bin/gstack-skill-start directly
- skill-fixture: error messages and docblocks name the actual boundary
(harness-version non-behavioral note updated)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Adds test/preamble-hoist.test.ts (tier 1 unchanged; tier 2+ SKILL.md plus
sections/preamble.md reproduces the pre-hoist preamble; pointer position and id)
and two gen-skill-docs-checks cases (one shared preamble per host, beside every
pointer and named by its id; preamble artifact kind).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
The [Unreleased] Tests bullet now says the default-copy test checks both halves of the rule (full coverage of the requirement; smaller diff only at equal coverage; no impossible-state checks; never excuses a gap), matching 88e3cc0 and 44eacaf.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
The default-copy check now also fails if 'on equal coverage' is dropped from the smaller-diff rule (which would tell models to prefer the smaller diff unconditionally) or if the no-impossible-state-checks clause is removed.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
The completeness section shrank by 3 characters (5 bytes), matching the 89 pins lowered by 3. The default-copy test pinned only the minimal-code half; an expectMentions check now fails if the full-coverage or never-excuses-a-gap clause is dropped.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* 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>
screen-summary failed on #3434 with 'PR profile requires full validation' for nine
skills whose only paid coverage is periodic: their new sections/preamble.md had no
dependency identity, while the SKILL.md beside it inherits its template's.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* 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>
Every tier 2+ SKILL.md inlined the same ~23 KB preamble. It now renders once
per host into sections/preamble.md beside each tier 2+ SKILL.md; the SKILL.md
keeps a pointer that asks for the Read only when the file's id is not already
in context. Only sections byte-identical to the shared render move, so every
skill keeps exactly its pre-hoist paragraphs (verified across all 41 skills).
Parity caps for ten skills raised to their measured unions (owner-approved,
Garry 2026-10-25: "do it"); 63 size pins lowered and 26 deleted.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* 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>
* 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>
* 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>
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>
* 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>
* 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>
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>
* 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>
* 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>
* 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>