Well, for anyone who may be interested, I rolled my own using the perl script below, annotate-parano.pl.
In my particular case, I got the list of paragraph/line numbers from a modified parano.sty that uses newfile. The relevant portion is:
\everypar{\addtostream{@parano}{\arabic{parano} \parano@sourceline}}
where \parano@sourceline is modified from this answer:
\ifnum\inputlineno=\m@ne
\let\parano@sourceline\@empty
\else
\def\parano@sourceline{\the\inputlineno}
\fi
I have read that modifying \everypar can be dicey in LaTeX, but it's working OK in my use case.
In my document class, I use
\RequirePackage[map]{parano}
followed, later on, by \parano.
Source follows.
Source of annotate-parano.pl
#!/usr/bin/perl -s
# annotate-parano.pl: Copyright (c) 2017 cxw. CC-BY 4.0.
# Usage: annotate-parano.pl -m=linemap.txt <file(s)>
# Produces output on stdin. Line numbers are continuous over any files listed.
# linemap.txt should have one line per marker to be added, with two fields:
# paragraph number and line number.
use v5.10;
# Load the deltas from the given marker file
my @deltas;
my @markers;
my $prevline = 1; # last line number at which a marker was added
open(my $marker_fd, $m) || die "Can't open marker file $m";
while(<$marker_fd>) {
my ($parano, $lineno)=split;
push @deltas, $lineno-$prevline;
$prevline = $lineno;
push @markers, "%\@$parano"; # or whatever marker format you want
} #foreach marker
# Mark the provided input
my $lastmarkedline = 1; # anchor for the deltas. 1 is like $prevline.
my $marker_idx = 0;
while(<>) {
if( ($marker_idx <= $#deltas) &&
( ($.-$lastmarkedline) == $deltas[$marker_idx] ) ) { # time to mark
say $markers[$marker_idx];
$lastmarkedline=$.;
++$marker_idx;
}
print;
} #foreach input line
Source of parano.sty
% parano.sty, modified by cxw.
% Changes Copyright (c) 2013--2017 cxw.
%%
%% The original source files were:
%% parano.dtx (with options: `package')
%%
%% File: parano.dtx Copyright (c) 2003, CV Radhakrishnan
%% River Valley Technologies, Trivandrum, India
%% <cvr@river-valley.org>
%%
%% This package may be distributed under the terms of the LaTeX Project
%% Public License, as described in lppl.txt in the base LaTeX distribution.
%% either version 1.0 or, at your option, any later version.
%%
%% $Id: parano.sty,v 1.3 2003/06/14 19:20:42 cvr Exp cvr $
%%
%%
%% Usage of the commands provided:
%%
%% \parano ==> starts para numbering
%% \parano[<number>] ==> starts the next para with number <number>
%% \endparano ==> stops para numbering
%% \prepara ==> redefine to add material that needs to appear
%% before the para number. default is null
%% \postpara ==> redefine to append material to para number.
%% default is null
%% \paranoboxwidth ==> width of paranumber box, default 2em
%%
%%
\NeedsTeXFormat{LaTeX2e}
\def\Fileversion$#1: #2 ${\gdef\fileversion{#2}}
\def\Filedate$#1: #2 #3 ${\gdef\filedate{#2}}
\Fileversion$Revision: 1.3-cw $
\Filedate$Date: 2015/06/08 00:00:00 $
\ProvidesPackage{parano}
[\filedate\space\fileversion\space Paranumber support (CVR) (CW)]
\PackageWarningNoLine{parano}
{****************************************\MessageBreak
Package parano v,\fileversion\space loaded\MessageBreak
****************************************}
% Get the current source line number. Modified from
% https://tex.stackexchange.com/a/81794/38377 by
% https://tex.stackexchange.com/users/3954/gonzalo-medina
\ifnum\inputlineno=\m@ne
\let\parano@sourceline\@empty
\else
\def\parano@sourceline{\the\inputlineno}
\fi
% Map file: if the "map" option is provided, print the line numbers and
% para numbers to a map file
\newif\if@parano@makemapfile\@parano@makemapfilefalse
\def\parano@saveline{}
\DeclareOption{map}{
\@parano@makemapfiletrue
}
\ProcessOptions\relax
\if@parano@makemapfile
\RequirePackage{newfile}
% Make the map file. Thanks to https://tex.stackexchange.com/a/10922/38377
% by https://tex.stackexchange.com/users/2674/leo-liu
\typeout{Logging paragraph numbers and line numbers to \jobname.paramap}
\newoutputstream{@parano}
\openoutputfile{\jobname.paramap}{@parano}
\def\parano@saveline{%
\addtostream{@parano}{\arabic{parano} \parano@sourceline}%
}
\fi
\newcounter{parano}
%\@addtoreset{parano}{section}
\def\prepara{}
\def\postpara{}
\newdimen\paranoboxwidth
\paranoboxwidth=3em\relax
\newdimen\parwidth
\renewcommand\theparano{\thesection.\arabic{parano}}
\newif\ifparano\paranofalse
\def\parano{\global\paranotrue\@ifnextchar[{\@@parano}{\@parano}}
\AtBeginDocument{\parwidth\parindent}
\long\def\@parano{%%
%\typeout{PARINDENT = \the\parindent----PARWIDTH = \the\parwidth}
\everypar{\parindent0pt\refstepcounter{parano}%
\parano@saveline
\hbox to \paranoboxwidth{\prepara\theparano\hfill}\postpara}}
\long\def\@@parano[#1]{%
\setcounter{parano}{#1}%
\addtocounter{parano}{-1}%
\everypar{\parindent0pt%
\refstepcounter{parano}%
\hbox to \paranoboxwidth{\prepara\theparano\hfill}\postpara}}
\def\endparano{\everypar{\parindent\parwidth}
\global\paranofalse%
\parindent\parwidth%
%\typeout{PARINDENT = \the\parindent::::PARWIDTH = \the\parwidth}
}
\def\@xsect#1{%
\@tempskipa #1\relax
\ifdim \@tempskipa>\z@
\par \nobreak
\vskip \@tempskipa
\@afterheading
\else
\@nobreakfalse
\global\@noskipsectrue
\everypar{%
\if@noskipsec
\global\@noskipsecfalse
{\setbox\z@\lastbox}%
\clubpenalty\@M
\begingroup \@svsechd \endgroup
\unskip
\@tempskipa #1\relax
\hskip -\@tempskipa
\else
\clubpenalty \@clubpenalty
\everypar{}%
\fi}%
\fi
\ifparano\@parano\fi\ignorespaces}
\def\@startsection#1#2#3#4#5#6{\everypar{}%
\if@noskipsec \leavevmode \fi
\par
\@tempskipa #4\relax
\@afterindenttrue
\ifdim \@tempskipa <\z@
\@tempskipa -\@tempskipa \@afterindentfalse
\fi
\everypar{}%
\addpenalty\@secpenalty\addvspace{\@tempskipa}
\@ifstar
{\@ssect{#3}{#4}{#5}{#6}}%
{\@dblarg{\@sect{#1}{#2}{#3}{#4}{#5}{#6}}}}
%%
%% End of file 'parano.sty'
%%