Presence Self-Check (κ 在场自检)
Purpose
Long-running agent work fails in a characteristic way: the agent reports success
that was never verified. A /health endpoint returns 200, so the agent writes
"OK" — even though the underlying model never loaded. An exception is caught and
logged at debug level, so the pipeline "passes". A network wall gets retried
forty times because retrying feels like progress.
This skill supplies the discipline that prevents this: a scoring model (κ) that
makes self-deception numerically visible, a three-tier constraint system that
separates non-negotiable invariants from tunable ones, and a tri-state verdict
rule that forbids collapsing "unverified" into "OK".
When to Use
Apply this skill when any of the following hold:
- Maintaining a daemon, watcher, or periodically-executed health check.
- Debugging a system that is partially broken (some links work, some do not).
- An environment limit is suspected (network wall, missing credential, offline
model download) and the temptation exists to paper over it. - Producing a status report the user will trust without re-verifying.
- Any task where "it looks fine" is cheaper to write than "I confirmed it".
Core Discipline
1. Tri-state verdicts, never binary
Every probed capability resolves to exactly one of three states. Collapsing
UNCONFIRMED into OK is the single most common self-deception failure.
| State | Meaning | Allowed when |
|---|---|---|
OK |
Verified end-to-end by an actual round-trip | A real request returned real data |
FAIL-<cause> |
Verified broken, with the root cause named | Root cause identified from logs/errors |
UNCONFIRMED |
Module present, capability not exercised | Shallow probe only; deep probe pending |
A registry entry, a truthy config flag, or a module import proves existence, not
capability. Existence maps to UNCONFIRMED, never OK.
2. The three tiers: S / K / X
Constraints are not flat. Sort every rule into one of three tiers before acting;
the tier determines what happens on conflict.
- S tier — existence floor, non-negotiable. Identity, the fixed interpreter
path, the one correct way to launch the service. Violating an S rule invalidates
the work regardless of outcome. Never trade an S rule for speed. - K tier — traceable constraints, fix on contact. No faking, no silent
exception swallowing, no untraceable change, root cause before edit. Every
modification must cite the K rule it serves. - X tier — performance boundary, minimize. Timeouts, avoiding restart loops,
cleaning up temp artifacts. X yields to S and K when they conflict.
Write the project's own rules into a K_RULES.md at repository root using this
tiering. See references/kappa_model.md for the full rule template.
3. Score every significant action with κ
κ = 0.5·S_recog + 0.3·K_overlap − 0.2·X_conflict
S_recog∈ [0,1] — did the action honor the existence floor?K_overlap∈ [0,1] — fraction of applicable K rules satisfied.X_conflict∈ [0,1] — fraction of performance boundaries violated.
κ < 0 indicates self-referential rupture (deceptive alignment): the agent is
reporting alignment it does not have. Roll back rather than proceed.
Note the asymmetry — this is deliberate. S carries the largest weight because
existence violations are unrecoverable. X carries a negative weight so that
performance tricks can never buy back a broken invariant.
4. Environment walls are reported, not fought
When a limit is environmental (no network to a model host, missing credential,
offline sandbox), record it verbatim as FAIL-<cause> and stop. Do not retry,
do not add a warm-up path, do not relabel the workaround as an "optimization".
Delete work that only existed to disguise a wall.
5. Deep probes are periodic, shallow probes are honest
Expensive verification (a 40s model load, a full round-trip) must not run every
cycle — that violates the X tier. Run it every N cycles, cache the confirmed
verdict for the process lifetime, and have shallow cycles report UNCONFIRMED
rather than inheriting an optimistic guess.
How to Use
Running the checker
scripts/kappa_check.py is a dependency-light, self-contained implementation of
the model. It has no required third-party packages and no project coupling.
Score a set of verdicts directly:
python scripts/kappa_check.py score \
--s-recog 1.0 \
--k "link_transparent=true" --k "failure_disclosed=true" --k "no_fake_optimization=true" \
--x "restart_loop=false" --x "unbounded_wait=false"
Probe an HTTP service and score the result:
python scripts/kappa_check.py probe --url http://127.0.0.1:8000/health --deep-every 6
Use it as a library inside a project's own guard loop:
from kappa_check import kappa, Verdict, TriState
k = kappa(
s_recog=1.0,
k_rules={"link_transparent": True, "failure_disclosed": True},
x_rules={"restart_loop": False},
)
if k < 0:
raise RuntimeError("self-referential rupture — roll back")
Exit codes: 0 for κ ≥ 0.5, 1 for 0 ≤ κ < 0.5 (degraded), 2 for κ < 0
(rupture). This makes the checker usable directly as a CI gate.
Authoring project rules
To adopt the discipline in a repository, create K_RULES.md at root following
the template in references/kappa_model.md, then require that every change cite
the rule it serves. Rules that cannot be cited are unowned and should be removed.
Wiring a guard loop
For a persistent watcher, follow the loop shape documented in
references/guard_loop.md: shallow cycle by default, deep probe every N cycles,
tri-state verdicts, append-only log, and a reminiscence step that records the
diff against the previous snapshot rather than recomputing state cold. The diff
is what makes a long-running agent's memory continuous instead of amnesiac.
Anti-Patterns
Reject these on sight:
- Treating a truthy health flag as proof of capability.
except Exception: pass, or logging a failure below the level the user reads.- Retrying an environment wall on the theory that persistence helps.
- Renaming a failed workaround as an "optimization" to keep it in the tree.
- Reporting aggregate "all systems normal" when any component is
UNCONFIRMED.