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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.agents/skills/evaluate-feature/SKILL.md +27 -0
  3. data/.claude/skills/evaluate-feature/SKILL.md +27 -0
  4. data/.cursor/rules/diogenes.mdc +40 -0
  5. data/.diogenes/artifacts/decision_record.md.erb +44 -0
  6. data/.diogenes/diogenes.rb +13 -0
  7. data/.diogenes/hooks/README.md +15 -0
  8. data/.diogenes/rules/five_gates.rb +33 -0
  9. data/.diogenes/skills/example_skill.rb +33 -0
  10. data/.release-please-manifest.json +1 -1
  11. data/CHANGELOG.md +7 -0
  12. data/CLAUDE.md +24 -128
  13. data/lib/diogenes/build/sources.rb +8 -0
  14. data/lib/diogenes/cli/build.rb +115 -0
  15. data/lib/diogenes/cli.rb +5 -2
  16. data/lib/diogenes/configuration.rb +38 -0
  17. data/lib/diogenes/targets/base.rb +58 -0
  18. data/lib/diogenes/targets/claude_code.rb +76 -0
  19. data/lib/diogenes/targets/codex.rb +59 -0
  20. data/lib/diogenes/targets/copilot.rb +50 -0
  21. data/lib/diogenes/targets/cursor.rb +59 -0
  22. data/lib/diogenes/targets/gemini.rb +56 -0
  23. data/lib/diogenes/targets.rb +20 -0
  24. data/lib/diogenes/version.rb +1 -1
  25. data/lib/diogenes.rb +13 -0
  26. data/sig/generated/diogenes/cli/build.rbs +40 -0
  27. data/sig/generated/diogenes/configuration.rbs +22 -0
  28. data/sig/generated/diogenes/targets/base.rbs +25 -0
  29. data/sig/generated/diogenes/targets/claude_code.rbs +29 -0
  30. data/sig/generated/diogenes/targets/codex.rbs +26 -0
  31. data/sig/generated/diogenes/targets/copilot.rbs +26 -0
  32. data/sig/generated/diogenes/targets/cursor.rbs +26 -0
  33. data/sig/generated/diogenes/targets/gemini.rbs +26 -0
  34. data/sig/generated/diogenes/targets.rbs +10 -0
  35. data/sig/generated/diogenes.rbs +6 -0
  36. metadata +28 -1
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ require "fileutils"
5
+
6
+ module Diogenes
7
+ module Targets
8
+ class Base
9
+ #: (cwd: String, out: IO) -> void
10
+ def initialize(cwd:, out:)
11
+ @cwd = cwd #: String
12
+ @out = out #: IO
13
+ end
14
+
15
+ #: (sources: untyped) -> Array[String]
16
+ def build(sources:)
17
+ raise NotImplementedError, "#{self.class}#build must be implemented"
18
+ end
19
+
20
+ protected
21
+
22
+ #: (String, String) -> String
23
+ def write(relative_path, content)
24
+ full = File.join(@cwd, relative_path)
25
+ FileUtils.mkdir_p(File.dirname(full))
26
+ File.write(full, content)
27
+ relative_path
28
+ end
29
+
30
+ #: (String) -> String
31
+ def generated_banner(target_name)
32
+ "Generated by `diogenes build --target #{target_name}`. " \
33
+ "Edit sources in `.diogenes/` and rebuild. Do not edit directly."
34
+ end
35
+
36
+ #: (Array[DSL::Skill], skills_dir: String) -> Array[String]
37
+ def write_skill_files(skills, skills_dir:)
38
+ skills.map do |skill|
39
+ slug = skill.command.to_s.sub(/\A\//, "")
40
+ write(File.join(skills_dir, slug, "SKILL.md"), skill_file_content(skill))
41
+ end
42
+ end
43
+
44
+ #: (DSL::Skill) -> String
45
+ def skill_file_content(skill)
46
+ <<~MD.strip
47
+ # #{skill.command}
48
+
49
+ #{skill.description}
50
+
51
+ ## Prompt
52
+
53
+ #{skill.prompt}
54
+ MD
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module Diogenes
5
+ module Targets
6
+ class ClaudeCode < Base
7
+ OUTPUT_PATH = "CLAUDE.md" #: String
8
+
9
+ #: (sources: untyped) -> Array[String]
10
+ def build(sources:)
11
+ skill_files = write_skill_files(sources.skills, skills_dir: ".claude/skills")
12
+ [write(OUTPUT_PATH, render(sources))] + skill_files
13
+ end
14
+
15
+ private
16
+
17
+ #: (untyped) -> String
18
+ def render(sources)
19
+ parts = [header]
20
+ parts << skills_section(sources.skills) unless sources.skills.empty?
21
+ parts << rules_section(sources.rules) unless sources.rules.empty?
22
+ parts << hooks_section(sources.hooks) unless sources.hooks.empty?
23
+ parts.join("\n\n")
24
+ end
25
+
26
+ #: () -> String
27
+ def header
28
+ <<~HEADER.strip
29
+ # Agent Configuration
30
+
31
+ > #{generated_banner("claude-code")}
32
+ HEADER
33
+ end
34
+
35
+ #: (Array[DSL::Skill]) -> String
36
+ def skills_section(skills)
37
+ lines = ["## Available Skills", ""]
38
+ skills.each do |skill|
39
+ lines << "### #{skill.command}"
40
+ lines << ""
41
+ lines << skill.description
42
+ lines << ""
43
+ end
44
+ lines.join("\n").strip
45
+ end
46
+
47
+ #: (Array[DSL::Rule]) -> String
48
+ def rules_section(rules)
49
+ lines = ["## Active Rules", ""]
50
+ rules.each do |rule|
51
+ lines << "### #{rule.name}"
52
+ lines << ""
53
+ lines << rule.content
54
+ lines << ""
55
+ lines << "---"
56
+ lines << ""
57
+ end
58
+ lines.join("\n").strip
59
+ end
60
+
61
+ #: (Array[DSL::Hook]) -> String
62
+ def hooks_section(hooks)
63
+ lines = ["## Hooks", ""]
64
+ hooks.each do |hook|
65
+ lines << "### #{hook.name}"
66
+ lines << ""
67
+ lines << "**Trigger:** #{hook.trigger}"
68
+ lines << ""
69
+ lines << hook.prompt
70
+ lines << ""
71
+ end
72
+ lines.join("\n").strip
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module Diogenes
5
+ module Targets
6
+ class Codex < Base
7
+ OUTPUT_PATH = "AGENTS.md" #: String
8
+
9
+ #: (sources: untyped) -> Array[String]
10
+ def build(sources:)
11
+ skill_files = write_skill_files(sources.skills, skills_dir: ".agents/skills")
12
+ [write(OUTPUT_PATH, render(sources))] + skill_files
13
+ end
14
+
15
+ private
16
+
17
+ #: (untyped) -> String
18
+ def render(sources)
19
+ parts = [header]
20
+ parts << rules_section(sources.rules) unless sources.rules.empty?
21
+ parts << skills_section(sources.skills) unless sources.skills.empty?
22
+ parts.join("\n\n")
23
+ end
24
+
25
+ #: () -> String
26
+ def header
27
+ <<~HEADER.strip
28
+ # Agent Instructions
29
+
30
+ > #{generated_banner("codex")}
31
+ HEADER
32
+ end
33
+
34
+ #: (Array[DSL::Rule]) -> String
35
+ def rules_section(rules)
36
+ lines = ["## Rules", ""]
37
+ rules.each do |rule|
38
+ lines << "### #{rule.name}"
39
+ lines << ""
40
+ lines << rule.content
41
+ lines << ""
42
+ end
43
+ lines.join("\n").strip
44
+ end
45
+
46
+ #: (Array[DSL::Skill]) -> String
47
+ def skills_section(skills)
48
+ lines = ["## Available commands", ""]
49
+ skills.each do |skill|
50
+ lines << "### #{skill.command}"
51
+ lines << ""
52
+ lines << skill.description
53
+ lines << ""
54
+ end
55
+ lines.join("\n").strip
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module Diogenes
5
+ module Targets
6
+ class Copilot < Base
7
+ OUTPUT_PATH = ".github/copilot-instructions.md" #: String
8
+
9
+ #: (sources: untyped) -> Array[String]
10
+ def build(sources:)
11
+ skill_files = write_skill_files(sources.skills, skills_dir: ".agents/skills")
12
+ [write(OUTPUT_PATH, render(sources))] + skill_files
13
+ end
14
+
15
+ private
16
+
17
+ #: (untyped) -> String
18
+ def render(sources)
19
+ parts = [header]
20
+ parts << rules_section(sources.rules) unless sources.rules.empty?
21
+ parts << skills_section(sources.skills) unless sources.skills.empty?
22
+ parts.join("\n\n")
23
+ end
24
+
25
+ #: () -> String
26
+ def header
27
+ "<!-- #{generated_banner("copilot")} -->"
28
+ end
29
+
30
+ #: (Array[DSL::Rule]) -> String
31
+ def rules_section(rules)
32
+ lines = ["## Always apply these rules", ""]
33
+ rules.each do |rule|
34
+ lines << rule.content
35
+ lines << ""
36
+ end
37
+ lines.join("\n").strip
38
+ end
39
+
40
+ #: (Array[DSL::Skill]) -> String
41
+ def skills_section(skills)
42
+ lines = ["## Available slash commands", ""]
43
+ skills.each do |skill|
44
+ lines << "- **#{skill.command}**: #{skill.description}"
45
+ end
46
+ lines.join("\n").strip
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module Diogenes
5
+ module Targets
6
+ class Cursor < Base
7
+ OUTPUT_PATH = ".cursor/rules/diogenes.mdc" #: String
8
+
9
+ #: (sources: untyped) -> Array[String]
10
+ def build(sources:)
11
+ skill_files = write_skill_files(sources.skills, skills_dir: ".agents/skills")
12
+ [write(OUTPUT_PATH, render(sources))] + skill_files
13
+ end
14
+
15
+ private
16
+
17
+ #: (untyped) -> String
18
+ def render(sources)
19
+ parts = []
20
+ parts << frontmatter
21
+ parts << "<!-- #{generated_banner("cursor")} -->"
22
+ parts << rules_block(sources.rules) unless sources.rules.empty?
23
+ parts << skills_block(sources.skills) unless sources.skills.empty?
24
+ parts.join("\n\n")
25
+ end
26
+
27
+ #: () -> String
28
+ def frontmatter
29
+ <<~YAML.strip
30
+ ---
31
+ description: Diogenes AI feature decision framework
32
+ alwaysApply: true
33
+ ---
34
+ YAML
35
+ end
36
+
37
+ #: (Array[DSL::Rule]) -> String
38
+ def rules_block(rules)
39
+ lines = ["## Rules", ""]
40
+ rules.each do |rule|
41
+ lines << "### #{rule.name}"
42
+ lines << ""
43
+ lines << rule.content
44
+ lines << ""
45
+ end
46
+ lines.join("\n").strip
47
+ end
48
+
49
+ #: (Array[DSL::Skill]) -> String
50
+ def skills_block(skills)
51
+ lines = ["## Skills", ""]
52
+ skills.each do |skill|
53
+ lines << "- **#{skill.command}** — #{skill.description}"
54
+ end
55
+ lines.join("\n").strip
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module Diogenes
5
+ module Targets
6
+ class Gemini < Base
7
+ OUTPUT_PATH = ".gemini/instructions.md" #: String
8
+
9
+ #: (sources: untyped) -> Array[String]
10
+ def build(sources:)
11
+ skill_files = write_skill_files(sources.skills, skills_dir: ".agents/skills")
12
+ [write(OUTPUT_PATH, render(sources))] + skill_files
13
+ end
14
+
15
+ private
16
+
17
+ #: (untyped) -> String
18
+ def render(sources)
19
+ parts = [header]
20
+ parts << rules_section(sources.rules) unless sources.rules.empty?
21
+ parts << skills_section(sources.skills) unless sources.skills.empty?
22
+ parts.join("\n\n")
23
+ end
24
+
25
+ #: () -> String
26
+ def header
27
+ <<~HEADER.strip
28
+ # Agent Instructions
29
+
30
+ > #{generated_banner("gemini")}
31
+ HEADER
32
+ end
33
+
34
+ #: (Array[DSL::Rule]) -> String
35
+ def rules_section(rules)
36
+ lines = ["## Rules", ""]
37
+ rules.each do |rule|
38
+ lines << "### #{rule.name}"
39
+ lines << ""
40
+ lines << rule.content
41
+ lines << ""
42
+ end
43
+ lines.join("\n").strip
44
+ end
45
+
46
+ #: (Array[DSL::Skill]) -> String
47
+ def skills_section(skills)
48
+ lines = ["## Skills", ""]
49
+ skills.each do |skill|
50
+ lines << "- **#{skill.command}**: #{skill.description}"
51
+ end
52
+ lines.join("\n").strip
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ # rbs_inline: enabled
3
+
4
+ module Diogenes
5
+ module Targets
6
+ KNOWN = %i[claude_code cursor copilot codex gemini].freeze #: Array[Symbol]
7
+
8
+ #: (Symbol, cwd: String, out: IO) -> Targets::Base
9
+ def self.for(key, cwd:, out:)
10
+ case key
11
+ when :claude_code then ClaudeCode.new(cwd:, out:)
12
+ when :cursor then Cursor.new(cwd:, out:)
13
+ when :copilot then Copilot.new(cwd:, out:)
14
+ when :codex then Codex.new(cwd:, out:)
15
+ when :gemini then Gemini.new(cwd:, out:)
16
+ else raise UserError, "Unknown target: #{key}. Known targets: #{KNOWN.join(", ")}"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -2,5 +2,5 @@
2
2
  # rbs_inline: enabled
3
3
 
4
4
  module Diogenes
5
- VERSION = "0.1.7" #: String
5
+ VERSION = "0.1.8" #: String
6
6
  end
data/lib/diogenes.rb CHANGED
@@ -37,6 +37,18 @@ module Diogenes
37
37
  VERSION
38
38
  end
39
39
 
40
+ #: () { () -> void } -> Configuration
41
+ def configure(&block)
42
+ @configuration ||= Configuration.new
43
+ @configuration.instance_eval(&block) if block
44
+ @configuration
45
+ end
46
+
47
+ #: () -> Configuration
48
+ def configuration
49
+ @configuration ||= Configuration.new
50
+ end
51
+
40
52
  #: (String) { () -> void } -> DSL::Skill
41
53
  def skill(name, &block)
42
54
  @skills[name] = DSL::Skill.new(name, &block)
@@ -75,6 +87,7 @@ module Diogenes
75
87
  @rules = {}
76
88
  @hooks = {}
77
89
  @artifacts = {}
90
+ @configuration = nil
78
91
  end
79
92
  end
80
93
  end
@@ -0,0 +1,40 @@
1
+ # Generated from lib/diogenes/cli/build.rb with RBS::Inline
2
+
3
+ module Diogenes
4
+ class Cli
5
+ class Build
6
+ DIOGENES_DIR: String
7
+
8
+ SOURCE_SUBDIRS: Array[String]
9
+
10
+ # : (argv: Array[String], cwd: String, out: IO, err: IO, **untyped) -> Integer
11
+ def self.run: (argv: Array[String], cwd: String, out: IO, err: IO, **untyped) -> Integer
12
+
13
+ # : (argv: Array[String], cwd: String, out: IO, err: IO) -> void
14
+ def initialize: (argv: Array[String], cwd: String, out: IO, err: IO) -> void
15
+
16
+ # : () -> Integer
17
+ def run: () -> Integer
18
+
19
+ private
20
+
21
+ # : () -> void
22
+ def parse_options: () -> void
23
+
24
+ # : () -> Integer
25
+ def usage_error: () -> Integer
26
+
27
+ # : (String) -> void
28
+ def load_config: (String) -> void
29
+
30
+ # : (String) -> void
31
+ def load_sources: (String) -> void
32
+
33
+ # : (Array[Symbol], untyped) -> Array[Hash[Symbol, untyped]]
34
+ def build_targets: (Array[Symbol], untyped) -> Array[Hash[Symbol, untyped]]
35
+
36
+ # : (Array[Hash[Symbol, untyped]]) -> void
37
+ def print_summary: (Array[Hash[Symbol, untyped]]) -> void
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,22 @@
1
+ # Generated from lib/diogenes/configuration.rb with RBS::Inline
2
+
3
+ module Diogenes
4
+ class Configuration
5
+ DEFAULT_ARTIFACTS_DIR: String
6
+
7
+ # : () -> void
8
+ def initialize: () -> void
9
+
10
+ # : (?String?) -> String?
11
+ def name: (?String?) -> String?
12
+
13
+ # : (?String?) -> String?
14
+ def description: (?String?) -> String?
15
+
16
+ # : (*Symbol) -> Array[Symbol]
17
+ def targets: (*Symbol) -> Array[Symbol]
18
+
19
+ # : (?String?) -> String
20
+ def artifacts_dir: (?String?) -> String
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ # Generated from lib/diogenes/targets/base.rb with RBS::Inline
2
+
3
+ module Diogenes
4
+ module Targets
5
+ class Base
6
+ # : (cwd: String, out: IO) -> void
7
+ def initialize: (cwd: String, out: IO) -> void
8
+
9
+ # : (sources: untyped) -> Array[String]
10
+ def build: (sources: untyped) -> Array[String]
11
+
12
+ # : (String, String) -> String
13
+ def write: (String, String) -> String
14
+
15
+ # : (String) -> String
16
+ def generated_banner: (String) -> String
17
+
18
+ # : (Array[DSL::Skill], skills_dir: String) -> Array[String]
19
+ def write_skill_files: (Array[DSL::Skill], skills_dir: String) -> Array[String]
20
+
21
+ # : (DSL::Skill) -> String
22
+ def skill_file_content: (DSL::Skill) -> String
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,29 @@
1
+ # Generated from lib/diogenes/targets/claude_code.rb with RBS::Inline
2
+
3
+ module Diogenes
4
+ module Targets
5
+ class ClaudeCode < Base
6
+ OUTPUT_PATH: String
7
+
8
+ # : (sources: untyped) -> Array[String]
9
+ def build: (sources: untyped) -> Array[String]
10
+
11
+ private
12
+
13
+ # : (untyped) -> String
14
+ def render: (untyped) -> String
15
+
16
+ # : () -> String
17
+ def header: () -> String
18
+
19
+ # : (Array[DSL::Skill]) -> String
20
+ def skills_section: (Array[DSL::Skill]) -> String
21
+
22
+ # : (Array[DSL::Rule]) -> String
23
+ def rules_section: (Array[DSL::Rule]) -> String
24
+
25
+ # : (Array[DSL::Hook]) -> String
26
+ def hooks_section: (Array[DSL::Hook]) -> String
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ # Generated from lib/diogenes/targets/codex.rb with RBS::Inline
2
+
3
+ module Diogenes
4
+ module Targets
5
+ class Codex < Base
6
+ OUTPUT_PATH: String
7
+
8
+ # : (sources: untyped) -> Array[String]
9
+ def build: (sources: untyped) -> Array[String]
10
+
11
+ private
12
+
13
+ # : (untyped) -> String
14
+ def render: (untyped) -> String
15
+
16
+ # : () -> String
17
+ def header: () -> String
18
+
19
+ # : (Array[DSL::Rule]) -> String
20
+ def rules_section: (Array[DSL::Rule]) -> String
21
+
22
+ # : (Array[DSL::Skill]) -> String
23
+ def skills_section: (Array[DSL::Skill]) -> String
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # Generated from lib/diogenes/targets/copilot.rb with RBS::Inline
2
+
3
+ module Diogenes
4
+ module Targets
5
+ class Copilot < Base
6
+ OUTPUT_PATH: String
7
+
8
+ # : (sources: untyped) -> Array[String]
9
+ def build: (sources: untyped) -> Array[String]
10
+
11
+ private
12
+
13
+ # : (untyped) -> String
14
+ def render: (untyped) -> String
15
+
16
+ # : () -> String
17
+ def header: () -> String
18
+
19
+ # : (Array[DSL::Rule]) -> String
20
+ def rules_section: (Array[DSL::Rule]) -> String
21
+
22
+ # : (Array[DSL::Skill]) -> String
23
+ def skills_section: (Array[DSL::Skill]) -> String
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # Generated from lib/diogenes/targets/cursor.rb with RBS::Inline
2
+
3
+ module Diogenes
4
+ module Targets
5
+ class Cursor < Base
6
+ OUTPUT_PATH: String
7
+
8
+ # : (sources: untyped) -> Array[String]
9
+ def build: (sources: untyped) -> Array[String]
10
+
11
+ private
12
+
13
+ # : (untyped) -> String
14
+ def render: (untyped) -> String
15
+
16
+ # : () -> String
17
+ def frontmatter: () -> String
18
+
19
+ # : (Array[DSL::Rule]) -> String
20
+ def rules_block: (Array[DSL::Rule]) -> String
21
+
22
+ # : (Array[DSL::Skill]) -> String
23
+ def skills_block: (Array[DSL::Skill]) -> String
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # Generated from lib/diogenes/targets/gemini.rb with RBS::Inline
2
+
3
+ module Diogenes
4
+ module Targets
5
+ class Gemini < Base
6
+ OUTPUT_PATH: String
7
+
8
+ # : (sources: untyped) -> Array[String]
9
+ def build: (sources: untyped) -> Array[String]
10
+
11
+ private
12
+
13
+ # : (untyped) -> String
14
+ def render: (untyped) -> String
15
+
16
+ # : () -> String
17
+ def header: () -> String
18
+
19
+ # : (Array[DSL::Rule]) -> String
20
+ def rules_section: (Array[DSL::Rule]) -> String
21
+
22
+ # : (Array[DSL::Skill]) -> String
23
+ def skills_section: (Array[DSL::Skill]) -> String
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,10 @@
1
+ # Generated from lib/diogenes/targets.rb with RBS::Inline
2
+
3
+ module Diogenes
4
+ module Targets
5
+ KNOWN: Array[Symbol]
6
+
7
+ # : (Symbol, cwd: String, out: IO) -> Targets::Base
8
+ def self.for: (Symbol, cwd: String, out: IO) -> Targets::Base
9
+ end
10
+ end
@@ -24,6 +24,12 @@ module Diogenes
24
24
  # : () -> String
25
25
  def self.version: () -> String
26
26
 
27
+ # : () { () -> void } -> Configuration
28
+ def self.configure: () { () -> void } -> Configuration
29
+
30
+ # : () -> Configuration
31
+ def self.configuration: () -> Configuration
32
+
27
33
  # : (String) { () -> void } -> DSL::Skill
28
34
  def self.skill: (String) { () -> void } -> DSL::Skill
29
35