@axinom/mosaic-agent-skills 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +121 -0
  2. package/dist/index.d.ts +3 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +58 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/logger.d.ts +6 -0
  7. package/dist/logger.d.ts.map +1 -0
  8. package/dist/logger.js +15 -0
  9. package/dist/logger.js.map +1 -0
  10. package/dist/tools/graphql/index.d.ts +3 -0
  11. package/dist/tools/graphql/index.d.ts.map +1 -0
  12. package/dist/tools/graphql/index.js +84 -0
  13. package/dist/tools/graphql/index.js.map +1 -0
  14. package/dist/tools/graphql/tools.d.ts +71 -0
  15. package/dist/tools/graphql/tools.d.ts.map +1 -0
  16. package/dist/tools/graphql/tools.js +187 -0
  17. package/dist/tools/graphql/tools.js.map +1 -0
  18. package/dist/tools/graphql/utils.d.ts +20 -0
  19. package/dist/tools/graphql/utils.d.ts.map +1 -0
  20. package/dist/tools/graphql/utils.js +140 -0
  21. package/dist/tools/graphql/utils.js.map +1 -0
  22. package/dist/tools/skills/index.d.ts +3 -0
  23. package/dist/tools/skills/index.d.ts.map +1 -0
  24. package/dist/tools/skills/index.js +62 -0
  25. package/dist/tools/skills/index.js.map +1 -0
  26. package/dist/tools/skills/tools.d.ts +5 -0
  27. package/dist/tools/skills/tools.d.ts.map +1 -0
  28. package/dist/tools/skills/tools.js +67 -0
  29. package/dist/tools/skills/tools.js.map +1 -0
  30. package/dist/tools/skills/types.d.ts +12 -0
  31. package/dist/tools/skills/types.d.ts.map +1 -0
  32. package/dist/tools/skills/types.js +3 -0
  33. package/dist/tools/skills/types.js.map +1 -0
  34. package/dist/tools/skills/utils.d.ts +11 -0
  35. package/dist/tools/skills/utils.d.ts.map +1 -0
  36. package/dist/tools/skills/utils.js +127 -0
  37. package/dist/tools/skills/utils.js.map +1 -0
  38. package/package.json +40 -0
  39. package/skills/_shared/actions/execution-summary.md +53 -0
  40. package/skills/_shared/actions/typescript-codegen.md +32 -0
  41. package/skills/_shared/actions/typescript-validation.md +32 -0
  42. package/skills/_shared/conventions/field-component-mapping.md +155 -0
  43. package/skills/_shared/conventions/field-validation-schema.md +77 -0
  44. package/skills/_shared/discovery/discover-paths.md +52 -0
  45. package/skills/_shared/discovery/extract-entity-features.md +565 -0
  46. package/skills/generate-create-station/SKILL.md +93 -0
  47. package/skills/generate-create-station/refs/finalization/station-registration.md +163 -0
  48. package/skills/generate-create-station/refs/templates/create-form-station.md +206 -0
  49. package/skills/generate-create-station/refs/templates/graphql-operations.md +56 -0
  50. package/skills/generate-details-station/SKILL.md +125 -0
  51. package/skills/generate-details-station/refs/finalization/explorer-integration.md +242 -0
  52. package/skills/generate-details-station/refs/finalization/station-registration.md +139 -0
  53. package/skills/generate-details-station/refs/templates/actions.md +127 -0
  54. package/skills/generate-details-station/refs/templates/breadcrumb.md +67 -0
  55. package/skills/generate-details-station/refs/templates/details-form-station.md +589 -0
  56. package/skills/generate-details-station/refs/templates/details-wrapper.md +54 -0
  57. package/skills/generate-details-station/refs/templates/form-data-types.md +62 -0
  58. package/skills/generate-details-station/refs/templates/graphql-operations.md +256 -0
  59. package/skills/generate-details-station/refs/templates/managed-integrations/image-management-station.md +322 -0
  60. package/skills/generate-details-station/refs/templates/managed-integrations/video-management-station.md +283 -0
  61. package/skills/generate-explorer-station/SKILL.md +121 -0
  62. package/skills/generate-explorer-station/refs/finalization/station-registration.md +145 -0
  63. package/skills/generate-explorer-station/refs/select-columns-filters.md +63 -0
  64. package/skills/generate-explorer-station/refs/templates/bulk-edit.md +369 -0
  65. package/skills/generate-explorer-station/refs/templates/common/bulk-actions.md +64 -0
  66. package/skills/generate-explorer-station/refs/templates/common/columns.md +131 -0
  67. package/skills/generate-explorer-station/refs/templates/common/data-provider.md +83 -0
  68. package/skills/generate-explorer-station/refs/templates/common/filters.md +220 -0
  69. package/skills/generate-explorer-station/refs/templates/common/inline-actions.md +45 -0
  70. package/skills/generate-explorer-station/refs/templates/common/types.md +28 -0
  71. package/skills/generate-explorer-station/refs/templates/graphql-operations.md +235 -0
  72. package/skills/generate-explorer-station/refs/templates/navigation-explorer-station.md +144 -0
@@ -0,0 +1,163 @@
1
+ ---
2
+ name: station-registration
3
+ input:
4
+ - EntityFeatures
5
+ - Generated create component
6
+ - DiscoveredPaths
7
+ output:
8
+ - Updated registrations.tsx with create route
9
+ - Updated explorer with onCreateAction (if explorer exists)
10
+ ---
11
+
12
+ # Register Create Station
13
+
14
+ Register create route and optionally integrate with explorer.
15
+
16
+ ## File Path
17
+
18
+ `{workflowsPath}/src/Stations/{EntityPlural}/registrations.tsx`
19
+
20
+ ## Add Import
21
+
22
+ ```typescript
23
+ import { {Entity}Create } from './{Entity}Create/{Entity}Create';
24
+ ```
25
+
26
+ ## Add Route Registration
27
+
28
+ Add inside the `register()` function:
29
+
30
+ ```typescript
31
+ app.registerPage('/{kebabCasePlural}/create', {Entity}Create, {
32
+ breadcrumb: () => 'New {Entity}',
33
+ permissions: { '{features.service.serviceId}': {features.service.permissions} },
34
+ });
35
+ ```
36
+
37
+ ## Update Explorer Component (if exists)
38
+
39
+ **Search for:**
40
+ `{workflowsPath}/src/Stations/{EntityPlural}/{EntityPlural}Explorer/{EntityPlural}.tsx`
41
+
42
+ **If file exists:**
43
+
44
+ 1. Check if `onCreateAction` prop already exists in `NavigationExplorer`
45
+ 2. If prop has TODO comment, replace with actual path
46
+ 3. If prop missing, add it
47
+
48
+ ```typescript
49
+ <NavigationExplorer<{Entity}Data>
50
+ title="{EntityPlural}"
51
+ stationKey="{EntityPlural}Explorer"
52
+ calculateNavigateUrl={(item) => `/{kebabCasePlural}/${item.id}`}
53
+ onCreateAction="/{kebabCasePlural}/create" // <-- Add or update this line
54
+ columns={{entityCamel}Columns}
55
+ // ... rest of props
56
+ />
57
+ ```
58
+
59
+ **If file does not exist:** Skip this step (explorer not yet generated)
60
+
61
+ ## Example
62
+
63
+ ```typescript
64
+ // In registrations.tsx
65
+ import { PiletApi } from '@axinom/mosaic-portal';
66
+ import React from 'react';
67
+ import {
68
+ Extensions,
69
+ ExtensionsContext,
70
+ } from '{discoveredPaths.extensionsContextPath}';
71
+ import { MediaIconName, MediaIcons } from '../../MediaIcons';
72
+ import { Movies } from './MoviesExplorer/Movies';
73
+ import { MovieDetails } from './MovieDetails/MovieDetails';
74
+ import { MovieDetailsCrumb } from './MovieDetails/MovieDetailsCrumb';
75
+ import { MovieCreate } from './MovieCreate/MovieCreate';
76
+
77
+ export function register(app: PiletApi, extensions: Extensions): void {
78
+ const moviesNav = {
79
+ name: 'movies',
80
+ path: '/movies',
81
+ label: 'Movies',
82
+ icon: <MediaIcons icon={MediaIconName.Movie} />,
83
+ };
84
+
85
+ app.registerTile({ ...moviesNav, kind: 'home', type: 'large' }, false);
86
+ app.registerNavigationItem({ ...moviesNav, categoryName: 'Content' });
87
+
88
+ // Explorer route
89
+ app.registerPage(
90
+ '/movies',
91
+ () => (
92
+ <ExtensionsContext.Provider value={extensions}>
93
+ <Movies />
94
+ </ExtensionsContext.Provider>
95
+ ),
96
+ {
97
+ breadcrumb: () => 'Movies',
98
+ permissions: { 'media-service': ['ADMIN', 'MOVIES_EDIT', 'MOVIES_VIEW'] },
99
+ },
100
+ );
101
+
102
+ // Create route
103
+ app.registerPage('/movies/create', MovieCreate, {
104
+ breadcrumb: () => 'New Movie',
105
+ permissions: { 'media-service': ['ADMIN', 'MOVIES_EDIT'] },
106
+ });
107
+
108
+ // Details route
109
+ app.registerPage(
110
+ '/movies/:movieId',
111
+ () => (
112
+ <ExtensionsContext.Provider value={extensions}>
113
+ <MovieDetails />
114
+ </ExtensionsContext.Provider>
115
+ ),
116
+ {
117
+ breadcrumb: MovieDetailsCrumb,
118
+ permissions: { 'media-service': ['ADMIN', 'MOVIES_EDIT', 'MOVIES_VIEW'] },
119
+ },
120
+ );
121
+ }
122
+ ```
123
+
124
+ ```typescript
125
+ // In MoviesExplorer/Movies.tsx
126
+ import { NavigationExplorer } from '@axinom/mosaic-ui';
127
+ import React from 'react';
128
+ import { useMoviesBulkActions } from './common/Movies.bulkActions';
129
+ import { moviesColumns } from './common/Movies.columns';
130
+ import { createMoviesDataProvider } from './common/Movies.dataProvider';
131
+ import { useMoviesFilters } from './common/Movies.filters';
132
+ import { useMoviesInlineActions } from './common/Movies.inlineActions';
133
+ import { MovieData } from './common/Movies.types';
134
+
135
+ export const Movies: React.FC = () => {
136
+ const { transformFilters, filterOptions } = useMoviesFilters();
137
+ const { bulkActions } = useMoviesBulkActions();
138
+ const { generateInlineMenuActions } = useMoviesInlineActions();
139
+ const dataProvider = createMoviesDataProvider(transformFilters);
140
+
141
+ return (
142
+ <NavigationExplorer<MovieData>
143
+ title="Movies"
144
+ stationKey="MoviesExplorer"
145
+ calculateNavigateUrl={(item) => `/movies/${item.id}`}
146
+ onCreateAction="/movies/create" // <-- Integrated
147
+ columns={moviesColumns}
148
+ dataProvider={dataProvider}
149
+ filterOptions={filterOptions}
150
+ defaultSortOrder={{ column: 'updatedDate', direction: 'desc' }}
151
+ inlineMenuActions={generateInlineMenuActions}
152
+ bulkActions={bulkActions}
153
+ quickEditRegistrations={[]}
154
+ />
155
+ );
156
+ };
157
+ ```
158
+
159
+ ## Notes
160
+
161
+ - Create route uses same permissions as explorer (with `EDIT` capabilities)
162
+ - Route path: `/{kebabCasePlural}/create`
163
+ - Breadcrumb: Simple function returning `'New {Entity}'`
@@ -0,0 +1,206 @@
1
+ ---
2
+ name: create-form-station
3
+ input:
4
+ - EntityFeatures
5
+ - DiscoveredPaths
6
+ - Reference: field-component-mapping
7
+ - Reference: field-validation-schema
8
+ output:
9
+ - path: '{workflowsPath}/src/Stations/{EntityPlural}/{Entity}Create/{Entity}Create.tsx'
10
+ description:
11
+ 'Create component with form, validation, mutation, navigation, breadcrumb'
12
+ ---
13
+
14
+ # Generate Create Form Station
15
+
16
+ Create station with `@axinom/mosaic-ui` Create component, mutation, and
17
+ navigation.
18
+
19
+ ## Template
20
+
21
+ ```typescript
22
+ import { BreadcrumbResolver } from '@axinom/mosaic-portal';
23
+ import {
24
+ ActionHandler,
25
+ Create,
26
+ Nullable,
27
+ // Import components based on field types (see field-component-mapping)
28
+ SingleLineTextField,
29
+ DateTimeTextField,
30
+ SelectField,
31
+ CheckboxField,
32
+ // ... other components as needed
33
+ } from '@axinom/mosaic-ui';
34
+ import { Field } from 'formik';
35
+ import { ObjectSchemaDefinition } from 'ObjectSchemaDefinition';
36
+ import React, { useCallback } from 'react';
37
+ import { useHistory } from 'react-router-dom';
38
+ import * as Yup from 'yup';
39
+ import { client } from '{discoveredPath}/apolloClient';
40
+ import {
41
+ Create{Entity}Mutation,
42
+ Create{Entity}MutationVariables,
43
+ useCreate{Entity}Mutation,
44
+ } from '../../../generated/graphql';
45
+
46
+ type FormData = Create{Entity}MutationVariables['input']['{entityCamel}'];
47
+
48
+ type SubmitResponse = Nullable<Create{Entity}Mutation['create{Entity}']>;
49
+
50
+ const {entityCamel}CreateSchema = Yup.object<ObjectSchemaDefinition<FormData>>({
51
+ // Generate validation for REQUIRED fields only from features.schema.input
52
+ // Use field-validation-schema patterns based on field.type
53
+
54
+ {titleField}: Yup.string().required('{TitleLabel} is a required field').max({maxLength}),
55
+ // ... other required fields only
56
+ });
57
+
58
+ export const {Entity}Create: React.FC = () => {
59
+ const [create{Entity}] = useCreate{Entity}Mutation({
60
+ client: client,
61
+ fetchPolicy: 'no-cache',
62
+ });
63
+
64
+ const saveData = useCallback(
65
+ async (formData: FormData): Promise<SubmitResponse> => {
66
+ return (
67
+ await create{Entity}({
68
+ variables: {
69
+ input: {
70
+ {entityCamel}: {
71
+ // Map REQUIRED fields from formData to mutation input
72
+ // Use field-component-mapping for type conversions (Number() for Int/Float)
73
+ {titleField}: formData.{titleField},
74
+ // ... other required fields
75
+ },
76
+ },
77
+ },
78
+ })
79
+ ).data?.create{Entity};
80
+ },
81
+ [create{Entity}],
82
+ );
83
+
84
+ const history = useHistory();
85
+ const onProceed = useCallback<ActionHandler<FormData, SubmitResponse>>(
86
+ ({ submitResponse }) => {
87
+ if (submitResponse?.{entityCamel}) {
88
+ // If Details station exists:
89
+ history.push(`/{kebabCasePlural}/${submitResponse?.{entityCamel}.id}`);
90
+ // If Details station does not exist:
91
+ // TODO: Update navigation once Details station is created
92
+ // history.push('/{kebabCasePlural}');
93
+ } else {
94
+ // The schema has the response.data properties marked as optional, since theoretically a user could have
95
+ // permissions to mutate but not to read. In practice this can not happen on that service, so we just throw
96
+ // an error in case we get there.
97
+ throw new Error('Not expected');
98
+ }
99
+ },
100
+ [history],
101
+ );
102
+
103
+ return (
104
+ <Create<FormData, SubmitResponse>
105
+ title="New {Entity}"
106
+ subtitle="Add new {entityCamel} metadata"
107
+ validationSchema={{entityCamel}CreateSchema}
108
+ saveData={saveData}
109
+ onProceed={onProceed}
110
+ cancelNavigationUrl="/{kebabCasePlural}" // Navigate to explorer (if explorer doesn't exist, add TODO)
111
+ initialData={{
112
+ loading: false,
113
+ }}
114
+ >
115
+ {/* Generate Field for each REQUIRED field in features.schema.input where field.isRequired === true */}
116
+ {/* Use field-component-mapping to select component based on field.type */}
117
+ <Field name="{titleField}" label="{TitleLabel}" as={SingleLineTextField} />
118
+ {/* ... other required fields */}
119
+ </Create>
120
+ );
121
+ };
122
+
123
+ export const {Entity}CreateCrumb: BreadcrumbResolver = () => 'Create';
124
+ ```
125
+
126
+ ## Example
127
+
128
+ ```typescript
129
+ import { BreadcrumbResolver } from '@axinom/mosaic-portal';
130
+ import { ActionHandler, Create, SingleLineTextField } from '@axinom/mosaic-ui';
131
+ import { Field } from 'formik';
132
+ import { ObjectSchemaDefinition } from 'ObjectSchemaDefinition';
133
+ import React, { useCallback } from 'react';
134
+ import { useHistory } from 'react-router-dom';
135
+ import * as Yup from 'yup';
136
+ import { client } from '../../../apolloClient';
137
+ import {
138
+ CreateMovieMutation,
139
+ CreateMovieMutationVariables,
140
+ useCreateMovieMutation,
141
+ } from '../../../generated/graphql';
142
+
143
+ type FormData = CreateMovieMutationVariables['input']['movie'];
144
+ type SubmitResponse = CreateMovieMutation['createMovie'];
145
+
146
+ const movieCreateSchema = Yup.object().shape<ObjectSchemaDefinition<FormData>>({
147
+ title: Yup.string().required('Title is a required field').max(100),
148
+ });
149
+
150
+ export const MovieCreate: React.FC = () => {
151
+ const [movieCreate] = useCreateMovieMutation({
152
+ client: client,
153
+ fetchPolicy: 'no-cache',
154
+ });
155
+
156
+ const saveData = useCallback(
157
+ async (formData: FormData): Promise<SubmitResponse> => {
158
+ return (
159
+ await movieCreate({
160
+ variables: { input: { movie: { title: formData.title } } },
161
+ })
162
+ ).data?.createMovie;
163
+ },
164
+ [movieCreate],
165
+ );
166
+
167
+ const history = useHistory();
168
+ const onProceed = useCallback<ActionHandler<FormData, SubmitResponse>>(
169
+ ({ submitResponse }) => {
170
+ if (submitResponse?.movie) {
171
+ history.push(`/movies/${submitResponse.movie.id}`);
172
+ } else {
173
+ throw new Error('Not expected');
174
+ }
175
+ },
176
+ [history],
177
+ );
178
+
179
+ return (
180
+ <Create<FormData, SubmitResponse>
181
+ title="New Movie"
182
+ subtitle="Add new movie metadata"
183
+ validationSchema={movieCreateSchema}
184
+ saveData={saveData}
185
+ onProceed={onProceed}
186
+ cancelNavigationUrl="/movies"
187
+ initialData={{ loading: false }}
188
+ >
189
+ <Field name="title" label="Title" as={SingleLineTextField} />
190
+ </Create>
191
+ );
192
+ };
193
+
194
+ export const MovieCreateCrumb: BreadcrumbResolver = () => 'Create';
195
+ ```
196
+
197
+ ## Notes
198
+
199
+ - **Navigation after success (`onProceed`):**
200
+ - If Details station exists: Navigate to `/{kebabCasePlural}/${id}`
201
+ - If Details station does not exist: Keep commented fallback with TODO,
202
+ navigate to `/{kebabCasePlural}/${id}` (will be updated when Details is built)
203
+ - **Cancel navigation (`cancelNavigationUrl`):**
204
+ - If Explorer station exists: Navigate to `/{kebabCasePlural}`
205
+ - If Explorer station does not exist: ADD TODO comment above the prop
206
+ - **Only required fields** - no optional fields in create station
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: graphql-operations
3
+ input:
4
+ - EntityFeatures
5
+ output:
6
+ - path: '{workflowsPath}/src/Stations/{EntityPlural}/{Entity}Create/{Entity}Create.graphql'
7
+ description: 'Create mutation returning id and title'
8
+ ---
9
+
10
+ # Generate GraphQL File
11
+
12
+ Single file with create mutation.
13
+
14
+ ## Template
15
+
16
+ ```graphql
17
+ mutation Create{features.name}($input: Create{features.name}Input!) {
18
+ create{features.name}(input: $input) {
19
+ {features.camelCase} {
20
+ id
21
+ {features.titleField}
22
+ }
23
+ }
24
+ }
25
+ ```
26
+
27
+ ## Pattern
28
+
29
+ - Mutation name: `Create{Entity}`
30
+ - Input type: `Create{Entity}Input!` (standard PostGraphile pattern)
31
+ - Return payload path: `create{Entity}.{entityCamel}`
32
+ - Return fields: `id`
33
+
34
+ ## Example
35
+
36
+ ```graphql
37
+ mutation CreateMovie($input: CreateMovieInput!) {
38
+ createMovie(input: $input) {
39
+ movie {
40
+ id
41
+ title
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ ```graphql
48
+ mutation CreateCollection($input: CreateCollectionInput!) {
49
+ createCollection(input: $input) {
50
+ collection {
51
+ id
52
+ title
53
+ }
54
+ }
55
+ }
56
+ ```
@@ -0,0 +1,125 @@
1
+ ---
2
+ name: generate-details-station
3
+ description: |
4
+ Generates a Details station for a Mosaic entity from scratch using
5
+ components from the `@axinom/mosaic-ui` library and GraphQL schema
6
+ introspection.
7
+
8
+ This skill is SELF-CONTAINED with all conventions, naming patterns, code
9
+ structures, and templates defined in its `references`. The skill's templates
10
+ and conventions are the AUTHORITATIVE source - rely on them as the primary
11
+ guide for all generation decisions.
12
+
13
+ use the `get_skill_references` to retrieve ALL reference
14
+ files mentioned in the steps below BEFORE starting any code generation.
15
+ allowed-tools:
16
+ - search_schema
17
+ - get_type_definitions
18
+ - get_query_fields
19
+ - get_mutation_fields
20
+ - get_subscription_fields
21
+ - list_skills
22
+ - get_skill
23
+ - get_skill_references
24
+ - execute_skill
25
+ ---
26
+
27
+ # Generate Details Station
28
+
29
+ ## Input
30
+
31
+ **Entity name** (PascalCase): e.g., "Movie", "Product", "ServiceAccount"
32
+
33
+ ## Output
34
+
35
+ Complete details station with:
36
+
37
+ - Details form with query, mutations, field rendering, info panel
38
+ - URL parameter wrapper component
39
+ - Actions hook (delete, navigate to child resources)
40
+ - Breadcrumb resolver
41
+ - Optional image management station (if entity has image capability)
42
+ - Optional video management station (if entity has video capability)
43
+ - Quick edit integration with explorer
44
+ - Route registration
45
+
46
+ ## Steps
47
+
48
+ ### 1. Discover Project Paths → `../_shared/discovery/discover-paths.md`
49
+
50
+ Discover: schema path, apollo client, generated types path, workflows path,
51
+ service name
52
+
53
+ ### 2. Extract Entity Features → `../_shared/discovery/extract-entity-features.md`
54
+
55
+ Extract `EntityFeatures` from schema using MCP tools (fields, associations,
56
+ capabilities, mutations)
57
+
58
+ ### 3. Generate GraphQL Operations → `refs/templates/graphql-operations.md`
59
+
60
+ Generate `.graphql` file with entity query, update/delete mutations, search
61
+ queries for autocomplete
62
+
63
+ ### 4. Run Codegen → `../_shared/actions/typescript-codegen.md`
64
+
65
+ Generate TypeScript types from GraphQL operations
66
+
67
+ ### 5. Generate Form Data Types → `refs/templates/form-data-types.md`
68
+
69
+ Generate form data type extending GraphQL update patch with transformed
70
+ association arrays
71
+
72
+ ### 6. Generate Actions Hook → `refs/templates/actions.md`
73
+
74
+ Generate actions hook with delete mutation and navigation to child resources
75
+
76
+ ### 7. Generate Details Form
77
+
78
+ #### 7.1. Read Field Component Mapping → `../_shared/conventions/field-component-mapping.md`
79
+
80
+ Reference for component selection rules (String → TextField, Boolean → Checkbox,
81
+ etc.)
82
+
83
+ #### 7.2. Read Field Validation Schema → `../_shared/conventions/field-validation-schema.md`
84
+
85
+ Reference for Yup validation patterns (required, length, format, etc.)
86
+
87
+ #### 7.3. Generate Form Component → `refs/templates/details-form-station.md`
88
+
89
+ Generate main `{Entity}DetailsForm.tsx` with query, mutations, field rendering,
90
+ info panel
91
+
92
+ ### 8. Generate Details Wrapper → `refs/templates/details-wrapper.md`
93
+
94
+ Generate `{Entity}Details.tsx` wrapper that extracts URL params and delegates to
95
+ form
96
+
97
+ ### 9. Generate Breadcrumb → `refs/templates/breadcrumb.md`
98
+
99
+ Generate async breadcrumb resolver for entity title
100
+
101
+ ### 10. Generate Image Management → `refs/templates/managed-integrations/image-management-station.md`
102
+
103
+ Generate image management station
104
+
105
+ ### 11. Generate Video Management → `refs/templates/managed-integrations/video-management-station.md`
106
+
107
+ Generate video management station
108
+
109
+ ### 12. Integrate with Explorer → `refs/finalization/explorer-integration.md`
110
+
111
+ Integrate details station with explorer: quick edit components, inline actions,
112
+ and navigation URLs
113
+
114
+ ### 13. Validate TypeScript → `../_shared/actions/typescript-validation.md`
115
+
116
+ Run `tsc --noEmit` to verify all generated files compile successfully
117
+
118
+ ### 14. Register Station → `refs/finalization/station-registration.md`
119
+
120
+ Register details routes, image/video routes, and breadcrumbs in
121
+ registrations.tsx
122
+
123
+ ### 15. Print Summary → `../_shared/actions/execution-summary.md`
124
+
125
+ Display execution summary with generated files, configuration, routes, TODOs