import type { ValidationIssue } from '../artifacts/schema'; /** * Append-only scope remediation protocol (v1). * * A remediation corrects the *live* state of a closed scope without touching the immutable * checkpoint, snapshot, narrative or ledger commitment that proves how the scope originally closed. * Every correction is a strongly typed, all-or-nothing batch: there is no generic JSON Patch and no * free-form payload anywhere in this contract. Adding a new correction capability means adding a * new discriminated-union member plus its own validation, preconditions and regression matrix. */ export declare const SCOPE_REMEDIATION_KIND: "scope-remediation"; /** Immutable record version emitted before compact witnesses existed. */ export declare const SCOPE_REMEDIATION_SCHEMA_VERSION: 1; /** Current immutable record version: operations plus a compact replay witness, never a SprintFile. */ export declare const SCOPE_REMEDIATION_V2_SCHEMA_VERSION: 2; /** * Revision that introduces record-level debt canonicalization (ADR-0003). * * It is an explicit revision rather than a silent extension of v2 so a reader that predates * `debt.canonicalize` fails closed as unsupported instead of interpreting a record it cannot * execute. `CURRENT_…` deliberately stays at v2: a batch is written at the LOWEST revision that * admits every operation in it (see `requiredRemediationRevision`), so an origin-only remediation * still emits exactly the v2 bytes it always did and only a canonicalization raises the revision. */ export declare const SCOPE_REMEDIATION_V3_SCHEMA_VERSION: 3; export declare const SCOPE_REMEDIATION_V4_SCHEMA_VERSION: 4; export declare const CURRENT_SCOPE_REMEDIATION_SCHEMA_VERSION: 2; export declare const SCOPE_REMEDIATION_SCHEMA_VERSIONS: { readonly V1: 1; readonly V2: 2; readonly V3: 3; readonly V4: 4; }; export type ScopeRemediationSchemaVersion = (typeof SCOPE_REMEDIATION_SCHEMA_VERSIONS)[keyof typeof SCOPE_REMEDIATION_SCHEMA_VERSIONS]; /** Closed operation registry across every revision. An unknown kind fails before any plan is produced. */ export declare const REMEDIATION_OPERATION_KINDS: readonly ["debt.origin.set", "debt.canonicalize", "convention.append", "adr.append", "ledger.checkpoint.reanchor"]; export type RemediationOperationKind = (typeof REMEDIATION_OPERATION_KINDS)[number]; /** * Which operations each revision may carry. A kind is bound to the revision that introduced it, so * a v1/v2 record containing `debt.canonicalize` is rejected rather than reinterpreted, and a v3 * record keeps executing the older operation unchanged. */ export declare const OPERATION_KINDS_BY_REVISION: Record; /** * The revisions current Kyro is allowed to WRITE, lowest first. v1 is readable forever but is never * emitted again: its snapshot witness was retired by the compact record. */ export declare const WRITABLE_SCOPE_REMEDIATION_SCHEMA_VERSIONS: readonly [2, 3, 4]; export type WritableScopeRemediationSchemaVersion = (typeof WRITABLE_SCOPE_REMEDIATION_SCHEMA_VERSIONS)[number]; /** The exact canonical debt key set an after-image must carry — no more, no fewer. */ export declare const CANONICAL_DEBT_AFTER_KEYS: readonly ["id", "title", "origin", "priority", "status", "targetSprint", "note"]; declare const DEBT_PRIORITIES: readonly ["critical", "high", "medium", "low"]; declare const DEBT_STATUSES: readonly ["open", "in_progress", "resolved", "deferred"]; /** SHA-256 commitment to an immutable checkpoint payload, copied from the live ledger anchor. */ export interface RemediationCheckpointCommitment { path: string; commitment: string; } /** The exact state a remediation is bound to. A stale digest or head must fail the transaction. */ export interface RemediationBase { stateSha256: string; /** Commitment of the preceding remediation record, or null for the first link in the chain. */ remediationHead: string | null; checkpoints: RemediationCheckpointCommitment[]; } /** A concrete historical defect. `path` is diagnostic only — it is never an executable pointer. */ export interface RemediationIssue { id: string; code: string; path: string; observedValueSha256: string; } /** Replace a `Debt.origin` that was persisted with a non-numeric value. */ export interface SetDebtOriginOperation { id: string; kind: 'debt.origin.set'; /** Ids of the issues this operation resolves; preserves the issue-to-operation mapping. */ resolves: string[]; debtId: string; /** Precondition: digest of the value currently stored in `debt[].origin`. */ expectedOriginSha256: string; /** Explicit numeric replacement supplied by the operator. Never inferred. */ origin: number; reason: string; } /** * Rewrite one legacy debt record into its exact canonical form (ADR-0002). * * This is deliberately record-level and closed: one debt, one atomic after-image, no path * expressions and no partial field patches. The origin-only operation above cannot add an absent * canonical field or retire a legacy-only key, which is precisely why the motivating scope could * not be repaired at all. * * The precondition binds the *whole* observed `debt[]` collection, not the single record: reordering * or editing any other debt entry between preparation and application changes what the operator * reviewed, and must invalidate the operation. * * Every value in `after` is operator-authorized. Evidence may suggest a value (ADR-0004), but no * suggestion reaches this structure without an explicit decision. */ export interface CanonicalizeDebtOperation { id: string; kind: 'debt.canonicalize'; /** Ids of the issues this operation resolves; preserves the issue-to-operation mapping. */ resolves: string[]; /** Identity of the debt being canonicalized. Must equal `after.id`. */ debtId: string; /** Precondition: digest of the complete observed `debt[]` collection. */ expectedDebtCollectionSha256: string; /** The exact seven-key canonical record that replaces the legacy one. */ after: CanonicalDebtAfterImage; /** Legacy-only keys this operation retires, recorded so the audit trail names what disappeared. */ retiredKeys: string[]; reason: string; } /** The seven-key canonical debt image. Structurally identical to `Debt`, declared here so the * protocol contract does not depend on the live state module. */ export interface CanonicalDebtAfterImage { id: string; title: string; origin: number; priority: (typeof DEBT_PRIORITIES)[number]; status: (typeof DEBT_STATUSES)[number]; targetSprint: number | null; note: string; } /** Append one structured convention. Binds the whole observed conventions[] collection. */ export interface AppendConventionOperation { id: string; kind: 'convention.append'; resolves: string[]; expectedConventionCollectionSha256: string; after: { id: string; rule: string; tags: string[]; addedSprint: number; }; reason: string; } export interface AppendAdrOperation { id: string; kind: 'adr.append'; resolves: string[]; expectedAdrCollectionSha256: string; after: { id: string; title: string; status: string; date: string; context: string; decision: string; consequences: string[]; alternatives: string[]; links?: Record; }; reason: string; } /** Change only checkpointSha256 on one ledger row identified by sprint number and slug. */ export interface ReanchorLedgerCheckpointOperation { id: string; kind: 'ledger.checkpoint.reanchor'; resolves: string[]; sprintN: number; sprintSlug: string; expectedOldSha256: string; afterSha256: string; reason: string; } export type RemediationOperation = SetDebtOriginOperation | CanonicalizeDebtOperation | AppendConventionOperation | AppendAdrOperation | ReanchorLedgerCheckpointOperation; export interface RemediationResult { stateSha256: string; /** Snapshot of the scope state after applying operations. Used by E1 to replay multi-record chains. */ snapshot: unknown; } export declare const COMPACT_REPLAY_WITNESS_KIND: "operations-replay"; export declare const COMPACT_REPLAY_WITNESS_SCHEMA_VERSION: 1; /** v2 needs no state image: the typed operations and bound digests are the replay evidence. */ export interface CompactReplayWitnessV1 { schemaVersion: typeof COMPACT_REPLAY_WITNESS_SCHEMA_VERSION; kind: typeof COMPACT_REPLAY_WITNESS_KIND; } export interface CompactRemediationResult { stateSha256: string; witness: CompactReplayWitnessV1; } export interface RemediationProvenance { reason: string; actor: string; kyroVersion: string; } /** Immutable record persisted at `archive/remediations/remediation-NNN.json`. */ export interface ScopeRemediationV1 { schemaVersion: typeof SCOPE_REMEDIATION_SCHEMA_VERSION; kind: typeof SCOPE_REMEDIATION_KIND; id: string; scope: string; createdAt: string; base: RemediationBase; issues: RemediationIssue[]; operations: RemediationOperation[]; result: RemediationResult; provenance: RemediationProvenance; } /** * Immutable compact record emitted by current Kyro. Historic v1 records are never rewritten. * * v2 and v3 share this one shape by design: the revision names which operations the record may * carry, not how the record is laid out. Keeping a single structure is what lets a v3 chain be * verified, replayed and certified by exactly the code paths that already handle v2 (ADR-0003). */ export interface CompactScopeRemediation { schemaVersion: WritableScopeRemediationSchemaVersion; kind: typeof SCOPE_REMEDIATION_KIND; id: string; scope: string; createdAt: string; base: RemediationBase; issues: RemediationIssue[]; operations: RemediationOperation[]; result: CompactRemediationResult; provenance: RemediationProvenance; } /** The compact record pinned to one revision, for callers that mean specifically v2 or v3. */ export type ScopeRemediationV2 = CompactScopeRemediation & { schemaVersion: typeof SCOPE_REMEDIATION_V2_SCHEMA_VERSION; }; export type ScopeRemediationV3 = CompactScopeRemediation & { schemaVersion: typeof SCOPE_REMEDIATION_V3_SCHEMA_VERSION; }; export type ScopeRemediationV4 = CompactScopeRemediation & { schemaVersion: typeof SCOPE_REMEDIATION_V4_SCHEMA_VERSION; }; export type ScopeRemediation = ScopeRemediationV1 | CompactScopeRemediation; /** * The LOWEST revision current Kyro writes that admits every operation in a batch. * * Choosing per batch rather than globally is what keeps ADR-0003 honest in both directions: an * origin-only remediation keeps emitting a v2 record byte-for-byte as before, so no existing chain, * reader or fixture is disturbed; a batch containing a `debt.canonicalize` is written as v3, so a * reader that predates the operation refuses the record instead of silently ignoring an operation it * cannot execute. Bumping a global CURRENT_… would have made every remediation unreadable to older * Kyro, which is a migration, not a revision. */ export declare function requiredRemediationRevision(operations: readonly RemediationOperation[]): WritableScopeRemediationSchemaVersion; export declare function isRemediationOperationKind(value: unknown): value is RemediationOperationKind; /** * Full fail-closed validation of a remediation record. Returns one issue per defect with a * field-specific path (e.g. `operations[0].origin`) so a rejection is actionable without guessing. */ export declare function validateScopeRemediation(value: unknown, path: string): ValidationIssue[]; export declare function isScopeRemediationSchemaVersion(value: unknown): value is ScopeRemediationSchemaVersion; export declare function asScopeRemediation(value: unknown): ScopeRemediation | null; export declare const REMEDIATION_MANIFEST_KIND: "scope-remediation-manifest"; /** * Operator-authored input to `remediate preview` / `remediate apply`. * * It declares the state the operator inspected (`base`) so a manifest written against an older * live state is rejected as stale rather than silently re-targeted. `kyroVersion`, `id`, `createdAt` * and `result` are supplied by the runtime — an operator cannot pre-declare the outcome of a * transaction Kyro has not evaluated yet. */ export interface RemediationManifestV1 { schemaVersion: typeof SCOPE_REMEDIATION_SCHEMA_VERSION | typeof SCOPE_REMEDIATION_V3_SCHEMA_VERSION | typeof SCOPE_REMEDIATION_V4_SCHEMA_VERSION; kind: typeof REMEDIATION_MANIFEST_KIND; scope: string; base: { stateSha256: string; remediationHead: string | null; }; issues: RemediationIssue[]; operations: RemediationOperation[]; provenance: { reason: string; actor: string; }; } export declare function validateRemediationManifest(value: unknown, path: string): ValidationIssue[]; /** * Preconditions a canonicalization must satisfy against the state actually on disk. * * Schema validation proves the operation is well-formed; this proves it still describes reality. * Pure and read-only: it takes the observed collection as a value and returns issues, so it can be * called from a planner, a preview, or a future apply without any of them owning the rule. * * `debtCollectionDigest` is injected rather than imported so this module stays free of the state * and hashing layers it must not depend on. */ export declare function verifyCanonicalizePreconditions(operation: CanonicalizeDebtOperation, observedDebt: readonly unknown[], debtCollectionDigest: (debt: readonly unknown[]) => string, path: string, prefix: string): ValidationIssue[]; export declare function isCanonicalizeDebtOperation(value: RemediationOperation): value is CanonicalizeDebtOperation; export {}; //# sourceMappingURL=protocol.d.ts.map