import { PromptOverride } from '@happyvertical/smrt-prompts'; import { DatabaseInterface } from '@happyvertical/sql'; import { AgentPersonaCollection } from './agent-persona.js'; import { DirectivePrincipal } from './directive-principal.js'; import { DirectiveProposal, DirectiveProposalCollection } from './directive-proposal.js'; import { Feedback, FeedbackCollection } from './feedback.js'; /** Raised when a principal without the activation permission attempts to review. */ export declare class DirectiveActivationDeniedError extends Error { constructor(message?: string); } /** Raised when a review is attempted on a proposal that is not pending. */ export declare class DirectiveNotPendingError extends Error { constructor(status: string); } /** Options for {@link DirectiveApprovalService}. */ export interface DirectiveApprovalServiceOptions { db: DatabaseInterface; proposals?: DirectiveProposalCollection; feedback?: FeedbackCollection; personas?: AgentPersonaCollection; } /** Result of approving a proposal. */ export interface DirectiveApprovalResult { proposal: DirectiveProposal; /** The activated persona-scoped override. */ override: PromptOverride; /** The recorded `accept` signal. */ signal: Feedback; } /** Result of rejecting a proposal. */ export interface DirectiveRejectionResult { proposal: DirectiveProposal; /** The recorded `reject` signal. */ signal: Feedback; } /** A proposal reference: the row, or its id. */ export type ProposalRef = DirectiveProposal | string; /** * The permission-gated review surface for persona directives. */ export declare class DirectiveApprovalService { private readonly db; private proposals?; private feedback?; private personas?; constructor(options: DirectiveApprovalServiceOptions); /** * Assert a principal is authorised to review directives. The single gate: * everything privileged in this service calls it first. * * @throws {DirectiveActivationDeniedError} when the principal lacks the slug. */ assertCanActivate(principal: DirectivePrincipal): void; /** * Assert a principal may review a specific proposal: its resolved tenant, when * bound, must match the proposal's tenant. Permissions are resolved per * tenant, so holding the slug in one tenant must not authorise activating * another tenant's directive. * * @throws {DirectiveActivationDeniedError} on a cross-tenant attempt. */ private assertTenantMatch; /** * Approve a pending proposal: activate the persona-scoped override and record * an `accept` signal. Pass `editedInstructions` to activate a revised text * (the proposal keeps the model's original as its audit record; the override * holds what was activated). * * @throws {DirectiveActivationDeniedError} when the principal lacks the slug. * @throws {DirectiveNotPendingError} when the proposal is already reviewed. */ approve(ref: ProposalRef, principal: DirectivePrincipal, options?: { note?: string; editedInstructions?: string; }): Promise; /** * Reject a pending proposal: record a `reject` signal and close it so it is * never re-surfaced. * * @throws {DirectiveActivationDeniedError} when the principal lacks the slug. * @throws {DirectiveNotPendingError} when the proposal is already reviewed. */ reject(ref: ProposalRef, principal: DirectivePrincipal, options?: { note?: string; }): Promise; private loadPending; private getProposal; private recordSignal; private syncPersonaInstructions; private personasCollection; private proposalsCollection; private feedbackCollection; } //# sourceMappingURL=directive-approval.d.ts.map