onion-check 1.0.1 → 2.0.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.
Files changed (208) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +346 -0
  3. package/dist/auditor/compare.d.ts +24 -0
  4. package/dist/auditor/compare.d.ts.map +1 -0
  5. package/dist/auditor/compare.js +87 -0
  6. package/dist/auditor/compare.js.map +1 -0
  7. package/dist/auditor/cost.d.ts +11 -0
  8. package/dist/auditor/cost.d.ts.map +1 -0
  9. package/dist/auditor/cost.js +102 -0
  10. package/dist/auditor/cost.js.map +1 -0
  11. package/dist/auditor/dependencies.d.ts +9 -0
  12. package/dist/auditor/dependencies.d.ts.map +1 -0
  13. package/dist/auditor/dependencies.js +80 -0
  14. package/dist/auditor/dependencies.js.map +1 -0
  15. package/dist/auditor/index.d.ts +14 -0
  16. package/dist/auditor/index.d.ts.map +1 -0
  17. package/dist/auditor/index.js +338 -0
  18. package/dist/auditor/index.js.map +1 -0
  19. package/dist/auditor/migration.d.ts +11 -0
  20. package/dist/auditor/migration.d.ts.map +1 -0
  21. package/dist/auditor/migration.js +134 -0
  22. package/dist/auditor/migration.js.map +1 -0
  23. package/dist/auditor/model-routing.d.ts +10 -0
  24. package/dist/auditor/model-routing.d.ts.map +1 -0
  25. package/dist/auditor/model-routing.js +160 -0
  26. package/dist/auditor/model-routing.js.map +1 -0
  27. package/dist/auditor/techstack.d.ts +18 -0
  28. package/dist/auditor/techstack.d.ts.map +1 -0
  29. package/dist/auditor/techstack.js +303 -0
  30. package/dist/auditor/techstack.js.map +1 -0
  31. package/dist/cli/create-onion-stack.d.ts +3 -0
  32. package/dist/cli/create-onion-stack.d.ts.map +1 -0
  33. package/dist/cli/create-onion-stack.js +74 -0
  34. package/dist/cli/create-onion-stack.js.map +1 -0
  35. package/dist/cli/onion-check.d.ts +3 -0
  36. package/dist/cli/onion-check.d.ts.map +1 -0
  37. package/dist/cli/onion-check.js +269 -0
  38. package/dist/cli/onion-check.js.map +1 -0
  39. package/dist/core/banner.d.ts +2 -0
  40. package/dist/core/banner.d.ts.map +1 -0
  41. package/dist/core/banner.js +96 -0
  42. package/dist/core/banner.js.map +1 -0
  43. package/dist/core/colors.d.ts +15 -0
  44. package/dist/core/colors.d.ts.map +1 -0
  45. package/dist/core/colors.js +31 -0
  46. package/dist/core/colors.js.map +1 -0
  47. package/dist/core/config.d.ts +77 -0
  48. package/dist/core/config.d.ts.map +1 -0
  49. package/dist/core/config.js +74 -0
  50. package/dist/core/config.js.map +1 -0
  51. package/dist/core/index.d.ts +7 -0
  52. package/dist/core/index.d.ts.map +1 -0
  53. package/dist/core/index.js +5 -0
  54. package/dist/core/index.js.map +1 -0
  55. package/dist/core/layers.d.ts +3 -0
  56. package/dist/core/layers.d.ts.map +1 -0
  57. package/dist/core/layers.js +333 -0
  58. package/dist/core/layers.js.map +1 -0
  59. package/dist/core/types.d.ts +66 -0
  60. package/dist/core/types.d.ts.map +1 -0
  61. package/dist/core/types.js +2 -0
  62. package/dist/core/types.js.map +1 -0
  63. package/dist/generators/claude-integration.d.ts +3 -0
  64. package/dist/generators/claude-integration.d.ts.map +1 -0
  65. package/dist/generators/claude-integration.js +75 -0
  66. package/dist/generators/claude-integration.js.map +1 -0
  67. package/dist/generators/context.d.ts +3 -0
  68. package/dist/generators/context.d.ts.map +1 -0
  69. package/dist/generators/context.js +153 -0
  70. package/dist/generators/context.js.map +1 -0
  71. package/dist/generators/evaluation.d.ts +3 -0
  72. package/dist/generators/evaluation.d.ts.map +1 -0
  73. package/dist/generators/evaluation.js +229 -0
  74. package/dist/generators/evaluation.js.map +1 -0
  75. package/dist/generators/goal.d.ts +3 -0
  76. package/dist/generators/goal.d.ts.map +1 -0
  77. package/dist/generators/goal.js +185 -0
  78. package/dist/generators/goal.js.map +1 -0
  79. package/dist/generators/governance.d.ts +3 -0
  80. package/dist/generators/governance.d.ts.map +1 -0
  81. package/dist/generators/governance.js +150 -0
  82. package/dist/generators/governance.js.map +1 -0
  83. package/dist/generators/index.d.ts +18 -0
  84. package/dist/generators/index.d.ts.map +1 -0
  85. package/dist/generators/index.js +275 -0
  86. package/dist/generators/index.js.map +1 -0
  87. package/dist/generators/layer-docs.d.ts +16 -0
  88. package/dist/generators/layer-docs.d.ts.map +1 -0
  89. package/dist/generators/layer-docs.js +206 -0
  90. package/dist/generators/layer-docs.js.map +1 -0
  91. package/dist/generators/model.d.ts +3 -0
  92. package/dist/generators/model.d.ts.map +1 -0
  93. package/dist/generators/model.js +64 -0
  94. package/dist/generators/model.js.map +1 -0
  95. package/dist/generators/orchestration.d.ts +3 -0
  96. package/dist/generators/orchestration.d.ts.map +1 -0
  97. package/dist/generators/orchestration.js +172 -0
  98. package/dist/generators/orchestration.js.map +1 -0
  99. package/dist/generators/security.d.ts +3 -0
  100. package/dist/generators/security.d.ts.map +1 -0
  101. package/dist/generators/security.js +277 -0
  102. package/dist/generators/security.js.map +1 -0
  103. package/dist/generators/skills.d.ts +3 -0
  104. package/dist/generators/skills.d.ts.map +1 -0
  105. package/dist/generators/skills.js +317 -0
  106. package/dist/generators/skills.js.map +1 -0
  107. package/dist/generators/tools.d.ts +3 -0
  108. package/dist/generators/tools.d.ts.map +1 -0
  109. package/dist/generators/tools.js +110 -0
  110. package/dist/generators/tools.js.map +1 -0
  111. package/dist/generators/types.d.ts +19 -0
  112. package/dist/generators/types.d.ts.map +1 -0
  113. package/dist/generators/types.js +2 -0
  114. package/dist/generators/types.js.map +1 -0
  115. package/dist/history/status.d.ts +2 -0
  116. package/dist/history/status.d.ts.map +1 -0
  117. package/dist/history/status.js +126 -0
  118. package/dist/history/status.js.map +1 -0
  119. package/dist/history/tracker.d.ts +45 -0
  120. package/dist/history/tracker.d.ts.map +1 -0
  121. package/dist/history/tracker.js +227 -0
  122. package/dist/history/tracker.js.map +1 -0
  123. package/dist/hooks/pre-commit.d.ts +3 -0
  124. package/dist/hooks/pre-commit.d.ts.map +1 -0
  125. package/dist/hooks/pre-commit.js +102 -0
  126. package/dist/hooks/pre-commit.js.map +1 -0
  127. package/dist/index.d.ts +19 -0
  128. package/dist/index.d.ts.map +1 -0
  129. package/dist/index.js +18 -0
  130. package/dist/index.js.map +1 -0
  131. package/dist/interactive/consultant.d.ts +14 -0
  132. package/dist/interactive/consultant.d.ts.map +1 -0
  133. package/dist/interactive/consultant.js +563 -0
  134. package/dist/interactive/consultant.js.map +1 -0
  135. package/dist/interactive/diagnostic.d.ts +2 -0
  136. package/dist/interactive/diagnostic.d.ts.map +1 -0
  137. package/dist/interactive/diagnostic.js +364 -0
  138. package/dist/interactive/diagnostic.js.map +1 -0
  139. package/dist/interactive/fixer.d.ts +3 -0
  140. package/dist/interactive/fixer.d.ts.map +1 -0
  141. package/dist/interactive/fixer.js +49 -0
  142. package/dist/interactive/fixer.js.map +1 -0
  143. package/dist/interactive/intake.d.ts +15 -0
  144. package/dist/interactive/intake.d.ts.map +1 -0
  145. package/dist/interactive/intake.js +112 -0
  146. package/dist/interactive/intake.js.map +1 -0
  147. package/dist/interactive/prompt.d.ts +11 -0
  148. package/dist/interactive/prompt.d.ts.map +1 -0
  149. package/dist/interactive/prompt.js +71 -0
  150. package/dist/interactive/prompt.js.map +1 -0
  151. package/dist/mcp/index.d.ts +3 -0
  152. package/dist/mcp/index.d.ts.map +1 -0
  153. package/dist/mcp/index.js +13 -0
  154. package/dist/mcp/index.js.map +1 -0
  155. package/dist/mcp/server.d.ts +3 -0
  156. package/dist/mcp/server.d.ts.map +1 -0
  157. package/dist/mcp/server.js +196 -0
  158. package/dist/mcp/server.js.map +1 -0
  159. package/dist/mcp/tools.d.ts +35 -0
  160. package/dist/mcp/tools.d.ts.map +1 -0
  161. package/dist/mcp/tools.js +66 -0
  162. package/dist/mcp/tools.js.map +1 -0
  163. package/dist/scaffold/generator.d.ts +6 -0
  164. package/dist/scaffold/generator.d.ts.map +1 -0
  165. package/dist/scaffold/generator.js +81 -0
  166. package/dist/scaffold/generator.js.map +1 -0
  167. package/dist/scaffold/index.d.ts +4 -0
  168. package/dist/scaffold/index.d.ts.map +1 -0
  169. package/dist/scaffold/index.js +3 -0
  170. package/dist/scaffold/index.js.map +1 -0
  171. package/dist/scaffold/templates.d.ts +13 -0
  172. package/dist/scaffold/templates.d.ts.map +1 -0
  173. package/dist/scaffold/templates.js +403 -0
  174. package/dist/scaffold/templates.js.map +1 -0
  175. package/dist/scanner/consistency.d.ts +3 -0
  176. package/dist/scanner/consistency.d.ts.map +1 -0
  177. package/dist/scanner/consistency.js +143 -0
  178. package/dist/scanner/consistency.js.map +1 -0
  179. package/dist/scanner/content-validators.d.ts +3 -0
  180. package/dist/scanner/content-validators.d.ts.map +1 -0
  181. package/dist/scanner/content-validators.js +554 -0
  182. package/dist/scanner/content-validators.js.map +1 -0
  183. package/dist/scanner/detectors.d.ts +3 -0
  184. package/dist/scanner/detectors.d.ts.map +1 -0
  185. package/dist/scanner/detectors.js +190 -0
  186. package/dist/scanner/detectors.js.map +1 -0
  187. package/dist/scanner/framework-patterns.d.ts +8 -0
  188. package/dist/scanner/framework-patterns.d.ts.map +1 -0
  189. package/dist/scanner/framework-patterns.js +76 -0
  190. package/dist/scanner/framework-patterns.js.map +1 -0
  191. package/dist/scanner/index.d.ts +7 -0
  192. package/dist/scanner/index.d.ts.map +1 -0
  193. package/dist/scanner/index.js +18 -0
  194. package/dist/scanner/index.js.map +1 -0
  195. package/dist/scanner/reporter.d.ts +7 -0
  196. package/dist/scanner/reporter.d.ts.map +1 -0
  197. package/dist/scanner/reporter.js +276 -0
  198. package/dist/scanner/reporter.js.map +1 -0
  199. package/dist/scanner/scorer.d.ts +5 -0
  200. package/dist/scanner/scorer.d.ts.map +1 -0
  201. package/dist/scanner/scorer.js +74 -0
  202. package/dist/scanner/scorer.js.map +1 -0
  203. package/dist/scanner/watcher.d.ts +6 -0
  204. package/dist/scanner/watcher.d.ts.map +1 -0
  205. package/dist/scanner/watcher.js +133 -0
  206. package/dist/scanner/watcher.js.map +1 -0
  207. package/package.json +41 -6
  208. package/bin.js +0 -2
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Michael Davidson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,346 @@
1
+ # The Onion Architecture
2
+
3
+ **Most people think deploying AI is one decision. It's eight.**
4
+
5
+ ![Onion Score](https://img.shields.io/badge/onion--score-8%2F8-brightgreen?style=for-the-badge)
6
+ [![MIT License](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](LICENSE)
7
+ [![npm](https://img.shields.io/npm/v/onion-architecture?style=flat-square)](https://www.npmjs.com/package/onion-architecture)
8
+
9
+ Every AI system that works in production is an onion. It has layers. Each layer wraps around the one inside it. Each layer adds a dimension of capability that the layer beneath it can't provide on its own. Most people are building a single layer and calling it a system.
10
+
11
+ ---
12
+
13
+ ## What It Does
14
+
15
+ **`onion-check`** scans your project and tells you exactly what's missing, what's weak, and what to fix — across all 8 layers of a production AI system.
16
+
17
+ **`create-onion-stack`** builds a complete, production-ready AI system from scratch. It interviews you about your business, encodes your expertise into skills, configures your tools, sets up security scanning, defines approval workflows, and creates quality benchmarks. 30+ customized files in under 5 minutes.
18
+
19
+ ---
20
+
21
+ ## Quick Start
22
+
23
+ **Diagnose your project:**
24
+
25
+ ```bash
26
+ npx onion-check
27
+ ```
28
+
29
+ **Build a new project with all 8 layers:**
30
+
31
+ ```bash
32
+ npx create-onion-stack my-project
33
+ ```
34
+
35
+ **Start from a template:**
36
+
37
+ ```bash
38
+ npx create-onion-stack my-project --template agency
39
+ npx create-onion-stack my-project --template saas
40
+ npx create-onion-stack my-project --template content
41
+ npx create-onion-stack my-project --template support
42
+ ```
43
+
44
+ ---
45
+
46
+ ## Example Output
47
+
48
+ ### `npx onion-check`
49
+
50
+ ```
51
+ ██████╗ ███╗ ██╗ ██╗ ██████╗ ███╗ ██╗
52
+ ██╔═══██╗ ████╗ ██║ ██║ ██╔═══██╗ ████╗ ██║
53
+ ██║ ██║ ██╔██╗ ██║ ██║ ██║ ██║ ██╔██╗ ██║
54
+ ██║ ██║ ██║╚██╗██║ ██║ ██║ ██║ ██║╚██╗██║
55
+ ╚██████╔╝ ██║ ╚████║ ██║ ╚██████╔╝ ██║ ╚████║
56
+ ╚═════╝ ╚═╝ ╚═══╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
57
+ A R C H I T E C T U R E
58
+
59
+ LAYER SCAN
60
+ ────────────────────────────────────────
61
+
62
+ ✓ Layer 1: Model
63
+ ✓ Layer 2: Context
64
+ ✓ Layer 3: Skills
65
+ ✓ Layer 4: Tools
66
+ ✗ Layer 5: Orchestration
67
+ ✓ Layer 6: Security
68
+ ✗ Layer 7: Governance
69
+ ✗ Layer 8: Evaluation
70
+
71
+ SCORE: 5/8 (Production Ready)
72
+
73
+ ███████████████░░░░░░░░░
74
+
75
+ MIGRATION ROADMAP
76
+ ────────────────────────────────────────
77
+
78
+ 1. Layer 8: Evaluation [HIGH]
79
+ AI output degrades over time without monitoring.
80
+ Effort: 2-3 hours
81
+
82
+ 2. Layer 5: Orchestration [MEDIUM]
83
+ One agent doing everything produces mediocre output.
84
+ Effort: 2-4 hours
85
+
86
+ 3. Layer 7: Governance [LOW]
87
+ Can wait until you have orchestration or high-stakes actions.
88
+ Effort: 1-2 hours
89
+ ```
90
+
91
+ ### `npx onion-check --audit`
92
+
93
+ Adds deep quality analysis on top of the layer scan:
94
+
95
+ ```
96
+ QUALITY AUDIT
97
+ ────────────────────────────────────────
98
+
99
+ ✓ Layer 1: Model 100/100
100
+ ✓ Layer 2: Context 100/100
101
+ ○ Layer 3: Skills 60/100
102
+ ▸ Skill "content-writing" scores 45/100 — no decision framework, no quality standards
103
+ Fix: Add decision framework, quality standards, edge case handling
104
+ ✓ Layer 4: Tools 100/100
105
+ ○ Layer 6: Security 75/100
106
+ ▸ No pre-commit hooks — security scan won't run automatically
107
+ Fix: Install pre-commit hooks to run security scan on every commit
108
+
109
+ QUALITY: 87/100 (2 issues found)
110
+
111
+ MODEL ROUTING RECOMMENDATIONS
112
+ ────────────────────────────────────────
113
+
114
+ ▼ DOWNGRADE — save money, same quality
115
+ triage → Fast/Cheap (Haiku, GPT-4o-mini, Flash)
116
+ Classification tasks don't need deep reasoning — 90% cost reduction
117
+
118
+ ● BALANCED — good quality/cost ratio
119
+ content-writing → Balanced (Sonnet, GPT-4o, Gemini Pro)
120
+ Creative output needs good language ability but not maximum reasoning
121
+
122
+ ▲ KEEP TOP-TIER — complexity requires it
123
+ code-review → Top-tier (Opus, o3, Gemini Ultra)
124
+ Multi-step process with judgment calls — needs maximum reasoning
125
+ ```
126
+
127
+ ### `npx create-onion-stack my-agency --template agency`
128
+
129
+ ```
130
+ ✓ Layer 1: Model — .env.example, model.config.json
131
+ ✓ Layer 2: Context — CLAUDE.md, company profile, context guide
132
+ ✓ Layer 3: Skills — 4 domain skills (content, reporting, email, SEO)
133
+ ✓ Layer 4: Tools — .mcp.json with 3 integrations
134
+ ✓ Layer 5: Orchestration — 3 agents, handoff protocol, AGENTS.md
135
+ ✓ Layer 6: Security — security scan, rules, pre-commit hooks
136
+ ✓ Layer 7: Governance — approval rules, escalation policy
137
+ ✓ Layer 8: Evaluation — quality rubric, metrics, audit template
138
+ ✓ onion.config.json — Architecture manifest
139
+
140
+ my-agency is ready. (30 files generated)
141
+ ```
142
+
143
+ Generated project structure:
144
+
145
+ ```
146
+ my-agency/
147
+ ├── CLAUDE.md # AI instructions (customized to your business)
148
+ ├── AGENTS.md # Agent hierarchy and routing
149
+ ├── onion.config.json # Architecture manifest
150
+ ├── .mcp.json # Tool connections (MCP servers)
151
+ ├── .env.example # API keys template
152
+ ├── model.config.json # Model selection and routing
153
+ ├── security-scan.sh # Automated security scanner (15 checks)
154
+ ├── security-rules.md # Security requirements
155
+ ├── setup-hooks.sh # Pre-commit hook installer
156
+ ├── context/
157
+ │ ├── company-profile.md # Business context
158
+ │ └── README.md
159
+ ├── skills/
160
+ │ ├── content-writing.md # Domain skill definitions
161
+ │ ├── reporting.md
162
+ │ ├── email-communications.md
163
+ │ └── seo.md
164
+ ├── agents/
165
+ │ ├── content/README.md # Specialized agent configs
166
+ │ ├── client-comms/README.md
167
+ │ └── research/README.md
168
+ ├── workflows/
169
+ │ ├── handoff-protocol.md # Agent coordination
170
+ │ └── README.md
171
+ ├── governance/
172
+ │ ├── approval-rules.json # What needs human approval
173
+ │ ├── escalation-policy.md # Escalation tiers and timeouts
174
+ │ └── README.md
175
+ └── evaluation/
176
+ ├── quality-rubric.md # Scoring criteria (1-5 scale)
177
+ ├── metrics.json # What to measure
178
+ ├── sample-audit-template.md
179
+ └── README.md
180
+ ```
181
+
182
+ ---
183
+
184
+ ## The 8 Layers
185
+
186
+ | # | Layer | Purpose | Without It |
187
+ |---|-------|---------|------------|
188
+ | 1 | **Model** | The AI engine | No AI system at all |
189
+ | 2 | **Context** | Business knowledge | Technically competent, operationally useless output |
190
+ | 3 | **Skills** | Domain expertise | Consistent, on-brand, mediocre output |
191
+ | 4 | **Tools** | External connections | A brain in a jar that can't act |
192
+ | 5 | **Orchestration** | Multi-agent coordination | Agents in silos, you become the integration layer |
193
+ | 6 | **Security** | Protection & sandboxing | Every document is an attack vector |
194
+ | 7 | **Governance** | Human oversight & accountability | Nobody responsible when AI costs money |
195
+ | 8 | **Evaluation** | Quality monitoring & drift detection | Silent erosion nobody catches |
196
+
197
+ ---
198
+
199
+ ## Features
200
+
201
+ ### Layer Scan
202
+ Binary detection across all 8 layers. Present or absent. No partial credit.
203
+
204
+ ### Quality Audit (`--audit`)
205
+ Goes beyond detection — checks if your layers are actually production-grade. Flags placeholders, missing decision frameworks, weak security configs, and generic content. Every issue gets a severity and a specific fix.
206
+
207
+ ### Migration Roadmap
208
+ When layers are missing, shows a prioritized path: what to add first, why, and how much effort. Considers dangerous combinations (tools without security, orchestration without governance).
209
+
210
+ ### Dependency Warnings
211
+ Flags dangerous layer combinations:
212
+ - "You have Tools but NO Security — every tool is an unprotected attack surface"
213
+ - "You have Orchestration but no Evaluation — multi-agent drift compounds faster"
214
+
215
+ ### Model Routing (`--routing`)
216
+ Analyzes each skill and agent, recommends the optimal model tier:
217
+ - Simple classification → Haiku/GPT-4o-mini (90% cheaper)
218
+ - Standard work → Sonnet/GPT-4o (balanced)
219
+ - Complex reasoning → Opus/o3 (worth the cost)
220
+
221
+ ### Tech Stack Detection
222
+ Auto-detects your framework, database, auth, payments, and AI SDKs. Gives stack-specific security recommendations.
223
+
224
+ ### Cost Estimation (`--costs`)
225
+ Estimates monthly costs per layer based on your model, task volume, and audit rate.
226
+
227
+ ### Snapshot Compare (`--compare`)
228
+ Save a baseline, make improvements, compare:
229
+ ```bash
230
+ npx onion-check --save-snapshot before.json
231
+ # ... make changes ...
232
+ npx onion-check --compare before.json
233
+ ```
234
+ ```
235
+ Layers: 5/8 ▲ 8/8 (+3)
236
+ Quality: 86/100 ▲ 91/100 (+5)
237
+ ```
238
+
239
+ ### Interactive Fix (`--fix`)
240
+ Walks you through each missing layer, asks the right questions, generates production-ready files.
241
+
242
+ ### Skills From Expertise
243
+ The skills generator doesn't just pick from a list. It asks if you have existing skills, audits their quality, then walks you through encoding YOUR expertise step by step. SkillStack is mentioned only as a last resort for domains where you don't have in-house knowledge.
244
+
245
+ ---
246
+
247
+ ## CLI Reference
248
+
249
+ ### `onion-check`
250
+
251
+ ```bash
252
+ npx onion-check [directory] [options]
253
+
254
+ Options:
255
+ --audit Deep quality audit + routing + tech stack + costs
256
+ --fix Interactively fix missing layers
257
+ --routing Model routing recommendations per skill/agent
258
+ --costs Monthly cost estimates per layer
259
+ --init Generate onion.config.json interactively
260
+ --report Generate onion-report.md
261
+ --json Machine-readable JSON output
262
+ --quiet Single-line output for CI (supports ONION_MIN_SCORE env var)
263
+ --compare <file> Compare against a saved snapshot
264
+ --save-snapshot <file> Save current scan as snapshot
265
+ --no-banner Skip ASCII banner
266
+ -V, --version Show version
267
+ -h, --help Show help
268
+ ```
269
+
270
+ ### `create-onion-stack`
271
+
272
+ ```bash
273
+ npx create-onion-stack <project-name> [options]
274
+
275
+ Options:
276
+ --template <type> Start from a template: agency, saas, content, support
277
+ --dry-run Preview files without creating them
278
+ --no-git Skip git initialization
279
+ --no-interview Use template defaults (skip questions)
280
+ --no-banner Skip ASCII banner
281
+ -V, --version Show version
282
+ -h, --help Show help
283
+ ```
284
+
285
+ ---
286
+
287
+ ## GitHub Action
288
+
289
+ Add to your CI pipeline:
290
+
291
+ ```yaml
292
+ name: Onion Check
293
+ on: [pull_request]
294
+
295
+ jobs:
296
+ onion:
297
+ runs-on: ubuntu-latest
298
+ steps:
299
+ - uses: actions/checkout@v4
300
+ - uses: onion-architecture/check@v1
301
+ with:
302
+ audit: true
303
+ fail-below: 4 # Fail PR if score drops below 4
304
+ comment: true # Post results as PR comment
305
+ ```
306
+
307
+ ---
308
+
309
+ ## Scoring
310
+
311
+ | Score | Badge | Level |
312
+ |-------|-------|-------|
313
+ | 1-2 | ![](https://img.shields.io/badge/onion--score-2%2F8-red?style=flat-square) | Getting Started |
314
+ | 3-4 | ![](https://img.shields.io/badge/onion--score-4%2F8-orange?style=flat-square) | Foundation |
315
+ | 5-6 | ![](https://img.shields.io/badge/onion--score-6%2F8-yellow?style=flat-square) | Production Ready |
316
+ | 7-8 | ![](https://img.shields.io/badge/onion--score-8%2F8-brightgreen?style=flat-square) | Full Stack |
317
+
318
+ Add the badge to your README:
319
+
320
+ ```markdown
321
+ ![Onion Score](https://img.shields.io/badge/onion--score-YOUR_SCORE%2F8-COLOR?style=for-the-badge)
322
+ ```
323
+
324
+ ---
325
+
326
+ ## When Each Layer Becomes Critical
327
+
328
+ | Scale | Required Layers |
329
+ |-------|----------------|
330
+ | Solo founder, internal tools | 1-3 (Model, Context, Skills) |
331
+ | Client work, real money | 1-4 + 6 (add Tools, Security) |
332
+ | Team (10-50 people) | 1-6 + lightweight 7-8 |
333
+ | Mid-size (50-500) | All 8 |
334
+ | Enterprise | All 8 at full maturity |
335
+
336
+ ---
337
+
338
+ ## The Full Article
339
+
340
+ This tool implements the framework described in [The Onion Architecture](https://michaeldavidson.io/onion-architecture) by Michael Davidson. The article covers why each layer exists, what breaks without it, and patterns from 30+ production deployments across industries.
341
+
342
+ ---
343
+
344
+ ## License
345
+
346
+ MIT
@@ -0,0 +1,24 @@
1
+ import type { OnionReport } from '../core/types.js';
2
+ import type { LayerAudit } from './index.js';
3
+ export interface CompareResult {
4
+ layerNumber: number;
5
+ layerName: string;
6
+ before: {
7
+ detected: boolean;
8
+ quality: number;
9
+ };
10
+ after: {
11
+ detected: boolean;
12
+ quality: number;
13
+ };
14
+ change: 'added' | 'removed' | 'improved' | 'regressed' | 'unchanged';
15
+ }
16
+ export declare function compareReports(before: {
17
+ report: OnionReport;
18
+ audits: LayerAudit[];
19
+ }, after: {
20
+ report: OnionReport;
21
+ audits: LayerAudit[];
22
+ }): CompareResult[];
23
+ export declare function formatComparison(results: CompareResult[], beforeLabel: string, afterLabel: string): string;
24
+ //# sourceMappingURL=compare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../src/auditor/compare.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,KAAK,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,WAAW,CAAC;CACtE;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,UAAU,EAAE,CAAA;CAAE,EACrD,KAAK,EAAE;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,UAAU,EAAE,CAAA;CAAE,GACnD,aAAa,EAAE,CA4BjB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CA+D1G"}
@@ -0,0 +1,87 @@
1
+ import { colors } from '../core/colors.js';
2
+ export function compareReports(before, after) {
3
+ const results = [];
4
+ for (let i = 0; i < before.report.layers.length; i++) {
5
+ const bLayer = before.report.layers[i];
6
+ const aLayer = after.report.layers[i];
7
+ const bAudit = before.audits.find(a => a.layerNumber === bLayer.layer.number);
8
+ const aAudit = after.audits.find(a => a.layerNumber === aLayer.layer.number);
9
+ const bQuality = bAudit?.qualityScore ?? 0;
10
+ const aQuality = aAudit?.qualityScore ?? 0;
11
+ let change = 'unchanged';
12
+ if (!bLayer.detected && aLayer.detected)
13
+ change = 'added';
14
+ else if (bLayer.detected && !aLayer.detected)
15
+ change = 'removed';
16
+ else if (aQuality > bQuality)
17
+ change = 'improved';
18
+ else if (aQuality < bQuality)
19
+ change = 'regressed';
20
+ results.push({
21
+ layerNumber: bLayer.layer.number,
22
+ layerName: bLayer.layer.name,
23
+ before: { detected: bLayer.detected, quality: bQuality },
24
+ after: { detected: aLayer.detected, quality: aQuality },
25
+ change,
26
+ });
27
+ }
28
+ return results;
29
+ }
30
+ export function formatComparison(results, beforeLabel, afterLabel) {
31
+ const c = colors;
32
+ const lines = [];
33
+ const beforeScore = results.filter(r => r.before.detected).length;
34
+ const afterScore = results.filter(r => r.after.detected).length;
35
+ const scoreDiff = afterScore - beforeScore;
36
+ const beforeQuality = results.filter(r => r.before.quality > 0);
37
+ const afterQuality = results.filter(r => r.after.quality > 0);
38
+ const avgBefore = beforeQuality.length > 0 ? Math.round(beforeQuality.reduce((s, r) => s + r.before.quality, 0) / beforeQuality.length) : 0;
39
+ const avgAfter = afterQuality.length > 0 ? Math.round(afterQuality.reduce((s, r) => s + r.after.quality, 0) / afterQuality.length) : 0;
40
+ const qualityDiff = avgAfter - avgBefore;
41
+ lines.push('');
42
+ lines.push(c.bold(' COMPARISON'));
43
+ lines.push(c.dim(' ' + '\u2500'.repeat(40)));
44
+ lines.push(` ${c.dim(beforeLabel)} ${c.dim('\u2192')} ${c.white(afterLabel)}`);
45
+ lines.push('');
46
+ // Score change
47
+ const scoreColor = scoreDiff > 0 ? c.green : scoreDiff < 0 ? c.red : c.dim;
48
+ const scoreArrow = scoreDiff > 0 ? '\u25B2' : scoreDiff < 0 ? '\u25BC' : '\u2500';
49
+ lines.push(` ${c.bold('Layers:')} ${beforeScore}/8 ${scoreColor(`${scoreArrow} ${afterScore}/8`)} ${scoreDiff !== 0 ? scoreColor(`(${scoreDiff > 0 ? '+' : ''}${scoreDiff})`) : ''}`);
50
+ const qualColor = qualityDiff > 0 ? c.green : qualityDiff < 0 ? c.red : c.dim;
51
+ const qualArrow = qualityDiff > 0 ? '\u25B2' : qualityDiff < 0 ? '\u25BC' : '\u2500';
52
+ lines.push(` ${c.bold('Quality:')} ${avgBefore}/100 ${qualColor(`${qualArrow} ${avgAfter}/100`)} ${qualityDiff !== 0 ? qualColor(`(${qualityDiff > 0 ? '+' : ''}${qualityDiff})`) : ''}`);
53
+ lines.push('');
54
+ // Per-layer changes
55
+ const changes = results.filter(r => r.change !== 'unchanged');
56
+ if (changes.length > 0) {
57
+ lines.push(c.bold(' Changes:'));
58
+ lines.push('');
59
+ for (const r of changes) {
60
+ switch (r.change) {
61
+ case 'added':
62
+ lines.push(` ${c.green('\u2713 ADDED')} Layer ${r.layerNumber}: ${r.layerName} ${c.dim(`(quality: ${r.after.quality}/100)`)}`);
63
+ break;
64
+ case 'removed':
65
+ lines.push(` ${c.red('\u2717 REMOVED')} Layer ${r.layerNumber}: ${r.layerName}`);
66
+ break;
67
+ case 'improved': {
68
+ const diff = r.after.quality - r.before.quality;
69
+ lines.push(` ${c.green('\u25B2 IMPROVED')} Layer ${r.layerNumber}: ${r.layerName} ${c.dim(`${r.before.quality} \u2192 ${r.after.quality}`)} ${c.green(`(+${diff})`)}`);
70
+ break;
71
+ }
72
+ case 'regressed': {
73
+ const diff = r.after.quality - r.before.quality;
74
+ lines.push(` ${c.red('\u25BC REGRESSED')} Layer ${r.layerNumber}: ${r.layerName} ${c.dim(`${r.before.quality} \u2192 ${r.after.quality}`)} ${c.red(`(${diff})`)}`);
75
+ break;
76
+ }
77
+ }
78
+ }
79
+ lines.push('');
80
+ }
81
+ else {
82
+ lines.push(c.dim(' No changes detected.'));
83
+ lines.push('');
84
+ }
85
+ return lines.join('\n');
86
+ }
87
+ //# sourceMappingURL=compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare.js","sourceRoot":"","sources":["../../src/auditor/compare.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { OnionConfig } from '../core/config.js';
2
+ import type { OnionReport } from '../core/types.js';
3
+ export interface CostEstimate {
4
+ layer: string;
5
+ description: string;
6
+ monthlyEstimate: string;
7
+ basis: string;
8
+ }
9
+ export declare function estimateCosts(report: OnionReport, config: OnionConfig | null): CostEstimate[];
10
+ export declare function formatCostEstimates(estimates: CostEstimate[]): string;
11
+ //# sourceMappingURL=cost.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/auditor/cost.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;CACf;AAsBD,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,GAAG,YAAY,EAAE,CAmE7F;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,MAAM,CAoBrE"}
@@ -0,0 +1,102 @@
1
+ import { colors } from '../core/colors.js';
2
+ // Rough per-1K-token costs (input) as of early 2026
3
+ const MODEL_COSTS = {
4
+ 'opus': { input: 0.015, output: 0.075, label: 'Opus-class' },
5
+ 'sonnet': { input: 0.003, output: 0.015, label: 'Sonnet-class' },
6
+ 'haiku': { input: 0.0008, output: 0.004, label: 'Haiku-class' },
7
+ 'gpt-4o': { input: 0.005, output: 0.015, label: 'GPT-4o' },
8
+ 'gpt-4o-mini': { input: 0.00015, output: 0.0006, label: 'GPT-4o-mini' },
9
+ 'default': { input: 0.003, output: 0.015, label: 'Mid-tier model' },
10
+ };
11
+ function getModelTier(modelName) {
12
+ const lower = modelName.toLowerCase();
13
+ if (lower.includes('opus'))
14
+ return MODEL_COSTS['opus'];
15
+ if (lower.includes('haiku'))
16
+ return MODEL_COSTS['haiku'];
17
+ if (lower.includes('sonnet'))
18
+ return MODEL_COSTS['sonnet'];
19
+ if (lower.includes('gpt-4o-mini') || lower.includes('4o-mini'))
20
+ return MODEL_COSTS['gpt-4o-mini'];
21
+ if (lower.includes('gpt-4o') || lower.includes('gpt-4'))
22
+ return MODEL_COSTS['gpt-4o'];
23
+ return MODEL_COSTS['default'];
24
+ }
25
+ export function estimateCosts(report, config) {
26
+ const estimates = [];
27
+ const model = config?.layers.model.primary || 'claude-sonnet-4-20250514';
28
+ const tier = getModelTier(model);
29
+ const has = (n) => report.layers.find(l => l.layer.number === n)?.detected ?? false;
30
+ // Estimate tasks per month based on what's detected
31
+ const hasTools = has(4);
32
+ const hasOrchestration = has(5);
33
+ const agentCount = config?.layers.orchestration.agents.length || 1;
34
+ // Base volume estimate
35
+ const tasksPerDay = hasOrchestration ? agentCount * 20 : 10;
36
+ const tasksPerMonth = tasksPerDay * 22; // business days
37
+ const avgTokensPerTask = 2000; // ~1K in, ~1K out
38
+ // Layer 1: Model — base cost
39
+ const baseMonthlyCost = tasksPerMonth * (avgTokensPerTask / 1000) * ((tier.input + tier.output) / 2);
40
+ estimates.push({
41
+ layer: 'Layer 1: Model',
42
+ description: `${tier.label} at ~${tasksPerMonth} tasks/month`,
43
+ monthlyEstimate: `$${baseMonthlyCost.toFixed(0)}-${(baseMonthlyCost * 1.5).toFixed(0)}`,
44
+ basis: `${tasksPerDay} tasks/day × ${avgTokensPerTask} avg tokens × ${tier.label} pricing`,
45
+ });
46
+ // Layer 3: Skills — negligible extra (skills are instructions, not extra calls)
47
+ // Layer 5: Orchestration — multiplier for routing + multiple agents
48
+ if (has(5) && agentCount > 1) {
49
+ const routingOverhead = tasksPerMonth * 0.2 * (500 / 1000) * tier.input; // 20% need routing, 500 tokens each
50
+ estimates.push({
51
+ layer: 'Layer 5: Orchestration',
52
+ description: `Routing overhead for ${agentCount} agents`,
53
+ monthlyEstimate: `+$${routingOverhead.toFixed(0)}-${(routingOverhead * 2).toFixed(0)}`,
54
+ basis: '~20% of tasks need routing decisions (~500 tokens each)',
55
+ });
56
+ }
57
+ // Layer 8: Evaluation — benchmark cost
58
+ if (has(8) || config?.layers.evaluation) {
59
+ const auditPct = config?.layers.evaluation.auditPercentage || 5;
60
+ const sampledTasks = Math.ceil(tasksPerMonth * (auditPct / 100));
61
+ const evalTokens = 1500; // re-evaluate output quality
62
+ const evalCost = sampledTasks * (evalTokens / 1000) * ((tier.input + tier.output) / 2);
63
+ estimates.push({
64
+ layer: 'Layer 8: Evaluation',
65
+ description: `${auditPct}% audit rate (${sampledTasks} samples/month)`,
66
+ monthlyEstimate: `+$${evalCost.toFixed(0)}-${(evalCost * 2).toFixed(0)}`,
67
+ basis: `${sampledTasks} sampled outputs × ${evalTokens} tokens per evaluation`,
68
+ });
69
+ }
70
+ else {
71
+ const auditPct = 5;
72
+ const sampledTasks = Math.ceil(tasksPerMonth * (auditPct / 100));
73
+ const evalTokens = 1500;
74
+ const evalCost = sampledTasks * (evalTokens / 1000) * ((tier.input + tier.output) / 2);
75
+ estimates.push({
76
+ layer: 'Layer 8: Evaluation (if added)',
77
+ description: `${auditPct}% audit rate would cost`,
78
+ monthlyEstimate: `+$${evalCost.toFixed(0)}-${(evalCost * 2).toFixed(0)}`,
79
+ basis: `${sampledTasks} sampled outputs × ${evalTokens} tokens per evaluation`,
80
+ });
81
+ }
82
+ return estimates;
83
+ }
84
+ export function formatCostEstimates(estimates) {
85
+ if (estimates.length === 0)
86
+ return '';
87
+ const c = colors;
88
+ const lines = [];
89
+ lines.push('');
90
+ lines.push(c.bold(' COST ESTIMATES'));
91
+ lines.push(c.dim(' ' + '\u2500'.repeat(40)));
92
+ lines.push(c.dim(' Rough estimates based on detected config. Actual costs vary.'));
93
+ lines.push('');
94
+ for (const est of estimates) {
95
+ lines.push(` ${c.white(est.layer)}`);
96
+ lines.push(` ${c.cyan(est.monthlyEstimate)}/mo ${c.dim('\u2014 ' + est.description)}`);
97
+ lines.push(c.dim(` Basis: ${est.basis}`));
98
+ lines.push('');
99
+ }
100
+ return lines.join('\n');
101
+ }
102
+ //# sourceMappingURL=cost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/auditor/cost.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { OnionReport } from '../core/types.js';
2
+ export interface DependencyWarning {
3
+ severity: 'critical' | 'warning';
4
+ message: string;
5
+ explanation: string;
6
+ }
7
+ export declare function checkDependencies(report: OnionReport): DependencyWarning[];
8
+ export declare function formatDependencyWarnings(warnings: DependencyWarning[]): string;
9
+ //# sourceMappingURL=dependencies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../src/auditor/dependencies.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,UAAU,GAAG,SAAS,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,iBAAiB,EAAE,CAoE1E;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,MAAM,CAmB9E"}