diogenes 0.1.7 → 0.1.8
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/.agents/skills/evaluate-feature/SKILL.md +27 -0
- data/.claude/skills/evaluate-feature/SKILL.md +27 -0
- data/.cursor/rules/diogenes.mdc +40 -0
- data/.diogenes/artifacts/decision_record.md.erb +44 -0
- data/.diogenes/diogenes.rb +13 -0
- data/.diogenes/hooks/README.md +15 -0
- data/.diogenes/rules/five_gates.rb +33 -0
- data/.diogenes/skills/example_skill.rb +33 -0
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +7 -0
- data/CLAUDE.md +24 -128
- data/lib/diogenes/build/sources.rb +8 -0
- data/lib/diogenes/cli/build.rb +115 -0
- data/lib/diogenes/cli.rb +5 -2
- data/lib/diogenes/configuration.rb +38 -0
- data/lib/diogenes/targets/base.rb +58 -0
- data/lib/diogenes/targets/claude_code.rb +76 -0
- data/lib/diogenes/targets/codex.rb +59 -0
- data/lib/diogenes/targets/copilot.rb +50 -0
- data/lib/diogenes/targets/cursor.rb +59 -0
- data/lib/diogenes/targets/gemini.rb +56 -0
- data/lib/diogenes/targets.rb +20 -0
- data/lib/diogenes/version.rb +1 -1
- data/lib/diogenes.rb +13 -0
- data/sig/generated/diogenes/cli/build.rbs +40 -0
- data/sig/generated/diogenes/configuration.rbs +22 -0
- data/sig/generated/diogenes/targets/base.rbs +25 -0
- data/sig/generated/diogenes/targets/claude_code.rbs +29 -0
- data/sig/generated/diogenes/targets/codex.rbs +26 -0
- data/sig/generated/diogenes/targets/copilot.rbs +26 -0
- data/sig/generated/diogenes/targets/cursor.rbs +26 -0
- data/sig/generated/diogenes/targets/gemini.rbs +26 -0
- data/sig/generated/diogenes/targets.rbs +10 -0
- data/sig/generated/diogenes.rbs +6 -0
- metadata +28 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 59e0697472a007da996d52c2c52049bd875d48a06bb4c9747e87d60aeb81977f
|
|
4
|
+
data.tar.gz: 9802457c4c57f7fbf9aa78a97026c96b862138e2d1f4d00fe07a6ceabf174009
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: be715cb566e8eb48fad63ee0a0c4b4c53d5907a45d93b6f8366fd1a5aa2b6966b37f80d88fbe6ab64789d0756b290c82d8b4dfebb00b06568a9d48a15c09d7af
|
|
7
|
+
data.tar.gz: 743a2837f4d2a4e6f97942d36956dc08f2b69507c04e3ea19e56e33159fb75f65263c0f92e3c8429c14a75b37ba8b8fdf4c1aff1d769e85e04797f5a38915429
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# /evaluate-feature
|
|
2
|
+
|
|
3
|
+
Walk a proposed AI feature through the five Diogenes gates
|
|
4
|
+
|
|
5
|
+
## Prompt
|
|
6
|
+
|
|
7
|
+
You are helping a Ruby developer evaluate whether a proposed AI feature
|
|
8
|
+
should be built. Walk them through each of the five Diogenes gates in order,
|
|
9
|
+
asking focused questions and surfacing the failure mode clearly if a gate fails.
|
|
10
|
+
|
|
11
|
+
The feature being evaluated: {{input}}
|
|
12
|
+
|
|
13
|
+
The five gates are:
|
|
14
|
+
1. Failure Mode — What happens when this feature is wrong? Is the failure recoverable?
|
|
15
|
+
2. User Verifiable — Can the average user tell when it's wrong?
|
|
16
|
+
3. Human in the Loop — Is there a real human checking, with time and authority to intervene?
|
|
17
|
+
4. Observability — Do you have monitoring to know when it's going wrong in production?
|
|
18
|
+
5. Right Tool — Is AI the right answer, or just the exciting one?
|
|
19
|
+
|
|
20
|
+
For each gate:
|
|
21
|
+
- State the gate name and the Ruby principle it maps to
|
|
22
|
+
- Ask one focused question to determine pass or fail
|
|
23
|
+
- State the verdict clearly (PASS or FAIL)
|
|
24
|
+
- If FAIL: explain why and suggest what the right approach is instead
|
|
25
|
+
|
|
26
|
+
At the end, generate a structured decision record with a summary verdict:
|
|
27
|
+
PROCEED, REJECT, or PROCEED WITH CONDITIONS.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# /evaluate-feature
|
|
2
|
+
|
|
3
|
+
Walk a proposed AI feature through the five Diogenes gates
|
|
4
|
+
|
|
5
|
+
## Prompt
|
|
6
|
+
|
|
7
|
+
You are helping a Ruby developer evaluate whether a proposed AI feature
|
|
8
|
+
should be built. Walk them through each of the five Diogenes gates in order,
|
|
9
|
+
asking focused questions and surfacing the failure mode clearly if a gate fails.
|
|
10
|
+
|
|
11
|
+
The feature being evaluated: {{input}}
|
|
12
|
+
|
|
13
|
+
The five gates are:
|
|
14
|
+
1. Failure Mode — What happens when this feature is wrong? Is the failure recoverable?
|
|
15
|
+
2. User Verifiable — Can the average user tell when it's wrong?
|
|
16
|
+
3. Human in the Loop — Is there a real human checking, with time and authority to intervene?
|
|
17
|
+
4. Observability — Do you have monitoring to know when it's going wrong in production?
|
|
18
|
+
5. Right Tool — Is AI the right answer, or just the exciting one?
|
|
19
|
+
|
|
20
|
+
For each gate:
|
|
21
|
+
- State the gate name and the Ruby principle it maps to
|
|
22
|
+
- Ask one focused question to determine pass or fail
|
|
23
|
+
- State the verdict clearly (PASS or FAIL)
|
|
24
|
+
- If FAIL: explain why and suggest what the right approach is instead
|
|
25
|
+
|
|
26
|
+
At the end, generate a structured decision record with a summary verdict:
|
|
27
|
+
PROCEED, REJECT, or PROCEED WITH CONDITIONS.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Diogenes AI feature decision framework
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- Generated by `diogenes build --target cursor`. Edit sources in `.diogenes/` and rebuild. Do not edit directly. -->
|
|
7
|
+
|
|
8
|
+
## Rules
|
|
9
|
+
|
|
10
|
+
### five_gates
|
|
11
|
+
|
|
12
|
+
## The Five Diogenes Gates
|
|
13
|
+
|
|
14
|
+
When evaluating or building AI features, apply these gates in order.
|
|
15
|
+
A gate failure is information, not a verdict — but it must be addressed
|
|
16
|
+
before shipping.
|
|
17
|
+
|
|
18
|
+
**Gate 1 — Failure Mode** (Least surprise at scale)
|
|
19
|
+
What happens when this feature is wrong? Recoverable failures pass.
|
|
20
|
+
Embarrassing failures pass with conditions. Catastrophic failures do not pass.
|
|
21
|
+
|
|
22
|
+
**Gate 2 — User Verifiable** (Trust requires verification)
|
|
23
|
+
Can the average user tell when the output is wrong? If the user lacks
|
|
24
|
+
domain expertise to evaluate AI output, the feature creates a confidence gap.
|
|
25
|
+
|
|
26
|
+
**Gate 3 — Human in the Loop** (Human-centered design, genuinely)
|
|
27
|
+
Is there a human with time, context, and authority to actually intervene?
|
|
28
|
+
Rubber-stamping is not a loop.
|
|
29
|
+
|
|
30
|
+
**Gate 4 — Observability** (Craftsmanship — you wouldn't ship blind)
|
|
31
|
+
Do you have monitoring to detect when this feature degrades in production?
|
|
32
|
+
Silent degradation is worse than no feature.
|
|
33
|
+
|
|
34
|
+
**Gate 5 — Right Tool** (Convention over configuration)
|
|
35
|
+
Is AI the right answer, or just the exciting one? Prefer the boring,
|
|
36
|
+
predictable software alternative when it serves the same need.
|
|
37
|
+
|
|
38
|
+
## Skills
|
|
39
|
+
|
|
40
|
+
- **/evaluate-feature** — Walk a proposed AI feature through the five Diogenes gates
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# AI Feature Decision Record
|
|
2
|
+
|
|
3
|
+
**Feature:** <%= feature_name %>
|
|
4
|
+
**Date:** <%= Date.today.strftime("%Y-%m-%d") %>
|
|
5
|
+
**Evaluator:** <%= evaluator %>
|
|
6
|
+
**Verdict:** <%= verdict %>
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Gate Results
|
|
11
|
+
|
|
12
|
+
| Gate | Principle | Result | Reason |
|
|
13
|
+
|------|-----------|--------|--------|
|
|
14
|
+
| Failure Mode | Least surprise at scale | <%= gate_result(:failure_mode) %> | <%= gate_reason(:failure_mode) %> |
|
|
15
|
+
| User Verifiable | Trust requires verification | <%= gate_result(:user_verifiable) %> | <%= gate_reason(:user_verifiable) %> |
|
|
16
|
+
| Human in the Loop | Human-centered design, genuinely | <%= gate_result(:human_in_loop) %> | <%= gate_reason(:human_in_loop) %> |
|
|
17
|
+
| Observability | Craftsmanship — you wouldn't ship blind | <%= gate_result(:observability) %> | <%= gate_reason(:observability) %> |
|
|
18
|
+
| Right Tool | Convention over configuration | <%= gate_result(:right_tool) %> | <%= gate_reason(:right_tool) %> |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Verdict: <%= verdict %>
|
|
23
|
+
|
|
24
|
+
<% if verdict == "REJECT" || verdict == "PROCEED WITH CONDITIONS" -%>
|
|
25
|
+
### Recommended Alternative or Mitigation
|
|
26
|
+
|
|
27
|
+
<%= alternative.empty? ? "_No alternative or mitigation described._" : alternative %>
|
|
28
|
+
|
|
29
|
+
<% end -%>
|
|
30
|
+
<% if verdict == "PROCEED WITH CONDITIONS" -%>
|
|
31
|
+
### Conditions for Proceeding
|
|
32
|
+
|
|
33
|
+
<%= conditions.empty? ? "_No conditions specified._" : conditions %>
|
|
34
|
+
|
|
35
|
+
<% end -%>
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Notes
|
|
39
|
+
|
|
40
|
+
<%= notes.empty? ? "_No additional notes._" : notes %>
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
*Generated by [Diogenes](https://github.com/meaganewaller/diogenes)*
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Diogenes project configuration.
|
|
4
|
+
# Run `diogenes build --all` after changing source files.
|
|
5
|
+
|
|
6
|
+
Diogenes.configure do
|
|
7
|
+
name "My Project"
|
|
8
|
+
description "AI agent configuration for this project"
|
|
9
|
+
|
|
10
|
+
targets :claude_code, :cursor
|
|
11
|
+
|
|
12
|
+
artifacts_dir "docs/decisions"
|
|
13
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Hooks
|
|
2
|
+
|
|
3
|
+
Hooks define event-triggered behaviors that run automatically during agent sessions.
|
|
4
|
+
|
|
5
|
+
Add `.rb` files to this directory when you're ready. Example:
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
Diogenes.hook "run_tests_before_commit" do
|
|
9
|
+
trigger "PreToolUse"
|
|
10
|
+
description "Remind the agent to run tests before committing"
|
|
11
|
+
prompt <<~PROMPT
|
|
12
|
+
Before making any git commit, run the test suite and confirm it passes.
|
|
13
|
+
PROMPT
|
|
14
|
+
end
|
|
15
|
+
```
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Diogenes.rule "five_gates" do
|
|
4
|
+
description "The five Diogenes gates — default ruleset for AI feature decisions"
|
|
5
|
+
|
|
6
|
+
content <<~RULE
|
|
7
|
+
## The Five Diogenes Gates
|
|
8
|
+
|
|
9
|
+
When evaluating or building AI features, apply these gates in order.
|
|
10
|
+
A gate failure is information, not a verdict — but it must be addressed
|
|
11
|
+
before shipping.
|
|
12
|
+
|
|
13
|
+
**Gate 1 — Failure Mode** (Least surprise at scale)
|
|
14
|
+
What happens when this feature is wrong? Recoverable failures pass.
|
|
15
|
+
Embarrassing failures pass with conditions. Catastrophic failures do not pass.
|
|
16
|
+
|
|
17
|
+
**Gate 2 — User Verifiable** (Trust requires verification)
|
|
18
|
+
Can the average user tell when the output is wrong? If the user lacks
|
|
19
|
+
domain expertise to evaluate AI output, the feature creates a confidence gap.
|
|
20
|
+
|
|
21
|
+
**Gate 3 — Human in the Loop** (Human-centered design, genuinely)
|
|
22
|
+
Is there a human with time, context, and authority to actually intervene?
|
|
23
|
+
Rubber-stamping is not a loop.
|
|
24
|
+
|
|
25
|
+
**Gate 4 — Observability** (Craftsmanship — you wouldn't ship blind)
|
|
26
|
+
Do you have monitoring to detect when this feature degrades in production?
|
|
27
|
+
Silent degradation is worse than no feature.
|
|
28
|
+
|
|
29
|
+
**Gate 5 — Right Tool** (Convention over configuration)
|
|
30
|
+
Is AI the right answer, or just the exciting one? Prefer the boring,
|
|
31
|
+
predictable software alternative when it serves the same need.
|
|
32
|
+
RULE
|
|
33
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Example skill demonstrating the full Diogenes skill DSL.
|
|
4
|
+
# Copy this file, rename it, and customize the values for your project.
|
|
5
|
+
|
|
6
|
+
Diogenes.skill "evaluate_feature" do
|
|
7
|
+
command "/evaluate-feature"
|
|
8
|
+
description "Walk a proposed AI feature through the five Diogenes gates"
|
|
9
|
+
|
|
10
|
+
prompt <<~PROMPT
|
|
11
|
+
You are helping a Ruby developer evaluate whether a proposed AI feature
|
|
12
|
+
should be built. Walk them through each of the five Diogenes gates in order,
|
|
13
|
+
asking focused questions and surfacing the failure mode clearly if a gate fails.
|
|
14
|
+
|
|
15
|
+
The feature being evaluated: {{input}}
|
|
16
|
+
|
|
17
|
+
The five gates are:
|
|
18
|
+
1. Failure Mode — What happens when this feature is wrong? Is the failure recoverable?
|
|
19
|
+
2. User Verifiable — Can the average user tell when it's wrong?
|
|
20
|
+
3. Human in the Loop — Is there a real human checking, with time and authority to intervene?
|
|
21
|
+
4. Observability — Do you have monitoring to know when it's going wrong in production?
|
|
22
|
+
5. Right Tool — Is AI the right answer, or just the exciting one?
|
|
23
|
+
|
|
24
|
+
For each gate:
|
|
25
|
+
- State the gate name and the Ruby principle it maps to
|
|
26
|
+
- Ask one focused question to determine pass or fail
|
|
27
|
+
- State the verdict clearly (PASS or FAIL)
|
|
28
|
+
- If FAIL: explain why and suggest what the right approach is instead
|
|
29
|
+
|
|
30
|
+
At the end, generate a structured decision record with a summary verdict:
|
|
31
|
+
PROCEED, REJECT, or PROCEED WITH CONDITIONS.
|
|
32
|
+
PROMPT
|
|
33
|
+
end
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.1.8](https://github.com/meaganewaller/diogenes/compare/diogenes/v0.1.7...diogenes/v0.1.8) (2026-06-27)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **build:** emit agent config files from .diogenes/ sources :rocket: ([#15](https://github.com/meaganewaller/diogenes/issues/15)) ([d2727b6](https://github.com/meaganewaller/diogenes/commit/d2727b6fa51e0646e4042e24ad665bf740642d34))
|
|
9
|
+
|
|
3
10
|
## [0.1.7](https://github.com/meaganewaller/diogenes/compare/diogenes/v0.1.6...diogenes/v0.1.7) (2026-06-27)
|
|
4
11
|
|
|
5
12
|
|
data/CLAUDE.md
CHANGED
|
@@ -1,146 +1,42 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Agent Configuration
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
> Edit the source in `.diogenes/` and rebuild. Do not edit this file directly.
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## What This Gem Is
|
|
9
|
-
|
|
10
|
-
Diogenes is a Ruby gem with two surfaces:
|
|
11
|
-
|
|
12
|
-
**CLI / Build Tool** — Takes a canonical `.diogenes/` source (skills, rules, hooks, artifacts defined in a Ruby DSL) and builds agent-specific configuration files for Claude Code, Cursor, Copilot, Codex, Gemini, and other agents. One source of truth, many targets.
|
|
13
|
-
|
|
14
|
-
**Runtime Library** — A `Diogenes::Gated` module you include in Ruby classes that touch AI. It enforces a five-gate decision framework at class load time (loud in development, graceful in production) and provides RSpec/Minitest matchers so gate decisions live in the test suite.
|
|
15
|
-
|
|
16
|
-
The gem is grounded in a decision framework for AI features derived from Ruby's core principles: least surprise, programmer happiness, and human-centered design.
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## Codebase Map
|
|
21
|
-
|
|
22
|
-
```text
|
|
23
|
-
lib/
|
|
24
|
-
├── diogenes.rb # entry point, autoloads, top-level configure block
|
|
25
|
-
├── diogenes/
|
|
26
|
-
│ ├── cli/ # Thor-based CLI commands
|
|
27
|
-
│ │ ├── init.rb # diogenes init
|
|
28
|
-
│ │ ├── build.rb # diogenes build
|
|
29
|
-
│ │ ├── evaluate.rb # diogenes evaluate (interactive)
|
|
30
|
-
│ │ └── validate.rb # diogenes validate
|
|
31
|
-
│ ├── dsl/ # source format DSL
|
|
32
|
-
│ │ ├── skill.rb # Diogenes.skill { ... }
|
|
33
|
-
│ │ ├── rule.rb # Diogenes.rule { ... }
|
|
34
|
-
│ │ ├── hook.rb # Diogenes.hook { ... }
|
|
35
|
-
│ │ └── artifact.rb # Diogenes.artifact { ... }
|
|
36
|
-
│ ├── gates/ # one file per gate
|
|
37
|
-
│ │ ├── base.rb # shared validation interface
|
|
38
|
-
│ │ ├── failure_mode.rb # Gate 1
|
|
39
|
-
│ │ ├── user_verifiable.rb # Gate 2
|
|
40
|
-
│ │ ├── human_in_loop.rb # Gate 3
|
|
41
|
-
│ │ ├── observability.rb # Gate 4
|
|
42
|
-
│ │ └── right_tool.rb # Gate 5
|
|
43
|
-
│ ├── targets/ # one file per agent target
|
|
44
|
-
│ │ ├── base.rb # shared emit interface
|
|
45
|
-
│ │ ├── claude_code.rb # .claude/ + CLAUDE.md
|
|
46
|
-
│ │ ├── cursor.rb # .cursor/rules/
|
|
47
|
-
│ │ ├── copilot.rb # .github/copilot-instructions.md
|
|
48
|
-
│ │ ├── codex.rb # codex-instructions.md + tools.json
|
|
49
|
-
│ │ └── gemini.rb # .gemini/instructions.md
|
|
50
|
-
│ ├── runtime/ # the Gated module and GateResult
|
|
51
|
-
│ │ ├── gated.rb # include Diogenes::Gated
|
|
52
|
-
│ │ ├── gate_result.rb # structured pass/fail response
|
|
53
|
-
│ │ └── environment.rb # development vs production behaviour
|
|
54
|
-
│ └── rspec/ # RSpec matchers
|
|
55
|
-
│ └── matchers.rb # have_gate, pass_gate, fail_gate
|
|
56
|
-
spec/ # mirrors lib/
|
|
57
|
-
exe/
|
|
58
|
-
└── diogenes # CLI entry point
|
|
59
|
-
.diogenes/ # this gem's own canonical source
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
---
|
|
63
|
-
|
|
64
|
-
## Key Conventions
|
|
65
|
-
|
|
66
|
-
**Error messages are human.** When a gate fails or a configuration is invalid, the message should say what happened, why it matters, and what to do instead. Not just what went wrong — what to do about it.
|
|
67
|
-
|
|
68
|
-
**Development is loud, production is graceful.** Gate failures raise in development (`Diogenes::GateFailed`), return a `GateResult` in production. Environment is detected via `Rails.env` if present, otherwise `ENV["DIOGENES_ENV"]`.
|
|
69
|
-
|
|
70
|
-
**The DSL is the source of truth.** Nothing in `lib/` should have an opinion about what format a particular agent uses. Targets do the translation. Gates do the validation. The DSL holds the intent.
|
|
71
|
-
|
|
72
|
-
**Agent-agnostic means agent-agnostic.** When working on a target, resist any temptation to leak target-specific concepts into the DSL or gates. A skill is a skill. A rule is a rule. The target decides what to do with them.
|
|
73
|
-
|
|
74
|
-
---
|
|
3
|
+
> Generated by `diogenes build --target claude-code`. Edit sources in `.diogenes/` and rebuild. Do not edit directly.
|
|
75
4
|
|
|
76
5
|
## Available Skills
|
|
77
6
|
|
|
78
|
-
|
|
7
|
+
### /evaluate-feature
|
|
79
8
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
Walk a proposed gem feature through the five Diogenes gates. Yes, the gem evaluates itself. Produces a decision record you should commit alongside the PR.
|
|
83
|
-
|
|
84
|
-
*Use when:* You're about to build something new and want to check it against the framework before writing code.
|
|
85
|
-
|
|
86
|
-
### `/new-target <agent-name>`
|
|
87
|
-
|
|
88
|
-
Scaffold a new build target. Generates `lib/diogenes/targets/<name>.rb`, the corresponding spec file, and a stub entry in `docs/targets.md`.
|
|
89
|
-
|
|
90
|
-
*Use when:* Adding support for a new agent.
|
|
91
|
-
|
|
92
|
-
### `/review-philosophy`
|
|
93
|
-
|
|
94
|
-
Review the current working context (open files, recent changes) for alignment with Diogenes' principles. Flags anything that feels like scope creep, API surface bloat, or a violation of the "agent-agnostic source" rule.
|
|
95
|
-
|
|
96
|
-
*Use when:* You've been in the weeds for a while and want a sanity check.
|
|
97
|
-
|
|
98
|
-
### `/generate-stories <feature description>`
|
|
99
|
-
|
|
100
|
-
Draft user stories with acceptance criteria for a proposed feature, scoped to the demo or the full roadmap depending on what you specify.
|
|
101
|
-
|
|
102
|
-
*Use when:* Scoping new work before opening a PR.
|
|
103
|
-
|
|
104
|
-
### `/gate-schema <gate-name> <option-name>`
|
|
105
|
-
|
|
106
|
-
Help design the schema and validation logic for a new gate option. Asks targeted questions about what passes, what fails, and what the failure message should say.
|
|
107
|
-
|
|
108
|
-
*Use when:* Adding new options to an existing gate.
|
|
109
|
-
|
|
110
|
-
---
|
|
9
|
+
Walk a proposed AI feature through the five Diogenes gates
|
|
111
10
|
|
|
112
11
|
## Active Rules
|
|
113
12
|
|
|
114
|
-
|
|
13
|
+
### five_gates
|
|
115
14
|
|
|
116
|
-
|
|
15
|
+
## The Five Diogenes Gates
|
|
117
16
|
|
|
118
|
-
|
|
17
|
+
When evaluating or building AI features, apply these gates in order.
|
|
18
|
+
A gate failure is information, not a verdict — but it must be addressed
|
|
19
|
+
before shipping.
|
|
119
20
|
|
|
120
|
-
**
|
|
21
|
+
**Gate 1 — Failure Mode** (Least surprise at scale)
|
|
22
|
+
What happens when this feature is wrong? Recoverable failures pass.
|
|
23
|
+
Embarrassing failures pass with conditions. Catastrophic failures do not pass.
|
|
121
24
|
|
|
122
|
-
**Gate
|
|
25
|
+
**Gate 2 — User Verifiable** (Trust requires verification)
|
|
26
|
+
Can the average user tell when the output is wrong? If the user lacks
|
|
27
|
+
domain expertise to evaluate AI output, the feature creates a confidence gap.
|
|
123
28
|
|
|
124
|
-
**
|
|
29
|
+
**Gate 3 — Human in the Loop** (Human-centered design, genuinely)
|
|
30
|
+
Is there a human with time, context, and authority to actually intervene?
|
|
31
|
+
Rubber-stamping is not a loop.
|
|
125
32
|
|
|
126
|
-
|
|
33
|
+
**Gate 4 — Observability** (Craftsmanship — you wouldn't ship blind)
|
|
34
|
+
Do you have monitoring to detect when this feature degrades in production?
|
|
35
|
+
Silent degradation is worse than no feature.
|
|
127
36
|
|
|
128
|
-
|
|
37
|
+
**Gate 5 — Right Tool** (Convention over configuration)
|
|
38
|
+
Is AI the right answer, or just the exciting one? Prefer the boring,
|
|
39
|
+
predictable software alternative when it serves the same need.
|
|
129
40
|
|
|
130
|
-
```bash
|
|
131
|
-
bundle exec exe/diogenes --help
|
|
132
|
-
bundle exec exe/diogenes init
|
|
133
|
-
bundle exec exe/diogenes evaluate "some feature idea"
|
|
134
|
-
bundle exec exe/diogenes build --all
|
|
135
|
-
bundle exec rspec
|
|
136
|
-
```
|
|
137
41
|
|
|
138
42
|
---
|
|
139
|
-
|
|
140
|
-
## Rebuilding This File
|
|
141
|
-
|
|
142
|
-
This file was generated from `.diogenes/`. To regenerate after source changes:
|
|
143
|
-
|
|
144
|
-
```bash
|
|
145
|
-
bundle exec exe/diogenes build --target claude-code
|
|
146
|
-
```
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# rbs_inline: enabled
|
|
3
|
+
|
|
4
|
+
require "optparse"
|
|
5
|
+
|
|
6
|
+
module Diogenes
|
|
7
|
+
class Cli
|
|
8
|
+
class Build
|
|
9
|
+
DIOGENES_DIR = ".diogenes" #: String
|
|
10
|
+
SOURCE_SUBDIRS = %w[skills rules hooks].freeze #: Array[String]
|
|
11
|
+
|
|
12
|
+
#: (argv: Array[String], cwd: String, out: IO, err: IO, **untyped) -> Integer
|
|
13
|
+
def self.run(argv:, cwd:, out:, err:, **_opts)
|
|
14
|
+
new(argv:, cwd:, out:, err:).run
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
#: (argv: Array[String], cwd: String, out: IO, err: IO) -> void
|
|
18
|
+
def initialize(argv:, cwd:, out:, err:)
|
|
19
|
+
@argv = argv #: Array[String]
|
|
20
|
+
@cwd = cwd #: String
|
|
21
|
+
@out = out #: IO
|
|
22
|
+
@err = err #: IO
|
|
23
|
+
@build_all = false #: bool
|
|
24
|
+
@target_key = nil #: Symbol?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
#: () -> Integer
|
|
28
|
+
def run
|
|
29
|
+
parse_options
|
|
30
|
+
return usage_error unless @build_all || @target_key
|
|
31
|
+
|
|
32
|
+
diogenes_dir = File.join(@cwd, DIOGENES_DIR)
|
|
33
|
+
unless Dir.exist?(diogenes_dir)
|
|
34
|
+
@err.puts "No #{DIOGENES_DIR}/ found. Run `diogenes init` first."
|
|
35
|
+
return 1
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
Diogenes.reset!
|
|
39
|
+
load_config(diogenes_dir)
|
|
40
|
+
load_sources(diogenes_dir)
|
|
41
|
+
|
|
42
|
+
target_keys = @target_key ? [@target_key] : Diogenes.configuration.targets
|
|
43
|
+
|
|
44
|
+
if target_keys.empty?
|
|
45
|
+
@err.puts "No targets configured. Add `targets :claude_code, :cursor` to #{DIOGENES_DIR}/diogenes.rb"
|
|
46
|
+
return 1
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
sources = Diogenes::Build::Sources.new(
|
|
50
|
+
skills: Diogenes.skills,
|
|
51
|
+
rules: Diogenes.rules,
|
|
52
|
+
hooks: Diogenes.hooks,
|
|
53
|
+
artifacts: Diogenes.artifacts
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
built = build_targets(target_keys, sources)
|
|
57
|
+
print_summary(built)
|
|
58
|
+
0
|
|
59
|
+
rescue UserError => e
|
|
60
|
+
@err.puts e.message
|
|
61
|
+
1
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
#: () -> void
|
|
67
|
+
def parse_options
|
|
68
|
+
OptionParser.new do |o|
|
|
69
|
+
o.on("--all") { @build_all = true }
|
|
70
|
+
o.on("--target TARGET") { |v| @target_key = v.to_sym }
|
|
71
|
+
end.parse!(@argv.dup)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
#: () -> Integer
|
|
75
|
+
def usage_error
|
|
76
|
+
@err.puts "Usage: diogenes build --all"
|
|
77
|
+
@err.puts " diogenes build --target <target>"
|
|
78
|
+
1
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
#: (String) -> void
|
|
82
|
+
def load_config(dir)
|
|
83
|
+
config = File.join(dir, "diogenes.rb")
|
|
84
|
+
load config if File.exist?(config)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
#: (String) -> void
|
|
88
|
+
def load_sources(dir)
|
|
89
|
+
SOURCE_SUBDIRS.each do |subdir|
|
|
90
|
+
Dir.glob(File.join(dir, subdir, "**/*.rb")).sort.each { |f| load f }
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
#: (Array[Symbol], untyped) -> Array[Hash[Symbol, untyped]]
|
|
95
|
+
def build_targets(keys, sources)
|
|
96
|
+
keys.map do |key|
|
|
97
|
+
target = Targets.for(key, cwd: @cwd, out: @out)
|
|
98
|
+
files = target.build(sources:)
|
|
99
|
+
{key:, files:}
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
#: (Array[Hash[Symbol, untyped]]) -> void
|
|
104
|
+
def print_summary(built)
|
|
105
|
+
@out.puts
|
|
106
|
+
@out.puts "Build complete."
|
|
107
|
+
@out.puts
|
|
108
|
+
built.each do |b|
|
|
109
|
+
@out.puts " #{b[:key]}:"
|
|
110
|
+
b[:files].each { |f| @out.puts " wrote #{f}" }
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
data/lib/diogenes/cli.rb
CHANGED
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
# rbs_inline: enabled
|
|
3
3
|
|
|
4
4
|
require_relative "cli/init"
|
|
5
|
+
require_relative "cli/build"
|
|
5
6
|
require_relative "cli/evaluate"
|
|
6
7
|
|
|
7
8
|
module Diogenes
|
|
8
9
|
class Cli
|
|
9
10
|
COMMANDS = {
|
|
10
11
|
"init" => Init,
|
|
12
|
+
"build" => Build,
|
|
11
13
|
"evaluate" => Evaluate
|
|
12
14
|
}.freeze #: Hash[String, Class]
|
|
13
15
|
|
|
@@ -22,6 +24,7 @@ module Diogenes
|
|
|
22
24
|
@out = out #: IO
|
|
23
25
|
@err = err #: IO
|
|
24
26
|
@in = opts.fetch(:in, $stdin) #: IO
|
|
27
|
+
@cwd = opts.fetch(:cwd, Dir.pwd) #: String
|
|
25
28
|
end
|
|
26
29
|
|
|
27
30
|
#: () -> Integer
|
|
@@ -47,8 +50,8 @@ module Diogenes
|
|
|
47
50
|
|
|
48
51
|
#: (Class, Array[String]) -> Integer
|
|
49
52
|
def run_command(command_class, args)
|
|
50
|
-
opts = {in: @in}
|
|
51
|
-
command_class.run(argv: args, cwd:
|
|
53
|
+
opts = {in: @in, cwd: @cwd}
|
|
54
|
+
command_class.run(argv: args, cwd: @cwd, out: @out, err: @err, **opts)
|
|
52
55
|
end
|
|
53
56
|
|
|
54
57
|
#: () -> Integer
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# rbs_inline: enabled
|
|
3
|
+
|
|
4
|
+
module Diogenes
|
|
5
|
+
class Configuration
|
|
6
|
+
DEFAULT_ARTIFACTS_DIR = "docs/decisions" #: String
|
|
7
|
+
|
|
8
|
+
#: () -> void
|
|
9
|
+
def initialize
|
|
10
|
+
@targets = [] #: Array[Symbol]
|
|
11
|
+
@artifacts_dir = DEFAULT_ARTIFACTS_DIR #: String
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
#: (?String?) -> String?
|
|
15
|
+
def name(value = nil)
|
|
16
|
+
@name = value unless value.nil?
|
|
17
|
+
@name
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
#: (?String?) -> String?
|
|
21
|
+
def description(value = nil)
|
|
22
|
+
@description = value unless value.nil?
|
|
23
|
+
@description
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
#: (*Symbol) -> Array[Symbol]
|
|
27
|
+
def targets(*values)
|
|
28
|
+
@targets = values.flatten unless values.empty?
|
|
29
|
+
@targets
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
#: (?String?) -> String
|
|
33
|
+
def artifacts_dir(value = nil)
|
|
34
|
+
@artifacts_dir = value unless value.nil?
|
|
35
|
+
@artifacts_dir
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|