Files
brain/tools/blessed-ops.test.mjs
T
Дмитрий bbc053e0a6 feat: D1 — благословлённый ops-runbook (деплой выполняет агент под ревью)
Деплой, помеченный **Kind:** deploy и опечатанный (наставник+судья GO,
judge_mode=live-block), агент выполняет по белому списку шагов под ОДНИМ
согласием владельца `FLOOR-ESCAPE: ops-runbook:<plan-hash>` — без аварийного
выхода на каждую команду. «Ядерный» набор (rm -rf/force-push/migrate:fresh/
db:wipe) остаётся на per-command escape.

- plan-lock: freezePlan принимает kind (в подписанную базу + хеш, как delivery);
  не-'normal' добавляет поле, обычные планы байт-идентичны старым печатям.
- plan-skills: parsePlanKind (**Kind:** deploy|normal, default normal).
- seal-orchestration: sealablePlan/sealPlan прокидывают kind в печать.
- escape-grant: loadOpsRunbookGrants (окно = существование плана, БЕЗ 5-мин
  фильтра) + opsRunbookGrantOpen (точный матч на plan_id).
- floor-decide: floorDecide получает инъектируемый blessedOps(cmd); content-block
  команда из набора пропускается, ЯДЕРНЫЙ набор (bashIsFloor) исключён из послабления.
- blessed-ops (новый модуль-мост): buildBlessedOps + loadBlessedOpsForSession —
  знает план+пол, чтобы СОХРАНИТЬ Δ9 (enforce-floor не зависит от модуля печати плана).
  Предикат пускает команду только дословно из Bash-листов опечатанного deploy-плана.
- enforce-floor: gated — blessed-ops грузит план/гранты ТОЛЬКО при открытом
  ops-runbook-гранте; без согласия владельца пол плана не касается (Δ9 цел).

План: docs/superpowers/plans/2026-06-18-blessed-ops-runbook-plan.md
Спека: docs/superpowers/specs/2026-06-18-blessed-ops-runbook-design.md §3.1-3.7.
+33 теста, свод 4299 passed / 2 skipped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 13:19:22 +03:00

60 lines
3.3 KiB
JavaScript

import { describe, it, expect } from 'vitest';
import { buildBlessedOps, loadBlessedOpsForSession } from './blessed-ops.mjs';
import { freezePlan } from './plan-lock.mjs';
describe('buildBlessedOps (D1 — белый список из опечатанного deploy-плана)', () => {
const K = 'k-bless';
const norm = (p) => String(p);
const mk = (over) => freezePlan({ steps: [{ op: 'Bash', object: 'composer install' }], kind: 'deploy', judgeMode: 'live-block', key: K, nowMs: 1, ...over });
it('грант на хеш + kind:deploy + live-block + valid seal → предикат пускает Bash-шаг дословно', () => {
const plan = mk();
const bless = buildBlessedOps({ frozenPlan: plan, grants: [{ action: `ops-runbook:${plan.plan_id}`, ts: 1 }], key: K, verifyImpl: () => true, normalize: norm });
expect(typeof bless).toBe('function');
expect(bless('composer install')).toBe(true);
expect(bless('rm -rf /')).toBe(false);
});
it('нет гранта на этот хеш → null', () => {
const plan = mk();
expect(buildBlessedOps({ frozenPlan: plan, grants: [{ action: 'ops-runbook:OTHER', ts: 1 }], key: K, verifyImpl: () => true, normalize: norm })).toBe(null);
});
it('план не kind:deploy → null', () => {
const plan = freezePlan({ steps: [{ op: 'Bash', object: 'composer install' }], judgeMode: 'live-block', key: K, nowMs: 1 });
expect(buildBlessedOps({ frozenPlan: plan, grants: [{ action: `ops-runbook:${plan.plan_id}`, ts: 1 }], key: K, verifyImpl: () => true, normalize: norm })).toBe(null);
});
it('печать невалидна (verifyImpl→false) → null', () => {
const plan = mk();
expect(buildBlessedOps({ frozenPlan: plan, grants: [{ action: `ops-runbook:${plan.plan_id}`, ts: 1 }], key: K, verifyImpl: () => false, normalize: norm })).toBe(null);
});
it('judge_mode не live-block → null', () => {
const plan = mk({ judgeMode: 'shadow' });
expect(buildBlessedOps({ frozenPlan: plan, grants: [{ action: `ops-runbook:${plan.plan_id}`, ts: 1 }], key: K, verifyImpl: () => true, normalize: norm })).toBe(null);
});
it('нет frozenPlan → null', () => {
expect(buildBlessedOps({ frozenPlan: null, grants: [{ action: 'ops-runbook:x', ts: 1 }], key: K, verifyImpl: () => true })).toBe(null);
});
});
describe('loadBlessedOpsForSession (D1 — gated I/O: нет гранта → план не грузим)', () => {
it('нет ops-runbook-грантов → null, план НЕ грузится (Δ9 сохранён)', () => {
let planLoaded = false;
const r = loadBlessedOpsForSession('S', {
loadGrantsImpl: () => [],
loadPlanImpl: () => { planLoaded = true; return null; },
keyImpl: () => 'k',
});
expect(r).toBe(null);
expect(planLoaded).toBe(false);
});
it('есть грант на хеш + deploy-план → предикат построен', () => {
const key = 'k-load';
const plan = freezePlan({ steps: [{ op: 'Bash', object: 'composer install' }], kind: 'deploy', judgeMode: 'live-block', key, nowMs: 1 });
const bless = loadBlessedOpsForSession('S', {
loadGrantsImpl: () => [{ action: `ops-runbook:${plan.plan_id}`, ts: 1 }],
loadPlanImpl: () => plan,
keyImpl: () => key,
});
expect(typeof bless).toBe('function');
expect(bless('composer install')).toBe(true);
});
});