feat(m6): toFloorEscapeRecord — распознавание escape-одобрения

This commit is contained in:
Дмитрий
2026-06-07 18:44:09 +03:00
parent 87d84a2e3f
commit 6b44e7afd8
2 changed files with 27 additions and 0 deletions
+13
View File
@@ -189,6 +189,19 @@ export function toApprovalRecord(answer, { question, nowMs = Date.now() } = {})
return { type: 'approve_git_operation', command, ts: nowMs };
}
const FLOOR_ESCAPE_RE = /FLOOR-ESCAPE:\s*([^\n]+?)\s*$/;
/** Перевести ответ AskUser в floor_escape-запись, либо null. Stop-намерения → null. */
export function toFloorEscapeRecord(answer, { nowMs = Date.now() } = {}) {
if (typeof answer !== 'string') return null;
if (isStopAnswer(answer)) return null;
const m = FLOOR_ESCAPE_RE.exec(answer);
if (!m) return null;
const action = m[1].trim();
if (!action) return null;
return { type: 'floor_escape', action, ts: nowMs };
}
import { signPayload, verifyReceipt, RECEIPT_DOMAINS } from './receipt-sign.mjs';
/**
+14
View File
@@ -299,3 +299,17 @@ describe('toApprovalRecord (Stream H Task 6 — schema sync)', () => {
expect(toApprovalRecord(42)).toBeNull();
});
});
import { toFloorEscapeRecord } from './askuser-answer-parser.mjs';
describe('askuser-answer-parser toFloorEscapeRecord', () => {
it('распознаёт FLOOR-ESCAPE токен → запись floor_escape', () => {
const r = toFloorEscapeRecord('Разрешаю FLOOR-ESCAPE: bash:git push --force', { nowMs: 5 });
expect(r).toEqual({ type: 'floor_escape', action: 'bash:git push --force', ts: 5 });
});
it('без токена → null', () => {
expect(toFloorEscapeRecord('просто да', { nowMs: 5 })).toBe(null);
});
it('stop-намерение → null', () => {
expect(toFloorEscapeRecord('отмена FLOOR-ESCAPE: bash:x', { nowMs: 5 })).toBe(null);
});
});