Skip to content
zit Artifact [0dfa881628]
Login

Artifact [0dfa881628]

Artifact 0dfa88162891adb28511aede7a465ccbc2a4a2f99a4d3e60dacc778e6e099591:


Erratum — draft-fossil-repo-state-00 §8.3

Document draft-fossil-repo-state-00
Section 8.3 — Procedure (trailing-punctuation retry)
Type Technical (the text diverges from Fossil's implemented behavior)
Status Proposed — operator decision pending
Reported 2026-10-11
Submitter Dan Mestas
Found via A three-letter tag that did not resolve with a trailing period; traced to Fossil 2.28 src/name.c and confirmed by running Fossil 2.28

1. Summary

§8.3 says that when no form matches and the name ends in exactly one trailing punctuation character, resolution MUST retry without it. Fossil's rule differs in three ways:

  1. Length. The retry needs a name longer than four characters, so the stem left after stripping is at least four characters. release. is retried; rel. is not.
  2. Which characters. Only seven count: . _ ) > ! ? ,. Others, such as ; and :, never trigger a retry.
  3. Two characters. A name ending in exactly two of those characters is retried with both removed (the name must then be longer than five characters). Three or more trailing characters are never stripped.

This is a deliberate heuristic, not a defect: it targets names lifted from prose or a URL, and the length floor keeps short names from being rewritten.

2. Location

§8.3, the paragraph after the numbered dispatch list. Current text:

If none of the preceding forms match and the name ends in exactly one trailing punctuation character (for example, punctuation incidentally captured when a name is lifted from surrounding prose or a URL), resolution MUST retry recursively with that trailing character stripped.

3. The divergence

Verified against Fossil 2.28 by reading the source and by running it.

3.1 Source

is_trailing_punct() (src/name.c:399) defines the set:

return c=='.' || c=='_' || c==')' || c=='>' || c=='!' || c=='?' || c==',';

The retry is the last step of symbolic_name_to_rid() (src/name.c:704-720):

if( nTag>4
 && is_trailing_punct(zTag[nTag-1])
 && !is_trailing_punct(zTag[nTag-2])
){
  ... symbolic_name_to_rid(<zTag without its last character>, zType);
}else
if( nTag>5
 && is_trailing_punct(zTag[nTag-1])
 && is_trailing_punct(zTag[nTag-2])
 && !is_trailing_punct(zTag[nTag-3])
){
  ... symbolic_name_to_rid(<zTag without its last two characters>, zType);
}

The stripped name goes through the whole procedure again. Its last character is not in the set, so it is never stripped a second time.

3.2 Run

One check-in tagged release, rel and relx; fossil info NAME:

NAME resolves why
release. yes one trailing character, stem of 7
release) yes ) is in the set
release.. yes two trailing characters, both stripped
release... no three trailing characters
release; no ; is not in the set
release: no : is not in the set
relx. yes length 5, stem of 4
relx., yes length 6, two stripped
rel. no length 4 is not more than 4
rel? no same

4. Impact

Observable, minor. An implementation that follows §8.3 resolves rel., release; and release: where Fossil does not, and refuses release.. where Fossil resolves it. The same name can therefore name a check-in in one tool and nothing in the other, and a link pasted from prose behaves differently.

5. Correction

-   If none of the preceding forms match and the name ends in exactly one
-   trailing punctuation character (for example, punctuation incidentally
-   captured when a name is lifted from surrounding prose or a URL),
-   resolution MUST retry recursively with that trailing character
-   stripped.
+   If none of the preceding forms match, the name may carry punctuation
+   incidentally captured when it was lifted from surrounding prose or a
+   URL.  For this rule the trailing punctuation characters are exactly
+   ".", "_", ")", ">", "!", "?" and ",".  If the name is longer than
+   four characters and ends in exactly one of these characters,
+   resolution MUST retry the whole procedure with that character
+   removed.  Otherwise, if the name is longer than five characters and
+   ends in exactly two of these characters, resolution MUST retry with
+   both removed.  A name ending in three or more of these characters,
+   or one too short for either case, MUST NOT be retried.  A stripped
+   name is not stripped again.

6. Rationale

7. Verification


Prepared against draft-fossil-repo-state-00. The RFC remains the oracle; the reference implementation is used only to confirm the observable behavior.