diogenes 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.mise/config.toml +72 -0
- data/.mise/mise.lock +179 -0
- data/.mise/tasks/update-hk-import +79 -0
- data/.release-please-config.json +1 -1
- data/.release-please-manifest.json +2 -2
- data/CHANGELOG.md +7 -0
- data/CLAUDE.md +107 -99
- data/CONTRIBUTING.md +206 -0
- data/README.md +157 -134
- data/Rakefile +15 -1
- data/Steepfile +11 -0
- data/docs/gates.md +178 -0
- data/docs/targets.md +11 -0
- data/exe/diogenes +6 -0
- data/hk.pkl +46 -0
- data/lib/diogenes/cli/init.rb +88 -0
- data/lib/diogenes/cli.rb +95 -0
- data/lib/diogenes/templates/init/artifacts/decision_record.md.erb +53 -0
- data/lib/diogenes/templates/init/diogenes.rb +13 -0
- data/lib/diogenes/templates/init/hooks/README.md +15 -0
- data/lib/diogenes/templates/init/rules/five_gates.rb +33 -0
- data/lib/diogenes/templates/init/skills/example_skill.rb +33 -0
- data/lib/diogenes/version.rb +2 -1
- data/lib/diogenes.rb +27 -2
- data/sig/generated/diogenes/cli/init.rbs +34 -0
- data/sig/generated/diogenes/cli.rbs +34 -0
- data/sig/generated/diogenes/version.rbs +5 -0
- data/sig/generated/diogenes.rbs +26 -0
- metadata +23 -9
- data/docs/context.md +0 -60
- data/docs/contributing.md +0 -228
- data/docs/dashboard.md +0 -365
- data/docs/examples.md +0 -162
- data/docs/framework.md +0 -146
- data/mise.lock +0 -48
- data/mise.toml +0 -6
data/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Contributing to Diogenes
|
|
2
|
+
|
|
3
|
+
Thanks for contributing. Diogenes has opinions — about AI, about Ruby, and about how this gem should be built. This doc explains both the practical setup and the philosophy that should guide contributions.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/meaganewaller/diogenes
|
|
9
|
+
cd diogenes
|
|
10
|
+
bundle install
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Run the test suite:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
bundle exec rspec
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Run the CLI locally:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
bundle exec exe/diogenes --help
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## The Gem Eats Its Own Cooking
|
|
26
|
+
|
|
27
|
+
Diogenes ships with its own `.diogenes/` configuration. When you're working on this gem, your AI agent is configured with skills and rules that reflect the gem's own philosophy.
|
|
28
|
+
|
|
29
|
+
After cloning, build the agent configs for your setup:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
bundle exec exe/diogenes build --all
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
This generates:
|
|
36
|
+
|
|
37
|
+
* `.claude/commands/` + `CLAUDE.md` if you use Claude Code
|
|
38
|
+
* `.cursor/rules/` if you use Cursor
|
|
39
|
+
* `.github/copilot-instructions.md` if you use Copilot
|
|
40
|
+
|
|
41
|
+
The skills available to you while developing:
|
|
42
|
+
|
|
43
|
+
| Command | What it does |
|
|
44
|
+
|---------|-------------|
|
|
45
|
+
| `/evaluate-feature` | Run a proposed gem feature through the five gates |
|
|
46
|
+
| `/new-target <name>` | Scaffold a new agent build target |
|
|
47
|
+
| `/review-philosophy` | Check whether a change aligns with Diogenes' principles |
|
|
48
|
+
| `/generate-stories` | Draft user stories for a proposed feature |
|
|
49
|
+
| `/gate-schema` | Help define options and validation for a new gate |
|
|
50
|
+
|
|
51
|
+
## Before Adding a Feature
|
|
52
|
+
|
|
53
|
+
Run the proposed feature through the gates. Yes, the gem's own gates. Yes, seriously.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
bundle exec exe/diogenes evaluate "your proposed feature description"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Commit the decision record. If a gate fails, that's either a reason not to build it, or a reason to write down why you're overriding the gate and what you're doing to mitigate the risk.
|
|
60
|
+
|
|
61
|
+
This isn't bureaucracy. It's the gem practicing what it preaches.
|
|
62
|
+
|
|
63
|
+
## Adding a New Build Target
|
|
64
|
+
|
|
65
|
+
Each build target lives in `lib/diogenes/targets/`. A target is a class that:
|
|
66
|
+
|
|
67
|
+
1. Accepts the compiled source (skills, rules, hooks, artifacts)
|
|
68
|
+
2. Knows where to write its output files
|
|
69
|
+
3. Emits idiomatic configuration for that agent
|
|
70
|
+
|
|
71
|
+
To scaffold a new target:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
bundle exec exe/diogenes /new-target <agent-name>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Or manually:
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
# lib/diogenes/targets/my_agent.rb
|
|
81
|
+
|
|
82
|
+
module Diogenes
|
|
83
|
+
module Targets
|
|
84
|
+
class MyAgent < Base
|
|
85
|
+
TARGET_NAME = :my_agent
|
|
86
|
+
|
|
87
|
+
def build
|
|
88
|
+
emit_file ".myagent/instructions.md", render_rules
|
|
89
|
+
emit_file ".myagent/commands/", render_skills
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
private
|
|
93
|
+
|
|
94
|
+
def render_rules
|
|
95
|
+
# transform source rules into target format
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def render_skills
|
|
99
|
+
# transform source skills into target format
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Register it in `lib/diogenes/targets.rb`:
|
|
107
|
+
|
|
108
|
+
```ruby
|
|
109
|
+
autoload :MyAgent, "diogenes/targets/my_agent"
|
|
110
|
+
REGISTRY[:my_agent] = Targets::MyAgent
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Add tests in `spec/diogenes/targets/my_agent_spec.rb`. See existing targets for patterns.
|
|
114
|
+
|
|
115
|
+
Update `docs/targets.md` with the new target's output format and any quirks.
|
|
116
|
+
|
|
117
|
+
## Adding a New Gate Option
|
|
118
|
+
|
|
119
|
+
Gate options are defined in `lib/diogenes/gates/`. Each gate has:
|
|
120
|
+
|
|
121
|
+
* A name (`:failure_mode`, etc.)
|
|
122
|
+
* A schema of valid options and values
|
|
123
|
+
* Validation logic that determines pass/fail
|
|
124
|
+
* A plain-English failure message
|
|
125
|
+
|
|
126
|
+
To add a new option to an existing gate:
|
|
127
|
+
|
|
128
|
+
1. Find the gate in `lib/diogenes/gates/<gate_name>.rb`
|
|
129
|
+
2. Add the option to the schema
|
|
130
|
+
3. Add validation logic
|
|
131
|
+
4. Add a descriptive failure message
|
|
132
|
+
5. Add tests in `spec/diogenes/gates/<gate_name>_spec.rb`
|
|
133
|
+
6. Update `docs/gates.md`
|
|
134
|
+
|
|
135
|
+
The failure message should:
|
|
136
|
+
|
|
137
|
+
* Say clearly what the problem is
|
|
138
|
+
* Suggest a concrete alternative or mitigation
|
|
139
|
+
* Sound like a thoughtful colleague, not a compiler error
|
|
140
|
+
|
|
141
|
+
## Code Conventions
|
|
142
|
+
|
|
143
|
+
This is a Ruby gem. It should feel like one.
|
|
144
|
+
|
|
145
|
+
* Follow the existing style — `standard` is configured and enforced in CI
|
|
146
|
+
* Error messages should be human. `Diogenes::GateFailed` should tell you what happened and what to do, not just what went wrong.
|
|
147
|
+
* Public APIs should be minimal. Less surface area means fewer things to break.
|
|
148
|
+
* If you're adding a class, it probably needs tests. If you're not sure, add them anyway.
|
|
149
|
+
* Prefer explicit over clever. The person reading this at 11pm before a deploy should understand it immediately.
|
|
150
|
+
|
|
151
|
+
## Testing
|
|
152
|
+
|
|
153
|
+
The test suite uses RSpec. Run it:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
bundle exec rspec
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Run a specific file:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
bundle exec rspec spec/diogenes/gates/failure_mode_spec.rb
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Test structure mirrors `lib/`:
|
|
166
|
+
|
|
167
|
+
```text
|
|
168
|
+
spec/
|
|
169
|
+
├── diogenes/
|
|
170
|
+
│ ├── cli/
|
|
171
|
+
│ ├── gates/
|
|
172
|
+
│ ├── targets/
|
|
173
|
+
│ └── runtime/
|
|
174
|
+
└── spec_helper.rb
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Aim for:
|
|
178
|
+
|
|
179
|
+
* Unit tests on individual gate validators
|
|
180
|
+
* Integration tests on the CLI commands (use `TTY::Testing` or similar)
|
|
181
|
+
* Target output tests that snapshot the emitted files
|
|
182
|
+
* RSpec matcher tests that verify matcher messages, not just pass/fail
|
|
183
|
+
|
|
184
|
+
## Pull Requests
|
|
185
|
+
|
|
186
|
+
* One thing per PR. Seriously.
|
|
187
|
+
* Include the decision record if you ran `diogenes evaluate` — link it in the PR description.
|
|
188
|
+
* Update `CHANGELOG.md` under `[Unreleased]`.
|
|
189
|
+
* Update docs if you changed behavior.
|
|
190
|
+
* CI must pass. Don't open a PR you know is red.
|
|
191
|
+
|
|
192
|
+
PR title format: `[gate|target|cli|runtime|docs] short description`
|
|
193
|
+
|
|
194
|
+
Examples:
|
|
195
|
+
|
|
196
|
+
* `[gate] Add :data_sensitivity option to user_verifiable gate`
|
|
197
|
+
* `[target] Add Gemini build target`
|
|
198
|
+
* `[cli] Add --dry-run flag to build command`
|
|
199
|
+
|
|
200
|
+
## Changelog
|
|
201
|
+
|
|
202
|
+
We use [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format. Add your change under `[Unreleased]` in the appropriate section: `Added`, `Changed`, `Deprecated`, `Removed`, `Fixed`, `Security`.
|
|
203
|
+
|
|
204
|
+
## Questions
|
|
205
|
+
|
|
206
|
+
Open an issue. Tag it `question`. We'll answer and, if it's a common one, fold the answer into this doc.
|
data/README.md
CHANGED
|
@@ -1,215 +1,238 @@
|
|
|
1
1
|
# Diogenes
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> *Diogenes walked through Athens with a lantern in broad daylight, looking for an honest man.*
|
|
4
4
|
|
|
5
|
-
Diogenes is a Ruby gem that
|
|
5
|
+
**Diogenes** is a Ruby gem that holds your AI features to the same light. It has two jobs:
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
1. A five-gate gauntlet decision framework that determines whether something should be an AI feature in production, or whether it's a software problem in disguise. Derived from Ruby's core principles: least surprise, programmer happiness, and human-centered design.
|
|
8
|
+
2. An agent configuration build tool that lets you write your AI agent skills, rules, and hooks once in a canonical Ruby DSL, and Diogenes builds the right configuration for every agent you use: Claude Code, Cursor, Copilot, Codex, Gemini, and more.
|
|
8
9
|
|
|
9
|
-
A mounted dashboard surfaces all of this in one place. Think Sidekiq Web for AI accountability.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Why Diogenes?
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
The current pressure to ship AI features is real. Your PM read something. Your CEO saw a demo. And you're a Ruby developer — you know how to build it, the APIs are cheap, and a proof of concept takes an afternoon.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
But Ruby has always had opinions about how software should feel, who it should serve, and what it means to write something you're proud of. Those opinions are exactly the framework we need right now.
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
**Mistake two:** Shipping them and assuming they continue to work. AI features degrade silently — documents go stale, retrieval quality drifts, models change. Traditional monitoring misses all of it because wrong-but-fluent outputs don't raise exceptions.
|
|
20
|
-
|
|
21
|
-
Diogenes addresses both.
|
|
22
|
-
|
|
23
|
-
---
|
|
17
|
+
Diogenes encodes those opinions into something you can run, test, and commit.
|
|
24
18
|
|
|
25
19
|
## Installation
|
|
26
20
|
|
|
27
21
|
```ruby
|
|
28
|
-
|
|
22
|
+
# Gemfile
|
|
23
|
+
gem "diogenes"
|
|
29
24
|
```
|
|
30
25
|
|
|
31
26
|
```bash
|
|
32
27
|
bundle install
|
|
33
|
-
rails generate diogenes:install
|
|
34
|
-
bundle exec rake db:migrate
|
|
35
28
|
```
|
|
36
29
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
## What Diogenes Does
|
|
30
|
+
Or, install globally to use the CLI anywhere:
|
|
40
31
|
|
|
41
|
-
|
|
32
|
+
```bash
|
|
33
|
+
gem install diogenes
|
|
34
|
+
```
|
|
42
35
|
|
|
43
|
-
|
|
36
|
+
## The CLI - Agent Configuration as Code
|
|
44
37
|
|
|
45
|
-
|
|
46
|
-
class SupportAssistant
|
|
47
|
-
include Diogenes::Feature
|
|
38
|
+
### Initialize a project
|
|
48
39
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
gate :human_in_loop, verified: true, max_daily_reviews: 80
|
|
52
|
-
gate :observability, logging: :full, alerting: :enabled
|
|
53
|
-
gate :necessity, alternatives_considered: true
|
|
54
|
-
|
|
55
|
-
def answer(query, agent:)
|
|
56
|
-
# your implementation
|
|
57
|
-
end
|
|
58
|
-
end
|
|
40
|
+
```bash
|
|
41
|
+
diogenes init
|
|
59
42
|
```
|
|
60
43
|
|
|
61
|
-
A feature that cannot satisfy a gate raises `Diogenes::UnsafeFeatureError` at boot with a plain-English explanation of what needs to change.
|
|
62
|
-
|
|
63
|
-
**The five gates:** `:failure_mode`, `:user_calibration`, `:human_in_loop`, `:observability`, `:necessity`. See [docs/framework.md](docs/framework.md) for full documentation.
|
|
64
44
|
|
|
65
|
-
|
|
45
|
+
Creates a `.diogenes/` directory with a canonical source structure:
|
|
66
46
|
|
|
67
|
-
|
|
47
|
+
```text
|
|
48
|
+
.diogenes/
|
|
49
|
+
├── diogenes.rb # root config — declare your targets
|
|
50
|
+
├── skills/ # things you invoke explicitly (/commands)
|
|
51
|
+
├── rules/ # standing instructions for every session
|
|
52
|
+
├── hooks/ # event-triggered behaviors
|
|
53
|
+
└── artifacts/ # output templates (decision records, ADRs, etc.)
|
|
54
|
+
```
|
|
68
55
|
|
|
69
|
-
|
|
56
|
+
### Define skills in the Ruby DSL
|
|
70
57
|
|
|
71
58
|
```ruby
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
59
|
+
# .diogenes/skills/evaluate_feature.rb
|
|
60
|
+
|
|
61
|
+
Diogenes.skill "evaluate_feature" do
|
|
62
|
+
command "/evaluate-feature"
|
|
63
|
+
description "Walk a proposed AI feature through the five Diogenes gates"
|
|
64
|
+
prompt <<~PROMPT
|
|
65
|
+
You are helping a Ruby developer evaluate whether a proposed AI feature
|
|
66
|
+
should be built. Walk them through each of the five Diogenes gates in order,
|
|
67
|
+
asking focused questions and surfacing the failure mode clearly if a gate fails.
|
|
68
|
+
|
|
69
|
+
The five gates are:
|
|
70
|
+
1. Is the failure mode acceptable at scale?
|
|
71
|
+
2. Can the average user tell when it's wrong?
|
|
72
|
+
3. Is there a real human in the loop — actually checking?
|
|
73
|
+
4. Do you have the observability to know when it's going wrong?
|
|
74
|
+
5. Is AI actually the right tool, or just the exciting one?
|
|
75
|
+
|
|
76
|
+
At the end, generate a structured decision record.
|
|
77
|
+
PROMPT
|
|
84
78
|
end
|
|
85
79
|
```
|
|
86
80
|
|
|
87
|
-
|
|
81
|
+
### Build for your agents
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
diogenes build --all # build for every configured target
|
|
85
|
+
diogenes build --target claude-code # .claude/commands/ + CLAUDE.md
|
|
86
|
+
diogenes build --target cursor # .cursor/rules/
|
|
87
|
+
diogenes build --target copilot # .github/copilot-instructions.md
|
|
88
|
+
diogenes build --target codex # codex-instructions.md + tools.json
|
|
89
|
+
diogenes build --target gemini # .gemini/instructions.md
|
|
90
|
+
```
|
|
88
91
|
|
|
89
|
-
Configure
|
|
92
|
+
Configure your targets in `diogenes.rb`:
|
|
90
93
|
|
|
91
94
|
```ruby
|
|
92
|
-
Diogenes.configure do
|
|
93
|
-
|
|
95
|
+
Diogenes.configure do
|
|
96
|
+
targets :claude_code, :cursor, :copilot
|
|
94
97
|
end
|
|
95
98
|
```
|
|
96
99
|
|
|
97
|
-
|
|
100
|
+
### Evaluate a feature interactively
|
|
98
101
|
|
|
99
|
-
|
|
102
|
+
```bash
|
|
103
|
+
diogenes evaluate "AI assistant to explain billing history"
|
|
104
|
+
```
|
|
100
105
|
|
|
101
|
-
|
|
106
|
+
Walks through each gate as a conversation:
|
|
102
107
|
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
diff_size: :major
|
|
109
|
-
)
|
|
110
|
-
```
|
|
108
|
+
```text
|
|
109
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
110
|
+
DIOGENES — Feature Gate Evaluation
|
|
111
|
+
"AI assistant to explain billing history"
|
|
112
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
111
113
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
114
|
+
Gate 1 of 5: Failure Mode
|
|
115
|
+
→ Ruby principle: Least surprise — at scale
|
|
116
|
+
|
|
117
|
+
What happens when this feature is wrong?
|
|
118
|
+
A wrong answer here is a billing dispute the user
|
|
119
|
+
can't resolve without contacting support.
|
|
120
|
+
|
|
121
|
+
Severity: [recoverable / embarrassing / catastrophic]
|
|
122
|
+
> catastrophic
|
|
123
|
+
|
|
124
|
+
✗ GATE FAILED
|
|
125
|
+
Catastrophic failure modes don't pass Gate 1.
|
|
126
|
+
Consider: is there a software solution that makes
|
|
127
|
+
the billing data clearer without AI interpretation?
|
|
128
|
+
|
|
129
|
+
Continue evaluating remaining gates? (y/N)
|
|
119
130
|
```
|
|
120
131
|
|
|
121
|
-
|
|
132
|
+
At the end, generates a decision record you can commit:
|
|
122
133
|
|
|
123
|
-
|
|
134
|
+
```bash
|
|
135
|
+
✓ Decision record written to docs/decisions/ai_billing_assistant_decision.md
|
|
136
|
+
```
|
|
124
137
|
|
|
125
|
-
|
|
138
|
+
## The Runtime Library — Gates in Your Code
|
|
126
139
|
|
|
127
|
-
|
|
140
|
+
### Include Diogenes::Gated
|
|
128
141
|
|
|
129
142
|
```ruby
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
does_not_contain("24 hours")
|
|
139
|
-
)
|
|
140
|
-
end
|
|
143
|
+
class BillingAssistant
|
|
144
|
+
include Diogenes::Gated
|
|
145
|
+
|
|
146
|
+
gate :failure_mode, severity: :catastrophic
|
|
147
|
+
gate :user_verifiable, domain: :financial
|
|
148
|
+
gate :human_in_loop, capacity: :real
|
|
149
|
+
gate :observability, monitoring: :required
|
|
150
|
+
gate :right_tool
|
|
141
151
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
expects one_of(
|
|
145
|
-
low_confidence_response,
|
|
146
|
-
routes_to_human_review
|
|
147
|
-
)
|
|
152
|
+
def explain(invoice)
|
|
153
|
+
# implementation
|
|
148
154
|
end
|
|
149
155
|
end
|
|
150
156
|
```
|
|
151
157
|
|
|
152
|
-
|
|
153
|
-
bundle exec rake diogenes:evals:run[SupportAssistant]
|
|
154
|
-
```
|
|
158
|
+
### Development — loud failures
|
|
155
159
|
|
|
156
|
-
|
|
160
|
+
In development, gate configuration is validated at class load time.
|
|
161
|
+
A failing gate raises immediately so you can't start a server with a misconfigured AI feature:
|
|
157
162
|
|
|
158
|
-
|
|
163
|
+
```text
|
|
164
|
+
Diogenes::GateFailed: Gate 1 (failure_mode) failed.
|
|
165
|
+
severity: :catastrophic — catastrophic failures are not acceptable at scale.
|
|
166
|
+
Consider a software alternative: clearer UI, explicit error states,
|
|
167
|
+
or rule-based logic with predictable output.
|
|
168
|
+
```
|
|
159
169
|
|
|
160
|
-
###
|
|
170
|
+
### Production — structured failures
|
|
161
171
|
|
|
162
|
-
|
|
172
|
+
In production, gate failures return a `Diogenes::GateResult` rather than raising:
|
|
163
173
|
|
|
164
174
|
```ruby
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
175
|
+
result = BillingAssistant.new.explain(invoice)
|
|
176
|
+
|
|
177
|
+
if result.passed?
|
|
178
|
+
render json: result.value
|
|
179
|
+
else
|
|
180
|
+
render json: { error: result.reason }, status: :service_unavailable
|
|
168
181
|
end
|
|
169
182
|
```
|
|
170
183
|
|
|
171
|
-
|
|
184
|
+
### Testing — gates are testable
|
|
172
185
|
|
|
173
|
-
|
|
186
|
+
```ruby
|
|
187
|
+
# spec/models/billing_assistant_spec.rb
|
|
188
|
+
require "diogenes/rspec"
|
|
189
|
+
|
|
190
|
+
RSpec.describe BillingAssistant do
|
|
191
|
+
it "declares all five gates" do
|
|
192
|
+
expect(described_class).to have_gate(:failure_mode)
|
|
193
|
+
expect(described_class).to have_gate(:user_verifiable)
|
|
194
|
+
expect(described_class).to have_gate(:human_in_loop)
|
|
195
|
+
expect(described_class).to have_gate(:observability)
|
|
196
|
+
expect(described_class).to have_gate(:right_tool)
|
|
197
|
+
end
|
|
174
198
|
|
|
175
|
-
|
|
199
|
+
it "fails the failure mode gate — catastrophic severity is not acceptable" do
|
|
200
|
+
expect(described_class).to fail_gate(:failure_mode)
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
```
|
|
176
204
|
|
|
177
|
-
## The
|
|
205
|
+
## The Five Gates
|
|
178
206
|
|
|
179
|
-
|
|
207
|
+
| Gate | Ruby Principle | The Question |
|
|
208
|
+
|------|---------------|--------------|
|
|
209
|
+
| 1. Failure Mode | Least surprise — at scale | What happens when it's wrong? Is that acceptable? |
|
|
210
|
+
| 2. User Verifiable | Trust — you can't trust what you can't verify | Can your average user tell when it's wrong? |
|
|
211
|
+
| 3. Human in the Loop | Human-centered design, genuinely | Is there a human checking — actually checking? |
|
|
212
|
+
| 4. Observability | Craftsmanship — you wouldn't ship a sort blind | Do you have the monitoring to know when it drifts? |
|
|
213
|
+
| 5. Right Tool | Convention over configuration | Is AI the right answer, or just the exciting one? |
|
|
180
214
|
|
|
181
|
-
|
|
182
|
-
Diogenes::AuditLog.for_feature(SupportAssistant)
|
|
183
|
-
# => [
|
|
184
|
-
# {
|
|
185
|
-
# feature: "SupportAssistant",
|
|
186
|
-
# gate_config: { failure_mode: :recoverable, ... },
|
|
187
|
-
# query_hash: "sha256:...",
|
|
188
|
-
# context_sources: ["refund-policy.md", "enterprise-terms.md"],
|
|
189
|
-
# grounding: { supported: [...], unsupported: [], contradicted: [] },
|
|
190
|
-
# verified_by: "agent@company.com",
|
|
191
|
-
# timestamp: 2024-01-15 14:23:01 UTC
|
|
192
|
-
# }
|
|
193
|
-
# ]
|
|
194
|
-
```
|
|
215
|
+
## Gate Reference
|
|
195
216
|
|
|
196
|
-
|
|
217
|
+
See [`docs/gates.md`](docs/gates.md) for the full schema of gate options and what passes/fails each gate.
|
|
197
218
|
|
|
198
|
-
|
|
219
|
+
## Agent Targets
|
|
199
220
|
|
|
200
|
-
|
|
221
|
+
See [`docs/targets.md`](docs/targets.md) for the full list of supported build targets, what files they emit, and how to add a new target.
|
|
222
|
+
|
|
223
|
+
## Contributing
|
|
201
224
|
|
|
202
|
-
|
|
225
|
+
See [`CONTRIBUTING.md`](CONTRIBUTING.md).
|
|
203
226
|
|
|
204
|
-
|
|
227
|
+
Diogenes uses itself. The `.diogenes/` directory in this repo contains the canonical source for the skills, rules, and hooks used when developing the gem. Run `diogenes build --all` after changing them.
|
|
205
228
|
|
|
206
|
-
|
|
229
|
+
## Philosophy
|
|
207
230
|
|
|
208
|
-
|
|
231
|
+
Diogenes is not anti-AI. It's pro-Ruby.
|
|
209
232
|
|
|
210
|
-
|
|
233
|
+
Ruby has always prioritized the human — the programmer, the user, the person reading the code at 2am. That priority is the framework. The gates aren't a checklist to defeat; they're the questions you'd ask if you had time to think.
|
|
211
234
|
|
|
212
|
-
|
|
235
|
+
Most AI features should be software features. The ones that survive all five gates are worth building well.
|
|
213
236
|
|
|
214
237
|
## License
|
|
215
238
|
|
data/Rakefile
CHANGED
|
@@ -7,4 +7,18 @@ Minitest::TestTask.create
|
|
|
7
7
|
|
|
8
8
|
require "standard/rake"
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
namespace :rbs do
|
|
11
|
+
desc "Generate RBS type signatures from inline annotations"
|
|
12
|
+
task :generate do
|
|
13
|
+
sh "bundle exec rbs-inline --output sig/generated lib"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
namespace :steep do
|
|
18
|
+
desc "Run Steep type checks"
|
|
19
|
+
task :check do
|
|
20
|
+
sh "bundle exec steep check"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
task default: %i[test standard rbs:generate steep:check]
|