Skip to content

Runtime-witness persistence loses the evaluated-vs-not-evaluated distinction #331

Closed

Description

@PhysShell

Problem

docs/runtime-witness-operations.md defines an exit-code contract that deliberately keeps three states apart:

0 = evaluated, witness absent   (ABSENT / OBSERVED_ONLY)
1 = evaluated, witness present  (RETAINED)
2 = not evaluated               (usage error, unreadable target, refused attach)

and states the reason plainly:

Not looking and looking and finding nothing are different outcomes, and collapsing them is how a monitoring pipeline learns to report health it never measured.

The persistence layer then collapses exactly that distinction. A refused attach writes no runtime.json at all, so once the process has exited the durable record is:

artifact present  →  some evaluated outcome
artifact absent   →  not_evaluated
                  OR never invoked
                  OR runner died before invocation
                  OR the run happened but persistence failed
                  OR the artifact was produced and lost in transit
                  OR an older format nothing reads any more

Absence has too many preimages to carry meaning. The process contract distinguishes three states; the storage contract merges two of them back together and adds four more, so the guarantee the exit codes were designed to provide does not survive the end of the process.

Refusing to write a verdict that was never earned is correct and should stay. The defect is using file-absence as the representation of "not evaluated", rather than recording it.

Invariant

Absence of a record means no durable knowledge, never a semantic outcome.

Acceptance

Every attempted witness evaluation leaves a durable execution-state record.

observed         observation scope required
clean            observation scope required
not_evaluated    reason required (refused attach, unreadable target,
                 usage error, ...)
error            error classification required

missing record   has no semantic interpretation

A clean with no recorded scope is a malformed record, not a weak one — it should take the same handling path as a schema violation, not be read as a quieter version of not_evaluated.

Scope

A representation defect in the runtime-witness lane, self-contained. It needs no new analysis capability, no change to the exit-code contract (which is right as it stands), and no change to what the witness measures — only that the state the process already computes survives into storage.

Not related to #270, which covers generating witness evidence rather than how its execution state is recorded.

Activity

  1. PhysShell commented on Aug 18, 2026

    @PhysShell
    OwnerAuthor

    Закрываю вручную: обе половины в main.

    половина PR merge commit
    consumer (fail-closed) PhysShell/OwnAudit#61 a11ae7e7
    producer (запись состояния) #333 e06e6b9f

    Оба PR ссылались на этот issue через Refs, а не Closes, — намеренно. Изменение живёт в двух репозиториях, и автозакрытие сработало бы от первого же смерженного PR, то есть объявило бы issue решённым в момент, когда была готова ровно половина. Порядок при этом обязателен и соблюдён: сначала consumer, потом producer. В обратном порядке возникает окно, в котором producer уже пишет новую форму записи, а consumer ещё читает not_evaluated-прогон как «ничего не удержано» — то есть ровно тот дефект, который этот issue и описывает, только с более убедительным на вид артефактом.

    Что теперь верно. Runtime-свидетель различает четыре состояния — observed, clean, not_evaluated, error — и verdict/retained появляются только у оценённых. Отказ атакуется по стадии, на которой он произошёл (open-target / create-runtime / walk), а refused-attach резервируется за отказом на открытии цели с наблюдаемой политикой, записываемой как policy_in_force — наблюдение, а не доказанная причина. На стороне потребителя нечитаемая запись отвергается через UnusableRuntimeRecord, а прежние выходные файлы стираются до любого пути выхода, так что отказ не оставляет стоять старое ложно-приписанное evidence.

    Оставшийся хвост, если понадобится: docs/runtime-witness-operations.md § «The durable record» описывает таблицу состояний, а denied-attach gate в CI утверждает, что отказ записан, а не что артефакт отсутствует.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions