Instruction file imported from edobry/minsky (
.cursor/rules/hook-observers.mdc). Copyright stays with the author.
Hook Observers
NON-BLOCKING hooks: detectors, injection, reminders, trackers, SessionEnd ingest — no
decisions. Gates + compile workflow: hook-files.
This is an INDEX, not the narration. Each entry gives the trigger, the enforcement status,
and the override var. The durable detail — mechanism, incident history, design rationale,
false-positive posture — lives in docs/architecture/hooks/<name>.md, which every Detail:
pointer below is relative to. Read that page before changing, citing, or reasoning about any
observer's behavior; an entry here is deliberately too terse to answer "why does it work this
way?"
Write the page anyway — but the ceiling no longer binds this rule (mt#4332). The 15,000-char
per-rule ceiling (mt#3676) applies only to alwaysApply: true rules
(findPerRuleCeilingViolations, packages/domain/src/compile/size-budget.ts, filters on exactly
that), and this roster is now path-scoped — so compile --check --target claude.md no longer
reports it at all, and a new entry cannot breach anything. Do not read that as licence to write
narration here. Keep an entry to trigger + status + override + pointer and put the mechanism,
incident history and false-positive posture in docs/architecture/hooks/<name>.md, for the reason
this rule's own header gives: an index is consulted at speed, and prose in it is prose nobody
finds. What changed is the enforcement, not the shape.
Two things follow. MINSKY_SKIP_SIZE_BUDGET and MINSKY_SKIP_SIZE_JUSTIFICATION are no longer
reachable from this file — if you find yourself reaching for either while editing this roster,
something else is wrong. And if this rule is ever promoted back to alwaysApply: true, the
ceiling returns immediately and roughly fifty entries arrive over it in one step; re-promotion is
therefore a restructure, not a frontmatter flip.
All observers on one event share ONE injected block. The dispatcher merges every guard's
additionalContext into a single hookSpecificOutput — not N separate injections (mt#3394 was
filed on the opposite assumption and falsified it). Order is by contextPriority; the block is
capped at MERGED_CONTEXT_BUDGET_CHARS in .minsky/hooks/dispatcher.ts — read the constant,
never a figure quoted in prose. Over budget, the lowest-priority fragments are dropped and NAMED,
never silently, and still write their calibration records. Separate events mean separate blocks.
Detail: guard-dispatcher-framework.md.
- Skill/agent/rule staleness — stale skill/agent/rule baseline.
MINSKY_SKIP_SKILL_STALENESS. - Drive-PR-to-convergence — reminds wait-for-review. none.
- Drive-READY-to-implementation — on
tasks_status_set→ READY, injects "invoke/implement-tasknow". Fires only on a real transition into READY; skipsstate-opskind (mt#3373).MINSKY_SKIP_READY_CHAIN_WALK. - Warn-peer-task-activity (mt#4494) — on
tasks_status_set+tasks_spec_patch, reads the TASK EVENT LEDGER and injects anysession.started(no window — a session is a durable claim) ortask.status_changedinsidePRESENCE_CLAIM_TTL_MS. Filters the caller's OWNsession.started(id frominput.cwd); since mt#5086 asession.startedrow carries its WRITER's agentId (server-injectedcallerActorIdonsession.start, same primitive as the claim tools) and is labelledthis conversation/ANOTHER conversation — not yours, not your subagent's/comparison not madeagainst the hook'ssession_id, so a peer's session is never attributed from timing (mt#5055 retraction); status-change rows carry no actor and stay unattributed (mt#4440). STANDALONE, not dispatcher-registered — that seam already carries standalone hooks, which avoids ADR-042'sregistry-status-set-guards.tswiring (booked to mt#4172). Advisory by design, not by calibration ladder: denying is substrate-RFC Open question 4. No override — it cannot deny. Detail:warn-peer-task-activity.md. - Warn-stale-forward-reference (mt#4535, seam corrected by mt#4545) — fires on two surfaces: PostToolUse on
session_pr_merge(a successful merge — this is where DONE is actually written, and the ONLY surface that fires in practice) and PreToolUse ontasks_status_setto DONE (kept for an agent that sets it explicitly, which policy says not to do). mt#4535 shipped with the status-set surface alone and therefore never fired:session-merge-status-sync.tscallstaskService.setTaskStatus()directly, which no tool-level hook observes — the fire log showed 1 record withguardOutcomeunset against 249 for its sibling. ADR-042's discriminator ("fire where the trace first exists") is the frame that names the error. It scansdocs/architecture/adr-*.md+.minsky/rules/**and injects any paragraph describing THIS task's deliverable as still-pending, with file, line and excerpt. Match = a forward-looking marker (upgrade path,future work,deferred, …) AND either the task id OR 2 distinct title tokens. The title path is the load-bearing half: the originating instance — ADR-006's "upgrade path if that bites", left stale when mt#3900 shipped exactly that mapping — names no task id, so an id-only index misses the class that matters. STANDALONE (same seam convention as the two above). Log-only: the title-token path's FP rate against the corpus is unmeasured, so the fire-log denominator ships before any enforcement. CLOSED is deliberately not covered — abandoned work needs different advisory text. No override — it cannot deny. Detail:warn-stale-forward-reference.md. - Coverage-claim-path (mt#4426) — PreToolUse on the write tools: a comment being written CLAIMS coverage/convention/precedent at a path that does not resolve. Third structural instance of a class three tasks fixed one at a time (mt#4202, mt#3994, mt#4413). TWO conjuncts, neither redundant — comment-scoping (removes fixture paths in test string literals) AND a governing claim phrase within 160 chars (removes the illustrative names that live in COMMENTS, measured at three of five sampled). The path pattern's leading lookbehind removes the largest class:
transcripts/CONTAINSscripts/. Resolves against the CITING file's package root before the repo root, so a service-localscripts/is not a manufactured miss. Which TREE it asks is taken from the tool input'ssessionId, notinput.cwd(mt#4674) — asession_*write lands in a session workspace while the MCP call stands in MAIN, so cwd-rooting made all 3 of its first 3 live fires false (a path the session had already created, absent from main until merge) AND silently missed the inverse (a path the session DELETED, still on main). An unlocatable session workspace records nothing rather than guessing. Its calibration log stays pinned to the hook's own install root (deriveHookRepoRoot, mem#797), because the two roots answer different questions. Deliberately does NOT elide inline code spans, unlike ADR-024 Rung 1's prose-oriented prefilter — in a source comment a backticked path is the normal way to cite a real one, and one of the two known true positives is backticked, so eliding would suppress half the real findings and remove no false class. Measured corpus-wide: 22 fires, 21 real (95.5%), against ~1.8% for the naive path-existence form the predecessor's audit called "decidable by grep". STANDALONE, log-only. No override — it cannot deny. - Substrate-bypass — unencoded commitments/retro-prose/DB-bypass, + log-only post-merge instr.
MINSKY_ACK_SUBSTRATE_BYPASS. - Retrospective-trigger — reminds
/retrospective; Stop siblingturn-end-retro-scan. Full ADR-024 ladder as of mt#3652.MINSKY_ACK_RETROSPECTIVE_TRIGGER; Rung-3 kill switchMINSKY_DISABLE_RUNG3_CONFIRM. Detail:retrospective-trigger-scanner.md. - Retrospective-completeness — whether a retro that FIRED is complete: the sections its declared triage level requires, and in-turn status reads for cited fix-tasks (mt#3601). Log-only.
MINSKY_SKIP_RETRO_COMPLETENESS. - Turn-end-untaken-action — Stop scan (mt#3179): final message names a next action without taking it. Phrase-keyed to MATCH; its two suppressions are not. Two arms ride along LOG-ONLY (
LOG_ONLY_FAMILIES) — they reach the calibration record and neveradditionalContext: the tool-call-state arm (mt#4697) and the present-progressive arm (mt#4835), which catches "Running X now" — an assertion that an action is already underway, the form position alone cannot settle.MINSKY_ACK_UNTAKEN_ACTION. Detail:turn-end-untaken-action-scan.md. - Turn-end-unwalked-task — Stop scan (mt#3536): the turn minted a task id and ended with no status-set/session-start/dispatch/ask naming it. Tool-call-state-keyed, so it sees the SILENT stop.
MINSKY_ACK_UNWALKED_TASK. - Code-mechanism-assertion — unread code-symbol claims. LIVE 2026-07-21. Relayed claims SURFACE rather than suppress (mt#3152). Three surfaces: chat (live), added comments (log-only, mt#3571), durable artifacts — PR bodies, specs, memories, asks (log-only, mt#3642). Two Rung-2 cohorts behind
MINSKY_CMA_RUNG2_NOMINATION(ships disabled): symbol-BEARING identity claims (mt#4155) and symbol-FREE claims (mt#3726) — the latter recorded only, never injected, with no suppression yet, per-class off-switchMINSKY_SKIP_SYMBOL_FREE_CLAIMS.MINSKY_ACK_CODE_MECHANISM_ASSERTION. Detail:code-mechanism-assertion-detector.md. - Negative-existence-claim (mt#3918) — a claim of ABSENCE written into a durable artifact, justified by a same-turn search returning <=1 hit, citing a DONE task. Calibration-first.
MINSKY_ACK_NEGATIVE_EXISTENCE_CLAIM. Detail:negative-existence-claim-detector.md. - Secret-request-in-chat (mt#2428) — the assistant asking the principal to hand over a secret through the conversation ("paste your bot token here"); the transcript is persisted AND ingested, so
credentials.requestis the surface. Suppresses the agent REFUSING, and prose DESCRIBING the antipattern — the dominant FP class, since the corpus discusses it at length. Carved from operator-deferral by verb class: deposit verbs and generic-verb-plus-recipient here, bareprovide the <secret>stays a deferral. Calibration-first.MINSKY_SKIP_SECRET_REQUEST_IN_CHAT. Detail:secret-request-in-chat-detector.md. - Turn-end-bare-ref-scan — Stop scan (mt#3286): the closing message carries an entity ref the reader cannot click. Per finding class:
bare-short-id,malformed-target,raw-uuid-labelLIVE, the rest RECORD-ONLY.MINSKY_ACK_BARE_ENTITY_REF. Detail:turn-end-bare-ref-scan.md. - Turn-end-unescalated-incident — Stop scan (mt#3593): final message reports an incident and names the remediation as the principal's, with no
asks_createcarryingseverity: "incident". LIVE.MINSKY_ACK_UNESCALATED_INCIDENT. - Turn-end-stale-state-assertion (mt#4199) — Stop scan: closing message says an ask/task awaits the principal; substrate disagrees. Two classes (mt#4375): terminal state, or an ask's text declaring it resolved. Calibration-first.
MINSKY_SKIP_STALE_STATE_ASSERTION_SCAN. Detail:turn-end-stale-state-assertion-scan.md. - Ask-routing deferral — chat-prose deferral bypassing Asks. LIVE mt#2694 (not log-only).
MINSKY_ACK_ASK_ROUTING_DEFERRAL. Precedence (mt#4531): when this fires and the principal's last message is about HOW you are communicating, the principal wins — answer it and stop, do not act on this advisory. It pushes toward action; a concision complaint asks for none. R7 (mem#664) is both live at once with the wrong one winning. Not rendered in the payload (that guard's size ceiling is a measurement its own declaration says not to raise); the rule iscommunication-contract.mdc §A message about how you are communicating authorizes nothing. First detector in this family to climb to ADR-024 Rung 2 (mt#4404): its settled-decision SUPPRESSOR — which stops it warning you for stating a decision you already took — now has an embedding nominator beneath the pattern list, because three windows measured the same behaviour recurring in renderings no first-person pattern reaches. Opt-in, off by default:MINSKY_ARD_RUNG2_NOMINATION. A degraded provider suppresses nothing and still injects, so the failure mode is a false positive, never a silenced deferral. Sibling climb SHIPPED (mt#4649):operator-deferral's permission-ask surface now carries the same rung, behind its OWN flagMINSKY_ODD_RUNG2_NOMINATION— separate deliberately, because ADR-024 gates each climb on its own detector's evidence and one switch would make either residual unattributable. Both ship inert; the sibling's threshold is additionallyNaNand UNMEASURED, because replaying its log through current code cut the must-suppress corpus to three records and the principal chose to pause rather than fit a band to three points (mt#4920 owns the measurement). - Operator deferral — an ACTION deferred to the principal without a same-turn capability probe; sibling of ask-routing-deferral, which covers a DECISION. Six surfaces. Calibration-first (mt#2459).
MINSKY_SKIP_OPERATOR_DEFERRAL. Detail:operator-deferral-detector.md. - Wall-of-text — turn-end report shape violation (over-budget/label-lead). LIVE mt#3112.
MINSKY_SKIP_WALL_OF_TEXT. - Silent-stretch — tool-only run crossing the heartbeat cadence (10min OR 15 calls,
user-preferences.mdc §Progress heartbeats) with no interstitial prose. LIVE mt#3399.MINSKY_SKIP_SILENT_STRETCH. - Context-fill gauge (mt#4291) — reports the session's context fill; LIVE, acts on nothing.
MINSKY_SKIP_CONTEXT_FILL_GAUGE. Detail:context-fill-gauge.md. - Handoff-at-work-boundary (mt#5042) — records context fill at a WORK BOUNDARY (a merge, a PR landing, a
tasks_status_setto DONE) plus whether a trigger at the pre-registered 650K threshold would have fired; LOG-ONLY, acts on nothing. Adds the boundary CONJUNCTION to the gauge's per-turn reading, and the conjunction forces a LOWER threshold than a fill-only trigger's: boundaries are sparse, so at 950K it catches 8 of the 135 boundaries that preceded a compaction (5.9%) against 75 of 135 (55.6%) at 650K — measured over 2,644 boundary events across 605 sessions, counting only calls that SUCCEEDED, which is what the hook fires on. The 650K is a hypothesis sitting between two measured points — do not cite it as derived, and the event-grain figures above were SUPERSEDED before the hook merged (mt#5082): priced per SESSION against the wall-hit class (auto-compacted OR handed off at ≥800K, 16.3% of sessions), 800K cuts 142 sessions at 68.3% precision catching 75.2% of wall-hits, where 650K cuts 320 at 37.5% — mt#5042## CORRECTION 2026-09-09. The constant stays at 650K until ask#11976 (threshold + log-only-vs-directive, withautoCompactWindowas the no-build alternative) is answered. AnESTIMATEDfill reading (unknown model → assumed window, mt#4968) is recorded but can never fire. No bespokeMINSKY_SKIP_*name per ADR-028 D3: useMINSKY_HOOK_OVERRIDE=handoff-at-work-boundary. Re-derive withbun scripts/measure-context-at-merge.ts --all-projects. - Chained-verification-commands (mt#3910) — a
Bash/session_execstring chaining TWO OR MORE verification commands with;/&&/||, making a non-zero exit unattributable. Deliberately narrow; binary list in the page. Calibration-first.MINSKY_SKIP_CHAINED_VERIFICATION_SCAN. Detail:chained-verification-commands-detector.md. - Nonexistent-search-path (mt#4215) — a nonexistent
grep/rg/findpath; empty output is not absence. Calibration-first.MINSKY_SKIP_NONEXISTENT_SEARCH_PATH. Detail:nonexistent-search-path-detector.md. - Truncated-outcome-read (mt#4096) — an outcome-bearing command piped into
tail/head, discardingpushed/pushUnconfirmedby position. Second arm (mt#4176): a truncated--help. Calibration-first.MINSKY_SKIP_TRUNCATED_OUTCOME_READ. Detail:truncated-outcome-read-detector.md. - CLI-substitutes-MCP (mt#4144) — a
Bash/session_execinvoking the Minsky CLI for a command that HAS anmcp__minsky__*equivalent, when MCP has not succeeded — or, since mt#4353, once an MCP call has ERRORED since the last success, or from the SECOND such call after it. INJECTS (never denied; "calibration-first" here was wrong for its whole life, mt#4290).MINSKY_ALLOW_CLI_SUBSTITUTION. Detail:cli-mcp-substitution-detector.md. - Constructed-identifier batch — TWO passes: mint-and-consume in one parallel batch (categorical), and consume-before-mint across a turn (exact, mt#3340). Calibration-first.
MINSKY_ACK_CONSTRUCTED_IDENTIFIER_BATCH. Detail:constructed-identifier-batch-detector.md. - Bare-prohibition dispatch — a dispatch prompt telling a subagent NOT to do something without stating its basis (mem#702). Narrowed mt#3167. Calibration-first (mt#3162).
MINSKY_ACK_BARE_PROHIBITION. Detail:bare-prohibition-dispatch-detector.md. - Duplicate-check search provenance (mt#4004) — a duplicate-check record CLAIMING a past-tense search, in a session with no
tasks_search/tasks_similar/refs_statuscall. Third of four tiers on that record (present / true / searched / read). A subagent's create is judged against the SUBAGENT's own transcript, not the parent's (mt#5108; 3 of 4 subagent fires in one 30-day window were searches the writer had itself run). Calibration-first.MINSKY_SKIP_SEARCH_PROVENANCE. - Duplicate-check candidate read (mt#4167) — the fourth tier: the record distinguishes candidates whose specs were never opened this session. NAMED candidates only. Calibration-first.
MINSKY_SKIP_CANDIDATE_READ_PROVENANCE. Detail:duplicate-check-candidate-read.md. - Claim provenance (mt#4168) — FOUR classes at the spec-WRITE seam, each with no discharging call: a file-level COLLISION, a NEGATIVE OWNERSHIP claim, (mt#4299) a REMAINING-WORK assertion about a task discharged by a status read on that id, and (mt#4876) a CAUSAL ATTRIBUTION to a named task — "consistent with mt#X", "because mt#X" — discharged ONLY by a CONTENT read (
tasks_spec_get, ortasks_getwithincludeSpec) or by authoring that spec. The fourth's discharge set is deliberately a STRICT SUBSET of the third's, and that is the whole point: a status read says where a task sits in the lifecycle, and only its body says what it claims. The originating incident sourced "consistent with mt#4753 being BLOCKED" from the task TITLE, which a baretasks_getreturns — so the wider set would have discharged it. Sentence-scoped (the siblings are paragraph-scoped), and it yields towarn-unwired-task-relationshipon a relationship phrase so one claim cannot fire two guards. RECORD-ONLY.MINSKY_SKIP_CLAIM_PROVENANCE. Detail:claim-provenance-scan.md. - Criterion reconciliation (mt#4213) — a spec write EXPLAINS that a criterion is unmet (
is not satisfied,cannot be satisfied,unsatisfiable), names it (SC<n>/AT<n>), and leaves that criterion's own normative entry out of the same write. Four reviewer-caught recurrences in eight days, all post-dating the DONE prose tier (mt#2504). Both halves of the join are sections of one document, so no DB and no transcript. On ADR-024's ladder — the nominating half is a phrase set by necessity, so a recall bound is answered by a rung climb, never a widened list; mt#4038 ships as an asserted known miss. RECORD-ONLY.MINSKY_SKIP_CRITERION_RECONCILIATION. Detail:criterion-reconciliation-scan.md. - Unwired task relationship (mt#2264) — a spec STATES a relationship naming another task ("hard prerequisite for mt#N", "feeds mt#N", "is part of mt#N") while the matching edge is absent. Whole spec-authoring seam; discharge is exact — the payload's
dependsOn/parentat create, the livetask_relationshipsgraph at the edit seams. Names which AXIS to wire (dependency vs parent/child, mem#530). RECORD-ONLY. Override is the unifiedMINSKY_HOOK_OVERRIDE=warn-unwired-task-relationship— no bespoke var, per ADR-028 D3. Detail:warn-unwired-task-relationship.md. - Evidence-record provenance (mt#4044) — a
Negative control:/Execution evidence:record claiming a run, written into a commit message or PR body with no matching run in the session. Per-CLAIM since mt#4236: an evidence block asserting a typecheck/lint/format result is judged against a run of THAT kind, and a run predating a later write to a file it reads recordsstale-evidence— a write INSIDE the workspace, that is (mt#5087): a scratchpad or/tmpedit is not a file any run of the repo read, so it no longer counts. A negative-control claim is also discharged by the run's summary counts as the record states them, an abbreviated quoted line, or a bare (un-backticked) identifier — discharge signals only, none makes a record judgeable (mt#4306; 154 → 114 fires on a frozen population, no true positive moved). A SUBAGENT's write is judged against the subagent's ownagent-<id>.jsonl, writer-only, never the parent's lines (mt#5108; 6 of 19 records in one window were runs the parent never made, and the record now carrieswriterAgentId). A control run WITHOUT a test runner discharges too (mt#4309):bun --cwd <dir> testandrun-related-testsare runners, a RUN-shaped command (an invocation, never ased/cat/grep— 22 of 45 naive candidates were reads whose text heldFAIL) whose output reports failure in a harness's vocabulary is a harness run, andbunx tsgoon a scratch module observederror TSis a typecheck-shaped control; 123 → 99 undischarged on a frozen 21-day population, all 24 inspected. RECORD-ONLY (tune: mt#4067).MINSKY_SKIP_EVIDENCE_PROVENANCE. Detail:evidence-record-provenance.md. - Duplicate-signature scan (mt#3722) —
tasks_createwhose spec carries signature tokens already in an active task's spec that its duplicate-check record does not concede. Exact substring, no similarity metric (mem#819). Calibration-first.MINSKY_SKIP_DUPLICATE_SIGNATURE_SCAN. Detail:duplicate-signature-scan.md. - Stale-signal sweep (mt#3959) —
session_pr_createon a branch that STOPPED emitting an operator-facing<label>=while active specs, memories or ADRs still quote it. Calibration-first.MINSKY_SKIP_STALE_SIGNAL_SWEEP. Detail:stale-signal-sweep.md. - Unrendered-result-field scan (mt#3913) —
session_pr_createon a branch adding a counter/flag to a*Resulttype that no output site renders. A log call is not a render site. Calibration-first.MINSKY_SKIP_UNRENDERED_RESULT_FIELD_SCAN. Detail:unrendered-result-field-scan.md. - Enumeration-scope check (mt#4171) — TWO rows now, and the second is the one that fires. Row 1:
session_pr_createchanging a serialized contract with nodocs/sweep; a SUBTREE is not its directory. Row 2 (mt#4399): a session that REPLACED a message literal whose wording still renders in files the sweep never reached — the inverse direction, since row 1 can only see "swept code, missed docs" and PR #3219 was "swept docs, missed code". Its prescribed set is DERIVED from the change (the clauses removed, searched withgit grep -F), not asserted as a constant, so it can namesrc/packageswhere row 1 deliberately would not. Row 1 decided 0 of 86 live invocations; replayed over 1,124 windows the two together decide 29.7% against row 1's 1.2%. Atpr, not ADR-042's READY seam (mt#4293). Calibration-first.MINSKY_SKIP_ENUMERATION_SCOPE. Detail:enumeration-scope-check.md. - Spec-scope execution (mt#4544) —
session_pr_createwhere the bound task's spec enumerates in-scope file paths the session never edited. The sibling above asks whether the SWEEP THE AUTHOR RAN reached gate (h)'s prescribed directories; this asks whether the LIST THE SPEC NAMED was touched — the author's own enumeration is the cheapest available oracle and was write-only until now. Originating instance mt#4531 / PR #3310: the spec named a doc explicitly, the implementation never touched it, and the reviewer caught it BLOCKING a round late by re-deriving the impact. Parses STRICTLY (extractInScopeFiles(spec, { strict: true })) — the shared extractor's## Context/ whole-document fallback is right for collision detection and would here collect every path a spec merely MENTIONS, reporting each as an unkept promise. A spec with no parseable in-scope paths recordsskipped("nothing to compare"), neverclean. Record-only, calibration-first; the dominant false positive is a CONDITIONAL enumeration line whose condition did not fire, which is why the record carries the spec's own line beside each path.MINSKY_SKIP_SPEC_SCOPE_EXECUTION. - Gate-walk provenance (mt#1880) —
session_pr_mergeon a task with notask.status_changed→ READY row: was it gated at ALL? The existence half of the pair above, at the only seam mem#416's four bypass paths share.skipped(pre-horizon, unreadable) is kept strictly apart fromungated. Record-only.MINSKY_SKIP_GATE_WALK_PROVENANCE. Detail:gate-walk-provenance.md. - New-surface design pass (mt#4124) —
session_pr_createon a branch that ADDS a render-path file, or (mt#4356) MODIFIES one when the bound spec declares the change visually judged, with no design skill invoked in the authoring conversation. The judgment half of mt#2421. The second trigger exists because file-add proxied for "this is a design decision" and missed the largest class of design work — changing how an existing surface looks; the whole cockpit redesign sequence is modify-only and was invisible to it. Calibration-first.MINSKY_SKIP_NEW_SURFACE_DESIGN_PASS. Detail:new-surface-design-pass.md. - Flakiness-control detector (mt#3658) —
tasks_createwhose spec claims a failure MODE with no isolation control recorded. Fires on the ATTRIBUTION and equally on the DENIAL (mt#4166). Calibration-first.MINSKY_SKIP_FLAKINESS_CONTROL. Detail:flakiness-control-detector.md. - Unowned-finding scan (mt#4246) — a
tasks_status_set→ DONE whose spec's findings section holds an item declaring neither[owner: mt#N]nor[no-owner: reason]. Calibration-first.MINSKY_SKIP_UNOWNED_FINDING_SCAN. Detail:unowned-finding-scan.md. - Consumer-account (mt#4493) — a merge whose branch diff REMOVES, or newly GUARDS, a signal-producing call (
process.exit(,.emit(,.close(, a state-file write) undersrc/packages/cockpit-tray, with noConsumer account:section in the PR body naming what consumed it. The finding is the missing account, never the removal. Calibration-first. NoMINSKY_SKIP_*of its own — a log-only surface has no decision to bypass, and ADR-028 D3 retires per-guard names;MINSKY_HOOK_OVERRIDE=require-execution-evidence-before-mergecovers it. Rides the execution-evidence gate as its fifth calibration surface, so the mechanics sit with its four siblings inhook-files.mdc §Execution-evidence. - Spec-criterion-claim (mt#4153) — a
## Success Criteria/## Acceptance Testsbullet asserting unverified corpus state (Class A) or imposing a precondition absent from the authorizing ask (Class B, edit surfaces only). Calibration-first.MINSKY_SKIP_SPEC_CRITERION_CLAIM. Detail:spec-criterion-claim-detector.md. - Display linkifier (mt#2565) — MessageDisplay: rewrites bare
mt#NNNN/PR #N/ask#N/mem#N/ws#Ninto deeplinks as a message streams; the stored transcript keeps the bare ref. OFF the dispatcher.MINSKY_SKIP_TERMINAL_LINKIFY. Detail:linkify-message-display.md. - Injection (per-turn) — current-time/git-state/prod-state/dispatch-watchdog.
MINSKY_SKIP_*_INJECTION. - Memory-capture notice (mt#3997) — surfaces an mt#3973 resident-memory capture the first time it is seen, naming the process role, resident MB, and the tool calls in flight. Silent when none exists (the normal state).
MINSKY_SKIP_MEMORY_CAPTURE_NOTICE. Detail:inject-memory-capture.md. - Answered-ask notice (mt#3564) — an ask THIS conversation filed has reached
responded/closed; names its short id, title and the chosen option. Fires ONCE per response (a re-answer fires again). Reads two local files only — the attribution map plus the ask-state cache — never the DB.MINSKY_HOOK_OVERRIDE=inject-ask-responses. - Ask-conversation stamp (mt#3564) — PostToolUse on
asks_create: records which conversation filed the ask, the one place both ids are visible (the mt#3120 pattern). Writes one local JSON file, no DB, entries pruned at 7 days / 200. Without it the notice above can never fire:Ask.parentSessionIdholds a WORKSPACE session id and a main-workspace conversation has none.MINSKY_HOOK_OVERRIDE=stamp-ask-conversation. - Agent-dispatch record (mt#2292) — PreToolUse on
Agent: writes thependingsubagent_invocationsrow on the RAW spawn path, and stamps(session_id, tool_use_id)into the prompt. Never denies.MINSKY_SKIP_AGENT_DISPATCH_RECORD. Detail:subagent-invocation-recording-hook.md. - SubagentStop recording — writes Stop-time columns on dispatch row; recovers the mt#2292 stamp
from
agent_transcript_pathto close on the parent key. none. - PR-author link — stamps workspace↔conversation link at
session_pr_create(mt#3101). none. - Session-creator link — stamps workspace↔conversation link at
session_start(mt#3120). none. - Subagent model verification — Agent-tool PostToolUse: warns when the requested
modelmismatchesresolvedModel(mt#3151); degraded payloads log instead of warning (mt#3257).MINSKY_SKIP_SUBAGENT_MODEL_CHECK. - Session-end ingest — ingests transcript at SessionEnd.
MINSKY_SKIP_TRANSCRIPT_INGEST_HOOK. - Guard-events sweep ingest (mt#4035) — SessionEnd runs one
guard-events.ingestsweep tick (40-stream exhaust, HWM cursor, dedupe-key insert). Latency only — the cockpit's periodicstartGuardEventsSweepBackstopis the correctness layer (SessionEnd unreliable, ADR-017/mt#2313).MINSKY_SKIP_GUARD_EVENTS_INGEST_HOOK. - Work-package claim release (mt#5132) — SessionEnd spawns one
tasks release-conversation <session_id> --reason <reason>, releasing the packages claimed under this conversation'sconv:identity; the command releases nothing underclear/resume. Latency only — the minsky-opspackage-lifecyclesweep's 24h presence-staleness backstop is the correctness layer, and a daemon-scopedproc:claim is only ever the sweep's.MINSKY_HOOK_OVERRIDE=release-work-package-claims-on-session-end. - Calibration (log-only) — causal-premise/cadence/build-claim/knowledge-acquisition.
MINSKY_ACK_*/MINSKY_SKIP_*. - Guard-health tracker — guard failure streaks tagged
infra/logic; escalation banner cools down per-session up to 1h (mt#3072). Since mt#3892 the summary carriesliveness+lastCleanRunAt, sorecoveredanddormantare no longer one state. none. Detail:guard-health-tracker.md. - Cross-turn hedge — UserPromptSubmit: a claim HEDGED in an earlier turn and restated as FACT in a later one, with no tool call naming that subject in between — the falsifier
claim-confidence.mdc's warrant vocabulary previously had none of. Subjects are decidable entity refs only, and the hedge turn's OWN lookup deliberately does not count as resolving, since it is usually what produced the hedge. Log-only.MINSKY_ACK_CROSS_TURN_HEDGE. No detail page yet — this entry is the whole documentation; a page is owned by mt#4992. - Pre-narration — a turn that states a tool outcome — created, merged, tests pass — before that result is in hand. Log-only.
MINSKY_ACK_PRE_NARRATION. No detail page yet — this entry is the whole documentation; a page is owned by mt#4992. - Two-strikes record — PostToolUse: records every tool error and accumulates per-conversation error streaks, feeding the calibration data behind the 2-strikes rule. Observation mode by default — it logs what WOULD have fired without acting, so the discipline itself stays the agent's to keep.
MINSKY_TWO_STRIKES_MODE. No detail page yet — this entry is the whole documentation; a page is owned by mt#4992. - Warn main-workspace mutation — PostToolUse on
Bash: reads the MAIN workspace'sgit statusand names tracked files that became modified DURING that call. It observes git STATE, not the command string, which is the point — the recurrence it was built for usedsed -i,cat >>and apython3heredoc, none of which any destructive-verb list contains. Fires at most once per file (the reported set is a diff against the last observation), and untracked files are exempt. Log-only. none. No detail page yet — this entry is the whole documentation; a page is owned by mt#4992. - Standalone duplicate matcher — PreToolUse: the advisory duplicate probe on a standalone
tasks_create. Embedding-based, and provably unable to discriminate at the distances real duplicates sit at (mem#819) — which is why the deny-tier sibling inhook-files.mdcis a presence check instead. none. No detail page yet — this entry is the whole documentation; a page is owned by mt#4992. - Post-merge unasked-direction scan — PostToolUse: after a session PR merges, runs an AI analyzer over that session's transcript to surface preference-bound decisions the agent made without asking, written for weekly operator triage. Observational — the merge has already happened, so it never blocks.
MINSKY_UNASKED_DIRECTION_DETECTOR. No detail page yet — this entry is the whole documentation; a page is owned by mt#4992. - Bridge-memory retirement — PostToolUse: when a task reaches DONE or its PR merges, names any bridge memory tagged with that task, so the retirement decision is made at the moment it becomes answerable. A bridge memory whose structural fix has shipped is stale guidance that still reads as current.
MINSKY_SKIP_BRIDGE_RETIREMENT. No detail page yet — this entry is the whole documentation; a page is owned by mt#4992. - Deploy-verification after merge — PostToolUse: after a merge touching a deploy surface, injects the reminder that the task is not done until the post-merge deploy is verified healthy. It injects rather than blocks because DONE is set atomically at merge and the deploy only exists afterwards.
MINSKY_SKIP_DEPLOY_VERIFY. No detail page yet — this entry is the whole documentation; a page is owned by mt#4992. - Success-criteria injection — PreToolUse on PR create: emits the bound task's success criteria verbatim, so they are confronted at ship time rather than recalled from having written them. The create call is already in flight when it fires, so it prompts a follow-up edit rather than shaping the body. none. No detail page yet — this entry is the whole documentation; a page is owned by mt#4992.
- MCP daemon staleness — UserPromptSubmit: warns when the running MCP daemon is older than the built source, so a tool result reflecting stale server code is attributable rather than mysterious. none. No detail page yet — this entry is the whole documentation; a page is owned by mt#4992.
- Memory search — UserPromptSubmit: auto-injects top-K memory-search results for non-trivial prompts, restoring preamble-parity for Claude Code without the agent having to remember to search. Explicitly TEMPORARY and harness-specific; retirement tracked at mt#1588 (
CLAUDE.md §Memory Usage). none. No detail page yet — this entry is the whole documentation; a page is owned by mt#4992. - Typecheck on edit — PostToolUse: runs an incremental typecheck after a TypeScript edit, surfaces filtered errors as context, and records which project root was touched. Never blocks; the root it records is what its Stop-time sibling reads to know what to check. none. No detail page yet — this entry is the whole documentation; a page is owned by mt#4992.
- Conversation run-state record — forwards one observed harness event to the cockpit daemon over HTTP, so the fleet view knows what each conversation is doing. One script registered under every observed event, branching on the event name; it POSTs rather than writing the DB directly because a cold hook process pays ~695ms for a domain bootstrap against ~20ms for the POST. none. No detail page yet — this entry is the whole documentation; a page is owned by mt#4992.
- Auto session title — UserPromptSubmit: emits a derived title for the conversation. Outputs a scalar, not a judgment about the trajectory. none. No detail page yet — this entry is the whole documentation; a page is owned by mt#4992.