Skip to content

chore: close AI-readiness gaps (AGENTS.md, CI checks, hermetic specs, RuboCop) - #29

Open
Bhargavi Kamble (bhargavikamblepattern) wants to merge 9 commits into
masterfrom
chore/ai-readiness-common-gaps
Open

Bhargavi Kamble (bhargavikamblepattern) wants to merge 9 commits into
masterfrom
chore/ai-readiness-common-gaps

Conversation

@bhargavikamblepattern

@bhargavikamblepattern Bhargavi Kamble (bhargavikamblepattern) commented Oct 6, 2026 •

Copy link
Copy Markdown

Summary

Raises blurb's AI-readiness score (ClickUp SRE-3689, INFRA batch 5/13) by closing gaps from docs/engineering-best-practices-audit.md. This PR adds tooling, docs and tests. The only runtime change is a require-only fix in its own fix: commit (see below); otherwise lib/ gains whitespace fixes and # @type comments, and the gem's runtime dependencies and the existing .github/workflows/ci.yml are untouched (apart from a whitespace-only formatter fix). It leaves README.md alone so it doesn't conflict with #26.

Audit item Change
1 Skills .claude/skills/change-and-verify (Ruby change/verify/release flow) and change-github-workflows
2 AGENTS.md AGENTS.md (layout, commands, do-not-touch); CLAUDE.md is a symlink to it
3 ADRs docs/adr/0002 (single request path: key casing and error mapping), 0003 (campaign-type URL codes, no /v2 for SD). Both are Proposed — owner to confirm
4 Runbooks docs/runbooks/release-gem.md (the audit's one recurring task)
7 Changelog CHANGELOG.md, rebuilt from tags v0.5.2–v0.5.9 plus a note on upgrading to 0.2.0
9 CODEOWNERS * @patterninc/sre (backstage Owner: sre-comm)
10/11/21 Lint, format, complexity RuboCop 1.50 (.rubocop.yml, metrics cops on). Existing offenses are listed by file in .rubocop_todo.yml (exclude-only, no raised Max), so new code has to meet the defaults
12 Type checking RBS signatures for the public API in sig/blurb.rbs (+ sig/vendor.rbs stubs), checked by Steep 1.4 (Steepfile) as a pre-commit hook, so in make lint and Static Checks; make typecheck
13/14 Pre-commit, commits .pre-commit-config.yaml (hygiene hooks, RuboCop, Conventional Commits on commit-msg); PR Hygiene checks PR titles
16 Required checks New Static Checks and PR Hygiene PR workflows. Making them required is a separate admin step, not done here (see below)
18 License scan Trivy license scan of the installed gems in Static Checks; one documented ignore in .trivyignore.yaml: diff-lcs, a dev-only gem that is also MIT-licensed
23/25/34 Unit tests, fixtures spec/unit/ has 19 hermetic specs using WebMock stubs and JSON fixtures in spec/fixtures/. They pin request/response key casing, error mapping, 307 report download, URL shapes and bulk splitting
25 Golden files spec/unit/golden_payloads_spec.rb pins the exact JSON body of sp/hsa/sd report creates and history retrieve against spec/fixtures/golden/ (UPDATE_GOLDEN=1 regenerates)
24/32 Integration, flaky Live-API specs under spec/blurb/ are tagged :live and left out of the default run; make test-live (BLURB_LIVE=1) runs them
29 Coverage SimpleCov gate at 82% (current hermetic coverage is 82.66%)
33 Structured output make test writes rspec-junit.xml, uploaded by Static Checks
36 Toolchain .ruby-version / .tool-versions set to Ruby 2.7.8; .devcontainer/
37 Setup Makefile: bootstrap, fmt, lint, test, test-live, all
48 Lockfiles Gemfile.lock is now committed (removed from .gitignore), locked for linux and darwin on x86_64 and arm64
49 Manifest .agents/pattern-agents.json

Dev-only additions to blurb.gemspec: webmock ~> 3.18, simplecov ~> 0.22, rubocop ~> 1.50.2, steep ~> 1.4.0.

Runtime fix (own commit)

fix: require active_support and object/blank in request.rb: the gem failed to load outside Rails with ActiveSupport >= 7.1 (core_ext loaded before active_support), and Request#make_request called present? without requiring object/blank. Both requires now live in lib/blurb/request.rb and the workaround in spec/spec_helper.rb is gone. No effect where Rails has already loaded them.

Verification

  • make all passes locally: every pre-commit hook including RuboCop and Steep, then 24 examples with 0 failures and 82.66% coverage.

  • gauge-repo audit (docs/engineering-best-practices-audit.md, re-run on this branch):

    Adjusted compliance Met / Partial / Gap / N/A Critical gates
    master (before) 30.3% 8 / 4 / 21 / 16 RED
    this PR, first push 86.8% 28 / 3 / 3 / 15 RED
    this PR, now 91.2% 30 / 2 / 2 / 15 RED (only item 16, an admin setting)

    Remaining: 16 Partial (make the checks required), 49 Partial (clickup_list_id), 30 Gap (mutation testing, blocked on Ruby 3), 43 Gap (logging, runtime change).

  • check.sh: before, 2 Met / 1 Partial / 10 Gap / 5 N/A; after, 12 Met / 1 Partial (16, an admin setting) / 0 Gap / 5 N/A. Its N/A rows 10, 11, 23 and 48 appear because the script doesn't detect Ruby; the audit counts them, and this PR addresses them.

Defaults used

  • .agents/pattern-agents.json: datadog.service=blurb, datadog.env=production are the script's defaults. This gem has no runtime of its own, so the owner may want to drop them. clickup_list_id is not set.
  • Ruby 2.7.8, the latest 2.7 patch. The legacy ci.yml still pins 2.7.2.
  • Slack #sre-comm, from backstage Owner.

Follow-ups (not done here; they change behaviour or existing workflows)

  • Ruby 3 incompatibility: RequestCollection#execute_bulk_request calls execute_request(execute_request_params) with a positional hash; Ruby 3 raises ArgumentError. Fix with **execute_request_params, then remove the two downgraded diagnostics in Steepfile.
  • SnapshotRequests#download builds headers = @headers.dup["Content-Encoding"] = "gzip" and then sends @headers, so the gzip header is never sent.
  • Item 30 (mutation testing): current mutant needs Ruby >= 3.0; the last 2.7-compatible release (0.11.25) needs parser ~> 3.2.2, which conflicts with RuboCop 1.50. Add mutant-rspec after the Ruby 3 move.
  • FailedRequest, RequestThrottled and InvalidReportRequest inherit from StandardError, not Blurb::BaseException, even though the 0.5.4 commit says they should.
  • Add an upper bound on the runtime activesupport dependency (audit item 48). Left out because it changes consumers' dependency resolution.
  • Item 43: replace the puts-based log in lib/blurb/request.rb with an injectable Logger.
  • .github/workflows/ci.yml runs on every push, installs gems only, and passes unrelated RUBY_GEM_BUNDLE_TOKEN / SIDEKIQ_ENTERPRISE_TOKEN secrets. Delete it, or align it to .ruby-version, now that Static Checks runs the suite. Delete the stale .travis.yml too.
  • README.md: the TravisCI badge, iserve-products links and the .env variable names in "Development" are stale (the code reads BLURB_*). Left alone to avoid conflicting with Update README.md #26. The gemspec homepage is stale as well.
  • Pay down .rubocop_todo.yml in small PRs (about 860 existing offenses, about 816 auto-correctable).
  • Record VCR cassettes for the live suite (items 23/25), so more of the API runs without credentials.
  • Items 15/16: after this PR's checks have reported, an admin applies the ai-readiness-branch-rules ruleset (the dry run is ready) to require Static Checks and PR Hygiene on master.

Open questions for the owner

  1. ClickUp list for agent-dispatched work on this repo (clickup_list_id in .agents/pattern-agents.json)?
  2. CODEOWNERS team: is @patterninc/sre right for backstage owner sre-comm?
  3. ADRs 0002/0003: please confirm (or correct) the reasoning and change their status to Accepted.
  4. Ruby version: 2.7 is EOL. Is 2.7.8 the right pin for consumers, or should CI also test a 3.x?
  5. Datadog fields in the manifest: keep or remove for a library?

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ense scan in Static Checks

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…kill

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 6, 2026 07:09
@wiz-55ccc8b716

wiz-55ccc8b716 Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Wiz Scan Summary

Scanner Findings
Vulnerability Finding Vulnerabilities -
Data Finding Sensitive Data -
Secret Finding Secrets -
IaC Misconfiguration IaC Misconfigurations -
SAST Finding SAST Findings -
Software Management Finding Software Management Findings 1 High
Total 1 High

View scan details in Wiz

To detect these findings earlier in the dev lifecycle, try the Wiz Code extension for VS Code, JetBrains, or Visual Studio.

Comment thread Gemfile.lock
crack (1.0.1)
bigdecimal
rexml
diff-lcs (1.6.2)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

High Software Management Finding - Software License

Code library with Restrictive license

More Details

Code library diff-lcs version 1.6.2 has GPL-2.0-or-later license, categorized as Restrictive, its use may cause a supply chain licensing issue.

Remediation guidance

  • Review the license terms to understand its specific rules.
  • If needed, Replace this component immediately with an alternative using a permissive license (e.g., MIT, Apache 2.0).
  • Consult your legal team if the component is business-critical or the terms are unclear.

To ignore this finding as an exception, reply to this conversation with #wiz_ignore reason

If you'd like to ignore this finding in all future scans, add an exception in the .wiz file (learn more) or create an Ignore Rule (learn more).


To get more details on how to remediate this issue using AI, reply to this conversation with #wiz remediate

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Agent documentation contains incorrect HTTP and exception-hierarchy guidance, and the RuboCop baseline contradicts the stated exclude-only configuration.

Review effort: Balanced
Findings: 1 Medium severity · 3 Low severity

Open (4)
What changed in this PR

Adds AI-readiness documentation, reproducible tooling, CI checks, and hermetic tests without changing runtime behavior.

Changes:

  • Adds agent guidance, ADRs, release documentation, and changelog history.
  • Introduces RuboCop, pre-commit, locked tooling, and PR workflows.
  • Separates hermetic unit tests from opt-in live API tests.
File Description
.agents/​pattern-agents.json Adds agent dispatch metadata.
.claude/​skills/​change-and-verify/​SKILL.md Documents Ruby change and release flow.
.claude/​skills/​change-github-workflows/​SKILL.md Documents workflow-change guidance.
.devcontainer/​devcontainer.json Adds a Ruby development container.
.github/​CODEOWNERS Routes repository reviews.
.github/​workflows/​ci.yml Removes trailing whitespace.
.github/​workflows/​pr-hygiene.yml Validates PR titles.
.github/​workflows/​static-checks.yml Runs linting, tests, and license scanning.
.gitignore Tracks the lockfile and ignores outputs.
.pre-commit-config.yaml Adds hygiene and RuboCop hooks.
.rubocop.yml Configures Ruby linting and metrics.
.rubocop_todo.yml Baselines existing offenses.
.ruby-version Pins Ruby 2.7.8.
.tool-versions Pins Ruby for tool managers.
.trivyignore.yaml Documents the diff-lcs license exception.
AGENTS.md Adds repository guidance.
CHANGELOG.md Reconstructs release history.
CLAUDE.md Links Claude guidance to AGENTS.md.
Gemfile.lock Locks development dependencies and platforms.
Makefile Adds setup, lint, and test commands.
blurb.gemspec Adds test and lint dependencies.
docs/​adr/​0000-template.md Adds an ADR template.
docs/​adr/​0001-record-architecture-decisions.md Establishes ADR usage.
docs/​adr/​0002-single-request-path-with-key-case-conversion.md Documents request behavior.
docs/​adr/​0003-campaign-type-codes-in-resource-urls.md Documents campaign URL construction.
docs/​adr/​README.md Indexes ADRs.
docs/​runbooks/​README.md Indexes runbooks.
docs/​runbooks/​release-gem.md Documents gem releases.
lib/​blurb/​base_class.rb Applies whitespace formatting.
lib/​blurb/​errors/​request_throttled.rb Applies whitespace formatting.
lib/​blurb/​request.rb Applies whitespace formatting.
spec/​blurb/​product_ad_requests_spec.rb Removes trailing whitespace.
spec/​fixtures/​create_response.json Adds a create-response fixture.
spec/​fixtures/​error_bad_request.json Adds a bad-request fixture.
spec/​fixtures/​error_invalid_report.json Adds a report-error fixture.
spec/​fixtures/​error_throttled.json Adds a throttling fixture.
spec/​fixtures/​profiles.json Adds profile fixtures.
spec/​fixtures/​sp_campaigns.json Adds campaign fixtures.
spec/​fixtures/​token.json Adds a fake OAuth fixture.
spec/​spec_helper.rb Separates hermetic and live suites.
spec/​support/​fixtures.rb Adds fixture loading support.
spec/​unit/​account_spec.rb Tests OAuth and profile behavior.
spec/​unit/​request_collection_spec.rb Tests URL and bulk-request behavior.
spec/​unit/​request_spec.rb Tests request conversion and errors.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .rubocop_todo.yml
Comment on lines +491 to +493
Style/RaiseArgs:
EnforcedStyle: compact

# Changing code in blurb

1. Read `AGENTS.md` (layout, what must not change) and `docs/adr/` before touching `lib/blurb/request.rb`, `lib/blurb/base_class.rb` or `lib/blurb/request_collection*.rb`.
2. Make the change. Every HTTP call goes through `Blurb::Request` (ADR 0002); don't call `RestClient` elsewhere.
Comment thread AGENTS.md
- `lib/blurb/request.rb` — the single HTTP path (`rest-client`). Camel-cases request keys, snake-cases response keys, maps HTTP errors to `lib/blurb/errors/*`. See `docs/adr/0002-*`.
- `lib/blurb/request_collection*.rb` — generic list/retrieve/create/update/delete over a resource URL; `RequestCollectionWithCampaignType` adds the `sp`/`hsa`/`sd` path segment. See `docs/adr/0003-*`.
- `lib/blurb/*_requests.rb` — endpoint-specific collections (reports, snapshots, history, suggested keywords).
- `lib/blurb/errors/` — `FailedRequest`, `RequestThrottled`, `InvalidReportRequest` (all inherit `BaseException`).
Comment on lines +12 to +19
`lib/blurb/request.rb` is the only code that talks HTTP:

- Request payloads and query params are camel-cased (`camelcase_keys`), except keys that are already all upper case, which pass through. `Date`/`Time`/`ActiveSupport::TimeWithZone` values are formatted as `YYYYMMDD`.
- Responses are JSON-parsed and every key becomes a snake_case **symbol** (`underscore_keys`).
- `429` raises `Blurb::RequestThrottled`; `406` on a report URL raises `Blurb::InvalidReportRequest`; any other error response raises `Blurb::FailedRequest` with the parsed body. A `307` is followed with a plain `GET` and returned **unparsed** — that is how report and snapshot downloads work.
- `GET` requests set `max_redirects: 0` so the `307` reaches the rescue above.

`RequestCollection`, `Account` and the `*_requests.rb` classes only build URLs, headers and payloads and call `Request#make_request`.
The gem failed to load outside Rails with ActiveSupport >= 7.1 (core_ext
loaded before active_support) and Request#make_request called present?
without requiring object/blank. The spec helper worked around both; the
requires now live in lib/blurb/request.rb and the workaround is gone.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Pins the exact JSON body sent for sp/hsa/sd report creates and history
retrieve under spec/fixtures/golden/ (UPDATE_GOLDEN=1 regenerates).
Raises the SimpleCov gate to 82% (current 82.66%).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
sig/blurb.rbs types Blurb, Account, Profile, the request collections and
error classes; sig/vendor.rbs stubs rest-client, oauth2 and ActiveSupport.
steep check runs as a pre-commit hook (so in make lint and Static Checks)
and as make typecheck. lib/ only gains '# @type var' comments and one
whitespace fix; no runtime change. The positional-hash call in
RequestCollection#execute_bulk_request is reported as information, not
an error, pending a Ruby 3 follow-up.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants