Skip to content

Bluefly Drupal Package Map

Which Bluefly-owned Drupal package is still justified, which must shrink, which is replaced, which is contributed upstream, and which leaves a consumer after migration. This is the persistent answer to "is this Bluefly package still ours to own?" Ownership is a cost; the justified set is deliberately small.

Vocabulary for CURRENT_DISPOSITION: KEEP (justified core ownership), SHRINK (keep the differentiation, delete the generic surface), REPLACE (an upstream owner takes the capability), CONTRIBUTE_UPSTREAM (correct shape; belongs on drupal.org), DELETE_AFTER_MIGRATION (leaves the consumer or the estate once consumers and replacements are proven). A package can carry a primary and a secondary disposition; the primary is listed first.

Every measurement below is REPORTED from the 2026-09-20 audit (bluefly.io, branch chore/bluefly-9yp-ownership-audit, commit bc18aa8c), LAST_VERIFIED=2026-09-20. None of these are blanket delete instructions: every removal must prove consumers, migration, and replacement through contrib-module-adoption.md. GitLab group and subgroup conventions (contrib-ready/, private/, themes/, recipes/) are defined in drupal-standard.md section 10.


What Bluefly is still justified in owning

Reported by the audit (section 5) and carried here as the current reference:

  1. api_normalization core — OpenAPI → managed data sources → Tool API. A proven gap; already on drupal.org.
  2. duadp (protocol implementation) and ai_agents_ossa core (OSSA manifest → agent derivation) — standards Bluefly authors.
  3. ai_context governance extensions — Cedar-gated writes, DUADP attestation, GAID provenance. The ContextControl differentiation, not the plumbing.
  4. The Gas City bridge, as Tool API plugins, in one package.
  5. bluefly_theme SDCs and design tokens — brand presentation.

Everything else in the map is replaceable by core, contrib, or configuration.


contrib-ready/*

api_normalization

PACKAGE=api_normalization (contrib-ready; installed 0.1.9 from GitLab; drupal.org has 1.0.0-alpha4)
PURPOSE=OpenAPI specification → managed data sources → Tool API plugins
UPSTREAM_OWNER_IF_ANY=drupal.org project exists (Bluefly-authored); generic pieces owned by drupal/tool, drupal/openapi, ECA, ai_agents
BLUEFLY_DIFFERENTIATION=the OpenAPI-to-Tool-API derivation path; proven gap
CURRENT_DISPOSITION=KEEP core; SHRINK submodules; CONTRIBUTE_UPSTREAM (consumer must track the drupal.org release, not a GitLab pin)
OVERLAP_EVIDENCE=30.5k PHP; 89 plugins (31 Tool, 23 ECA, 2 monitoring, openapi, feeds); 14 submodules with 2 enabled; 13 forms; 9 controllers; own tool_api_adapter plugin manager. Shrink list: _feeds/_tamper (feeds unused), _flowdrop, _monitoring, _apidog, _entity_gen, _advancedqueue, _project_browser, _gateway, _openapi (the openapi module generates specs), _modeler; delete the parallel tool_api_adapter abstraction and keep only the Tool API deriver. Submodule surface ≈ 9,000 PHP LOC (about 30 percent of the package).

duadp and duadp_client

PACKAGE=duadp / duadp_client (contrib-ready, two repositories carrying the same module: duadp_client root is duadp.info.yml)
PURPOSE=DUADP protocol implementation; /.well-known/duadp.json discovery
UPSTREAM_OWNER_IF_ANY=drupal.org project (Bluefly-authored)
BLUEFLY_DIFFERENTIATION=Bluefly authors the standard; the implementation is the reference
CURRENT_DISPOSITION=KEEP (one drupal/duadp); DELETE_AFTER_MIGRATION for the duplicate duadp_client repository; CONTRIBUTE_UPSTREAM
OVERLAP_EVIDENCE=25k PHP; 47 plugins; 18 controllers; 10 entities; 4 submodules; not enabled on the audited site. Two repositories represent one capability. Replacement path for discovery on bluefly.io: enable duadp_discovery (configuration only). Note: [drupal-standard.md section 10](../../standards/drupal/drupal-standard.md#10-bluefly-platform-stack-binding-for-bluefly-hosted-drupal-sites) names duadp as the agent-discovery owner (reconciled 2026-09-20).

dita_ccms

PACKAGE=dita_ccms (contrib-ready; installed dev, not enabled)
PURPOSE=DITA component content management
UPSTREAM_OWNER_IF_ANY=none identified
BLUEFLY_DIFFERENTIATION=not applicable to bluefly.io (track_registry: not in scope)
CURRENT_DISPOSITION=DELETE_AFTER_MIGRATION (remove from the bluefly.io consumer composer; package itself not dispositioned by this audit)
OVERLAP_EVIDENCE=17.7k PHP; 0 tests; no requirement on the consumer. Largest single removable surface measured (17,675 LOC).

ai_agents_ossa

PACKAGE=ai_agents_ossa (contrib-ready; drupal.org 1.0.0-alpha3; not installed on the audited site)
PURPOSE=OSSA manifest → ai_agents plugin derivation
UPSTREAM_OWNER_IF_ANY=drupal.org project (Bluefly-authored); dashboards owned by ai_dashboard, ai_metering, ai_logging; registry consumption owned by duadp; UI components owned by the theme
BLUEFLY_DIFFERENTIATION=manifest-to-agent derivation (a standard Bluefly authors)
CURRENT_DISPOSITION=SHRINK; CONTRIBUTE_UPSTREAM (finish alpha → beta)
OVERLAP_EVIDENCE=submodules agent_registry_consumer, ai_agent_ossa_ui_components (8 SDCs), ai_agents_dashboard (+agents, +monitoring), ai_agents_ossa_api_normalization. Drop ai_agents_dashboard/_monitoring (→ ai_dashboard, ai_metering, ai_logging); ui_components → theme; agent_registry_consumer → duadp; hard dependencies on kb_cache and mcp_registry (MR !205/!206) to remove.

private/*

agentic_canvas_blocks

PACKAGE=agentic_canvas_blocks (private; not installed)
PURPOSE=dashboard, health, cost, review, composer, palette, export, flow-drop builder, manifest preview, skill palette, workflow visualisation blocks; REST resources; 8 SDCs
UPSTREAM_OWNER_IF_ANY=Canvas + SDC (presentation); canvas_tools (21 tools); ai_dashboard / ai_metering (dashboards); JSON:API / Tool API (REST)
BLUEFLY_DIFFERENTIATION=none in PHP
CURRENT_DISPOSITION=DELETE_AFTER_MIGRATION (delete the module; move the 8 SDCs to the single component home and dedupe with ai_agent_ossa_ui_components)
OVERLAP_EVIDENCE=Controller, Form, Plugin/Block, REST resources, Service, vendor/ committed; agent_ui_components duplicates the 8 SDCs in ai_agent_ossa_ui_components. One of the four duplicated Bluefly AI dashboards.

cedar_policy

PACKAGE=cedar_policy (private; not installed)
PURPOSE=policy decision integration (Cedar PDP)
UPSTREAM_OWNER_IF_ANY=http_client_manager + Tool API + ECA for the client shape; secure_drupal recipe (drupal.org) for compliance baselines
BLUEFLY_DIFFERENTIATION=a thin PDP client: Tool plugin policy_check plus an ECA condition
CURRENT_DISPOSITION=REPLACE (inline executor / proxy / middleware violate the PDP-is-compliance-engine rule; _cursor, _flowdrop, _orchestration deleted; compliance config splits fedramp/gdpr/hipaa → secure_drupal recipe)
OVERLAP_EVIDENCE=6 submodules (_ai, _cursor, _executor, _flowdrop, _modeler, _orchestration); entities; forms; middleware; proxy; REST; ECA and Tool plugins; policy templates. Note: [drupal-standard.md section 10](../../standards/drupal/drupal-standard.md#10-bluefly-platform-stack-binding-for-bluefly-hosted-drupal-sites) names cedar_policy as a thin PDP client with no inline evaluation (reconciled 2026-09-20).

contractplane_client

PACKAGE=contractplane_client (private; not installed)
PURPOSE=ContractPlane integration (gas_town, orchestration, statemesh submodules)
UPSTREAM_OWNER_IF_ANY=api_normalization managed source → Tool API → mcp_server
BLUEFLY_DIFFERENTIATION=none for bluefly.io (display-only per the project AGENTS); platform sites decide statemesh separately
CURRENT_DISPOSITION=REPLACE for this consumer (ContractPlane OpenAPI as an api_normalization managed source)
OVERLAP_EVIDENCE=plugins AdvancedQueue, AiAgent, AiFunctionCall, ECA, Mcp, jsonrpc, rest, tool — four parallel exposure paths for one capability; Model/Normalizer; trust/trace/economics/policy directories. gas_town duplicates the Gas City bridge in ai_agents_agui.

kb_cache

PACKAGE=kb_cache (private; not installed)
PURPOSE=ContextControl extensions over ai_context
UPSTREAM_OWNER_IF_ANY=ai_context (providers, scoring, caching, items); Beads (project tracking); Tool API (REST replacement)
BLUEFLY_DIFFERENTIATION=governance extension of ai_context: Cedar-gated writes, DUADP attestation, GAID provenance
CURRENT_DISPOSITION=SHRINK
OVERLAP_EVIDENCE=ai_context_ccc, contextcontrol_data (own entities/openapi/sdk), kb_cache_figma, ContextMemoryProvider and ContextScoring plugins, REST and Tool plugins, legacy Annotation; config/install ships node type kb_project plus about 30 field_kb_* storages and the agent_memory ai_context_item type. Delete kb_project and field_kb_* (project tracking is Beads' job; the 28 orphan storages removed in MR !133 came from here), kb_cache_figma, and any generic memory provider or scoring that ai_context 1.0 owns; REST → Tool API. Unblocks bead 9yp.20.2. Semantic-retrieval direction: ledger/audits/drupal-lane-audit-2026-09-14 section 4.

skills_browser

PACKAGE=skills_browser (private; not installed)
PURPOSE=skills.sh and registry sources for project_browser; Tool plugins; AiContextScope
UPSTREAM_OWNER_IF_ANY=project_browser (general gap: registry sources)
BLUEFLY_DIFFERENTIATION=small and correctly shaped
CURRENT_DISPOSITION=CONTRIBUTE_UPSTREAM (Track 2 site, not bluefly.io)
OVERLAP_EVIDENCE=2 config entities; 3 forms; 4 ProjectBrowserSource plugins; 2 Tool plugins; 2 AiContextScope; SkillsShClient; tests. No overlap found.

recipe_onboarding

PACKAGE=recipe_onboarding (private; not installed)
PURPOSE=onboarding tooling: GraphQL schema, validation constraints, CLI generators, helm charts, tour builder, bpmn
UPSTREAM_OWNER_IF_ANY=core Recipe API + project_browser + drupal_cms_helper; JSON:API instead of GraphQL
BLUEFLY_DIFFERENTIATION=none for bluefly.io
CURRENT_DISPOSITION=REPLACE
OVERLAP_EVIDENCE=GraphQL DataProducer/Schema; Validation constraints; cli generators; helm charts; committed playwright-report; fleet extension (AdvancedQueue, tool); tour builder; bpmn.

ai_agents_agui

PACKAGE=ai_agents_agui (private; not installed)
PURPOSE=AG-UI integration and the Gas City bridge
UPSTREAM_OWNER_IF_ANY=contrib agui 1.0.4 (enabled) owns the protocol; ai_dashboard / ai_metering own analytics; ai_agents and duadp own the registry
BLUEFLY_DIFFERENTIATION=the Gas City bridge (11 Gas* function-call plugins)
CURRENT_DISPOSITION=SHRINK (bridge as Tool API plugins — AiFunctionCall is the legacy type, tool_ai_connector bridges — in one home; delete analytics, api and registry submodules)
OVERLAP_EVIDENCE=submodules analytics/api/bridge; 11 Gas* AiFunctionCall plugins; blu-chat CSS; AiContextScope; Block. contractplane_client also carries gas_town: duplicate bridge ownership.

themes/*

bluefly_theme

PACKAGE=bluefly_theme (themes; installed 0.1.2)
PURPOSE=brand presentation: SDCs, tokens, Twig
UPSTREAM_OWNER_IF_ANY=none (Drupal theme layer)
BLUEFLY_DIFFERENTIATION=brand
CURRENT_DISPOSITION=KEEP (with fixes)
OVERLAP_EVIDENCE=0 PHP; 23 SDC; 27 Twig; 4.9k CSS. Fixes: Twig must render menu regions (bead 9yp.7.6); SDC schemas format: uri-reference and array props → slots (9yp.7.2 / 7.5); CSS selector mismatches; 14 stale component names (9yp.20.3). Component-library convergence target with agentic_canvas: 39 + 23 SDCs → at most 30.

agentic_canvas (theme)

PACKAGE=agentic_canvas (themes; installed 0.1.7)
PURPOSE=tokens and base SDCs for agent-facing experiences
UPSTREAM_OWNER_IF_ANY=ai_dashboard (dashboard controllers); canvas_tools (tooling)
BLUEFLY_DIFFERENTIATION=tokens and base SDCs
CURRENT_DISPOSITION=SHRINK (a theme must not own controllers or services; delete or move the PHP; one component library with bluefly_theme)
OVERLAP_EVIDENCE=11.7k PHP inside a theme (9 controllers, 5 services, ThemeNegotiator, PerformanceMonitor, LLMUIBridge); 39 SDCs; 104 Twig. Removable surface measured at 11,656 LOC. One of the four duplicated Bluefly AI dashboards.

recipes/*

PACKAGE=recipes/* (recipe_secure_drupal, recipe_amcs, recipe_blucity and others named in drupal-standard.md section 10)
CURRENT_DISPOSITION=NOT_ESTABLISHED by this audit
OVERLAP_EVIDENCE=the 2026-09-20 audit did not evaluate recipe packages. It names the drupal.org secure_drupal recipe as the replacement owner for cedar_policy compliance baselines and core recipes as the replacement for recipe_onboarding. Recipe composition authority and the 2026-09-13 recipe-layer audit live in Playbooks/drupal/DRUPAL-FACTORY-CONVERGENCE-PLAYBOOK.md.

Totals and measured effect

REPORTED (audit section 2): BLUEFLY_PACKAGES_KEEP=3 (api_normalization core, duadp, bluefly_theme) · SHRINK=5 (api_normalization submodules, ai_agents_ossa, kb_cache, ai_agents_agui, agentic_canvas theme PHP) · REPLACE=4 (cedar_policy, contractplane_client, recipe_onboarding, agentic_canvas_blocks) · CONTRIBUTE_UPSTREAM=1 (skills_browser) · DELETE from consumer=2 (dita_ccms, duplicate duadp_client repository).

Measured removable PHP in the bluefly.io installed surface: dita_ccms 17,675 + agentic_canvas theme 11,656 + api_normalization submodules ≈ 9,000 ≈ 38k LOC. Private repositories were measured by structure, not LOC.

Cross-cutting findings to carry into any Pack or Formula

  • Duplicated dashboards: four Bluefly AI dashboards exist across ai_agents_ossa, agentic_canvas_blocks, ai_agents_agui and the agentic_canvas theme; ai_dashboard + ai_metering + ai_logging own that capability. Do not create a fifth.
  • Duplicated DUADP: one capability in two repositories. Merge before any new consumer depends on either.
  • Duplicated Gas City bridge: ai_agents_agui and contractplane_client both carry one. One home, as Tool API plugins.
  • Duplicated component libraries: 39 + 23 SDCs plus 8 duplicated between two modules. One library.
  • kb_cache shrinks to governance; generic context plumbing is ai_context's; project tracking is Beads'.
  • markdownify + llms_txt is the agent-readable content surface; no Bluefly package builds another.
  • Migration Factory runs on core Migrate + migrate_plus configuration; no private migration module.