mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-01 19:25:10 +02:00
3e3843c4a9
* feat: contributor mode, session awareness, universal RECOMMENDATION format
- Rename {{UPDATE_CHECK}} → {{PREAMBLE}} across all 10 skill templates
- Add session tracking (touch ~/.gstack/sessions/$PPID, count active sessions)
- ELI16 mode when 3+ concurrent sessions detected (re-ground user on context)
- Contributor mode: auto-file field reports to ~/.gstack/contributor-logs/
- Universal AskUserQuestion format: context → question → RECOMMENDATION → options
- Update plan-ceo-review and plan-eng-review to reference preamble baseline
- Add vendored symlink awareness section to CLAUDE.md
- Rewrite CONTRIBUTING.md with contributor workflow and cross-project testing
- Add tests for contributor mode and session awareness in generated output
- Add E2E eval for contributor mode report filing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add Enum & Value Completeness to /review critical checklist
New CRITICAL review category that traces new enum values, status strings,
and type constants through every consumer outside the diff. Catches the
class of bugs where a new value is added but not handled in all switch/case
chains, allowlists, or frontend-backend contracts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: bump v0.4.1, user-facing changelog, update qa-only template and architecture docs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add CHANGELOG style guide — user-facing, sell the feature
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: rewrite v0.4.1 changelog to be user-facing and sell the features
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add evals for RECOMMENDATION format, session awareness, and enum completeness
Free tests (Tier 1): RECOMMENDATION format + session awareness in all
preamble SKILL.md files, enum completeness checklist structure and CRITICAL
classification.
E2E eval: /review catches missed enum handlers when a new status value
is added but not handled in case/switch and notify methods.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add E2E eval for session awareness ELI16 mode
Stubs _SESSIONS=4, gives agent a decision point on feature/add-payments
branch, verifies the output re-grounds the user with project, branch,
context, and RECOMMENDATION — the ELI16 mode behavior for 3+ sessions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: contributor mode eval marked FAIL due to expected browse error
The test intentionally runs a nonexistent binary to trigger contributor
mode. The session runner's browse error detection catches "no such file
or directory...browse" and sets browseErrors, causing recordE2E to mark
passed=false. Override passed to check only exitReason since the browse
error is the expected scenario.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
7.7 KiB
7.7 KiB
Pre-Landing Review Checklist
Instructions
Review the git diff origin/main output for the issues listed below. Be specific — cite file:line and suggest fixes. Skip anything that's fine. Only flag real problems.
Two-pass review:
- Pass 1 (CRITICAL): Run SQL & Data Safety and LLM Output Trust Boundary first. These can block
/ship. - Pass 2 (INFORMATIONAL): Run all remaining categories. These are included in the PR body but do not block.
Output format:
Pre-Landing Review: N issues (X critical, Y informational)
**CRITICAL** (blocking /ship):
- [file:line] Problem description
Fix: suggested fix
**Issues** (non-blocking):
- [file:line] Problem description
Fix: suggested fix
If no issues found: Pre-Landing Review: No issues found.
Be terse. For each issue: one line describing the problem, one line with the fix. No preamble, no summaries, no "looks good overall."
Review Categories
Pass 1 — CRITICAL
SQL & Data Safety
- String interpolation in SQL (even if values are
.to_i/.to_f— usesanitize_sql_arrayor Arel) - TOCTOU races: check-then-set patterns that should be atomic
WHERE+update_all update_column/update_columnsbypassing validations on fields that have or should have constraints- N+1 queries:
.includes()missing for associations used in loops/views (especially avatar, attachments)
Race Conditions & Concurrency
- Read-check-write without uniqueness constraint or
rescue RecordNotUnique; retry(e.g.,where(hash:).firstthensave!without handling concurrent insert) find_or_create_byon columns without unique DB index — concurrent calls can create duplicates- Status transitions that don't use atomic
WHERE old_status = ? UPDATE SET new_status— concurrent updates can skip or double-apply transitions html_safeon user-controlled data (XSS) — check any.html_safe,raw(), or string interpolation intohtml_safeoutput
LLM Output Trust Boundary
- LLM-generated values (emails, URLs, names) written to DB or passed to mailers without format validation. Add lightweight guards (
EMAIL_REGEXP,URI.parse,.strip) before persisting. - Structured tool output (arrays, hashes) accepted without type/shape checks before database writes.
Enum & Value Completeness
When the diff introduces a new enum value, status string, tier name, or type constant:
- Trace it through every consumer. Read (don't just grep — READ) each file that switches on, filters by, or displays that value. If any consumer doesn't handle the new value, flag it. Common miss: adding a value to the frontend dropdown but the backend model/compute method doesn't persist it.
- Check allowlists/filter arrays. Search for arrays or
%w[]lists containing sibling values (e.g., if adding "revise" to tiers, find every%w[quick lfg mega]and verify "revise" is included where needed). - Check
case/if-elsifchains. If existing code branches on the enum, does the new value fall through to a wrong default? To do this: use Grep to find all references to the sibling values (e.g., grep for "lfg" or "mega" to find all tier consumers). Read each match. This step requires reading code OUTSIDE the diff.
Pass 2 — INFORMATIONAL
Conditional Side Effects
- Code paths that branch on a condition but forget to apply a side effect on one branch. Example: item promoted to verified but URL only attached when a secondary condition is true — the other branch promotes without the URL, creating an inconsistent record.
- Log messages that claim an action happened but the action was conditionally skipped. The log should reflect what actually occurred.
Magic Numbers & String Coupling
- Bare numeric literals used in multiple files — should be named constants documented together
- Error message strings used as query filters elsewhere (grep for the string — is anything matching on it?)
Dead Code & Consistency
- Variables assigned but never read
- Version mismatch between PR title and VERSION/CHANGELOG files
- CHANGELOG entries that describe changes inaccurately (e.g., "changed from X to Y" when X never existed)
- Comments/docstrings that describe old behavior after the code changed
LLM Prompt Issues
- 0-indexed lists in prompts (LLMs reliably return 1-indexed)
- Prompt text listing available tools/capabilities that don't match what's actually wired up in the
tool_classes/toolsarray - Word/token limits stated in multiple places that could drift
Test Gaps
- Negative-path tests that assert type/status but not the side effects (URL attached? field populated? callback fired?)
- Assertions on string content without checking format (e.g., asserting title present but not URL format)
.expects(:something).nevermissing when a code path should explicitly NOT call an external service- Security enforcement features (blocking, rate limiting, auth) without integration tests verifying the enforcement path works end-to-end
Crypto & Entropy
- Truncation of data instead of hashing (last N chars instead of SHA-256) — less entropy, easier collisions
rand()/Random.randfor security-sensitive values — useSecureRandominstead- Non-constant-time comparisons (
==) on secrets or tokens — vulnerable to timing attacks
Time Window Safety
- Date-key lookups that assume "today" covers 24h — report at 8am PT only sees midnight→8am under today's key
- Mismatched time windows between related features — one uses hourly buckets, another uses daily keys for the same data
Type Coercion at Boundaries
- Values crossing Ruby→JSON→JS boundaries where type could change (numeric vs string) — hash/digest inputs must normalize types
- Hash/digest inputs that don't call
.to_sor equivalent before serialization —{ cores: 8 }vs{ cores: "8" }produce different hashes
View/Frontend
- Inline
<style>blocks in partials (re-parsed every render) - O(n*m) lookups in views (
Array#findin a loop instead ofindex_byhash) - Ruby-side
.select{}filtering on DB results that could be aWHEREclause (unless intentionally avoiding leading-wildcardLIKE)
Gate Classification
CRITICAL (blocks /ship): INFORMATIONAL (in PR body):
├─ SQL & Data Safety ├─ Conditional Side Effects
├─ Race Conditions & Concurrency ├─ Magic Numbers & String Coupling
├─ LLM Output Trust Boundary ├─ Dead Code & Consistency
└─ Enum & Value Completeness ├─ LLM Prompt Issues
├─ Test Gaps
├─ Crypto & Entropy
├─ Time Window Safety
├─ Type Coercion at Boundaries
└─ View/Frontend
Suppressions — DO NOT flag these
- "X is redundant with Y" when the redundancy is harmless and aids readability (e.g.,
present?redundant withlength > 20) - "Add a comment explaining why this threshold/constant was chosen" — thresholds change during tuning, comments rot
- "This assertion could be tighter" when the assertion already covers the behavior
- Suggesting consistency-only changes (wrapping a value in a conditional to match how another constant is guarded)
- "Regex doesn't handle edge case X" when the input is constrained and X never occurs in practice
- "Test exercises multiple guards simultaneously" — that's fine, tests don't need to isolate every guard
- Eval threshold changes (max_actionable, min scores) — these are tuned empirically and change constantly
- Harmless no-ops (e.g.,
.rejecton an element that's never in the array) - ANYTHING already addressed in the diff you're reviewing — read the FULL diff before commenting