- Project: https://aftershock.phantombugz.com
- Demo: https://youtu.be/yopSGs_kx5s
- Source: https://github.com/PhantomBugz/aftershock
Aftershock is a DataHub-backed incident-response agent for the Agents That Do Real Work challenge. It is a deterministic, auditable, policy-driven agent loop:
observe DataHub context -> decide from governed metadata and policy
-> act through an exact remediation grant
-> persist receipts back to DataHub
Its agency comes from closing this governed observe/decide/act/persist loop. The listener/API path begins after an authenticated incident trigger; the live judge command invokes the same processor directly for the fixed seeded scenario. Every demonstrated decision is reproducible from DataHub metadata and operator policy.
We use Action Debt as project terminology for operational follow-up created
when an automated system acts on data that is later found to be unreliable.
In the live proof, bad pricing has already issued PO-AFTERSHOCK-001;
Aftershock finds the exposed job in DataHub, cancels that order, prevents the
next issuance, and writes the PO-bound receipt back.
For a critical Aftershock-normalized incident envelope, the workflow:
- calls the official
mcp-server-datahub==0.6.0through FastMCP; - discovers downstream assets with
get_lineage(upstream=false); - fetches entity metadata with
get_entities; - reads the exact structured-property qualified names
aftershock.businessActionandaftershock.remediationWebhook; - checks the target URN, entity type, business action, and endpoint against an operator-controlled exact remediation grant;
- invokes bounded, asynchronous compensating controls and records factual receipts; and
- finds a verified prior incident Document when one exists, then calls
save_documentthrough MCP to create or update the summary and related asset URNs for the next operator or agent.
Aftershock does not rebuild catalog or lineage capabilities. DataHub supplies the downstream context, governed playbook metadata, and durable organizational memory. Live mode never changes to fixture data after a failed MCP call.
For mcp-server-datahub==0.6.0, the adapter passes max_hops=3; in this pinned
server contract that value means unlimited lineage traversal, not a finite hop
limit. Results are paginated and validated fail-closed before controls run.
DataHub incidentInfo MetadataChangeLogEvent
|
custom DataHub Action adapter (not implemented)
|
authenticated normalized envelope
|
FastAPI listener
|
official DataHub MCP server over FastMCP
| | |
get_lineage get_entities save_document
| | |
+---- governed target policy ----+ |
| |
exact remediation grants
|
receipts + DataHub incident record
The current API begins after the authenticated normalized trigger. A production
event integration would translate DataHub's incidentInfo
MetadataChangeLogEvent with a custom DataHub Action, then POST the normalized
contract to Aftershock. That adapter remains future integration work. See the
MetadataChangeLogEvent reference and custom Action guide.
Every target settles into one of five states:
| Status | Meaning |
|---|---|
succeeded |
A success-class response contained the required v1 terminal succeeded contract and a valid external receipt ID. This includes HTTP 202 only when that explicit terminal contract is present. A 408/5xx is honored only when it carries that terminal contract. |
accepted |
The receiver acknowledged work, but no terminal outcome is known. HTTP 202 without a terminal v1 contract, and accepted/pending contracts on ordinary success-class responses, are nonterminal. |
failed |
The request failed before dispatch, was rejected with a 4xx other than 408, encountered a disabled redirect, or returned a valid v1 terminal failure receipt. |
skipped |
The playbook was incomplete, its exact endpoint was denied, or the workflow deadline expired before dispatch. |
outcome_unknown |
Dispatch may have occurred, but a 408/5xx without a valid terminal receipt, transport failure, deadline expiry, or another invalid/missing terminal response left the outcome unproven. |
The success response contract is:
{
"receipt_version": 1,
"status": "succeeded",
"receipt_id": "receiver-generated-stable-id"
}The external receipt ID is shown in the API, dashboard, and DataHub incident
document. Extra response fields are ignored and never establish success. A
plain HTTP 200 is not business-success evidence. An explicit v1 terminal
success/failure receipt is honored on HTTP 408/5xx; without one, those
ambiguous responses remain outcome_unknown.
The API returns completed only when every discovered control is terminal
succeeded and the DataHub write-back succeeds. accepted and
outcome_unknown therefore produce completed_with_issues.
Each dispatched request carries a deterministic Idempotency-Key derived from
the incident, target, and business action. It is a stable retry key, not proof
of exactly-once execution. The engine uses at most eight workers and a
30-second workflow deadline by default. At the deadline, dispatched work is
conservatively outcome_unknown; work not yet dispatched is skipped.
DataHub write-back is also duplicate-resistant for sequential replay. Before saving, Aftershock performs a bounded exact-title search, verifies a stable incident+dataset record key (or the dataset marker on a legacy record), and updates the lexically stable matching Document URN. It creates a new Document only when no verified match exists, and never falls back to creating one after a failed search or update. This is not a claim of globally atomic exactly-once persistence across concurrent processes.
Critical listener sessions require AFTERSHOCK_REMEDIATION_ALLOWLIST_JSON, a
nonempty JSON array of exact, four-field grants. An endpoint alone cannot
authorize a different asset or business action:
$env:AFTERSHOCK_REMEDIATION_ALLOWLIST_JSON = '[{"target_urn":"urn:li:dataJob:(urn:li:dataFlow:(airflow,aftershock_demo,DEV),purchase_order_generator)","entity_type":"DATA_JOB","business_action":"ISSUE_PO","endpoint":"http://127.0.0.1:8765/remediate/cancel_po"}]'Authorization is exact across target_urn, entity_type, business_action,
and endpoint. The endpoint's scheme, host, port, path, and query must also
match. User information and fragments are rejected. Plain HTTP is allowed only
for loopback hosts; nonloopback endpoints require HTTPS. Redirects are
disabled. Query values may participate in authorization but are removed from
logs and persisted receipt endpoints.
Never put credentials in a structured property or URL. DataHub property-write RBAC, document-mutation permissions, receiver authentication, and network egress policy remain operator responsibilities.
The primary submission path uses a real local DataHub OSS deployment, the official DataHub MCP server, a loopback-only stateful receiver, and independent MCP read-back. First follow the live setup guide to start and seed DataHub. Then start the built-in receiver in one PowerShell window:
python src\demo_remediation_receiver.pyIn a second window, select the live MCP context and run the proof gate:
$env:AFTERSHOCK_DATAHUB_MODE = "mcp"
$env:DATAHUB_GMS_URL = "http://127.0.0.1:8080"
Remove-Item Env:DATAHUB_GMS_TOKEN -ErrorAction SilentlyContinue
Remove-Item Env:DATAHUB_MCP_URL -ErrorAction SilentlyContinue
Remove-Item Env:DATAHUB_MCP_TOKEN -ErrorAction SilentlyContinue
python src\live_demo.pylive_demo.py refuses fixture mode. It resets the receiver and displays the
seeded order PO-AFTERSHOCK-001 as issued. It then executes the
OBSERVE/DECIDE/ACT/PERSIST loop, requires a PO-bound terminal v1 success
receipt, confirms the order is canceled and further issuance is disabled,
and requires the DataHub write-back to succeed. It then proves persistence
through three independent MCP reads:
search_documentsfinds the exact returned document URN and title;grep_documentsfinds the incident ID and external receipt ID in content;get_entitiesfinds the saved document in both the dataset and DataJobrelatedDocumentsbacklinks.
On August 4, 2026, this path passed against local DataHub OSS Quickstart v1.6.0:
the seeded order changed from issued to canceled exactly once, the same
PO-bound receipt was persisted to DataHub, and all read-back gates passed. The
credential-free evidence is captured in
examples/live_demo_proof.txt.
Requirements: Python 3.12 and PowerShell.
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
python -m pytest -q
python src\demo_dashboard.pyThe dashboard is unmistakably labeled OFFLINE FIXTURE MODE. It uses local,
deterministic lineage, exact in-memory remediation grants, httpx.MockTransport
responses containing valid v1 terminal receipts, and an in-memory write-back
recorder. It does not represent a live DataHub run.
The protocol tests use an in-process FastMCP server and genuine MCP/JSON-RPC exchanges. They verify tool arguments, parsing, failure behavior, and write-back contracts, but they are not evidence of persistence to a live DataHub instance.
This command exercises the real API and policy configuration, but the fixture endpoints are reserved example hosts and normally do not produce successful receipts. Use the dashboard for a deterministic presentation.
$env:AFTERSHOCK_DATAHUB_MODE = "fixture"
$env:AFTERSHOCK_WEBHOOK_TOKEN = "replace-with-a-long-random-secret"
$env:AFTERSHOCK_REMEDIATION_ALLOWLIST_JSON = '[{"target_urn":"urn:li:dataJob:(urn:li:dataFlow:(airflow,aftershock_demo,PROD),purchase_order_generator)","entity_type":"DATA_JOB","business_action":"ISSUE_PO","endpoint":"https://api.internal.example/remediate/cancel_po"},{"target_urn":"urn:li:mlModel:(urn:li:dataPlatform:sagemaker,dynamic_pricing_model,PROD)","entity_type":"ML_MODEL","business_action":"ADJUST_PRICE","endpoint":"https://api.internal.example/remediate/revert_pricing"}]'
python -m uvicorn lineage_listener:app --app-dir src --host 127.0.0.1 --port 8000From a second PowerShell window:
$headers = @{ Authorization = "Bearer replace-with-a-long-random-secret" }
$body = @{
incident_id = "INC-DEMO-001"
dataset_urn = "urn:li:dataset:(urn:li:dataPlatform:postgres,inventory_pricing,PROD)"
severity = "CRITICAL"
} | ConvertTo-Json
Invoke-RestMethod `
-Method Post `
-Uri "http://127.0.0.1:8000/webhook/datahub" `
-Headers $headers `
-ContentType "application/json" `
-Body $bodyCritical envelopes require Authorization: Bearer <AFTERSHOCK_WEBHOOK_TOKEN>.
Invalid input returns 422; missing or invalid authorization returns 401;
missing authentication/remediation configuration or unavailable DataHub
processing returns a fixed, secret-safe 503. Noncritical envelopes return
ignored before opening a DataHub context or constructing remediation grants.
Fixture metadata is explicitly synthetic and uses PROD URNs. The separate
live bootstrap uses collision-checked, namespaced DEV assets. Follow the
live setup guide for mandatory target confirmation, collision
handling, receiver requirements, and exact commands.
src/datahub_context.py— explicit fixture and MCP context adapterssrc/blast_radius_mapper.py— lineage-to-structured-playbook mappingsrc/compensating_action_engine.py— governed execution and receiptssrc/incident_processor.py— read, act, andsave_documentorchestrationsrc/lineage_listener.py— authenticated normalized-envelope APIsrc/demo_dashboard.py— receipt-driven offline presentationsrc/demo_contract.py— exact seeded live-demo identities and endpointsrc/demo_remediation_receiver.py— loopback-only observable demo controlsrc/live_demo.py— live MCP workflow and three-read persistence proofconfig/andscripts/— safe live metadata bootstraptests/— unit, MCP protocol, API, dashboard, and opt-in live testsexamples/— captured outputs labeled by execution modedocs/submission-checklist.md— completed technical and external release gates
The MVP operates at the system-exposure and compensating-control level. A lineage edge shows downstream exposure; it does not prove which individual records a system read or which external actions resulted. The MVP therefore does not claim row-level causality or individual-action recovery.
The proposed Action-Provenance Ledger RFC describes a future path to action IDs, incident windows, and more selective controls. It is a project proposal, not an upstream contribution.
The MCP server, FastMCP, and DataHub SDK integration dependencies are pinned.
Offline tests and demo inputs are deterministic. On August 4, 2026, the offline
suite passed 309 tests with the one opt-in live test skipped as expected. The
same live test then ran explicitly against local DataHub OSS Quickstart v1.6.0
and passed (1 passed). The final live demonstration also proved the
purchase-order transition from issued to canceled, canonical PO-bound
receipt, MCP save_document, searchable content, and both related-asset
backlinks. A future skipped live test still must not be presented as a new
successful live result; use the dated
proof transcript as the captured evidence.
On August 5, 2026, replay hardening raised the current suite to 320 passed, 1 skipped. Two consecutive real MCP demonstrations then updated the same
canonical Document URN and passed all read-back gates; the five historical
same-title development records did not increase. See the dated
replay-hardening proof. Historical
records were preserved rather than destructively removed.
Useful DataHub references:
Standard AI coding assistants were used during development to help scaffold, test, review, and document the project. The project concept, acceptance criteria, architecture decisions, and submission decisions remain under human direction and review.
Licensed under the Apache License 2.0. The public repository contains the reviewed implementation, setup guide, reproducible examples, captured live proof transcript, and DataHub screenshot. GitHub's Apache-2.0 license detection was verified on August 4, 2026. The public project URL and 2:48 demonstration video were published and verified anonymously on August 5, 2026. The Devpost entry was submitted to Build with DataHub: The Agent Hackathon in the Agents That Do Real Work category and verified anonymously on August 5, 2026; see the completed submission checklist.
