/** * CODEX-OWNERSHIP-MACHINE * * The EXECUTABLE replacement for the hand-rolled `if/then` ownership arms in * `codex-native.ts`. Each Codex-owned artifact (a generated `agent-harness-*` * profile, or the repo marketplace) has an OWNERSHIP STATE. A LIFECYCLE ACTION * (apply / re-apply / reduce / reset / re-add) is driven by an ACTOR (harness * or user). The decision for every (surface, state, actor, action) cell is * declared here as DATA — the `CODE_X_OWNERSHIP_TRANSITIONS` table — not as * scattered branches, so no transition can be left unguarded or drift from the * documented contract. This module is the single interpreter: classification * turns observed on-disk facts into a state, and resolution looks the matching * row up in the table and returns the concrete decision the adapter executes * against the filesystem. * * This module mirrors `CODEX-OWNERSHIP-TABLE.md` (the human-readable spec); the * table here IS the executable form the adapter code reads. The full matrix is * enumerable via `codexOwnershipMatrix()` for exhaustive transition-matrix * tests generated FROM the table — no hand-written transition is left outside * the enumerable set the tests sweep. */ /** * A single Codex custom-agent profile file Agent Harness owns. The machine * defines the record shape (single source of truth); `codex-native.ts` reads * and writes it via the manifest. */ export interface CodexAgentProfileRecord { fileName: string; /** Original pre-apply content; null when the file did not exist before. */ priorContent: string | null; /** * Content hash of the EXACT bytes this apply wrote for the profile. Reset / * reduced-agent reconcile removes (or restores the prior snapshot of) a * profile ONLY when the on-disk bytes still match this fingerprint; a user * who edited the generated `agent-harness-*.toml` after apply changes the * bytes, so the user's edits are preserved instead of deleted/overwritten. * Absent on legacy records written before the field existed. */ contentFingerprint?: string; /** * True when this profile is user-owned: the user edited the generated file * after apply, so Agent Harness relinquished ownership. The record is * RETAINED (not dropped) so a subsequent apply recognizes the profile as * user-owned and never regenerates/overwrites it. */ userOwned?: boolean; } /** The owned Codex surfaces the machine governs. */ export type CodexOwnershipSurface = "profile" | "marketplace"; /** * The lifecycle operation being performed on the surface. * * apply / re-apply / re-add all funnel an IN-COMING profile through the writer; * reduce / reset funnel DROPPED, absent, or reset profiles through cleanup. The * two groups resolve identically for a given state, but each action is * enumerated as a distinct row so the matrix is exhaustive and an action can * never silently go unexpressed by the table. */ export type CodexOwnershipAction = "apply" | "re-apply" | "reduce" | "reset" | "re-add"; /** * The principal whose ownership right a transition honors: `harness` owns the * artifact (created/wrote it, untouched), `user` owns it (edited it, deleted * it, replaced a harness file, or a legacy record we cannot prove we wrote). */ export type CodexOwnershipActor = "harness" | "user"; /** * Classification of a single Codex agent profile's ownership, derived from the * prior manifest record (or none) and the live on-disk bytes. */ export type CodexProfileState = /** No record and no live file: a fresh profile this apply may create. */ "untracked-absent" /** * No record but a live file: a pre-existing user file whose deterministic * name collides with the profile. The first apply DISPLACES it (records the * user's bytes as priorContent so reset restores them). */ | "untracked-displace" /** * Record says harness wrote it (fingerprint present, live bytes match) and * priorContent was null: harness created it from nothing. */ | "harness-created" /** * Record says harness wrote it (fingerprint matches) and priorContent was * non-null: harness displaced a pre-existing user file to write this. */ | "harness-displaced" /** Record is userOwned:true and the file is present. */ | "user-owned" /** Record has a fingerprint but the live bytes differ: user edited it. */ | "user-edited" /** Legacy no-fingerprint record: cannot prove we wrote those bytes. */ | "legacy-user-owned" /** Record exists but the live file is absent: the user deleted it. */ | "user-deleted"; /** Classification of the repo marketplace's whole-file ownership. */ export type CodexMarketplaceState = /** No marketplace file: this apply would create it from nothing. */ "untracked" /** Ownership says harness created it and the live bytes still match. */ | "harness-created-unchanged" /** Ownership says harness created it but the live bytes differ (user replaced it). */ | "harness-created-replaced" /** No harness provenance (pre-existing user or team marketplace). */ | "user-owned"; /** * The source of the `priorContent` a WRITE decision must record. * * - "none": record priorContent null (harness created it from nothing, or is * regenerating a deleted profile so reset must never resurrect stale bytes). * - "live": record the current on-disk bytes as prior (first apply displacing a * colliding user file — reset must restore them). * - "prior-record": carry the prior record's original priorContent forward * (a re-write of an already-owned profile must NOT re-snapshot harness bytes * as the user's "prior" — the re-apply-poisoning guard). */ export type CodexPriorContentMode = "none" | "live" | "prior-record"; /** The decision the machine returns for a profile cell; the adapter executes it. */ export type CodexProfileDecision = /** Create/regenerate the profile: write bytes, record the priorContent by mode. */ { kind: "write"; priorContentMode: CodexPriorContentMode; } /** Keep the user's live bytes, do not write; record the profile as user-owned. */ | { kind: "preserve-user-edit"; } /** Keep the user-owned profile and RETAIN its record across cleanup. */ | { kind: "retain-user-owned"; } /** Remove the harness-created file (priorContent was null). */ | { kind: "remove-harness-file"; } /** Restore the displaced user bytes (priorContent was non-null). */ | { kind: "restore-prior-content"; } /** The user-deleted file is already gone; drop its record without touching disk. */ | { kind: "ghost-drop"; }; /** Writer-side profile decisions (apply / re-apply / re-add rows). */ export type CodexWriteProfileDecision = Extract; /** Cleanup-side profile decisions (reduce / reset rows). */ export type CodexCleanupProfileDecision = Extract; /** The decision the machine returns for a marketplace cell. */ export type CodexMarketplaceDecision = /** Merge the managed entry and keep whole-file ownership (created:true). */ { kind: "merge-and-keep-ownership"; } /** Merge but relinquish whole-file ownership (created:false). */ | { kind: "merge-and-relinquish"; } /** Reset: no whole-file delete (preserve / strip-managed-entry only). */ | { kind: "marketplace-preserve"; } /** Reset: whole-delete the provably harness-created, byte-unchanged file. */ | { kind: "remove-marketplace-file"; }; /** A single transition row in the ownership table. */ export interface CodexOwnershipTransition { surface: CodexOwnershipSurface; state: CodexProfileState | CodexMarketplaceState; actor: CodexOwnershipActor; action: CodexOwnershipAction; /** The decision the interpreter returns when this cell is hit. */ decision: CodexProfileDecision | CodexMarketplaceDecision; /** * Human-readable contract line for the row, mirroring CODEX-OWNERSHIP-TABLE.md. * Names the Greptile/CodeRabbit finding or ownership doctrine this cell seals. */ contract: string; } /** * Writer-side profile rows. apply / re-apply / re-add resolve identically: the * OWNERSHIP STATE already captures whether this is a first write, a re-write, * or a re-add, so the writer makes the same decision per state for any of the * three in-coming actions. */ declare function profileWriteRows(action: "apply" | "re-apply" | "re-add"): CodexOwnershipTransition[]; /** Cleanup/reconcile-side profile rows (decision identical for reduce/reset). */ declare function profileCleanupRows(action: "reduce" | "reset"): CodexOwnershipTransition[]; /** Marketplace merge-side rows. */ declare function marketplaceMergeRows(action: "apply" | "re-apply" | "re-add"): CodexOwnershipTransition[]; /** Marketplace cleanup/reset-side rows. */ declare function marketplaceResetRows(action: "reduce" | "reset"): CodexOwnershipTransition[]; /** * The ownership transition table — the single source of truth. Every * (surface, state, actor, action) cell the adapter can reach has exactly one * row; `resolveOwnershipDecision` throws if a cell is missing, so an * unguarded/un-tested transition fails loudly instead of silently degrading. */ export declare const CODE_X_OWNERSHIP_TRANSITIONS: readonly CodexOwnershipTransition[]; /** Returns every (surface, state, actor, action) row in the transition table. */ export declare function codexOwnershipMatrix(): readonly CodexOwnershipTransition[]; /** * The actor (owner principal) implied by a classified profile state. States * that are harness-owned (untracked-absent, and untouched harness-created / * harness-displaced) belong to harness; every user-owned / user-edited / * legacy / displaced-user / deleted cell belongs to the user. Deriving the * actor from the STATE (not from raw record fields) keeps the transition table * unambiguous for untracked cells where optional-chaining would mislabel them. */ export declare function profileActorForState(state: CodexProfileState): CodexOwnershipActor; /** * The actor (owner principal) implied by a classified marketplace state. * `untracked` (harness would create it) and `harness-created-unchanged` * (harness owns it, untouched) belong to harness; a replaced or pre-existing * user marketplace belongs to the user. */ export declare function marketplaceActorForState(state: CodexMarketplaceState): CodexOwnershipActor; /** * Fit the observed facts for a profile into one of the ownership states. * * `priorRecord` is the manifest record from the last apply (or undefined for a * never-owned file); `live` is the current on-disk bytes (null when absent); * `liveMatchesFingerprint` is whether `createContentHash(live)` equals the * record's recorded fingerprint (the adapter computes the hash once). */ export declare function classifyProfileState(priorRecord: CodexAgentProfileRecord | undefined, live: string | null, liveMatchesFingerprint: boolean): CodexProfileState; /** * Fit the observed marketplace facts into one of the four ownership states. * `createdPreviously` is the recorded `created` flag; `liveMatchesFingerprint` * is whether the current bytes match the recorded fingerprint. */ export declare function classifyMarketplaceState(exists: boolean, createdPreviously: boolean, liveMatchesFingerprint: boolean): CodexMarketplaceState; /** * The interpreter: looks the (surface, state, actor, action) cell up in the * transition table and returns the concrete decision for the adapter to run. * A cell with no row throws — the matrix must be complete or a transition * cannot be silently left undefined (the terminating-refactor requirement). */ export declare function resolveOwnershipDecision(surface: CodexOwnershipSurface, state: CodexProfileState | CodexMarketplaceState, actor: CodexOwnershipActor, action: CodexOwnershipAction): CodexProfileDecision | CodexMarketplaceDecision; /** Test-only surface for the machine: types, classification, resolution, table. */ export declare const codexOwnershipMachineInternals: { CODE_X_OWNERSHIP_TRANSITIONS: readonly CodexOwnershipTransition[]; classifyProfileState: typeof classifyProfileState; classifyMarketplaceState: typeof classifyMarketplaceState; resolveOwnershipDecision: typeof resolveOwnershipDecision; codexOwnershipMatrix: typeof codexOwnershipMatrix; profileActorForState: typeof profileActorForState; marketplaceActorForState: typeof marketplaceActorForState; profileWriteRows: typeof profileWriteRows; profileCleanupRows: typeof profileCleanupRows; marketplaceMergeRows: typeof marketplaceMergeRows; marketplaceResetRows: typeof marketplaceResetRows; }; export {};