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.

Zur Installation springen

Quellinformationen

Repository
oracle-samples/oracle-aidp-samples
Letzte Quellaktivität
7. August 2026 um 11:32
Erkannte Sprache von SKILL.md
Englisch
Sterne
46
Forks
30

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
3 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
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
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen