nomos 0.1.0

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.
@@ -0,0 +1,375 @@
1
+ @import url("https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,700&family=Space+Grotesk:wght@400;500;600;700&display=swap");
2
+
3
+ :root {
4
+ --bg: #f7f4ef;
5
+ --surface: #ffffff;
6
+ --ink: #1b1c1f;
7
+ --muted: #4e5563;
8
+ --accent: #0b7a75;
9
+ --accent-2: #e07a2e;
10
+ --stroke: rgba(27, 28, 31, 0.12);
11
+ --shadow: 0 30px 60px rgba(15, 23, 42, 0.12);
12
+ }
13
+
14
+ * {
15
+ box-sizing: border-box;
16
+ }
17
+
18
+ body {
19
+ margin: 0;
20
+ font-family: "Space Grotesk", sans-serif;
21
+ color: var(--ink);
22
+ background: radial-gradient(circle at 20% 20%, rgba(224, 122, 46, 0.15), transparent 45%),
23
+ radial-gradient(circle at 80% 10%, rgba(11, 122, 117, 0.16), transparent 45%),
24
+ var(--bg);
25
+ }
26
+
27
+ h1,
28
+ h2,
29
+ h3,
30
+ h4 {
31
+ font-family: "Fraunces", serif;
32
+ margin: 0 0 0.6rem;
33
+ letter-spacing: -0.02em;
34
+ }
35
+
36
+ h1 {
37
+ font-size: clamp(2.6rem, 5vw, 4rem);
38
+ line-height: 1.05;
39
+ }
40
+
41
+ h2 {
42
+ font-size: clamp(2rem, 3.5vw, 2.8rem);
43
+ }
44
+
45
+ h3 {
46
+ font-size: 1.35rem;
47
+ }
48
+
49
+ p {
50
+ margin: 0 0 1rem;
51
+ color: var(--muted);
52
+ line-height: 1.6;
53
+ }
54
+
55
+ a {
56
+ color: inherit;
57
+ text-decoration: none;
58
+ }
59
+
60
+ main {
61
+ padding: 2.5rem clamp(1.5rem, 4vw, 5rem) 4rem;
62
+ }
63
+
64
+ .noise {
65
+ position: fixed;
66
+ inset: 0;
67
+ pointer-events: none;
68
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.7' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)' opacity='.05'/%3E%3C/svg%3E");
69
+ mix-blend-mode: multiply;
70
+ z-index: 0;
71
+ }
72
+
73
+ .glow {
74
+ position: fixed;
75
+ inset: 0;
76
+ background: radial-gradient(circle at 70% 30%, rgba(224, 122, 46, 0.18), transparent 55%);
77
+ pointer-events: none;
78
+ z-index: 0;
79
+ }
80
+
81
+ .hero {
82
+ position: relative;
83
+ z-index: 1;
84
+ }
85
+
86
+ .nav {
87
+ display: flex;
88
+ align-items: center;
89
+ justify-content: space-between;
90
+ gap: 1.5rem;
91
+ padding: 1rem 0 2rem;
92
+ }
93
+
94
+ .brand img {
95
+ height: 40px;
96
+ }
97
+
98
+ .nav-links {
99
+ display: flex;
100
+ gap: 1.25rem;
101
+ font-weight: 500;
102
+ }
103
+
104
+ .nav-links a {
105
+ color: var(--muted);
106
+ }
107
+
108
+ .button {
109
+ display: inline-flex;
110
+ align-items: center;
111
+ justify-content: center;
112
+ gap: 0.4rem;
113
+ padding: 0.75rem 1.3rem;
114
+ border-radius: 999px;
115
+ border: 1px solid transparent;
116
+ font-weight: 600;
117
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
118
+ }
119
+
120
+ .button.primary {
121
+ background: linear-gradient(120deg, var(--accent), #1f9b90);
122
+ color: white;
123
+ box-shadow: 0 20px 40px rgba(11, 122, 117, 0.25);
124
+ }
125
+
126
+ .button.ghost {
127
+ border-color: var(--stroke);
128
+ color: var(--ink);
129
+ background: rgba(255, 255, 255, 0.6);
130
+ }
131
+
132
+ .button:hover {
133
+ transform: translateY(-2px);
134
+ box-shadow: 0 16px 30px rgba(15, 23, 42, 0.15);
135
+ }
136
+
137
+ .hero-content {
138
+ display: grid;
139
+ grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
140
+ align-items: center;
141
+ gap: 2.5rem;
142
+ padding: 2rem 0 3rem;
143
+ }
144
+
145
+ .eyebrow {
146
+ text-transform: uppercase;
147
+ letter-spacing: 0.2em;
148
+ font-size: 0.75rem;
149
+ font-weight: 600;
150
+ color: var(--accent);
151
+ margin-bottom: 1rem;
152
+ }
153
+
154
+ .lead {
155
+ font-size: 1.15rem;
156
+ max-width: 34rem;
157
+ }
158
+
159
+ .hero-actions {
160
+ display: flex;
161
+ flex-wrap: wrap;
162
+ gap: 0.8rem;
163
+ margin: 1.5rem 0;
164
+ }
165
+
166
+ .hero-meta {
167
+ display: flex;
168
+ flex-wrap: wrap;
169
+ gap: 0.8rem;
170
+ font-size: 0.9rem;
171
+ color: var(--muted);
172
+ }
173
+
174
+ .hero-card {
175
+ background: var(--surface);
176
+ border-radius: 24px;
177
+ box-shadow: var(--shadow);
178
+ padding: 1.5rem;
179
+ border: 1px solid rgba(11, 122, 117, 0.18);
180
+ }
181
+
182
+ .code-header {
183
+ display: flex;
184
+ align-items: center;
185
+ gap: 0.4rem;
186
+ font-size: 0.85rem;
187
+ margin-bottom: 1rem;
188
+ color: var(--muted);
189
+ }
190
+
191
+ .code-header span {
192
+ width: 10px;
193
+ height: 10px;
194
+ border-radius: 50%;
195
+ background: #f2c94c;
196
+ }
197
+
198
+ .code-header span:first-child {
199
+ background: #eb5757;
200
+ }
201
+
202
+ .code-header span:nth-child(2) {
203
+ background: #27ae60;
204
+ }
205
+
206
+ pre {
207
+ margin: 0;
208
+ font-size: 0.9rem;
209
+ line-height: 1.5;
210
+ color: #0f172a;
211
+ white-space: pre-wrap;
212
+ }
213
+
214
+ .section {
215
+ padding: 4rem 0;
216
+ position: relative;
217
+ z-index: 1;
218
+ animation: fadeUp 0.9s ease forwards;
219
+ }
220
+
221
+ .section-title {
222
+ max-width: 48rem;
223
+ margin-bottom: 2.5rem;
224
+ }
225
+
226
+ .grid {
227
+ display: grid;
228
+ gap: 1.5rem;
229
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
230
+ }
231
+
232
+ .card {
233
+ background: var(--surface);
234
+ border-radius: 20px;
235
+ padding: 1.8rem;
236
+ border: 1px solid var(--stroke);
237
+ box-shadow: 0 12px 30px rgba(15, 23, 42, 0.08);
238
+ }
239
+
240
+ .card.code {
241
+ background: #0b1020;
242
+ color: #f8fafc;
243
+ }
244
+
245
+ .card.code pre {
246
+ color: #f8fafc;
247
+ }
248
+
249
+ .split {
250
+ display: grid;
251
+ grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
252
+ gap: 2.5rem;
253
+ align-items: center;
254
+ }
255
+
256
+ .list {
257
+ list-style: none;
258
+ padding: 0;
259
+ margin: 1.5rem 0 0;
260
+ }
261
+
262
+ .list li {
263
+ padding-left: 1.5rem;
264
+ position: relative;
265
+ margin-bottom: 0.8rem;
266
+ color: var(--muted);
267
+ }
268
+
269
+ .list li::before {
270
+ content: "✦";
271
+ position: absolute;
272
+ left: 0;
273
+ color: var(--accent-2);
274
+ }
275
+
276
+ .timeline {
277
+ display: grid;
278
+ gap: 1.2rem;
279
+ }
280
+
281
+ .timeline-item {
282
+ display: flex;
283
+ gap: 1rem;
284
+ align-items: flex-start;
285
+ background: rgba(255, 255, 255, 0.65);
286
+ border-radius: 16px;
287
+ padding: 1rem 1.2rem;
288
+ border: 1px solid var(--stroke);
289
+ }
290
+
291
+ .timeline-item span {
292
+ width: 32px;
293
+ height: 32px;
294
+ border-radius: 50%;
295
+ background: var(--accent);
296
+ color: white;
297
+ display: inline-flex;
298
+ align-items: center;
299
+ justify-content: center;
300
+ font-weight: 600;
301
+ }
302
+
303
+ .config-grid {
304
+ display: grid;
305
+ grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
306
+ gap: 2rem;
307
+ align-items: stretch;
308
+ }
309
+
310
+ .muted {
311
+ color: var(--muted);
312
+ font-size: 0.95rem;
313
+ }
314
+
315
+ .text-link {
316
+ font-weight: 600;
317
+ color: var(--accent);
318
+ }
319
+
320
+ .cta {
321
+ display: flex;
322
+ align-items: center;
323
+ justify-content: space-between;
324
+ gap: 2rem;
325
+ background: linear-gradient(130deg, rgba(11, 122, 117, 0.12), rgba(224, 122, 46, 0.12));
326
+ border-radius: 28px;
327
+ padding: 2.5rem;
328
+ border: 1px solid var(--stroke);
329
+ }
330
+
331
+ .footer {
332
+ display: flex;
333
+ justify-content: space-between;
334
+ align-items: center;
335
+ padding: 2rem clamp(1.5rem, 4vw, 5rem) 3rem;
336
+ font-size: 0.9rem;
337
+ color: var(--muted);
338
+ }
339
+
340
+ @keyframes fadeUp {
341
+ from {
342
+ opacity: 0;
343
+ transform: translateY(12px);
344
+ }
345
+ to {
346
+ opacity: 1;
347
+ transform: translateY(0);
348
+ }
349
+ }
350
+
351
+ @media (max-width: 900px) {
352
+ .nav-links {
353
+ display: none;
354
+ }
355
+
356
+ .cta {
357
+ flex-direction: column;
358
+ align-items: flex-start;
359
+ }
360
+ }
361
+
362
+ @media (max-width: 600px) {
363
+ .nav {
364
+ flex-wrap: wrap;
365
+ }
366
+
367
+ .hero-meta {
368
+ flex-direction: column;
369
+ }
370
+
371
+ .footer {
372
+ flex-direction: column;
373
+ gap: 0.8rem;
374
+ }
375
+ }
@@ -0,0 +1,7 @@
1
+ ---
2
+ title: "Nomos"
3
+ description: "Rules-driven pull request checks with fast startup, minimal API calls, and clear configuration."
4
+ layout: "home"
5
+ cta_url: "https://github.com/ydah/nomos"
6
+ cta_label: "View on GitHub"
7
+ ---
data/site/craze.yml ADDED
@@ -0,0 +1,19 @@
1
+ site:
2
+ title: "Nomos"
3
+ description: "Bring harmony to your pull requests."
4
+ url: "https://ydah.github.io/nomos"
5
+ language: "en"
6
+
7
+ build:
8
+ out_dir: "dist"
9
+ base_path: "/nomos/"
10
+ clean: true
11
+
12
+ content:
13
+ dir: "content"
14
+
15
+ templates:
16
+ dir: "templates"
17
+
18
+ assets:
19
+ dir: "assets"
@@ -0,0 +1,20 @@
1
+ <!doctype html>
2
+ <html lang="<%= site["language"] || "en" %>">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title><%= page["title"] %> | <%= site["title"] %></title>
7
+ <meta name="description" content="<%= page["description"] || site["description"] %>" />
8
+ <meta property="og:title" content="<%= page["title"] %>" />
9
+ <meta property="og:description" content="<%= page["description"] || site["description"] %>" />
10
+ <meta property="og:type" content="website" />
11
+ <meta property="og:url" content="<%= site["url"] %>" />
12
+ <link rel="icon" href="<%= asset_path('logo-header.svg') %>" />
13
+ <link rel="stylesheet" href="<%= asset_path('styles.css') %>" />
14
+ </head>
15
+ <body>
16
+ <div class="noise"></div>
17
+ <div class="glow"></div>
18
+ <%= page["content"] %>
19
+ </body>
20
+ </html>
@@ -0,0 +1,198 @@
1
+ <!doctype html>
2
+ <html lang="<%= site["language"] || "en" %>">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title><%= page["title"] %> | <%= site["title"] %></title>
7
+ <meta name="description" content="<%= page["description"] || site["description"] %>" />
8
+ <meta property="og:title" content="<%= page["title"] %>" />
9
+ <meta property="og:description" content="<%= page["description"] || site["description"] %>" />
10
+ <meta property="og:type" content="website" />
11
+ <meta property="og:url" content="<%= site["url"] %>" />
12
+ <link rel="icon" href="<%= asset_path('logo-header.svg') %>" />
13
+ <link rel="stylesheet" href="<%= asset_path('styles.css') %>" />
14
+ </head>
15
+ <body>
16
+ <div class="noise"></div>
17
+ <div class="glow"></div>
18
+
19
+ <main>
20
+ <header class="hero">
21
+ <nav class="nav">
22
+ <div class="brand">
23
+ <img src="<%= asset_path('logo.png') %>" alt="Nomos logo" />
24
+ </div>
25
+ <div class="nav-links">
26
+ <a href="#features">Features</a>
27
+ <a href="#workflow">Workflow</a>
28
+ <a href="#config">Config</a>
29
+ <a href="#integrations">Integrations</a>
30
+ </div>
31
+ <a class="button ghost" href="<%= page["cta_url"] %>"><%= page["cta_label"] %></a>
32
+ </nav>
33
+
34
+ <section class="hero-content">
35
+ <div>
36
+ <p class="eyebrow">PR Policy Engine</p>
37
+ <h1>Bring harmony to your pull requests.</h1>
38
+ <p class="lead"><%= page["description"] %></p>
39
+ <div class="hero-actions">
40
+ <a class="button primary" href="<%= page["cta_url"] %>"><%= page["cta_label"] %></a>
41
+ <a class="button ghost" href="#config">See config</a>
42
+ </div>
43
+ <div class="hero-meta">
44
+ <span>Ruby 3.2+</span>
45
+ <span>GitHub Actions ready</span>
46
+ <span>Fast startup</span>
47
+ </div>
48
+ </div>
49
+ <div class="hero-card">
50
+ <div class="code-header">
51
+ <span></span><span></span><span></span>
52
+ <strong>nomos.yml</strong>
53
+ </div>
54
+ <pre><code>reporter:
55
+ github: true
56
+ console: true
57
+
58
+ rules:
59
+ - name: no_large_pr
60
+ type: builtin.no_large_pr
61
+ params:
62
+ max_changed_lines: 800</code></pre>
63
+ </div>
64
+ </section>
65
+ </header>
66
+
67
+ <section id="features" class="section">
68
+ <div class="section-title">
69
+ <h2>Designed for the pull request moment.</h2>
70
+ <p>Nomos evaluates PR metadata and diffs, then reports findings as message, warn, or fail.</p>
71
+ </div>
72
+ <div class="grid">
73
+ <article class="card">
74
+ <h3>Diff-first execution</h3>
75
+ <p>Start with the PR diff and lazy-fetch extra data only when a rule needs it.</p>
76
+ </article>
77
+ <article class="card">
78
+ <h3>Parallel rule engine</h3>
79
+ <p>Run built-in and custom Ruby rules concurrently for fast feedback in CI.</p>
80
+ </article>
81
+ <article class="card">
82
+ <h3>Clear reporting</h3>
83
+ <p>Ship results to GitHub comments, console output, or JSON for downstream tooling.</p>
84
+ </article>
85
+ <article class="card">
86
+ <h3>Strict mode</h3>
87
+ <p>Fail the pipeline when policy is violated and keep your standards enforced.</p>
88
+ </article>
89
+ </div>
90
+ </section>
91
+
92
+ <section id="workflow" class="section split">
93
+ <div>
94
+ <h2>Fast, intentional workflow.</h2>
95
+ <p>Nomos is optimized to stay out of the way while still giving you precise, configurable checks.</p>
96
+ <ul class="list">
97
+ <li>Minimal GitHub API calls with optional caching</li>
98
+ <li>Lazy diff fetching to keep startup time low</li>
99
+ <li>Ruby DSL for custom rule logic</li>
100
+ </ul>
101
+ </div>
102
+ <div class="timeline">
103
+ <div class="timeline-item">
104
+ <span>1</span>
105
+ <div>
106
+ <h4>Discover</h4>
107
+ <p>Load event data and compute diffs.</p>
108
+ </div>
109
+ </div>
110
+ <div class="timeline-item">
111
+ <span>2</span>
112
+ <div>
113
+ <h4>Evaluate</h4>
114
+ <p>Run built-in and custom rules concurrently.</p>
115
+ </div>
116
+ </div>
117
+ <div class="timeline-item">
118
+ <span>3</span>
119
+ <div>
120
+ <h4>Report</h4>
121
+ <p>Emit GitHub, console, or JSON output.</p>
122
+ </div>
123
+ </div>
124
+ </div>
125
+ </section>
126
+
127
+ <section id="config" class="section">
128
+ <div class="section-title">
129
+ <h2>Configuration that reads like policy.</h2>
130
+ <p>Define your checks in a single YAML file and keep them close to the repo.</p>
131
+ </div>
132
+ <div class="config-grid">
133
+ <div class="card code">
134
+ <pre><code>version: 1
135
+
136
+ reporter:
137
+ github: true
138
+ console: true
139
+
140
+ performance:
141
+ concurrency: 4
142
+ cache: true
143
+ lazy_diff: true
144
+
145
+ rules:
146
+ - name: require_changelog
147
+ type: builtin.require_file_change
148
+ params:
149
+ patterns:
150
+ - CHANGELOG.md</code></pre>
151
+ </div>
152
+ <div class="card">
153
+ <h3>Ruby DSL for custom rules</h3>
154
+ <p>Define richer logic in `.nomos/rules.rb` and ship it alongside your repo.</p>
155
+ <p class="muted">Run once, cache results, and keep policy close to the code.</p>
156
+ <a class="text-link" href="<%= page["cta_url"] %>">Explore docs on GitHub →</a>
157
+ </div>
158
+ </div>
159
+ </section>
160
+
161
+ <section id="integrations" class="section">
162
+ <div class="section-title">
163
+ <h2>Integrations that fit your CI.</h2>
164
+ <p>Designed for GitHub Actions with clear environment inputs and predictable output.</p>
165
+ </div>
166
+ <div class="grid">
167
+ <article class="card">
168
+ <h3>GitHub Actions</h3>
169
+ <p>Run `nomos run` with a GitHub token and event payload.</p>
170
+ </article>
171
+ <article class="card">
172
+ <h3>Console output</h3>
173
+ <p>Readable local output for quick iteration.</p>
174
+ </article>
175
+ <article class="card">
176
+ <h3>JSON export</h3>
177
+ <p>Pipe findings into dashboards or additional automation.</p>
178
+ </article>
179
+ </div>
180
+ </section>
181
+
182
+ <section class="section cta">
183
+ <div>
184
+ <h2>Ship guardrails, not gatekeeping.</h2>
185
+ <p>Keep PR standards consistent while staying fast and predictable.</p>
186
+ </div>
187
+ <a class="button primary" href="<%= page["cta_url"] %>"><%= page["cta_label"] %></a>
188
+ </section>
189
+ </main>
190
+
191
+ <footer class="footer">
192
+ <div>Nomos · MIT License</div>
193
+ <div>
194
+ <a href="<%= page["cta_url"] %>">GitHub</a>
195
+ </div>
196
+ </footer>
197
+ </body>
198
+ </html>
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nomos
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Yudai Takada
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: Nomos evaluates pull request metadata and diffs, then reports findings
13
+ as message, warn, or fail. It is designed for fast startup, minimal GitHub API calls,
14
+ and clear configuration.
15
+ email:
16
+ - t.yudai92@gmail.com
17
+ executables:
18
+ - nomos
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - CHANGELOG.md
23
+ - LICENSE.txt
24
+ - README.md
25
+ - Rakefile
26
+ - docs/logo-header.svg
27
+ - examples/.nomos/rules.rb
28
+ - examples/nomos.yml
29
+ - exe/nomos
30
+ - lib/nomos.rb
31
+ - lib/nomos/cache.rb
32
+ - lib/nomos/cli.rb
33
+ - lib/nomos/config.rb
34
+ - lib/nomos/context.rb
35
+ - lib/nomos/context_loader.rb
36
+ - lib/nomos/finding.rb
37
+ - lib/nomos/github_client.rb
38
+ - lib/nomos/reporters/console.rb
39
+ - lib/nomos/reporters/github.rb
40
+ - lib/nomos/reporters/json.rb
41
+ - lib/nomos/rules.rb
42
+ - lib/nomos/rules/base.rb
43
+ - lib/nomos/rules/builtin/forbid_paths.rb
44
+ - lib/nomos/rules/builtin/no_large_pr.rb
45
+ - lib/nomos/rules/builtin/require_file_change.rb
46
+ - lib/nomos/rules/builtin/require_labels.rb
47
+ - lib/nomos/rules/builtin/todo_guard.rb
48
+ - lib/nomos/rules/ruby_dsl.rb
49
+ - lib/nomos/rules/ruby_file.rb
50
+ - lib/nomos/runner.rb
51
+ - lib/nomos/timing.rb
52
+ - lib/nomos/version.rb
53
+ - sig/nomos.rbs
54
+ - site/assets/logo.png
55
+ - site/assets/styles.css
56
+ - site/content/index.md
57
+ - site/craze.yml
58
+ - site/templates/layouts/default.html.erb
59
+ - site/templates/layouts/home.html.erb
60
+ homepage: https://github.com/ydah/nomos
61
+ licenses:
62
+ - MIT
63
+ metadata:
64
+ homepage_uri: https://github.com/ydah/nomos
65
+ source_code_uri: https://github.com/ydah/nomos
66
+ changelog_uri: https://github.com/ydah/nomos/blob/main/CHANGELOG.md
67
+ bug_tracker_uri: https://github.com/ydah/nomos/issues
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 3.2.0
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubygems_version: 4.0.3
83
+ specification_version: 4
84
+ summary: Evaluate GitHub pull requests with configurable rules.
85
+ test_files: []