refactor: drop the two store members nothing consults

`TuiModelStore.confirmSatisfied()` and `approvalFor()` had no caller
outside their own tests. The first one mattered: it answered "does the
typed text authorize this kill?" with an exact name match, while the rule
actually consulted (`confirmAccepts()` in tui-app) also accepts the
8-character id prefix a mux name carries. Two divergent answers to one
question, the stricter one unreachable and waiting to be picked up by
mistake. knip cannot see class members, so the dead-code sweep never
flagged either.

The tests they existed for now assert observable state instead, and the
approvals one got stronger on the way: it checks that a session id coming
back does not inherit the dead session's dialog, which is the invariant
`removeSession()` is actually keeping.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer
2026-08-22 14:13:58 +02:00
parent 954a9ac26a
commit 1385415e53
2 changed files with 18 additions and 18 deletions
+6 -10
View File
@@ -349,10 +349,6 @@ export class TuiModelStore implements TuiRenderModel {
});
}
approvalFor(sessionId: string): ApprovalItem | undefined {
return this.approvalsBySession.get(sessionId);
}
sessions(): TuiSessionRow[] {
return [...this.sessionsById.values()];
}
@@ -440,7 +436,12 @@ export class TuiModelStore implements TuiRenderModel {
this.touch();
}
/** Arm the typed-name confirmation for `x` (kill). */
/**
* Arm the typed-name confirmation for `x` (kill). Whether what the user typed
* AUTHORIZES the kill is `confirmAccepts()` in tui-app, which owns that rule
* for every caller: a second copy here answered the same question differently
* (it refused the id prefix a mux name carries) and nothing consulted it.
*/
beginConfirmKill(row: TuiRow): void {
this.confirm = {
sessionId: row.session.sessionId,
@@ -457,11 +458,6 @@ export class TuiModelStore implements TuiRenderModel {
this.touch();
}
/** Does the typed text authorize the kill? Exact match on the name shown. */
confirmSatisfied(): boolean {
return this.confirm !== null && this.confirm.typed.trim() === this.confirm.name;
}
/** Drop whatever overlay owns the keyboard and go back to the list. */
closeOverlay(): void {
this.confirm = null;
+12 -8
View File
@@ -262,28 +262,32 @@ describe('the store', () => {
expect(flattenRows(model.groups())).toHaveLength(3);
});
it('tracks the confirm-kill overlay and only accepts the exact name', () => {
// Whether the typed text AUTHORIZES the kill is `confirmAccepts()` in
// tui-app, tested there; the store only carries what was typed.
it('tracks the confirm-kill overlay, keyed to the name it showed', () => {
const model = createTuiModel();
model.replaceSessions([session({ sessionId: 'a', name: 'w4-api' })]);
model.beginConfirmKill(model.rows()[0]);
expect(model.mode).toBe('confirm-kill');
expect(model.confirmSatisfied()).toBe(false);
expect(model.confirm).toEqual({ sessionId: 'a', name: 'w4-api', typed: '' });
model.setConfirmInput('w4-ap');
expect(model.confirmSatisfied()).toBe(false);
model.setConfirmInput('w4-api');
expect(model.confirmSatisfied()).toBe(true);
expect(model.confirm?.typed).toBe('w4-ap');
model.closeOverlay();
expect(model.mode).toBe('list');
expect(model.confirm).toBeNull();
});
it('drops a session approval along with the session', () => {
it('drops a session approval along with the session, and never resurrects it', () => {
const model = createTuiModel();
model.replaceSessions([session({ sessionId: 'a' })]);
model.setApprovals([approval({ sessionId: 'a' })]);
expect(model.approvalFor('a')).toBeDefined();
expect(model.rows()[0].approval).toBeDefined();
model.removeSession('a');
expect(model.approvalFor('a')).toBeUndefined();
expect(model.rows()).toHaveLength(0);
// The same id coming back must not inherit the dead session's dialog.
model.upsertSession(session({ sessionId: 'a' }));
expect(model.rows()[0].approval).toBeUndefined();
expect(model.rows()[0].state).toBe('idle');
});
});