Skip to content

Pass reverse-engineered business logic into migration/conversion pipeline#45

Merged
jkordick merged 4 commits intomainfrom
copilot/fix-migration-process-logic
Mar 5, 2026
Merged

Pass reverse-engineered business logic into migration/conversion pipeline#45
jkordick merged 4 commits intomainfrom
copilot/fix-migration-process-logic

Conversation

Copy link
Contributor

Copilot AI commented Feb 23, 2026

The output of reverse engineering (business logic, features, business rules) was captured but never forwarded to the conversion step — converters operated with only the structural CobolAnalysis, missing the semantic context extracted by BusinessLogicExtractorAgent.

Changes

Interface & converter agents

  • Added SetBusinessLogicContext(List<BusinessLogic>) to ICodeConverterAgent (mirrors the existing SetRunId pattern)
  • Implemented in JavaConverterAgent, CSharpConverterAgent, ChunkAwareJavaConverter, ChunkAwareCSharpConverter
  • Each converter looks up the BusinessLogic entry by filename at conversion time and injects it into the AI prompt:
var businessLogic = _businessLogicExtracts
    .FirstOrDefault(bl => string.Equals(bl.FileName, cobolFile.FileName, StringComparison.OrdinalIgnoreCase));
if (businessLogic != null)
{
    userPromptBuilder.AppendLine("Here is the extracted business logic from the reverse engineering phase. " +
        "Use this to ensure the converted code faithfully implements all business rules and features:");
    userPromptBuilder.Append(FormatBusinessLogicContext(businessLogic));
}
  • Extracted shared FormatBusinessLogicContext helper to AgentBase to avoid duplication across all four converter classes

Pipeline wiring

  • MigrationProcess and ChunkedMigrationProcess each expose SetBusinessLogicContext, which delegates to their respective converter agent
  • SmartMigrationOrchestrator.RunAsync() gains an optional List<BusinessLogic>? businessLogicExtracts parameter and calls SetBusinessLogicContext on whichever sub-process is instantiated (direct or chunked), after InitializeAgents()
  • Program.cs: reverseEngResult is now persisted in outer scope and reverseEngResult.BusinessLogicExtracts is passed into smartOrchestrator.RunAsync() — effective for both the full pipeline and skip-reverse-engineering modes (context is null/empty when RE was skipped, converters no-op gracefully)
Original prompt

This section details on the original issue you should resolve

<issue_title>reverse-engineered business logic not used in migration/conversion step</issue_title>
<issue_description>It appears that in the current workflow, the output of the reverse engineering process, such as business logic extraction and dependency mapping (see ReverseEngineeringProcess), is not directly used as input for the code conversion step within the migration phase (handled by MigrationProcess).

Specifically:

  • In Program.cs, both reverse engineering and migration/conversion are implemented as separate steps.
  • The DependencyMapperAgent appears to be used mainly to generate documentation and diagrams, rather than to condition or guide actual code conversion logic (MigrationProcess.RunAsync).

Is this separation intentional? Could you provide insight into the rationale for not passing the reverse-engineered business logic and dependencies directly into the migration/conversion pipeline? Were design trade-offs made versus a model-driven approach (MDRE), where such context would typically inform automated conversion?

Submitted via email.

Note by @jkordick: No, this is not inteded. Add this as a to do.

References:

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

…line

Co-authored-by: jkordick <52427852+jkordick@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix migration process to include reverse-engineered business logic Pass reverse-engineered business logic into migration/conversion pipeline Feb 23, 2026
… business logic persistence

- Added dependency mapping step to ChunkedReverseEngineeringProcess and ReverseEngineeringProcess.
- Integrated IMigrationRepository for saving and reusing business logic and dependency maps.
- Updated RunMigrationAsync to support loading persisted business logic from previous runs with --reuse-re flag.
- Modified command-line interface to include options for reusing business logic and improved documentation.
- Enhanced README and architecture documentation to reflect changes in business logic persistence and usage.
@jkordick jkordick requested a review from Copilot February 23, 2026 16:36
@jkordick jkordick marked this pull request as ready for review February 23, 2026 16:36
Comment on lines +1382 to +1386
catch (Exception ex)
{
Console.WriteLine($"❌ Error fetching business logic for run {runId}: {ex.Message}");
return Results.Problem($"Failed to fetch business logic: {ex.Message}");
}
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request addresses issue #20 by implementing end-to-end persistence and injection of business logic extracted during reverse engineering into the conversion prompts. Previously, the BusinessLogicExtractorAgent output was generated for documentation only; now it is stored in a new SQLite table and passed to converter agents to guide AI-based code translation.

Changes:

  • Added SetBusinessLogicContext() to ICodeConverterAgent and implemented it across all four converter agents (Java, C#, and chunk-aware variants), with a shared FormatBusinessLogicContext() helper in AgentBase
  • Introduced business_logic SQLite table and three new repository methods (SaveBusinessLogicAsync, GetBusinessLogicAsync, DeleteBusinessLogicAsync) to persist and retrieve business logic per run
  • Extended ReverseEngineeringProcess and ChunkedReverseEngineeringProcess to persist business logic and dependency maps, and added a --reuse-re CLI flag to load cached results when running conversion-only mode
  • Added REST API endpoints (GET/DELETE /api/runs/{runId}/business-logic) and Portal UI (🔬 RE Results button per run) to view and delete persisted business logic
  • Updated SmartMigrationOrchestrator, MigrationProcess, and ChunkedMigrationProcess to accept and thread business logic context and dependency maps through the pipeline
  • Enhanced doctor.sh to prompt for --reuse-re in convert-only mode and updated documentation across README, CHANGELOG, and REVERSE_ENGINEERING_ARCHITECTURE

Reviewed changes

Copilot reviewed 26 out of 26 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
Agents/Interfaces/ICodeConverterAgent.cs Added SetBusinessLogicContext() method to interface
Agents/JavaConverterAgent.cs Implemented business logic context injection into Java conversion prompts
Agents/CSharpConverterAgent.cs Implemented business logic context injection into C# conversion prompts
Agents/ChunkAwareJavaConverter.cs Implemented business logic context injection for chunked Java conversion
Agents/ChunkAwareCSharpConverter.cs Implemented business logic context injection for chunked C# conversion
Agents/Infrastructure/AgentBase.cs Added shared FormatBusinessLogicContext() helper method
Agents/BusinessLogicExtractorAgent.cs Fixed feature extraction to match "Use Case" and "Operation" headings
Persistence/IMigrationRepository.cs Added business logic persistence methods to interface
Persistence/SqliteMigrationRepository.cs Created business_logic table and implemented save/get/delete methods
Persistence/HybridMigrationRepository.cs Delegated business logic methods to SQLite repository
Processes/ReverseEngineeringProcess.cs Added dependency mapping step and business logic persistence
Processes/ChunkedReverseEngineeringProcess.cs Added dependency mapping step and business logic persistence for chunked RE
Processes/MigrationProcess.cs Added SetBusinessLogicContext() and dependency map reuse logic
Processes/ChunkedMigrationProcess.cs Added SetBusinessLogicContext() and dependency map reuse logic
Processes/SmartMigrationOrchestrator.cs Extended RunAsync() to accept and pass business logic and dependency map context
Program.cs Added --reuse-re flag, logic to load cached business logic, and wiring to pass context to orchestrator
Helpers/FileHelper.cs Added SaveDependencyOutputsAsync() helper method
McpChatWeb/Program.cs Added REST API endpoints for business logic retrieval/deletion and injected RE results into chat context
McpChatWeb/Services/McpProcessClient.cs Updated chat system prompt to mention RE context availability
McpChatWeb/wwwroot/runs-viewer.js Added UI for viewing and deleting per-run RE results
McpChatWeb/wwwroot/run-selector.js Added run type label display in selector
McpChatWeb/wwwroot/index.html Renamed modal title to "Reverse Engineering Results"
doctor.sh Added interactive prompt for --reuse-re in convert-only mode and updated help text
docs/REVERSE_ENGINEERING_ARCHITECTURE.md Documented business logic persistence feature and updated diagrams
README.md Added business logic persistence section with usage modes table
CHANGELOG.md Documented all changes in v2.5.0 release
Comments suppressed due to low confidence (1)

Program.cs:1454

  • The ChunkedReverseEngineeringProcess constructor is missing the migrationRepository parameter. In the main migration flow (lines 656-666), the chunked RE process receives migrationRepository as the last parameter, but in the reverse-eng command flow (here), it's omitted. This means when running ./doctor.sh reverse-eng with large files, business logic won't be persisted to the database, breaking the --reuse-re functionality. Add migrationRepository as the last constructor parameter to match the pattern at line 666.
                var chunkedProcess = new ChunkedReverseEngineeringProcess(
                    cobolAnalyzerAgent,
                    businessLogicExtractorAgent,
                    dependencyMapperAgent,
                    fileHelper,
                    settings.ChunkingSettings,
                    chunkingOrchestrator,
                    loggerFactory.CreateLogger<ChunkedReverseEngineeringProcess>(),
                    enhancedLogger,
                    databasePath);

Comment on lines +1357 to +1359
(SELECT COUNT(*) FROM json_each(user_stories_json)) AS story_count,
(SELECT COUNT(*) FROM json_each(features_json)) AS feature_count,
(SELECT COUNT(*) FROM json_each(business_rules_json)) AS rule_count,
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SQL query uses json_each() to count array elements, which will fail silently if the JSON is null or invalid, returning 0. However, the table schema shows these columns can be NULL (inserted via DBNull.Value). When a column is NULL, json_each(NULL) will return an empty set, so COUNT will correctly return 0. This is actually safe, but consider adding COALESCE to make the intent clearer: COALESCE((SELECT COUNT(*) FROM json_each(user_stories_json)), 0).

Suggested change
(SELECT COUNT(*) FROM json_each(user_stories_json)) AS story_count,
(SELECT COUNT(*) FROM json_each(features_json)) AS feature_count,
(SELECT COUNT(*) FROM json_each(business_rules_json)) AS rule_count,
COALESCE((SELECT COUNT(*) FROM json_each(user_stories_json)), 0) AS story_count,
COALESCE((SELECT COUNT(*) FROM json_each(features_json)), 0) AS feature_count,
COALESCE((SELECT COUNT(*) FROM json_each(business_rules_json)), 0) AS rule_count,

Copilot uses AI. Check for mistakes.
Comment on lines +821 to +858
protected static string FormatBusinessLogicContext(BusinessLogic businessLogic)
{
var sb = new StringBuilder();
if (!string.IsNullOrWhiteSpace(businessLogic.BusinessPurpose))
{
sb.AppendLine($"Purpose: {businessLogic.BusinessPurpose}");
}
if (businessLogic.BusinessRules.Count > 0)
{
sb.AppendLine("Business Rules:");
foreach (var rule in businessLogic.BusinessRules)
{
sb.AppendLine($"- {rule.Description}");
if (!string.IsNullOrWhiteSpace(rule.Condition))
sb.AppendLine($" Condition: {rule.Condition}");
if (!string.IsNullOrWhiteSpace(rule.Action))
sb.AppendLine($" Action: {rule.Action}");
}
}
if (businessLogic.Features.Count > 0)
{
sb.AppendLine("Features:");
foreach (var feature in businessLogic.Features)
{
sb.AppendLine($"- {feature.Name}: {feature.Description}");
}
}
if (businessLogic.UserStories.Count > 0)
{
sb.AppendLine("Feature Descriptions:");
foreach (var story in businessLogic.UserStories)
{
sb.AppendLine($"- {story.Title}: {story.Action}");
}
}
sb.AppendLine();
return sb.ToString();
}
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The FormatBusinessLogicContext method always appends a blank line at the end (line 856), even when the BusinessLogic object has no content (all lists are empty and BusinessPurpose is null/empty). This means converters will inject "Here is the extracted business logic..." followed by just a blank line when no business logic was extracted. Consider adding a check at the start: if (string.IsNullOrWhiteSpace(businessLogic.BusinessPurpose) && businessLogic.BusinessRules.Count == 0 && businessLogic.Features.Count == 0 && businessLogic.UserStories.Count == 0) return string.Empty; to avoid injecting empty context.

Copilot uses AI. Check for mistakes.
features_json TEXT,
business_rules_json TEXT,
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(run_id) REFERENCES runs(id),
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The business_logic table's FOREIGN KEY constraint is missing ON DELETE CASCADE. The documentation at docs/REVERSE_ENGINEERING_ARCHITECTURE.md line 469 shows the schema should include ON DELETE CASCADE, which makes sense since business logic entries should be deleted when their parent run is deleted. Without this, orphaned business_logic records will remain in the database if a run is manually deleted. Add ON DELETE CASCADE to the FOREIGN KEY constraint on line 296 to match the documented schema and prevent orphaned records.

Copilot uses AI. Check for mistakes.
@jkordick jkordick merged commit 0f02acf into main Mar 5, 2026
14 checks passed
@jkordick jkordick deleted the copilot/fix-migration-process-logic branch March 5, 2026 15:44
Copilot AI added a commit that referenced this pull request Mar 5, 2026
Co-authored-by: jkordick <52427852+jkordick@users.noreply.github.com>
jkordick added a commit that referenced this pull request Mar 5, 2026
…tion) (#53)

* docs: fill three documentation gaps from PR #45 (BL injection)

Co-authored-by: jkordick <52427852+jkordick@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jkordick <52427852+jkordick@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

reverse-engineered business logic not used in migration/conversion step

3 participants