Claude Code plugin for end-to-end integration maturity assessment. One pipeline skill, 35 templates, and an 8-Dimension Integration Maturity Framework whose maturity levels follow Gartner's published ladder.
Evaluate integrations from code analysis through customer-facing reports:
Code Export -> Inventory -> Assessment -> Scorecard -> Design/Roadmap -> Review -> Summary
All 6 phases run from the /integration-pipeline skill, interactively or headless. The two modes are not
equivalent, and the difference is Phase 2: interactive mode interviews a domain owner, headless mode cannot, and a
headless run therefore leaves the business-process layer Unknown and says so rather than inferring it from job
names.
The templates are in three layers, and the boundary between them is enforced by scripts/lint-templates.sh
rather than by convention:
templates/integration/
├── method/ reasoning discipline. No platform name may appear here.
├── outputs/ document skeletons - what each phase writes into.
└── platforms/ everything platform-specific, one directory per platform.
This is what lets the same methodology run against a Talend workspace, a Workato export, or hand-written
integration code without editing a method document. Where a method rule needs a platform fact - which signals the
export actually carries, how to address a locus, whether a scoring ceiling differs - it says "read the profile",
and platforms/<name>/profile.md answers.
Adding a platform is additive: one directory, one row in platforms/README.md, zero changes to method/ or
outputs/ - provided the platform ships a file-based export. That is the method's stated boundary: detection
globs a directory tree, so a platform holding its design in a queryable metadata repository is out of scope
rather than not-yet-written, because the acquisition mechanism differs rather than the parser. The registry's
"When no row matches" section states it and says what would change it.
Each platform directory splits its knowledge by which phase consumes it, which matters because the phases read different files:
| File | Read by | Holds |
|---|---|---|
profile.md |
Phases 1 and 3 | What the artifact can and cannot tell you: signal availability, independent signal classes, locus form, scoring deviations, declared gaps |
parsing-*.md |
Phase 1 | How to read the artifact: structure, addressing, reference resolution, call-graph construction |
platform-behaviour.md |
Phases 4 and 5 | What the runtime does as distinct from what the artifact declares: runtime architecture, component behaviour, capabilities that pre-empt findings |
| Platform | Parser | Profile | Evidence |
|---|---|---|---|
| Talend DI / ESB | yes | yes | 2 independent Studio workspace exports; platform behaviour and control-plane model from vendor documentation |
| Workato | yes | yes | vendor documentation, not export-verified |
| Plain code (no iPaaS) | guidance | yes | method; not yet applied to a codebase |
| MuleSoft, Boomi, SAP CPI | no | declared-gap stubs | none - detection works, parsing does not |
A declared gap is a populated stub stating what is unknown and what would close it, not a missing file. The
registry at templates/integration/platforms/README.md is the single source for detection.
Lineage on two axes. Horizontally, the inventory traces a target field back to its origin field across the
call graph, and the landscape traces impact system to system. Vertically, landscape section 7 traces an artifact
upward - artifact, logical entity, business concept, business process - so a technical finding can be tied to
the business process it serves, and a field change can be tied to the processes it affects. Every rung carries a
Basis, and the upper rungs are Unknown until a domain owner confirms them: no code export states which
business process a flow serves, and the pipeline will not guess one from a flow name.
claude plugin install <org>/integration-suiteclaude --plugin-dir /path/to/plugins/integration-suiteNone. Templates are read from the plugin at run time - see "Template Source" below. The SessionStart hook only checks whether a project still holds a legacy pre-2.1.0 template copy and reports it; it never writes.
/integration-suite:integration-pipeline code-first /path/to/export customer-syncRuns all 6 phases: Analyze -> Assess -> Score -> Design -> Review -> Summarize
/integration-suite:integration-pipeline new "Salesforce-SAP customer master data sync" salesforce-sap/integration-suite:integration-pipeline new --quick "MuleSoft order processing" order-syncRun individual phases with --phase:
# Score an existing assessment
/integration-suite:integration-pipeline --phase score --from-file assessment.md my-integration
# Review a design with security deep-dive
/integration-suite:integration-pipeline --phase review --from-file design.md --security my-integration
# Generate customer summary
/integration-suite:integration-pipeline --phase summarize --from-file scorecard.md my-integration./skills/integration-pipeline/run-pipeline.sh --mode code-first --export /path/to/export customer-sync
./skills/integration-pipeline/run-pipeline.sh --mode new --brief "Description" --quick my-integration
./skills/integration-pipeline/run-pipeline.sh --phase score --from-file assessment.md my-integration35 templates, laid out by the three layers above.
No platform name appears in any of these, and the lint enforces it.
| Template | What it owns |
|---|---|
confidence-model.md |
The one confidence vocabulary: Basis per finding, ceiling per document, aggregation by minimum. A Confirmed finding must name the artifact attribute it was read from |
abstraction-ladder.md |
The one vertical-lineage vocabulary: four rungs from artifact to business process, a Basis ceiling per rung, a binding-signal ranking |
diagram-conventions.md |
The one diagram grammar: edge IDs plus a keyed edge table, role-column layout, a fixed class vocabulary where styling encodes findings, the renderer behaviours that bite, and the evidence stages for the customer-facing diagram |
extraction-guide.md |
The universal extraction checklist, system identification and the >=2 independent signals rule, forensic discipline, the locus format, and the signal-availability row set. Its Analysis Strategy is the Phase 1 workflow |
scoring-rubric.md |
8 dimensions x 5 levels, general confidence ceilings, the two unscored states, the weighted-average formula |
assessment-questionnaire.md |
Interview structure, evidence-bias table, the runtime-data gate, and the section 1b ladder walkthrough |
validation-checklist.md |
Pre-delivery (Section A) and peer review (Section B) |
pattern-library.md |
Integration patterns reference |
anti-patterns.md |
What to watch for in a design |
red-flags-library.md |
Catalogue of common critical findings |
security-review-checklist.md |
OWASP API Top 10, auth, encryption, compliance |
industry-benchmarks.md |
Sector benchmarks. Inherited priors - orientation, not measurement |
| Template | Phase |
|---|---|
inventory-document.md |
1 - per-finding Basis, a locus per Confirmed claim, analysis-pass log, patterns checked and not found |
system-landscape.md |
1 - C4 context, per-system profiles, interface catalogue, coupling and blast radius, EIP mapping, runtime-validation register, vertical lineage |
assessment-document.md |
2 |
scorecard-template.md |
3 - input-class classification, dimension scores with weight base, red flags, quick wins, score revision log, runtime-validation table |
design-document.md |
4 - new architecture |
improvement-roadmap.md |
4 - existing integration |
review-report-template.md |
5 |
customer-summary-template.md |
6 |
| Template | What it is |
|---|---|
README.md |
The detection registry. Single source: export signals to platform, and which files to read |
_profile-template.md |
The required shape of a profile. Six sections, all mandatory |
talend/profile.md, talend/parsing-core.md, talend/parsing-di-jobs.md, talend/parsing-esb-routes.md, talend/platform-behaviour.md |
Talend DI and ESB |
workato/profile.md, workato/parsing-recipes.md, workato/platform-behaviour.md |
Workato |
plain-code/profile.md, plain-code/parsing-guidance.md |
Hand-written integration code, framed by what differs from a platform export: no component vocabulary to enumerate, so the dependency manifest takes its place |
mulesoft/profile.md, boomi/profile.md, sap-cpi/profile.md |
Declared gaps. Detection works; parsing does not |
Every template carries front matter stating what it applies to, the artifact format it was verified against,
what it was verified against, its evidence class, and a date. Read it before trusting a claim - evidence class: inherited means the entries are not individually sourced, and declared gap means nothing has been read at all.
See CONTRIBUTING.md.
bash scripts/lint-templates.sh # structural: layering, front matter, path and link resolution, gate/template agreement
bash scripts/test-gates.sh # 20 fixture cases against the real gate functions
bash scripts/test-run-phase.sh # 14 cases against run_phase's failure, retry and logging paths, with a stubbed subprocesslint-templates.sh check 4 is the one worth knowing about: it asserts every gate pattern in run-pipeline.sh
matches the template that phase is told to follow. A gate requiring a heading no template emits makes a
correctly-written output fail, and that defect has occurred three times in this repo's history - now it fails at
commit time instead.
The two suites test different things and the distinction matters. test-gates.sh asks what the gate says about a
document; test-run-phase.sh asks what the orchestrator does with that answer - when the subprocess dies, and
which kind of retry a failure earns. All three defects fixed at 3.0.1 were invisible to the first kind of check,
which is why the second one exists.
Templates are read from the plugin, not copied into your project. One source of truth: a plugin update reaches every project on its next run, and a template fix cannot silently fail to arrive.
To customize, fork this repository and install your fork. Edits then stay under version control and apply to
every project that uses it. To add a platform, see "Adding a platform" in
templates/integration/platforms/README.md - it touches one directory and one registry row.
Project-local copies under .agent/templates/integration/ are not read. run-pipeline.sh read one as a fallback
until 3.0.0, which contradicted this section and reintroduced the drift the single-source rule exists to remove;
that fallback is gone. If a project still holds such a copy, the SessionStart hook reports it so you can remove it.
One defect, found by running 3.5.0 rather than by reading it. A verification run of Phase 1 reported an execution failure; the subprocess had produced two complete, gate-valid documents and been killed by a session limit after writing them.
sed | grep -qunderpipefailreports a found line as a missing one (PW-24). Three gate checks strip inline emphasis before matching.grep -qexits at its first match,sedis then killed by SIGPIPE writing the rest of the file, the pipeline reports 141, andif ! ...reads that as "the line is absent". A correct document is rejected because it states the required line, and the more prominently it states it the more likely the rejection.- It also defeated PW-17. A subprocess killed after writing valid output is accepted only if the gate passes, so a false gate failure turns a completed phase back into a reported execution failure. That is what the verification run reported.
- It needs a file over the pipe buffer and a match near the top, which is why fifteen fixtures never saw it: they are all a few KB. On the 80 KB landscape that found it, the legend check rejected a correct document in 36 of 40 attempts; the coverage check on the same file, whose match is 430 lines further down, failed 0 of 40.
- Fixed by removing the pipe, in one helper used by all three call sites. The regression test builds an 80 KB document rather than committing one, and asserts a clean sweep of 20 runs - against the pre-fix form the same test rejects the document 20 of 20 times.
The reconciliation check becomes a gate, and a recorded decision is reversed to get it there. One new Phase 1 gate check; a re-run will now fail its Phase 1 gate on a landscape whose section 3 catalogues an interface that appears in no edge-key row.
- Every interface in section 3 must appear in the edge key. This is the check that surfaced 4 of 23 interfaces never drawn on the first real run, and every other gate check passed on that same document. It names the IDs it could not place, because the repair prompt forbids inventing content to clear a check and the author has to be able to tell a legitimate repair - drawing an edge the catalogue already documents - from fabricating one.
- This reverses the 3.3.0 decision to leave it out, which was recorded in five places and is now corrected in all of them. The reason given then still holds: it is Markdown table-scraping, and PW-18's fact base proposes to retire exactly that. It goes in because PW-18 is parked, so "until the fact base lands" became an indefinite wait. The helper carries a delete-me-when note.
- Two limits, stated rather than implied. It checks the join, not whether the join is correct: an edge key naming an interface the diagram does not draw reconciles and passes. And it does not fire on a key that names no interface anywhere, because reporting every interface as missing is noise rather than a finding.
- Two fixtures pin it, one of them a false-positive guard: aggregating several interfaces onto one edge is
expected and must pass, and IDs are matched as whole tokens so
I1is not found insideI12.
Three findings that needed no new evidence, two of them stale in the record rather than genuinely open. Template and governance text only - no orchestrator change, nothing to do on upgrade.
- The enumerate-first rule reaches both parsing guides (PC-03). It was applied to
parsing-core.mdat 2.1.0 and recorded asApplied, but both companion guides still carried the fixed component tables it replaced - 15 route components of 26 known, 34 job components of 90. Two independent exports of the same platform shared only 46 of 123 distinct components, so a maintained list is permanently incomplete and biases classification toward whatever it happens to name. Both tables now defer to the enumeration and keep only rows that state what the component changes in the parse. The grep blocks lead with the generic form and label the alternations as filters. - A
tMap's configuration decides whether a mapping is resolvable (PC-13). The documented option set lands - match models (Unique Matchmeans the last matching row), load models, and the three flags that change semantics - together with what each does to a mapping'sBasisand a list of settings that must not be reported as transformations. The.itemattribute names stay a declared gap: they are documented nowhere, and a grep for an invented one returns zero matches, which reads as "the feature is absent". Find them by diff, not by search. - The toolkit states its artifact-source boundary (OG-09). It analyses file-based exports: detection globs
a directory tree, so a platform holding its design in a queryable metadata repository is out of scope rather
than not-yet-written - the gap is in acquisition, not in parsing, and it is not closed by writing a parser.
Every profile now carries an
Acquisitionline, which is what makes the boundary checkable per platform.
The context diagram gets a grammar, and the customer summary gets a diagram. Five findings from the first real run, all of them about the only visual artifact the pipeline produces - which is also the artifact a stakeholder looks at first. One new template, three new gate checks, and one new required section in the customer summary; existing projects need nothing on upgrade, but a re-run will now fail its Phase 1 gate on a landscape whose diagram carries prose edge labels.
- Edge labels are IDs; attributes move to a keyed table. Measured on the diagram the first run produced - 10 systems, 14 edges - 8 of 14 labels ran over 30 characters and 4 rendered detached from the edge they describe. The mechanism is not a matter of taste: label text drives node spacing, node spacing drives edge length, and Mermaid places the label at the midpoint, so a long label ends up floating in open canvas. The old instruction ("label edges with protocol + direction + trigger") is correct at two nodes and self-defeating at ten.
- The edge key joins the diagram to the interface catalogue, and that join found real gaps. Its
Interfacescolumn resolves each drawn edge to the section 3 rows it aggregates, and every interface must appear in at least one key row. Filling that column in on a real document surfaced 4 of 23 interfaces that had never been drawn. An interface nobody drew reads as an interface that does not exist. - A
Chainedtrigger now needs a caller that was found. The trigger inventory runs caller-to-callee and structurally cannot tell you a flow is invoked by nobody. The inverse check - enumerate every called-artifact reference, diff against the artifact list - found an interface recorded asChainedthat nothing in the export invokes: a token-validation job on an unauthenticated inbound path, which moves a security control from "present" to "not invoked". Where no caller is found the value isnone found, never a chain inferred from what a job is evidently for. - Styling encodes findings and nothing else, with a fixed class vocabulary and a declared legend. The colour
channel was free and unused while the findings it could carry sat in prose several sections away. Every
classDefwith afillalso sets acolor:, or it renders light-on-light in a dark-theme viewer. - The customer summary now carries exactly one diagram, stage-gated by evidence. It had none - the one document
a business stakeholder reads was unbroken prose. The slot declares an evidence stage (static export / plus
deployment facts / plus an attributed walkthrough), each stage fixes what may be drawn and what must be drawn as
absent, and only the last permits a process shape. Business-process rungs are
Unknownon a code export, and an ungated slot invites the highest-prominence claim in the package to be the one with no evidence behind it. - Never issue a Mermaid fence to a customer. Exported to PDF or Word it ships as source code in the middle of an executive summary. The template says to export an image and keep the block as the source of truth; deliberately not a render step in the pipeline, because a renderer is an external binary the toolkit cannot assume - and one that silently does nothing when the binary is absent reproduces the same failure one layer down.
- Also: a Basis capped by a confidence ceiling rather than by its findings must now say
Unknown (ceiling-capped)and name what the findings supported. A plainUnknownsays the evidence is weak; the annotated form says a prior about the input class is what holds the value down, which is a different instruction to the reader.
tests/fixtures/phase6/ is new, and the three phase-1 landscape fixtures gained the section 1 they never had.
Three observability fixes, all from the same first run as 3.0.1's. Nothing about the method or the outputs changes;
what changes is whether the next failure can be diagnosed. One visible difference: per-attempt logs now live
in logs/ under the output directory instead of beside the deliverables.
- The run log no longer erases itself.
pipeline-log.mdwas truncated on every non-resume start, so the invocation that failed - the one explaining why there is a second - left no trace; it now appends one block per invocation. Phase logs were opened with>on every attempt, so the attempt whose output survived was overwritten by the retry that followed it: in the observed run a 66-byte session-limit message stood where the output of a 1828-second parse should have been. Each attempt now writeslogs/phase-N-attempt-K.log, and each gate retrylogs/phase-N-retry-K.log. Writing this release's own history required comparing file mtimes against phase timings, which is the argument for the change. - A phase wrote a directory inside the export. An empty tree appeared under the customer's export directory one minute after Phase 1 started - read-only material, on a gitignored path, so nothing reported it. The root cause is not established and the fix says so: both the output and export paths are now absolutised before any prompt sees them, the Phase 1 prompt states that the export is read-only, and each phase logs the working directory its subprocess inherits so the next occurrence names its own cause.
- A headless run says what it cannot reach.
--briefis required fornewandexistingbut not forcode-first, so the mode most likely to run unattended built its Phase 2 prompt with an empty**Integration Brief**:field - an invitation to fill the gap from the export, which is exactly the inference the method forbids. The prompt now states that there is no brief and no interview and that business-domain questions are therefore open; the run says the same at startup.--briefis still not mandatory: a code export is a legitimate sole input, and requiring a brief would push someone into writing one from the export.
Talend platform knowledge, from a documentation read rather than an export: the built-in/repository axis, project reference constraints, the control-plane object model, and the platform's own lineage tooling. One correctness fix in the method layer and one in the Talend parser. No pipeline or gate change, and one new output column; nothing to do on upgrade.
- "Static parsing is the only applicable lineage method" was wrong, and platform-neutral. The extraction guide asserted it for every platform, then listed dynamic SQL first among the hops to flag for manual verification. Talend Studio emits a per-run JSON lineage log carrying the executed query, and commercial scanners consume it for exactly those hops. The guide now calls static parsing the default method and points at the profile's artifact-format table before a hop is declared permanently untraceable. Because the claim named no platform the lint passed it at every commit since 3.0.0 - a neutral sentence is not automatically a general one.
- Joblet labels can resolve in more than one project. Job bindings resolve by GUID with an optional project qualifier; joblet references resolve by label with none, joblets are the one item type permitted to share a name between a project and its reference, and a project setting decides whether lookup falls back beyond the originating project. A uniqueness check is now required before resolving. The old behaviour failed silently - it produced a plausible graph.
- Built-in versus repository is now a parsing distinction. An inline schema may be a copy of a centralized
metadata/item; centralized items drift from those copies, because propagation is offered rather than enforced; and where components bind,metadata/is a join across flows the call graph does not show. The inline-versus-bound ratio is countable and it bounds what any lineage tooling can do - including Talend's own, which sees only centralized items. - Lineage edges now carry a kind -
transformed,pass-through,control-flow,constant- and aconstanthop is a complete answer, not a failed trace. The inventory's Field Lineage table gains one column. - Phases 4 and 5 gained the platform's lineage facilities: impact analysis and its centralization precondition, runtime lineage, cloud lineage collection with its 50-dataset / 500-record caps, and the Big Data path. "The platform provides no lineage capability" is now a pre-empted finding.
- Two Talend declared gaps became requests: the control plane's object model is documented, so the profile names the objects holding the schedules D3 is capped for instead of recording an absence.
Three orchestration fixes, all found by running the pipeline end to end over a real workspace export for the first time. No template, method or output-format change; nothing to do on upgrade.
-
The section 7.3 coverage gate rejected a correct document on inline emphasis. A Phase 1 that wrote
**Coverage**: **11 of 74 mapped fields traced.**- the requirement met in full - failed the gate, burned both retries and aborted a 30-minute phase. Emphasis is now stripped before matching. The check exists to prove a denominator was stated, not to constrain how it is typeset. -
A subprocess killed after writing its output was reported as a failed phase. Gate validation sat after the execution-retry loop, so a non-zero exit returned before the gate ever saw the file: a phase that produced a complete, gate-valid deliverable and was then killed exited non-zero, while
--resumea minute later called it COMPLETE. The gate is now asked first, about output this attempt actually wrote. A gate failure reported after a retry that itself died now says so, instead of presenting a stale content error as the cause. -
A gate retry re-ran the whole phase to fix a defect in one line. There was one retry path - append "output was missing required sections" to the original prompt and start over - and on a phase that takes half an hour with output that is 99% correct, that is both expensive and untrue. The retry now splits by the state of the output: repair when the document exists and is substantial (edit it in place, fix exactly the named checks, do not re-read the export) and regenerate only when it is absent, truncated or an agent failure. The repair prompt also tells the model that if a reported check is already satisfied it should change nothing and say so - a gate that fails a correct document is a defect in the gate, and the retry loop previously had no way to report one.
scripts/test-run-phase.sh is new and pins the second and third; tests/fixtures/phase1/landscape-bold-coverage.md
pins the first.
The three are one story. A gate that can only say that it failed, to a retry that can only start over, turns any false gate failure into a terminal one. The first fix removes an instance; the third removes the amplifier.
Breaking, and only for forks or scripts that reference template paths directly:
- Template paths gained a layer.
templates/integration/<name>.mdis nowtemplates/integration/method/<name>.mdortemplates/integration/outputs/<name>.md. platform-parsers/is nowplatforms/<name>/, and the Talend and Workato files were renamed and split:talend.mdtotalend/parsing-core.md,talend-jobs.mdtotalend/parsing-di-jobs.md,talend-routes.mdtotalend/parsing-esb-routes.md,workato.mdtoworkato/parsing-recipes.md. Runtime and component knowledge moved out of those files intoplatform-behaviour.md, and signal availability intoprofile.md.run-pipeline.shnow fails at startup on a pre-3.0.0 flat template tree rather than part-way through a phase.
Nothing changes for normal use: the skill resolves templates from the plugin, so /integration-pipeline and
run-pipeline.sh work unchanged after a plugin update.
Fixed in the same release: Phase 4 could not pass its own gate on the improvement-roadmap path; Phase 3's prompt
instructed the confidence vocabulary its gate rejects, and hardcoded a /17 denominator the rubric had already
replaced; --from-file was parsed and then used by nothing, so every documented standalone-phase flow failed;
scorecard-template.md lacked three sections the gate requires. scripts/lint-templates.sh check 4 exists so the
first and last of those cannot recur silently.
- Plugin: 3.5.1
- Framework: 8-Dimension Integration Maturity Framework. Maturity levels follow Gartner's published integration maturity ladder; the eight dimensions and their weights are this toolkit's own, not Gartner's.
- Platforms: Talend (export-verified, DI + ESB), Workato (documented, not export-verified), plain code (method, not yet applied); MuleSoft, Boomi and SAP CPI are declared gaps with populated stubs, not guesses.