feat(session-limits): LS8-front — filet humain niveau 3 (saisie d'heure de reprise)

UI permettant à l'humain de renseigner l'heure de reprise quand le
niveau 2 détecte une limite sans heure exploitable.

- ports/index.ts : setResumeAt(agentId, resetsAtMs) sur InputGateway.
- adapters/input.ts : setResumeAt → invoke("set_resume_at").
- adapters/mock/index.ts : MockInputGateway.setResumeAt (resumeArmings[]).
- features/agents/useAgents.ts : action setResumeAt (sans mutation optimiste).
- features/agents/AgentLimitBadge.tsx : formulaire de saisie d'heure sur
  l'état suspected sans heure + helper pur timeInputToEpochMs (TODO LS7 retiré).
- features/agents/AgentsPanel.tsx : câblage onSetResumeAt.

Tests AgentLimitBadge.test.tsx mis à jour au nouveau contrat + couverture LS8 ;
typecheck propre, suite agents verte.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-17 08:44:54 +02:00
parent c480d2820a
commit 5d9dd32c29
7 changed files with 225 additions and 29 deletions

View File

@ -121,6 +121,13 @@ export interface AgentsViewModel {
* resume had already fired / none was armed).
*/
cancelResume: (agentId: string) => Promise<boolean>;
/**
* Human net (level 3, ARCHITECTURE §21.1): arms a resume at a user-chosen
* `resetsAtMs` (epoch-ms) for an agent whose limit was suspected without a
* reliable time. No optimistic mutation — the backend re-emits
* `agentResumeScheduled`, which flips the badge to the nominal countdown.
*/
setResumeAt: (agentId: string, resetsAtMs: number) => Promise<void>;
}
function describe(e: unknown): string {
@ -447,6 +454,19 @@ export function useAgents(projectId: string): AgentsViewModel {
[input],
);
const setResumeAt = useCallback(
async (agentId: string, resetsAtMs: number): Promise<void> => {
// No optimistic mutation: the backend re-emits `agentResumeScheduled`,
// which the subscription folds into `limitByAgent` (badge → countdown).
try {
await input?.setResumeAt(agentId, resetsAtMs);
} catch (e) {
setError(describe(e));
}
},
[input],
);
return {
agents,
selectedAgentId,
@ -468,5 +488,6 @@ export function useAgents(projectId: string): AgentsViewModel {
launchAgent,
stopAgent,
cancelResume,
setResumeAt,
};
}