Skip to content

Commit 694428c

Browse files
committed
docs(spec): fix adversarial-review findings
Ran /codex:adversarial-review focused on authoring/GUI UX. Verified each finding against the shipped CSL source before deciding what to fix. MEDIUM_DESIGNATOR.md: confirmed access-phrase wasn't actually shared across the three target styles. NLM's "Retrieved from: URL" is itself suppressed for article-journal; Springer uses "URL. Accessed DATE" with no "retrieved" wording; CSE renders a bare URL. A single boolean toggle can't represent three different rules. Dropped access-phrase from the option entirely, narrowing it to the two pieces that are genuinely uniform (the [Internet] marker and the cited-date bracket). Filed the URL/DOI rendering work separately (csl26-e8ul). Also clarified the legal-reference anchor gap is already gated by Acceptance Criteria, not shipped as a known bug. GROUP_SELECT.md: elevated sorting.rs's reduced precision for select: first groups from a documented "known limitation" to a required Acceptance Criterion -- select: first's entire contract is choosing the candidate that actually produces output, so a sort key that can disagree with the rendered value undermines the primitive's own promise, unlike render-when's pre-existing, more tolerable imprecision. Added a note that the two select: first validation rules are semantic, not schema-expressible, so a schema-only GUI needs the real validator too.
1 parent faf18fd commit 694428c

13 files changed

Lines changed: 992 additions & 9 deletions
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
# csl26-57a7
3+
title: Audit TemplateComponent::Group consumers for an Alternatives arm
4+
status: scrapped
5+
type: task
6+
priority: normal
7+
tags:
8+
- engine
9+
- style
10+
- schema
11+
- fidelity
12+
created_at: 2026-09-07T00:42:55Z
13+
updated_at: 2026-09-08T12:49:16Z
14+
parent: csl26-40n4
15+
---
16+
17+
docs/specs/ALTERNATIVES.md (Draft) proposed a new TemplateComponent::Alternatives variant -- since redesigned as select: first, docs/specs/GROUP_SELECT.md. A grep found TemplateComponent::Group matched in 21 files across citum-engine and citum-schema-style -- not just the renderer. Three were checked directly and confirmed to key on specific component kinds (Title, Date(Issued), Number(Volume), Variable(Url/Doi)) for non-rendering purposes:
18+
19+
- crates/citum-engine/src/values/list.rs (is_term_based -- already accounted for in the spec)
20+
- crates/citum-engine/src/processor/rendering/grouped/component_predicates.rs (citation grouping / contributor-stripping)
21+
- crates/citum-engine/src/processor/rendering/grouped/template_policy.rs (article-journal bibliography template filtering, the same file csl26-8z39 extends)
22+
23+
If a title, contributor, date, number, or url/doi variable is wrapped inside an alternatives: candidate, these consumers won't see it structurally, regardless of nesting depth -- restricting nesting does not fix this, since the cause is what a candidate contains, not how deep it sits.
24+
25+
Update 2026-09-07: audit complete for all 18 files. Findings folded into ALTERNATIVES.md v1.1. Most are already safe under the content restriction (key on title/contributor, which v1 already forbids as candidate content) or are compiler-enforced-safe (dispatch_component! in macros.rs is exhaustive, no wildcard). Two real gaps found and closed by widening the restriction / adding requirements in the spec itself: sorting.rs's first_date_component_ref searches any date, not just issued (restriction widened from 'issued date' to 'any date'); helpers.rs's leading_group_affix/strip_leading_group_affixes are kind-independent structural helpers needing their own Alternatives arm regardless of content restriction (added to Implementation Notes/AC). Two low-severity, non-blocking gaps remain, deferred to this bean's remaining scope: lint.rs's collect_template_requirements and api/warnings.rs's unknown-enum-variant scanner both special-case Group but not Alternatives -- tooling completeness, not rendering correctness.
26+
27+
## Todo
28+
- [x] Enumerate the remaining 18 files matching TemplateComponent::Group (grep -rln 'TemplateComponent::Group' crates/citum-engine/src crates/citum-schema-style/src, minus the 3 already checked)
29+
- [x] For each, determine whether it needs an Alternatives arm to remain correct once alternatives: is in general use
30+
- [ ] Add the arm to each file that needs one, with a regression test per file
31+
- [ ] Once complete, lift ALTERNATIVES.md's v1 placement restriction (update Scope/'v1 placement restriction' section, promote to v2)
32+
33+
## Reasons for Scrapping
34+
35+
This bean's entire premise -- `docs/specs/ALTERNATIVES.md` proposing a new `TemplateComponent::Alternatives` variant, requiring an audit of every structural consumer of `TemplateComponent::Group` for a matching `Alternatives` arm -- no longer applies. Design review (PR #1268) found a cleaner shape: `select: first` as a mode on `TemplateGroup` itself, not a new component type. Since a `select: first` group is still `TemplateComponent::Group`, every consumer this bean was going to audit (component_predicates.rs, template_policy.rs, sorting.rs, the affix helpers) already recurses into it with no new arm needed. See docs/specs/GROUP_SELECT.md.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
# csl26-cjen
3+
title: Add Alternatives arm to lint/warning tooling
4+
status: scrapped
5+
type: task
6+
priority: low
7+
tags:
8+
- engine
9+
- schema
10+
- style
11+
created_at: 2026-09-07T12:05:24Z
12+
updated_at: 2026-09-08T12:47:08Z
13+
blocked_by:
14+
- csl26-57a7
15+
---
16+
17+
Once alternatives: ships (docs/specs/ALTERNATIVES.md), two tooling functions still special-case Group but not Alternatives, so a candidate's content is invisible to them: lint.rs's collect_template_requirements (locale-requirement collection for style linting) and api/warnings.rs's scan_template_for_unknowns (unknown-enum-variant warnings). Neither affects rendered output -- found during csl26-57a7's consumer audit, split out because it's tooling completeness, not a rendering-correctness gate on alternatives:'s own Acceptance Criteria.
18+
19+
## Reasons for Scrapping
20+
21+
Same reason as csl26-57a7: this bean assumed a new `TemplateComponent::Alternatives` variant that lint.rs and api/warnings.rs would need their own arm for. The redesigned `select: first` (docs/specs/GROUP_SELECT.md) is a mode on the existing `TemplateComponent::Group`, which both tools already handle generically. No arm needed, nothing to do here.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
# csl26-2hr4
3+
title: Group tracker merges before checking if the group rendered
4+
status: todo
5+
type: bug
6+
priority: high
7+
tags:
8+
- engine
9+
- rendering
10+
- fidelity
11+
created_at: 2026-09-06T23:13:42Z
12+
updated_at: 2026-09-08T12:47:52Z
13+
parent: csl26-8m2p
14+
---
15+
16+
render_group_component_with_format (crates/citum-engine/src/processor/rendering/grouped/core.rs, ~line 1368) clones the tracker for a group's children, then unconditionally calls tracker.merge_from(group_tracker) BEFORE checking whether render_group_child_values actually produced output (the values? empty-check comes after the merge). So an empty/suppressed group's tracker mutations -- variable-once marks, substitution bookkeeping, date-fallback-first-issued flags -- still leak into the parent tracker even though the group rendered nothing.
17+
18+
This is a BLOCKING PREREQUISITE for select: first (docs/specs/GROUP_SELECT.md), not an independent someday investigation. Clone-and-discard at the select: first group's own boundary alone is insufficient -- the merge-before-check happens at EVERY level of nesting inside render_group_component_with_format, so if the WINNING candidate is itself a nested group containing a suppressed sub-group, that sub-group's tracker mutations are already baked into the candidate's own clone before select: first ever gets a say. Merging 'only the winner's' tracker still commits the pollution. select: first cannot be implemented with correct tracker isolation until this ordering is fixed (or explicitly proven safe as-is) -- see docs/specs/GROUP_SELECT.md's Implementation Notes and Acceptance Criteria for the dependency.
19+
20+
Impact on existing group: rendering is unclear -- may be intentional (once a variable is examined it should never be considered again regardless of group suppression) or may be a real bug (a suppressed group's exploratory tracker probing should not count). Needs investigation before deciding whether to fix.
21+
22+
## Todo
23+
- [ ] Determine whether current merge-always behavior is intentional or a bug (check test coverage/git history for render_group_component_with_format's tracker handling)
24+
- [ ] If a bug, fix by moving tracker.merge_from after the values? empty-check (or conditioning it on Some(_))
25+
- [ ] Add a regression test: an empty/suppressed group followed by a component that should still be eligible to render the variable the suppressed group examined
26+
- [ ] Add a regression test matching select: first's forcing case: a winning candidate containing a suppressed/empty nested group, followed by a component that depends on tracker state the nested group must not have touched
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
# csl26-8z39
3+
title: Extend ArticleJournalNoPageFallback to test volume absence (NLM/CSE)
4+
status: todo
5+
type: task
6+
priority: normal
7+
tags:
8+
- style
9+
- engine
10+
- schema
11+
- fidelity
12+
created_at: 2026-09-06T23:14:03Z
13+
updated_at: 2026-09-08T12:48:20Z
14+
parent: csl26-ccdt
15+
---
16+
17+
docs/specs/ARTICLE_JOURNAL_NO_PAGE_FALLBACK.md's ArticleJournalNoPageFallback::Doi currently gates on page absence alone (article_journal_bibliography_mode in crates/citum-engine/src/processor/rendering/grouped/template_policy.rs:76-99, reference_has_pages). T&F-NLM's shipped access macro (styles-legacy/taylor-and-francis-national-library-of-medicine.csl:72-88) gates the same DOI-vs-detail-block choice on page AND volume both being absent (if match="none" variable="page volume"), scoped to article-journal only.
18+
19+
Found while drafting docs/specs/GROUP_SELECT.md (formerly ALTERNATIVES.md): an earlier draft incorrectly proposed generalizing this NLM rule into a select: first group, using the full detail block (including date: issued, which is nearly always present) as the first candidate -- that would never fall through to DOI, so select: first cannot express this rule at all. The correct fix is extending the existing, narrower, already-shipped ArticleJournalNoPageFallback option instead, which already implements exactly this type-gated field-presence shape for RSC's page-only case.
20+
21+
## Todo
22+
- [ ] Extend ArticleJournalNoPageFallback (or add a sibling variant) to test volume absence in addition to/instead of page, matching NLM's match="none" variable="page volume" rule
23+
- [ ] Wire taylor-and-francis-national-library-of-medicine-core.yaml and taylor-and-francis-council-of-science-editors-author-date-core.yaml to use it
24+
- [ ] report-core.js --diff verifying the ~11 T&F-NLM DOI rows flip with 0 regressions
25+
- [ ] Update docs/specs/ARTICLE_JOURNAL_NO_PAGE_FALLBACK.md acceptance criteria
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
# csl26-e8ul
3+
title: Design NLM/springer/CSE access-URL and DOI rendering
4+
status: todo
5+
type: task
6+
priority: normal
7+
tags:
8+
- style
9+
- engine
10+
- schema
11+
- fidelity
12+
created_at: 2026-09-08T13:18:42Z
13+
updated_at: 2026-09-08T13:18:48Z
14+
parent: csl26-ccdt
15+
blocked_by:
16+
- csl26-8z39
17+
---
18+
19+
Split out of docs/specs/MEDIUM_DESIGNATOR.md after an adversarial review found the 'access-phrase' bundle wasn't actually shared across the three target styles. Each style's access macro is genuinely different, verified against the shipped CSL:
20+
21+
- NLM (taylor-and-francis-national-library-of-medicine.csl:72-91): if type=article-journal, DOI-if-no-page-volume (csl26-8z39's scope) else nothing; else-if URL, 'Retrieved from: URL'. The phrase never renders for article-journal.
22+
- Springer (springer-vancouver-brackets.csl:88-107): if DOI, doi.org URL; else-if URL, 'URL. Accessed DATE' -- no 'retrieved' wording, a date inline in this macro (separate from the [cited ...] bracket rendered elsewhere).
23+
- CSE (taylor-and-francis-council-of-science-editors-author-date.csl:48-56): if DOI, doi.org URL; else bare URL. No phrase, no date.
24+
25+
This needs its own per-style design (DOI-preference-over-URL is shared across all three; the phrase/date wording is not), entangled with csl26-8z39's DOI-preference logic for NLM specifically. MEDIUM_DESIGNATOR.md's online-access option now covers only the [Internet] marker and cited-date bracket, which are genuinely uniform.

.beans/csl26-x61x--chicago-volume-issue-and-series-grammar.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@ tags:
99
- chicago
1010
- fidelity
1111
created_at: 2026-08-23T20:40:45Z
12-
updated_at: 2026-08-23T20:40:45Z
12+
updated_at: 2026-09-08T12:49:16Z
1313
parent: csl26-h7oc
1414
---
1515

1616
Leverage class from the 2026-08-23 audit. 136 entries: vol./no./special issue/supplement/pt./ser. grammar around container-title and locator. Related to csl26-vf5x's original container-title-before-volume hypothesis. Touches all four Chicago variants.
17+
18+
## Cross-link (2026-09-06)
19+
20+
Named as the eventual home for `render-when`'s 25 structural-policy ("B-shape") uses -- volume-or-issue / part-number-numeric / part-number-non-numeric gating editor form and container routing. No design exists yet; this is the blocker on removing `render-when`. Evidence and per-field counts in `docs/architecture/audits/2026-09-06_RENDER_WHEN_DISPOSITION.md`.

.beans/csl26-x79y--render-when-field-presentauthor-ignores-editor-sub.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ tags:
1111
- render-when
1212
- fidelity
1313
created_at: 2026-09-02T18:19:10Z
14-
updated_at: 2026-09-02T18:19:14Z
14+
updated_at: 2026-09-08T12:48:29Z
1515
parent: csl26-h7oc
1616
---
1717

@@ -22,3 +22,7 @@ Discovered while fixing csl26-4if2 (render_author_for_grouping_with_format now c
2222
Net effect on chicago-shortened-notes-bibliography's exact-parity corpus: the csl26-4if2 fix is a clear net improvement (roughly 21 items gained vs 3 lost in the visible coverage-audit sample; the style's afterExactParity.passed count moved from 87 to 86, tracked in scripts/report-core.test.js's `generateReport exposes the registered coverage audit on its corresponding style` test), but this is one of the 3 lost items.
2323

2424
Needs a decision: should `condition_field_present`'s Author (and likely Editor/Translator/Recipient) variants check the *effective* (substitution-aware) primary contributor rather than the raw field, or is the literal-field reading the correct, documented semantics and templates author-controlled to gate on it should write field-present:author OR field-absent... explicitly accounting for substitution themselves? Either resolution should re-run report-core.js for chicago-shortened-notes-bibliography and confirm no further regressions.
25+
26+
## Cross-link (2026-09-06)
27+
28+
This is exactly the blind spot `docs/specs/GROUP_SELECT.md` (Draft) is designed to close: `render-when`'s conditions read raw source fields and structurally cannot see substitution results (documented as policy in `RENDER_WHEN_CONTRACT.md`), while a `select: first` group tests actual output. Once `select: first` ships and chicago-shortened-notes-bibliography-core's author+title gate migrates to it, this bug is fixed by construction rather than by a semantics decision on `condition_field_present`. See `docs/architecture/audits/2026-09-06_RENDER_WHEN_DISPOSITION.md`.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
# csl26-zmxt
3+
title: Design work-form routing to replace render-when's structural-policy uses
4+
status: todo
5+
type: task
6+
priority: normal
7+
tags:
8+
- schema
9+
- engine
10+
- style
11+
- chicago
12+
- fidelity
13+
created_at: 2026-09-06T21:58:21Z
14+
updated_at: 2026-09-08T12:48:48Z
15+
parent: csl26-40n4
16+
---
17+
18+
Under csl26-40n4 (Chicago family substrate). The render-when disposition audit (docs/architecture/audits/2026-09-06_RENDER_WHEN_DISPOSITION.md) found 25 of render-when's 125 uses are structural policy gates -- the tested field (volume-or-issue, part-number-numeric, part-number-non-numeric, genre, title) never appears in the branch it guards, meaning it routes an unrelated component (editor form, container title, page prefix) based on a property of the reference. No declarative primitive covers this today; it's why render-when can't be removed, only frozen.
19+
20+
Forcing-case inventory (file:line in the audit's appendix): chicago-author-date-18th.yaml:457/465 (editor form by volume-or-issue), chicago-author-date-18th.yaml:426/489 (title routing by part-number-non-numeric), and the genre/title B-shape uses across chicago-notes-18th.yaml and chicago-shortened-notes-bibliography-core.yaml.
21+
22+
Likely home: docs/specs/INPUT_REFERENCE_CLASS_DISCRIMINATOR.md, or a new work-form concept alongside it. Related to csl26-x61x (Chicago volume/issue/series grammar).
23+
24+
## Todo
25+
- [ ] Enumerate the full 25-use B-shape set with rendered-content diffs (what actually differs between branches)
26+
- [ ] Propose a declarative primitive (option, discriminator, or type-variant axis)
27+
- [ ] Spec in docs/specs/ before implementation
28+
- [ ] Once shipped, migrate render-when's structural-policy uses and deprecate render-when

.beans/csl26-zs9y--style-templates-cant-condition-a-literal-on-url-pr.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ tags:
99
- fidelity
1010
- style
1111
created_at: 2026-09-05T21:24:36Z
12-
updated_at: 2026-09-06T15:27:08Z
12+
updated_at: 2026-09-08T12:48:48Z
1313
parent: csl26-ccdt
1414
---
1515

@@ -42,3 +42,11 @@ a `Url` variant added to `TemplateConditionField` plus wiring
4242
components, or (b) a narrower purpose-built "online-source marker"
4343
component. Scope: engine (`crates/citum-engine`) + schema
4444
(`crates/citum-schema-style`), not style YAML.
45+
46+
## Resolution direction (2026-09-06)
47+
48+
Root cause reclassified: this is not a render-when gap (option (a) above), it's option (b) -- a narrower purpose-built option. Spec drafted at `docs/specs/MEDIUM_DESIGNATOR.md` (Draft): a `BibliographyConfig.online_access` option bundling the title-suffix marker, access-phrase, and cited-date-bracket, gated by URL presence and an excluded-type list. Decided alongside the broader `render-when` disposition question -- see `docs/architecture/audits/2026-09-06_RENDER_WHEN_DISPOSITION.md`.
49+
50+
Confirmed against the shipped .csl: `taylor-and-francis-national-library-of-medicine.csl:133-150` (title macro) and `springer-vancouver-brackets.csl:113-120` (accessed-date macro). Also affects `taylor-and-francis-council-of-science-editors-author-date`. IEEE's analogous "[Online]. Available: URL" pattern (noted above) is a plausible second consumer once this option exists, not part of this spec's acceptance criteria.
51+
52+
Next: spec review, then implementation in a stacked PR.

0 commit comments

Comments
 (0)