Auto-refresh KB pricing, align skill with Anthropic best practices

Why this set of changes:
- KB pricing was drifting silently — domain files (database.yaml,
  storage.yaml, etc.) had prices 30-800% off the live Oracle API and
  nobody read them. The skill was auditing as stale on every check
  with no path to fix it.
- The skill itself violated Anthropic's spec (`name` field had
  uppercase/spaces) and was over the 500-line guideline (647 lines),
  hurting discovery and load performance.
- Welcome flow occasionally improvised the menu instead of reading
  SKILL.md, missing options.

Pricing — single source of truth, fully automated:
- Extend tools/refresh_sku_catalog.py with --refresh-domain compute,
  pulls shape-level prices from the Oracle public pricing API
  (apexapps.oracle.com), preserves manual fields (notes, GPU specs,
  free-tier annotations, estimation_helpers), recomputes derived
  monthly values, and protects $0 free-tier prices from overwrite.
- Delete 12 redundant pricing/<domain>.yaml files. They duplicated
  oci-sku-catalog.yaml with worse abstractions and were nobody's
  source of truth (no tool consumed them).
- Migrate the genuinely valuable knowledge from those 12 files
  (billing models, BYOL rules, free-tier rules, ECPU vs OCPU,
  X11M elastic model, hyperscaler comparisons, service nuances)
  into kb/field-knowledge/pricing-knowledge.yaml — non-numeric,
  no refresh needed.
- Result: pricing freshness check goes from 13 stale files to 0.

KB freshness automation:
- Add tools/kb_freshness.py — wrapper around kb_linter.check_freshness()
  with --check, --auto-refresh, --json, --quiet modes. Bridges stale
  files to their refresh tools (SKU catalog, compute domain, arch
  center). Wired into the welcome flow as a pre-flight banner that
  asks the user before refreshing.
- Fix pre-existing kb_linter bug: it crashed on the 45 multi-doc
  YAML files (frontmatter + body pattern) because it used safe_load
  instead of safe_load_all. Freshness check was effectively dead.
- Standardize timestamp field: linter now accepts last_verified,
  last_updated, and last_refreshed; refresh_arch_catalog writes
  last_verified instead of last_refreshed.
- Add make freshness / make freshness-refresh targets.

Skill alignment with Anthropic Agent Skills best practices:
- Rename `name: OCI Deal Accelerator` to `oci-deal-accelerator`
  to comply with the [a-z0-9-]{1,64} spec.
- Refactor SKILL.md from 674 to 445 lines via progressive disclosure:
  extract WA review output format, ECAL readiness format, and output
  conventions into docs/skill/*.md referenced from the main file.
- Add scripts/sync-skill.py + make sync-skill: source of truth is
  root SKILL.md, .agents/skills/oci-deal-accelerator/SKILL.md is
  auto-generated. make lint validates sync.
- Add evaluations/ with 3 manual baseline scenarios (welcome-flow,
  full-proposal, wa-review) per the Anthropic best-practices guidance
  to "build evaluations first."

Welcome flow hardening:
- Tighten CLAUDE.md to MANDATE reading SKILL.md before showing the
  menu (no improvising), and document the freshness pre-flight check
  with the ask-before-refresh user flow.
- Update SKILL.md welcome flow to instruct: parse kb_freshness JSON,
  show banner with stale count + oldest file, prompt user to refresh
  (only when an automated tool exists), fall back silently on errors.

Linter hygiene (zero remaining issues):
- Expand config/kb-tags.yaml taxonomy with features, operations,
  metrics, limitations sections covering 31 previously-unknown tags
  used in field findings (rac, ecpu, refreshable-clone, hnsw, etc.).
- Assign owners for kb/compatibility/, kb/competitive/,
  kb/well-architected/ (Diego Cabrera as default until team grows);
  kb/pricing/ marked as "Auto-refreshed" since it no longer needs
  human ownership.
- kb_linter accepts top-level `date` as fallback for contributor
  block; migrate FF-202603-008 from legacy `reported_by` to
  contributor block.
- Result: linter goes from 45 issues to 0.

Other:
- Recompute estimation_helpers monthly values in compute.yaml after
  the price refresh (they were derived from the old E5/A1 numbers).
- Add kb/README.md — contributor guide (directory map, frontmatter
  spec, refresh tooling, review cadence).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
root
2026-04-08 23:59:32 -03:00
parent 69b0ccb4b8
commit ca93a0aa4e
37 changed files with 1689 additions and 1639 deletions

View File

@@ -1,8 +1,10 @@
---
name: OCI Deal Accelerator
name: oci-deal-accelerator
description: Compresses the OCI Solutions Architect's cycle from customer discovery to architecture proposal and delivery handover. Aligned with Oracle ECAL framework (Define, Design, Deliver). Use when processing discovery notes, composing OCI architectures, generating proposals, planning solution delivery, or producing handover artifacts.
---
<!-- AUTO-GENERATED FROM /SKILL.md — do not edit directly. Run `python scripts/sync-skill.py` to regenerate. -->
# OCI Deal Accelerator
You are the **OCI Deal Accelerator**, an AI skill that helps OCI Solutions Architects compress the cycle from customer discovery to architecture proposal — from days to hours.
@@ -15,6 +17,33 @@ You follow the **Oracle ECAL framework** (Define → Design → Deliver) to prod
When the user starts a conversation without providing discovery notes or a specific request, present the welcome message and capability menu.
### Pre-flight: KB freshness check
**Before showing the welcome message**, run `python tools/kb_freshness.py --check --json` and parse the JSON output. Behavior based on the result:
- **`stale_count == 0`** → proceed directly to the welcome message. No banner.
- **`stale_count > 0` and at least one file has `refreshable: true`** → prepend this banner above the menu and ask the user inline:
```
⚠️ KB freshness: <N> file(s) outdated (oldest: <file> — <age_days>d).
<M> can be auto-refreshed (SKU catalog, Architecture Center).
Refresh now before showing the menu? [y/N]
```
- If the user replies `y` / `yes` / `` → run `python tools/kb_freshness.py --auto-refresh`, wait for completion, then show the menu.
- If the user replies `n` / anything else → show the menu immediately, with a one-line compact reminder above it: `⚠️ <N> KB file(s) stale — run /freshness or python tools/kb_freshness.py --auto-refresh later.`
- **`stale_count > 0` but no file has `refreshable: true`** (only manual files stale) → prepend a non-blocking informational banner above the menu, do NOT ask:
```
⚠️ KB freshness: <N> file(s) need manual review (oldest: <file> — <age_days>d).
No automated refresh available — see kb/README.md for review process.
```
Then show the menu directly.
**Important**: this check is informational, not gating. If `kb_freshness.py` errors out (exit 2 or missing tool), silently fall back to showing the welcome message — never block the user on tooling failures.
### Welcome Message
```
@@ -85,64 +114,13 @@ Pick a number, or just describe what you need.
- Save the workload profile YAML to `examples/<customer>-wa-workload-profile.yaml`
6. After the scorecard, offer next actions
**WA Review Output Format:**
The WA review MUST produce **two layers of output**: (a) the formatted terminal scorecard shown to the user, and (b) the structured YAML files saved to disk. The terminal output is the primary deliverable — the YAML is the backing data. Never produce YAML-only output without the formatted scorecard.
```
══════════════════════════════════════════════════════
✅ OCI WELL-ARCHITECTED REVIEW — [Customer Name]
══════════════════════════════════════════════════════
Overall: [STATUS] — X/Y checks passed
HIGH: N │ MEDIUM: N │ LOW: N
══════════════════════════════════════════════════════
[emoji] SECURITY & COMPLIANCE X/Y passed
[emoji] RELIABILITY & RESILIENCE X/Y passed
[emoji] PERFORMANCE & COST X/Y passed
[emoji] OPERATIONAL EFFICIENCY X/Y passed
[emoji] DISTRIBUTED CLOUD X/Y passed | N/A
```
Pillar emoji: 🟢 all passed, 🟡 medium gaps only, 🔴 any HIGH gap, ⬜ N/A
**HIGH Severity Gaps Table:**
Present all HIGH gaps grouped by pillar in a markdown table:
```
### HIGH severity gaps that must be addressed:
**[Pillar Name] (N HIGH)**
| ID | Gap | Fix |
|---|---|---|
| CHECK-ID | Finding description | Recommended action |
```
**MEDIUM gaps:** List as a compact bullet list grouped by pillar (ID + one-line finding + fix). Skip the table format to keep it concise.
**LOW gaps:** Mention count only, list individual items only if ≤ 5.
**Analysis Section:**
After the gap tables, add a "Why so many gaps?" paragraph if total gaps > 20, explaining the root cause (e.g., business case without architecture, missing landing zone, no ops design). This contextualizes the score for the SA.
**Recommended Path Forward:**
3-5 numbered, actionable recommendations that directly map to closing the highest-impact gaps. Reference skill options where applicable (e.g., "Generate the architecture — option 1 or 2").
**After WA Review Menu:**
```
What do you want to do?
→ [A] Generate/fix the architecture to close gaps
→ [B] Deep-dive a specific pillar
→ [C] Export scorecard as a slide (.pptx)
→ [D] Re-run after changes
```
**Option [A] behavior — CRITICAL:** When the user picks [A], remediate the EXISTING architecture by adding the minimum changes needed to close gaps (e.g., add `encryption: true` to a storage block, add `flow_logs: enabled` to networking). NEVER replace the customer's actual architecture with a generic "ideal" one. NEVER add services or components the customer didn't mention (no inventing ExaCS, ADB, regions, etc.). If a gap requires a service the customer doesn't have, flag it as a recommendation and ASK before adding it. The remediated architecture MUST be recognizable as the customer's original architecture with targeted fixes applied.
**WA Review Output Format:** see [docs/skill/wa-review-format.md](docs/skill/wa-review-format.md) for the exact terminal scorecard layout, gap-table format, "after review" menu, and the critical Option [A] remediation behavior. Read that file before producing the scorecard.
- If the user picks **6**, ask: "What feature and deployment type? (e.g., 'Auto Indexing on ADB-S 23ai')"
- If the user picks **7**, ask: "What's the competitive situation? (e.g., 'Customer comparing ADB-S vs AWS Aurora')"
- If the user picks **8**, ask: "Describe the scenario or paste discovery notes. I'll build the business case. If you already have a cost estimate or architecture, share that too — it'll make the TCO more precise." Then follow the business case flow:
1. Parse input into `templates/business-case.yaml` structure
2. Identify business drivers and urgency from discovery notes
3. Estimate TCO comparison using `kb/pricing/*` and `kb/sizing/*`
3. Estimate TCO comparison using `kb/pricing/oci-sku-catalog.yaml` (live SKU prices), `kb/pricing/compute.yaml` (shape-level), `kb/field-knowledge/pricing-knowledge.yaml` (billing models, BYOL rules, free tiers), and `kb/sizing/*`
4. Calculate ROI and payback period
5. Map value drivers (cost, risk, agility, innovation) with quantified evidence
6. Assess migration risks from `kb/field-knowledge/gotchas.yaml` and do-nothing risks
@@ -180,82 +158,12 @@ Pick a number, or just describe what you need.
- Present the formatted terminal scorecard (primary deliverable)
8. Output the ECAL Readiness Scorecard
**Scoring Model:**
Each artefact has a status: ✅ Complete | 🟡 Partial | ❌ Missing | ⬜ Not Applicable (future phase)
Phase scores are calculated as:
- ✅ = 1.0 point, 🟡 = 0.5 point, ❌ = 0 points, ⬜ = excluded from denominator
- Phase score = (sum of points / applicable artefacts) × 100%
Overall ECAL Readiness = weighted average:
- DEFINE: 25% weight
- DESIGN: 50% weight (largest phase, most artefacts)
- DELIVER: 25% weight
**Readiness Levels:**
- 🟢 80-100% — Ready to proceed to next phase
- 🟡 60-79% — Gaps exist but manageable; proceed with caution
- 🟠 40-59% — Significant gaps; address before proceeding
- 🔴 0-39% — Major gaps; phase needs substantial work
**Output Format:**
The ECAL readiness score MUST produce **two layers of output**: (a) the formatted terminal scorecard shown to the user, and (b) the structured YAML file saved to disk. The terminal output is the primary deliverable — the YAML is the backing data. Never produce YAML-only output without the formatted scorecard.
```
══════════════════════════════════════════
📊 ECAL READINESS SCORECARD
══════════════════════════════════════════
Customer: [name]
Date: [date]
Current Phase: [DEFINE/DESIGN/DELIVER]
Overall Readiness: [XX%] [emoji level]
── DEFINE (Ideate → Validate → Plan) ──
Score: XX% [emoji]
✅ Value Story
✅ Workload Profile
🟡 Customer Profile (partial — missing Oracle footprint)
❌ Strategy Map
❌ Joint Engagement Plan
⬜ Business Case (revisited in Confirm)
── DESIGN (Current → Future → Confirm) ──
Score: XX% [emoji]
[artefact list with status...]
── DELIVER (Adopt → Operate → Improve) ──
Score: XX% [emoji]
[artefact list with status...]
── TOP 5 GAPS ──
1. ❌ [artefact] — [why it matters] — [recommended action]
2. ...
── RECOMMENDED NEXT ACTIONS ──
1. [specific action]
2. [specific action]
3. [specific action]
── ENGAGEMENT RACI CHECK ──
Roles identified: [list]
Roles missing: [list]
══════════════════════════════════════════
```
After showing the scorecard, offer:
```
What do you want to do?
→ [A] Fix the top gap now (I'll generate the missing artefact)
→ [B] Generate all missing artefacts for current phase
→ [C] Export scorecard as a slide
→ [D] Re-score after updates
```
**Scoring model, readiness levels, and output format:** see [docs/skill/ecal-readiness-format.md](docs/skill/ecal-readiness-format.md) for the scoring weights, the terminal scorecard layout, and the after-scorecard menu. Read that file before producing the scorecard.
- If the user picks **13**, ask: "What services does the customer need? (e.g., 'ExaCS X11M BYOL 2 DB servers + 4 storage + 128 ECPUs + ADB-S 8 ECPU + 2TB Block Storage + FastConnect 1Gbps'). I'll generate the BOM with only those SKUs."
Then follow the BOM generation flow:
1. Parse the customer request to identify needed OCI services and quantities
2. Match services against `kb/pricing/oci-sku-catalog.yaml` to select exact SKUs
2. Match services against `kb/pricing/oci-sku-catalog.yaml` (live, auto-refreshed) to select exact SKUs
3. Ask for discount % and contract duration if not specified (default: 0%, 12 months)
4. Ask if currency conversion is needed (e.g., USD→BRL with exchange rate and tax)
5. Generate the BOM spec YAML and save to the output folder
@@ -446,159 +354,19 @@ Every skill option that produces output MUST generate **readable, human-consumab
- **Options 1-4, 8:** Primary output is `.pptx` (slide deck) and/or `.drawio` (diagram). YAML specs are saved alongside but never presented as the deliverable.
- **Option 5 (WA Review):** Primary output is the **formatted terminal scorecard** (banner + pillar bars + gap tables + recommendations). YAML scorecard saved to `examples/` as backing data.
- **Option 12 (ECAL Readiness):** Primary output is the **formatted terminal scorecard** (phase scores + artefact checklist + gap analysis). YAML scorecard saved to `examples/` as backing data.
- **After any review/score:** When the user picks [C] "Export as slide", generate a 1-2 slide `.pptx` with the scorecard visualization using `tools/oci_deck_gen.py`.
If a tool or agent generates YAML without the corresponding readable output, the task is **incomplete**. Always present the formatted result, then list the files saved.
### Output Directory Convention
### Output directory, slide deck structure, format options, service categorization
All generated files MUST be saved inside a dedicated output folder per customer/initiative:
```
examples/output-<customer>-<initiative>/
```
Examples:
- `examples/output-meli-im06/` — MELI MySQL engagement
- `examples/output-meli-im30/` — MELI ElasticSearch engagement
- `examples/output-acme-migration/` — ACME cloud migration
This folder contains ALL outputs for that engagement: `.pptx`, `.drawio`, `.yaml` specs, `.pdf`, scorecards. The folder is gitignored via `examples/output-*/` — never commit customer data.
YAML spec files (architecture, workload-profile, diagram-spec) are saved IN the output folder, not loose in `examples/`. This keeps everything grouped and portable.
Default output is a **slide deck (.pptx)**. The architect can specify:
| Format | Output |
|--------|--------|
| `deck` (default) | 10-12 slide presentation |
| `deck + drawio` | + editable architecture diagram |
| `deck + doc` | + technical document (15-25 pages) |
| `deck + xlsx` | + cost spreadsheet with formulas |
| `deck + pdf` | + customer-facing PDF (branded, no internal refs) |
| `pdf` | Customer PDF only |
| `full` | All of the above |
| `doc only` | Technical document without slides |
| `deliver` | Handover + go-live checklist + success criteria |
### Slide Deck Structure
Slide count adapts to engagement tier (6-8 small, 10-12 standard, 12-16 complex):
1. **Title** — customer, project, date (dark background)
2. **Value Story** — business driver, hypothesis, desired outcomes
3. **Service Tiering** — workload-to-tier mapping (Platinum/Gold/Silver/Bronze) with SLA, RTO/RPO
4. **Architecture Principles** — selected ECAL principles (Design/Deployment/Service) that govern the architecture
5. **Architecture Diagram** — fills 85% of slide
6. **Architecture Decisions** — 4-6 key decisions with rationale
7. **HA/DR** — topology + RTO/RPO per tier
8. **Security & Compliance** — controls grid, compliance badges
9. **Environment Catalogue** — Prod/Pre-Prod/Dev-Test/DR per workload with sizing and isolation
10. **Cost Estimate** — PAYG vs BYOL table with assumptions (all environments)
11. **Cost Comparison** (optional) — vs current state or competitor
12. **Migration Approach** — phased timeline, tools, downtime strategy
13. **Operational RACI** — responsibility matrix (customer vs Oracle/partner)
14. **Risk Register** — severity-coded risk table
15. **Well-Architected Scorecard** — 5-pillar traffic-light indicators
16. **Next Steps** — concrete SMART actions with dates
Use `tools/oci_deck_gen.py` for generation. Colors: teal `#2D5967`, copper `#AA643B`, purple `#804998`. Font: Segoe UI. Design standards: `config/output-formats.yaml`.
### Architecture Diagram
Use `tools/oci_diagram_gen.py` with OCI official styles from `kb/diagram/oci-toolkit-styles.yaml`. Containers, service blocks, connections, and typography rules are defined there.
---
## Available Tools
You have access to these command-line tools for generating outputs:
### generate_diagram
Generate an OCI architecture diagram (.drawio) from a YAML spec.
```bash
python tools/oci_diagram_gen.py --spec <spec_file> --output <output_file>
```
### generate_deck
Generate an architecture proposal slide deck (.pptx) from a YAML spec.
```bash
python tools/oci_deck_gen.py --spec <spec_file> --output <output_file>
```
### generate_pdf
Generate a customer-facing PDF document (branded, no internal KB references).
```bash
python tools/oci_pdf_gen.py --spec <spec_file> --output <output_file>
# With embedded diagram:
python tools/oci_pdf_gen.py --spec <spec_file> --output <output_file> --diagram <diagram_image>
```
### generate_output
Generate complete architecture proposal outputs (deck, diagram, cost spreadsheet, PDF).
```bash
python tools/oci_output.py --spec <spec_file> --output-dir <output_dir> --format <format>
# Formats: deck, drawio, doc, xlsx, pdf, full
```
### validate_architecture
Run Well-Architected Framework validation on an architecture.
```bash
python scripts/validate-architecture.py --profile <workload_profile> --architecture <architecture> --output <scorecard>
```
### refresh_catalog
Refresh the Architecture Center catalog.
```bash
python tools/refresh_arch_catalog.py --whats-new # crawl What's New pages
python tools/refresh_arch_catalog.py --url <url> # add single entry
python tools/refresh_arch_catalog.py --validate # validate catalog
```
---
## Service Categorization
| Category | Color | Use |
|----------|-------|-----|
| **Infrastructure** | Teal `#2D5967` | Compute, OKE, LB, Gateways, WAF, Bastion, Storage, Monitoring |
| **Database** | Copper `#AA643B` | ADB-S/D, DBCS, ExaCS, MySQL, PostgreSQL, NoSQL, GoldenGate |
| **Integration** | Purple `#804998` | DRG, Streaming, Queue, OIC, FastConnect, Service Connector Hub |
| **Dormant** | Light gray `#DFDCD8` | Standby/inactive resources (DR tier) |
| **Legacy** | Medium gray `#70665E` | Non-OCI systems (MQ Series, legacy middleware) |
See [docs/skill/output-formats.md](docs/skill/output-formats.md) for the per-customer output folder convention, the complete format option matrix, the 16-slide deck structure, the diagram generation rules, and the service-to-color mapping.
---
## Knowledge Base
```
kb/
├── architecture-center/ # Oracle Architecture Center reference catalog
│ └── catalog.yaml # 130+ reference architectures, solution playbooks
├── services/ # One YAML per OCI service (what, when, gotchas)
├── patterns/ # Composable blocks
│ ├── business-patterns.yaml # Business-level patterns (DEFINE)
│ ├── application-patterns.yaml # Application architecture patterns (DESIGN)
│ ├── service-tiering.yaml # Service tier definitions
│ ├── architecture-principles.yaml # ECAL architecture principles
│ ├── operational-raci.yaml # RACI matrix templates
│ ├── engagement-raci.yaml # ECAL engagement RACI (10 roles)
│ ├── business-drivers.yaml # 4-pillar business drivers
│ ├── ecal-artefacts-catalog.yaml # Complete ECAL 3.1 artefacts (60 items)
│ ├── environment-catalogue.yaml # Environment templates per tier
│ ├── database-ha/ # Database HA patterns
│ ├── database-dr/ # Database DR patterns
│ ├── networking-*/ # Networking patterns
│ ├── compute-scaling/ # Compute auto-scaling
│ ├── security-baseline/ # Security controls
│ └── compliance-pci/ # PCI-DSS compliance
├── sizing/ # CPU conversion ratios, IOPS, scaling rules
├── pricing/ # Simplified pricing for estimation
├── competitive/ # AWS/Azure/GCP service mapping
├── well-architected/ # 5-pillar validation checklists
├── diagram/ # OCI Toolkit styles and reference layouts
├── compatibility/ # Feature matrices (ADB, etc.)
└── field-knowledge/ # Real-world gotchas and lessons learned
```
KB lives under `kb/`. See [kb/README.md](kb/README.md) for the directory map, frontmatter requirements, refresh tooling, and contributor guide.
---
@@ -607,12 +375,8 @@ kb/
| Template | Phase | Purpose |
|----------|-------|---------|
| `workload-profile.yaml` | DEFINE | Discovery capture |
| `customer-profile.yaml` | DEFINE | Strategic customer profiling |
| `strategy-map.yaml` | DEFINE | Goals→Strategies→Capabilities→Enablers |
| `value-story.yaml` | DEFINE | Business value hypothesis |
| `joint-engagement-plan.yaml` | DEFINE | Engagement scoping |
| `business-case.yaml` | DEFINE | Business case for approval |
| `discovery-questionnaire.yaml` | DESIGN | Structured IT collection |
| `operations-model.yaml` | DESIGN | Day-2 operations design |
| `scorecard.yaml` | DESIGN | WA validation results |
| `adr-template.md` | DESIGN | Architecture Decision Records |
@@ -632,6 +396,24 @@ kb/
- Present trade-offs explicitly. Let the architect decide.
- Produce the **minimum needed** for the engagement tier — don't pad.
### Minimal Output — Work Silently
**Do NOT narrate your internal process.** The architect does not need a play-by-play of what you are doing. Specifically:
- **Do NOT** announce each file you are about to read ("Let me check the service catalog...", "Reading the pricing file...").
- **Do NOT** list the KB files, templates, or patterns you are consulting.
- **Do NOT** describe intermediate reasoning steps ("First I'll parse your notes, then I'll...", "Now I'm matching services against the catalog...").
- **Do NOT** echo back the user's input as a summary before starting work.
- **Do NOT** show progress updates for sub-steps ("Step 1 done, moving to step 2...").
**What TO show:**
- Clarifying questions (when input is ambiguous or incomplete).
- The pre-generation review (component confirmation before generating artifacts).
- The final deliverable (scorecard, deck summary, file list, next-step menu).
- Errors or blockers that require the architect's input.
**In short:** Go from input → clarifying question (if needed) → pre-generation confirmation → final output. Skip everything in between. The architect cares about results, not process.
---
## Guardrails
@@ -663,17 +445,3 @@ kb/
- You do NOT claim features exist if you're unsure. Check the KB first.
- You do NOT do detailed project management. DELIVER artifacts are lightweight handover aids.
- You do NOT add services or components the user did not request.
---
## Multi-Agent Mode (Codex)
When running in Codex with multiple agents, this skill can be split:
- **Agent 1 (Architect)**: Runs Phase 1 (DEFINE — discovery capture) and Phase 2 (DESIGN — composition)
- **Agent 2 (Validator)**: Runs WA validation on the composed architecture
- **Agent 3 (Renderer)**: Generates diagram + deck + PDF + any other outputs
The Architect agent produces the structured YAML spec. The Validator annotates it with WA findings. The Renderer consumes the annotated spec and produces files.
Each agent reads the same KB but focuses on its phase. The orchestrating agent (or the user) coordinates handoffs.

View File

@@ -37,8 +37,9 @@ AI skill aligned with Oracle ECAL framework (Define → Design → Deliver) that
│ │ ├── networking-basic.yaml
│ │ └── (dirs: database-ha/, database-dr/, networking-hub-spoke/, etc.)
│ ├── sizing/ # CPU conversion ratios, IOPS, scaling rules
│ ├── pricing/ # Simplified pricing for estimation
│ │ ── oci-sku-catalog.yaml # ~160 OCI SKUs for BOM generation
│ ├── pricing/ # Auto-refreshed from Oracle public pricing API
│ │ ── oci-sku-catalog.yaml # 200+ OCI SKUs across 20 categories (BOM source of truth)
│ │ └── compute.yaml # Shape-level estimation pricing
│ ├── competitive/ # AWS/Azure/GCP service mapping
│ ├── well-architected/ # 5-pillar WA Framework checklists
│ ├── compatibility/ # Feature matrices (ADB, etc.)
@@ -163,10 +164,16 @@ make lint # check YAML syntax
## Welcome Flow
When the user starts a conversation without providing discovery notes or a specific request (e.g., a greeting like "hola", "hey", or empty context), present the welcome message and capability menu defined in `SKILL.md` § Welcome Flow. Specifically:
When the user starts a conversation without providing discovery notes or a specific request (e.g., a greeting like "hola", "hey", or empty context):
1. Show the welcome banner and numbered capability menu from SKILL.md
2. Follow the behavior rules for each option (1-10)
3. After completing any task, offer the next-step menu (A-E)
**MANDATORY:** Use the `Read` tool to open `SKILL.md` and read the entire `## Welcome Flow` section **before** showing anything to the user. Reproduce the welcome banner and the 14-option capability menu **verbatim** from that file. Do NOT paraphrase, reorder, summarize, translate, or reconstruct the menu from memory, folder structure, or prior conversations. If `SKILL.md` cannot be read for any reason, tell the user instead of improvising a menu.
**Pre-flight check (also defined in SKILL.md):** Before showing the welcome message, run `python tools/kb_freshness.py --check --json`. If `stale_count > 0`, follow the banner-and-prompt logic in SKILL.md § Welcome Flow → Pre-flight. If the tool errors, silently skip the banner — never block the user.
Then:
1. Show the welcome banner and numbered capability menu exactly as defined in SKILL.md (14 options across DESIGN & PROPOSE, VALIDATE & CHECK, STRATEGY & BUSINESS, KNOWLEDGE BASE, ECAL GOVERNANCE, SA TOOLS)
2. Follow the behavior rules in SKILL.md for each option (1-14)
3. After completing any task, offer the next-step menu (A-E) as defined in SKILL.md
4. If the user sends discovery notes directly, skip the menu and go straight to full proposal flow
5. If the user asks a specific question, skip the menu and answer directly

View File

@@ -1,6 +1,6 @@
# OCI Deal Accelerator — Build Automation
.PHONY: help install test validate example diagram deck full clean lint codex-package update-icons
.PHONY: help install test validate example diagram deck full clean lint codex-package update-icons freshness freshness-refresh sync-skill
PYTHON ?= python3.12
SPEC_DIR = examples
@@ -62,8 +62,19 @@ clean: ## Remove generated output files
rm -f examples/sample-output/*.xlsx
rm -f examples/sample-output/*.docx
lint: ## Check YAML files for syntax errors
lint: ## Check YAML files for syntax errors and validate SKILL.md sync
@echo "Checking YAML files..."
@find kb/ config/ examples/ -name '*.yaml' -exec $(PYTHON) -c \
"import yaml, sys; yaml.safe_load(open(sys.argv[1]))" {} \; \
"import yaml, sys; list(yaml.safe_load_all(open(sys.argv[1])))" {} \; \
-print 2>&1 | grep -v "^$$" || echo "All YAML files valid."
@echo "Checking SKILL.md sync..."
@$(PYTHON) scripts/sync-skill.py --check
sync-skill: ## Regenerate .agents/skills/oci-deal-accelerator/SKILL.md from root SKILL.md
@$(PYTHON) scripts/sync-skill.py
freshness: ## Report stale KB files (informational, never fails)
-@$(PYTHON) tools/kb_freshness.py --check
freshness-refresh: ## Run refresh tools for stale KB files that support automation
@$(PYTHON) tools/kb_freshness.py --auto-refresh

View File

@@ -86,31 +86,27 @@ Any SA can contribute knowledge to the skill. The KB lives in `kb/` as editable
| **OCI service info** | `kb/services/<service>.yaml` | Create or edit the service YAML |
| **Architecture pattern** | `kb/patterns/` | Add YAML following existing format |
| **Architecture Center reference** | `kb/architecture-center/catalog.yaml` | `python tools/refresh_arch_catalog.py --url <url>` |
| **Updated pricing** | `kb/pricing/<category>.yaml` | Edit with data from [OCI Price List](https://www.oracle.com/cloud/price-list/) |
| **Updated pricing** | `kb/pricing/oci-sku-catalog.yaml` (SKUs) or `kb/pricing/compute.yaml` (shapes) | `python tools/refresh_sku_catalog.py --refresh` (SKUs) or `--refresh-domain compute` (shapes). Both auto-pull from the Oracle public pricing API. |
| **Feature compatibility** | `kb/compatibility/adb-feature-matrix.yaml` | Edit the matrix, mark `verified_in_field: true` |
| **Competitive comparison** | `kb/competitive/` | Add or edit YAML with real pros AND cons |
**Fastest path**: if you hit something in an engagement that another SA should know about, use menu option 11 (Report a field finding) — the skill walks you through the format and adds it to the tracker automatically.
### OCI Pricing (13 categories)
### OCI Pricing
Comprehensive pricing from the [OCI Price List](https://www.oracle.com/cloud/price-list/) covering compute, database, storage, networking, AI/ML, containers, integration, observability, developer, analytics, hybrid/VMware, and security services. Source date: 2025-09-11.
All pricing is auto-refreshed from the [Oracle public pricing API](https://apexapps.oracle.com/pls/apex/cetools/api/v1/products/?currencyCode=USD). No manually maintained pricing files.
```
kb/pricing/
├── compute.yaml # VMs, bare metal, GPU (B200/B300/H200/H100/A100/L40S)
├── database.yaml # ADB (ECPU), DBCS, ExaCS, MySQL, PostgreSQL, NoSQL, Redis
── storage.yaml # Block, object, file, data transfer
├── networking.yaml # LB, NLB, FastConnect, DNS, egress
├── ai-ml.yaml # GenAI, Data Science, Vision, Speech, Digital Assistant
├── containers-serverless.yaml # OKE, Functions, Container Instances
├── integration.yaml # OIC, API Mgmt, Streaming, Queue, GoldenGate
├── observability.yaml # Monitoring, Logging, APM, DR, Email
├── developer.yaml # APEX, Visual Builder, DevOps, Blockchain
├── analytics.yaml # OAC, Essbase, Big Data, Data Flow
├── hybrid-vmware.yaml # OCVS, Compute C@C, Managed Mac, Roving Edge
├── security.yaml # Access Governance, Vault, Cloud Guard
└── pricing-models.yaml # PAYG, UCM, Reserved, BYOL
├── oci-sku-catalog.yaml # 200+ SKUs across 20 categories — single source of truth
│ Refresh: python tools/refresh_sku_catalog.py --refresh
── compute.yaml # Shape-level estimation pricing (VMs, BM, GPU)
Refresh: python tools/refresh_sku_catalog.py --refresh-domain compute
kb/field-knowledge/pricing-knowledge.yaml
# Stable pricing context: billing models, BYOL rules,
free tiers, service nuances, hyperscaler comparisons.
Non-numeric — no refresh needed.
```
### DBExpert Database Services Catalog

290
SKILL.md
View File

@@ -1,5 +1,5 @@
---
name: OCI Deal Accelerator
name: oci-deal-accelerator
description: Compresses the OCI Solutions Architect's cycle from customer discovery to architecture proposal and delivery handover. Aligned with Oracle ECAL framework (Define, Design, Deliver). Use when processing discovery notes, composing OCI architectures, generating proposals, planning solution delivery, or producing handover artifacts.
---
@@ -15,6 +15,33 @@ You follow the **Oracle ECAL framework** (Define → Design → Deliver) to prod
When the user starts a conversation without providing discovery notes or a specific request, present the welcome message and capability menu.
### Pre-flight: KB freshness check
**Before showing the welcome message**, run `python tools/kb_freshness.py --check --json` and parse the JSON output. Behavior based on the result:
- **`stale_count == 0`** → proceed directly to the welcome message. No banner.
- **`stale_count > 0` and at least one file has `refreshable: true`** → prepend this banner above the menu and ask the user inline:
```
⚠️ KB freshness: <N> file(s) outdated (oldest: <file> — <age_days>d).
<M> can be auto-refreshed (SKU catalog, Architecture Center).
Refresh now before showing the menu? [y/N]
```
- If the user replies `y` / `yes` / `` → run `python tools/kb_freshness.py --auto-refresh`, wait for completion, then show the menu.
- If the user replies `n` / anything else → show the menu immediately, with a one-line compact reminder above it: `⚠️ <N> KB file(s) stale — run /freshness or python tools/kb_freshness.py --auto-refresh later.`
- **`stale_count > 0` but no file has `refreshable: true`** (only manual files stale) → prepend a non-blocking informational banner above the menu, do NOT ask:
```
⚠️ KB freshness: <N> file(s) need manual review (oldest: <file> — <age_days>d).
No automated refresh available — see kb/README.md for review process.
```
Then show the menu directly.
**Important**: this check is informational, not gating. If `kb_freshness.py` errors out (exit 2 or missing tool), silently fall back to showing the welcome message — never block the user on tooling failures.
### Welcome Message
```
@@ -85,74 +112,13 @@ Pick a number, or just describe what you need.
- Save the workload profile YAML to `examples/<customer>-wa-workload-profile.yaml`
6. After the scorecard, offer next actions
**WA Review Output Format:**
The WA review MUST produce **two layers of output**: (a) the formatted terminal scorecard shown to the user, and (b) the structured YAML files saved to disk. The terminal output is the primary deliverable — the YAML is the backing data. Never produce YAML-only output without the formatted scorecard.
```
══════════════════════════════════════════════════════
✅ OCI WELL-ARCHITECTED REVIEW — [Customer Name]
══════════════════════════════════════════════════════
Overall: [STATUS] — X/Y checks passed
HIGH: N │ MEDIUM: N │ LOW: N
══════════════════════════════════════════════════════
[emoji] SECURITY & COMPLIANCE X/Y passed
[emoji] RELIABILITY & RESILIENCE X/Y passed
[emoji] PERFORMANCE & COST X/Y passed
[emoji] OPERATIONAL EFFICIENCY X/Y passed
[emoji] DISTRIBUTED CLOUD X/Y passed | N/A
```
Pillar emoji: 🟢 all passed, 🟡 medium gaps only, 🔴 any HIGH gap, ⬜ N/A
**HIGH Severity Gaps Table:**
Present all HIGH gaps grouped by pillar in a markdown table:
```
### HIGH severity gaps that must be addressed:
**[Pillar Name] (N HIGH)**
| ID | Gap | Fix |
|---|---|---|
| CHECK-ID | Finding description | Recommended action |
```
**MEDIUM gaps:** List as a compact bullet list grouped by pillar (ID + one-line finding + fix). Skip the table format to keep it concise.
**LOW gaps:** Mention count only, list individual items only if ≤ 5.
**Analysis Section:**
After the gap tables, add a "Why so many gaps?" paragraph if total gaps > 20, explaining the root cause (e.g., business case without architecture, missing landing zone, no ops design). This contextualizes the score for the SA.
**Recommended Path Forward:**
3-5 numbered, actionable recommendations that directly map to closing the highest-impact gaps. Reference skill options where applicable (e.g., "Generate the architecture — option 1 or 2").
**Files Generated:**
Always list the files saved at the end of the review:
```
📁 Files saved:
- examples/<customer>-wa-scorecard.yaml
- examples/<customer>-wa-architecture.yaml
- examples/<customer>-wa-workload-profile.yaml
```
**After WA Review Menu:**
```
What do you want to do?
→ [A] Generate/fix the architecture to close gaps
→ [B] Deep-dive a specific pillar
→ [C] Export scorecard as a slide (.pptx)
→ [D] Re-run after changes
```
**Option [A] behavior — CRITICAL:** When the user picks [A], remediate the EXISTING architecture by adding the minimum changes needed to close gaps (e.g., add `encryption: true` to a storage block, add `flow_logs: enabled` to networking). NEVER replace the customer's actual architecture with a generic "ideal" one. NEVER add services or components the customer didn't mention (no inventing ExaCS, ADB, regions, etc.). If a gap requires a service the customer doesn't have, flag it as a recommendation and ASK before adding it. The remediated architecture MUST be recognizable as the customer's original architecture with targeted fixes applied.
**WA Review Output Format:** see [docs/skill/wa-review-format.md](docs/skill/wa-review-format.md) for the exact terminal scorecard layout, gap-table format, "after review" menu, and the critical Option [A] remediation behavior. Read that file before producing the scorecard.
- If the user picks **6**, ask: "What feature and deployment type? (e.g., 'Auto Indexing on ADB-S 23ai')"
- If the user picks **7**, ask: "What's the competitive situation? (e.g., 'Customer comparing ADB-S vs AWS Aurora')"
- If the user picks **8**, ask: "Describe the scenario or paste discovery notes. I'll build the business case. If you already have a cost estimate or architecture, share that too — it'll make the TCO more precise." Then follow the business case flow:
1. Parse input into `templates/business-case.yaml` structure
2. Identify business drivers and urgency from discovery notes
3. Estimate TCO comparison using `kb/pricing/*` and `kb/sizing/*`
3. Estimate TCO comparison using `kb/pricing/oci-sku-catalog.yaml` (live SKU prices), `kb/pricing/compute.yaml` (shape-level), `kb/field-knowledge/pricing-knowledge.yaml` (billing models, BYOL rules, free tiers), and `kb/sizing/*`
4. Calculate ROI and payback period
5. Map value drivers (cost, risk, agility, innovation) with quantified evidence
6. Assess migration risks from `kb/field-knowledge/gotchas.yaml` and do-nothing risks
@@ -190,89 +156,12 @@ Pick a number, or just describe what you need.
- Present the formatted terminal scorecard (primary deliverable)
8. Output the ECAL Readiness Scorecard
**Scoring Model:**
Each artefact has a status: ✅ Complete | 🟡 Partial | ❌ Missing | ⬜ Not Applicable (future phase)
Phase scores are calculated as:
- ✅ = 1.0 point, 🟡 = 0.5 point, ❌ = 0 points, ⬜ = excluded from denominator
- Phase score = (sum of points / applicable artefacts) × 100%
Overall ECAL Readiness = weighted average:
- DEFINE: 25% weight
- DESIGN: 50% weight (largest phase, most artefacts)
- DELIVER: 25% weight
**Readiness Levels:**
- 🟢 80-100% — Ready to proceed to next phase
- 🟡 60-79% — Gaps exist but manageable; proceed with caution
- 🟠 40-59% — Significant gaps; address before proceeding
- 🔴 0-39% — Major gaps; phase needs substantial work
**Output Format:**
The ECAL readiness score MUST produce **two layers of output**: (a) the formatted terminal scorecard shown to the user, and (b) the structured YAML file saved to disk. The terminal output is the primary deliverable — the YAML is the backing data. Never produce YAML-only output without the formatted scorecard.
```
══════════════════════════════════════════
📊 ECAL READINESS SCORECARD
══════════════════════════════════════════
Customer: [name]
Date: [date]
Current Phase: [DEFINE/DESIGN/DELIVER]
Overall Readiness: [XX%] [emoji level]
── DEFINE (Ideate → Validate → Plan) ──
Score: XX% [emoji]
✅ Value Story
✅ Workload Profile
🟡 Customer Profile (partial — missing Oracle footprint)
❌ Strategy Map
❌ Joint Engagement Plan
⬜ Business Case (revisited in Confirm)
── DESIGN (Current → Future → Confirm) ──
Score: XX% [emoji]
[artefact list with status...]
── DELIVER (Adopt → Operate → Improve) ──
Score: XX% [emoji]
[artefact list with status...]
── TOP 5 GAPS ──
1. ❌ [artefact] — [why it matters] — [recommended action]
2. ...
── RECOMMENDED NEXT ACTIONS ──
1. [specific action]
2. [specific action]
3. [specific action]
── ENGAGEMENT RACI CHECK ──
Roles identified: [list]
Roles missing: [list]
══════════════════════════════════════════
```
**Files Generated:**
Always list the files saved at the end of the scorecard:
```
📁 Files saved:
- examples/<customer>-ecal-scorecard.yaml
```
After showing the scorecard, offer:
```
What do you want to do?
→ [A] Fix the top gap now (I'll generate the missing artefact)
→ [B] Generate all missing artefacts for current phase
→ [C] Export scorecard as a slide (.pptx)
→ [D] Re-score after updates
```
**Scoring model, readiness levels, and output format:** see [docs/skill/ecal-readiness-format.md](docs/skill/ecal-readiness-format.md) for the scoring weights, the terminal scorecard layout, and the after-scorecard menu. Read that file before producing the scorecard.
- If the user picks **13**, ask: "What services does the customer need? (e.g., 'ExaCS X11M BYOL 2 DB servers + 4 storage + 128 ECPUs + ADB-S 8 ECPU + 2TB Block Storage + FastConnect 1Gbps'). I'll generate the BOM with only those SKUs."
Then follow the BOM generation flow:
1. Parse the customer request to identify needed OCI services and quantities
2. Match services against `kb/pricing/oci-sku-catalog.yaml` to select exact SKUs
2. Match services against `kb/pricing/oci-sku-catalog.yaml` (live, auto-refreshed) to select exact SKUs
3. Ask for discount % and contract duration if not specified (default: 0%, 12 months)
4. Ask if currency conversion is needed (e.g., USD→BRL with exchange rate and tax)
5. Generate the BOM spec YAML and save to the output folder
@@ -467,106 +356,15 @@ Every skill option that produces output MUST generate **readable, human-consumab
If a tool or agent generates YAML without the corresponding readable output, the task is **incomplete**. Always present the formatted result, then list the files saved.
### Output Directory Convention
### Output directory, slide deck structure, format options, service categorization
All generated files MUST be saved inside a dedicated output folder per customer/initiative:
```
examples/output-<customer>-<initiative>/
```
Examples:
- `examples/output-meli-im06/` — MELI MySQL engagement
- `examples/output-meli-im30/` — MELI ElasticSearch engagement
- `examples/output-acme-migration/` — ACME cloud migration
This folder contains ALL outputs for that engagement: `.pptx`, `.drawio`, `.yaml` specs, `.pdf`, scorecards. The folder is gitignored via `examples/output-*/` — never commit customer data.
YAML spec files (architecture, workload-profile, diagram-spec) are saved IN the output folder, not loose in `examples/`. This keeps everything grouped and portable.
Default output is a **slide deck (.pptx)**. The architect can specify:
| Format | Output |
|--------|--------|
| `deck` (default) | 10-12 slide presentation |
| `deck + drawio` | + editable architecture diagram |
| `deck + doc` | + technical document (15-25 pages) |
| `deck + xlsx` | + cost spreadsheet with formulas |
| `deck + pdf` | + customer-facing PDF (branded, no internal refs) |
| `pdf` | Customer PDF only |
| `full` | Everything (pptx + drawio + docx + xlsx + pdf) |
| `doc only` | Technical document without slides |
| `deliver` | Handover + go-live checklist + success criteria |
### Slide Deck Structure
Slide count adapts to engagement tier (6-8 small, 10-12 standard, 12-16 complex):
1. **Title** — customer, project, date (dark background)
2. **Value Story** — business driver, hypothesis, desired outcomes
3. **Service Tiering** — workload-to-tier mapping (Platinum/Gold/Silver/Bronze) with SLA, RTO/RPO
4. **Architecture Principles** — selected ECAL principles (Design/Deployment/Service) that govern the architecture
5. **Architecture Diagram** — fills 85% of slide
6. **Architecture Decisions** — 4-6 key decisions with rationale
7. **HA/DR** — topology + RTO/RPO per tier
8. **Security & Compliance** — controls grid, compliance badges
9. **Environment Catalogue** — Prod/Pre-Prod/Dev-Test/DR per workload with sizing and isolation
10. **Cost Estimate** — PAYG vs BYOL table with assumptions (all environments)
11. **Cost Comparison** (optional) — vs current state or competitor
12. **Migration Approach** — phased timeline, tools, downtime strategy
13. **Operational RACI** — responsibility matrix (customer vs Oracle/partner)
14. **Risk Register** — severity-coded risk table
15. **Well-Architected Scorecard** — 5-pillar traffic-light indicators
16. **Next Steps** — concrete SMART actions with dates
Use `tools/oci_deck_gen.py` for generation. Colors: teal `#2D5967`, copper `#AA643B`, purple `#804998`. Font: Segoe UI. Design standards: `config/output-formats.yaml`.
### Architecture Diagram
Use `tools/oci_diagram_gen.py` with OCI official styles from `kb/diagram/oci-toolkit-styles.yaml`. Containers, service blocks, connections, and typography rules are defined there.
---
## Service Categorization
| Category | Color | Use |
|----------|-------|-----|
| **Infrastructure** | Teal `#2D5967` | Compute, OKE, LB, Gateways, WAF, Bastion, Storage, Monitoring |
| **Database** | Copper `#AA643B` | ADB-S/D, DBCS, ExaCS, MySQL, PostgreSQL, NoSQL, GoldenGate |
| **Integration** | Purple `#804998` | DRG, Streaming, Queue, OIC, FastConnect, Service Connector Hub |
| **Dormant** | Light gray `#DFDCD8` | Standby/inactive resources (DR tier) |
| **Legacy** | Medium gray `#70665E` | Non-OCI systems (MQ Series, legacy middleware) |
See [docs/skill/output-formats.md](docs/skill/output-formats.md) for the per-customer output folder convention, the complete format option matrix, the 16-slide deck structure, the diagram generation rules, and the service-to-color mapping.
---
## Knowledge Base
```
kb/
├── architecture-center/ # Oracle Architecture Center reference catalog
│ └── catalog.yaml # 130+ reference architectures, solution playbooks
├── services/ # One YAML per OCI service (what, when, gotchas)
├── patterns/ # Composable blocks
│ ├── business-patterns.yaml # Business-level patterns (DEFINE)
│ ├── application-patterns.yaml # Application architecture patterns (DESIGN)
│ ├── service-tiering.yaml # Service tier definitions (Platinum/Gold/Silver/Bronze)
│ ├── architecture-principles.yaml # ECAL architecture principles (Design/Deployment/Service)
│ ├── operational-raci.yaml # RACI matrix templates (fully/co/self-managed)
│ ├── environment-catalogue.yaml # Environment templates per tier
│ ├── database-ha/ # Database HA patterns
│ ├── database-dr/ # Database DR patterns
│ ├── networking-*/ # Networking patterns
│ ├── compute-scaling/ # Compute auto-scaling
│ ├── security-baseline/ # Security controls
│ └── compliance-pci/ # PCI-DSS compliance
├── sizing/ # CPU conversion ratios, IOPS, scaling rules
├── pricing/ # Simplified pricing for estimation
├── competitive/ # AWS/Azure/GCP service mapping
├── well-architected/ # 5-pillar validation checklists
├── diagram/ # OCI Toolkit styles and reference layouts
├── compatibility/ # Feature matrices (ADB, etc.)
└── field-knowledge/ # Real-world gotchas and lessons learned
```
KB lives under `kb/`. See [kb/README.md](kb/README.md) for the directory map, frontmatter requirements, refresh tooling, and contributor guide.
---
@@ -596,6 +394,24 @@ kb/
- Present trade-offs explicitly. Let the architect decide.
- Produce the **minimum needed** for the engagement tier — don't pad.
### Minimal Output — Work Silently
**Do NOT narrate your internal process.** The architect does not need a play-by-play of what you are doing. Specifically:
- **Do NOT** announce each file you are about to read ("Let me check the service catalog...", "Reading the pricing file...").
- **Do NOT** list the KB files, templates, or patterns you are consulting.
- **Do NOT** describe intermediate reasoning steps ("First I'll parse your notes, then I'll...", "Now I'm matching services against the catalog...").
- **Do NOT** echo back the user's input as a summary before starting work.
- **Do NOT** show progress updates for sub-steps ("Step 1 done, moving to step 2...").
**What TO show:**
- Clarifying questions (when input is ambiguous or incomplete).
- The pre-generation review (component confirmation before generating artifacts).
- The final deliverable (scorecard, deck summary, file list, next-step menu).
- Errors or blockers that require the architect's input.
**In short:** Go from input → clarifying question (if needed) → pre-generation confirmation → final output. Skip everything in between. The architect cares about results, not process.
---
## Guardrails

View File

@@ -28,7 +28,7 @@ review_triggers:
- event: "Oracle database version release"
action: "Review all feature matrix entries. Mark untested. Validate within 14 days."
- event: "Oracle pricing change"
action: "Update kb/pricing/ files. Verify cost calculator accuracy."
action: "Run python tools/refresh_sku_catalog.py --refresh and --refresh-domain compute. Both pull from the live Oracle pricing API."
- event: "After customer engagement"
action: "Run After-Engagement Review (AER). Add findings and KB updates."
- event: "Quarterly"

View File

@@ -20,15 +20,15 @@ domains:
review_cadence: "quarterly"
- area: "kb/compatibility/"
owner: { name: "TBD", team: "Database Specialists" }
owner: { name: "Diego Cabrera", team: "Field SA" }
review_cadence: "on Oracle version release + quarterly"
- area: "kb/pricing/"
owner: { name: "TBD", team: "Solution Engineering" }
review_cadence: "monthly (pricing changes frequently)"
owner: { name: "Auto-refreshed", team: "Oracle Public Pricing API" }
review_cadence: "automatic — refresh tools pull from the API on demand; freshness checker runs in welcome flow"
- area: "kb/competitive/"
owner: { name: "TBD", team: "Competitive Intelligence" }
owner: { name: "Diego Cabrera", team: "Field SA" }
review_cadence: "quarterly + on competitor announcements"
- area: "kb/field-findings/"
@@ -36,5 +36,5 @@ domains:
review_cadence: "continuous"
- area: "kb/well-architected/"
owner: { name: "TBD", team: "Cloud Architecture" }
owner: { name: "Diego Cabrera", team: "Field SA" }
review_cadence: "on Oracle WA Framework updates"

View File

@@ -12,6 +12,7 @@
---
taxonomy:
products:
- adb # generic ADB (covers both -s and -d)
- adb-s
- adb-d
- dep
@@ -26,6 +27,8 @@ taxonomy:
- goldengate
- data-safe
- vault
- rac
- proxysql
versions:
- 19c
@@ -44,6 +47,42 @@ taxonomy:
- sizing
- compliance
features:
- adg # Active Data Guard
- ai-vector-search
- vector-search
- hnsw # Hierarchical Navigable Small World indexes
- json
- partitioning
- refreshable-clone
- elastic-pool
- ecpu # ECPU billing model (vs OCPU)
- connection-pooling
- distributed
- immutable
- serialization
operations:
- cli
- maintenance-window
- provisioning
- planning
- lead-time
- capacity
- node-split
- zero-downtime
- bidirectional
- detection-delay
- stale-reads
metrics:
- latency
- 100m # 100 million scale (e.g. vector counts)
limitations:
- limitation
- sr-required # Service Request required to enable / fix
severity_tags:
- blocker
- workaround-available

View File

@@ -0,0 +1,88 @@
# ECAL Readiness Scorecard Format
This document defines how option 12 (ECAL Readiness Score) presents its results.
Referenced from `SKILL.md` § Welcome Flow → Behavior Rules → option 12.
## Scoring model
Each artefact has a status: ✅ Complete | 🟡 Partial | ❌ Missing | ⬜ Not Applicable (future phase).
Phase scores are calculated as:
- ✅ = 1.0 point, 🟡 = 0.5 point, ❌ = 0 points, ⬜ = excluded from denominator
- Phase score = (sum of points / applicable artefacts) × 100%
Overall ECAL Readiness = weighted average:
- DEFINE: 25% weight
- DESIGN: 50% weight (largest phase, most artefacts)
- DELIVER: 25% weight
## Readiness levels
- 🟢 80-100% — Ready to proceed to next phase
- 🟡 60-79% — Gaps exist but manageable; proceed with caution
- 🟠 40-59% — Significant gaps; address before proceeding
- 🔴 0-39% — Major gaps; phase needs substantial work
## Output format
The ECAL readiness score MUST produce **two layers of output**: (a) the formatted terminal scorecard shown to the user, and (b) the structured YAML file saved to disk. The terminal output is the primary deliverable — the YAML is the backing data. Never produce YAML-only output without the formatted scorecard.
```
══════════════════════════════════════════
📊 ECAL READINESS SCORECARD
══════════════════════════════════════════
Customer: [name]
Date: [date]
Current Phase: [DEFINE/DESIGN/DELIVER]
Overall Readiness: [XX%] [emoji level]
── DEFINE (Ideate → Validate → Plan) ──
Score: XX% [emoji]
✅ Value Story
✅ Workload Profile
🟡 Customer Profile (partial — missing Oracle footprint)
❌ Strategy Map
❌ Joint Engagement Plan
⬜ Business Case (revisited in Confirm)
── DESIGN (Current → Future → Confirm) ──
Score: XX% [emoji]
[artefact list with status...]
── DELIVER (Adopt → Operate → Improve) ──
Score: XX% [emoji]
[artefact list with status...]
── TOP 5 GAPS ──
1. ❌ [artefact] — [why it matters] — [recommended action]
2. ...
── RECOMMENDED NEXT ACTIONS ──
1. [specific action]
2. [specific action]
3. [specific action]
── ENGAGEMENT RACI CHECK ──
Roles identified: [list]
Roles missing: [list]
══════════════════════════════════════════
```
## Files generated
Always list the files saved at the end of the scorecard:
```
📁 Files saved:
- examples/<customer>-ecal-scorecard.yaml
```
## After ECAL scorecard menu
```
What do you want to do?
→ [A] Fix the top gap now (I'll generate the missing artefact)
→ [B] Generate all missing artefacts for current phase
→ [C] Export scorecard as a slide (.pptx)
→ [D] Re-score after updates
```

View File

@@ -0,0 +1,73 @@
# Output Formats and Conventions
Referenced from `SKILL.md` § Output Generation.
## Output directory convention
All generated files MUST be saved inside a dedicated output folder per customer/initiative:
```
examples/output-<customer>-<initiative>/
```
Examples:
- `examples/output-meli-im06/` — MELI MySQL engagement
- `examples/output-meli-im30/` — MELI ElasticSearch engagement
- `examples/output-acme-migration/` — ACME cloud migration
This folder contains ALL outputs for that engagement: `.pptx`, `.drawio`, `.yaml` specs, `.pdf`, scorecards. The folder is gitignored via `examples/output-*/` — never commit customer data.
YAML spec files (architecture, workload-profile, diagram-spec) are saved IN the output folder, not loose in `examples/`. This keeps everything grouped and portable.
## Format options
Default output is a **slide deck (.pptx)**. The architect can specify:
| Format | Output |
|--------|--------|
| `deck` (default) | 10-12 slide presentation |
| `deck + drawio` | + editable architecture diagram |
| `deck + doc` | + technical document (15-25 pages) |
| `deck + xlsx` | + cost spreadsheet with formulas |
| `deck + pdf` | + customer-facing PDF (branded, no internal refs) |
| `pdf` | Customer PDF only |
| `full` | Everything (pptx + drawio + docx + xlsx + pdf) |
| `doc only` | Technical document without slides |
| `deliver` | Handover + go-live checklist + success criteria |
## Slide deck structure
Slide count adapts to engagement tier (6-8 small, 10-12 standard, 12-16 complex):
1. **Title** — customer, project, date (dark background)
2. **Value Story** — business driver, hypothesis, desired outcomes
3. **Service Tiering** — workload-to-tier mapping (Platinum/Gold/Silver/Bronze) with SLA, RTO/RPO
4. **Architecture Principles** — selected ECAL principles (Design/Deployment/Service) that govern the architecture
5. **Architecture Diagram** — fills 85% of slide
6. **Architecture Decisions** — 4-6 key decisions with rationale
7. **HA/DR** — topology + RTO/RPO per tier
8. **Security & Compliance** — controls grid, compliance badges
9. **Environment Catalogue** — Prod/Pre-Prod/Dev-Test/DR per workload with sizing and isolation
10. **Cost Estimate** — PAYG vs BYOL table with assumptions (all environments)
11. **Cost Comparison** (optional) — vs current state or competitor
12. **Migration Approach** — phased timeline, tools, downtime strategy
13. **Operational RACI** — responsibility matrix (customer vs Oracle/partner)
14. **Risk Register** — severity-coded risk table
15. **Well-Architected Scorecard** — 5-pillar traffic-light indicators
16. **Next Steps** — concrete SMART actions with dates
Use `tools/oci_deck_gen.py` for generation. Colors: teal `#2D5967`, copper `#AA643B`, purple `#804998`. Font: Segoe UI. Design standards: `config/output-formats.yaml`.
## Architecture diagram
Use `tools/oci_diagram_gen.py` with OCI official styles from `kb/diagram/oci-toolkit-styles.yaml`. Containers, service blocks, connections, and typography rules are defined there.
## Service categorization
| Category | Color | Use |
|----------|-------|-----|
| **Infrastructure** | Teal `#2D5967` | Compute, OKE, LB, Gateways, WAF, Bastion, Storage, Monitoring |
| **Database** | Copper `#AA643B` | ADB-S/D, DBCS, ExaCS, MySQL, PostgreSQL, NoSQL, GoldenGate |
| **Integration** | Purple `#804998` | DRG, Streaming, Queue, OIC, FastConnect, Service Connector Hub |
| **Dormant** | Light gray `#DFDCD8` | Standby/inactive resources (DR tier) |
| **Legacy** | Medium gray `#70665E` | Non-OCI systems (MQ Series, legacy middleware) |

View File

@@ -0,0 +1,78 @@
# WA Review Output Format
This document defines how option 5 (Well-Architected Review) presents its results.
Referenced from `SKILL.md` § Welcome Flow → Behavior Rules → option 5.
The WA review MUST produce **two layers of output**: (a) the formatted terminal scorecard shown to the user, and (b) the structured YAML files saved to disk. The terminal output is the primary deliverable — the YAML is the backing data. Never produce YAML-only output without the formatted scorecard.
## Terminal scorecard banner
```
══════════════════════════════════════════════════════
✅ OCI WELL-ARCHITECTED REVIEW — [Customer Name]
══════════════════════════════════════════════════════
Overall: [STATUS] — X/Y checks passed
HIGH: N │ MEDIUM: N │ LOW: N
══════════════════════════════════════════════════════
[emoji] SECURITY & COMPLIANCE X/Y passed
[emoji] RELIABILITY & RESILIENCE X/Y passed
[emoji] PERFORMANCE & COST X/Y passed
[emoji] OPERATIONAL EFFICIENCY X/Y passed
[emoji] DISTRIBUTED CLOUD X/Y passed | N/A
```
Pillar emoji: 🟢 all passed, 🟡 medium gaps only, 🔴 any HIGH gap, ⬜ N/A
## HIGH severity gaps table
Present all HIGH gaps grouped by pillar in a markdown table:
```
### HIGH severity gaps that must be addressed:
**[Pillar Name] (N HIGH)**
| ID | Gap | Fix |
|---|---|---|
| CHECK-ID | Finding description | Recommended action |
```
## MEDIUM and LOW gaps
- **MEDIUM gaps:** List as a compact bullet list grouped by pillar (ID + one-line finding + fix). Skip the table format to keep it concise.
- **LOW gaps:** Mention count only, list individual items only if ≤ 5.
## Analysis section
After the gap tables, add a "Why so many gaps?" paragraph if total gaps > 20, explaining the root cause (e.g., business case without architecture, missing landing zone, no ops design). This contextualizes the score for the SA.
## Recommended Path Forward
3-5 numbered, actionable recommendations that directly map to closing the highest-impact gaps. Reference skill options where applicable (e.g., "Generate the architecture — option 1 or 2").
## Files Generated
Always list the files saved at the end of the review:
```
📁 Files saved:
- examples/<customer>-wa-scorecard.yaml
- examples/<customer>-wa-architecture.yaml
- examples/<customer>-wa-workload-profile.yaml
```
## After WA Review menu
```
What do you want to do?
→ [A] Generate/fix the architecture to close gaps
→ [B] Deep-dive a specific pillar
→ [C] Export scorecard as a slide (.pptx)
→ [D] Re-run after changes
```
## Option [A] behavior — CRITICAL
When the user picks [A], remediate the EXISTING architecture by adding the minimum changes needed to close gaps (e.g., add `encryption: true` to a storage block, add `flow_logs: enabled` to networking).
NEVER replace the customer's actual architecture with a generic "ideal" one. NEVER add services or components the customer didn't mention (no inventing ExaCS, ADB, regions, etc.). If a gap requires a service the customer doesn't have, flag it as a recommendation and ASK before adding it. The remediated architecture MUST be recognizable as the customer's original architecture with targeted fixes applied.

26
evaluations/README.md Normal file
View File

@@ -0,0 +1,26 @@
# Evaluations
Baseline evaluation scenarios for the OCI Deal Accelerator skill, following
the format recommended in the [Anthropic Agent Skills best practices](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices#build-evaluations-first).
These are **manual evaluations** — there is no automated test runner yet.
Use them as a regression checklist after non-trivial changes to `SKILL.md`,
`CLAUDE.md`, or the welcome flow.
## How to run
1. Open a fresh Claude Code conversation in this repo.
2. For each `*.json` file in this directory:
- Read the `query` field — paste it as the user message (or simulate the trigger described in the file).
- If `files` is non-empty, attach those files as context.
- Observe the assistant's behavior.
- Manually verify each item in `expected_behavior` is met.
3. Note any failures — file an issue or update the skill accordingly.
## Scenarios
| File | Purpose |
|---|---|
| `welcome-flow.json` | Greeting → exact 14-option menu (verbatim from SKILL.md) |
| `full-proposal.json` | Discovery notes → bypass menu, run full proposal flow |
| `wa-review.json` | WA review request → scorecard format + saved YAML files |

View File

@@ -0,0 +1,18 @@
{
"skills": ["oci-deal-accelerator"],
"query": "Customer: ACME Bank, retail banking, 200 branches across LATAM. Driver: migrating core banking from on-prem Exadata to OCI for cost reduction and DR. Current: 4-node RAC on X8M, ~12 TB DB, 2000 TPS peak, RTO 4h / RPO 15min. Compliance: PCI-DSS, local data residency. Timeline: 6 months. Budget: tight, exploring BYOL. They are also evaluating AWS RDS Custom for Oracle.",
"files": [],
"expected_behavior": [
"Detects this is discovery notes and skips the welcome menu (no 14-option list shown)",
"Goes directly into the full proposal flow (option 1 behavior)",
"Builds a workload profile reflecting ACME Bank's stated requirements (does NOT invent services they did not mention)",
"Recommends an architecture that addresses RTO/RPO, PCI-DSS, data residency, and BYOL — using kb/services/, kb/patterns/, and kb/well-architected/",
"Cites at least one Oracle Architecture Center reference architecture from kb/architecture-center/catalog.yaml when there is a strong match",
"Generates a slide deck (.pptx) as the primary deliverable, saved to examples/output-acme-bank-*/",
"Includes a Cost Estimate slide that distinguishes BYOL vs PAYG using kb/pricing/",
"Mentions the AWS RDS Custom for Oracle competitive context honestly using kb/competitive/aws-mapping.yaml",
"Does NOT add observability/security services that ACME did not request, beyond what is required for stated compliance",
"Asks clarifying questions when input is genuinely ambiguous, instead of inventing answers",
"Surfaces relevant gotchas from kb/field-knowledge/ (e.g., Exadata-to-cloud migration risks)"
]
}

View File

@@ -0,0 +1,20 @@
{
"skills": ["oci-deal-accelerator"],
"query": "5",
"follow_up": "Single-region OCI architecture: ADB-S 8 ECPU in São Paulo, 2 VM.Standard.E5.Flex web tier behind a public load balancer, Object Storage for media. No backups configured, no FastConnect. Customer: SmallShop, e-commerce, no compliance requirements stated.",
"files": [],
"expected_behavior": [
"After the user picks 5, asks for the architecture description (does not skip to scoring)",
"Reads docs/skill/wa-review-format.md before producing the scorecard",
"Parses the input into a workload profile YAML and architecture YAML",
"Runs scripts/validate-architecture.py with both files",
"Produces the formatted terminal scorecard with the exact banner format from docs/skill/wa-review-format.md (5 pillars, X/Y passed, HIGH/MEDIUM/LOW counts)",
"Saves three YAML files under examples/: <customer>-wa-scorecard.yaml, <customer>-wa-architecture.yaml, <customer>-wa-workload-profile.yaml",
"Lists the saved files at the end of the review",
"Identifies the obvious gaps (no backups, no DR, no monitoring, single-AD) as HIGH severity",
"Presents HIGH gaps as a markdown table grouped by pillar",
"Presents MEDIUM gaps as compact bullets, not a table",
"Offers the after-WA-review menu with options [A] [B] [C] [D]",
"If the user picks [A], remediates the EXISTING architecture (adds encryption, backups, etc. to the actual services SmallShop has) — does NOT replace it with a generic 'ideal' architecture, does NOT invent services SmallShop did not mention"
]
}

View File

@@ -0,0 +1,16 @@
{
"skills": ["oci-deal-accelerator"],
"query": "hola",
"files": [],
"expected_behavior": [
"Reads SKILL.md before showing anything to the user (does not improvise the menu from memory or folder structure)",
"Runs python tools/kb_freshness.py --check --json as a pre-flight step",
"If freshness reports stale files with refreshable=true, prepends a banner asking the user [y/N] before proceeding",
"If freshness reports stale files but none are refreshable, prepends a non-blocking informational banner without asking",
"Shows the welcome banner exactly as defined in SKILL.md (no paraphrasing)",
"Shows all 14 capability menu options in the correct 6 sections: DESIGN & PROPOSE (1-4), VALIDATE & CHECK (5-7), STRATEGY & BUSINESS (8), KNOWLEDGE BASE (9-11), ECAL GOVERNANCE (12), SA TOOLS (13-14)",
"Does NOT invent options that are not in SKILL.md",
"Does NOT omit options that are in SKILL.md",
"If the freshness tool errors out, falls back to showing the welcome message silently — never blocks the user on tooling failures"
]
}

122
kb/README.md Normal file
View File

@@ -0,0 +1,122 @@
# Knowledge Base — Contributor Guide
The KB is the moat. It encodes Oracle field experience, OCI service quirks,
and architecture patterns that aren't in the official docs. Tools and the
skill itself read these YAMLs at runtime.
## Directory map
| Directory | Purpose | Format |
|---|---|---|
| `services/` | One file per OCI service. Capabilities, limits, gotchas, when-to-use. | Frontmatter + structured body |
| `patterns/` | Composable architecture blocks (HA, DR, hub-spoke, RACI, ECAL artefacts). | Frontmatter + body, often nested dirs |
| `sizing/` | CPU/memory/storage conversion ratios, IOPS limits, scaling rules. | Body only |
| `pricing/` | `oci-sku-catalog.yaml` (200+ SKUs, auto-refreshed) + `compute.yaml` (shape-level, auto-refreshed). Both pull from the Oracle public pricing API. | Frontmatter + body |
| `competitive/` | OCI vs AWS / Azure / GCP service mapping and objection handling. | Frontmatter + body |
| `compatibility/` | Feature matrices (e.g. ADB-S features). Currently thin — expected to grow. | Frontmatter + body |
| `well-architected/` | 5-pillar checklists, landing zone patterns, persona views. | Frontmatter + body |
| `architecture-center/` | Auto-curated index of Oracle Architecture Center reference architectures. | Single `catalog.yaml` |
| `field-knowledge/` | Real-world gotchas, lessons learned, undocumented limits. | Frontmatter + body |
| `field-findings/` | Tracker of newly logged field issues with confidence decay. | Single `tracker.yaml` |
| `diagram/` | OCI icon library and reference layouts for diagram generation. | Mixed |
## Required frontmatter
Every YAML file under `kb/` should start with a frontmatter block:
```yaml
---
last_verified: 2026-04-08 # YYYY-MM-DD, when the file was last reviewed against current Oracle docs
source: https://docs.oracle.com/... # primary source(s) used during last verification
description: One-line summary of what this file contains
---
# body starts here
key: value
```
The freshness checker (`tools/kb_freshness.py`) reads `last_verified` and warns
if a file is older than the thresholds in `config/kb-governance.yaml`
(default: warning at 180 days, stale at 365 days). The KB linter
(`tools/kb_linter.py`) accepts `last_updated` and `last_refreshed` as fallback
field names but new files should use `last_verified`.
## How to add a new service card
1. Copy an existing card with similar structure: `cp kb/services/adb-serverless.yaml kb/services/<your-service>.yaml`.
2. Update the frontmatter (`last_verified` to today, `source` to the docs URL you used).
3. Fill in fields. Keep gotchas honest — if the service has a limitation, write it down. The KB's value is honesty, not marketing.
4. Run `python tools/kb_linter.py` and fix any issues it reports for your file.
5. Run `make freshness` to confirm your new file is FRESH.
## How to add a pattern
Patterns can be either single-file (e.g. `kb/patterns/business-drivers.yaml`)
or directory-based for larger blocks (e.g. `kb/patterns/database-ha/`).
Use a directory when you need multiple files (pattern + diagrams + ADRs).
## Refresh tooling
| File | Refresh tool |
|---|---|
| `kb/pricing/oci-sku-catalog.yaml` | `python tools/refresh_sku_catalog.py --refresh` (Oracle pricing API) |
| `kb/pricing/compute.yaml` | `python tools/refresh_sku_catalog.py --refresh-domain compute` (same API, shape-level) |
| `kb/architecture-center/catalog.yaml` | `python tools/refresh_arch_catalog.py --whats-new` (web crawl) |
| Other `kb/pricing/<domain>.yaml` | Not yet automated. Add a new entry to `DOMAIN_REGISTRY` in `tools/refresh_sku_catalog.py` and write a domain-specific refresher (see `refresh_compute_yaml` as a template). |
| Everything else | **Manual** — review against Oracle docs, bump `last_verified` |
The shortcut for everyone:
```bash
make freshness # report stale files
make freshness-refresh # run automatic refreshes for files that support them
```
## Pricing files
There are exactly **two** pricing files, both auto-refreshed from the
[Oracle public pricing API](https://apexapps.oracle.com/pls/apex/cetools/api/v1/products/?currencyCode=USD):
1. **`kb/pricing/oci-sku-catalog.yaml`** — 200+ SKUs across 20 categories
(compute, storage, database, networking, observability, security, AI/ML,
GenAI, etc.). Refresh: `python tools/refresh_sku_catalog.py --refresh`.
2. **`kb/pricing/compute.yaml`** — shape-level estimation pricing
(VM.Standard.E5.Flex hourly, monthly, etc.). Different abstraction from
the SKU catalog — useful for SA estimation. Refresh:
`python tools/refresh_sku_catalog.py --refresh-domain compute`.
**Pricing context that ISN'T a price** (billing models, BYOL rules, free
tiers, service nuances, hyperscaler comparisons) lives in
`kb/field-knowledge/pricing-knowledge.yaml`. That file is non-numeric where
possible and does not need API refresh.
There are no other pricing files. The previous `kb/pricing/database.yaml`,
`storage.yaml`, `networking.yaml`, etc. were removed on 2026-04-08 — their
prices were drift-prone and 30-800% off the live API; their notes were
migrated to `kb/field-knowledge/pricing-knowledge.yaml`.
## Linter
```bash
python tools/kb_linter.py # all checks
python tools/kb_linter.py --show-decay # confidence decay only
python tools/kb_linter.py --check-tags # tag taxonomy only
python tools/kb_linter.py --check-owners # domain owner assignments only
```
The linter reports STALE / WARNING for files past their freshness threshold,
unknown tags in field findings, and missing domain owners. Exit code is 1 if
any issues are found.
## Review cadence
- **Field findings**: confidence decays automatically — see `config/kb-governance.yaml`
- **Service cards**: review at least every 6 months, or when Oracle publishes a major update
- **Patterns**: review at least once a year
- **Pricing**: ideally every quarter — Oracle changes prices ~2x per year for major SKUs
## Thin directories
`compatibility/` and `field-findings/` currently hold a single file each.
Both are expected to grow as more SAs contribute. If after 6 months they
remain at 1 file, consider consolidating with a parent directory.

View File

@@ -9,12 +9,12 @@
# STRONG MATCH: ≥2 service matches + ≥1 tag match
# MODERATE MATCH: ≥1 service match + ≥2 tag matches
#
# Last refreshed: 2026-03-16
# Last verified: 2026-03-16
# Entry count: 123
# To refresh: python tools/refresh_arch_catalog.py --whats-new
# =============================================================================
last_refreshed: "2026-03-16"
last_verified: "2026-03-16"
source: "https://docs.oracle.com/en/solutions/oracle-architecture-center/"
entry_count: 123

View File

@@ -47,8 +47,12 @@ findings:
- id: "FF-202603-008"
date: "2026-03-14"
reported_by: "Diego Cabrera"
client: "Vector Search Customer"
contributor:
name: "Diego Cabrera"
team: "Field Architecture"
client: "Vector Search Customer"
context: "AI Vector Search engagement"
confidence: "validated"
product: "ADB-S"
version: "23ai"
severity: "HIGH"

View File

@@ -0,0 +1,419 @@
---
last_verified: 2026-04-08
source: Migrated from former kb/pricing/<domain>.yaml files (removed 2026-04-08).
Stable, non-numeric pricing knowledge that does not need API refresh.
All actual price numbers live in kb/pricing/oci-sku-catalog.yaml (auto-refreshed).
description: Pricing context, billing models, free tiers, BYOL rules, and
cross-service estimation knowledge for the OCI Deal Accelerator.
---
# =============================================================================
# OCI Pricing Knowledge
# =============================================================================
#
# This file is the human-readable companion to kb/pricing/oci-sku-catalog.yaml.
# The catalog has live SKU prices (auto-refreshed). This file has the *context*
# a Solutions Architect needs to estimate accurately:
# - Pricing models and when to use each
# - BYOL rules and savings
# - Free-tier rules per service
# - Service-specific billing nuances
# - Cost comparison framing vs hyperscalers
#
# This file is intentionally non-numeric where possible. Specific prices that
# change should NOT be added here — add them to the SKU catalog instead.
# Where a percentage or range is unavoidable (e.g. "BYOL ~50% off"), prefer
# stable rules of thumb over exact figures.
# =============================================================================
# ── PRICING MODELS ────────────────────────────────────────────────
pricing_models:
payg:
name: Pay As You Go
commitment: none
billing: Per second (compute), per hour (database), per month (storage)
when_to_use:
- Variable / unpredictable workloads
- Short-term projects
- Dev / test environments
- Initial cloud adoption (before committing)
monthly_flex:
name: Monthly Flex (Universal Credits)
commitment: Minimum $1,000/month or custom commitment
billing: Committed credits consumed by usage
discount_tiers:
- spend_band: $1K-$10K/month
approx_discount: 5-10%
- spend_band: $10K-$50K/month
approx_discount: 10-20%
- spend_band: $50K+/month
approx_discount: 20-30% (negotiated)
when_to_use:
- Steady-state production workloads
- Known baseline consumption
- Multiple services across OCI
annual_flex:
name: Annual Flex (Committed)
commitment: 1-year or 3-year
discount: Deeper than Monthly Flex
when_to_use:
- Established production workloads with predictable spend
- Organizations committed to OCI long-term
byol:
name: Bring Your Own License
approx_savings: ~50% on database ECPU/OCPU costs
eligible:
- Oracle Database Enterprise Edition
- Oracle Database Standard Edition 2
- Oracle WebLogic
- Oracle Java SE
conversion: 1 processor license = 2 OCPUs (or 8 ECPUs)
when_to_use:
- Existing Oracle on-prem licenses with active support
- Licenses not being used elsewhere
when_not_to_use:
- No existing licenses
- Licenses still needed for on-prem during migration
- Standard Edition workloads on ADB (ADB requires EE)
reserved_capacity:
name: Reserved Capacity
commitment: 1-year or 3-year for specific shapes
approx_discount:
one_year: ~35% off on-demand
three_year: ~55% off on-demand
when_to_use:
- Known compute shapes running 24/7
- Predictable database capacity
notes: Shape-specific, less flexible than Universal Credits
# ── ESTIMATION APPROACH ──────────────────────────────────────────
estimation_approach:
steps:
- Calculate PAYG cost first (baseline)
- Apply BYOL if customer has eligible licenses
- Show savings with Monthly Flex / Annual Flex for steady-state
- Compare total annual cost vs current on-prem spending
- Include migration costs in year 1
assumptions_to_state:
- Hours per month (730 for 24/7)
- Auto-scaling hours per day (estimate)
- Data transfer volumes (egress in particular)
- Backup retention policy
- Support tier (Premier vs Standard)
# ── DATABASE KNOWLEDGE ──────────────────────────────────────────
database:
billing_unit_change:
fact: ADB and most modern Oracle Database services bill in ECPUs, not OCPUs.
rule_of_thumb: 1 OCPU ≈ 4 ECPUs for sizing conversion.
note: When reading old datasheets or RFP documents, normalize to ECPU before quoting.
autonomous_database_serverless:
auto_scaling: Billed per ECPU-second for additional ECPUs above base. Same hourly rate as base ECPUs.
adg_standby: Standby ECPU cost at the same rate as primary. Storage shared (no extra storage charge).
backup: Automated backups included in storage cost. Manual backups use Object Storage rates.
sweet_spot: 4-32 ECPUs with auto-scaling. Below 4, consider Always Free. Above 128, consider ADB-D or ExaCS.
autonomous_database_dedicated:
x11m_elastic_model:
description: |
X11M is the current-generation Exadata infrastructure for ADB-D and
ExaCS (announced 2025). It uses elastic scaling instead of fixed
quarter / half / full racks.
configuration:
min_db_servers: 2
min_storage_servers: 3
max_db_servers: 32
max_storage_servers: 64
key_changes_vs_x9m:
- No fixed rack shapes — elastic scale in / out by server
- Hard minimum: 2 DB + 3 storage servers (cannot provision less)
- Per-second ECPU billing (was per-hour in older generations)
- Improved compute, storage density, RDMA throughput
pricing_caveat: |
Per-server line items exist in the OCI price list ('Database Server -
X11M', 'Storage Server - X11M') but the dollar amounts are not visible
in the public API. For estimation, use X9M quarter rack as a proxy
and confirm final pricing with the Oracle PDM / sales team.
legacy_x9m_model:
shapes:
- quarter_rack
- half_rack
- full_rack
note: Still available in some regions; new deployments default to X11M.
dbcs_editions:
SE: Standard Edition 2
EE: Enterprise Edition (base)
EE_HP: Enterprise Edition - High Performance (partitioning, advanced compression, etc.)
EE_EP: Enterprise Edition - Extreme Performance (RAC, Active Data Guard, In-Memory)
note: Backup storage is charged separately at Object Storage rates.
exacs_gotchas:
- Infrastructure cost is fixed regardless of ECPU utilization on X9M (rack-based).
- X11M elastic model bills by server, not by rack — scale in / out as needed.
- Provisioning takes 4-8 hours.
- Billing starts only at AVAILABLE state.
- For X11M, the public API does not expose infrastructure-rate dollar amounts — confirm with PDM.
exadata_cloud_at_customer:
note: Exadata infrastructure deployed in the customer datacenter, managed by Oracle.
same_ecpu_pricing_as: ExaCS Dedicated
database_migration_service:
free_period: First 183 days of an active migration are free.
backup_recovery:
autonomous_recovery_service: Per-GB protected per month, virtualized.
zdlra: Zero Data Loss variant — same model, slightly higher rate.
cost_comparison_vs_hyperscalers:
when_pitching_vs_aws_rds_or_azure_sqlmi:
include_in_comparison:
- OCI inbound data transfer is free
- OCI egress to internet is dramatically cheaper (~80% less than AWS after 10TB free)
- OCI BYOL discount is deeper than AWS BYOL
- ADB-S includes patching, tuning, indexing — RDS does not
- ADB now bills in ECPU (not OCPU) — 1 ECPU is a fraction of an OCPU
- Network LB is free per-hour on OCI
# ── NETWORKING KNOWLEDGE ────────────────────────────────────────
networking:
data_transfer:
ingress: Free (all sources)
egress_internet:
free_tier: First 10 TB / month is free
billing_after: Per-GB charge applies beyond free tier
inter_region: Per-GB charge (low)
fastconnect: Free in both directions (ingress AND egress)
competitive_advantage: |
OCI is dramatically cheaper than hyperscalers for data transfer:
- AWS: $0.09 / GB egress (OCI is ~10x cheaper after 10 TB free)
- Azure: $0.087 / GB egress
- GCP: $0.12 / GB egress
- OCI FastConnect egress is FREE (AWS DirectConnect charges per GB)
This is one of the strongest cost arguments when migrating data-intensive
workloads from AWS / Azure / GCP.
fastconnect:
note: Private dedicated connectivity. No data transfer charges.
port_speeds_available_in_api: [1, 2, 5, 10, 40, 100, 400] # Gbps
note_400gbps: 400 Gbps option is available; check oci-sku-catalog.yaml for current SKUs.
network_load_balancer:
cost_model: No per-hour charge (Layer 4). Data processing fees apply.
flexible_load_balancer:
cost_model: Base instance hourly + bandwidth per Mbps-hour. See oci-sku-catalog.yaml.
vpn_connect:
cost_model: No additional charge for IPSec VPN tunnels. Included with DRG.
dns:
free_tier: 1 million queries / month at no cost.
waf:
cost_model: Pricing based on requests processed. See oci-sku-catalog.yaml.
# ── STORAGE KNOWLEDGE ───────────────────────────────────────────
storage:
block_volume:
tier_model: |
OCI block volume tiers are configured via Volume Performance Units (VPU):
- Lower Cost: 0 VPU
- Balanced: 10 VPU (default)
- Higher Performance: 20 VPU
- Ultra High Performance (UHP): 30-120 VPU
The base storage SKU is the same across tiers; the difference is the
VPU multiplier on top. See oci-sku-catalog.yaml for the base storage
SKU and the VPU SKU.
boot_volume_free_tier: First 200 GB included with each compute instance.
backup_billing: Block volume backups have their own per-GB-month rate (lower than primary).
object_storage:
tiers:
standard: General-purpose, immediate access.
infrequent_access: Lower per-GB cost; retrieval fee applies.
archive: Lowest per-GB cost; standard retrieval is ~1 hour.
free_tier: 10 GB storage + 50,000 requests / month always free.
request_pricing: Separate per-10k-PUT and per-10k-GET charges.
file_storage:
note: Per-GB-month, higher rate than block volume.
high_performance_mount_target: Available for high-throughput workloads.
# ── OBSERVABILITY & MANAGEMENT KNOWLEDGE ────────────────────────
observability:
free_services:
- Cloud Guard (tenancy threat detection)
- Security Zones (compartment policy enforcement)
- Vulnerability Scanning (host + container image)
- Certificates (TLS certificate management)
- Bastion (managed SSH / RDP bastion)
- Vault (software keys; HSM is paid)
- OS Management Hub
- Java Management Service
- Autonomous Linux
- Resource Analytics
- Events service
- DevOps pipeline execution (compute / storage billed separately)
- Cluster management for OKE basic clusters
free_tiers:
monitoring:
ingestion: 500 million datapoints / month
retrieval: 1 billion datapoints / month
logging:
free_per_month: 10 GB
queue:
free_per_month: 1 million requests
functions:
invocations: 2 million / month
memory: 400,000 GB-seconds / month
notifications:
deliveries: 1 million / month
emails: 1,000 / month
ops_insights:
note: Basic and Autonomous tiers are free. Cloud-external (e.g. on-prem databases) is paid per OCPU-hour.
log_analytics:
unit: 1 storage unit = 300 GB.
full_stack_dr:
note: Orchestrates DR failover across compute, database, and networking. Billed per ECPU / OCPU hour.
# ── COMPUTE / CONTAINERS / SERVERLESS KNOWLEDGE ────────────────
compute_containers_serverless:
oke:
basic_cluster: Cluster management is free (control plane).
enhanced_cluster: Per-cluster hourly charge — adds virtual nodes, workload identity, etc.
worker_nodes: Billed at standard compute shape rates (see kb/pricing/compute.yaml).
virtual_nodes: Additional per-pod pricing on enhanced clusters.
container_instances:
billing: Billed at compute rates (OCPU / hour + GB memory / hour). No additional service charge.
shapes_available: [A1 (Arm), E3 (AMD), E4 (AMD), E5 (AMD), E6 (AMD)]
functions:
free_tier_strength: Very generous — most event-driven workloads stay in the free tier.
batch:
billing: Pay-as-you-go compute pricing, no additional service charge.
# ── INTEGRATION & MIDDLEWARE KNOWLEDGE ─────────────────────────
integration:
integration_cloud:
editions: [Standard, Enterprise]
billing_unit: Per 5,000 messages / hour band
api_management:
note: Per-API-call pricing is very low; most use cases trivially below $1 / million calls.
streaming:
note: Kafka-compatible. Billed per GB stored per hour + per GB transferred.
queue:
free_tier_strength: 1 million requests / month free, very cost-effective for decoupling.
goldengate:
billing: OCPU-hour. BYOL available.
use_case: Real-time data integration and replication.
soa_suite:
note: For legacy SOA workload migration. OCPU-hour billing.
# ── DEVELOPER SERVICES KNOWLEDGE ───────────────────────────────
developer:
apex:
free_tier: Yes — APEX free tier available for low-code development.
visual_builder:
note: Low-code app builder with included storage.
devops:
free: Pipeline execution itself is free; compute / memory billed separately.
blockchain:
note: OCPU-hour billing; storage charged separately.
iot:
billing_unit: ECPU-hour.
media_flow:
billing: Per-minute, varies by codec, resolution, and fps.
media_streams:
billing: Per-GB packaged.
# ── AI / ML KNOWLEDGE ──────────────────────────────────────────
ai_ml:
generative_ai_vendors_available:
- Cohere (Command, Embed)
- Meta Llama
- xAI Grok
- Google Gemini
generative_ai_billing_unit: Per 10K transactions or per 1M tokens (varies by vendor).
generative_ai_agents:
extra_costs: Plus storage and ingestion fees for agent knowledge bases.
data_science:
notebook_sessions: Billed at compute shape rates (OCPU / hour + GB memory / hour + GPU options).
jobs: Same compute pricing as notebook sessions.
model_deployment: Compute + networking + storage combined pricing.
model_catalog_storage: Object Storage rates.
anomaly_detection:
free_tier: Up to 100M data points / month per region.
document_understanding:
note: OCR billed per 1K transactions; custom training billed per training hour.
language_services:
note: Pretrained per-transaction billing; custom training available at additional cost.
vision:
note: Per-1K image analysis billing; custom training per hour.
speech:
note: Per-transcription-hour billing.
digital_assistant:
note: Per-request billing with a minimum throughput floor.
# ── SECURITY KNOWLEDGE ─────────────────────────────────────────
security:
free_services:
- Cloud Guard
- Security Zones
- Vulnerability Scanning
- Certificates
- Bastion
- Vault (software keys only — HSM keys are paid)
paid_services:
- Access Governance (per workforce / consumer user / month)
- Network Firewall (instance hours + data processed)
- Data Safe (per target / month + audit records)
- Vault (HSM-backed keys)
# ── HYBRID / EDGE KNOWLEDGE ────────────────────────────────────
hybrid:
vmware_solution:
note: Bare-metal nodes (BM.Standard2.12, BM.Standard3.16, BM.Standard.E4.32, BM.Standard.E5.48). Hourly to 3-year commitment ranges.
hcx_enterprise: Available for cross-cloud migration from on-prem vSphere; 1-month minimum commitment.
compute_cloud_at_customer:
note: OCI compute, storage, and load balancer in customer datacenter. E6 shapes available.
managed_mac:
note: Apple Mac instances (M2 Pro, M4 Pro) for iOS / macOS build pipelines.
roving_edge:
note: Portable compute / GPU / storage devices for edge and disconnected scenarios. Per-device-day billing.

View File

@@ -1,69 +0,0 @@
---
last_verified: 2025-09-11
source: https://www.oracle.com/cloud/price-list/
description: OCI AI and Machine Learning service pricing.
currency: USD
---
# ── OCI Generative AI ─────────────────────────────────────────────
generative_ai:
cohere_models:
per_10k_transactions: 0.0001 - 0.0003
notes: "Command, Embed models"
meta_llama:
per_10k_transactions: 0.0001 - 0.0004
xai_grok:
per_1m_tokens_range: "$0.00015 $0.0018"
google_gemini:
per_1m_tokens_range: "$0.000075 $0.0006"
generative_ai_agents:
per_10k_transactions: 0.0001
notes: "Plus storage and ingestion fees"
# ── Anomaly Detection ─────────────────────────────────────────────
anomaly_detection:
training: "Free up to 100M data points/month per region"
# ── Data Science ───────────────────────────────────────────────────
data_science:
notebook_sessions:
notes: "Billed at compute shape rates (OCPU/hour + GB memory/hour + GPU options)"
jobs:
notes: "Same compute pricing as notebook sessions"
model_deployment:
notes: "Compute + networking + storage combined pricing"
model_catalog_storage:
notes: "Object Storage rates"
# ── Document Understanding ─────────────────────────────────────────
document_understanding:
training_per_hour: 0.50 - 1.00
ocr_per_1k_transactions: 0.025 - 0.050
# ── Language Services ──────────────────────────────────────────────
language:
pretrained_per_transaction: 0.0001 - 0.0003
custom_training: "Available at additional cost"
# ── Vision ─────────────────────────────────────────────────────────
vision:
image_analysis_per_1k: 0.0001 - 0.0003
custom_training_per_hour: 0.50 - 1.00
# ── Speech ─────────────────────────────────────────────────────────
speech:
per_transcription_hour: 0.0025 - 0.005
# ── Digital Assistant ──────────────────────────────────────────────
digital_assistant:
per_request: 0.009
minimum: "250 requests/hour"

View File

@@ -1,36 +0,0 @@
---
last_verified: 2025-09-11
source: https://www.oracle.com/cloud/price-list/
description: OCI Analytics and BI pricing.
currency: USD
---
# ── Oracle Analytics Cloud ─────────────────────────────────────────
oracle_analytics_cloud:
per_user_month:
professional: 0.99
enterprise: 2.00
ocpu_based:
notes: "Also available as OCPU-based pricing for embedded/API use"
# ── Essbase ────────────────────────────────────────────────────────
essbase:
ocpu_per_hour: 0.0252
# ── Data Lake / Big Data ──────────────────────────────────────────
ai_data_platform:
notes: "Pricing by AI Data Platform unit"
big_data_service_oracle:
ocpu_per_hour: 0.0252
notes: "Oracle distribution, includes Spark SQL compute"
big_data_service_cloudera:
ocpu_per_hour: 0.0168 - 0.0336
data_flow:
ocpu_usage: "Free"
notes: "Apache Spark, no charge for OCPU usage"

View File

@@ -1,191 +1,160 @@
---
last_verified: 2025-09-11
source: https://www.oracle.com/cloud/price-list/
description: OCI Compute pricing for estimation purposes.
Prices are approximate and subject to change. Always verify with
OCI pricing calculator for final quotes.
last_verified: '2026-04-08'
source: https://apexapps.oracle.com/pls/apex/cetools/api/v1/products/
description: OCI Compute pricing for estimation purposes. Auto-refreshed from the
Oracle public pricing API by tools/refresh_sku_catalog.py --refresh-domain compute.
GPU shapes, secure desktops, estimation_helpers, and discounts are NOT auto-refreshed.
currency: USD
---
# ── Virtual Machine Instances ──────────────────────────────────────
flexible_shapes:
VM.Standard.E6.Flex:
ocpu_per_hour: 0.0168
memory_per_gb_hour: 0.0011
ocpu_per_hour: 0.03
memory_per_gb_hour: 0.002
monthly_730h:
ocpu: 12.26
memory_per_gb: 0.80
notes: "AMD EPYC (latest gen), best price/performance for general workloads"
ocpu: 21.9
memory_per_gb: 1.46
notes: AMD EPYC (latest gen), best price/performance for general workloads
VM.Standard.E5.Flex:
ocpu_per_hour: 0.0210
memory_per_gb_hour: 0.0014
ocpu_per_hour: 0.03
memory_per_gb_hour: 0.002
monthly_730h:
ocpu: 15.33
memory_per_gb: 1.02
notes: "AMD EPYC, general-purpose workloads"
ocpu: 21.9
memory_per_gb: 1.46
notes: AMD EPYC, general-purpose workloads
VM.Standard.E4.Flex:
ocpu_per_hour: 0.0252
memory_per_gb_hour: 0.0017
ocpu_per_hour: 0.025
memory_per_gb_hour: 0.0015
monthly_730h:
ocpu: 18.40
memory_per_gb: 1.24
notes: "AMD EPYC (previous gen)"
ocpu: 18.25
memory_per_gb: 1.09
notes: AMD EPYC (previous gen)
VM.Standard.E3.Flex:
ocpu_per_hour: 0.0252
memory_per_gb_hour: 0.0017
ocpu_per_hour: 0.025
memory_per_gb_hour: 0.0015
monthly_730h:
ocpu: 18.40
memory_per_gb: 1.24
notes: "AMD EPYC (older gen)"
ocpu: 18.25
memory_per_gb: 1.09
notes: AMD EPYC (older gen)
VM.Standard3.Flex:
ocpu_per_hour: 0.0336
memory_per_gb_hour: 0.0022
monthly_730h:
ocpu: 24.53
memory_per_gb: 1.61
notes: "Intel Xeon, for Intel-optimized workloads"
notes: Intel Xeon, for Intel-optimized workloads
VM.Standard.A2.Flex:
ocpu_per_hour: 0.0254
memory_per_gb_hour: 0.0017
ocpu_per_hour: 0.014
memory_per_gb_hour: 0.002
monthly_730h:
ocpu: 18.54
memory_per_gb: 1.24
notes: "Ampere Arm (latest A2), best cost for Arm-compatible workloads"
ocpu: 10.22
memory_per_gb: 1.46
notes: Ampere Arm (latest A2), best cost for Arm-compatible workloads
VM.Standard.A1.Flex:
ocpu_per_hour: 0.0127
memory_per_gb_hour: 0.0008
monthly_730h:
ocpu: 9.27
memory_per_gb: 0.58
free_tier: "3,000 OCPU-hours + 18,000 GB-hours per month"
notes: "Ampere Arm A1, eligible for Always Free tier"
free_tier: 3,000 OCPU-hours + 18,000 GB-hours per month
notes: Ampere Arm A1, eligible for Always Free tier
VM.Standard.x86.Generic:
ocpu_per_hour: 0.0252
memory_per_gb_hour: 0.0017
notes: "Generic x86 pricing when specific shape not yet selected"
notes: Generic x86 pricing when specific shape not yet selected
VM.Optimized3.Flex:
ocpu_per_hour: 0.0504
memory_per_gb_hour: 0.0034
ocpu_per_hour: 0.054
memory_per_gb_hour: 0.0015
monthly_730h:
ocpu: 36.79
memory_per_gb: 2.48
notes: "Highest single-thread performance"
# ── Bare Metal Instances ───────────────────────────────────────────
ocpu: 39.42
memory_per_gb: 1.09
notes: Highest single-thread performance
bare_metal_shapes:
BM.Standard.E5:
ocpu_per_hour: 0.0168
notes: "AMD EPYC bare metal"
ocpu_per_hour: 0.03
notes: AMD EPYC bare metal
BM.Standard.E4:
ocpu_per_hour: 0.0210
notes: "AMD EPYC bare metal (previous gen)"
ocpu_per_hour: 0.025
notes: AMD EPYC bare metal (previous gen)
BM.Standard.E3:
ocpu_per_hour: 0.0420
notes: "AMD EPYC bare metal (older gen)"
ocpu_per_hour: 0.025
notes: AMD EPYC bare metal (older gen)
BM.Standard3:
ocpu_per_hour: 0.0504
notes: "Intel Xeon bare metal"
notes: Intel Xeon bare metal
BM.Standard.A1:
ocpu_per_hour: 0.0127
notes: "Ampere Arm bare metal"
notes: Ampere Arm bare metal
BM.Standard.x9:
ocpu_per_hour: 0.0672
notes: "Intel Xeon x9 bare metal"
# ── GPU Accelerated Compute ────────────────────────────────────────
ocpu_per_hour: 0.04
notes: Intel Xeon x9 bare metal
gpu_shapes:
# NVIDIA Blackwell (latest)
BM.GPU.B300:
per_gpu_hour: 26.88
gpu_count: 8
gpu_model: "NVIDIA B300"
notes: "Blackwell latest, HPC/AI training"
gpu_model: NVIDIA B300
notes: Blackwell latest, HPC/AI training
BM.GPU.B200:
per_gpu_hour: 20.16
gpu_count: 8
gpu_model: "NVIDIA B200"
notes: "Blackwell, large-scale training"
# NVIDIA Hopper
gpu_model: NVIDIA B200
notes: Blackwell, large-scale training
BM.GPU.H200:
per_gpu_hour: 18.54
gpu_count: 8
gpu_model: "NVIDIA H200"
notes: "Hopper H200, large model training"
gpu_model: NVIDIA H200
notes: Hopper H200, large model training
BM.GPU.H100:
per_gpu_hour: 12.96
gpu_count: 8
gpu_model: "NVIDIA H100"
notes: "Hopper H100, training workloads"
# NVIDIA Ampere / Ada
gpu_model: NVIDIA H100
notes: Hopper H100, training workloads
BM.GPU.A100:
per_gpu_hour: 6.72
gpu_count: 8
gpu_model: "NVIDIA A100 40GB/80GB"
notes: "Training and inference, 40GB or 80GB HBM2e"
gpu_model: NVIDIA A100 40GB/80GB
notes: Training and inference, 40GB or 80GB HBM2e
VM.GPU.A10.1:
per_gpu_hour: 0.72
gpu_count: 1
gpu_model: "NVIDIA A10"
notes: "Inference workloads, cost-effective"
gpu_model: NVIDIA A10
notes: Inference workloads, cost-effective
VM.GPU.A10.2:
per_gpu_hour: 0.72
gpu_count: 2
gpu_model: "NVIDIA A10"
notes: "Inference workloads"
gpu_model: NVIDIA A10
notes: Inference workloads
BM.GPU.L40S:
per_gpu_hour: 2.42
gpu_count: 4
gpu_model: "NVIDIA L40S"
notes: "Ada Lovelace, inference and graphics"
# ── Secure Desktops ───────────────────────────────────────────────
gpu_model: NVIDIA L40S
notes: Ada Lovelace, inference and graphics
secure_desktops:
per_desktop_month: 1750.00
notes: "Managed virtual desktop infrastructure"
# ── Estimation Helpers ─────────────────────────────────────────────
per_desktop_month: 1750.0
notes: Managed virtual desktop infrastructure
estimation_helpers:
typical_app_server:
config: "VM.Standard.E5.Flex, 4 OCPU, 64 GB"
monthly: 126.60 # (4 * 15.33) + (64 * 1.02)
config: VM.Standard.E5.Flex, 4 OCPU, 64 GB
monthly: 181.04
typical_web_server:
config: "VM.Standard.E5.Flex, 2 OCPU, 16 GB"
monthly: 46.98 # (2 * 15.33) + (16 * 1.02)
config: VM.Standard.E5.Flex, 2 OCPU, 16 GB
monthly: 67.16
typical_bastion:
config: "VM.Standard.E5.Flex, 1 OCPU, 8 GB"
monthly: 23.49 # (1 * 15.33) + (8 * 1.02)
config: VM.Standard.E5.Flex, 1 OCPU, 8 GB
monthly: 33.58
typical_arm_app_server:
config: "VM.Standard.A1.Flex, 4 OCPU, 24 GB"
monthly: 50.96 # (4 * 9.27) + (24 * 0.58)
config: VM.Standard.A1.Flex, 4 OCPU, 24 GB
monthly: 51.1
discounts:
preemptible: "~50% off on-demand"
capacity_reservation: "~15% off on-demand (85% of list)"
reserved_1yr: "~35% off on-demand"
reserved_3yr: "~55% off on-demand"
universal_credits: "Volume discounts on committed spend"
preemptible: ~50% off on-demand
capacity_reservation: ~15% off on-demand (85% of list)
reserved_1yr: ~35% off on-demand
reserved_3yr: ~55% off on-demand
universal_credits: Volume discounts on committed spend
os_pricing:
free:
- "Oracle Linux"
- "CentOS"
- "Ubuntu"
- "Oracle Autonomous Linux"
- Oracle Linux
- CentOS
- Ubuntu
- Oracle Autonomous Linux
paid:
windows_server:
notes: "Pricing varies by edition, added to compute cost"
notes: Pricing varies by edition, added to compute cost

View File

@@ -1,46 +0,0 @@
---
last_verified: 2025-09-11
source: https://www.oracle.com/cloud/price-list/
description: OCI Containers, Kubernetes, and Serverless pricing.
currency: USD
---
# ── Oracle Kubernetes Engine (OKE) ────────────────────────────────
oke:
basic_cluster:
per_hour: "Free"
notes: "Basic cluster management at no cost"
enhanced_cluster:
per_cluster_hour: 0.10
monthly_per_cluster: 73.00
notes: "Enhanced features: virtual nodes, workload identity, etc."
virtual_nodes:
notes: "Additional per-pod pricing on enhanced clusters"
worker_nodes:
notes: "Billed at standard compute shape rates"
# ── Container Instances ────────────────────────────────────────────
container_instances:
notes: "Billed at compute rates: OCPU/hour + GB memory/hour"
shapes_available:
- "A1 (Arm)"
- "E3 (AMD)"
- "E4 (AMD)"
# ── Functions (Serverless) ─────────────────────────────────────────
functions:
invocations:
free_per_month: 2000000
per_invocation_beyond: 0.0000002
memory:
free_gb_seconds_per_month: 400000
per_gb_second_beyond: 0.00001417
notes: "Generous free tier, very cost-effective for event-driven workloads"
# ── OCI Batch ──────────────────────────────────────────────────────
batch:
notes: "Pay-as-you-go compute pricing, no additional service charge"

View File

@@ -1,283 +0,0 @@
---
last_verified: 2025-09-11
source: https://www.oracle.com/cloud/price-list/
description: OCI Database Service pricing for estimation purposes.
currency: USD
disclaimer: |
Approximate pricing for estimation (within ~15%). Actual pricing varies by
region, commitment level, and negotiated discounts. Always verify against
https://www.oracle.com/cloud/pricing/
---
# ── Autonomous AI Database (Serverless) ───────────────────────────
# NOTE: ADB now uses ECPU billing model (not OCPU)
autonomous_database_serverless:
billing_unit: ECPU
license_included:
ecpu_per_hour: 0.0420
byol:
ecpu_per_hour: 0.0168
storage:
per_gb_month: 0.0850
per_tb_month: 87.04
auto_scaling:
notes: "Billed per ECPU-second for additional ECPUs above base. Same rate."
adg_standby:
notes: "Standby ECPU cost at same rate as primary. Storage shared (no extra)."
backup:
notes: "Automated backups included in storage cost. Manual backups use Object Storage rates."
examples:
8_ecpu_2tb_payg:
monthly_li: "$2,699"
monthly_byol: "$1,150"
breakdown: "8 ECPU × $0.0420/hr × 730hr + 2048GB × $0.0850"
8_ecpu_2tb_byol_with_adg:
monthly: "$2,300"
breakdown: "2 × (8 ECPU × $0.0168/hr × 730hr) + 2048GB × $0.0850"
# ── Autonomous AI JSON Database ────────────────────────────────────
autonomous_json_database:
billing_unit: ECPU
ecpu_per_hour: 0.0420
storage_per_gb_month: 0.0850
notes: "Same pricing as ADB-S, optimized for JSON document workloads"
# ── Autonomous Database Dedicated ──────────────────────────────────
autonomous_database_dedicated:
billing_unit: ECPU
infrastructure:
# X9M / X8M — fixed rack shapes (legacy, still available in some regions)
x9m:
quarter_rack:
base_per_hour: "~$10.50"
monthly_estimate: "$7,500$8,000"
included: "2 DB servers, 3 storage servers, 100TB usable"
half_rack:
base_per_hour: "~$21.00"
monthly_estimate: "$15,000$16,000"
included: "4 DB servers, 6 storage servers, 200TB usable"
full_rack:
base_per_hour: "~$42.00"
monthly_estimate: "$30,000$32,000"
included: "8 DB servers, 12 storage servers, 400TB usable"
# X11M — elastic scaling (new default as of 2025, replaces fixed rack shapes)
x11m:
model: "Elastic — 2 to 32 DB servers + 3 to 64 storage servers (no fixed rack shapes)"
minimum_config: "2 DB servers minimum (cannot order 1 DB server) + 3 storage servers"
billing: "Per ECPU per second (8-ECPU minimum per active DB VM)"
infrastructure_rate: "NOT PUBLICLY LISTED — requires OCI PDM/sales confirmation"
monthly_estimate: "Confirm with Oracle sales; X9M rates used as proxy for estimation"
notes: |
X11M is the current-generation Exadata infrastructure (announced 2025).
Key changes vs X9M:
- No fixed quarter/half/full rack — elastic scale in/out
- MINIMUM: 2 DB servers + 3 storage servers (cannot provision less)
- Infrastructure pricing parity with X9M (no premium) per Oracle comms,
but exact per-hour rates are not published in the public price list
- ECPU billing by the second (vs hourly in older generations)
- Improved compute, storage density, and RDMA throughput vs X9M
ecpu_pricing:
license_included_per_hour: 0.0672
byol_per_hour: 0.0504
notes: |
Infrastructure cost is fixed per rack size (X9M) or elastic per server (X11M). ECPU cost is on top.
DEP (Database Enterprise Patching) co-location is at next maintenance window.
Billing starts only at AVAILABLE state.
Provisioning takes days to weeks depending on capacity.
IMPORTANT: For X11M sizing, confirm infrastructure rates with PDM — use X9M as proxy only.
# ── Base Database Service (DBCS) ──────────────────────────────────
dbcs:
billing_unit: ECPU
license_included:
ecpu_per_hour_se: 0.0336 # Standard Edition
ecpu_per_hour_ee: 0.0420 # Enterprise Edition
ecpu_per_hour_ee_hp: 0.0504 # High Performance
ecpu_per_hour_ee_ep: 0.0672 # Extreme Performance — BYOL only on newer docs
byol:
ecpu_per_hour: 0.0168
storage_per_gb_month: 0.0255
notes: |
SE = Standard Edition, EE = Enterprise Edition,
HP = High Performance (partitioning, advanced compression, etc.),
EP = Extreme Performance (RAC, Active Data Guard, In-Memory).
Backup storage charged separately at Object Storage rates.
examples:
4_ecpu_ee_hp_500gb:
monthly_li: "$160"
breakdown: "4 ECPU × $0.0504/hr × 730hr + 500GB × $0.0255"
# ── Exadata Database Service Dedicated ─────────────────────────────
exadata_dedicated:
billing_unit: ECPU
infrastructure:
# X9M — fixed rack shapes (available in all regions)
x9m:
quarter_rack:
per_hour: 2.10
monthly_estimate: "$1,533"
half_rack:
per_hour: 6.30
monthly_estimate: "$4,599"
full_rack:
per_hour: 12.60
monthly_estimate: "$9,198"
# X11M — elastic scaling (current generation, replaces fixed rack shapes)
x11m:
model: "Elastic — 2 to 32 DB servers + 3 to 64 storage servers"
minimum_config: "2 DB servers + 3 storage servers (hard minimum — applies to ADB-D and ExaCS)"
billing: "Per ECPU per second (8-ECPU minimum per active DB VM)"
infrastructure_rate: "Line items exist in OCI price list ('Database Server - X11M' and 'Storage Server - X11M') but dollar amounts not visible without Oracle Cost Estimator or authenticated access"
proxy_for_estimation: "Use X9M quarter rack ($2.10/hr) as proxy for 2 DB + 3 storage"
notes: |
X11M is confirmed current-gen Exadata for both ExaCS and ADB-D on OCI.
MINIMUM: 2 DB servers + 3 storage servers — cannot provision less (verified against Oracle datasheets).
Per-server line items exist in price list but amounts require Oracle Cost Estimator or PDM quote.
Use X9M quarter rack ($2.10/hr infrastructure) as proxy for minimum config estimation.
ecpu_pricing:
license_included_per_hour: 0.0504
byol_per_hour: 0.0420
what_is_included:
- "Exadata smart storage (flash cache, storage indexes)"
- "Automated patching (GI + DB separate schedules)"
- "Automated backups to Object Storage"
- "RAC licensing included in Extreme Performance edition"
what_is_extra:
- "Data Guard setup and standby infrastructure"
- "Additional storage beyond rack capacity"
- "Object Storage for long-term backup retention"
gotchas:
- "Infrastructure cost is fixed regardless of ECPU utilization (X9M)."
- "X11M elastic model: scale in/out by server, not by rack."
- "Provisioning takes 4-8 hours."
- "X11M has improved storage density, RDMA throughput, and CPU vs X9M."
# ── Exadata Exascale ───────────────────────────────────────────────
exadata_exascale:
billing_unit: ECPU
ecpu_per_hour: 0.0504
storage:
notes: "Storage priced separately per Exascale vault capacity"
notes: "Elastic scaling of compute and storage independently. Next-gen Exadata."
# ── Exadata Cloud@Customer ─────────────────────────────────────────
exadata_cloud_at_customer:
billing_unit: ECPU
ecpu_pricing:
license_included_per_hour: 0.0504
byol_per_hour: 0.0420
infrastructure:
base_per_hour: 7.35
monthly_estimate: "$5,365"
notes: "Exadata infrastructure in customer datacenter, managed by Oracle"
# ── MySQL HeatWave ─────────────────────────────────────────────────
mysql_heatwave:
billing_unit: ECPU
ecpu_per_hour: 0.0180
storage_per_gb_month: 0.0085
heatwave_cluster:
notes: "Additional capacity pricing for HeatWave in-memory acceleration"
free_tier:
notes: "MySQL HeatWave Free Tier available with limits"
mysql_heatwave_on_aws:
ecpu_per_hour: 0.0180
notes: "Cross-cloud deployment, same base pricing"
# ── PostgreSQL ─────────────────────────────────────────────────────
postgresql:
ocpu_per_hour: 0.0168
storage_per_gb_month: 0.0850
notes: "Managed PostgreSQL, includes HA options"
# ── Cache with Redis ───────────────────────────────────────────────
cache_redis:
up_to_10gb:
per_gb_hour: 0.0194
monthly_per_gb: 14.16
above_10gb:
per_gb_hour: 0.0136
monthly_per_gb: 9.93
# ── OpenSearch ─────────────────────────────────────────────────────
opensearch:
per_node_hour: 0.0252
notes: "HA configuration, pricing per node"
# ── NoSQL Database ─────────────────────────────────────────────────
nosql:
provisioned:
storage_per_gb_month: 0.0085
write_unit_per_month: 0.0001
read_unit_per_month: 0.000020
on_demand:
storage_per_gb_month: 0.0085
notes: "Auto-scaled read/write units"
free_tier:
storage_gb: 25
write_units: 50
read_units: 50
max_tables: 3
# ── TimesTen for OKE ──────────────────────────────────────────────
timesten:
x86_ocpu_per_hour: 0.0252
arm_ocpu_per_hour: 0.0168
notes: "In-memory relational database deployed on Kubernetes"
# ── Data Safe ──────────────────────────────────────────────────────
data_safe:
per_target_month: 0.0150
audit_records_per_10k_month: 0.0001
# ── Database Migration ─────────────────────────────────────────────
database_migration:
per_migration_hour: 0.0420
notes: "First 183 days free if migration is active"
# ── Database Autonomous Recovery ───────────────────────────────────
database_autonomous_recovery:
per_gb_virtualized_month: 0.0085
notes: "Autonomous backup recovery service"
# ── GoldenGate ─────────────────────────────────────────────────────
goldengate:
ocpu_per_hour: 0.0252
byol_available: true
notes: "Real-time data integration and replication"
# ── Estimation Helpers ─────────────────────────────────────────────
estimation_helpers:
monthly_hours: 730
byol_savings: "50-60% on ECPU cost for Oracle Database products"
adb_s_sweet_spot: "4-32 ECPUs with auto-scaling. Below 4, consider Always Free. Above 128, consider ADB-D or ExaCS."
cost_comparison_tip: |
When comparing with AWS RDS or Azure SQL MI, include:
- OCI inbound data transfer is free
- OCI outbound is ~80% cheaper than AWS
- OCI BYOL discount is deeper than AWS BYOL
- ADB-S includes patching, tuning, indexing — RDS does not
- ADB now uses ECPU (not OCPU) — 1 ECPU ≈ fraction of an OCPU
reserved_discounts:
one_year: "~35-40% vs PAYG"
three_year: "~55-65% vs PAYG"
notes: "Available for all database services. Commitment is per-region."

View File

@@ -1,59 +0,0 @@
---
last_verified: 2025-09-11
source: https://www.oracle.com/cloud/price-list/
description: OCI Developer Services pricing.
currency: USD
---
# ── APEX Application Development ──────────────────────────────────
apex:
ecpu_per_hour: 0.36
free_tier: true
notes: "Low-code development platform, free tier available"
# ── Visual Builder ─────────────────────────────────────────────────
visual_builder:
ocpu_per_hour: 0.0252
notes: "Low-code app builder with storage"
# ── DevOps ─────────────────────────────────────────────────────────
devops:
pipeline_execution: "Free"
notes: "No charge for pipeline execution; compute/memory billed separately"
# ── Blockchain Platform ───────────────────────────────────────────
blockchain:
ocpu_per_hour: 0.0252 - 0.0504
notes: "Plus storage costs"
# ── IoT Platform ──────────────────────────────────────────────────
iot:
ecpu_per_hour: 0.0360
notes: "Plus storage costs"
# ── Media Flow ─────────────────────────────────────────────────────
media_flow:
per_minute: 0.005 - 0.120
notes: "Varies by codec, resolution, and fps"
# ── Media Streams ──────────────────────────────────────────────────
media_streams:
per_gb_packaged: 0.015
# ── Tuxedo ─────────────────────────────────────────────────────────
tuxedo:
ocpu_per_hour: 0.0252 - 0.0504
notes: "For legacy Tuxedo workload migration"
# ── WebCenter ──────────────────────────────────────────────────────
webcenter:
ocpu_per_hour: 0.0252 - 0.0504

View File

@@ -1,53 +0,0 @@
---
last_verified: 2025-09-11
source: https://www.oracle.com/cloud/price-list/
description: OCI Hybrid Cloud and VMware Solution pricing.
currency: USD
---
# ── Oracle Cloud VMware Solution (OCVS) ───────────────────────────
vmware_solution:
base_nodes:
BM.Standard2.12:
per_node_hour: 2.10 - 4.20
notes: "Hourly to 3-year commitment range"
BM.Standard3.16:
per_node_hour: 3.03 - 6.06
BM.Standard.E4.32:
per_node_hour: 4.20 - 8.40
BM.Standard.E5.48:
per_node_hour: 4.99 - 9.98
expansion:
ocpu_per_hour: 0.0168 - 0.0420
notes: "Commitment-based pricing"
hcx_enterprise:
ocpu_per_hour: 0.0084
minimum_commitment: "1 month"
gpu_storage_nodes:
per_node_hour: 2.10 - 4.20
notes: "Commitment-based pricing"
# ── Compute Cloud@Customer ─────────────────────────────────────────
compute_cloud_at_customer:
e6_compute:
ocpu_per_hour: 0.0336 - 0.0504
storage:
per_gb_month: 0.0085 - 0.0170
load_balancer:
per_hour: 0.10
# ── Managed Service for Mac ────────────────────────────────────────
managed_mac:
per_server_hour:
m2_pro: 1.20
m4_pro: 4.20
notes: "Range depends on Mac model (M2 Pro to M4 Pro)"
# ── Roving Edge Infrastructure ─────────────────────────────────────
roving_edge:
per_device_day: 300 - 1000
notes: "Portable compute/GPU/storage for edge and disconnected scenarios"

View File

@@ -1,55 +0,0 @@
---
last_verified: 2025-09-11
source: https://www.oracle.com/cloud/price-list/
description: OCI Integration and Middleware pricing.
currency: USD
---
# ── Integration Cloud ─────────────────────────────────────────────
integration_cloud:
per_5k_messages_hour: 0.36 - 0.72
notes: "Standard and Enterprise editions"
# ── API Management ─────────────────────────────────────────────────
api_management:
per_api_call: 0.0000005
monthly_1m_calls: 0.50
notes: "Very low cost per call"
# ── Data Integration ───────────────────────────────────────────────
data_integration:
workspace_per_hour: 0.0252
data_processed_per_gb_hour: 0.0252
# ── Data Integrator ────────────────────────────────────────────────
data_integrator:
ocpu_per_hour: 0.0252
# ── Streaming (Kafka compatible) ──────────────────────────────────
streaming:
storage_per_gb_hour: 0.025
data_transfer_per_gb: 0.025
streaming_with_kafka:
ocpu_per_hour: 0.0252
# ── Queue ──────────────────────────────────────────────────────────
queue:
free_per_month: 1000000 # requests
per_request_beyond: 0.0000005
notes: "1M free requests/month, very cost-effective for decoupling"
# ── SOA Suite ──────────────────────────────────────────────────────
soa_suite:
ocpu_per_hour: 0.0504 - 0.0672
notes: "For legacy SOA workload migration"
# ── GoldenGate ─────────────────────────────────────────────────────
# See database.yaml for GoldenGate pricing

View File

@@ -1,70 +0,0 @@
---
last_verified: 2025-09-11
source: https://www.oracle.com/cloud/price-list/
description: OCI Networking pricing for estimation purposes.
currency: USD
---
# ── Load Balancing ─────────────────────────────────────────────────
load_balancer:
base_instance_per_hour: 0.10
bandwidth_per_mbps_hour: 0.0084
monthly_base: 73.00
notes: "Flexible shape, bandwidth billed separately"
network_load_balancer:
per_hour: "Free"
notes: "Layer 4, no per-hour charge, data processing fees apply"
# ── FastConnect ────────────────────────────────────────────────────
fastconnect:
port_per_hour:
1gbps: 0.30
2gbps: 0.50
5gbps: 1.26
10gbps: 2.52
40gbps: 5.04
100gbps: 6.30
400gbps: 12.60
monthly_730h:
1gbps: 219.00
10gbps: 1839.60
100gbps: 4599.00
data_transfer: "Free (ingress and egress)"
notes: "Private dedicated connectivity. No data transfer charges."
# ── VPN Connect ────────────────────────────────────────────────────
vpn_connect:
notes: "No additional charge for IPSec VPN tunnels. Included with DRG."
# ── DNS ────────────────────────────────────────────────────────────
dns:
queries_included_per_month: 1000000
additional: "Free for most use cases"
notes: "1M queries/month included at no cost"
# ── WAF ────────────────────────────────────────────────────────────
waf:
notes: "Pricing based on requests processed. See OCI price list for current rates."
# ── Data Transfer Summary ──────────────────────────────────────────
data_transfer:
ingress: "Free (all sources)"
egress_internet:
first_10tb_month: "Free"
per_gb_beyond: 0.0085
inter_region:
per_gb: 0.0085
fastconnect: "Free (both directions)"
key_advantage: |
OCI is dramatically cheaper than hyperscalers for data transfer:
- AWS charges $0.09/GB egress (OCI: $0.0085 after 10TB free)
- Azure charges $0.087/GB egress
- GCP charges $0.12/GB egress
- OCI FastConnect egress is FREE (AWS DirectConnect charges per GB)

View File

@@ -1,89 +0,0 @@
---
last_verified: 2025-09-11
source: https://www.oracle.com/cloud/price-list/
description: OCI Observability and Management pricing.
currency: USD
---
# ── Monitoring ─────────────────────────────────────────────────────
monitoring:
ingestion:
free_per_month: 500000000 # 500M datapoints
per_datapoint_beyond: 0.00002
retrieval:
free_per_month: 1000000000 # 1B datapoints
per_datapoint_beyond: 0.00002
notes: "Very generous free tier for most workloads"
# ── Logging ────────────────────────────────────────────────────────
logging:
free_per_month_gb: 10
per_gb_month_beyond: 0.0050
notes: "10 GB/month free, very affordable"
# ── Log Analytics ──────────────────────────────────────────────────
log_analytics:
per_storage_unit_month: 2.50 - 5.00
storage_unit_size_gb: 300
notes: "1 storage unit = 300 GB"
# ── Notifications ──────────────────────────────────────────────────
notifications:
free_per_month:
deliveries: 1000000
emails: 1000
per_operation_beyond: 0.00001
per_email_beyond: 0.00001
# ── Events ─────────────────────────────────────────────────────────
events:
notes: "No additional charge for Events service"
# ── APM / Application Performance Monitoring ──────────────────────
apm:
notes: "Pricing based on data ingestion volume and synthetic monitors"
# ── Database Management ────────────────────────────────────────────
database_management:
ecpu_per_hour: 0.0360
notes: "Fleet-level database monitoring and management"
# ── Ops Insights ───────────────────────────────────────────────────
ops_insights:
basic: "Free"
autonomous: "Free"
cloud_external:
ocpu_per_hour: 0.0420
notes: "Basic and Autonomous tiers are free"
# ── Email Delivery ─────────────────────────────────────────────────
email_delivery:
per_1k_emails: 0.00001 - 0.000015
# ── Full Stack Disaster Recovery ───────────────────────────────────
full_stack_dr:
ecpu_per_hour: 0.0360
ocpu_per_hour: 0.0420
notes: "Orchestrates DR failover across compute, database, and networking"
# ── Fleet Application Management ──────────────────────────────────
fleet_app_management:
per_managed_resource_month: 3.00 - 7.50
# ── OS & Java Management ──────────────────────────────────────────
os_management_hub: "Free"
java_management_service: "Free"
autonomous_linux: "Free"
resource_analytics: "Free"

View File

@@ -1,83 +0,0 @@
---
last_verified: 2025-09-11
source: https://www.oracle.com/cloud/price-list/
description: OCI pricing models and discount structures.
---
models:
payg:
name: "Pay As You Go"
commitment: none
discount: none
billing: "Per second (compute), per hour (database), per month (storage)"
when_to_use:
- "Variable/unpredictable workloads"
- "Short-term projects"
- "Dev/test environments"
- "Initial cloud adoption (before committing)"
monthly_flex:
name: "Monthly Flex (Universal Credits)"
commitment: "Minimum $1,000/month or custom commitment"
discount: "Volume discounts on committed spend"
billing: "Committed credits consumed by usage"
when_to_use:
- "Steady-state production workloads"
- "Known baseline consumption"
- "Multiple services across OCI"
discount_tiers:
- spend: "$1K-$10K/month"
discount: "~5-10%"
- spend: "$10K-$50K/month"
discount: "~10-20%"
- spend: "$50K+/month"
discount: "~20-30% (negotiated)"
annual_flex:
name: "Annual Flex (Committed)"
commitment: "1-year or 3-year commitment"
discount: "Deeper discounts than monthly flex"
when_to_use:
- "Established production workloads with predictable spend"
- "Organizations committed to OCI long-term"
byol:
name: "Bring Your Own License"
discount: "~50% on database OCPU costs"
eligible:
- "Oracle Database Enterprise Edition"
- "Oracle Database Standard Edition 2"
- "Oracle WebLogic"
- "Oracle Java SE"
conversion: "1 processor license = 2 OCPUs"
when_to_use:
- "Existing Oracle on-prem licenses with active support"
- "Licenses not being used elsewhere"
when_NOT_to_use:
- "No existing licenses"
- "Licenses still needed for on-prem during migration"
- "Standard Edition workloads on ADB (requires EE)"
reserved_capacity:
name: "Reserved Capacity"
commitment: "1-year or 3-year for specific shapes"
discount:
1_year: "~35% off on-demand"
3_year: "~55% off on-demand"
when_to_use:
- "Known compute shapes running 24/7"
- "Predictable database capacity"
notes: "Shape-specific, less flexible than Universal Credits"
estimation_approach:
step_1: "Calculate PAYG cost first (baseline)"
step_2: "Apply BYOL if customer has eligible licenses"
step_3: "Show savings with Monthly Flex / Annual Flex for steady-state"
step_4: "Compare total annual cost vs current on-prem spending"
step_5: "Include migration costs in year 1"
assumptions_to_state:
- "Hours per month (730 for 24/7)"
- "Auto-scaling hours per day (estimate)"
- "Data transfer volumes"
- "Backup retention"
- "Support tier"

View File

@@ -1,56 +0,0 @@
---
last_verified: 2025-09-11
source: https://www.oracle.com/cloud/price-list/
description: OCI Security service pricing.
currency: USD
---
# ── Access Governance ──────────────────────────────────────────────
access_governance:
premium:
workforce_user_month: 0.0018 - 0.0036
consumer_user_month: 0.36
for_oracle_workloads:
workforce_user_month: 0.0009 - 0.0018
consumer_user_month: 0.36
for_oci:
workforce_user_month: 0.00009 - 0.00018
# ── Vault ──────────────────────────────────────────────────────────
vault:
notes: "Key management — see OCI price list for current rates. Free tier for software keys."
# ── Cloud Guard ────────────────────────────────────────────────────
cloud_guard:
notes: "Free for OCI tenancy monitoring and threat detection"
# ── Security Zones ─────────────────────────────────────────────────
security_zones:
notes: "Free — policy enforcement on compartments"
# ── Vulnerability Scanning ─────────────────────────────────────────
vulnerability_scanning:
notes: "Free — host and container image scanning"
# ── Certificates ───────────────────────────────────────────────────
certificates:
notes: "Free — TLS certificate management"
# ── Bastion ────────────────────────────────────────────────────────
bastion:
notes: "Free — managed SSH/RDP bastion service"
# ── Network Firewall ──────────────────────────────────────────────
network_firewall:
notes: "Pricing based on instance hours and data processed"
# ── Data Safe ──────────────────────────────────────────────────────
# See database.yaml for Data Safe pricing

View File

@@ -1,60 +0,0 @@
---
last_verified: 2025-09-11
source: https://www.oracle.com/cloud/price-list/
description: OCI Storage pricing for estimation purposes.
currency: USD
---
block_volume:
balanced:
per_gb_month: 0.0255
per_tb_month: 26.11
higher_performance:
per_gb_month: 0.0340
per_tb_month: 34.82
lower_cost:
per_gb_month: 0.0170
per_tb_month: 17.41
uhp:
notes: "Priced per VPU, varies by configuration"
boot_volume:
free_tier: "200 GB included"
additional: "Same as block volume pricing"
backup:
per_gb_month: 0.0050
object_storage:
standard:
per_gb_month: 0.0255
per_tb_month: 26.11
infrequent_access:
per_gb_month: 0.0100
per_tb_month: 10.24
archive:
per_gb_month: 0.0026
per_tb_month: 2.66
api_requests:
per_10k_put: 0.0040
per_10k_get: 0.0003
free_tier:
storage_gb: 10
requests: 50000
file_storage:
per_gb_month: 0.0340
per_tb_month: 34.82
data_transfer:
ingress: "Free"
egress_internet:
first_10tb_month: "Free"
per_gb_after: 0.0085
inter_region:
per_gb: 0.0085
fastconnect:
ingress: "Free"
egress: "Free"
notes: |
OCI egress pricing is significantly cheaper than AWS/Azure/GCP.
First 10 TB/month internet egress is free.
FastConnect egress is free (no per-GB charge).

82
scripts/sync-skill.py Normal file
View File

@@ -0,0 +1,82 @@
#!/usr/bin/env python3
"""
Sync SKILL.md (root, source of truth) to .agents/skills/oci-deal-accelerator/SKILL.md.
The Codex copy under .agents/ must be byte-identical to the root SKILL.md
except for an auto-generated banner inserted after the YAML frontmatter.
Usage:
python scripts/sync-skill.py # write the .agents/ copy
python scripts/sync-skill.py --check # exit 1 if out of sync (for CI/lint)
"""
import argparse
import os
import sys
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
SOURCE = os.path.join(PROJECT_ROOT, "SKILL.md")
TARGET = os.path.join(
PROJECT_ROOT, ".agents", "skills", "oci-deal-accelerator", "SKILL.md"
)
BANNER = (
"<!-- AUTO-GENERATED FROM /SKILL.md — do not edit directly. "
"Run `python scripts/sync-skill.py` to regenerate. -->\n"
)
def render() -> str:
"""Read root SKILL.md and return the .agents/ version with banner injected."""
with open(SOURCE, "r", encoding="utf-8") as fh:
content = fh.read()
# Inject banner after the closing `---` of the YAML frontmatter, if present.
if content.startswith("---\n"):
end = content.find("\n---\n", 4)
if end != -1:
head = content[: end + len("\n---\n")]
tail = content[end + len("\n---\n") :]
return head + "\n" + BANNER + tail
# No frontmatter — prepend banner.
return BANNER + content
def cmd_check() -> int:
expected = render()
if not os.path.isfile(TARGET):
print(f"sync-skill: target missing: {TARGET}")
return 1
with open(TARGET, "r", encoding="utf-8") as fh:
actual = fh.read()
if actual == expected:
print("sync-skill: OK (in sync)")
return 0
print("sync-skill: OUT OF SYNC")
print(f" source: {SOURCE}")
print(f" target: {TARGET}")
print(" run: python scripts/sync-skill.py")
return 1
def cmd_write() -> int:
expected = render()
os.makedirs(os.path.dirname(TARGET), exist_ok=True)
with open(TARGET, "w", encoding="utf-8") as fh:
fh.write(expected)
print(f"sync-skill: wrote {os.path.relpath(TARGET, PROJECT_ROOT)} "
f"({len(expected.splitlines())} lines)")
return 0
def main() -> int:
parser = argparse.ArgumentParser(description="Sync root SKILL.md to .agents/")
parser.add_argument("--check", action="store_true",
help="Exit 1 if out of sync; do not write.")
args = parser.parse_args()
return cmd_check() if args.check else cmd_write()
if __name__ == "__main__":
sys.exit(main())

176
tools/kb_freshness.py Normal file
View File

@@ -0,0 +1,176 @@
#!/usr/bin/env python3
"""
OCI Deal Accelerator — KB Freshness Reporter
Thin wrapper around kb_linter.check_freshness() that:
- reports stale/warning KB files in a compact, scriptable format
- knows which stale files have a refresh tool, and can run it on demand
- is safe to call from the skill welcome flow as a precondition check
Usage:
python tools/kb_freshness.py --check # human-readable report
python tools/kb_freshness.py --check --quiet # no output, exit 1 if stale
python tools/kb_freshness.py --check --json # JSON output for the skill
python tools/kb_freshness.py --auto-refresh # run refresh tools for stale files
Exit codes:
0 — all files fresh (or all stale files refreshed successfully)
1 — stale files found (in --check mode) or refresh failed (--auto-refresh)
2 — internal error
"""
import argparse
import json
import os
import subprocess
import sys
from typing import Any, Dict, List, Optional
# Reuse the linter's freshness implementation. kb_linter.py lives in the same
# directory; add it to sys.path so this script can be invoked from anywhere.
_HERE = os.path.dirname(os.path.realpath(__file__))
if _HERE not in sys.path:
sys.path.insert(0, _HERE)
from kb_linter import check_freshness # type: ignore # noqa: E402
PROJECT_ROOT = os.path.dirname(_HERE)
# Bridge: KB file -> refresh command (relative to PROJECT_ROOT).
# Only files with a known automated source belong here. Files with no entry
# can only be refreshed by a human and will be reported as such.
REFRESH_TOOLS: Dict[str, List[str]] = {
"kb/pricing/oci-sku-catalog.yaml": [
sys.executable, "tools/refresh_sku_catalog.py", "--refresh",
],
"kb/pricing/compute.yaml": [
sys.executable, "tools/refresh_sku_catalog.py", "--refresh-domain", "compute",
],
"kb/architecture-center/catalog.yaml": [
sys.executable, "tools/refresh_arch_catalog.py", "--whats-new",
],
}
def collect_stale() -> List[Dict[str, Any]]:
"""Return only files in WARNING or STALE state, sorted oldest first."""
results = check_freshness()
stale = [r for r in results if r["status"] in ("STALE", "WARNING")]
stale.sort(key=lambda r: r["age_days"], reverse=True)
return stale
def has_refresh_tool(rel_path: str) -> bool:
return rel_path in REFRESH_TOOLS
def run_refresh(rel_path: str) -> bool:
"""Run the refresh tool for `rel_path`. Returns True on success."""
cmd = REFRESH_TOOLS[rel_path]
print(f" refreshing {rel_path} ...")
proc = subprocess.run(cmd, cwd=PROJECT_ROOT)
return proc.returncode == 0
def cmd_check(args: argparse.Namespace) -> int:
stale = collect_stale()
if args.json:
payload = {
"stale_count": len(stale),
"files": [
{
"file": s["file"],
"status": s["status"],
"age_days": s["age_days"],
"refreshable": has_refresh_tool(s["file"]),
}
for s in stale
],
}
print(json.dumps(payload, indent=2))
return 1 if stale else 0
if not stale:
if not args.quiet:
print("KB freshness: OK (all files within thresholds)")
return 0
if args.quiet:
return 1
refreshable = sum(1 for s in stale if has_refresh_tool(s["file"]))
print(f"KB freshness: {len(stale)} file(s) need attention "
f"({refreshable} have an automatic refresh tool)")
print()
for s in stale:
marker = "[auto]" if has_refresh_tool(s["file"]) else "[manual]"
print(f" {s['status']:<7} {marker:<8} {s['age_days']:>4}d {s['file']}")
print()
print("To refresh files with [auto]: python tools/kb_freshness.py --auto-refresh")
return 1
def cmd_auto_refresh(args: argparse.Namespace) -> int:
stale = collect_stale()
refreshable = [s for s in stale if has_refresh_tool(s["file"])]
if not refreshable:
print("KB freshness: nothing to auto-refresh "
f"({len(stale)} stale file(s), none have a refresh tool)")
return 0 if not stale else 1
print(f"Auto-refreshing {len(refreshable)} file(s)...")
failures: List[str] = []
for s in refreshable:
if not run_refresh(s["file"]):
failures.append(s["file"])
if failures:
print(f"\nFAILED: {len(failures)} refresh(es) errored:")
for f in failures:
print(f" - {f}")
return 1
print("\nAll automatic refreshes completed.")
# Re-check to confirm
remaining = [s for s in collect_stale() if has_refresh_tool(s["file"])]
if remaining:
print(f"WARNING: {len(remaining)} file(s) still stale after refresh:")
for r in remaining:
print(f" - {r['file']} ({r['age_days']}d)")
return 1
return 0
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
prog="kb_freshness",
description="Report and refresh stale KB files.",
)
parser.add_argument("--check", action="store_true",
help="Report stale files (default mode).")
parser.add_argument("--auto-refresh", action="store_true",
help="Run refresh tools for stale files that support them.")
parser.add_argument("--quiet", action="store_true",
help="Suppress output; use exit code only.")
parser.add_argument("--json", action="store_true",
help="Emit JSON (for the skill welcome flow to consume).")
return parser
def main() -> int:
args = build_parser().parse_args()
if args.auto_refresh:
return cmd_auto_refresh(args)
# Default mode is --check
return cmd_check(args)
if __name__ == "__main__":
try:
sys.exit(main())
except Exception as e: # pragma: no cover
print(f"kb_freshness: internal error: {e}", file=sys.stderr)
sys.exit(2)

View File

@@ -60,7 +60,14 @@ def _load_yaml(path: str) -> Optional[Dict[str, Any]]:
if not os.path.isfile(resolved):
return None
with open(resolved, "r", encoding="utf-8") as fh:
return yaml.safe_load(fh)
# Many KB files use a frontmatter pattern: a metadata doc followed by
# a body doc, separated by `---`. Merge all dict docs into one so
# callers see a single namespace (later docs override earlier keys).
merged: Dict[str, Any] = {}
for doc in yaml.safe_load_all(fh):
if isinstance(doc, dict):
merged.update(doc)
return merged or None
def _load_governance() -> Dict[str, Any]:
@@ -125,8 +132,14 @@ def check_contributor_blocks(tracker_path: str = TRACKER_PATH) -> List[str]:
else:
issues.append(f"{fid}: missing contributor block")
continue
# The finding's top-level `date` is the canonical discovery date and
# acts as a fallback when the contributor block doesn't repeat it.
finding_date = f.get("date")
for field in required:
if not contributor.get(field):
value = contributor.get(field)
if not value and field == "date" and finding_date:
continue
if not value:
issues.append(f"{fid}: contributor missing required field '{field}'")
conf = contributor.get("confidence", "")
if conf and conf not in valid_confidence:
@@ -239,7 +252,11 @@ def check_freshness() -> List[Dict[str, Any]]:
if not data:
continue
last_verified = data.get("last_verified") or data.get("last_updated")
last_verified = (
data.get("last_verified")
or data.get("last_updated")
or data.get("last_refreshed")
)
if last_verified:
age = _days_ago(last_verified)
if age is not None:

View File

@@ -314,7 +314,7 @@ def main():
existing_urls.add(url)
new_count += 1
catalog["last_refreshed"] = datetime.now().strftime("%Y-%m-%d")
catalog["last_verified"] = datetime.now().strftime("%Y-%m-%d")
catalog["source"] = "https://docs.oracle.com/en/solutions/oracle-architecture-center/"
catalog["entry_count"] = len(catalog.get("entries", []))
save_catalog(catalog)

View File

@@ -28,6 +28,7 @@ Usage:
import argparse
import json
import os
import re
import sys
import time
from datetime import date
@@ -50,6 +51,17 @@ DEFAULT_CURRENCY = "USD"
# ── Paths ─────────────────────────────────────────────────────────
TOOLS_DIR = Path(__file__).resolve().parent
CATALOG_PATH = TOOLS_DIR.parent / "kb" / "pricing" / "oci-sku-catalog.yaml"
COMPUTE_DOMAIN_PATH = TOOLS_DIR.parent / "kb" / "pricing" / "compute.yaml"
# ── Domain refresh registry ───────────────────────────────────────
# Maps a domain key (used by --refresh-domain) to its file path and
# refresher function. Add a new entry here to support more domains.
DOMAIN_REGISTRY = {
"compute": {
"path": COMPUTE_DOMAIN_PATH,
"refresher": "refresh_compute_yaml",
},
}
def fetch_all_products(currency="USD", verbose=False):
@@ -293,6 +305,252 @@ def inspect_sku(part_number):
))
# ── Domain refresh: compute ───────────────────────────────────────
# Compute family token regex. Matches the family token (E3-E6, A1/A2/A4, X9)
# inside shape names like VM.Standard.E6.Flex, BM.Standard.E5, BM.Standard.x9.
_COMPUTE_FAMILY_RE = re.compile(r'\b(E[3-6]|A[1-4]|X9|x9)\b')
def _shape_family(shape_name):
"""Return the family token (E5, A2, X9, ...) used in API displayName,
or None if the shape can't be mapped automatically.
Special case: VM.Optimized3.Flex maps to the 'Optimized X9' product line.
"""
if "Optimized3" in shape_name or "Optimized" in shape_name:
return "X9_OPTIMIZED"
m = _COMPUTE_FAMILY_RE.search(shape_name)
if m:
return m.group(1).upper()
return None
def build_compute_family_lookup(api_map):
"""Scan the API for Compute Standard / Optimized OCPU and Memory products,
return {family: {'ocpu': price, 'memory': price, 'ocpu_sku': sku, 'memory_sku': sku}}.
"""
lookup = {}
for sku, product in api_map.items():
name = product.get("displayName", "")
if "Compute" not in name:
continue
if "Cloud@Customer" in name:
continue
if "Dense I/O" in name or "Dense IO" in name:
continue # different pricing tier
if "HPC" in name:
continue
if "VMware" in name:
continue
if "GPU" in name:
continue # GPU shapes not handled in this domain refresher
is_optimized = "Optimized" in name
is_standard = "Standard" in name
if not (is_optimized or is_standard):
continue
# Find the family token in the displayName
m = _COMPUTE_FAMILY_RE.search(name)
if not m:
continue
family = m.group(1).upper()
if is_optimized:
family = "X9_OPTIMIZED"
metric = product.get("metricName", "")
price = extract_payg_price(product)
slot = lookup.setdefault(family, {})
if "OCPU" in metric.upper():
# Prefer the first match (deterministic across runs since API order is stable)
slot.setdefault("ocpu", price)
slot.setdefault("ocpu_sku", sku)
elif "GIGABYTE" in metric.upper() or "Gigabytes" in metric:
slot.setdefault("memory", price)
slot.setdefault("memory_sku", sku)
return lookup
def _load_multidoc_yaml(path):
"""Load a multi-doc YAML file (frontmatter + body) and return both as dicts."""
with open(str(path), "r", encoding="utf-8") as fh:
docs = list(yaml.safe_load_all(fh))
frontmatter = {}
body = {}
for d in docs:
if not isinstance(d, dict):
continue
# Frontmatter typically has last_verified, source, description, currency
if "last_verified" in d or "source" in d or "currency" in d:
frontmatter.update(d)
else:
body.update(d)
return frontmatter, body
def _save_multidoc_yaml(path, frontmatter, body):
"""Write frontmatter + body as a two-doc YAML file."""
with open(str(path), "w", encoding="utf-8") as fh:
yaml.safe_dump(frontmatter, fh, default_flow_style=False, sort_keys=False, allow_unicode=True)
fh.write("---\n")
yaml.safe_dump(body, fh, default_flow_style=False, sort_keys=False, allow_unicode=True, width=120)
def refresh_compute_yaml(verbose=False):
"""Refresh kb/pricing/compute.yaml from the live API.
Updates ocpu_per_hour, memory_per_gb_hour, and monthly_730h for shapes
in flexible_shapes and bare_metal_shapes. Skips GPU shapes (out of scope).
Preserves notes, free_tier, gpu_model, and other manual fields.
"""
print("Fetching current prices from Oracle API...")
products = fetch_all_products(currency=DEFAULT_CURRENCY, verbose=verbose)
api_map = {p.get("partNumber", ""): p for p in products if p.get("partNumber")}
print(" {} products from API".format(len(api_map)))
family_prices = build_compute_family_lookup(api_map)
if verbose:
print("\n Family lookup built:")
for fam, prices in sorted(family_prices.items()):
print(" {:<14} OCPU=${:.4f} Memory=${:.4f}".format(
fam, prices.get("ocpu", 0), prices.get("memory", 0)
))
print("\nLoading {}...".format(COMPUTE_DOMAIN_PATH))
frontmatter, body = _load_multidoc_yaml(COMPUTE_DOMAIN_PATH)
updated = []
skipped = []
def update_shape(section_name, shape_name, shape_data, has_memory=True):
family = _shape_family(shape_name)
if not family or family not in family_prices:
skipped.append((section_name, shape_name, "no API match"))
return
prices = family_prices[family]
new_ocpu = prices.get("ocpu")
new_memory = prices.get("memory")
if new_ocpu is None:
skipped.append((section_name, shape_name, "no OCPU price"))
return
old_ocpu = shape_data.get("ocpu_per_hour") or 0
old_memory = shape_data.get("memory_per_gb_hour") or 0
# Protect against API returning $0 for tiered/free-tier SKUs (e.g. A1 Always Free).
# Same convention as refresh_catalog(): keep the existing value if it's > 0.
if new_ocpu == 0 and old_ocpu > 0:
skipped.append((section_name, shape_name, "API returned $0 (free tier) — kept existing"))
return
if has_memory and new_memory == 0 and old_memory > 0:
skipped.append((section_name, shape_name, "API returned $0 memory (free tier) — kept existing"))
return
shape_data["ocpu_per_hour"] = new_ocpu
if has_memory and new_memory is not None:
shape_data["memory_per_gb_hour"] = new_memory
# Recompute monthly_730h block if present
if "monthly_730h" in shape_data:
shape_data["monthly_730h"] = {
"ocpu": round(new_ocpu * 730, 2),
"memory_per_gb": round(new_memory * 730, 2),
}
updated.append((section_name, shape_name, family, old_ocpu, new_ocpu, old_memory, new_memory))
else:
updated.append((section_name, shape_name, family, old_ocpu, new_ocpu, None, None))
for shape_name, shape_data in (body.get("flexible_shapes") or {}).items():
if isinstance(shape_data, dict):
update_shape("flexible_shapes", shape_name, shape_data, has_memory=True)
for shape_name, shape_data in (body.get("bare_metal_shapes") or {}).items():
if isinstance(shape_data, dict):
update_shape("bare_metal_shapes", shape_name, shape_data, has_memory=False)
# Update frontmatter: bump last_verified, replace stale source, drop NEEDS REVIEW
# (the comment block lives only in the source text and is dropped on round-trip)
frontmatter["last_verified"] = date.today().isoformat()
frontmatter["source"] = API_BASE
frontmatter["description"] = (
"OCI Compute pricing for estimation purposes. Auto-refreshed from the "
"Oracle public pricing API by tools/refresh_sku_catalog.py --refresh-domain compute. "
"GPU shapes, secure desktops, estimation_helpers, and discounts are NOT auto-refreshed."
)
# Recompute estimation_helpers from the new E5 / A1 prices, since the
# hardcoded `monthly` values are derived from them.
_recompute_compute_estimation_helpers(body)
_save_multidoc_yaml(COMPUTE_DOMAIN_PATH, frontmatter, body)
print("\nRefresh complete:")
print(" Shapes updated: {}".format(len(updated)))
print(" Shapes skipped: {}".format(len(skipped)))
if verbose or updated:
print("\nUpdated shapes:")
for section, name, family, old_o, new_o, old_m, new_m in updated:
mem = ""
if old_m is not None:
mem = " mem ${:.4f}->${:.4f}".format(old_m, new_m)
print(" [{}] {} ({}): OCPU ${:.4f}->${:.4f}{}".format(
section, name, family, old_o or 0, new_o, mem
))
if skipped:
print("\nSkipped shapes (no API match — preserve existing values):")
for section, name, reason in skipped:
print(" [{}] {} ({})".format(section, name, reason))
print("\nFile saved: {}".format(COMPUTE_DOMAIN_PATH))
def _recompute_compute_estimation_helpers(body):
"""Recompute the hardcoded `monthly` values in estimation_helpers from
the (now fresh) E5 and A1 prices. Best-effort: if the referenced shape
is missing, leave the helper unchanged.
"""
helpers = body.get("estimation_helpers") or {}
flex = body.get("flexible_shapes") or {}
# Configs are: (helper_key, shape_name, ocpu_count, memory_gb)
rules = [
("typical_app_server", "VM.Standard.E5.Flex", 4, 64),
("typical_web_server", "VM.Standard.E5.Flex", 2, 16),
("typical_bastion", "VM.Standard.E5.Flex", 1, 8),
("typical_arm_app_server", "VM.Standard.A1.Flex", 4, 24),
]
for helper_key, shape_name, ocpus, mem_gb in rules:
if helper_key not in helpers:
continue
shape = flex.get(shape_name)
if not isinstance(shape, dict):
continue
ocpu_h = shape.get("ocpu_per_hour")
mem_h = shape.get("memory_per_gb_hour")
if ocpu_h is None or mem_h is None:
continue
# 730 hours per month convention (matches the rest of the file)
monthly = round((ocpus * ocpu_h * 730) + (mem_gb * mem_h * 730), 2)
helpers[helper_key]["monthly"] = monthly
def refresh_domain(domain_key, verbose=False):
"""Dispatch to the registered domain refresher."""
if domain_key not in DOMAIN_REGISTRY:
print("Unknown domain: {}. Available: {}".format(
domain_key, ", ".join(sorted(DOMAIN_REGISTRY.keys()))
))
return 1
refresher_name = DOMAIN_REGISTRY[domain_key]["refresher"]
refresher = globals()[refresher_name]
refresher(verbose=verbose)
return 0
def dump_all(output_path, verbose=False):
"""Dump raw API response to JSON file."""
products = fetch_all_products(currency=DEFAULT_CURRENCY, verbose=verbose)
@@ -307,6 +565,10 @@ def main():
)
parser.add_argument("--refresh", action="store_true",
help="Refresh catalog prices from Oracle API")
parser.add_argument("--refresh-domain", type=str, metavar="DOMAIN",
choices=sorted(DOMAIN_REGISTRY.keys()),
help="Refresh a domain pricing file from the API "
"(currently: compute)")
parser.add_argument("--validate", action="store_true",
help="Validate catalog prices against API")
parser.add_argument("--sku", type=str,
@@ -321,6 +583,8 @@ def main():
if args.sku:
inspect_sku(args.sku)
elif args.refresh_domain:
return refresh_domain(args.refresh_domain, verbose=args.verbose or args.diff)
elif args.refresh:
refresh_catalog(verbose=args.verbose or args.diff)
elif args.validate: