Mission: remove friction, not gates.
Use AI to speed research, produce better first drafts, and surface facts.
Never skip CI or reviewer sign-off.
- safer Rails changes
- repeatable reviews
- fewer context losses
- private memory that keeps improving
If it does not reduce mistakes, turn it off.
The Old Way
The old workflow was simple:
ask a model a question
copy the answer
paste into editor
manually fix context gaps
repeatThat works for small tasks.
It breaks down for real Rails work.
The missing context is predictable:
- repo conventions
- ownership mapping
- migration review expectations
- mandatory checks before merge
The result is familiar:
- good first draft
- wrong defaults
- missing tests
- too much confidence
- not enough repo memory
I still use chat. But I do not treat chat as the architecture.
The New Way
My current setup looks more like this:
Perplexity -> current research and primary-source trail
Claude Code -> long-context repo work
Codex -> tight edit, review, and verification loops
Superconductor -> parallel isolated implementations
gbrain -> private memory, persona, repeated preferences
llmwiki -> durable Markdown context
gstack -> repeatable workflows, QA, review, shipping
Copilot -> inline completion and delegated GitHub tasks
CodeRabbit -> PR, IDE, CLI, and Slack review signal
browser sessions -> UI proof, screenshots, console checks, canaries
GitHub Actions -> mandatory checks
human review -> final judgmentChat is fine. Chat is not architecture.
The Architecture
Keep the layers explicit:
private sources
-> redaction and source tagging
-> gbrain memory and persona
-> llmwiki durable Markdown pages
-> OpenClaw or local runtime experiments
-> gstack workflows and skills
-> Codex / Claude Code / Superconductor / Copilot / CodeRabbit
-> browser verification and production canaries
-> GitHub checks and human reviewRules:
- private sources stay private
- public research gets source links
- generated changes go through tests
- PR review stays async and reviewable
- production claims are verified on production
- team workflows stay visible in GitHub, Slack, Linear, Jira, or the PR thread
Explicit beats clever.
Hard Rules - Act, Enforce, Audit
- Never add runtime dependencies without a tested rollback.
- Never include private client details in prompts, posts, screenshots, or examples.
- Never merge AI-generated code without CI green, reviewer sign-off, and explicit acceptance.
- No green checks, no merge.
- No blog claim without build verification or a source.
- No monolithic prompt when a small wiki page can carry the context.
- No measuring success by percentage of code written by AI.
- No parallel agents touching the same files without isolated worktrees or a locked scope.
- No always-on local agent without logs, kill switch, and scoped tool access.
Enforce with:
- CI
- hooks
- evals
- review checklist
- production smoke tests
If a rule is violated: revert immediately. Document the learning. Add an eval or hook before re-merge.
Measure:
- fewer repeated explanations
- faster verified merges
- fewer review misses
- less context loss between tools
- better first drafts with less cleanup
- better handoffs between engineer, reviewer, PM, and client
Router, Not Model
Pick the tool, context, and exit criteria.
# ai/router.yml
rails_migration:
tools: [codex, claude_code]
context:
- db/schema.rb
- app/models
- recent migrations
- rollback policy
exit:
- migration runs forward and backward
- tests cover data behavior
- lock risk reviewed
- reviewer accepts rollback path
blog_post:
tools: [gbrain, perplexity, codex]
context:
- persona voice
- primary sources
- related Saeloun posts
exit:
- local Jekyll build passes
- rendered page checked
- public claims have sources
- CTA is clear
ui_change:
tools: [claude_code, codex, browser_session]
context:
- component files
- screenshots
- design notes
exit:
- system test passes
- desktop and mobile screenshots reviewed
- console is cleanRule: route the work -> constrain context -> define done.
Source Trust Levels
Every source is not equal.
I use a simple ladder:
level 0 -> private raw source, never sent out
level 1 -> redacted local note
level 2 -> llmwiki page with source refs
level 3 -> public primary source
level 4 -> generated summary
level 5 -> unsourced model outputThe rule: lower number wins.
For a Rails API change, I want the PR, commit, test, or docs.
For a client workflow, I want a redacted local note, not a chat transcript.
For a blog post, I want public sources for public claims.
Generated summaries are useful. They are not truth.
Perplexity Is For Research
I use Perplexity when I need current public context.
Good examples:
- “What changed in this Rails release?”
- “Which browser behavior changed?”
- “What are people using for this API?”
- “Find primary sources for this library behavior.”
- “Show me recent security discussion around this dependency.”
Perplexity is discovery only. Always attach the primary source before claiming something.
The useful output is not the prose. The useful output is the trail:
question -> candidate sources -> docs/issues/PRs -> final opinionFor Rails posts, that means I still want the primary source:
- Rails PR
- Rails commit
- Rails docs
- release note
- framework test
AI search finds the trail. I still read the patch.
Claude Code Is For Longer Repo Work
Claude Code is for long-context repo work.
I like it for:
- multi-file refactors
- reading a large codebase
- following a bug across models, jobs, controllers, and tests
- drafting a first implementation plan
- checking whether a proposed abstraction fits the existing shape
Do not ask it to “just fix it” and walk away.
The better workflow is:
explain goal
ask it to inspect first
make it summarize risk
apply a small patch
run tests
review diff
repeatFor Rails, the risk list is predictable:
- database changes
- callbacks
- authorization
- background jobs
- mailers
- API compatibility
- rollback path
- test coverage
It works best when it can read enough of the repo to stop guessing.
Codex Is For Focused Execution
Codex is where I like tight coding loops.
Good tasks:
- fix a failing spec
- update a helper
- write a small script
- review a branch
- patch a Jekyll include
- inspect a GitHub Actions failure
- make a narrow Rails change and verify it
The shape is usually:
inspect
patch
run targeted verification
review diff
shipFor example, when similar posts were not rendering on the blog, the issue was not “AI recommendations are bad”. The issue was boring:
generated YAML key: 2026-04-28-rails-authorization-patterns-complete-guide
Jekyll page.slug: rails-authorization-patterns-complete-guideThe fix was also boring:
{% assign page_file_slug = page.path | split: "/" | last | remove: ".md" %}
{% assign similar_post_slugs = site.data.similar_posts[page.slug] | default: site.data.similar_posts[page_file_slug] %}
{% if similar_post_slugs %}
{% for similar_slug in similar_post_slugs %}
{% assign similar_post = site.posts | where_exp: "post", "post.slug == similar_slug or post.path contains similar_slug or post.id contains similar_slug" | first %}
{% endfor %}
{% endif %}Then verify:
bundle exec jekyll build
rg "Similar Posts You Might Like" _site/2026/04/28/rails-authorization-patterns-complete-guide/index.htmlThat is the loop I want.
Not magic. Just faster inspection and tighter execution.
gbrain Is My Private Memory
gbrain is the part that makes the setup personal.
It stores distilled signals from my work:
- writing style
- review preferences
- repeated Rails opinions
- common risk patterns
- blog publishing rules
- team workflows
- mentor-style guidance
I do not want every assistant to start from zero.
Before:
"Write a LinkedIn post about this blog post."After:
bun run ~/.gbrain/src/cli.ts persona voice --for blog
bun run ~/.gbrain/src/cli.ts query \
"How should I talk about private AI setup for Rails teams?" \
--synth trueThis gives the assistant better defaults:
- direct tone
- no corporate filler
- Rails-specific examples
- verification before claims
- privacy boundaries
- practical CTA
AI has a strong default voice. I want mine.
llmwiki Is For Durable Knowledge
Chat history is not a knowledge base.
It is too loose. It is hard to diff. It is hard to review. It is easy to lose.
For durable knowledge, I prefer Markdown.
The local llmwiki layer turns private signals into structured pages that future assistants can read.
Do not dump everything into one giant prompt. Keep a small, reviewable knowledge layer:
sources/
gbrain-export-manifest.md
rails-review-preferences.md
blog-publishing-checklist.md
private-ai-boundaries.md
client-data-redaction-rules.mdAgents should ask for the relevant page instead of rediscovering the same rule again.
Memory Needs Promotion
Do not put every thought into permanent memory.
Promote it.
raw signal
-> redacted note
-> repeated pattern
-> llmwiki page
-> AGENTS.md / CLAUDE.md / CodeRabbit instruction
-> test, hook, or CI ruleExamples:
- one review comment stays in the PR
- three similar review comments become a wiki rule
- ten similar review comments become a repo instruction
- a risky repeated miss becomes a test or hook
That is the compounding loop.
Memory is not “store more”. Memory is “promote the right thing”.
gstack Turns Memory Into Workflow
gbrain remembers.
gstack applies.
That is the difference.
For writing:
gbrain voice -> draft -> persona review -> SEO check -> publish -> production verificationFor coding:
inspect repo -> patch -> run tests -> review diff -> CI -> CodeRabbit -> human review -> merge -> deploy verificationFor security:
threat model -> secrets check -> dependency risk -> auth boundaries -> logs -> final reviewFor Rails upgrades:
read changelog -> inspect app patterns -> upgrade branch -> fix failures -> verify deploy pathThe value is repeatability. The workflow remembers the checklist. I still verify the result.
Assistant Contracts Belong In The Repo
Agents need contracts.
Not vague prompts.
I like small repo-owned contracts:
# ai/contracts/rails_change.yml
must:
- inspect existing patterns before editing
- list changed files
- list tests run
- call out database, auth, job, mailer, and API risks
- mention rollback path for migrations
forbidden:
- add runtime dependencies without approval
- change public API without compatibility note
- touch unrelated files
- claim tests passed without command output
- include client names or secrets
done_when:
- diff is small enough to review
- CI is green
- reviewer accepts risk notesThis is boring.
That is why it works.
MCP And Hooks Are Guardrails
MCP is useful because it makes tools and context explicit.
But explicit access is still access.
I want MCP servers and hooks treated like application code:
- named owner
- scoped permissions
- logs
- review before adding tools
- no secret exposure
- disabled by default for risky repos
Claude Code hooks are useful here.
Examples:
Before tool use -> block writes outside allowed paths
After edit -> run formatter or targeted test
Stop -> notify human for review
Pre-commit -> scan for secrets and private client namesMake hooks simple: prevent the obvious mistake.
OpenClaw Is An Experiment
OpenClaw is interesting because it is a runtime layer, not another chat window.
The mental model:
gbrain -> memory
gstack -> workflow
OpenClaw -> runtime, gateway, channels, tools, cronThat is why I am experimenting with it.
Useful experiments:
- persistent local assistant
- channel-based work from Slack or messages
- scheduled checks and reminders
- tool registry for repeatable actions
- local-first automation with my own model/provider choices
- feeding learnings back into gbrain and llmwiki
The risk is obvious too.
An always-on agent with files, network, browser, email, or shell access is not a toy.
So my OpenClaw rule is strict:
read-only first
small tool scope
local logs
manual approval for writes
no secrets in prompts
no private client data in public channels
kill switch before autonomyThe experiment I want is not “agent does everything”.
The experiment is: can a local runtime keep the boring work moving while the engineering gates stay intact?
Superconductor Is For Parallel Agents
Parallel agents are useful only with isolation.
I do not want five terminals guessing against the same working tree. That creates conflicts and review noise.
Shape:
one task
-> small written spec
-> two or three isolated implementations
-> live preview or test output
-> compare diffs
-> keep the best parts
-> one reviewed PRSuperconductor fits this layer.
- cloud/team setup: tickets, live previews, shared workspaces, Slack/GitHub handoffs
- native macOS setup: local parallel agents, isolated git worktrees, CLI agents as subprocesses
- supported agent shape: Claude Code, Codex, Gemini CLI, OpenCode, custom CLI agents
That distinction matters.
For client code, I prefer local-first unless the repo and data policy allow cloud execution. For internal tools or public examples, cloud previews can be useful because a PM or designer can review without pulling a branch.
My workflow:
agent A -> conservative implementation
agent B -> simpler implementation
agent C -> test-focused implementation
human -> compare risk, choose direction, own the mergeThis is structured comparison.
Rule: one final diff, one accountable human, one CI gate.
Browser Sessions Are For Proof
Rails work is not finished when code compiles.
For web apps, I want the browser involved:
- load the page
- click the real controls
- check console errors
- capture screenshots
- verify mobile layout
- test the production URL after deploy
Use Playwright, Brave/Chrome sessions, and gstack browser skills here.
For a blog post, the browser proof is simple:
build locally
open rendered page
verify title/meta/OG tags
check screenshots or diagrams
verify production URL after mergeFor a Rails feature, the proof is stricter:
seed realistic data
run the system flow
check logs and console
verify authorization boundaries
capture before/after screenshots
run the same smoke test on production after deployLet the assistant click through the form. Let it compare screenshots. Let it inspect console errors.
Do not let it decide the feature is good.
Copilot Has Two Jobs Now
Copilot has split into two useful modes: inline help and delegated GitHub work.
So I split the mental model:
Copilot inline -> typing speed
Copilot cloud agent -> delegated GitHub taskInline Copilot is good for:
- repetitive test setup
- small method bodies
- obvious transformations
- docs comments
Copilot cloud agent is better for:
- small issues with clear acceptance criteria
- documentation fixes
- test coverage improvements
- low-risk refactors
- branch-based work that should be reviewed in GitHub
No risky migration without:
- human-written spec
- rollback plan
- reviewer ownership
CodeRabbit Is More Than A Comment Bot
CodeRabbit sits close to the PR. That is the right time for review.
That makes it useful for:
- PR review
- pre-commit review from CLI
- IDE feedback while code is still fresh
- Slack planning and follow-up tasks
- checking whether the PR matches team standards
Repeated feedback should move into durable instructions:
AGENTS.md
CLAUDE.md
gbrain
llmwiki
CodeRabbit instructions
repo docsNot by hoping the next chat remembers. By moving repeated review signals into files and tools.
The rule is simple:
AI review can block attention.
It cannot grant approval.Team Members Should Not All Use The Same Tool
Different people need different surfaces. Do not force one AI workflow on everyone.
The better setup is role-based:
Rails engineer
-> Codex / Claude Code / Copilot / gbrain / tests
Reviewer
-> CodeRabbit / GitHub diff / gstack review / security checklist
PM or founder
-> Perplexity / Superconductor preview / issue summary / acceptance criteria
Designer
-> browser screenshots / visual diff / responsive review
Support or ops
-> incident notes / logs / gbrain retrieval / runbook updates
CTO
-> private AI policy / OpenClaw runtime policy / model access / cost and risk review / team trainingThe shared layer is the workflow:
spec -> implementation -> review -> verification -> deploy -> learningTwitter And Public Signals Are Inputs
My X/Twitter feed can be useful, but not as a blind scrape into prompts.
Treat it like any other signal source:
export archive
redact private context
tag public vs private
extract repeated opinions
distill into gbrain
write durable llmwiki pages
review before using in public contentUseful signals:
- how I explain Rails tradeoffs publicly
- repeated phrasing from posts
- topics that got useful technical discussion
- questions people ask after I share AI/Rails work
- public feedback on tooling and workflow
Not useful:
- private DMs
- client names
- internal incidents
- screenshots with secrets
- unverified claims from the feed
Do not make the assistant “sound like Twitter”. Capture public technical taste. Keep raw data local and private.
I Test The Setup With Evals
If the AI setup matters, test it.
A tiny eval beats a long opinion thread.
# ai/evals/rails_migration_review.yml
name: migration_review
input: |
Review this migration. It adds a non-null column with a default
to a large table and backfills existing rows.
must_include:
- lock risk
- backfill strategy
- rollback plan
- production safety
must_not_include:
- "ship it"
- fake benchmark numbers
- unverified Rails version claimAnd a simple Rails-flavored test:
class AiWorkflowEvalTest < ActiveSupport::TestCase
test "migration review catches production risk" do
answer = Ai::EvalRunner.call(:migration_review)
assert_includes answer, "lock"
assert_includes answer, "rollback"
assert_no_match(/ship it/i, answer)
end
endThe goal is not to make the assistant perfect.
The goal is to catch repeated failure modes:
- fake certainty
- missing rollback
- no source link
- skipped tests
- unsafe migration advice
- leaking private context
Once a failure repeats, turn it into an eval, a hook, or a checklist item.
AI Runs Need An Audit Trail
I do not want a black box.
For serious workflows, I want a record of what happened:
create_table :ai_runs do |t|
t.string :tool, null: false
t.string :task_type, null: false
t.string :prompt_sha, null: false
t.jsonb :source_refs, default: []
t.string :branch
t.string :commit_sha
t.string :merged_sha
t.integer :duration_ms
t.integer :input_tokens
t.integer :output_tokens
t.boolean :human_approved, default: false
t.timestamps
endDo not store raw prompts when they may contain private data.
Store:
- hash
- source refs
- tool
- task type
- branch
- result
- reviewer
- verification commands
That gives the CTO useful questions:
- which tasks save time?
- which tools create noisy diffs?
- which evals fail often?
- which repos need stricter policy?
- which model change increased cost?
This is Rails thinking applied to AI tooling.
Make the workflow observable.
Model Changes Are Deploys
Changing a model, retriever, prompt, tool permission, or memory schema is a deploy.
Treat it that way.
1. write down the change
2. run evals
3. test on one repo or workflow
4. compare cost, latency, and review quality
5. roll out behind a flag
6. keep rollback readyI do not want model upgrades silently changing how migrations are reviewed.
Small AI systems fail quietly. That is the dangerous part.
Case Study: Uploadcare Rewrite
This is where the setup stopped being theory.
We used this AI-assisted workflow on the Uploadcare Ruby and Rails gems.
The starting point was not “rewrite everything with AI”.
The goal was simple: stabilize the existing line first, then rewrite v5 without losing Rails taste.
Release History
uploadcare-rubyshipped the stable 4.4.1, 4.4.2, and 4.4.3 line.uploadcare-railsshipped the stable 3.4.4 line.- The v5 Ruby SDK rewrite went through public rewrite PRs like uploadcare-ruby#181, uploadcare-ruby#186, and uploadcare-ruby#187.
- The Rails v5 work moved through uploadcare-rails#157 and uploadcare-rails#158.
- The release candidates are public: uploadcare-ruby 5.0.0.rc1 and uploadcare-rails 5.0.0.rc1.
API Shape
The rewrite had one API rule: make the Ruby SDK own Uploadcare semantics, and make Rails a thin integration layer over that SDK.
That avoided the common wrapper-gem mistake. The Rails gem should not slowly become a second Uploadcare client.
Across the repos, the split became:
uploadcare-ruby: framework-agnostic client, configuration, resources, endpoint parity, errors, docs, and runnable examples.uploadcare-rails: Rails engine config, model macros, form helpers, jobs, attached objects, and Active Storage service integration.uploadcare-rails-example: compatibility pressure test for the released gems, Rails app behavior, uploader fields, Active Record, Mongoid, Active Storage, request specs, and system specs.
The Ruby SDK moved to a client-first shape. This is the main public API:
client = Uploadcare::Client.new(
public_key: ENV.fetch("UPLOADCARE_PUBLIC_KEY"),
secret_key: ENV.fetch("UPLOADCARE_SECRET_KEY")
)
file = File.open("photo.jpg", "rb") do |io|
client.files.upload(io, store: true)
end
client.files.find(uuid: file.uuid)
client.groups.create(uuids: [file.uuid])
client.project.currentFor common app code, the convenience layer returns resources and collections, and raises typed exceptions.
For complete API coverage, the raw parity layer stays explicit:
result = client.api.rest.files.info(uuid: file.uuid)
if result.success?
puts result.success
else
warn result.error_message
end
File.open("photo.jpg", "rb") do |io|
client.api.upload.files.direct(file: io, store: true)
end
client.api.upload.files.from_url(
source_url: "https://example.com/image.jpg",
async: true
)That API shape is important.
client.files is the friendly path.
client.api.rest and client.api.upload are the exact endpoint paths.
They should not pretend to be the same abstraction.
Multi-account usage also became explicit:
primary = Uploadcare::Client.new(public_key: "pk-1", secret_key: "sk-1")
secondary = Uploadcare::Client.new(public_key: "pk-2", secret_key: "sk-2")
primary.files.find(uuid: "uuid-1")
secondary.files.find(uuid: "uuid-2")That matters in real Rails apps. A tenant-specific Uploadcare project should not leak through global process configuration.
Rails Convention
The Rails gem became a Rails-shaped API over that client:
class Post < ApplicationRecord
has_uploadcare_file :cover_image
has_uploadcare_files :attachments
endForms use Rails helper names:
<%= form_with model: @post do |f| %>
<%= f.uploadcare_file_field :cover_image, img_only: true %>
<%= f.uploadcare_files_field :attachments, solution: "inline" %>
<%= f.submit %>
<% end %>The mounted values are small objects, not another SDK:
post.cover_image.uuid
post.cover_image.cdn_url
post.cover_image.store
post.cover_image.delete
post.attachments.id
post.attachments.file_urls
post.attachments.storeConfiguration became Rails-shaped:
rails g uploadcare_configThat creates config/uploadcare.yml.
Credentials can come from Rails.application.credentials.
config/uploadcare.yml owns explicit environment settings,
and credentials backfill missing keys.
Manual API usage goes through Uploadcare::Rails.client or explicit Uploadcare::Client instances.
Per-model clients stayed possible, but they became explicit too:
class Asset < ApplicationRecord
belongs_to :account
has_uploadcare_file :file, uploadcare_client: -> {
Uploadcare::Client.new(
public_key: account.uploadcare_public_key,
secret_key: account.uploadcare_secret_key
)
}
endActive Storage stayed native-looking:
uploadcare:
service: Uploadcare
public_key: <%= Rails.application.credentials.dig(:uploadcare, :public_key) %>
secret_key: <%= Rails.application.credentials.dig(:uploadcare, :secret_key) %>The app code still reads like Rails:
class User < ApplicationRecord
has_one_attached :avatar
endUnderneath,
the service uploads through client.uploads.upload,
stores Uploadcare UUID mapping in blob metadata,
and resolves downloads and variants through the service client.
The stable line mattered too.
Before cutting the v5 RC path,
we kept the existing production line moving:
uploadcare-ruby on 4.4.x,
and uploadcare-rails on 3.4.x.
Then 5-0-stable became the release branch for the rewrite,
with 5.0.0.rc1 published for both gems.
Review Lenses
The DHH review lens was simple:
- keep the Rails gem thin
- do not make a second SDK inside Rails
- make the common case obvious
- remove compatibility surface that hides the real API
- preserve programmer happiness
The fxn review lens was stricter:
- names are API contracts
- file paths and constants must follow Zeitwerk
- raw endpoint parity belongs behind explicit names like
client.api.restandclient.api.upload - convenience APIs and raw APIs must not pretend to be the same thing
- migration docs must explain the tradeoff, not just list methods
My review lens:
- small public surface
- explicit clients for multi-account usage
- after-commit side effects for Rails models
- Active Storage integration should feel like Rails
- no private keys in examples or cassettes
- CodeRabbit, CI, docs, and real examples are part of done
The review pass was also cross-repo. That was important because the API shape had to hold at every layer:
- SDK code should stay framework-agnostic.
- Rails code should feel like Rails.
- Example app code should look like what a real app team would write.
- Docs should teach the new shape, not preserve stale rewrite drafts.
- Release notes should tell users what changed without hiding breaking changes.
AI helped here, but mostly as a relentless reviewer. Codex and Claude were useful for inspecting large diffs, checking stale names, drafting migration docs, and comparing old and new examples. gbrain kept the review preferences close: thin Rails layer, explicit clients, minimal dependencies, after-commit side effects, and no secrets in public examples. CodeRabbit and GitHub checks added independent review signal.
Verification Across Repos
Verification mattered more than the rewrite story.
The Ruby repo verification covered:
mise exec -- bundle exec rspecmise exec -- bundle exec yard doc- real REST API examples run against a demo account
- real Upload API examples run against a demo account
- workflow examples for simple upload, batch upload, group creation, URL upload, large file upload, and upload progress
- stale API scans for old names like
Uploadcare::Uploader, old client flows, and removed list classes - GitHub Actions on
5-0-stableand thev5.0.0.rc1release branch - Publish Gem workflow for the release candidate
The Rails repo verification covered:
mise exec -- bundle exec rubocopmise exec -- bundle exec rspec- review threads resolved
158 examples, 0 failures- callback timing around after-commit side effects
- cache identity for UUID-only attachments before a CDN URL is known
- object-shaped SDK resources in group store flows
- Active Storage UUID mapping for previews, redirects, and remote variants
- timeout and transport failures normalized to Rails errors where appropriate
- GitHub Actions Test and Publish Gem workflows for the release candidate
The example app gave the rewrite a third kind of verification.
It pinned uploadcare-ruby and uploadcare-rails to 5.0.0.rc1,
then exercised the API from application code:
Uploadcare::Rails.clientin controllershas_uploadcare_fileandhas_uploadcare_fileson models- uploader helper APIs in forms
- Active Storage with normal
has_one_attachedandhas_many_attached - request specs and system specs around the example flows
That is the kind of cross-repo verification AI is good at accelerating. It can chase old names, compare docs to code, spot inconsistent examples, and keep PR review context close.
But the gates stayed boring: tests, lint, docs, real examples, GitHub Actions, CodeRabbit, and human review.
Outcome
That is the article in one example:
AI helped inspect, draft, compare, and clean up.
gbrain kept the preferences close.
Codex and Claude helped with focused edits and review loops.
CodeRabbit added PR review signal.
GitHub checks and local test output still decided release readiness.The important part: the AI setup did not replace the Rails taste.
It made the Rails taste easier to apply repeatedly.
For my setup, CodeRabbit, Copilot, Codex, Claude Code, and gstack all feed into the same quality loop.
But GitHub checks and human review still matter.
GitHub Checks Are Not Optional
This is where many AI workflows go wrong. They make code generation faster, then weaken the gates.
That is backwards.
If AI writes more code, verification needs to get stricter.
For Rails projects, I want:
- test suite
- linting
- security checks
- link checks for blog/docs
- deploy preview
- production verification after merge
- clear PR description
- review history
For a blog post, that can be:
bundle exec jekyll build
rg "expected text" _site/path/to/post/index.html
gh pr checks --watch
curl -L https://blog.saeloun.com/path/to/post/For an app, that can be:
bin/rails test
bin/rails test:system
bundle exec rubocop
bundle exec brakeman
bin/rails db:migrate:statusNo green checks, no merge.
Put it in the PR template:
## AI-assisted work
- [ ] AI tool used:
- [ ] Source files inspected:
- [ ] Tests run:
- [ ] CI green:
- [ ] `ai_runs` entry or task link:
- [ ] Reviewer accepted risk notes:
- [ ] Migration rollback checked:
- [ ] Production smoke plan:This makes AI work reviewable.
Not mystical. Not hidden in a chat window.
My Current Daily Loop
This is roughly how I use the setup now.
For a Rails change:
1. classify the task in ai/router.yml
2. Perplexity for outside context if needed
3. Claude Code or Codex to inspect repo shape
4. gbrain query for project/review preferences
5. narrow patch
6. tests, static checks, evals
7. CodeRabbit/Copilot/GitHub checks as extra signal
8. human review
9. merge
10. production verification
11. promote repeated learnings to llmwiki or repo instructionsFor a blog post:
1. gbrain voice
2. source discovery
3. draft with concrete examples
4. persona review
5. SEO pass
6. build locally
7. publish
8. verify production
9. share on LinkedIn/X with image or diagramFor private AI work:
1. collect signals
2. redact sensitive data
3. tag source and timestamp
4. distill into gbrain
5. export durable pages to llmwiki
6. route workflows through gstack
7. log ai_runs without raw private prompts
8. keep tests and review mandatoryThis setup is always changing.
That is the point.
First Rollout For A Rails Team
Do not start with ten agents.
Start with four weeks:
week 1 -> ai/contracts/rails_change.yml + one private memory page
week 2 -> one migration or auth eval
week 3 -> browser smoke check + CodeRabbit/Copilot policy
week 4 -> model-change checklist + metric reviewThen review:
- did merge time improve?
- did review quality improve?
- did bugs go down?
- did interruptions go down?
- did cost stay sane?
- did private data stay private?
If not, fix the workflow before adding another tool.
What I Am Optimizing For
I am not optimizing for “AI wrote 80% of the code”.
That is a bad metric.
Track useful metrics:
- median time to merge
- review comments repeated across PRs
- eval failures by category
- post-deploy incidents from unsafe migrations
- number of claims fixed during source review
- browser smoke failures caught before merge
- private data violations
- cost per accepted change
The best AI setup is not the one with the most tools.
It is the one where each tool has a clear job, the memory improves, and the gates stay boring.
What I Would Not Outsource
I do not want AI to decide:
- product direction
- final security judgment
- client-sensitive tradeoffs
- production risk acceptance
- whether a migration is safe enough
- whether a PR is ready to merge
Those are engineering decisions.
AI can help prepare them. It should not silently own them.
Where This Is Going
The setup keeps moving toward:
- more local/private context
- better redaction
- stronger llmwiki pages
- reusable gstack skills
- project-specific review policies
- better evals for coding and writing
- more production verification
The pattern is clear:
less prompt stuffing
more durable memory
less tool worship
more workflow disciplineThat is the metric: does it help the team ship reliably?
Not “what percent of code did AI write?”
Fewer handoffs. Clearer gates. Repeatable checklists.
If it does not do that, turn it off.
Related Links
- Building a Private Karpathy-Style LLM Wiki With gbrain and gstack
- Claude Code documentation
- Claude Code hooks
- OpenAI Codex cloud documentation
- GitHub Copilot cloud agent documentation
- CodeRabbit documentation
- Superconductor cloud platform
- Superconductor native macOS app
- OpenClaw documentation
- Model Context Protocol specification
- OWASP Top 10 for LLM Applications
- OpenTelemetry documentation
- Perplexity
If your Rails team is trying to set up private AI workflows, local LLMs, AI review loops, or CTO-level AI training, we can help through Saeloun.
