@entelligentsia/forgecli 0.8.4 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +165 -2
  3. package/dist/bin/argv.d.ts +2 -2
  4. package/dist/bin/argv.js +17 -0
  5. package/dist/bin/argv.js.map +1 -1
  6. package/dist/bin/config.d.ts +69 -0
  7. package/dist/bin/config.js +315 -0
  8. package/dist/bin/config.js.map +1 -0
  9. package/dist/bin/doctor.d.ts +1 -0
  10. package/dist/bin/doctor.js +12 -0
  11. package/dist/bin/doctor.js.map +1 -1
  12. package/dist/bin/forge.js +7 -0
  13. package/dist/bin/forge.js.map +1 -1
  14. package/dist/extensions/forgecli/config-command.d.ts +8 -0
  15. package/dist/extensions/forgecli/config-command.js +66 -0
  16. package/dist/extensions/forgecli/config-command.js.map +1 -0
  17. package/dist/extensions/forgecli/config-layer.d.ts +38 -0
  18. package/dist/extensions/forgecli/config-layer.js +68 -0
  19. package/dist/extensions/forgecli/config-layer.js.map +1 -0
  20. package/dist/extensions/forgecli/config-tui/component.d.ts +35 -0
  21. package/dist/extensions/forgecli/config-tui/component.js +236 -0
  22. package/dist/extensions/forgecli/config-tui/component.js.map +1 -0
  23. package/dist/extensions/forgecli/config-tui/handler.d.ts +40 -0
  24. package/dist/extensions/forgecli/config-tui/handler.js +240 -0
  25. package/dist/extensions/forgecli/config-tui/handler.js.map +1 -0
  26. package/dist/extensions/forgecli/config-tui/index.d.ts +5 -0
  27. package/dist/extensions/forgecli/config-tui/index.js +5 -0
  28. package/dist/extensions/forgecli/config-tui/index.js.map +1 -0
  29. package/dist/extensions/forgecli/config-tui/keys.d.ts +26 -0
  30. package/dist/extensions/forgecli/config-tui/keys.js +33 -0
  31. package/dist/extensions/forgecli/config-tui/keys.js.map +1 -0
  32. package/dist/extensions/forgecli/config-tui/plugin-config-reader.d.ts +23 -0
  33. package/dist/extensions/forgecli/config-tui/plugin-config-reader.js +58 -0
  34. package/dist/extensions/forgecli/config-tui/plugin-config-reader.js.map +1 -0
  35. package/dist/extensions/forgecli/config-tui/screens/advanced-menu.d.ts +7 -0
  36. package/dist/extensions/forgecli/config-tui/screens/advanced-menu.js +83 -0
  37. package/dist/extensions/forgecli/config-tui/screens/advanced-menu.js.map +1 -0
  38. package/dist/extensions/forgecli/config-tui/screens/confirm-quit.d.ts +11 -0
  39. package/dist/extensions/forgecli/config-tui/screens/confirm-quit.js +54 -0
  40. package/dist/extensions/forgecli/config-tui/screens/confirm-quit.js.map +1 -0
  41. package/dist/extensions/forgecli/config-tui/screens/override-editor.d.ts +11 -0
  42. package/dist/extensions/forgecli/config-tui/screens/override-editor.js +233 -0
  43. package/dist/extensions/forgecli/config-tui/screens/override-editor.js.map +1 -0
  44. package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.d.ts +7 -0
  45. package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.js +91 -0
  46. package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.js.map +1 -0
  47. package/dist/extensions/forgecli/config-tui/screens/overrides-list.d.ts +7 -0
  48. package/dist/extensions/forgecli/config-tui/screens/overrides-list.js +71 -0
  49. package/dist/extensions/forgecli/config-tui/screens/overrides-list.js.map +1 -0
  50. package/dist/extensions/forgecli/config-tui/screens/persona-editor.d.ts +10 -0
  51. package/dist/extensions/forgecli/config-tui/screens/persona-editor.js +182 -0
  52. package/dist/extensions/forgecli/config-tui/screens/persona-editor.js.map +1 -0
  53. package/dist/extensions/forgecli/config-tui/screens/persona-picker.d.ts +7 -0
  54. package/dist/extensions/forgecli/config-tui/screens/persona-picker.js +76 -0
  55. package/dist/extensions/forgecli/config-tui/screens/persona-picker.js.map +1 -0
  56. package/dist/extensions/forgecli/config-tui/screens/personas-list.d.ts +7 -0
  57. package/dist/extensions/forgecli/config-tui/screens/personas-list.js +98 -0
  58. package/dist/extensions/forgecli/config-tui/screens/personas-list.js.map +1 -0
  59. package/dist/extensions/forgecli/config-tui/screens/shared.d.ts +29 -0
  60. package/dist/extensions/forgecli/config-tui/screens/shared.js +100 -0
  61. package/dist/extensions/forgecli/config-tui/screens/shared.js.map +1 -0
  62. package/dist/extensions/forgecli/config-tui/screens/show-resolved.d.ts +23 -0
  63. package/dist/extensions/forgecli/config-tui/screens/show-resolved.js +128 -0
  64. package/dist/extensions/forgecli/config-tui/screens/show-resolved.js.map +1 -0
  65. package/dist/extensions/forgecli/config-tui/screens/tier-menu.d.ts +7 -0
  66. package/dist/extensions/forgecli/config-tui/screens/tier-menu.js +135 -0
  67. package/dist/extensions/forgecli/config-tui/screens/tier-menu.js.map +1 -0
  68. package/dist/extensions/forgecli/config-tui/screens/tier-picker.d.ts +9 -0
  69. package/dist/extensions/forgecli/config-tui/screens/tier-picker.js +122 -0
  70. package/dist/extensions/forgecli/config-tui/screens/tier-picker.js.map +1 -0
  71. package/dist/extensions/forgecli/config-tui/screens/types.d.ts +24 -0
  72. package/dist/extensions/forgecli/config-tui/screens/types.js +5 -0
  73. package/dist/extensions/forgecli/config-tui/screens/types.js.map +1 -0
  74. package/dist/extensions/forgecli/config-tui/screens.d.ts +24 -0
  75. package/dist/extensions/forgecli/config-tui/screens.js +78 -0
  76. package/dist/extensions/forgecli/config-tui/screens.js.map +1 -0
  77. package/dist/extensions/forgecli/config-tui/state/buffer.d.ts +11 -0
  78. package/dist/extensions/forgecli/config-tui/state/buffer.js +91 -0
  79. package/dist/extensions/forgecli/config-tui/state/buffer.js.map +1 -0
  80. package/dist/extensions/forgecli/config-tui/state/constants.d.ts +4 -0
  81. package/dist/extensions/forgecli/config-tui/state/constants.js +14 -0
  82. package/dist/extensions/forgecli/config-tui/state/constants.js.map +1 -0
  83. package/dist/extensions/forgecli/config-tui/state/index.d.ts +6 -0
  84. package/dist/extensions/forgecli/config-tui/state/index.js +9 -0
  85. package/dist/extensions/forgecli/config-tui/state/index.js.map +1 -0
  86. package/dist/extensions/forgecli/config-tui/state/init.d.ts +2 -0
  87. package/dist/extensions/forgecli/config-tui/state/init.js +30 -0
  88. package/dist/extensions/forgecli/config-tui/state/init.js.map +1 -0
  89. package/dist/extensions/forgecli/config-tui/state/model.d.ts +192 -0
  90. package/dist/extensions/forgecli/config-tui/state/model.js +4 -0
  91. package/dist/extensions/forgecli/config-tui/state/model.js.map +1 -0
  92. package/dist/extensions/forgecli/config-tui/state/reducer.d.ts +2 -0
  93. package/dist/extensions/forgecli/config-tui/state/reducer.js +212 -0
  94. package/dist/extensions/forgecli/config-tui/state/reducer.js.map +1 -0
  95. package/dist/extensions/forgecli/config-tui/state/selectors.d.ts +91 -0
  96. package/dist/extensions/forgecli/config-tui/state/selectors.js +231 -0
  97. package/dist/extensions/forgecli/config-tui/state/selectors.js.map +1 -0
  98. package/dist/extensions/forgecli/config-tui/state.d.ts +6 -0
  99. package/dist/extensions/forgecli/config-tui/state.js +11 -0
  100. package/dist/extensions/forgecli/config-tui/state.js.map +1 -0
  101. package/dist/extensions/forgecli/config-tui/theme.d.ts +37 -0
  102. package/dist/extensions/forgecli/config-tui/theme.js +88 -0
  103. package/dist/extensions/forgecli/config-tui/theme.js.map +1 -0
  104. package/dist/extensions/forgecli/config-tui/tier-meta.d.ts +28 -0
  105. package/dist/extensions/forgecli/config-tui/tier-meta.js +69 -0
  106. package/dist/extensions/forgecli/config-tui/tier-meta.js.map +1 -0
  107. package/dist/extensions/forgecli/config-writer.d.ts +16 -0
  108. package/dist/extensions/forgecli/config-writer.js +63 -0
  109. package/dist/extensions/forgecli/config-writer.js.map +1 -0
  110. package/dist/extensions/forgecli/fix-bug.js +85 -1
  111. package/dist/extensions/forgecli/fix-bug.js.map +1 -1
  112. package/dist/extensions/forgecli/forge-cli-schema.json +54 -0
  113. package/dist/extensions/forgecli/forge-commands.js +3 -8
  114. package/dist/extensions/forgecli/forge-commands.js.map +1 -1
  115. package/dist/extensions/forgecli/forge-subagent.d.ts +13 -0
  116. package/dist/extensions/forgecli/forge-subagent.js +19 -0
  117. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  118. package/dist/extensions/forgecli/index.js +16 -0
  119. package/dist/extensions/forgecli/index.js.map +1 -1
  120. package/dist/extensions/forgecli/input-router.d.ts +33 -0
  121. package/dist/extensions/forgecli/input-router.js +133 -0
  122. package/dist/extensions/forgecli/input-router.js.map +1 -0
  123. package/dist/extensions/forgecli/model-resolver.d.ts +32 -0
  124. package/dist/extensions/forgecli/model-resolver.js +65 -0
  125. package/dist/extensions/forgecli/model-resolver.js.map +1 -0
  126. package/dist/extensions/forgecli/model-validator.d.ts +29 -0
  127. package/dist/extensions/forgecli/model-validator.js +107 -0
  128. package/dist/extensions/forgecli/model-validator.js.map +1 -0
  129. package/dist/extensions/forgecli/run-sprint.js +59 -0
  130. package/dist/extensions/forgecli/run-sprint.js.map +1 -1
  131. package/dist/extensions/forgecli/run-task.js +93 -1
  132. package/dist/extensions/forgecli/run-task.js.map +1 -1
  133. package/dist/extensions/forgecli/thread-switcher.js +5 -2
  134. package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
  135. package/dist/extensions/forgecli/whats-new-widget.js +5 -2
  136. package/dist/extensions/forgecli/whats-new-widget.js.map +1 -1
  137. package/package.json +11 -3
  138. package/dist/extensions/forgecli/review-command.d.ts +0 -2
  139. package/dist/extensions/forgecli/review-command.js +0 -184
  140. package/dist/extensions/forgecli/review-command.js.map +0 -1
  141. package/dist/forge-payload/.tools/banners.cjs +0 -435
  142. package/dist/forge-payload/.tools/build-context-pack.cjs +0 -290
  143. package/dist/forge-payload/.tools/build-init-context.cjs +0 -322
  144. package/dist/forge-payload/.tools/build-overlay.cjs +0 -326
  145. package/dist/forge-payload/.tools/build-persona-pack.cjs +0 -226
  146. package/dist/forge-payload/.tools/collate.cjs +0 -1041
  147. package/dist/forge-payload/.tools/generation-manifest.cjs +0 -311
  148. package/dist/forge-payload/.tools/lib/forge-root.cjs +0 -59
  149. package/dist/forge-payload/.tools/lib/paths.cjs +0 -29
  150. package/dist/forge-payload/.tools/lib/pricing.cjs +0 -165
  151. package/dist/forge-payload/.tools/lib/project-root.cjs +0 -32
  152. package/dist/forge-payload/.tools/lib/result.js +0 -40
  153. package/dist/forge-payload/.tools/lib/store-facade.cjs +0 -162
  154. package/dist/forge-payload/.tools/lib/store-nlp.cjs +0 -250
  155. package/dist/forge-payload/.tools/lib/store-query-exec.cjs +0 -272
  156. package/dist/forge-payload/.tools/lib/validate.js +0 -141
  157. package/dist/forge-payload/.tools/manage-config.cjs +0 -340
  158. package/dist/forge-payload/.tools/manage-versions.cjs +0 -365
  159. package/dist/forge-payload/.tools/package.json +0 -3
  160. package/dist/forge-payload/.tools/parse-gates.cjs +0 -151
  161. package/dist/forge-payload/.tools/parse-verdict.cjs +0 -67
  162. package/dist/forge-payload/.tools/preflight-gate.cjs +0 -350
  163. package/dist/forge-payload/.tools/prompts/sprint-plan-prompt.md +0 -70
  164. package/dist/forge-payload/.tools/schemas/task-list.schema.json +0 -53
  165. package/dist/forge-payload/.tools/seed-store.cjs +0 -237
  166. package/dist/forge-payload/.tools/store-cli.cjs +0 -1226
  167. package/dist/forge-payload/.tools/store-query.cjs +0 -319
  168. package/dist/forge-payload/.tools/store.cjs +0 -315
  169. package/dist/forge-payload/.tools/substitute-placeholders.cjs +0 -625
  170. package/dist/forge-payload/.tools/validate-store.cjs +0 -593
@@ -0,0 +1,212 @@
1
+ // Config TUI reducer — pure (state, action) → state. No I/O.
2
+ // Split from state.ts (Phase 1).
3
+ import { writePersonaEntry, deletePersonaEntry, writePhaseOverride, clearPhaseOverride, writeTierAssignment } from "./buffer.js";
4
+ export function reducer(state, action) {
5
+ switch (action.kind) {
6
+ case "push-view":
7
+ return { ...state, view: [...state.view, action.view] };
8
+ case "pop-view":
9
+ if (state.view.length <= 1)
10
+ return state;
11
+ return { ...state, view: state.view.slice(0, -1) };
12
+ case "cursor-move": {
13
+ const top = state.view[state.view.length - 1];
14
+ // Every cursored view variant gets the same lower-bound clamp; the
15
+ // component clamps the upper bound based on per-view item counts.
16
+ if (top.kind === "tier-menu" ||
17
+ top.kind === "tier-picker" ||
18
+ top.kind === "advanced-menu" ||
19
+ top.kind === "personas-list" ||
20
+ top.kind === "persona-picker" ||
21
+ top.kind === "show-resolved" ||
22
+ top.kind === "persona-editor" ||
23
+ top.kind === "overrides-list-pipelines" ||
24
+ top.kind === "overrides-list-phases" ||
25
+ top.kind === "override-editor") {
26
+ const newCursor = Math.max(0, top.cursor + action.delta);
27
+ const replaced = { ...top, cursor: newCursor };
28
+ return { ...state, view: [...state.view.slice(0, -1), replaced] };
29
+ }
30
+ return state;
31
+ }
32
+ case "begin-persona-edit": {
33
+ const editor = {
34
+ kind: "persona-editor",
35
+ persona: action.persona,
36
+ step: "pick-provider",
37
+ provider: undefined,
38
+ model: undefined,
39
+ cursor: 0,
40
+ };
41
+ return { ...state, view: [...state.view, editor] };
42
+ }
43
+ case "set-persona-provider": {
44
+ const top = state.view[state.view.length - 1];
45
+ if (top.kind !== "persona-editor")
46
+ return state;
47
+ const updated = {
48
+ ...top,
49
+ provider: action.provider,
50
+ model: undefined,
51
+ step: "pick-model",
52
+ cursor: 0,
53
+ };
54
+ return { ...state, view: [...state.view.slice(0, -1), updated] };
55
+ }
56
+ case "set-persona-model": {
57
+ const top = state.view[state.view.length - 1];
58
+ if (top.kind !== "persona-editor")
59
+ return state;
60
+ const updated = {
61
+ ...top,
62
+ model: action.model,
63
+ step: "pick-layer",
64
+ cursor: 0,
65
+ };
66
+ return { ...state, view: [...state.view.slice(0, -1), updated] };
67
+ }
68
+ // ── Tiered-baseline actions (Phase A+) ───────────────────────────────────
69
+ case "select-tier": {
70
+ const tierPicker = {
71
+ kind: "tier-picker",
72
+ tier: action.tier,
73
+ step: "pick-provider",
74
+ provider: undefined,
75
+ cursor: 0,
76
+ };
77
+ return { ...state, view: [...state.view, tierPicker] };
78
+ }
79
+ case "set-tier-provider": {
80
+ const top = state.view[state.view.length - 1];
81
+ if (top.kind !== "tier-picker")
82
+ return state;
83
+ const updated = {
84
+ ...top,
85
+ provider: action.provider,
86
+ step: "pick-model",
87
+ cursor: 0,
88
+ };
89
+ return { ...state, view: [...state.view.slice(0, -1), updated] };
90
+ }
91
+ case "commit-tier-model": {
92
+ const entry = { provider: action.provider, model: action.model };
93
+ const buffer = writeTierAssignment(state.buffer, action.layer, action.tier, entry);
94
+ // Pop the tier-picker view, returning to tier-menu
95
+ const view = state.view.length > 1 ? state.view.slice(0, -1) : state.view;
96
+ return {
97
+ ...state,
98
+ buffer,
99
+ view,
100
+ dirty: true,
101
+ };
102
+ }
103
+ case "toggle-scope": {
104
+ const newScope = state.scope === "global" ? "project" : "global";
105
+ return { ...state, scope: newScope };
106
+ }
107
+ // ── Legacy actions ────────────────────────────────────────────────────────
108
+ case "commit-persona-edit": {
109
+ const top = state.view[state.view.length - 1];
110
+ if (top.kind !== "persona-editor")
111
+ return state;
112
+ if (!top.provider || !top.model)
113
+ return state;
114
+ const entry = { provider: top.provider, model: top.model };
115
+ const buffer = writePersonaEntry(state.buffer, action.layer, top.persona, entry);
116
+ return {
117
+ ...state,
118
+ buffer,
119
+ view: state.view.slice(0, -1),
120
+ dirty: true,
121
+ };
122
+ }
123
+ case "delete-persona-entry": {
124
+ const buffer = deletePersonaEntry(state.buffer, action.layer, action.persona);
125
+ const changed = buffer !== state.buffer;
126
+ return changed ? { ...state, buffer, dirty: true } : state;
127
+ }
128
+ case "begin-override-edit": {
129
+ const editor = {
130
+ kind: "override-editor",
131
+ pipeline: action.pipeline,
132
+ phaseRole: action.phaseRole,
133
+ step: "pick-type",
134
+ provider: undefined,
135
+ cursor: 0,
136
+ };
137
+ return { ...state, view: [...state.view, editor] };
138
+ }
139
+ case "set-override-step": {
140
+ const top = state.view[state.view.length - 1];
141
+ if (top.kind !== "override-editor")
142
+ return state;
143
+ const updated = { ...top, step: action.step, cursor: 0 };
144
+ return { ...state, view: [...state.view.slice(0, -1), updated] };
145
+ }
146
+ case "set-override-provider": {
147
+ const top = state.view[state.view.length - 1];
148
+ if (top.kind !== "override-editor")
149
+ return state;
150
+ const updated = {
151
+ ...top,
152
+ provider: action.provider,
153
+ step: "pick-model",
154
+ cursor: 0,
155
+ };
156
+ return { ...state, view: [...state.view.slice(0, -1), updated] };
157
+ }
158
+ case "commit-override-name": {
159
+ const top = state.view[state.view.length - 1];
160
+ if (top.kind !== "override-editor")
161
+ return state;
162
+ const buffer = writePhaseOverride(state.buffer, top.pipeline, top.phaseRole, action.name);
163
+ return {
164
+ ...state,
165
+ buffer,
166
+ view: state.view.slice(0, -1),
167
+ dirty: true,
168
+ };
169
+ }
170
+ case "commit-override-inline": {
171
+ const top = state.view[state.view.length - 1];
172
+ if (top.kind !== "override-editor")
173
+ return state;
174
+ const buffer = writePhaseOverride(state.buffer, top.pipeline, top.phaseRole, {
175
+ provider: action.provider,
176
+ model: action.model,
177
+ });
178
+ return {
179
+ ...state,
180
+ buffer,
181
+ view: state.view.slice(0, -1),
182
+ dirty: true,
183
+ };
184
+ }
185
+ case "clear-phase-override": {
186
+ const buffer = clearPhaseOverride(state.buffer, action.pipeline, action.phaseRole);
187
+ const changed = buffer !== state.buffer;
188
+ // If invoked from inside the override-editor, also pop back to the phases list.
189
+ const top = state.view[state.view.length - 1];
190
+ const view = changed && top.kind === "override-editor" ? state.view.slice(0, -1) : state.view;
191
+ return changed ? { ...state, buffer, dirty: true, view } : state;
192
+ }
193
+ case "mark-clean":
194
+ return { ...state, dirty: false, lastSaved: action.lastSaved ?? state.lastSaved };
195
+ case "clear-status":
196
+ return { ...state, lastSaved: null };
197
+ case "request-quit":
198
+ // If a confirm-quit modal is already open, another `q` is a no-op
199
+ // (user must press y/n/esc). This is what makes repeated `q` "tricky"
200
+ // — without this guard, every q re-fires the modal and looks broken.
201
+ if (state.confirmQuit)
202
+ return state;
203
+ if (!state.dirty)
204
+ return { ...state, shouldExit: true };
205
+ return { ...state, confirmQuit: true };
206
+ case "confirm-quit":
207
+ return { ...state, confirmQuit: false, shouldExit: action.discard };
208
+ default:
209
+ return state;
210
+ }
211
+ }
212
+ //# sourceMappingURL=reducer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reducer.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/config-tui/state/reducer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ import type { ConfigTuiState, View, ResolvedPersonaEntry, PersonaPickerEntry, PipelineOverrideSummary, PhaseOverride, TierAssignment } from "./model.js";
2
+ import type { ConfigLayer } from "../../config-writer.js";
3
+ import { type Tier } from "../tier-meta.js";
4
+ export declare function getActiveView(state: ConfigTuiState): View;
5
+ export declare function listResolvedPersonas(state: ConfigTuiState): ResolvedPersonaEntry[];
6
+ export declare function listPersonaPickerEntries(state: ConfigTuiState): PersonaPickerEntry[];
7
+ export declare function uniqueProviders(state: ConfigTuiState): string[];
8
+ export declare function listPipelineOverrideSummaries(state: ConfigTuiState): PipelineOverrideSummary[];
9
+ export declare function getPhaseOverride(state: ConfigTuiState, pipeline: string, phaseRole: string): PhaseOverride | undefined;
10
+ import { type ResolveSource } from "../../model-resolver.js";
11
+ /** A row in the phase table (Screen 3 — "Show what runs at each step"). */
12
+ export interface PhaseTableRow {
13
+ /** Phase role (e.g. "plan", "review-plan"). */
14
+ role: string;
15
+ /** Persona name (e.g. "engineer"). */
16
+ persona: string;
17
+ /** Persona emoji (e.g. "🌱"). */
18
+ personaEmoji: string;
19
+ /** Persona tier ("heavy" | "standard" | "light"). */
20
+ tier: Tier;
21
+ /** Resolved model string ("provider:model") or "(inherit pi current)". */
22
+ resolved: string;
23
+ /** Raw model resolver source ("L1", "L2", "L4-inline", etc.). */
24
+ rawSource: ResolveSource;
25
+ /** Human-readable source label (e.g. "Standard tier (global)"). */
26
+ sourceLabel: string;
27
+ }
28
+ /** Map a model-resolver source + persona tier + resolved-layer to a
29
+ * human-readable source label per the plan's cascade vocabulary.
30
+ *
31
+ * | Internal | Plain English |
32
+ * |-----------|---------------|
33
+ * | L4-inline / L4-name | "Step override" |
34
+ * | L3 | "Per-persona override (pipeline)" |
35
+ * | L2 | "{Tier} tier (project)" |
36
+ * | L1 | "{Tier} tier (global)" |
37
+ * | default | "Default fallback" |
38
+ * | inherit | "Falls back to pi current" |
39
+ */
40
+ export declare function sourceToLabel(rawSource: ResolveSource, tier: Tier | undefined, isProject: boolean): string;
41
+ /** Build the phase table for Screen 3.
42
+ * Joins PHASE_PERSONA_TABLE with model resolution results. */
43
+ export declare function getPhaseTable(state: ConfigTuiState): PhaseTableRow[];
44
+ /** Determine the effective model for an entire tier.
45
+ * Returns "set" when all personas in the tier resolve to the same model,
46
+ * "mixed" when some are missing or they diverge, "unset" when none are resolved. */
47
+ export declare function getTierAssignment(state: ConfigTuiState, tier: Tier): TierAssignment;
48
+ /** Return all three tier assignments as an array (stable order: heavy, standard, light). */
49
+ export declare function getAllTierAssignments(state: ConfigTuiState): Array<{
50
+ tier: Tier;
51
+ assignment: TierAssignment;
52
+ }>;
53
+ /** Scope-aware tier assignment: returns what's set at the given scope layer.
54
+ * When scope is "global", shows global-layer assignments only.
55
+ * When scope is "project", shows the resolved (merged) view since project
56
+ * layer is where overrides live on top of global.
57
+ * If a tier has no assignment at the active scope layer but has one at
58
+ * the other layer, shows { status: "set-in-other-layer" } with the details. */
59
+ export type ScopedTierAssignment = {
60
+ status: "set";
61
+ provider: string;
62
+ model: string;
63
+ layer: ConfigLayer;
64
+ } | {
65
+ status: "set-in-other-layer";
66
+ provider: string;
67
+ model: string;
68
+ otherLayer: ConfigLayer;
69
+ } | {
70
+ status: "mixed";
71
+ } | {
72
+ status: "unset";
73
+ };
74
+ export declare function getScopedTierAssignment(state: ConfigTuiState, tier: Tier, scope: ConfigLayer): ScopedTierAssignment;
75
+ export declare function getAllScopedTierAssignments(state: ConfigTuiState, scope: ConfigLayer): Array<{
76
+ tier: Tier;
77
+ assignment: ScopedTierAssignment;
78
+ }>;
79
+ /** Which tier does a persona belong to? Returns undefined for unknown names. */
80
+ export declare function getTierForPersona(persona: string): Tier | undefined;
81
+ /** Persona names in a tier. */
82
+ export declare function getPersonasInTier(tier: Tier): readonly string[];
83
+ /** True when neither global nor project config has any persona-model assignments.
84
+ * Replaces the old `state.isEmpty` snapshot — this is derived from buffer,
85
+ * so it stays correct after mutations. */
86
+ export declare function isConfigEmpty(state: ConfigTuiState): boolean;
87
+ /** Human-readable source label for a persona-model assignment.
88
+ * Replaces the old raw L1/L2/default-L1/default-L2 display.
89
+ * Uses tier labels when the persona has a known tier, otherwise falls back
90
+ * to generic "global"/"project" labels. */
91
+ export declare function personaSourceLabel(persona: string, source: "L1" | "L2"): string;
@@ -0,0 +1,231 @@
1
+ // Config TUI selectors — read-only derived data from state.
2
+ // Split from state.ts (Phase 1).
3
+ import { TIERS, TIER_PERSONAS, PERSONA_META } from "../tier-meta.js";
4
+ export function getActiveView(state) {
5
+ return state.view[state.view.length - 1];
6
+ }
7
+ export function listResolvedPersonas(state) {
8
+ const out = new Map();
9
+ const projectMap = state.buffer.project["persona-models"] ?? {};
10
+ const globalMap = state.buffer.global["persona-models"] ?? {};
11
+ for (const [persona, entry] of Object.entries(globalMap)) {
12
+ out.set(persona, { persona, provider: entry.provider, model: entry.model, source: "L1" });
13
+ }
14
+ // Project layer wins per-key
15
+ for (const [persona, entry] of Object.entries(projectMap)) {
16
+ out.set(persona, { persona, provider: entry.provider, model: entry.model, source: "L2" });
17
+ }
18
+ return [...out.values()].sort((a, b) => a.persona.localeCompare(b.persona));
19
+ }
20
+ export function listPersonaPickerEntries(state) {
21
+ const assignmentsByName = new Map(listResolvedPersonas(state).map((p) => [p.persona, p]));
22
+ const catalogue = state.personaCatalogue.filter((p) => p !== "default").sort();
23
+ const order = ["default", ...catalogue];
24
+ const seen = new Set(order);
25
+ for (const name of assignmentsByName.keys()) {
26
+ if (!seen.has(name)) {
27
+ order.push(name);
28
+ seen.add(name);
29
+ }
30
+ }
31
+ return order.map((persona) => ({
32
+ persona,
33
+ assignment: assignmentsByName.get(persona),
34
+ inCatalogue: persona === "default" || state.personaCatalogue.includes(persona),
35
+ }));
36
+ }
37
+ export function uniqueProviders(state) {
38
+ const providers = new Set();
39
+ for (const m of state.availableModels)
40
+ providers.add(m.provider);
41
+ for (const p of state.authenticatedProviders)
42
+ providers.add(p);
43
+ return [...providers].sort();
44
+ }
45
+ export function listPipelineOverrideSummaries(state) {
46
+ const names = state.pipelineCatalogue ?? ["default"];
47
+ return names.map((pipeline) => {
48
+ const phases = state.buffer.project.pipelines?.[pipeline]?.phases ?? {};
49
+ const overrideCount = Object.values(phases).filter((p) => p["model-override"] !== undefined).length;
50
+ return { pipeline, overrideCount };
51
+ });
52
+ }
53
+ export function getPhaseOverride(state, pipeline, phaseRole) {
54
+ return state.buffer.project.pipelines?.[pipeline]?.phases?.[phaseRole]?.["model-override"];
55
+ }
56
+ // ── Phase table selector ────────────────────────────────────────────────────
57
+ import { PHASE_PERSONA_TABLE, TIER_LABELS } from "../tier-meta.js";
58
+ import { resolveModelForPhase } from "../../model-resolver.js";
59
+ /** Map a model-resolver source + persona tier + resolved-layer to a
60
+ * human-readable source label per the plan's cascade vocabulary.
61
+ *
62
+ * | Internal | Plain English |
63
+ * |-----------|---------------|
64
+ * | L4-inline / L4-name | "Step override" |
65
+ * | L3 | "Per-persona override (pipeline)" |
66
+ * | L2 | "{Tier} tier (project)" |
67
+ * | L1 | "{Tier} tier (global)" |
68
+ * | default | "Default fallback" |
69
+ * | inherit | "Falls back to pi current" |
70
+ */
71
+ export function sourceToLabel(rawSource, tier, isProject) {
72
+ switch (rawSource) {
73
+ case "L4-inline":
74
+ case "L4-name":
75
+ return "Step override";
76
+ case "L3":
77
+ return "Per-persona override";
78
+ case "L2":
79
+ if (tier)
80
+ return `${TIER_LABELS[tier]} tier (project)`;
81
+ return "Per-persona (project)";
82
+ case "L1":
83
+ if (tier)
84
+ return `${TIER_LABELS[tier]} tier (global)`;
85
+ return "Per-persona (global)";
86
+ case "default":
87
+ return "Default fallback";
88
+ case "inherit":
89
+ return "Falls back to pi current";
90
+ }
91
+ }
92
+ /** Build the phase table for Screen 3.
93
+ * Joins PHASE_PERSONA_TABLE with model resolution results. */
94
+ export function getPhaseTable(state) {
95
+ const pipelineNames = state.pipelineCatalogue ?? ["default"];
96
+ const pipeline = pipelineNames[0] ?? "default";
97
+ return PHASE_PERSONA_TABLE.map((phase) => {
98
+ const result = resolveModelForPhase(pipeline, phase.role, phase.personaNoun, {
99
+ ...state.buffer.global,
100
+ ...state.buffer.project,
101
+ _global: state.buffer.global,
102
+ _project: state.buffer.project,
103
+ });
104
+ const resolved = result.model
105
+ ? `${result.model.provider}:${result.model.model}`
106
+ : "(inherit pi current)";
107
+ const meta = PERSONA_META[phase.personaNoun];
108
+ const isProject = result.source === "L2" || result.source === "L4-inline" || result.source === "L4-name" || result.source === "L3";
109
+ return {
110
+ role: phase.role,
111
+ persona: phase.personaNoun,
112
+ personaEmoji: meta?.emoji ?? "",
113
+ tier: phase.tier,
114
+ resolved,
115
+ rawSource: result.source,
116
+ sourceLabel: sourceToLabel(result.source, phase.tier, isProject),
117
+ };
118
+ });
119
+ }
120
+ // ── Tier selectors ───────────────────────────────────────────────────────────
121
+ /** Determine the effective model for an entire tier.
122
+ * Returns "set" when all personas in the tier resolve to the same model,
123
+ * "mixed" when some are missing or they diverge, "unset" when none are resolved. */
124
+ export function getTierAssignment(state, tier) {
125
+ const personas = TIER_PERSONAS[tier];
126
+ const resolved = listResolvedPersonas(state);
127
+ const resolvedMap = new Map(resolved.map((p) => [p.persona, p]));
128
+ const entries = personas.map((p) => resolvedMap.get(p));
129
+ // All tier personas must be in the resolved map.
130
+ const allPresent = entries.every((e) => e !== undefined);
131
+ if (!allPresent) {
132
+ // If none are resolved → unset; if partial → mixed
133
+ const anyPresent = entries.some((e) => e !== undefined);
134
+ return anyPresent ? { status: "mixed" } : { status: "unset" };
135
+ }
136
+ // All present — check they agree on provider:model
137
+ const first = entries[0];
138
+ const allSame = entries.every((e) => e.provider === first.provider && e.model === first.model);
139
+ if (!allSame)
140
+ return { status: "mixed" };
141
+ const layer = first.source.endsWith("L2") ? "project" : "global";
142
+ return { status: "set", provider: first.provider, model: first.model, layer };
143
+ }
144
+ /** Return all three tier assignments as an array (stable order: heavy, standard, light). */
145
+ export function getAllTierAssignments(state) {
146
+ return TIERS.map((tier) => ({ tier, assignment: getTierAssignment(state, tier) }));
147
+ }
148
+ export function getScopedTierAssignment(state, tier, scope) {
149
+ const personas = TIER_PERSONAS[tier];
150
+ const targetBuffer = state.buffer[scope];
151
+ const otherBuffer = state.buffer[scope === "global" ? "project" : "global"];
152
+ const targetPersonaModels = targetBuffer["persona-models"] ?? {};
153
+ const otherPersonaModels = otherBuffer["persona-models"] ?? {};
154
+ // Check if all personas in this tier have assignments in the target layer
155
+ const targetEntries = personas.map((p) => targetPersonaModels[p]);
156
+ const targetPresent = targetEntries.filter((e) => e !== undefined);
157
+ if (targetPresent.length === personas.length) {
158
+ // All tier personas have assignments in target layer
159
+ const allSame = targetEntries.every((e) => e !== undefined && e.provider === targetEntries[0].provider && e.model === targetEntries[0].model);
160
+ if (allSame) {
161
+ return {
162
+ status: "set",
163
+ provider: targetEntries[0].provider,
164
+ model: targetEntries[0].model,
165
+ layer: scope,
166
+ };
167
+ }
168
+ return { status: "mixed" };
169
+ }
170
+ if (targetPresent.length === 0) {
171
+ // No assignments in target layer
172
+ // Check if any are set in the other layer
173
+ const otherEntries = personas.map((p) => otherPersonaModels[p]);
174
+ const otherPresent = otherEntries.filter((e) => e !== undefined);
175
+ if (otherPresent.length > 0) {
176
+ // Some are set in the other layer — show that
177
+ const allSameOther = otherPresent.every((e) => e.provider === otherPresent[0].provider && e.model === otherPresent[0].model);
178
+ if (allSameOther) {
179
+ return {
180
+ status: "set-in-other-layer",
181
+ provider: otherPresent[0].provider,
182
+ model: otherPresent[0].model,
183
+ otherLayer: scope === "global" ? "project" : "global",
184
+ };
185
+ }
186
+ return { status: "mixed" };
187
+ }
188
+ return { status: "unset" };
189
+ }
190
+ // Partial assignments in target layer
191
+ return { status: "mixed" };
192
+ }
193
+ export function getAllScopedTierAssignments(state, scope) {
194
+ return TIERS.map((tier) => ({ tier, assignment: getScopedTierAssignment(state, tier, scope) }));
195
+ }
196
+ /** Which tier does a persona belong to? Returns undefined for unknown names. */
197
+ export function getTierForPersona(persona) {
198
+ return PERSONA_META[persona]?.tier;
199
+ }
200
+ /** Persona names in a tier. */
201
+ export function getPersonasInTier(tier) {
202
+ return TIER_PERSONAS[tier];
203
+ }
204
+ // ── isEmpty selector (Phase E — replaces state.isEmpty snapshot) ──────────
205
+ /** True when neither global nor project config has any persona-model assignments.
206
+ * Replaces the old `state.isEmpty` snapshot — this is derived from buffer,
207
+ * so it stays correct after mutations. */
208
+ export function isConfigEmpty(state) {
209
+ const g = state.buffer.global;
210
+ const p = state.buffer.project;
211
+ const gEmpty = !g || !g["persona-models"] || Object.keys(g["persona-models"]).length === 0;
212
+ const pEmpty = !p || !p["persona-models"] || Object.keys(p["persona-models"]).length === 0;
213
+ return gEmpty && pEmpty;
214
+ }
215
+ // ── Source label for persona list display ─────────────────────────────────
216
+ /** Human-readable source label for a persona-model assignment.
217
+ * Replaces the old raw L1/L2/default-L1/default-L2 display.
218
+ * Uses tier labels when the persona has a known tier, otherwise falls back
219
+ * to generic "global"/"project" labels. */
220
+ export function personaSourceLabel(persona, source) {
221
+ const tier = PERSONA_META[persona]?.tier;
222
+ const layer = source === "L1" ? "global" : "project";
223
+ if (persona === "default") {
224
+ return `Default fallback (${layer})`;
225
+ }
226
+ if (tier) {
227
+ return `${TIER_LABELS[tier]} tier (${layer})`;
228
+ }
229
+ return `Per-persona (${layer})`;
230
+ }
231
+ //# sourceMappingURL=selectors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectors.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/config-tui/state/selectors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export type { View, ConfigBuffer, AvailableModel, InitOptions, ConfigTuiState, ConfigTuiAction, PhaseOverride, ConfigLayer, ResolvedPersonaEntry, PersonaPickerEntry, PipelineOverrideSummary, TierAssignment, } from "./state/model.js";
2
+ export { CANONICAL_PHASES } from "./state/constants.js";
3
+ export { initialState } from "./state/init.js";
4
+ export { reducer } from "./state/reducer.js";
5
+ export { getActiveView, listResolvedPersonas, listPersonaPickerEntries, uniqueProviders, listPipelineOverrideSummaries, getPhaseOverride, getTierAssignment, getAllTierAssignments, getTierForPersona, getPersonasInTier, getPhaseTable, sourceToLabel, type PhaseTableRow, type ScopedTierAssignment, getScopedTierAssignment, getAllScopedTierAssignments, isConfigEmpty, personaSourceLabel, } from "./state/selectors.js";
6
+ export { writePersonaEntry, deletePersonaEntry, writePhaseOverride, clearPhaseOverride, writeTierAssignment, } from "./state/buffer.js";
@@ -0,0 +1,11 @@
1
+ // Config TUI state model — re-exports from split modules.
2
+ // Phase 1: This file is now a barrel that re-exports everything from state/.
3
+ // The implementation lives in state/model.ts, state/init.ts, state/reducer.ts,
4
+ // state/selectors.ts, state/buffer.ts, and state/constants.js.
5
+ // Phase 3: authError added to InitOptions and ConfigTuiState.
6
+ export { CANONICAL_PHASES } from "./state/constants.js";
7
+ export { initialState } from "./state/init.js";
8
+ export { reducer } from "./state/reducer.js";
9
+ export { getActiveView, listResolvedPersonas, listPersonaPickerEntries, uniqueProviders, listPipelineOverrideSummaries, getPhaseOverride, getTierAssignment, getAllTierAssignments, getTierForPersona, getPersonasInTier, getPhaseTable, sourceToLabel, getScopedTierAssignment, getAllScopedTierAssignments, isConfigEmpty, personaSourceLabel, } from "./state/selectors.js";
10
+ export { writePersonaEntry, deletePersonaEntry, writePhaseOverride, clearPhaseOverride, writeTierAssignment, } from "./state/buffer.js";
11
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/config-tui/state.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,6EAA6E;AAC7E,+EAA+E;AAC/E,+DAA+D;AAC/D,8DAA8D;AAiB9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,wBAAwB,EACxB,eAAe,EACf,6BAA6B,EAC7B,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,aAAa,EAGb,uBAAuB,EACvB,2BAA2B,EAC3B,aAAa,EACb,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { Theme } from "@earendil-works/pi-coding-agent";
2
+ export type { Theme };
3
+ /** Horizontal rule spanning the full width, themed as a border. */
4
+ export declare function rule(width: number, theme: Theme): string;
5
+ /** Breadcrumb: "forge config › personas › pick which". */
6
+ export declare function breadcrumb(parts: string[], width: number, theme: Theme): string;
7
+ export declare function cursor(isSelected: boolean, theme: Theme): string;
8
+ export declare function authBadge(ok: boolean, theme: Theme): string;
9
+ export declare function warning(text: string, theme: Theme): string;
10
+ export declare function muted(text: string, theme: Theme): string;
11
+ export declare function dim(text: string, theme: Theme): string;
12
+ export declare function accent(text: string, theme: Theme): string;
13
+ export declare function accentBold(text: string, theme: Theme): string;
14
+ export declare function error(text: string, theme: Theme): string;
15
+ export declare function success(text: string, theme: Theme): string;
16
+ /** Mark an unsaved-change indicator — themed as warning. */
17
+ export declare function dirtyMarker(theme: Theme): string;
18
+ /** Tier badge — displays Heavy / Standard / Light in accent color. */
19
+ export declare function tierBadge(tier: "heavy" | "standard" | "light", theme: Theme): string;
20
+ /**
21
+ * Right-pad a string that may contain ANSI escape codes to a given visible width.
22
+ * Uses visibleWidth so ANSI codes don't inflate the padding.
23
+ * Does NOT truncate — allows over-wide columns. Width-safety truncation
24
+ * is applied at the line level by truncateLines() / safeLines().
25
+ */
26
+ export declare function padRight(text: string, width: number): string;
27
+ /**
28
+ * Truncate a potentially-ANSI string to a visible width, padding with spaces
29
+ * if shorter. This replaces the old padRight for column-aligned output and
30
+ * is safe for themed text.
31
+ */
32
+ export declare function padOrTruncate(text: string, width: number): string;
33
+ /**
34
+ * Truncate every line to the given visible width. Applied as a final safety
35
+ * guard in every screen's render method so no line overflows the terminal.
36
+ */
37
+ export declare function truncateLines(lines: string[], width: number): string[];