Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
138 commits
Select commit Hold shift + click to select a range
4a4e403
Routing + in-engine agentic conversion (route -> alter -> fill)
matthewmoorcroft Sep 16, 2026
74c5eb0
Merge stack/agentic-component into routing-agentic
matthewmoorcroft Sep 17, 2026
cd843d3
Add flowx-route skill and five-step migrate flow; register routing sk…
matthewmoorcroft Sep 17, 2026
a8d9921
Fix re-review findings: Airflow merge path, merge behavior, migrate o…
matthewmoorcroft Sep 17, 2026
c37d830
Fix merge status claim: merge sets no status field
matthewmoorcroft Sep 17, 2026
3c74b27
Scope routing/agentic-conversion as ADF-only; fix Airflow control-edg…
matthewmoorcroft Sep 17, 2026
05e2570
Routing/combine: source-tag check, idempotent combine, route audit, G…
matthewmoorcroft Sep 18, 2026
b09c750
Merge stack/agentic-component (FIX 1, 7, 4, 8a) into stack/routing-ag…
matthewmoorcroft Sep 18, 2026
cbcd215
Combine idempotency: key on recorded report state + fingerprint, not …
matthewmoorcroft Sep 18, 2026
848e89b
Merge stack/agentic-component (FIX 1 + 8a re-fixes) into stack/routin…
matthewmoorcroft Sep 18, 2026
3529ab1
Merge stack/agentic-component (structured GA/Preview release_state) i…
matthewmoorcroft Sep 18, 2026
c061f5d
Routing: surface recommended-pattern release_state as a neutral discl…
matthewmoorcroft Sep 18, 2026
72869fa
Merge stack/agentic-component (neutral release_state disclosure) into…
matthewmoorcroft Sep 18, 2026
bd81522
Merge stack/agentic-component (drop residual warning wording) into st…
matthewmoorcroft Sep 18, 2026
b6297ff
Merge stack/agentic-component (soften doNotSuggest; drop hardcoded re…
matthewmoorcroft Sep 18, 2026
1643c41
Refresh AGENTS.md module map for the sources/ layout
matthewmoorcroft Sep 21, 2026
9182cac
Make CLAUDE.md a symlink to AGENTS.md
matthewmoorcroft Sep 21, 2026
d113cc0
Add self-governance note to AGENTS.md
matthewmoorcroft Sep 21, 2026
c2fb754
Refuse agentic routing decisions for non-ADF inventories
matthewmoorcroft Oct 5, 2026
5e0a2ba
Fail package closed on a stale routing plan and hash the route audit
matthewmoorcroft Oct 5, 2026
bcba3ca
Describe models/discovery.py as the source-neutral discovery graph co…
matthewmoorcroft Oct 5, 2026
fb57536
Merge stack/agentic-component (source_insights.json, motifs in source…
matthewmoorcroft Oct 5, 2026
4a79c09
Build routing test inventories with motifs on the graphs
matthewmoorcroft Oct 5, 2026
235e527
Make the typed ConversionPlan (schema 2) the library's plan API
matthewmoorcroft Oct 5, 2026
bd083a8
Merge stack/agentic-component (enrich wording, #84 validated head) in…
matthewmoorcroft Oct 5, 2026
b839e96
Bring docs, AGENTS.md and the migrate and route skills in line with t…
matthewmoorcroft Oct 5, 2026
25c26ea
Merge stack/agentic-component (#96 validated head b508ecc) into stack…
matthewmoorcroft Oct 6, 2026
1e7cbe7
no-mistakes(review): Replace routing markers with a per-component rou…
matthewmoorcroft Oct 7, 2026
15d6924
no-mistakes(review): Enforce one fill per component; refresh stamped …
matthewmoorcroft Oct 7, 2026
d518cde
no-mistakes(review): Detect name-colliding combines via routed gaps; …
matthewmoorcroft Oct 7, 2026
fcf5a60
no-mistakes(review): Fill routed-agentic components only by combine; …
matthewmoorcroft Oct 7, 2026
a37c0ca
Implement replay model for routing: immutable baseline, pure rebuild,…
matthewmoorcroft Oct 7, 2026
44cd53c
Fix adapter route logic to remove reroute_conflict refusal
matthewmoorcroft Oct 7, 2026
0846aa1
Complete replay model implementation: baseline verification, audit, a…
matthewmoorcroft Oct 7, 2026
af2205d
Fix apply_combine_fill to handle same hash idempotently and validate …
matthewmoorcroft Oct 7, 2026
0fcec05
Add unit tests for combine idempotency and validation
matthewmoorcroft Oct 7, 2026
2c42991
Document the replay model: routing, combine, and preflight behavior
matthewmoorcroft Oct 7, 2026
832fa0a
Check the route audit's per-component and baseline-gaps fields
matthewmoorcroft Oct 7, 2026
1c772db
no-mistakes(review): Restore baseline on switch-back; verify combines…
matthewmoorcroft Oct 7, 2026
8ef71c2
no-mistakes(review): Check configured reports against live record; ti…
matthewmoorcroft Oct 7, 2026
7cc139f
no-mistakes(document): Document route skill, MCP routing commands and…
matthewmoorcroft Oct 7, 2026
e9cf7c6
Merge stack/agentic-component (#96 head 839b2c6, carrying #94 and #95…
matthewmoorcroft Oct 8, 2026
9221edc
Route into the plan, accept groupings, package agentic outputs only
matthewmoorcroft Oct 9, 2026
aafb337
no-mistakes(review): Fix routing review findings and drop unrequested…
matthewmoorcroft Oct 9, 2026
3abd8b2
no-mistakes(review): Derive grouping ids from members; fix workflow, …
matthewmoorcroft Oct 9, 2026
2f88d9e
no-mistakes(review): Say stale plan copies need a fresh route, not en…
matthewmoorcroft Oct 9, 2026
c2dc0e6
no-mistakes(document): Fix enrich step order and package routing poin…
matthewmoorcroft Oct 9, 2026
a313dc3
no-mistakes(review): Validate edited plans as written; report dropped…
matthewmoorcroft Oct 9, 2026
11785e9
no-mistakes(review): Document dropped groupings resetting components …
matthewmoorcroft Oct 9, 2026
bac85dc
Merge stack/agentic-component (#96 head 07eae42) into stack/routing-a…
matthewmoorcroft Oct 9, 2026
517af7c
Drop convert gaps nested inside a routed container
matthewmoorcroft Oct 9, 2026
9b8b9ae
Refuse a recorded plan with malformed nested fields
matthewmoorcroft Oct 9, 2026
3244db6
no-mistakes(review): Clear stale gaps on re-convert; walk Until place…
matthewmoorcroft Oct 9, 2026
3a5571d
no-mistakes(document): Note malformed plan findings in ConversionPlan…
matthewmoorcroft Oct 9, 2026
d26fcb0
Let a filled unit own the gaps of its motifs and inventory-only activ…
matthewmoorcroft Oct 13, 2026
d7497e6
no-mistakes(review): Drop shared inventory-only gaps across filled ag…
matthewmoorcroft Oct 13, 2026
2f5579a
no-mistakes(review): Document filled-unit ownership of convert gaps i…
matthewmoorcroft Oct 13, 2026
cde5de8
no-mistakes(document): Note inventory gap ownership in apply_plan_to_…
matthewmoorcroft Oct 13, 2026
8bfee4b
Bump flowx to 0.2.0 and add its changelog entry
matthewmoorcroft Oct 13, 2026
f5abf26
no-mistakes(review): Reword CHANGELOG 0.2.0 agentic component entry
matthewmoorcroft Oct 13, 2026
e4b740b
Send hosted MCP migrations through enrich and route
matthewmoorcroft Oct 13, 2026
774c04f
no-mistakes(review): Clarify hosted MCP source inputs for discover an…
matthewmoorcroft Oct 13, 2026
b8ac29b
no-mistakes(review): Keep enrich in hosted Airflow flow; skip only ro…
matthewmoorcroft Oct 13, 2026
ae31bec
no-mistakes(review): Drop ADF-only qualifier from migrate step-by-ste…
matthewmoorcroft Oct 13, 2026
deec92b
no-mistakes(review): Say enrich runs for every source in skill scope …
matthewmoorcroft Oct 13, 2026
b29851c
no-mistakes(document): Add enrich and route to guide's migrate phases
matthewmoorcroft Oct 13, 2026
5e61007
Ask migrate inputs per step and probe SQL Server ingestion in route
matthewmoorcroft Oct 14, 2026
a2cddca
no-mistakes(review): Skip route and fill for deterministic-only migra…
matthewmoorcroft Oct 14, 2026
a045049
no-mistakes(review): Detect SQL Server by activity source type in skills
matthewmoorcroft Oct 14, 2026
22c68e9
no-mistakes(test): Clear stale bundle resources before package rewrit…
matthewmoorcroft Oct 14, 2026
54940df
no-mistakes(document): Note package clears stale resources YAML each run
matthewmoorcroft Oct 14, 2026
6e89fb8
Ask open questions at enrich and qualify target patterns at route
matthewmoorcroft Oct 14, 2026
5c81f30
no-mistakes(review): Flag database sources in enrich and identify the…
matthewmoorcroft Oct 14, 2026
9b2ecb7
no-mistakes(review): Restore uv.lock to public PyPI URLs
matthewmoorcroft Oct 14, 2026
f8f8150
no-mistakes(document): Note enrich questions and route limit checks i…
matthewmoorcroft Oct 14, 2026
dcbc866
no-mistakes(review): Align route M2 suggestion order with checks table
matthewmoorcroft Oct 14, 2026
39cb989
no-mistakes(review): Treat C8 as disclosed risk in route suggestion o…
matthewmoorcroft Oct 14, 2026
c950c2b
no-mistakes(review): Count gateways in route C2, C6 and C7 checks
matthewmoorcroft Oct 14, 2026
420eb4b
no-mistakes(review): Rule out gateway-mode M1 when C6 slots run out
matthewmoorcroft Oct 14, 2026
1fc3732
Redesign the routing review page in the Databricks style
matthewmoorcroft Oct 14, 2026
1d9087f
Refuse a grouping accepted value that is not a boolean
matthewmoorcroft Oct 14, 2026
4b386bd
Refuse a fill whose pipeline name is not a non-empty string
matthewmoorcroft Oct 14, 2026
ccef873
Archive an earlier run's outputs when discover starts afresh
matthewmoorcroft Oct 14, 2026
4b01e0e
no-mistakes(review): Deliver the current bundle first and cap the arc…
matthewmoorcroft Oct 14, 2026
c6247f0
no-mistakes(document): Document the re-run archive in changelog, enri…
matthewmoorcroft Oct 14, 2026
e8592e4
Refuse a fill whose pipeline has no tasks list or is marked excluded
matthewmoorcroft Oct 14, 2026
63ba643
Refuse insights written for a different inventory
matthewmoorcroft Oct 14, 2026
8c36944
no-mistakes(review): Refuse non-object authored tasks; reword insight…
matthewmoorcroft Oct 14, 2026
62faf9c
no-mistakes(document): Document fill-agentic buildable checks and ins…
matthewmoorcroft Oct 14, 2026
0e495a8
Refuse unknown plan keys on read and read lineage edges fail closed
matthewmoorcroft Oct 18, 2026
41d4cfa
Check the saved baseline and hash every stored field before a rebuild
matthewmoorcroft Oct 18, 2026
fb099d9
Say in the route skill what package now refuses in the plan and the s…
matthewmoorcroft Oct 18, 2026
a67bfba
Move resource files package no longer writes into the archive
matthewmoorcroft Oct 18, 2026
05f67e8
Archive the bundle folders a later package no longer writes
matthewmoorcroft Oct 18, 2026
4588933
Merge #96's final head ca3d7c7 into stack/routing-agentic
matthewmoorcroft Oct 18, 2026
8817014
no-mistakes(review): Keep new src/resources bundle folders when widen…
matthewmoorcroft Oct 18, 2026
75117dd
no-mistakes(review): Archive recorded stale bundle folders before wri…
matthewmoorcroft Oct 18, 2026
d518d68
no-mistakes(document): Fix archive docstring and rewrap package/route…
matthewmoorcroft Oct 19, 2026
b1db89f
Take filled convert gaps out of gaps.json on the merge and on route's…
matthewmoorcroft Oct 20, 2026
867deb3
Reserve authored names only for the outputs the rebuild applies
matthewmoorcroft Oct 20, 2026
ff554d9
Write each carried-forward row's current component id back onto it
matthewmoorcroft Oct 20, 2026
ab84fc3
Report a control edge whose source is not a pipeline instead of skipp…
matthewmoorcroft Oct 20, 2026
d256374
Make the route skill's Private Preview rule match enrich and the code
matthewmoorcroft Oct 20, 2026
ea070d9
Drop the reserved per-node assignments until Phase 2 routes per node
matthewmoorcroft Oct 20, 2026
4b387fa
Read the agentic pipelines from the routing units
matthewmoorcroft Oct 20, 2026
3bb0475
Tell a decided but unapplied unit to re-run route on the review page
matthewmoorcroft Oct 20, 2026
f4ad628
Test nested gap removal for ForEach and Switch as well as If and Until
matthewmoorcroft Oct 20, 2026
9d8ef25
Read gaps.json before the merge writes anything, and skip it when unr…
matthewmoorcroft Oct 20, 2026
40eba35
Fix the three gaps the cross-review found in the round-three fixes
matthewmoorcroft Oct 20, 2026
dbb0c81
Merge #96's round-three head 3406913 into stack/routing-agentic
matthewmoorcroft Oct 20, 2026
bf07b01
no-mistakes(review): Show accepted groupings with pending components …
matthewmoorcroft Oct 20, 2026
3fe19e0
Merge #96's ADF export-field fix (a973940) into stack/routing-agentic
matthewmoorcroft Oct 21, 2026
41016bc
Fail MCP route when the plan or review page is cut from the inline bu…
matthewmoorcroft Oct 26, 2026
160760a
Refuse to package an unrouted report while a gap fill is stored
matthewmoorcroft Oct 26, 2026
15f17aa
Fail MCP route when a successful route leaves the plan or page missing
matthewmoorcroft Oct 26, 2026
cc41c9e
Say the gap-fill refusal applies only with a plan recorded
matthewmoorcroft Oct 26, 2026
b3ad1bd
Copy route's plan and page before checking them, and say when ok is f…
matthewmoorcroft Oct 26, 2026
db066bc
Hold one route lock across route, fill-agentic and in-place merges
matthewmoorcroft Oct 26, 2026
f63c72e
Say exactly why MCP route could not deliver its plan or page
matthewmoorcroft Oct 26, 2026
fb7c76e
Refuse unknown top-level keys in the agent's conversion output store
matthewmoorcroft Oct 26, 2026
fd2c3ba
Read route's inventory pipelines through enrich's guard
matthewmoorcroft Oct 26, 2026
43c3312
Check route's plan and page before delivering either
matthewmoorcroft Oct 26, 2026
cd4aecf
Cover every write of a live report with the route lock
matthewmoorcroft Oct 26, 2026
456dc19
Require both keys in the agent's conversion output store
matthewmoorcroft Oct 26, 2026
b50d373
Say a failed route's inline bundle carries only text files
matthewmoorcroft Oct 26, 2026
2872c51
Refuse an inventory route cannot read the way discover writes it
matthewmoorcroft Oct 26, 2026
ed6e431
Read a malformed insights list as no suggestion instead of crashing
matthewmoorcroft Oct 26, 2026
7cc0147
Say to re-run the refused fill or merge after a stale route lock
matthewmoorcroft Oct 26, 2026
9dc2e3a
Require each inventory pipeline's name and activities before routing
matthewmoorcroft Oct 26, 2026
07a21ed
Require a motif's member names, and check record_plan's arguments first
matthewmoorcroft Oct 26, 2026
2bbfaa8
Require a motif id, and read record_plan's plan before any file
matthewmoorcroft Oct 26, 2026
dda3bce
no-mistakes(review): Refuse malformed inventory and insights in fill …
matthewmoorcroft Oct 26, 2026
2c473ee
no-mistakes(document): Document route lock refusals for merges and fills
matthewmoorcroft Oct 26, 2026
6fd0c51
no-mistakes(document): Document how merge_agentic reports a held rout…
matthewmoorcroft Oct 26, 2026
5edec1c
Merge #96's Greg-standard fixes (cb7f0d2) into stack/routing-agentic
matthewmoorcroft Oct 26, 2026
6bc639e
Remove the route lock on a failed token write only while it is ours
matthewmoorcroft Oct 26, 2026
387a85b
Read the platform limits live instead of from a stored copy
matthewmoorcroft Oct 28, 2026
1ab810e
no-mistakes(document): Note the failed lock write case in route skill
matthewmoorcroft Oct 28, 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
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"name": "flowx",
"source": "./",
"description": "Translate data pipelines to Databricks Lakeflow Jobs via Declarative Automation Bundles. Deterministic translation for known activity types with agentic fallback.",
"version": "0.1.0",
"version": "0.2.0",
"license": "MIT",
"keywords": ["adf", "databricks", "migration", "dabs", "lakeflow", "orchestration", "data-pipelines"]
}
Expand Down
3 changes: 2 additions & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "flowx",
"version": "0.1.0",
"version": "0.2.0",
"description": "Translate Azure Data Factory pipelines to Databricks Lakeflow Jobs via Declarative Automation Bundles. Deterministic translation for known activity types with agentic fallback.",
"author": {
"name": "Greg Hansen",
Expand All @@ -12,6 +12,7 @@
"./skills/flowx-setup",
"./skills/flowx-discover",
"./skills/flowx-enrich",
"./skills/flowx-route",
"./skills/flowx-convert",
"./skills/flowx-package",
"./skills/flowx-migrate"
Expand Down
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ intermediates under `.work/` (pruned by `package`).
| `reporting/coverage.py` | Builds per-pipeline coverage rows from `metadata/` |
| `reporting/results.py` | Writes per-run coverage to a UC table (run_id/run_date/run_by) via the SDK |
| `reporting/dashboard.py` | Installs + publishes an AI/BI coverage dashboard over the results table |
| `reporting/routing_review.py` | Renders `metadata/routing_review.html`, the standard eight-section routing review page, from `routing_review_template.html` (stdlib only, no timestamps) |
| `routing.py` | Groups pipelines into connected components over control lineage; recommends deterministic/agentic per component (both options) and suggests groupings from the insights; writes the recommendation into `metadata/conversion_plan.json` with decisions pending and records the user's edits (additive; convert untouched). Agentic decisions are ADF-only; also the reader-side check that `agentic_insights.json` agrees with the inventory |
| `route_agentic.py` | Applies a routing decision after convert: rebuilds the report from the never-rewritten baseline (`.work/route_baseline/`), the plan, and the agent's output in `metadata/agentic_conversion.json` (per-unit pipelines + fills of convert's own gaps); `fill-agentic` is the only fill for routed-agentic units |
| `models/conversion_plan.py` | Typed `ConversionPlan` (schema 3): the library's load/validate/record API for `conversion_plan.json`, one decision per component (pending until made), suggested groupings, the routing conversation, bound to the inventory, `source_graphs.json` and `agentic_insights.json` hashes; package fails closed on a mismatch, a pending decision, or an unfilled agentic unit |

## Activity Types

Expand Down
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@ All notable changes to flowx will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [0.2.0]

### Added
- Enrich step: the agent adds insights on top of the discover inventory, and asks a few open
questions about the estate that the code can't answer
- Route step: decides deterministic or agentic conversion per connected component, records the
decision in the conversion plan, and renders a routing review page; before suggesting an ingestion
pattern it checks it against the current platform limits, read live from the docs, as enrich does for
every pattern it recommends
- Fill-agentic step: applies the agent's conversion output to routed-agentic units
- Agentic component: for an activity the typed engine cannot express, the agent can author Databricks
tasks, files, pipeline resources and job environments, which package writes into the bundle while
flowx keeps the task name, dependencies and run policy

### Changed
- Re-running discover over an output folder that already holds a run now moves that run's outputs
into `metadata/archive/<UTC time>/`, with an `archive.json` of what moved, instead of deleting them;
re-running package does the same for any resource file and bundle folder it no longer writes, keeping
the list of bundle folders it wrote in `metadata/packaged_bundles.json`

## [0.1.0]

### Added
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ Or run individual phases:
/flowx:flowx-discover # Parse the source (ADF JSON / Airflow DAGs), produce inventory + complexity report
/flowx:flowx-enrich # Validate and record agent-authored insights on the inventory
/flowx:flowx-convert # Deterministic + agentic translation
/flowx:flowx-route # Decide deterministic vs. agentic per pipeline group and fill the agentic groups (ADF)
/flowx:flowx-package # Generate DABs project
```

Expand Down Expand Up @@ -262,6 +263,11 @@ flowx_output/
agentic_insights.json # enrich: validated agent-authored insights, rebuilt into inventory.json
profile_report.csv # discover: per-pipeline complexity report
<pipeline>.arm.json # discover: verbatim original ADF/ARM source
conversion_plan.json # route: the recommendation, suggested groupings and the user's per-component decisions
routing_review.html # route: the standard review page drawn from the plan
agentic_conversion.json # fill-agentic (ADF): the agent's conversion output per routed-agentic unit, re-applied by every route
route_audit.json # package: routing decisions, outcomes, history, conversation and hashes, written when a plan is recorded
packaged_bundles.json # package: the bundle folders it wrote, so the next package archives the ones it no longer writes
configuration.json # modify: collected configuration answers
.work/ # transient intermediates (translation report, IR, gaps.json); pruned by package
```
Expand Down
4 changes: 3 additions & 1 deletion app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ operation; `parameters` is its keyword-argument dict.
| `merge_agentic` | `adapter convert --merge-agentic` | Merge ADF agent-produced results into the report |
| `resolve_agentic` | `adapter resolve-agentic` | Prepare, stage, and apply reviewed Airflow leaf-gap resolutions |
| `enrich` | `adapter enrich` | Return `inventory.json` (`prepare`), then validate and record agent-authored insights (`apply`) |
| `route` | `adapter route` | Write the recommendation into `conversion_plan.json` and the review page; apply the plan once decided |
| `fill_agentic` | `adapter fill-agentic` | Fill a routed-agentic unit with agent-authored pipelines (ADF) |
| `inspect` | `adapter inspect` | Surface pending translation options |
| `apply_answers` | `adapter modify` | Apply answers → stamped IR |
| `materialize_lookup` | `adapter materialize-lookup` | CSV → lookup-values JSON |
| `workspace_paths` | `adapter workspace-paths` | Detect workspace paths / hosts |
| `package` | `adapter package` | Emit the deployable DAB bundle |
| `migrate` | discover→convert→package | Full non-interactive migration |
| `migrate` | discover→convert→package | Deterministic-only migration in one call (never runs `enrich` or `route`; for a migration that enriches (any source) or routes (ADF), run the phases one at a time, passing the same source to `discover` and `convert`) |
| `record_results` | `adapter record-results` | Write coverage to a UC table |
| `install_dashboard` | `adapter install-dashboard` | Publish the coverage dashboard |

Expand Down
2 changes: 1 addition & 1 deletion docs/content/docs/architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ See [Installation](/flowx/docs/installation#running-flowx-as-an-mcp-server) for
<Callout type="info" title="Inputs and outputs on a hosted app">
A Databricks App can't read the user's workspace / UC Volume files (`/Volumes/...` is **not** auto-mounted). Two ways to get data in/out of the `flowx` tool:

- **Small jobs — inline.** `command="discover"`/`"migrate"` accept `adf_definitions` (a mapping of relative path → ARM JSON, Git-export layout), supplied by the agent and materialized to a temp dir; `package`/`migrate` return the DAB inline as `bundle = {"files": {relpath: text, …}}`. Inline data flows through the agent's context, so it's capped (~5 MB in).
- **Small jobs — inline.** `command="discover"`/`"convert"`/`"migrate"` accept `adf_definitions` (a mapping of relative path → ARM JSON, Git-export layout), supplied by the agent and materialized to a temp dir; pass the same source to `discover` and `convert`; `package`/`migrate` return the DAB inline as `bundle = {"files": {relpath: text, …}}`. Inline data flows through the agent's context, so it's capped (~5 MB in).
- **Large factories — by reference (recommended).** Point the server at the source: `adf_volume_path` (a UC Volume read via the SDK Files API) or `adf_workspace_path` (a `/Workspace` directory — e.g. an ADF Git folder — read via the SDK Workspace API). Write the DAB to `output_volume_path` (UC Volume, SDK Files API) or `output_workspace_path` (`/Workspace` directory, SDK Workspace API with `ImportFormat.RAW`), returned as `bundle_uploaded`. The bytes bypass the agent entirely, so it scales to thousands of pipelines; grant the app's service principal read on the source and write on the output target.

Locally hosted, ordinary `adf_source_path` / `output_dir` paths and mounted volumes work as-is.
Expand Down
11 changes: 9 additions & 2 deletions docs/content/docs/guide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ flowx migrate pipelines in `/Volumes/main/default/adf_export`. Save output in `.
Your agent will use flowx's `migrate` skill to run an end-to-end migration consisting of several phases:

1. `discover` parses JSON files, builds an inventory, assigns a translation strategy for each resource, and creates a complexity report.
2. `convert` converts each activity to an intermediate representation. The agent will ask for confirmation before running any LLM-based translation.
3. `package` creates a [Declarative Automation Bundle](https://docs.databricks.com/aws/en/dev-tools/bundles/resources) with job configuration, code, and setup scripts (e.g. to create Databricks Secret Scopes or Unity Catalog connections).
2. `enrich` (default) has the agent author insights over the inventory and records them.
3. `convert` converts each activity to an intermediate representation. The agent will ask for confirmation before running any LLM-based translation.
4. `route` (ADF) recommends deterministic or agentic conversion per group of connected pipelines, shows the plan on a review page, and records your decisions; the agent then fills the groups you route agentic.
5. `package` creates a [Declarative Automation Bundle](https://docs.databricks.com/aws/en/dev-tools/bundles/resources) with job configuration, code, and setup scripts (e.g. to create Databricks Secret Scopes or Unity Catalog connections).

<Callout type="info" title="Running migration step-by-step">
To run a single step, invoke its skill directly (e.g. `@flowx-discover`) or ask your agent to run a single step.
Expand All @@ -80,6 +82,11 @@ flowx_output/
│ ├── inventory.json # discover: activity inventory
│ ├── profile_report.csv # profile: per-pipeline complexity report
│ ├── <pipeline>.arm.json # discover: verbatim original ADF/ARM pipeline source
│ ├── conversion_plan.json # route: the recommendation and the user's per-component decisions
│ ├── routing_review.html # route: the standard review page drawn from the plan
│ ├── agentic_conversion.json # fill-agentic: the agent's conversion output, re-applied by every route
│ ├── route_audit.json # package: what each routing unit was converted to, and the routing conversation
│ ├── packaged_bundles.json # package: the bundle folders it wrote, so the next package archives stale ones
│ └── configuration.json # modify: the collected configuration answers
└── .work/ # transient intermediates (translation report, IR, gaps.json); pruned by prepare
```
Expand Down
2 changes: 1 addition & 1 deletion docs/content/docs/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ flowx is distributed through a Claude Code marketplace. It can be installed as a
You can also copy the skill folders straight into your local skills directory:

```shell
cp -R skills/{flowx-setup,flowx-discover,flowx-enrich,flowx-convert,flowx-package,flowx-migrate} ~/.claude/skills/
cp -R skills/{flowx-setup,flowx-discover,flowx-enrich,flowx-route,flowx-convert,flowx-package,flowx-migrate} ~/.claude/skills/
```
</Tab>
</Tabs>
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "databricks-flowx"
version = "0.1.0"
version = "0.2.0"
description = "ADF to Databricks Lakeflow Jobs translator via Declarative Automation Bundles"
readme = "README.md"
requires-python = ">=3.12"
Expand Down
6 changes: 4 additions & 2 deletions skills/flowx-convert/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ agentic-gap flow with just-in-time configuration. Airflow converts deterministic
Run the **`setup`** skill first if you haven't.

- **MCP tool (Genie Code, or local stdio):** call the single **`flowx`** tool with
`command="convert"` and `parameters` including `"source": "<source>"` and `"output_dir": "<dir>"`.
`command="convert"` and `parameters` including `"source": "<source>"`, `"output_dir": "<dir>"` and
the same source key discover read (`adf_definitions`, `adf_volume_path`, `adf_workspace_path` or
`airflow_source_path`): convert reads the source again.

- **venv CLI (local):**

Expand Down Expand Up @@ -70,7 +72,7 @@ across ADF and Airflow.
`show_when` condition). Walk it locally; ask an option only when its `show_when` is satisfied.
- `modify <report> --output-dir <dir> --answer OPTION_ID=VALUE ...` — validate and apply collected
answers, writing `.work/translation_report.stamped.json` + `metadata/configuration.json`.
- `merge_agentic --report <report> --agentic-results <dir>` — **ADF only**. Fold agent-produced per-activity translations into an ADF report. Airflow's legacy name-based merge is disabled.
- `merge_agentic --report <report> --agentic-results <dir>` — **ADF only**. Fold agent-produced per-activity translations into an ADF report, filling convert's own agentic gaps. It refuses, writing nothing, any result landing in a pipeline the routing record routes agentic (fill those with `fill-agentic`). After routing, a merge written in place into the live `.work/translation_report.json` is also stored as a gap fill in `metadata/agentic_conversion.json`, so the next rebuild re-applies it on top of route's unchanged deterministic baseline; a merge written to a separate `--output` copy stores nothing, so a re-route does not keep it. Airflow's legacy name-based merge is disabled.

## Output artifacts (shared, transient under `<output_dir>/.work/`)

Expand Down
8 changes: 7 additions & 1 deletion skills/flowx-convert/sources/adf.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,13 @@ Where the fragment leaves a value out, flowx adds only the plumbing the task nee
```

Placeholders are replaced in place, status → `translated`. Exits non-zero if any result can't be
matched. Add `--output <path>` to write a copy instead of overwriting.
matched. Add `--output <path>` to write a copy instead of overwriting. An in-place merge into
`.work/translation_report.json` also takes the merged activities' gaps out of `.work/gaps.json`. After
routing, only such an in-place merge is also stored as a gap fill in `metadata/agentic_conversion.json`
(so a re-route keeps it, while route's saved deterministic baseline stays as convert wrote it); a merge
written to an `--output` copy stores nothing and leaves `gaps.json` alone. A merge into the live report
refuses, writing nothing, while a route, fill-agentic or another merge is writing to the same output
folder, so run merges one at a time (see "One at a time per output folder" in the `flowx-route` skill).

## Step 6.1 — Just-in-time translation configuration

Expand Down
5 changes: 5 additions & 0 deletions skills/flowx-discover/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ All under the shared `<output_dir>/metadata/` folder:
| `metadata/source_graphs.json` | (ADF) The saved source graphs (activities, lineage and detected motifs), versioned and content-hashed; the inventory is built from it and records its hash as `source_graphs_sha256` |
| `metadata/profile_report.csv` | Per-pipeline complexity report (counts + T-shirt size) |
| `metadata/<pipeline>.arm.json` | (ADF) Verbatim original source for each pipeline (provenance) |
| `metadata/archive/<UTC time>/` | Only on a re-run: the earlier run's `metadata/`, `.work/` and bundle, moved here with an `archive.json` of what moved, from where and when |

Discover starts each run afresh. Over an output folder that already holds a run, it moves that run's
files into a new archive folder instead of deleting them, and says so; package keeps `metadata/`,
so the archive stays.

The inventory classifies every task into one of three strategies:

Expand Down
19 changes: 16 additions & 3 deletions skills/flowx-discover/sources/adf.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ The directory should contain subdirectories or files for:
- `linkedService/` or `linked_services/` — linked service JSON files (optional)
- `trigger/` or `triggers/` — trigger definition JSON files (optional)

On the MCP path the hosted server cannot read your workspace/volume files, so pass the ADF JSON
inline as `adf_definitions` (a mapping of relative path → JSON content), or for large factories
reference the source via `adf_volume_path` / `adf_workspace_path`.
On the MCP path the hosted server cannot read your local files, so reference the source via
`adf_volume_path` / `adf_workspace_path` (the server reads them through the SDK), or for small
factories pass the ADF JSON inline as `adf_definitions` (a mapping of relative path → JSON content).

## Step 2 — Download from UC volumes if needed

Expand Down Expand Up @@ -104,6 +104,19 @@ from the activity's ARM JSON (no built-in deterministic translator exists), e.g.
For `unsupported` activities, warn clearly, e.g. `ExecuteSSISPackage` — recommend manual conversion
to a PySpark notebook.

## Where to look for the facts enrich asks about

`flowx-enrich` reads the raw activity JSON in `inventory.json` (and `metadata/<pipeline>.arm.json`) to
find the facts that narrow the target pattern. In ADF they sit in:

- a Lookup feeding `ForEach.items`, and an `ExecutePipeline` called once per item (scale, repeat);
- dataset parameters and sink paths templated by item (fan-in);
- query text, such as a version or watermark read before the copy, or change functions (change,
shaping);
- `ForEach.batchCount` and trigger schedules (bar);
- a Copy or Lookup `typeProperties.source.type` of `SqlServerSource`, `AzureSqlSource` or
`SqlMISource`, which marks a SQL Server source.

## Step 8 — Confirm output location

Tell the user where the metadata files were written (`<output_dir>/metadata/`), summarise the
Expand Down
10 changes: 10 additions & 0 deletions skills/flowx-discover/sources/airflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ For `agentic` tasks, name the operator that has no deterministic mapping yet (e.
provider operator) and note it will be emitted as a placeholder notebook for the convert phase to
fill via LLM-assisted translation.

## Where to look for the facts enrich asks about

`flowx-enrich` reads the DAG source to find the facts that narrow the target pattern. In Airflow they
sit in:

- dynamic task mapping (`expand`) and task groups, and the list a mapped task is given (scale,
repeat);
- operator SQL, such as a watermark read before the load (change, shaping);
- the DAG's `schedule` and `max_active_tasks` (bar).

## Coverage notes

Current deterministic coverage: `PythonOperator` (callable body → generated PySpark notebook) and
Expand Down
Loading
Loading