Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
7cc25d8
Add ADOP claude Code Plugin
lavrekha Sep 24, 2026
570a5e3
Merge pull request #28 from lavrekha/adop-claude-plugin
JohnChe88 Sep 24, 2026
3876b0d
Add .claude-plugin manifest (plugin.json + marketplace.json)
lavrekha Sep 25, 2026
ee3c603
Merge branch 'aws-samples:adop-claude-plugin' into adop-claude-plugin
lavrekha Sep 25, 2026
eb0fab1
Merge pull request #29 from lavrekha/adop-claude-plugin
JohnChe88 Sep 25, 2026
4e10433
Merge remote-tracking branch 'origin/main' into adop-claude-plugin
builder-ujaladi Sep 29, 2026
ecb1f3c
Drop the README reference to an Amazon Q doc that was never written
builder-ujaladi Sep 29, 2026
5c42223
Annotate the four bandit findings that cannot apply here
builder-ujaladi Sep 29, 2026
3b7ac06
Annotate the claims DAG's demo temp paths instead of relocating them
builder-ujaladi Sep 29, 2026
544aec0
Merge branch 'fix/ci-red-jobs' into adop-claude-plugin
builder-ujaladi Sep 29, 2026
5a614c9
Teach the MCP config validator about ${CLAUDE_PLUGIN_ROOT}
builder-ujaladi Sep 29, 2026
9c36aa7
Move the plugin to plugins/claude-code for the coming variants
builder-ujaladi Sep 29, 2026
0e33075
Add the root marketplace manifest so the plugin installs from GitHub
builder-ujaladi Sep 29, 2026
ac691d2
Fix the invalid YAML in the plugin's server inventory
builder-ujaladi Sep 29, 2026
c59b86d
Make the plugin's derivation from the repo a checkable contract
builder-ujaladi Sep 29, 2026
6e9eb33
Vendor the codegen engine, templates and contracts into the plugin
builder-ujaladi Sep 29, 2026
acadbb7
Vendor the logging, metadata and utils modules the agents name
builder-ujaladi Sep 29, 2026
3d74d96
Vendor the real regulation packs and the IaC resource catalog
builder-ujaladi Sep 29, 2026
e1acb57
Vendor the MCP servers, config and tool registry
builder-ujaladi Sep 29, 2026
633a3ae
Validate declared anchors against the source, not only the target
builder-ujaladi Sep 29, 2026
60c4600
Carry the 12 .claude/rules into three plugin skills
builder-ujaladi Sep 29, 2026
4f03885
Replace the plugin's agents with translations of .claude/agents/
builder-ujaladi Sep 29, 2026
daf96f1
Replace the plugin's commands with translations of .claude/commands/
builder-ujaladi Sep 29, 2026
36c26d2
Ship the discovery gate and codegen enforcement as plugin hooks
builder-ujaladi Sep 29, 2026
4378472
Rewrite the plugin README for what actually ships, and guard it
builder-ujaladi Sep 29, 2026
53a5382
Add the eval suite and the drift-check CLI
builder-ujaladi Sep 29, 2026
9b76c02
Clear two stale pending markers in the translation manifest
builder-ujaladi Sep 29, 2026
2875d47
Fix the template-to-contract mapping, found by an end-to-end run
builder-ujaladi Sep 29, 2026
70a3a9c
Drop a dangling symlink the plugin was shipping, and guard against more
builder-ujaladi Sep 29, 2026
42f507b
Add a preflight check so a user can tell what they can run
builder-ujaladi Sep 29, 2026
a5d7b50
Credit both authors, and bump to 0.2.0 so an update is actually deliv…
builder-ujaladi Sep 29, 2026
bdae256
Merge origin/main (PR #33) into adop-claude-plugin
builder-ujaladi Sep 29, 2026
ae9a6ae
Restore the README's Amazon Q line, dropped from the CI-fix PR
builder-ujaladi Sep 29, 2026
638caf1
Undo the .mcp.json reformat, keeping only the fastmcp fix it was hiding
builder-ujaladi Sep 29, 2026
e9ee20b
Fix the nosec annotations bandit was reading as garbage, and stop cla…
builder-ujaladi Sep 29, 2026
6ec6c1a
Bump the plugin to 0.2.1 so the nosec and manifest fixes reach an ins…
builder-ujaladi Sep 29, 2026
e176685
Carry the three missing repo hooks into the plugin, and guard the gap…
builder-ujaladi Sep 29, 2026
d9d7097
Bump to 0.3.0 — the plugin gained three hooks
builder-ujaladi Sep 29, 2026
581e1a6
Make adop_check_drift.py refuse paths that contain no artifacts
builder-ujaladi Sep 29, 2026
b8c545b
Close the renderer's blind side: a spec field no template reads, and …
builder-ujaladi Sep 30, 2026
c08a21b
Make four answers expressible that the contracts could not hold, and …
builder-ujaladi Sep 30, 2026
fa30edd
Bump to 0.4.0 — contracts widened, three templates changed
builder-ujaladi Sep 30, 2026
f8ff241
Stop the HIPAA runbook recommending masking methods the system cannot…
builder-ujaladi Sep 30, 2026
9736ae8
C1: render compliance_rules, so the HIPAA masking gate exists
builder-ujaladi Sep 30, 2026
b4aa2c6
M3: honour null_handling, so the pipeline stops overriding the human'…
builder-ujaladi Sep 30, 2026
0b1bbfd
M7: build the Gold schema that was asked for — plus three more silent…
builder-ujaladi Sep 30, 2026
9173f74
H4: scope quality rules to their zone, and stop an empty rule set sco…
builder-ujaladi Sep 30, 2026
526539c
M1/M2: stop a failure being silent, and enforce the SLA that was decl…
builder-ujaladi Sep 30, 2026
1c162af
Fix partitionedBy: it was handed a list, so any partitioned write wou…
builder-ujaladi Sep 30, 2026
c9c0d3d
Finish C1 and H4: all five quality dimensions render, and all five ar…
builder-ujaladi Sep 30, 2026
30e0cf6
Adopt another agent's logical_date fix: port it to the source, and gu…
builder-ujaladi Sep 30, 2026
76dc322
Make the drift validator see the artifacts it was skipping
builder-ujaladi Sep 30, 2026
7217bc6
Two things a spec could ask for and no pipeline could do: suppress a …
builder-ujaladi Sep 30, 2026
b6d2c83
Validate the shipped workload specs — one of them never has
builder-ujaladi Sep 30, 2026
c5ca81c
Stop one hook's deny message contradicting another hook
builder-ujaladi Sep 30, 2026
039d112
Resolve the ${NAME} parameters instead of shipping them as literal text
builder-ujaladi Sep 30, 2026
9afd97b
README: say plainly what you give it, what you get, and how to deploy
builder-ujaladi Oct 1, 2026
098f86e
Stop the test suite creating phantom workloads in the repository
builder-ujaladi Oct 1, 2026
a5c2b5c
SCD Type 2 for Gold dimensions, and a CDC ingest sequence for Bronze
builder-ujaladi Oct 1, 2026
e4e783b
Check that the stages of a pipeline actually connect to each other
builder-ujaladi Oct 1, 2026
3107dbd
Stop the Bronze source guard inviting the defect it was written to pr…
builder-ujaladi Oct 1, 2026
21619a6
Bump the plugin to 0.9.0 so the engine fixes actually reach an instal…
builder-ujaladi Oct 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "https://json.schemastore.org/claude-code-marketplace.json",
"name": "adop-marketplace",
"description": "Agentic Data Operations Platform (ADOP) plugins for Claude Code — turn a natural-language data source description into a tested Bronze→Silver→Gold pipeline with inline compliance controls.",
"owner": {
"name": "AWS Samples",
"url": "https://github.com/aws-samples/sample-Agentic-Ai-Data-Operations"
},
"plugins": [
{
"name": "adop",
"source": "./plugins/claude-code",
"description": "Agentic Data Operations Platform — natural language to a tested Bronze→Silver→Gold data pipeline with inline compliance controls."
}
]
}
9 changes: 7 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ dist/
downloads/
eggs/
.eggs/
lib/
lib64/
/lib/
/lib64/
parts/
sdist/
var/
Expand Down Expand Up @@ -278,3 +278,8 @@ cleanup_*.sh

# Local README preview (generated by /tmp/render_readme.py)
README-preview.html

# `claude plugin eval` writes timestamped run output here — reports, aggregate JSON and
# scaffold temp dirs. Transient artifacts of running the suite, not plugin content.
# Anchored, because an unanchored `results/` once swallowed 27 vendored files.
/plugins/claude-code/evals/results/
2 changes: 1 addition & 1 deletion .mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
},
"pii-detection": {
"command": "uv",
"args": ["run", "--no-project", "--with", "boto3", "--with", "mcp", "--python", "3.13", "mcp-servers/pii-detection-server/server.py"],
"args": ["run", "--no-project", "--with", "boto3", "--with", "fastmcp", "--python", "3.13", "mcp-servers/pii-detection-server/server.py"],
"env": {
"AWS_REGION": "us-east-1",
"AWS_PROFILE": "default"
Expand Down
6 changes: 6 additions & 0 deletions contracts/v1/bronze_spec.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@
"enum": ["full_load", "incremental", "cdc"],
"default": "full_load"
},
"ingest_sequence_column": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]*$",
"description": "Name of a column Bronze STAMPS on every ingested row with the run's logical date, supplying a monotonic ordering across runs that the source itself does not provide. Bronze stays append-only: this ADDS a column, it never updates an existing row, so Bronze immutability holds. Silver then resolves same-primary-key conflicts by taking the highest value, which is the only way to apply an upstream restatement — a claim moving PENDING to PAID, say — when no source column changes on update. Point silver_spec.dedup_order_by at this column. Omit it when the source supplies its own reliable last-updated timestamp and order by that instead.",
"$comment": "Needed because ingestion_mode: cdc was unimplementable on its own: a merge has to know which of two rows is newer, and a source whose update does not touch any column cannot say."
},
"file_pattern": {
"type": "string",
"description": "Glob pattern to match source files (e.g., *.csv)"
Expand Down
54 changes: 44 additions & 10 deletions contracts/v1/dag_spec.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
"title": "DAG Schedule Spec",
"description": "Defines Airflow DAG scheduling, retries, failure handling, and task dependencies.",
"type": "object",
"required": ["dataset_name", "schema_version", "schedule", "tasks"],
"required": [
"dataset_name",
"schema_version",
"schedule",
"tasks"
],
"additionalProperties": false,
"properties": {
"dataset_name": {
Expand All @@ -22,13 +27,19 @@
},
"schedule": {
"type": "object",
"required": ["cron", "timezone"],
"required": [
"cron",
"timezone"
],
"additionalProperties": false,
"properties": {
"cron": {
"type": "string",
"type": [
"string",
"null"
],
"minLength": 9,
"description": "Cron expression (e.g., '0 6 * * *')"
"description": "Cron expression (e.g., '0 6 * * *'), or null for a manual / on-demand DAG. minLength applies only to the string form, so null is accepted. Was string-only, which made schedule_interval=None inexpressible even though it is ordinary Airflow."
},
"timezone": {
"type": "string",
Expand Down Expand Up @@ -81,7 +92,10 @@
"type": "array",
"items": {
"type": "object",
"required": ["task_id", "type"],
"required": [
"task_id",
"type"
],
"additionalProperties": false,
"properties": {
"task_id": {
Expand All @@ -90,15 +104,24 @@
},
"type": {
"type": "string",
"enum": ["glue_job", "quality_check", "sensor", "python_callable", "dummy"]
"enum": [
"glue_job",
"quality_check",
"sensor",
"python_callable",
"dummy"
]
},
"script_path": {
"type": "string",
"description": "Path to the script this task executes"
},
"depends_on": {
"type": "array",
"items": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
"items": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]*$"
},
"default": []
},
"timeout_minutes": {
Expand All @@ -120,7 +143,13 @@
"properties": {
"on_failure_callback": {
"type": "string",
"enum": ["sns_alert", "slack_notify", "pagerduty", "email", "none"],
"enum": [
"sns_alert",
"slack_notify",
"pagerduty",
"email",
"none"
],
"default": "sns_alert"
},
"notification_channel": {
Expand All @@ -143,14 +172,19 @@
},
"critical_tasks": {
"type": "array",
"items": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" },
"items": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]*$"
},
"description": "Tasks that trigger SLA breach alerts"
}
}
},
"tags": {
"type": "array",
"items": { "type": "string" },
"items": {
"type": "string"
},
"default": []
}
}
Expand Down
23 changes: 22 additions & 1 deletion contracts/v1/gold_spec.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@
"type": "string",
"pattern": "^[a-z][a-z0-9_]*$"
},
"publish_via_gate": {
"type": "boolean",
"default": false,
"description": "When true this template writes to {iceberg_table}_staging instead of the real table, leaving publication to the quality gate. iceberg_table stays the real name so semantic.yaml, the LF-Tag grants and gold_spec.source_table keep pointing at it. Requires gate_before_publish on the workload's quality_spec and PROMOTE_TO on the quality task -- without both, the data is staged and never published."
},
"iceberg_partition_spec": {
"type": "array",
"items": { "type": "string" },
Expand All @@ -121,10 +126,21 @@
"columns": {
"type": "array",
"items": { "type": "string" }
},
"atomic": {
"type": "boolean",
"default": false,
"description": "For a `fact` table only: write one row per SOURCE row, straight from the pre-aggregation dataframe, instead of at the spec's `grain`. Use it to publish an atomic fact alongside the aggregate when a consumer needs a dimension that the aggregate grain does not carry — provider-level slicing off a daily plan/claim-type aggregate, for instance, which is otherwise impossible. An atomic fact republishes row-level detail into Gold, so under HIPAA it inherits the source zone's sensitivity and needs its own column-level controls; it is not a cheaper aggregate. Ignored for dimension and flat tables."
},
"business_key": {
"type": "array",
"minItems": 1,
"items": { "type": "string" },
"description": "Natural key identifying one entity in this dimension. Used as the MERGE predicate when the table is written as SCD Type 2. REQUIRED when any dimensions[] attribute whose source_column appears in this table's columns declares scd_type 2: a Type 2 merge must know which rows are successive versions of the same entity, and because dimensions[] names attributes rather than tables there is nothing to infer it from. Every listed column must also appear in columns. Ignored for Type 1 dimensions and for fact/flat tables."
}
}
},
"description": "For star_schema: list of fact + dimension tables"
"description": "For star_schema: list of fact + dimension tables. A dimension table is written as SCD Type 2 when any dimensions[] attribute whose source_column is among its columns declares scd_type 2; otherwise Type 1 (overwrite)."
},
"freshness_sla_hours": {
"type": "integer",
Expand Down Expand Up @@ -160,6 +176,11 @@
},
"default": [],
"description": "Columns derived from aggregated measures (booleans, ratios, masking expressions over Gold dimensions)."
},
"post_aggregation_filter": {
"type": "string",
"minLength": 1,
"description": "Spark SQL predicate applied to the aggregated rows immediately before the write. Rows not satisfying it are dropped, not labelled. This is the only way to suppress a published cell: post_aggregation_columns can add a column but cannot remove a row, so a k-anonymity flag computed there is a boolean sitting next to the disclosed row rather than a suppression. Example for k=11: claim_count >= 11."
}
}
}
Loading
Loading