I don't think that there is an easy way to do what you want. The main issue is that you want to have the list printed at the top of the document, with the list being constructed from commands that come later. This means that you need to write the list to a file and read it back in.
The code below defines two commands:
\PrintList: prints the list from the last time the document was compiled. It accepts an optional argument that becomes the list heading, which is "My list" by default.
\AddToList: adds a comma separated list of entries as a new row to the list.
When given the input:
\PrintList
\AddToList{oranges, yellow, good}
\AddToList{strawberries, red, perfect }
it produces:

(The list uses booktabs.)
The code works by writing the list entries to a file \jobname.dlist, where \jobname is the name of the LaTeX file. This file is read back in the next time the file is compiled, which allows \PrintList to print the list anywhere in the document. This also means that you need to compile the file twice to see any changes to the list.
If all of the \AddToList commands have three items, then the list will have three columns. In general, the number of columns in the list will be the maximum number of items in one of the \AddToList commands.
Here is the code, which uses LaTeX3:
\documentclass{amsart}
\usepackage{booktabs}
\ExplSyntaxOn
% if the .dlist file exists then read it into \g_index_of_notation_tl
\int_new:N \g__dlist_cols_int % maximum number of columns i the list so far
\int_new:N \g__dlist_max_int % maximum number of columns in last from last compile
\tl_new:N \g__dlist_list_tl % holds the list generated last compile
\file_if_exist:nT{\c_sys_jobname_str.dlist}
{
% Read the .dlist file in if it exists. This will set
% \g__dlist_list_tl equal to the list from the last compilation
% and set \g__dlist_max_int equal to the number of columns required
\input {\c_sys_jobname_str.dlist}
}
\AtBeginDocument{
% create a stream to write the new dlist file
\iow_new:N \g__dlist_iow
\iow_open:Nn \g__dlist_iow {\c_sys_jobname_str.dlist}
}
\NewDocumentCommand\PrintList{ O{My~list} }
{
% print the list \g__dlist_list_tl if it is nonempty
\tl_if_empty:NF \g__dlist_list_tl
{
\begin{tabular}{*{\int_use:N\g__dlist_max_int}{ll}}\toprule
\multicolumn{\int_use:N\g__dlist_max_int}{c}{#1}\\\midrule
\g__dlist_list_tl
\bottomrule
\end{tabular}
}
}
\NewDocumentCommand\AddToList{m}
{
% Save the comma separated entries in #1 to the .dlist file as
% \tl_gput_right \g__dlist_list_tl { item1&item2&...&itemN\\ }
% and update \g__dlist_cols_int
\int_zero:N \l_tmpa_int
\tl_set:Nn \l_tmpa_tl {\tl_gput_right:Nn \g__dlist_list_tl}
\tl_put_right:NV \l_tmpa_tl \c_left_brace_str
\clist_map_inline:nn {#1}
{
\int_compare:nNnT {\l_tmpa_int} > 0 {\tl_put_right:Nn \l_tmpa_tl {&}}
\tl_put_right:No \l_tmpa_tl {##1}
\int_incr:N \l_tmpa_int
}
\int_gset:Nn \g__dlist_cols_int {\int_max:nn {\g__dlist_cols_int} {\l_tmpa_int}}
\tl_put_right:Ne \l_tmpa_tl {\c_backslash_str\c_backslash_str\c_right_brace_str}
\iow_now:NV \g__dlist_iow \l_tmpa_tl
}
\cs_generate_variant:Nn \iow_now:Nn {NV}
\AtEndDocument{
\tl_set:Nn \l_tmpa_tl { \int_gset:Nn \g__dlist_max_int }
\tl_put_right:NV \l_tmpa_tl \c_left_brace_str
\tl_put_right:Ne \l_tmpa_tl {\int_use:N\g__dlist_cols_int }
\tl_put_right:NV \l_tmpa_tl \c_right_brace_str
\iow_now:NV \g__dlist_iow \l_tmpa_tl
\iow_close:N \g__dlist_iow
}
\ExplSyntaxOff
\begin{document}
\PrintList
\AddToList{oranges, yellow, good}
\AddToList{strawberries, red, perfect }
\end{document}
\documentclassetc. and content which shows what you'd like\appendRowto do.