persistent counters between builds

I need to manage a list of requirements, with counters that keeps their values once created. How could I do that ?

Example:

• Step 1: the document is created with two requirements, alpha and beta, that gets numbers 1 and 2 after build:

1 alpha
2 beta

• Step 2: a third requirement is created. Build again:

1 alpha
2 beta
3 gamma

• Step 3: someone wants to add another requirement at the beginning of the doc, but older references must stay the same. So the firth is number four, even if between one and two:

1 alpha
4 delta
2 beta
3 gamma


I think it would require a generated file to remember used references, but I don't know how to achieve this.

• If the generated file is deleted in between or after some time the inserted information gets lost -- Nobody will know that delta was inserted as 4th item later on then. – user31729 Jun 12 '17 at 22:08

You can do this with the etoolbox package, which defines list operations, booleans and string comparison (among other things). The MWE below generates a file stored.txt where the requirements are stored in order of consecutive runs. For a new run, existing items are numbered in the order of this list and new items are added at the end. Note the comment by @Christian Hupfer.

\documentclass{article}
\usepackage{etoolbox}

\newcommand{\persistent}{} % create initially empty list

\newcounter{Current}       % existing position in list
\newcounter{MaxSeq}        % highest position in list
\newtoggle{FoundInList}    % boolean test if item is found

\newcommand{\cmphandler}[2]{%
\stepcounter{Current}%      % increase position in list
\ifstrequal{#1}{#2}%        % if the current item is the item to print
{\toggletrue{FoundInList}\listbreak}{}%    % then set to found and exit loop
}

% write full list to file after adding items

% print the current item in the document
\newcommand{\printpersistent}[1]{%
\setcounter{Current}{0}%
\togglefalse{FoundInList}%
\forlistloop{\cmphandler{#1}}{\persistent}% % find position in list
\iftoggle{FoundInList}%                     % if item is found
{\arabic{Current} #1}%                      % print position and item
{\listgadd{\persistent}{#1}\stepcounter{MaxSeq}\arabic{MaxSeq} #1}%     % else add to end of list and print item
\par                                        % start new paragraph
}

\begin{document}
% load existing list if available
\InputIfFileExists{stored.txt}{}{}

% print all items
\printpersistent{alpha $(\alpha)$}
\printpersistent{delta $(\delta)$}
\printpersistent{beta $(\beta)$}
\printpersistent{gamma $(\gamma)$}

% print full list to file
\newwrite\listfile
\openout\listfile=stored.txt
\forlistloop{\writeall}{\persistent}
\closeout\listfile
\end{document}


Result after three runs: