Skip to main content

mart-author

Author the smallest additive content-pack overlay for a missing gold mart, silver dimension, or compatible column. Use when live AIDP gold and existing packs cannot serve a business goal and a new medallion node is required.

Ir a la instalación

Datos de origen

Repositorio
oracle-samples/oracle-aidp-samples
Última actividad en el origen
7 de agosto de 2026 a las 11:32
Idioma detectado de SKILL.md
inglés
Estrellas
46
Forks
30

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Explorador de archivos
3 archivos

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
mart-author
description
Author the smallest additive content-pack overlay for a missing gold mart, silver dimension, or compatible column. Use when live AIDP gold and existing packs cannot serve a business goal and a new medallion node is required.
# mart-author — author a new medallion node, additively and cheaply ## Bundled CLI Resolve `<plugin-root>` as the directory two levels above this `SKILL.md`. On macOS/Linux, invoke `"<plugin-root>/bin/aidp-fusion-autopilot"`; on Windows, invoke `"<plugin-root>\\bin\\aidp-fusion-autopilot.cmd"`. Command examples below use `aidp-fusion-autopilot` as shorthand only—do not assume the plugin's `bin/` directory is on `PATH`. When the gold layer genuinely can't serve a dashboard, this skill extends the medallion **as v2 content-pack artifacts** (YAML + SQL), authored like a careful data engineer: the smallest, additive, lowest-cost change that serves the need **without disturbing already-materialized delta**. It is the GAP-handler of the skill family. It does **not** seed, query live data, create OAC datasets, or write `dim_*.py` modules (v2 forbids the last — content-pack YAML+SQL only; `tests/architectural/test_no_new_legacy_modules.py` enforces it). > Not to be confused with **`medallion-author`**, which resolves *tenant > variation* (column aliases / semantic variants) into an overlay. This skill > authors *new analytical content*. Both write to overlay packs. ## When to use - `oac-dataset-advisor` reports a **true GAP** (neither live gold nor the pack's buildable menu can serve the request). - "Add a metric/dimension my gold layer doesn't have", "create a mart for <business logic>", "I need a column that isn't there". ## When NOT to use - The data exists but isn't materialized → `aidp-fusion-autopilot run --mode seed` (or `$aidp-fusion-seed`); use `oac-dataset-advisor` to confirm. - Resolving column-alias / semantic-variant tenant variation → `medallion-author`. - A **bronze column-TYPE** bug (a declared `outputSchema` type is wrong vs the live PVO, e.g. `decimal(38,30)` → `decimal(18,0)`) → that's a **bronze type-overlay** via `medallion-author` (AIDPF-4070), **not** a new mart. The PVO source schema you inspect here surfaces the right type; retype in place via the overlay rather than authoring a new node. - Changing a **bronze** node's `requiredColumns` (assert/pull an extra source column, or relax a normally-required one a tenant's PVO lacks) → that's a **bronze requiredColumns overlay** via `medallion-author` (add via `requiredColumns`, acknowledged removal via `relaxRequiredColumns`; AIDPF-2062/2063), **not** a new mart. - Building the OAC dataset/workbook → `oac-dataset-advisor` + `workbook-authoring`. ## Non-negotiable safety rules 1. **Never disturb living delta.** Reading existing bronze/silver is fine; rewriting/altering/reprocessing them is forbidden (they may be terabytes). 2. **Additive only.** New nodes, or a new column on an existing node — never a change to an existing node's **grain or natural key**. 3. **New bronze extracts are additive** — a new `bronze_extract` node, never an edit to an existing one. 4. **Write to a persistent overlay pack beside the bundle** (`<bundle.yaml.parent>/overlays/<name>/`) — never `/tmp`, never the shipped installed `content_packs/` tree. 5. **Inspect the Fusion PVO source schema, not bronze**, to discover raw fields (metadata-only; cheap; authoritative for "what could be extracted"). 6. **Classify every new bronze PVO before authoring.** A rung-4 `bronze_extract` must be classified as transaction/change-feed, snapshot/config, or period-windowable snapshot before its YAML is accepted. 7. **Declare your inputs (AIDPF-2084).** In any silver/gold SQL you author: alias every upstream source, **never `SELECT *` from an upstream** (project columns explicitly), qualify every upstream column with its alias, and list every one in the node's `requiredColumns[<source>]` (literal, or `$column.<key>` / `$coa.<role>` for a token). If a consumed column isn't in the upstream's `outputSchema`, add it there too (keeps AIDPF-2045 green). The declared-inputs gate fails closed on an undeclared read or a wildcard. ## Helpers | File | Role | Invoked via | |---|---|---| | `change_planner.py` | Given where each needed field is sourced (existing layer / PVO-only / missing), picks the lowest-cost rung on the change ladder and emits a node spec with audit columns + refresh strategy + currency-in-grain checks pre-stamped. | `Bash`, JSON in/out | | `../oac-dataset-advisor/catalog_inventory.py` | Live materialized tables (what exists). | reuse | | `../oac-dataset-advisor/pack_capability.py` | Pack's buildable menu (what nodes already exist). | reuse | ## The change-strategy ladder (cheapest first) | Rung | Build | When | |---|---|---| | **3 — change a mart in place** | guarded same-id full replacement (`replaceNode`) of an existing silver/gold mart | add / remove / rewrite a column or logic from columns already in that node's sources, **identity unchanged** | | **1 — new gold** | new aggregate/business mart over EXISTING bronze/silver | a new metric/grain from already-materialized data | | **2 — new silver** | new conformed/typed node over EXISTING bronze | a conformed shape not yet in silver | | **4 — new bronze + node** | additive `bronze_extract` + downstream node | a raw field isn't extracted yet (only at the PVO source) | `change_planner.py` chooses the rung. Rung 3 keeps the mart's id (no downstream `dependsOn` repointing) but ships a complete replacement under an acknowledged `replaceNode` block — there is no separate additive mechanism, and add / remove / rewrite all use this one shape. **Rung-3 mechanism (guarded same-id full replacement).** Ship a complete new `overlays/<name>/<layer>/<id>.yaml` + `<id>.sql`, plus: ```yaml overrides: <layer>/<id>: replaceNode: reason: "Why this fork exists; e.g. TICKET-123." forkedFrom: sqlSha256: "<base SQL + referenced semantic fragments fingerprint>" contractSha256: "<base outputSchema/pii + requiredColumns + quality fingerprint>" packVersion: "<base pack version>" ``` - Compute/refresh `forkedFrom` with `aidp-fusion-autopilot content-pack refresh-fork overlays/<name> --node <layer>/<id>` (don't hand-author the hashes). - **Identity must equal base** — `layer`, `target`, the `dependsOn` edge set, and the `refresh` contract. Changing any → `AIDPF-2065`; author a new mart id instead. - A bare same-id file with no `replaceNode` → `AIDPF-2001`. SQL marts only (a builtin like `dim_calendar` → `AIDPF-2001`). - If the base mart later changes, validate fails closed (`AIDPF-2064`) until you re-reconcile and re-run `refresh-fork`. This is the accepted cost of forking the SQL (the base fix does not flow through automatically). --- ## Workflow ### 1 — Frame the gap Restate the missing metric/dimension/grain (ideally from `oac-dataset-advisor`'s GAP output) and the business logic. Confirm the intended output grain with the user. ### 2 — Inventory what already exists (read-only) Run the advisor's helpers to find the closest existing data to build on: - live materialized tables — `catalog_inventory.py` (what exists); - existing pack nodes/columns — `pack_capability.py` (what's already declared). Do not scan bronze data — you only need the column inventory. ### 3 — Probe the Fusion PVO SOURCE schema (metadata-only) For any field the business logic needs that is NOT already in an existing table, confirm it exists at source and get its real name/type **from the PVO, not bronze**: ```bash aidp-fusion-autopilot catalog probe --pod <url> # list/reconcile PVOs aidp-fusion-autopilot catalog probe-pvo <dataset_id> \ # one PVO's schema, metadata-only --datastore <DatastorePVO> --bicc-schema <Financial|HCM|SCM> \ --emit-pack-yaml overlays/<name>/bronze/<id>.yaml # persistent, beside bundle.yaml ``` `probe-pvo` does a schema-only roundtrip (no row pull) and emits a **draft bronze YAML** — the additive extract for rung 4. For any rung-4 `bronze_extract`, classify the source PVO before accepting the draft YAML. **The skill owns this classification. `change_planner.py` only validates and carries the evidence; it is not the source of truth.** Use BICC metadata, PVO semantics, and data-owner/business confirmation rather than column-name guesses. > **Verify incremental capability live — do not guess it from PVO class.** The > table below is a *hypothesis*, not the answer. The "snapshot/config ⇒ > `incrementalCapable: false`" heuristic is wrong often enough to matter: > `gl_coa` shipped `false` because it "looked like config," yet a live BICC probe > proved BICC fully honors the lineage delta for it (recent-watermark extract = 0 > rows vs full 69,578) — it is perfectly incrementable. Before you stamp > `incrementalCapable` (true OR false) on a new bronze node, hand the source PVO > to **`$incremental-mechanism`**, which live-probes whether BICC honors > `fusion.initial.extract-date` and returns the verified rung. Stamp the YAML from > that verdict, not from the class label. | PVO class | Required authoring behavior | |---|---| | **Transaction / change-feed PVO** | Use `incrementalCapable: true` only when live BICC metadata exposes a reliable `isLastUpdateDate` column and the business semantics confirm changes advance through that column. The column may have a PVO-specific name; record the exact metadata-observed watermark column and natural key in YAML. | | **Snapshot / config PVO** | Use `incrementalCapable: false`. Warn the user that incremental runs will full-pull this bronze source, then MERGE/payload-diff downstream. If the source may be large, stop for explicit user approval. | | **Period-windowable snapshot** | Treat high-volume period snapshots like `gl_period_balances` specially. Do not silently create a daily full-pull source; require explicit user approval and either attach/document an `extract_window` policy or create a backlog item until runtime supports it. | If classification is uncertain, stop and ask for evidence from BICC metadata or the Fusion data owner — or run `$incremental-mechanism` to settle it empirically. Never mark a snapshot PVO `incrementalCapable: true` just to make the extract faster; and never mark a node `false` on a hunch — the live probe is cheap and authoritative. ### 4 — Plan the change (pick the rung) Build a field-resolution map — for each required field, where is it sourced? `existing_gold` / `existing_silver` / `existing_bronze` / `pvo_only` / `missing` — then: ```bash python3 change_planner.py --input change_request.json ``` For every `pvo_only` field, include the PVO classification before planning: ```json { "name": "invoice_status", "source": "pvo_only", "pvo": "InvoiceHeaderExtractPVO", "sourceColumn": "StatusCode", "pvoClassification": "transaction_change_feed", "metadataLastUpdateColumns": ["ApInvoicesLastUpdateDate"], "watermarkColumn": "ApInvoicesLastUpdateDate", "businessSemanticsConfirmed": true } ``` Supported `pvoClassification` values are `transaction_change_feed`, `snapshot_config`, and `period_windowable_snapshot`. For a transaction/change feed PVO, provide the exact `metadataLastUpdateColumns` seen from BICC, the chosen `watermarkColumn`, and `businessSemanticsConfirmed: true`. The watermark column does not need to be named `LastUpdateDate`; it must be the metadata-backed column that really advances on meaningful source changes. For a period-windowable snapshot, provide an `extractWindowPolicy` or capture explicit user approval before writing bronze. Returns `{decision, reason, blastRadius, requiresNewBronze, missingFields, warnings, touchesLivingDelta, pvoClassifications, nodeSpecs}`. Act on it: - **`hard_gap`** (a field exists nowhere, not even at the PVO) → stop and tell the user it can't be served as specified; name the missing field(s). - **`requiresNewBronze: true`** → present the PVO classification, expected incremental behavior, and full-pull/window risk to the user before writing. - otherwise → present the chosen rung + blast radius to the user before writing, and resolve any `warnings` (e.g. add `currency_code` to an aggregate's grain). ### 5 — Author the artifacts (correct-by-construction) Write to a **persistent overlay pack beside the bundle**: **`<bundle.yaml.parent>/overlays/<name>/`** (e.g. `overlays/fusion-finance-ar-ext/`), with `pack.yaml` declaring `extends: fusion-finance-starter@<version>`. This is the canonical home — mirrors `medallion-author`'s write boundary, survives reboots, and is what the customer commits/points the bundle at. **Never** write to a temp dir (`/tmp` is lost on reboot) and **never** to the shipped installed `content_packs/` tree. For each `nodeSpec`: - **`<id>.yaml`** — `implementation.type: sql` (or `bronze_extract`), `dependsOn`, the planner's `refresh` strategy **with its documented reason**, and `outputSchema.columns` with a **mandatory `pii` classification per column** (missing → AIDPF-2030). High-PII columns must not be exposed to dashboards. For `bronze_extract`, `incrementalCapable` must match the classification from step 3: true only for proven transaction/change-feed PVOs; false for snapshot/config PVOs; explicit approval or `extract_window` policy for high-volume period-windowable snapshots. - **`<id>.sql`** — Jinja template enforcing the medallion invariants: `COALESCE(...,0)` around every amount arithmetic; **currency in the grain** of any amount aggregate; deterministic **`xxhash64(natural_key)`** surrogate keys (never `monotonically_increasing_id`); audit columns (`{{ run_id_literal }}` → `*_run_id`, `*_built_at`); single financially-correct shape (LEFT JOIN, fact preserved) over runtime path-selection; variation-point refs `{{ column.<name> }}` / `{{ semantic.<name> }}` where the tenant may differ. - (rung 4) the `bronze_extract` YAML from step 3's `probe-pvo` (additive). ### 6 — Validate ```bash aidp-fusion-autopilot content-pack validate <overlay> ``` Fix until clean — schema + content validators cover PII-missing (AIDPF-2030), dependency/SQL integrity, and the no-new-legacy-module rule. Document new error codes in `docs/aidpf-error-codes.md`. ### 7 — Wire the bundle for the client (one command), then hand off to seed An overlay isn't seeded until the bundle points at it. **Do this FOR the client** with the single wiring verb — don't hand-edit YAML: ```bash aidp-fusion-autopilot use-pack overlays/<name> --profile <tenant> ``` Use the default aligning behavior when the client wants the bundle scope to match every silver/gold node in the resolved pack. For narrow customer bundles or a one-mart SQL override, preserve the existing scope instead: ```bash aidp-fusion-autopilot use-pack overlays/<name> --profile <tenant> --no-align ``` When using `--no-align` for a new mart, add only the authored node to `gold.marts` before seeding; otherwise `--datasets <new-id>` is outside the bundle scope and the resolver fails with `AIDPF-1043`. `use-pack` does the content-pack wiring in one step: sets `contentPack: {name: <overlay-id>, path: overlays/<name>, profile}`, aligns `dimensions.build` / `gold.marts` to the resolved pack's real nodes unless `--no-align` is supplied (so stale v1 entries like `dim_org` / `po_backlog` can't break the plan resolver in full-scope wiring), and **normalizes a placeholder-vault `fusion.password` to `${FUSION_BICC_PASSWORD}`** (the cluster loads it from the AIDP credential store; a placeholder vault ref fails with `CredentialResolutionError`). It's comment-preserving and validates the result. Then: 1. **Profile present** — `use-pack` warns if `profiles/<tenant>.yaml` is absent; run `bootstrap` (or reuse one) so it exists. 2. **Config coords** — if `aidp.config.yaml` coords are missing/placeholder, route to `$aidp-fusion-config` (don't make the client hand-copy OCIDs). Any
Ver en GitHub
Este SKILL.md es muy grande, por eso SkillsMP muestra aqui solo la primera seccion. Ver en GitHub