Repository navigation
Description
Admission class
Extension
Requesting actor / evidence owner
Consumer owner / affected-surface owner
@darioaschero (nuri-expo send journey: the Lightning invoice review)
Request summary and current state
Amended 2026-11-10 after the independent review (#242 (comment)), following its claims, risks and recommendations; each requester choice below says how. In short:
- the real failure past the budget is stated, and "short" gets a measurable budget (a third of the line on iPhone SE at default size);
- a suffix and an end text on the same row are out of the contract;
- the order rule is worded for
textEnd, with tests for the wrong orders;- the plan gains a long end text, font scaling on iOS and Android, and a no-
growtest;- the snapshot change, the recipe header, the "expiry as its own row" alternative and the nuri-expo commit are recorded.
The admission decision itself is not recorded here; it is @darioaschero's, in an architect-owned comment.
This is the later additive request named in the #240 decision record (#240 (comment), anti-scope: "no end-of-line text (textEnd) in v1").
Evidence at main@c69488b (PR #241, merged 2026-11-10): list-item.ts · operation.html board 9, L833-837.
-
Current surface.
list-item(DS admission: list-item, the read-only list row #240, implemented in feat: ListItem, the read-only row of the List family — implements nuri-com/nuri-design-system#240 #241) has three slots:textMuted(the label),text(the value, required) andtextSuffix.textandtextSuffixshare the value's line (line, gapxs).- The suffix sits 3 after the value and never shrinks.
- There is no way to set a text at the end of the value's line.
-
The need. On the Lightning invoice review (
operation.htmlboard 9), the operator wants the expiry aligned right, on the value's line:Lightning invoice lnbc47…k3pz Expires in 9:41The operator showed this on 9 Nov with a screenshot of board 9, and asked for it again on 10 Nov: "puoi correggere Lightning invoice / lnbc47…k3pz / Expires in 9:41 con Expires in 9:41 allineato a destra".
-
Why it was left out of v1. On 9 Nov the operator made it conditional ("se rende tutto piu complicato no"). The independent review of DS admission: list-item, the read-only list row #240 then showed that the first design (
textEndwithfill: 'grow'andalign: 'end') was unsafe:growisflex: 1 0 auto, so the end text cannot truncate;- on web, a long end text collapsed the value to 0 px;
- Android measures a
flexGrowText at the full available width (packages/spec/components/select-trigger.ts:50-51,packages/spec/axes/resolve-map.ts:102-104).
-
Why now. feat: ListItem, the read-only row of the List family — implements nuri-com/nuri-design-system#240 #241 implements v1, and board 9 is the one row that still differs from the operator's design.
Proposed contract delta (not admitted)
Proposed public/observable delta. list-item gains one optional, singular text slot, textEnd (choice 3). Its text sits at the end of the value's line and never shrinks within its budget (choice 1). To get there without flexGrow on a text, the value's line splits into two internal groups:
// packages/spec/components/list-item.ts · proposed, not admitted (the changed parts only)
anatomy: … content: { el: 'view', parts: {
textMuted: { el: 'text' },
line: { el: 'view', parts: {
lead: { el: 'view', parts: { text: { el: 'text' }, textSuffix: { el: 'text' } } }, // NEW internal group
textEnd: { el: 'text' }, // NEW slot part
} },
} },
base: {
// the two groups go to the two ends; with no textEnd, lead sits at the start as today
line: { stack: { direction: 'row', align: 'center', justify: 'between', gap: 'md' } }, // at least 12 between the groups (choice 2)
lead: { stack: { direction: 'row', align: 'center', gap: 'xs', fill: 'shrink' } }, // the value group gives way (choice 1)
text: …unchanged (fill 'shrink', md emphasis, truncate),
textSuffix: …unchanged (fill 'hug', md muted),
textEnd: { stack: { fill: 'hug' }, typography: { size: 'md', align: 'end', flow: 'truncate', lines: 1 }, palette: { muted: true } }, // never shrinks (choice 1)
},
api: { slots: { …, textEnd: { part: 'textEnd', kind: 'text', component: true } } },Public names: RN ListItemTextEnd, web nuri-list-item-text-end.
How it behaves:
-
Placement. With
justify: 'between', the value group stays at the start and the end text goes to the right edge. No text part on the value's line grows (textandleadshrink,textSuffixandtextEndhug), so the AndroidflexGrowmeasurement does not arise. A test pins this. -
Rows without an end text. They look the same: the review measured identical boxes on web and RN-web, with short and long values. But every
list-itemrow's tree gains theleadview, andlinegainsgap: 'md'andjustify: 'between', so everylist-itemsnapshot moves. That rows are unchanged is proven by geometry probes, not by snapshots. -
Order. "End" holds only when
textEndis written after the value. The classifier places a group at its first-authored member (packages/spec/composition/classify.js:67-76), so:- written first on the value's line, the end text draws at the start and the value at the right edge;
- written before the label, it also moves the value's line above the label;
- written between the value and the suffix, the suffix still joins the value (the group wins).
The docs say: write it last, after the value and the suffix. Tests on both render paths pin the right order and the two wrong ones, so the behaviour is documented, not accidental.
-
Truncation, and the budget.
- The end text never shrinks, and the value gives way first.
hugcaps the end text at the line's width (max-inline-size: 100%,packages/prototype/styles/stack.css:47;maxWidth: '100%',packages/rn/runtime/resolve.ts:102-105).- Past its budget, it fails. The value goes to 0, and the end text runs 12 past the content edge into the row's side padding, because
leadplus the 12 gap cannot go below 12. - The budget: the end text fits in a third of the line on iPhone SE at default text size, that is at most 113 px. "Expires in 9:41" is 105.
-
Combinations. A suffix and an end text on the same row are out of the contract (choice 1). No row uses both, and with both, an amount is the first thing lost under large system text sizes.
-
Style. The end text is
md, muted and regular, like the suffix.- On RN,
hugaddsalignSelf: 'flex-start', while web sets none. In the centredline, the end text sits at the top on RN and centred on web. - With equal
mdline heights the two are identical, as they are for the suffix today. Any later size or emphasis option for the end text must handle this.
- On RN,
Affected:
- the
list-itemdescriptor (one slot, one internal group); - the generated RN component and web twin;
- every
list-itemsnapshot, which gains theleadview and thelinestyle; - the header comment of
packages/prototype/recipes/list-item.js, which lists the slots; - the type-tests;
- the doc page;
- the playground component page;
- board 9 of
operation.html.
No other component, token, axis or schema change.
Anti-scope (proposed):
- no end text over its budget: wider than a third of the line on iPhone SE at default size (choice 1);
- no suffix and end text on the same row (choice 1);
- no emphasis or size variant of the end text. nuri-expo's swap From/To puts its end figure in emphasis (
nuri-expo@5c818c8b:components/ActivityDetailSheet.tsx:169-173), and it stays uncovered; - no
growon any part of the value's line, pinned by a test; - no end text on the label's line;
- no icon or badge at the end;
- no change to
textSuffixor to the 60 / 73 geometry; - everything in DS admission: list-item, the read-only list row #240's anti-scope still holds.
Requester choices (10 Nov, amended after the independent review)
These are the requester's choices for the proposed contract. They are not an admission. Each one notes how the review's recommendation was followed.
1 · The end text never shrinks; the value group gives way. The operator chose this. The review says: keep, with conditions; they are followed.
-
The operator: "text end non si accorcia viene usato per casi particolari come l'expire in dove questo suffisso e' importante".
-
When the line is too long,
leadshrinks andtextEndhugs. Insidelead, the value truncates first. -
The failure past the budget, as the review measured it:
- the value and then the suffix go to 0;
- the end text runs 12 past the content edge.
It is stated in the contract, and the budget is measurable: a third of the line on iPhone SE at default size.
-
The suffix-plus-end-text combination is out of the contract. It has no consumer, and it is where an amount disappears under large system text sizes. The review's RN-web emulation erases the value from ×2.5.
-
The cost accepted with the expiry whole. On board 9's invoice row, which has no suffix, large system text sizes truncate the identifier: the review emulated 125 of 195 px at ×2, and 28 of 290 at ×3. The device runs in the plan measure this on iOS and Android.
-
The fallback. If the device runs show this is not acceptable, the option not chosen (the end text also shrinking, in proportion) keeps the value visible and truncates the expiry instead. That would come back to the architect.
-
The options not chosen: both texts shrinking in proportion, or the end text giving way first.
2 · At least md (12) between the value group and the end text. This is the requester's recommendation, which the operator did not change. The review says: keep.
- The review measured exactly 12 on web and RN-web.
justify: 'between'puts all free space between the groups, so the gap only applies when the line is full.- 12 keeps the end text from reading as a second suffix: inside the group, value and suffix are 3 apart.
- The options not chosen were 3 and 6.
3 · The name textEnd, with the order rule worded for it. This is the requester's recommendation, which the operator did not change. The review says: keep the name and change the wording; the wording is changed.
- "text" first, then the position, like
textSuffix. It matches the schema'send.list-action'strailingTextnames a different place: a column centred on the whole row. - "End" holds only when the end text is written last. The docs say so, and tests pin the wrong orders (see "Order").
- Authored order still applies, as everywhere in
list-item. The engine has no fixed-position slot, and adding one would be a wider change than this request. - The options not chosen were
textTrailingandtrailingText.
Consumer need, gap, and current workaround (before admission)
Consumer / owner. nuri-expo send journey, owned by @darioaschero. The row is the Lightning invoice review: "Lightning invoice" over the invoice, with its expiry.
Gap. list-item v1 can only put the expiry next to the value, as a suffix. That is board 9 at c69488b: operation.html:833-837, "lnbc47…k3pz Expires in 9:41".
Workaround available today. Compose that one row by hand in pure DS: the label over a nuri-view direction="row" justify="between" holding the value and the expiry, at list-item's geometry. It is not drawn: the operator chose this request over the hand-made row.
Available consumer-local prototype or evidence (before admission)
- The design: the operator's screenshot of board 9 (9 Nov) and the request of 10 Nov quoted above.
- The screenshot is not in the repository.
- The review reproduced the look in the browser: the value at 18–121.5, and the end text at 252.1–357, its right edge on the content edge.
- The row today:
operation.htmlboard 9 atc69488b. The same invoice row is insend-wip.htmlround 21, which is history and stays as it is. - The rejected first design and why: the DS admission: list-item, the read-only list row #240 review (DS admission: list-item, the read-only list row #240 (comment), claim 1 and R3).
- The mechanism:
justify: 'between'is in the schema'sStackNS(packages/spec/components/schema.ts:126) and is mapped on both engines (packages/prototype/styles/stack.css:35,packages/spec/axes/resolve-map.ts:81).- No shipped descriptor uses it yet. Rows use it in pure DS on both targets:
packages/playground/pages/unified-balance.html:229,packages/expo-demo/src/screens/Move.tsx:101, andnuri-expo@5c818c8b:components/ActivityDetailSheet.tsx:168.
- Missing: no device rendering of the proposed anatomy. It is shown during implementation, on iOS and Android, with font scaling.
Class-scoped Contraction / Mixed evidence
No response
Class-scoped Extension / Mixed evidence
Recurrence. Honestly narrow: one row on one board (the invoice expiry). nuri-expo's swap row has the same shape but a different style, and it is anti-scope. The case rests on the operator's design for the review sheet and on the low cost, not on recurrence.
DS ownership argument. The row is a list-item. Composing that one row by hand next to five DS rows would split the sheet between DS and copy, which is the drift list-item exists to stop.
Alternatives / trade study.
| Alternative | Requester's reading (not a decision) |
|---|---|
| The suffix, as in v1 | Already there; not the operator's design. |
| The expiry as its own v1 row ("Expires in" over "9:41") | No contract cost; one more row (73) on the sheet. It does not match the operator's design. |
textEnd with fill: 'grow' and align: 'end' (the first design) |
Refused by the #240 review: the value can collapse, and Android measures a flexGrow Text at full width. |
| An axis that moves the suffix to the end | One fewer slot, but the expiry could not sit at the end of a row that also has a suffix, should one ever need it. |
| The hand-made row on board 9 | Works today, in pure DS; it is the copy list-item replaces. |
Contract cost.
- one optional text slot and one internal group;
- every
list-itemsnapshot moves; - no axis, token or schema change.
Requested DS architect / admission recorder
@darioaschero · sole-architect exception · independent review: #242 (comment)
Architect decision record location (architect-owned)
No response
Proposed bounded execution scope if admitted
In scope:
packages/spec/components/list-item.ts: theleadgroup, thetextEndslot, and the header comment;- the regenerated RN and web outputs, and the updated
list-itemsnapshots; - the header comment of
packages/prototype/recipes/list-item.js; packages/rntype-tests, render-smoke and public-surface;- composition tests on both render paths:
- end text written last (the design);
- end text written first (it draws at the start);
- end text written before the label (the value's line moves above it);
- end text without a suffix;
- a test that no part of the value's line has
grow; - the doc pipeline and the
list-itempage:- the end text;
- its order rule (write it last);
- its truncation rule (it never shrinks, and the value gives way);
- the budget (a third of the line);
- the failure past it;
- no suffix together with an end text;
- the 12 minimum;
pages/component/list-item.html: boards with an end text, with a long value, and with an end text at its budget;operation.htmlboard 9: the invoice row usestextEnd;- the expo-demo sheet: one row with an end text.
Out of scope:
- nuri-expo;
- any other component;
send-wip.htmlhistory;- the single-element accessibility reading, which is still its own request.
Downstream verification plan (before Ready)
- Gates: the full suite, including
@nuri/doc. The re-emit is deterministic, and the Guard F pin is unchanged. - Existing rows, by geometry: rows without
textEndkeep their boxes on the six review boards, compared withmain@c69488b. The sheet tops are 281 and 354, the hairlines come every 73, and the value and suffix boxes are identical. Snapshots move by construction. - Board 9 on iPhone SE: the end text's right edge equals the row's content edge (357), and the value starts at 18.
- Long value, on web, RN-web and Android: the value truncates while the end text stays whole.
- End text past its budget, on web and RN-web: the documented failure is shown and measured (the value at 0, the end text 12 past the edge), so the docs match the engines.
- Font scaling, on iOS and Android at their largest system text sizes: on board 9's invoice row, the identifier keeps a visible part and the expiry stays whole. Record the measures. If the identifier disappears, stop and bring it back to the architect (choice 1, fallback).
- No
grow: the test pinning nogrowon the value's line passes and is mutation-tested. - Order: the order tests pass on both render paths.
- Device: VoiceOver and TalkBack read the end text after the value.
- Evidence: screenshots under
docs/evidence/list-item-text-end/.
Acceptance criteria and Verification/Done evidence
-
<ListItemTextEnd>and<nuri-list-item-text-end>render at the end of the value's line on both targets, when written last. - Rows without it are unchanged on screen, by geometry.
- Within its budget, the end text never shrinks and the value gives way first, on web, RN-web and Android.
- The failure past the budget, the order rule and the excluded combination are documented and pinned as above.
- Board 9 matches the operator's design.
- The full gate suite is green.
- This record's status line is flipped in the implementing PR.
Owning repository and base branch
nuri-com/nuri-design-system @ main
Dependencies and human decisions
- This builds on DS admission: list-item, the read-only list row #240, which deferred
textEnd, and on PR feat: ListItem, the read-only row of the List family — implements nuri-com/nuri-design-system#240 #241, which implements v1 (merged asmain@c69488b). The evidence lines are cited at that commit. - Independent review: DS admission: list-item textEnd, a text at the end of the value's line #242 (comment).
- Decision Needed: the architect's decision, answering each point of the review.
Risk class
Low
Authority, responsibility, and accountability evidence
This request: drafted by an agent session at the requester's direction. That session only read the repository. The operator chose the end text's truncation rule, asked for the request to be posted after #241's merge, and confirmed every correction after the independent review (10 Nov).
May change (after Ready):
packages/spec/components/list-item.ts;- the generated outputs and the
list-itemsnapshots; - the header comment of
packages/prototype/recipes/list-item.js; packages/rnandpackages/prototypetests;packages/doc;packages/playground;packages/expo-demo.
Must not change:
- nuri-expo;
- any other component's contract;
- the frozen schema.
Approval boundaries: no merge or tag without the operator, and Project Ready is set by a human.
Release, migration, and documentation plan
- Release. It is an additive slot, so no migration is needed. The release note reads: "ListItem:
textEnd, a text at the end of the value's line". - Docs. The
list-itempage gains:- the end text;
- its order rule (write it last);
- its truncation rule and budget (a third of the line, for short, important information like an expiry);
- the failure past the budget;
- no suffix together with an end text;
- the 12 minimum.
- Rollback. Revert the PR.
Admission-request acknowledgements
- This submission requests independent DS contract admission; it does not grant admission, execute the change, or authorize Project
Ready. - The requested contract delta is proposed until a named independent human DS architect records an
Admitdecision for a specific accepted contract and anti-scope. - Initial submission remains Pending/request-only until an architect-owned decision record exists; this form cannot be used to select or self-attest
Admit. - Admission independence is from the requester/consumer; the admitting architect may implement later, but independent verification remains required.
- If one human occupies both requester/consumer and architect roles, a second named human architectural reviewer is required in the architect-owned decision record.
- Class-specific evidence is provided for the selected class above; the named human DS architect enforces selected-class completeness because GitHub issue forms cannot conditionally require those fields.
- Any Extension or Mixed request includes recurrence or system-invariant evidence, DS ownership rationale, alternatives/trade study, contract cost, and anti-scope.
- Any Contraction or Mixed request includes proportional affected-consumer/non-use evidence, migration/deprecation/rollback implications, and ambiguity, misuse, duplication, or maintenance burden removed; pure Contractions are not forced through Extension prompts.
- Any Mixed request includes both Extension admission evidence and Contraction evidence.
- Before Project
Ready, this issue must have the architect-accepted contract, bounded execution scope, and downstream verification plan. - Executed Expo/device/runtime/compatibility proof is collected after implementation before Verified/Done, not treated as pre-Ready admission evidence.
- No form field, label, assignment, branch, PR, implementation, or green gate grants Project
Ready; ProjectReadyremains the sole execution authorization. - No public/observable DS growth is being routed through a maintenance form, bounded Experiment, playground, prototype, Expo demo, or other fast lane.
- All issue and PR references use canonical
owner/repo#numberform.
All fourteen apply as written. This is a request only (no Admit, no Ready). The roles overlap, and the second-reviewer box is met through the sole-architect exception (docs/design-system-admission.md, #229): an independent review session posts its findings on this issue before the decision is recorded.
Activity
darioaschero commentedon Nov 10, 2026
Independent review ·
list-itemtextEnd(Extension request)This is the independent review session of
docs/design-system-admission.md, "Named exception · sole DS architect". It is a fresh agent session that had no part in drafting the request, the evidence or the brief. It informs the decision and records no outcome.Inputs.
c69488b. Thepackages/tree was exported withgit archiveto a scratch folder and served statically.operation.htmlin the iPhone SE frame. Rows were rebuilt in the browser into the proposed anatomy with the factory's own stack attributes:data-justify="between"anddata-gap="md"online, aleadview withdata-fill="shrink", and the end text as a mutedmdtypography withdata-fill="hug".react-native-web0.21.2, in a 375 frame. It uses the RN renderer's resolved styles from the committed list-item snapshot (packages/rn/__tests__/__snapshots__/render-smoke.test.tsx.snap). The new parts are mapped through the sameFILLtable (packages/spec/axes/resolve-map.ts:107-113,packages/rn/runtime/resolve.ts:95-107).packages/spec/composition/classify.js), run in Node on the proposed anatomy.Not used: other sessions' notes, local drafts, nuri-expo (this request cites no nuri-expo commit), and the operator's screenshot.
Paths are at
c69488b. Measures are in px on iPhone SE (375), relative to the device viewport. The row's content edge is 18–357.1 · Claims I could not confirm
"The suffix and the end text stay whole" (Truncation; choice 1).
hugcaps a part at 100% of its parent (max-inline-size: 100%,packages/prototype/styles/stack.css:47;maxWidth: '100%',packages/rn/runtime/resolve.ts:102-105);lead, andleadshrinks to 0.leadplus themdgap cannot go below 12. The request does not say this."No long end text" as the bound. The threshold is lower than "long" suggests, and nothing checks it.
allowFontScaling: falseis set only fordecorativedescriptors (packages/rn/runtime/renderer.tsx:802).RN-web, every font size × k, "You pay ₿ 4 802 € 4.53 … Expires in 9:41":
"Rows without
textEndare unchanged"; "only the snapshot structure (lead) changes".leadgroup.list-itemrow, with or withouttextEnd, gains one host view on both targets.linestyle changes too:gapgoes from 3 to 12, andjustifyContent: 'space-between'is added.packages/rn/__tests__/render-smoke.test.tsx:916and:997), not only the new ones."It follows the author's order, as everywhere in
list-item." This is only partly true: the classifier places a group at its first-authored member (classify.js:67-76). Run on the proposed anatomy:textMuted, text, textSuffix, textEnd→content[textMuted line[lead[text textSuffix] textEnd]]: the design.textMuted, textEnd, text→line[textEnd lead[text]]: withjustify: 'between', the end text draws at the start (18–122.9) and the value at the right edge (253.5–357), on web and on RN-web.textEnd, textMuted, text→content[line[…] textMuted]: the value's line also moves above the label.textMuted, text, textEnd, textSuffix→lead[text textSuffix] textEnd: the authored interleaving is not kept, because the group wins.The planned test "end text written last" pins only the first case.
"End text alone" (execution scope, composition tests).
textis required: the web factory throws without it (packages/prototype/factory/factory.js:1112-1113).lead,justify: 'between'with a single child would also put the end text at the start (classifier:content[textMuted line[textEnd]]).Not checkable from these inputs (no finding either way):
c69488b);nuri-expo:components/ActivityDetailSheet.tsx:168and:169-173(this request cites no nuri-expo commit; the DS admission: list-item, the read-only list row #240 review read:169-173atnuri-expo@5c818c8b);Checked and confirmed
packages/spec/components/list-item.tsis as described: the slotstextMuted,text(required) andtextSuffix;linewith gapxs; the suffix withfill: 'hug'.operation.html:833-837is board 9's invoice row, with "Expires in 9:41" as a suffix.select-trigger.ts:50-51andresolve-map.ts:102-104carry the AndroidflexGrownote.schema.ts:126isStackNS.justify, which includesbetween.fillvalues.growisflex: 1 0 auto(stack.css:43,resolve-map.ts:108).shrinkisflex: 0 1 autowithmin-inline-size: 0(stack.css:45). On RN it isflexGrow 0,flexShrink 1,minWidth 0.hugisflex: 0 0 auto,fit-contentandmax-inline-size: 100%(stack.css:47). On RN it isalignSelf: 'flex-start'andmaxWidth: '100%'(resolve.ts:102-105).grow: 0:textandleadareshrink, andtextSuffixandtextEndarehug.linehas nofill, and onlycontentgrows (a view, unchanged).flexGrowText case ofselect-trigger.ts:50-51does not arise.justify: 'between'.stack.css:35,resolve-map.ts:81).packages/spec/components/uses it.operation.html:133), as the request says. Row uses exist in pure DS on both targets, for examplepackages/playground/pages/unified-balance.html:229andpackages/expo-demo/src/screens/Move.tsx:101.leadis a descriptor-local part, and Guard F pins the frozen schema shape (scripts/docs-drift.test.js:505), not descriptor data.packages/doc/generated/components/list-item.mdnames only the slots.trailingTextis another place. list-action'strailingis a column withalign: 'end', centred on the row (list-action.ts:40,62-66), as the request says.send-wip.html:1563-1565has the expiry as a mutedmdtext next to the value, with gapxs.2 · Risks to the contract
R1 · The
leadgroup reaches every existing row.Every
list-itemrow gains one view on both targets:operation.html;pages/component/list-item.html;packages/expo-demo/src/sheets/ActivitySheet.tsx;The geometry holds on web and RN-web (claim 3).
Not probed:
The plan covers both.
Authored order between the two lines now also depends on
textEnd: writing it first moves the value's line above the label (claim 4).R2 ·
justify: 'between'on both engines.starton both; I probed that rows withouttextEndare unchanged.betweenhere, but not onhug:alignSelf: 'flex-start', while web sets noalign-self;linerow withalign: 'center', the end text sits at the top on RN and is centred on web. The suffix already does this.mdline heights the difference is invisible today. A later size or emphasis option for the end text would show it.R3 · "The end text never shrinks."
hugcaps it at 100% of the line, and it truncates there (claim 1).flexGrowrisk;R4 · The order rule against the name.
textEndnames a position, but the order rule makes the position the author's: written first, it draws at the start of the line (claim 4).textSuffixhas the same property, and DS admission: list-item, the read-only list row #240 accepted it by documenting it. Here the mismatch shows at the opposite edge of the row, not 3 px away.R5 · The 12 minimum.
mdsuffix and a mutedmdend text ("€ 4.53 Expires in 9:41").R6 · The name.
leadingandtrailing(list-action:leadingAvatar,trailingText,trailingTextMuted,trailIcon);Suffix;End.align/justify: 'end'. "Trailing" would point at list-action's row-centred column, so the request's reason holds.lead, next to list-action's and topbar'sleading. It is internal and undocumented, so this is cosmetic.R7 · Recurrence.
list-itemrow ("Expires in" over "9:41"). It costs one more row (73) on the sheet and does not match the operator's design.R8 · What the gates would not catch. The 5 gates and the guards stay green with any of these:
textEndwritten first: it draws at the start and lifts the value's line above the label;grow: no test pins "noflexGrowon a text part" for this descriptor;align-selfdifference ofhug(R2);textEndunchanged": the snapshot of every row moves in the same PR (claim 3);R9 · Gaps in the verification plan and the scope.
packages/prototype/recipes/list-item.js:4-6lists the slots. The file is in neither the execution scope nor the "May change" list, which names onlypackages/prototypetests.3 · Recommendation for each requester choice
1 · The end text never shrinks; the value group gives way: keep, with conditions.
flexGrowcase.grow.shrinkon the end text too), keeps the value visible. It truncates the expiry instead.2 · At least
md(12) between the groups: keep.3 · The name
textEnd: keep the name, but change how the order rule is stated for it.textSuffix's text-first pattern and the schema'send, andtrailingTextwould mislead (R6).textEndcan draw at the start and lift the value's line above the label (claim 4). Either:This review records no outcome. The decision, and the answer to each point above, belong to the architect.
darioaschero commentedon Nov 10, 2026
Request amended after independent review
The issue body is amended to answer the independent review. No decision is recorded here, and no Project state moved. The admission decision remains @darioaschero's, in an architect-owned comment.
Claims the review could not confirm
leadin the treelead, thatlinegainsgap: 'md'andjustify: 'between', and that everylist-itemsnapshot moves. "Unchanged" is proven by geometry probes againstc69488b.textis required.nuri-expo@5c818c8b. The operator's quotes and screenshot stay as the requester's evidence. The look was reproduced by the review in the browser.Risks
leadreaches every rowbetweenandhugon both enginesalign-selfdifference ofhugis recorded under "Style": it is invisible with equal line heights, and any later size or emphasis option must handle it.textSuffixand the schema'send, whiletrailingTextnames another place.leadis internal.growtest (mutation-tested), the align-self note, geometry for unchanged rows, and Android on device.packages/prototype/recipes/list-item.js. "End text alone" is defined.Recommendations for the three choices
growtest). The proportional option is recorded as the fallback.md(12)textEnddarioaschero commentedon Nov 10, 2026
DS admission decision
Outcome: Admit
Admission class: Extension
Architect: @darioaschero
Second human architectural reviewer, if requester/consumer and architect overlap: none · sole-architect exception (@darioaschero) · independent review: #242 (comment)
Requester / consumer owner: @darioaschero (nuri-com/nuri-expo, the send review sheet: the Lightning invoice review)
Evidence considered:
list-itemas admitted in DS admission: list-item, the read-only list row #240 (decision: DS admission: list-item, the read-only list row #240 (comment)) and implemented in feat: ListItem, the read-only row of the List family — implements nuri-com/nuri-design-system#240 #241 (main@c69488b);packages/playground/pages/operation.htmlboard 9 atc69488b(L833-837), and my design for that row;fill: 'grow');c69488b(docs(admission): named sole-architect exception for @darioaschero #229).Rationale:
justify: 'between'. No text grows, so the AndroidflexGrowcase of the first design does not arise.list-itemsnapshot moves, but the review confirmed that rows without an end text keep their boxes on web and RN-web.list-itemsheet, and a hand-made row next to five DS rows is the driftlist-itemwas admitted to stop.Accepted contract:
list-itemgainstextEnd: optional and singular,md, muted and regular. RNListItemTextEnd, webnuri-list-item-text-end.leadgroup (text,textSuffix; gapxs,fill: 'shrink') andtextEnd(fill: 'hug',align: 'end'). Thelinehasjustify: 'between'and gapmd, so there are at least 12 between the two groups.growon any part of the value's line, pinned by a test.list-itempage states:Anti-scope:
growon the value's line;textSuffixor to the 60 / 73 geometry;Answers to the independent review:
list-item, and define "end" as "written last".leadin every row): accepted. Android measurement of the nested group and the reading order are in the device plan.hugalignment on RN and web): accepted, and recorded. It is invisible with equal line heights, and any later size or emphasis option must handle it.textEndfollowstextSuffixand the schema'send, whiletrailingTextnames list-action's centred column. Decision 84's family vocabulary stays deferred, as recorded on DS admission: list-item, the read-only list row #240.Process note:
c69488b, the two DS admission: list-item, the read-only list row #240 comments the request cites, and the policy.Contraction evidence considered, if applicable: none. This is a pure Extension.
Bounded execution scope reference: #242, "Proposed bounded execution scope if admitted" (as amended)
Downstream verification plan reference: #242, "Downstream verification plan (before Ready)" (as amended)