feat(app-dev): sync error hints, flatEntity labels, dev-mode summary UI, and docs (#21252)

Split out of #21240 — all remaining app-dev improvements. Stacked on
#21251 (review/merge that first).

- Actionable recovery hints on failed syncs; unified diff renderer;
`--dry-run` guard.
- Return `flatEntity` on update/delete sync actions and unify the diff
label.
- Summarize the dev-mode entity list unless `--verbose`.
- Docs: syncing & recovery guide + dry-run + open-an-issue prompt.
- Live execution mode for synced logic functions; clearer manifest
warnings.

<img width="1018" height="700" alt="image"
src="https://github.com/user-attachments/assets/5e9ce19e-0f1d-4f99-8524-4e118bde932b"
/>
This commit is contained in:
martmull
2026-06-08 17:43:28 +02:00
committed by GitHub
parent 13e8e26d1c
commit 77d1e8ced6
34 changed files with 716 additions and 292 deletions
@@ -16,10 +16,12 @@ import { ClientService } from '@/cli/utilities/client/client-service';
import { ConfigService } from '@/cli/utilities/config/config-service';
import { formatSyncActionsSummary } from '@/cli/utilities/dev/orchestrator/steps/format-sync-actions-summary';
import { formatManifestValidationErrors } from '@/cli/utilities/error/format-manifest-validation-errors';
import { getSyncErrorRecoveryHint } from '@/cli/utilities/error/get-sync-error-recovery-hint';
import { serializeError } from '@/cli/utilities/error/serialize-error';
import { FileUploader } from '@/cli/utilities/file/file-uploader';
import { runSafe } from '@/cli/utilities/run-safe';
import { APP_ERROR_CODES, type CommandResult } from '@/cli/types';
import chalk from 'chalk';
export type AppDevOnceOptions = {
appPath: string;
@@ -44,6 +46,15 @@ const reportMetadataChanges = (
}
};
const appendRecoveryHint = (
message: string,
errorMessage: string | undefined,
): string => {
const hint = getSyncErrorRecoveryHint(errorMessage);
return hint ? `${message}\n\n${hint}` : message;
};
const innerAppDevOnce = async (
options: AppDevOnceOptions,
): Promise<CommandResult<AppDevOnceResult>> => {
@@ -95,7 +106,7 @@ const innerAppDevOnce = async (
}
for (const warning of manifestResult.warnings) {
onProgress?.(`${warning}`);
onProgress?.(chalk.yellow(`${warning}`));
}
onProgress?.('Building application files...');
@@ -148,13 +159,13 @@ const innerAppDevOnce = async (
const message = errorEvents
? errorEvents.map((event) => event.message).join('\n')
: `Dry run failed with error: ${serializeError(dryRunResult.error)}`;
: `Dry run failed with error: ${dryRunResult.message ?? 'Unknown error'}`;
return {
success: false,
error: {
code: APP_ERROR_CODES.SYNC_FAILED,
message,
message: appendRecoveryHint(message, dryRunResult.message),
},
};
}
@@ -254,13 +265,13 @@ const innerAppDevOnce = async (
const message = errorEvents
? errorEvents.map((event) => event.message).join('\n')
: `Sync failed with error: ${serializeError(syncResult.error)}`;
: `Sync failed with error: ${syncResult.message ?? 'Unknown error'}`;
return {
success: false,
error: {
code: APP_ERROR_CODES.SYNC_FAILED,
message,
message: appendRecoveryHint(message, syncResult.message),
},
};
}
@@ -2,7 +2,6 @@ import { ApiService } from '@/cli/utilities/api/api-service';
import { readManifestFromFile } from '@/cli/utilities/build/manifest/manifest-reader';
import { ConfigService } from '@/cli/utilities/config/config-service';
import { formatManifestValidationErrors } from '@/cli/utilities/error/format-manifest-validation-errors';
import { serializeError } from '@/cli/utilities/error/serialize-error';
import { runSafe } from '@/cli/utilities/run-safe';
import { APP_ERROR_CODES, type CommandResult } from '@/cli/types';
@@ -40,7 +39,7 @@ const innerAppInstall = async (
const message = errorEvents
? errorEvents.map((event) => event.message).join('\n')
: `Install failed with error: ${serializeError(result.error)}`;
: `Install failed with error: ${result.message ?? 'Unknown error'}`;
return {
success: false,