@@ -12,9 +12,16 @@ import { resolveCreateDisplaySteps, resolveCreateFlowSteps } from "./menu-create
1212/**
1313 * Clamps a create settings index into the editable settings range.
1414 *
15+ * @param step - Candidate step index.
16+ * @param lastStep - Inclusive upper bound of the current settings range.
17+ * @returns `step` bounded to `[firstCreateSettingsStepIndex, lastStep]`.
1518 * @pure true
19+ * @effect n/a
1620 * @invariant result is between first settings step and lastStep when range is valid
21+ * @precondition `lastStep >= firstCreateSettingsStepIndex` for a non-empty settings range.
22+ * @postcondition result >= firstCreateSettingsStepIndex and result <= lastStep when the precondition holds.
1723 * @complexity O(1)
24+ * @throws Never
1825 */
1926// CHANGE: centralize create settings index clamping
2027// WHY: advancement and navigation must share the same range invariant
@@ -31,6 +38,31 @@ export const clampCreateSettingsStep = (
3138 lastStep : number
3239) : number => Math . min ( Math . max ( step , firstCreateSettingsStepIndex ) , lastStep )
3340
41+ /**
42+ * Computes a wrapped adjacent settings index.
43+ *
44+ * @param step - Current valid settings step index.
45+ * @param lastStep - Inclusive upper bound for settings.
46+ * @param direction - Vertical navigation direction.
47+ * @returns The previous or next settings index with wraparound.
48+ * @pure true
49+ * @effect n/a
50+ * @invariant result is inside `[firstCreateSettingsStepIndex, lastStep]`.
51+ * @precondition `step` is inside `[firstCreateSettingsStepIndex, lastStep]`.
52+ * @postcondition `up` decrements or wraps to `lastStep`; `down` increments or wraps to first settings step.
53+ * @complexity O(1)
54+ * @throws Never
55+ */
56+ // CHANGE: isolate wrapped create-settings index arithmetic
57+ // WHY: both create and display modes share the same vertical navigation law
58+ // QUOTE(ТЗ): "Add concise but compliant TSDoc + functional comments"
59+ // REF: issue-339
60+ // SOURCE: n/a
61+ // FORMAT THEOREM: forall s in [first,last], d: next(s,d) in [first,last]
62+ // PURITY: CORE
63+ // EFFECT: n/a
64+ // INVARIANT: navigation never returns the repo URL step
65+ // COMPLEXITY: O(1)
3466const nextCreateSettingsStep = (
3567 step : number ,
3668 lastStep : number ,
@@ -42,6 +74,31 @@ const nextCreateSettingsStep = (
4274 Match . exhaustive
4375 )
4476
77+ /**
78+ * Moves any settings-capable create-flow view within a bounded range.
79+ *
80+ * @param view - Create or display view to move.
81+ * @param lastStep - Inclusive upper bound for the active settings list.
82+ * @param direction - Vertical navigation direction.
83+ * @returns A moved view, the original view if unchanged, or null when no settings range is active.
84+ * @pure true
85+ * @effect n/a
86+ * @invariant Returned views preserve mode and committed values.
87+ * @precondition `view` is non-null and `lastStep` belongs to the step list used by the caller.
88+ * @postcondition Non-null moved views have empty `buffer` and null `inputError`.
89+ * @complexity O(1)
90+ * @throws Never
91+ */
92+ // CHANGE: share immutable settings movement across create and display modes
93+ // WHY: the two views differ only in the step list that defines `lastStep`
94+ // QUOTE(ТЗ): "Add concise but compliant TSDoc + functional comments"
95+ // REF: issue-339
96+ // SOURCE: n/a
97+ // FORMAT THEOREM: valid(v,last) -> move(v).values = v.values
98+ // PURITY: CORE
99+ // EFFECT: n/a
100+ // INVARIANT: repo URL or empty settings ranges return null
101+ // COMPLEXITY: O(1)
45102const moveCreateSettingsWithin = <
46103 A extends CreateModeFlowView | DisplayModeFlowView
47104> (
@@ -65,13 +122,59 @@ const moveCreateSettingsWithin = <
65122 }
66123}
67124
125+ /**
126+ * Resolves a horizontal boolean choice to the create-flow buffer token.
127+ *
128+ * @param direction - Horizontal choice direction.
129+ * @returns `"n"` for left and `"y"` for right.
130+ * @pure true
131+ * @effect n/a
132+ * @invariant result is always a valid yes/no buffer token.
133+ * @precondition `direction` is a valid CreateSettingsChoiceDirection.
134+ * @postcondition Left maps to false-preview token; right maps to true-preview token.
135+ * @complexity O(1)
136+ * @throws Never
137+ */
138+ // CHANGE: encode boolean left/right choices as create input buffer values
139+ // WHY: preview buffers reuse the same parser path as typed settings input
140+ // QUOTE(ТЗ): "Add concise but compliant TSDoc + functional comments"
141+ // REF: issue-339
142+ // SOURCE: n/a
143+ // FORMAT THEOREM: direction in {left,right} -> token in {n,y}
144+ // PURITY: CORE
145+ // EFFECT: n/a
146+ // INVARIANT: output token set is finite and parser-compatible
147+ // COMPLEXITY: O(1)
68148const booleanChoiceBuffer = ( direction : CreateSettingsChoiceDirection ) : string =>
69149 Match . value ( direction ) . pipe (
70150 Match . when ( "left" , ( ) => "n" ) ,
71151 Match . when ( "right" , ( ) => "y" ) ,
72152 Match . exhaustive
73153 )
74154
155+ /**
156+ * Resolves a horizontal GPU choice to the create-flow buffer token.
157+ *
158+ * @param direction - Horizontal choice direction.
159+ * @returns `"none"` for left and `"all"` for right.
160+ * @pure true
161+ * @effect n/a
162+ * @invariant result is always a valid GPU buffer token.
163+ * @precondition `direction` is a valid CreateSettingsChoiceDirection.
164+ * @postcondition Left maps to `none`; right maps to `all`.
165+ * @complexity O(1)
166+ * @throws Never
167+ */
168+ // CHANGE: encode GPU left/right choices as create input buffer values
169+ // WHY: display controls should use the same parser-compatible token space as manual input
170+ // QUOTE(ТЗ): "Add concise but compliant TSDoc + functional comments"
171+ // REF: issue-339
172+ // SOURCE: n/a
173+ // FORMAT THEOREM: direction in {left,right} -> token in {none,all}
174+ // PURITY: CORE
175+ // EFFECT: n/a
176+ // INVARIANT: output token set is finite and parser-compatible
177+ // COMPLEXITY: O(1)
75178const gpuChoiceBuffer = ( direction : CreateSettingsChoiceDirection ) : string =>
76179 Match . value ( direction ) . pipe (
77180 Match . when ( "left" , ( ) => "none" ) ,
@@ -82,9 +185,16 @@ const gpuChoiceBuffer = (direction: CreateSettingsChoiceDirection): string =>
82185/**
83186 * Resolves horizontal browser setting controls into preview buffer tokens.
84187 *
188+ * @param view - Browser display-settings view that provides the active row.
189+ * @param direction - Horizontal choice direction.
190+ * @returns A parser-compatible buffer token for discrete rows, otherwise null.
85191 * @pure true
192+ * @effect n/a
86193 * @invariant free-text rows return null
194+ * @precondition `view.step` may be inside or outside the display step range.
195+ * @postcondition Returned non-null tokens do not mutate `view.values`.
87196 * @complexity O(1)
197+ * @throws Never
88198 */
89199// CHANGE: map display-mode left/right choices to create setting buffer values
90200// WHY: browser controls should preview discrete settings without committing values
@@ -122,9 +232,16 @@ export const resolveCreateSettingsChoiceBuffer = (
122232/**
123233 * Moves the create-mode settings selection with wraparound.
124234 *
235+ * @param view - Create-mode view to move.
236+ * @param direction - Vertical navigation direction.
237+ * @returns Moved create-mode view or null when the repo URL step is active.
125238 * @pure true
239+ * @effect n/a
126240 * @invariant returned view has an empty buffer
241+ * @precondition `view` is a non-null CreateModeFlowView.
242+ * @postcondition Non-null result preserves mode and values while clearing transient input state.
127243 * @complexity O(s) where s = number of remaining create steps
244+ * @throws Never
128245 */
129246// CHANGE: expose pure create-mode settings navigation
130247// WHY: arrow-key handling must not mutate the current view
@@ -145,9 +262,16 @@ export const moveCreateSettingsStep = (
145262/**
146263 * Moves the browser display-settings selection with wraparound.
147264 *
265+ * @param view - Display-mode view to move.
266+ * @param direction - Vertical navigation direction.
267+ * @returns Moved display-mode view or null when no settings range is active.
148268 * @pure true
269+ * @effect n/a
149270 * @invariant returned view has an empty buffer
271+ * @precondition `view` is a non-null DisplayModeFlowView.
272+ * @postcondition Non-null result preserves mode and values while clearing transient input state.
150273 * @complexity O(s) where s = number of display steps
274+ * @throws Never
151275 */
152276// CHANGE: expose pure display-mode settings navigation
153277// WHY: browser settings keep all rows navigable regardless of committed values
0 commit comments