mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-09 22:48:57 +02:00
0c160e2a0ece5d0e3745acd4ea177d397b06d046
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7c90368229 |
fix: adversarial review fixes (Claude pass, 14 findings, 1 verified-live critical)
The fresh-context adversarial pass caught a live bug in this branch's own
performance fix: gstack-wtree exported GIT_INDEX_FILE BEFORE resolving the
real index path, so `git rev-parse --git-path index` returned the temp index
itself, the stat-cache copy self-copied and failed, and every invocation fell
back to the full re-hash — the fast path was dead code (verified with bash -x).
Resolution now happens before the export; measured 0.08s per call on this repo.
Also fixed: careful fails to an ASK (not silence) when its own helper file is
missing (same partial-install state freeze already defends against); the
--source label is sanitized inside the envelope lib (newline-stripped,
sentinel-defused, length-capped — it sits in trusted framing); the HIGH rm
tokenizer skips redirections/backgrounding/`--` (rm -rf / 2>/dev/null now
denies) and knows ${HOME}; user pattern lines starting with a dash work
(grep --); greptile bodies carry per-comment id headers inside the envelope so
multi-comment PRs stay attributable (ids verified against raw metadata, never
trusted in-body); the release-body tripwire fails CLOSED when its input files
are missing (separate-shell $$ reality); land 3.5b gets the same allow-paths
as ship; the "either side dirty" fallback leftover is gone from both grading
surfaces; the evidence pump races drain against error (EPIPE consumers can't
hang the wrapper); an unset HOME skips bookkeeping instead of creating a
literal ~ dir inside the repo; a write-failure log ends with a visible marker;
freeze expands a literal leading ~ in the boundary; review-log documents its
log-time binding window.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
5d6804cb61 |
fix: red-team review fixes (9 findings, 2 critical)
Red team reviewed what four specialists missed — cross-cutting and self-contradiction class: CRITICAL: the release-body banner tripwire failed OPEN on the exact leak it guards (grep -c prints 0 AND exits 1 on no-match, so a fallback echo double-emitted "0" twice and the -gt comparison fell into the clean branch) — counts now default via parameter expansion, and a functional drift test executes the rendered tripwire block against a 0->1 banner delta to prove the ABORT branch fires. CRITICAL: evidence fingerprints were captured AFTER the child exited, so a working-tree edit made DURING a long suite was certified as tested content — wtree is now captured before spawn and re-checked after; mid-run drift omits the fingerprint (grades STALE) with a warning. Also: the review-grading rule dropped its dirty-gates (they nullified the keystone dirty-record->commit->CURRENT property that evidence checks already honor — wtree equality alone proves identical content); careful's HIGH force-push tier falls back to probing origin/main|master when the origin/HEAD symbolic ref is absent (Conductor worktrees — the tier was silently inert in the primary deploy environment); quoted tokens (rm -rf "/", push "main") no longer dodge the deny; freeze fails CLOSED when its own helper file is missing (bash makes a missing source target fatal non-interactively, so an existence pre-check guards it); spec dedupe distinguishes pipeline failure from zero matches instead of silently skipping dedupe on gh/jq breakage; land 3.5b sets the cross-session --expect-cmd mismatch expectation; hook analytics JSON fields are encoder-built per this wave's own rule. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a171029e6b |
fix: pre-landing review fixes (27 specialist findings, 3 critical)
Specialist army findings, all quote-verified before fixing:
Security: careful force-push guard now catches git's plus-refspec force
syntax (git push origin +main carried force with no flag — silently allowed
before) and refspec-form targets (HEAD:main); default-branch matching is
tokenized FIXED-STRING comparison on the full branch path (slashed defaults
like release/2.0 work; no ERE interpolation), glob-safe via noglob. HIGH rm
tier is tokenized too: trailing long options (--no-preserve-root) and /* are
root-class. Stored evidence fingerprints are 40-hex re-validated before
reaching git argv. normalizeForDetection sweeps ALL Unicode format chars
(\p{Cf}: soft hyphens, bidi marks, tag chars) instead of five enumerated
zero-widths. The wiring scanner gains flagless gh pr/issue view patterns. The
release-body banner tripwire diffs against the fetched original so a hostile
pre-existing banner string can't permanently DoS doc updates. Ship/land
evidence checks now pass --expect-cmd (a green `echo ok` recorded under the
label can never mint FRESH); package.json stays allow-listed with the
residual documented.
Performance: gstack-wtree seeds its temp index by COPYING the real index
(stat cache preserved — measured 40x faster than read-tree seeding, identical
hash) with read-tree fallback; evidence uses findLast and one gstack-slug
spawn; the stream pump honors backpressure via drain; careful's pattern block
short-circuits before slug resolution when no pattern file exists.
Testing: the gh-failure envelope test was VACUOUS (killing PATH killed the
bun shebang before the code under test ran) — replaced with a PATH gh shim
that exercises the real branch, plus shimmed happy paths (issue/pr-body/
unparseable JSON); evidence check --all + empty ledger + non-numeric
--max-age (now a usage error, was silent fail-open) covered; HIGH-tier
variants pinned; hook analytics respect GSTACK_HOME so tests stop writing the
operator's real skill-usage.jsonl.
Maintainability: dead exit ternary removed; flagValue deduped into
bin-context; sentinel defusal derived from the banner constants (no invisible
literals — \u escapes only); scratch-repo git fixture extracted to
test/helpers/scratch-repo.ts (one hermetic incantation, three consumers);
shared gstack_hook_log_fire in hook-extract.sh; the dashboard/land diff-scoped
row lists are aligned (codex-review) and drift-pinned.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
f9a9716ad2 |
feat(security): trust envelope for tracker text at every model-context ingress
Web page content has had a trust envelope since v1.38; tracker text did not — PR bodies, PR/issue comment bodies, and model-judged issue titles entered agent context raw. Anyone who can comment on a PR could put instructions in front of the agent. New lib/tracker-guard.ts + bin/gstack-issue-guard: every tracker-text read now emits inside a "BEGIN UNTRUSTED TRACKER CONTENT" envelope. Content is enveloped even when clean (a pattern scan is not proof of safety); injection-shaped lines get a visible [INJECTION-PATTERN] label; NFKC + zero-width normalization runs for DETECTION only (fullwidth/invisible evasion caught, content bytes never rewritten); forged END banners are zero-width-spliced so they can't close the envelope early. Fetch failure exits non-zero with NO envelope — never a fake-trusted empty one. Issue numbers are validated and gh is spawned via argv arrays. Patterns reuse lib/jsonl-store's INJECTION_PATTERNS single copy plus a separate TRACKER_EXTRA list (kept separate so decision/learning store write-rejection semantics don't change). 8 sites wired: greptile findings + replies fetches (metadata/body split — ids and paths stay machine-raw for reply POSTs), review.ts PR-body reads x2, land-and-deploy 3.5c, document-release PR/MR body (two-artifact flow: the enveloped rendering is what the agent READS, the raw tempfile is what the pipeline mutates, and a write-side banner tripwire aborts any edit that leaked envelope markup), and spec's issue-title dedupe (titles are model-judged for similarity, so they're ingress). Title-prefix rewrites and state-routing fetches are mechanical, not ingress — deliberately not enveloped. test/tracker-guard-wiring.test.ts is the CI tripwire: raw tracker-text reads outside the guard fail the suite unless carried by a reasoned SCANNER_EXEMPT entry; exemptions are liveness-checked so a moved site forces a re-audit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a5833c413f |
v1.57.10.0 feat: Codex review default-on across review/ship/plan/docs (#1966)
* feat(config): make codex_reviews the master switch for all Codex review Broaden the codex_reviews doc to describe it governing /review, /ship, /document-release, plan reviews, and /autoplan. Reject invalid values on set (preserving the existing value) so a typo can never silently flip paid Codex calls on or off. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(review): Codex review default-on across review/ship/plan/docs Add a shared codexPreflight() helper (constants.ts) that, in one bash block, reads codex_reviews, sources gstack-codex-probe, checks install + auth, and echoes a single canonical mode (ready/not_installed/not_authed/ disabled). All Codex resolvers route through it. - generateCodexPlanReview: opt-in question removed; the outside voice now runs automatically (default-on), falling back to a Claude subagent when Codex is missing/unauthed. Cross-model tension still gates on user approval (sovereignty preserved). - generateAdversarialStep: probe-based availability (install AND auth), distinct not-installed vs not-authed guidance; 200-line structured-review threshold unchanged. - generateCodexDocReview (new, wired via CODEX_DOC_REVIEW): reviews the release's docs against the shipped diff range, informational + an explicit apply-fixes decision point, never auto-edits. - autoplan Phase 0.5 now honors codex_reviews=disabled so the switch is truly global. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(docs): regenerate SKILL docs + refresh ship golden Output of gen:skill-docs for the Codex-default-on resolver/template changes. Refreshes the factory-ship golden fixture (codex-host output unchanged — resolvers strip for the codex host). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(infra): widen size-budget guards for default-on Codex outside-voice The codexPreflight() block + CODEX_MODE branch prose (replacing the smaller opt-in question) grows plan-ceo/eng/devex-review and review by 5-7% over baseline. Each bump carries a comment justifying it as intentional capability, not slop. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: guard Codex default-on + config reject-on-set skill-validation: assert plan reviews no longer carry the opt-in question and render the default-on outside-voice, document-release carries the doc review, and the codex host strips all of it. gstack-config: codex_reviews defaults to enabled, accepts enabled/disabled, and rejects an invalid value while preserving the existing one. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(test): align gstack-config tests with defaults-fallback behavior Three tests (last touched v0.13.7.0) asserted get/list print empty for unset keys, but gstack-config falls back to the documented defaults table (get returns the default, list shows the active-values block). Update the assertions to the real behavior and split out an unknown-key case that does still return empty. Pre-existing red, unrelated to codex review. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * v1.57.10.0 feat: Codex review default-on across review/ship/plan/docs Codex cross-model review now runs by default on /review, /ship, all four plan reviews, /document-release, and /autoplan, governed by one master switch (codex_reviews, default enabled). Plan-review outside voice is default-on; /document-release gets a new Codex doc-vs-diff audit; every call site detects install AND auth and falls back to a Claude subagent with a clear reason. Disable everything with: gstack-config set codex_reviews disabled Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
e722c5bf89 |
v1.57.0.0 feat: carve-guard system + carve cso/document-release/design-consultation (#1907)
* test: canonical CARVE_GUARDS registry; derive parity + size-budget from it Single source of truth for the carved-skill set + per-skill invariants (EQ1). parity-harness.ts sectioned entries and skill-size-budget.ts SECTIONS_EXTRACTED now derive from it instead of hand-maintained lists. Closes a pre-existing drift: plan-devex-review was in SECTIONS_EXTRACTED but had no sectioned parity invariant; now generated. carve-guards.ts is a pure leaf data module (import type only) to avoid an import cycle. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: shared carve-guard check fns with injectable root discoverCarvedSkills/checkOrdering/checkCompleteness take a root param so the negative tests can point the real guards at a fixture dir. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: E2 data-driven carve static ordering guard (gate) Per-PR backstop for every carved skill, one test() per skill, driven by CARVE_GUARDS staticInvariants. Generalizes + retires the ceo-specific ordering test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: E1 carve-guard completeness meta-guard (gate) Asserts filesystem carved set == CARVE_GUARDS set both directions, so a future carve without a registry entry fails CI. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: ET1 guard-of-guards negative tests (gate) Temp fixture broken 3 ways proves E1/E2 actually throw, via the injectable root. Kills the silent-pass-guard failure class. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: T2 data-driven behavioral section-loading guard (periodic) One file iterating CARVE_GUARDS, one test() per skill with GSTACK_CARVE_SKILL cost-scoping (D-CODEX A). external carves (ship, plan-ceo) keep bespoke tests; testNames aligned to their touchfile keys. Registered in touchfiles. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: defer E3 real-session carve canary to TODOS Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: carve document-release into skeleton + on-demand section Steps 2-9 (per-file audit, auto-updates, risky-change asks, CHANGELOG voice polish, cross-doc consistency, TODOS cleanup, VERSION bump, commit + PR body) move to sections/release-body.md, read on demand after the Step 1.5 coverage map. Skeleton 59,256 -> 45,797 B (-23%); union preserved. Adds the CARVE_GUARDS entry (auto-extends parity + size-budget via EQ1). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: carve design-consultation into skeleton + on-demand section Phases 3-6 (complete proposal, drill-downs, design preview, writing DESIGN.md) move to sections/proposal-and-preview.md, read on demand after product context + research. Skeleton 80,719 -> 59,229 B (-27%); union preserved. Adds the CARVE_GUARDS entry. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: carve cso into skeleton + on-demand section (security-safe) Scope-dependent audit Phases 2-11 move to sections/audit-phases.md. Mode dispatch (## Arguments, ## Mode Resolution), always-run Phases 0/1, and the Phase 12 false-positive-filtering exceptions stay ALWAYS-LOADED in the skeleton. Skeleton 79,383 -> 65,117 B (-18%); union preserved. Adds a cso CARVE_GUARDS entry with an earliest-use invariant (mustPrecedeStop): mode dispatch must appear before any STOP-Read, so a directive that decides which sections to read can't be stranded behind the STOP that reads them (codex outside-voice #6). carve-guard-checks gains the mustPrecedeStop check. parity moves cso monolith -> generated carved entry. cso-preserved.test.ts strengthened: phrases checked against the union, plus an always-loaded contract on the skeleton (dispatch + FP-filtering, codex #5). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: make redaction/taxonomy tests union-aware for cso + document-release carves The cso carve moved Secrets Archaeology (prefixes, lib/redact-patterns.ts pointer, git-history scan) into sections/audit-phases.md, and the document-release carve moved the Step 9 PR-body redaction scan into sections/release-body.md. Three content-presence tests asserted that content in the skeleton SKILL.md/.md.tmpl; they now read the skeleton+sections union (same fix as cso-preserved + parity). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: bump version and changelog (v1.57.0.0) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: address pre-landing review (codex) on the carve - cso section: add a scope-gate header so '--owasp' (and other scoped modes) run only their selected phases, not every phase bundled in the section ('execute in full' no longer overrides Mode Resolution). - carve-guard-checks: gateAfterStop now compares against the LAST STOP, not the first, so a gate stranded between two STOPs in a multi-STOP skeleton fails. - TODOS: behavioral section-loading hermeticity (verifier matches global-install path, not the fixture) — pre-existing in auq-sdk-capture.ts, deferred. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |