| name | isme-decision-basis |
| description | Strong ISME decision-basis gate for making implicit state-machine decisions explicit before implementation. Use when Codex is modifying or designing complex stateful systems, async approval flows, persistent sessions, recovery behavior, concurrency, shared resources, external dependencies, security boundaries, failure semantics, irreversible actions, or when the user asks for decision explicitness, SKMB, ISME, no silent decisions, strong constraints, or module-level decision checkpoints. |
ISME Decision Basis
Use this skill as a strong plan-to-act gate for stateful work. Its purpose is to prevent Codex from silently inventing the designer's implicit state machine.
This skill implements the Implicit State Machine Elicitor (ISME) as a skill-level protocol. It cannot add unsupported parameters to tool schemas or physically intercept tool calls. It must still be treated as a hard behavioral gate: for covered work, do not perform implementation actions until an ISME check has been completed.
When improving this skill itself, use this skill on the change. Treat changes to SKILL.md, SKMB templates, or decision-basis semantics as state-machine-affecting actions.
Non-Negotiable Gate
Before any implementation action that can instantiate or modify state-machine behavior, perform an ISME check.
Implementation actions include file edits, generated code, migrations, tests that encode semantics, config changes, commits, deploys, irreversible sends, database writes, and commands that alter project state.
Read-only exploration may proceed without a gate. Once enough context exists to act, stop and run the gate before acting.
The default failure mode is fail closed:
- If the action triggers a high-impact pattern and no matching designer decision exists, set
resolved_by: pending and stop.
- Do not downgrade a missing high-impact decision to
statistical_default because a common pattern seems obvious.
- Do not encode unresolved behavior in tests, comments, docs, migrations, or generated stubs.
If the gate finds a decision that affects state semantics and the SKMB has no designer decision for it, do not guess silently. Either:
- Ask the designer a module-level decision question and wait, or
- If the designer explicitly permits proceeding unresolved, record the decision as open or statistical-default before acting.
Core Theory
Distinguish these gaps:
- Gap 1: explicit written requirements must be translated into code.
- Gap 2: required decisions are absent from the written requirements and exist only in the designer's mind.
This skill is for Gap 2. Gap 2 decisions are normative: the model has no authority to decide them from training distribution. It may propose options, but the designer owns the decision unless they explicitly delegate it.
Pattern Classifier
Trigger the gate when a planned action touches any of these patterns:
| Code | Pattern | Trigger examples |
|---|
| A | Async Wait | approvals, callbacks, human-in-the-loop waits, webhooks, pending operations |
| B | State Persistence | durable sessions, checkpoints, resumes, crash recovery, stored workflow state |
| C | Concurrent Operations | shared resources, parallel actors, races, locks, queues, idempotency |
| D | External Dependency | third-party APIs, notification delivery, adapters, outbound callbacks |
| E | Security Boundary | identity injection, permissions, token lifecycle, authorization scopes |
| F | Fail Semantics | fail-open/closed, retries, fallback, partial failures, error propagation |
| G | Irreversible Action | commits, sends, charges, grants, deletes, deploys, side effects |
Treat combinations as higher risk. For example, F + G means partial failure around an irreversible action; A + B means pending async state must survive or fail across restart.
SKMB
Use a State Machine Knowledge Base (SKMB) as the persistent decision record.
Default location inside a project:
docs/isme/SKMB.md
docs/isme/decisions/
docs/isme/archive/
If no project root is available, use the current working directory. If the SKMB index and decisions directory do not exist and the task triggers this skill, follow the first-time init flow below, then create docs/isme/SKMB.md from references/skmb-template.md and use references/skmb-decision-template.md for each new decision file before implementing state-machine behavior.
If modifying this skill itself, use docs/isme/SKMB.md and docs/isme/decisions/ inside the skill directory.
The SKMB is the authority for previously externalized decisions. Use SKMB.md as a lightweight index and store each accepted decision in its own file under docs/isme/decisions/.
Use one decision file per elicitation checkpoint or implementation change set. Prefer one decision file per commit when commits are part of the workflow. If the commit hash is not known yet, write commit: pending and update it later if a commit is created.
The SKMB system should record:
- designer decisions
- named states and meanings
- transition decisions
- invariants
- failure semantics
- open decisions
- statistical defaults that were allowed temporarily
First-Time SKMB Init
When a project has no docs/isme/SKMB.md and no docs/isme/decisions/, treat SKMB creation as first-time init.
During first-time init, ask whether the user wants Git hook automation before installing any hooks or changing hook config. Use one compact question:
First-time ISME init: do you want SKMB Git hook automation?
Options:
1. Both hooks (Recommended): pre-commit blocks unresolved SKMB decisions; post-commit archives current local SKMB.
2. Pre-commit only: blocks commits when SKMB is out of sync or concrete decisions are not accepted.
3. No hooks: create SKMB files only.
If you want post-commit only, a different archive path, or local-only hooks, say that explicitly.
Do not install hooks silently. If the user chooses hook automation, preserve existing project hooks; if core.hooksPath or hook files already exist, inspect them and merge or ask before replacing.
Optional Git Hook Automation
Use references/skmb-git-hooks.md when installing or reviewing SKMB hooks.
The pre-commit guard is blocking. It should fail closed when:
docs/isme/SKMB.md and docs/isme/decisions/ do not both exist when either exists.
- SKMB index rows and decision files are out of sync.
- A concrete
SKMB-* decision file is not status: accepted.
- An accepted decision lacks
decided_by: designer or a non-pending approval_source.
The post-commit archive is best-effort. It runs after a commit already exists and cannot reject or modify that commit. It should:
- No-op when no local SKMB exists.
- Validate SKMB sync before archiving when the check script is available.
- Copy
SKMB.md and top-level decisions/*.md to docs/isme/archive/<timestamp>-<commit>/.
- Write a manifest with commit hash, branch, timestamp, source, archive path, and copied files.
- Never mutate source SKMB files or silently amend commits.
Required Workflow
- Explore enough context to identify affected modules and planned actions.
- Locate or create
docs/isme/SKMB.md and docs/isme/decisions/; on first-time init, ask the Git hook automation question before installing hooks or changing hook config.
- Classify the planned action against patterns A-G.
- Query the SKMB index, then read matching decision files by pattern, context, state, event, invariant, or failure mode.
- Emit a
decision_basis block before acting.
- If all high-impact decisions resolve to
designer, proceed and cite the accepted decision files.
- If any high-impact decision is missing, ask one consolidated module-level elicitation question.
- After the designer explicitly answers or approves, create or update the relevant decision file and index before implementing.
- When proceeding with a statistical default by explicit permission, record it as reviewable debt in the SKMB index, its decision file, and the
decision_basis block.
Run these steps every time new implementation information reveals a new state-machine decision. ISME is continuous, not only a front-loaded planning pass.
SKMB Lookup
Treat an SKMB decision as matching only when it covers the same practical behavior, not merely the same broad pattern.
Check:
- pattern code
- affected workflow or module
- state and event, if identifiable
- failure mode or concurrency condition
- scope and
applies_to
- invariants that constrain the action
If a decision partially matches, cite it but narrow the unresolved remainder. Do not stretch a broad decision to cover a materially different state, actor, failure mode, or irreversible action.
Designer Approval
Never infer decided_by: designer from tone, preference, silence, or the fact that the user allowed work to continue.
Use decided_by: designer only when the user has explicitly answered the decision question, chosen an option, approved the checkpoint, or directly instructed the exact policy to record. Store the source text or a short quotation in the decision file as approval_source.
If the user gives direction but has not explicitly approved the SKMB record, use status: proposed and decided_by: pending. Proposed decisions are not authoritative and must not be cited as resolved_by: designer.
If the user says "OK", "approved", "do that", or equivalent in response to a concrete checkpoint or proposed SKMB record, that is explicit approval.
Decision Basis Block
Emit this block in conversation immediately before the relevant implementation action. Do not pass it as a tool argument unless the tool explicitly supports that field.
<decision_basis>
patterns: A_async_wait, F_fail_semantics
context: approval resolution timeout while waiting for external adapter callback
decision: timeout after 30s; fail closed; write audit event
resolved_by: designer
skmb_ref: SKMB-2026-06-11-001
confidence: high
applies_to: approval state transition, retry policy, tests
</decision_basis>
For unresolved high-impact decisions, emit a pending block and stop:
<decision_basis>
patterns: C_concurrent_operations, G_irreversible_action
context: two operators can resolve the same approval with conflicting outcomes
decision: unresolved; implementation is blocked until designer chooses race policy
resolved_by: pending
skmb_ref: none
confidence: low
applies_to: approval resolution write path, database constraint, conflict tests
</decision_basis>
Allowed resolved_by values:
designer: explicitly decided or approved by the human designer and recorded in an accepted SKMB decision file.
statistical_default: model default or common engineering convention; allowed only for low-impact choices or when the designer explicitly permits proceeding unresolved.
pending: unresolved normative decision; do not implement behavior that depends on it.
Use confidence: low whenever the design document is silent, options are materially different, or the choice affects safety, money, permissions, durability, concurrency, recovery, or irreversible side effects.
For high-impact decisions, confidence: low plus resolved_by: statistical_default is invalid unless the designer has explicitly allowed unresolved progress and the SKMB records that permission.
Elicitation Rules
Ask scenario questions, not abstract formalism.
Good:
If the system restarts while an approval is pending, should it resume waiting, auto-deny, or require operator intervention?
Avoid:
What is the transition function for pending_approval under system_restart?
Do not fragment the user with tiny questions. Accumulate related missing decisions into one module-level checkpoint with:
- context gathered so far
- affected module or workflow
- unresolved decision points
- 2-3 viable options per point when useful
- recommended option if one is technically safer
- exact behavior that will be implemented after approval
If there are more than five unresolved decisions, group them by pattern and ask for the highest-risk group first.
Use this checkpoint format:
ISME checkpoint: <module/workflow>
Context gathered:
- <what is known from code/spec/SKMB>
Designer decisions already found:
- <SKMB id / decision file>: <short decision>
Pending decision:
<scenario question>
Options:
1. <option and consequence>
2. <option and consequence>
3. <option and consequence>
Recommendation:
<recommended option if technically safer, or "no recommendation" if normative>
Implementation after approval:
- <exact files/behaviors/tests that will be changed>
Ask one checkpoint at a time unless the user explicitly asks for a full decision agenda.
Statistical Defaults
Use statistical_default only for decisions that are:
- low impact
- locally reversible
- not externally visible
- not security relevant
- not about crash recovery or concurrent conflict resolution
- not about irreversible side effects
- consistent with existing SKMB invariants
When using a statistical default, still emit decision_basis and record it in a decision file plus the SKMB index if it affects future behavior. Mark it for designer review.
When Not To Block
Do not block on ordinary implementation choices that do not define state-machine semantics:
- local variable names
- small helper extraction
- formatting
- logging wording that does not change audit semantics
- internal code organization with no API, persistence, concurrency, or failure behavior impact
- tests that only verify already-resolved designer decisions
If uncertain whether a choice is semantic, classify it. If it touches A-G and changes externally meaningful behavior, use the gate.
Strong Stop Conditions
Stop and ask before acting when any unresolved decision affects:
- crash recovery for a pending or partially completed workflow
- concurrent resolution of the same resource
- fail-open versus fail-closed semantics
- authorization, identity, token expiry, or permission scope
- retry exhaustion and final failure state
- partial completion of an irreversible action
- durable state shape that future code must honor
- externally visible behavior that users, auditors, or operators will rely on
Do not hide these behind tests. Tests that encode an unresolved normative choice are themselves implementation actions and require the gate first.
Verification Before Final Response
Before reporting completion on a task that used this skill, verify:
- every state-machine-affecting action has a visible
decision_basis
- every high-impact decision cites an accepted SKMB decision file or is explicitly pending
- every new designer answer was written to a decision file and indexed
- no decision file uses
decided_by: designer without explicit approval evidence
- every statistical default is recorded as reviewable debt
- no unresolved normative behavior was silently implemented
SKMB Update Format
Keep docs/isme/SKMB.md as an index:
# State Machine Knowledge Base
## Decision Index
| id | status | scope | patterns | file | commit |
| --- | --- | --- | --- | --- | --- |
| SKMB-2026-06-11-001 | accepted | approval workflow | F | decisions/2026-06-11-001-approval-notifier-failure.md | pending |
Add accepted decisions as separate files:
# SKMB-2026-06-11-001: Approval Notifier Failure
- status: accepted
- decided_by: designer
- approval_source: user explicitly chose retry then fail closed in checkpoint response
- date: 2026-06-11
- commit: pending
- patterns:
- F_fail_semantics
- scope: approval workflow
## Decision
Retry 3 times with exponential backoff. If all retries fail, transition to
fail_closed and write an audit event.
## Applies To
- approval state transition
- notifier adapter
- audit log tests
## Supersedes
None.
Open decisions must stay visible in the index and, when they need context, in a proposed decision file:
# SKMB-2026-06-11-002: Approval Resolution Race Policy
- status: proposed
- decided_by: pending
- approval_source: pending explicit designer approval
- date: 2026-06-11
- commit: pending
- patterns:
- C_concurrent_operations
- scope: approval workflow
## Context
Two operators can resolve the same approval with conflicting outcomes.
## Needed Before
Implementing approval resolution write path.
## Options
- first committed wins; second returns conflict
- deny wins
- require supervisor intervention
Practical Boundary
This skill is a strong prompt-level constraint, not a harness-level enforcement engine. If a future hook/plugin can inspect tool calls, map the decision_basis fields directly into pre-tool validation:
planned action -> pattern classification -> SKMB lookup -> designer decision or elicitation -> tool execution.
Until then, the skill must simulate that boundary through explicit checks, visible decision_basis blocks, and SKMB updates before implementation.