Operator Grammar — Incident Substrate Model
Document: operator_grammar.md
Path: /docs/Incident_Substrate_Model/operator_grammar.md
Revision: RTT/1 · Canon Edition
Status: Authoritative
Issued: 2026-05-20
Preamble#
This document defines the complete operator grammar for the Incident Substrate Model (ISM) within the TriadicFrameworks canon. All operators are specified under the RTT/1 (Recursive Triadic Taxonomy, version 1) protocol.
RTT/1 Grammar Conventions#
| Convention | Meaning |
|---|---|
OPERATOR |
Fully-qualified operator identifier in dot-namespace notation |
IN(...) |
Required input fields; typed and ordered |
OUT(...) |
Emitted output fields; typed and deterministic |
PRE[...] |
Precondition predicates — must all evaluate true before execution |
POST[...] |
Postcondition assertions — must all hold immediately after execution |
GUARD(...) |
Operator-level safety gates; failure aborts the operator |
YIELDS → |
Terminal state transition emitted on success |
FAULTS → |
Named fault states; each must be handled by the calling substrate |
MODE |
Execution mode: READONLY, MUTATING, or APPROVAL_GATED |
IDEMPOTENT |
Operator may be safely retried without side-effect accumulation |
All operators are deterministic: identical inputs under identical substrate state must produce identical outputs. Non-determinism is a grammar fault.
Operators marked READONLY must not alter any persisted substrate state. Operators marked MUTATING must declare all state transitions in POST[...]. Operators marked APPROVAL_GATED must not proceed past their GUARD(...) until an approval token is present in IN(...).
Namespace prefix incident. scopes all operators to the ISM substrate. Sub-namespace incident.execute.* is reserved for bounded, reversible-or-acknowledged execution operators only.
1. Operator Family: Ingestion#
incident.ingest#
MODE: MUTATING · IDEMPOTENT: Yes (keyed on signal_id)
Purpose: Accept a raw incident signal from any upstream emitter and normalize it into a canonical ISM IncidentRecord. This is the sole entry point for external signal traffic into the substrate.
OPERATOR incident.ingest
IN(
signal_id : UUID, -- Emitter-assigned unique signal identifier
source : String, -- Emitter identity (service name, sensor label, etc.)
raw_payload : Bytes, -- Unprocessed signal body; encoding declared by content_type
content_type : MIME, -- e.g. "application/json", "text/plain"
emitted_at : Timestamp, -- Emitter-side emission time (UTC ISO-8601)
severity_hint : SeverityHint? -- Optional emitter-declared severity; may be overridden downstream
)
OUT(
record_id : UUID, -- ISM-assigned canonical record identifier
ingested_at : Timestamp, -- Substrate-side ingestion time (UTC ISO-8601)
status : IngestionStatus -- ACCEPTED | DUPLICATE | REJECTED
)
PRE[
signal_id is syntactically valid UUID,
source is non-empty and registered in the emitter registry,
raw_payload byte length > 0,
content_type is a supported MIME type,
emitted_at <= substrate_clock.now()
]
POST[
status == ACCEPTED → IncidentRecord(record_id) exists in substrate with state = INGESTED,
status == DUPLICATE → no new record created; existing record_id returned,
status == REJECTED → no record created; fault emitted
]
GUARD(
emitter is authorized: source ∈ allowed_emitter_set,
payload size <= MAX_PAYLOAD_BYTES
)
YIELDS → INGESTED
FAULTS → UNAUTHORIZED_EMITTER | PAYLOAD_TOO_LARGE | MALFORMED_SIGNAL | UNSUPPORTED_CONTENT_TYPE
2. Operator Family: Classification#
incident.classify#
MODE: MUTATING · IDEMPOTENT: No (classification may evolve; each call is versioned)
Purpose: Assign a structured classification to an IncidentRecord. Classification is versioned — successive calls append a new ClassificationVersion rather than overwriting, preserving the full classification history on the record.
OPERATOR incident.classify
IN(
record_id : UUID, -- Target IncidentRecord
classifier_id : String, -- Identity of the classifying agent or model
category : IncidentCategory, -- Primary taxonomy node (e.g. SECRET_LEAK, DEPENDENCY_CVE)
subcategory : String?, -- Optional free-form subcategory label
confidence : Float[0.0,1.0], -- Classifier confidence in this classification
rationale : String -- Human-readable classification rationale
)
OUT(
record_id : UUID,
classification_version : UInt, -- Monotonically increasing version index on this record
effective_at : Timestamp
)
PRE[
IncidentRecord(record_id) exists,
IncidentRecord(record_id).state ∈ {INGESTED, CLASSIFIED, SURFACE_MAPPED},
confidence ∈ [0.0, 1.0],
rationale is non-empty
]
POST[
IncidentRecord(record_id).classification == ClassificationVersion(classification_version),
IncidentRecord(record_id).state == CLASSIFIED,
classification_version == previous_version + 1
]
GUARD(
classifier_id is registered,
confidence >= MIN_CLASSIFICATION_CONFIDENCE -- substrate-configured threshold
)
YIELDS → CLASSIFIED
FAULTS → RECORD_NOT_FOUND | INVALID_CATEGORY | CONFIDENCE_BELOW_THRESHOLD | INVALID_STATE_TRANSITION
3. Operator Family: Surface Mapping#
incident.map_surface_area#
MODE: MUTATING · IDEMPOTENT: Yes (keyed on record_id + surface_snapshot_hash)
Purpose: Enumerate all substrate surfaces (files, secrets, dependencies, services, configurations) that the classified incident touches. The surface area map is the authoritative scope boundary for all downstream rectification and execution operators.
OPERATOR incident.map_surface_area
IN(
record_id : UUID,
scanner_id : String, -- Identity of the surface scanner agent
surfaces : List<SurfaceEntry>, -- See SurfaceEntry schema below
surface_snapshot_hash : Hash -- Content hash of the surfaces list for idempotency
)
-- SurfaceEntry schema:
-- surface_type : SurfaceType (FILE | SECRET | DEPENDENCY | SERVICE | CONFIG)
-- surface_ref : String (path, ARN, package@version, service name, config key)
-- access_mode : AccessMode (READ | WRITE | EXECUTE | UNKNOWN)
-- confidence : Float[0.0,1.0]
-- notes : String?
OUT(
record_id : UUID,
surface_map_id : UUID, -- Stable identifier for this surface map snapshot
surface_count : UInt,
mapped_at : Timestamp
)
PRE[
IncidentRecord(record_id) exists,
IncidentRecord(record_id).state == CLASSIFIED,
surfaces is non-empty,
all surface_ref values are syntactically valid for their surface_type,
surface_snapshot_hash == hash(surfaces)
]
POST[
IncidentRecord(record_id).surface_map_id == surface_map_id,
IncidentRecord(record_id).state == SURFACE_MAPPED,
SurfaceMap(surface_map_id).entries.count == surface_count
]
GUARD(
scanner_id is registered,
surface_count <= MAX_SURFACE_ENTRIES -- prevents unbounded scope creep
)
YIELDS → SURFACE_MAPPED
FAULTS → RECORD_NOT_FOUND | INVALID_STATE_TRANSITION | EMPTY_SURFACE_LIST
| SURFACE_REF_INVALID | SURFACE_LIMIT_EXCEEDED | HASH_MISMATCH
4. Operator Family: Rectification Planning#
incident.derive_rectification_steps#
MODE: MUTATING · IDEMPOTENT: No (step derivation is versioned per surface map)
Purpose: Derive an ordered, bounded list of rectification steps from the surface area map. Each step maps to exactly one incident.execute.* operator. This operator does not execute anything — it produces a typed, operator-bound plan only.
OPERATOR incident.derive_rectification_steps
IN(
record_id : UUID,
surface_map_id : UUID,
planner_id : String, -- Identity of the planning agent
steps : List<RectificationStep> -- See RectificationStep schema below
)
-- RectificationStep schema:
-- step_index : UInt (0-based; must be unique and gapless)
-- operator_ref : OperatorRef (must resolve to an incident.execute.* operator)
-- target_ref : String (must exist in SurfaceMap(surface_map_id).entries)
-- parameters : Map<String,Any>
-- reversible : Bool
-- rationale : String
OUT(
record_id : UUID,
plan_id : UUID,
step_count : UInt,
derived_at : Timestamp
)
PRE[
IncidentRecord(record_id) exists,
IncidentRecord(record_id).state == SURFACE_MAPPED,
IncidentRecord(record_id).surface_map_id == surface_map_id,
steps is non-empty,
step indices are 0-based, unique, and gapless,
all operator_ref values resolve to valid incident.execute.* operators,
all target_ref values exist in SurfaceMap(surface_map_id).entries
]
POST[
IncidentRecord(record_id).plan_id == plan_id,
IncidentRecord(record_id).state == PLAN_DERIVED,
RectificationPlan(plan_id).steps.count == step_count
]
GUARD(
planner_id is registered,
step_count <= MAX_PLAN_STEPS,
all operator_ref values are within the incident.execute.* namespace only
)
YIELDS → PLAN_DERIVED
FAULTS → RECORD_NOT_FOUND | INVALID_STATE_TRANSITION | SURFACE_MAP_MISMATCH
| STEP_INDEX_INVALID | UNKNOWN_OPERATOR_REF | TARGET_NOT_IN_SURFACE_MAP
| PLAN_STEP_LIMIT_EXCEEDED
incident.generate_readonly_plan#
MODE: READONLY · IDEMPOTENT: Yes
Purpose: Render a human-readable, read-only representation of the current RectificationPlan for review. This operator does not modify any substrate state. It is the canonical gate before incident.request_operator_approval.
OPERATOR incident.generate_readonly_plan
IN(
record_id : UUID,
plan_id : UUID,
format : PlanFormat -- MARKDOWN | JSON | TEXT
)
OUT(
record_id : UUID,
plan_id : UUID,
rendered_plan : String, -- Plan body in requested format; no executable content
rendered_at : Timestamp
)
PRE[
IncidentRecord(record_id) exists,
IncidentRecord(record_id).plan_id == plan_id,
IncidentRecord(record_id).state ∈ {PLAN_DERIVED, PENDING_APPROVAL, APPROVED, HOLD},
format ∈ {MARKDOWN, JSON, TEXT}
]
POST[
no substrate state modified,
rendered_plan is non-empty,
rendered_plan contains no embedded operator invocations or executable directives
]
GUARD(
rendered_plan must not contain control characters or script injection patterns
)
YIELDS → (no state transition; read-only)
FAULTS → RECORD_NOT_FOUND | PLAN_NOT_FOUND | PLAN_ID_MISMATCH | UNSUPPORTED_FORMAT
incident.flag_uncertainty#
MODE: MUTATING · IDEMPOTENT: Yes (keyed on record_id + uncertainty_code)
Purpose: Attach a structured uncertainty annotation to a record when the substrate or a planning agent lacks sufficient confidence to proceed without human review. Flagging uncertainty does not block the record — it enriches the approval context and may trigger escalation routing.
OPERATOR incident.flag_uncertainty
IN(
record_id : UUID,
flagging_agent : String,
uncertainty_code : UncertaintyCode, -- See UncertaintyCode registry below
affected_field : String?, -- Optional pointer to the uncertain field or step
detail : String -- Human-readable description of the uncertainty
)
-- UncertaintyCode registry:
-- CLASSIFICATION_AMBIGUOUS -- Multiple categories plausible with similar confidence
-- SURFACE_INCOMPLETE -- Scanner may have missed surfaces
-- STEP_REVERSIBILITY_UNKNOWN -- Cannot confirm if a rectification step is reversible
-- AUTHORIZATION_AMBIGUOUS -- Approver set is unclear
-- EXTERNAL_DEPENDENCY_UNKNOWN -- Third-party behavior required for rectification is unverified
-- OTHER -- Catch-all; detail is mandatory when used
OUT(
record_id : UUID,
flag_id : UUID,
flagged_at : Timestamp
)
PRE[
IncidentRecord(record_id) exists,
uncertainty_code ∈ UncertaintyCode registry,
detail is non-empty,
if uncertainty_code == OTHER then detail.length >= MIN_OTHER_DETAIL_LENGTH
]
POST[
UncertaintyFlag(flag_id) attached to IncidentRecord(record_id),
IncidentRecord(record_id).uncertainty_flags.count increased by 1
]
GUARD(
flagging_agent is registered
)
YIELDS → (no state transition; annotation only)
FAULTS → RECORD_NOT_FOUND | UNKNOWN_UNCERTAINTY_CODE | EMPTY_DETAIL
| INSUFFICIENT_OTHER_DETAIL
5. Operator Family: Approval Flow#
incident.request_operator_approval#
MODE: APPROVAL_GATED · MUTATING · IDEMPOTENT: No
Purpose: Formally request human operator approval for the RectificationPlan. Transitions the record to PENDING_APPROVAL and notifies the designated approver set. No incident.execute.* operator may proceed until this request is satisfied.
OPERATOR incident.request_operator_approval
IN(
record_id : UUID,
plan_id : UUID,
requesting_agent : String,
approver_set : List<ApproverRef>, -- At least one approver required
approval_policy : ApprovalPolicy, -- ANY_ONE | MAJORITY | ALL
context_note : String? -- Optional note for the approver set
)
OUT(
record_id : UUID,
approval_request_id : UUID,
requested_at : Timestamp,
approver_count : UInt
)
PRE[
IncidentRecord(record_id) exists,
IncidentRecord(record_id).plan_id == plan_id,
IncidentRecord(record_id).state == PLAN_DERIVED,
approver_set is non-empty,
all ApproverRef values are resolvable in the approver registry,
approval_policy ∈ {ANY_ONE, MAJORITY, ALL}
]
POST[
IncidentRecord(record_id).state == PENDING_APPROVAL,
IncidentRecord(record_id).approval_request_id == approval_request_id,
approver_set notified via substrate notification channel
]
GUARD(
requesting_agent is registered,
plan_id refers to a non-empty, validated RectificationPlan,
record has no open uncertainty flags with severity >= BLOCKING
unless explicitly acknowledged in context_note
)
YIELDS → PENDING_APPROVAL
FAULTS → RECORD_NOT_FOUND | PLAN_NOT_FOUND | INVALID_STATE_TRANSITION
| EMPTY_APPROVER_SET | UNKNOWN_APPROVER | BLOCKING_UNCERTAINTY_FLAGS
| INVALID_APPROVAL_POLICY
incident.hold_for_review#
MODE: MUTATING · IDEMPOTENT: Yes (hold is idempotent if reason matches existing hold)
Purpose: Place a record into a HOLD state, suspending all pending execution. A hold may be placed at any point after PLAN_DERIVED. Holds must be explicitly released by an authorized operator before execution can resume. This operator is the primary safety brake in the ISM approval flow.
OPERATOR incident.hold_for_review
IN(
record_id : UUID,
held_by : String, -- Identity of the hold-placing operator or agent
reason_code : HoldReason, -- See HoldReason registry below
detail : String, -- Mandatory detail regardless of reason_code
resume_after : Timestamp? -- Optional: earliest time hold may be lifted
)
-- HoldReason registry:
-- MANUAL_REVIEW_REQUESTED
-- BLOCKING_UNCERTAINTY
-- APPROVAL_DISPUTED
-- EXTERNAL_DEPENDENCY_PENDING
-- POLICY_ESCALATION
-- SUBSTRATE_FAULT
OUT(
record_id : UUID,
hold_id : UUID,
held_at : Timestamp,
prior_state : RecordState -- State the record was in before hold
)
PRE[
IncidentRecord(record_id) exists,
IncidentRecord(record_id).state ∈ {PLAN_DERIVED, PENDING_APPROVAL, APPROVED},
reason_code ∈ HoldReason registry,
detail is non-empty
]
POST[
IncidentRecord(record_id).state == HOLD,
IncidentRecord(record_id).hold_id == hold_id,
HoldRecord(hold_id).prior_state == prior_state,
all queued incident.execute.* steps for record_id are suspended
]
GUARD(
held_by is authorized to place holds on this record
)
YIELDS → HOLD
FAULTS → RECORD_NOT_FOUND | INVALID_STATE_TRANSITION | UNKNOWN_HOLD_REASON
| HOLD_UNAUTHORIZED | EMPTY_DETAIL
6. Operator Family: Bounded Execution#
All incident.execute.* operators share these invariants:
Execution Invariants (apply to all operators in this family)
- Target must exist in
SurfaceMapof the parentIncidentRecord.- Parent record must be in state
APPROVED.- No execution operator may exceed the scope declared in the approved
RectificationPlan.- Each execution operator emits an immutable
ExecutionRecordon completion (success or fault).- Faulted executions must not leave targets in a partially-modified state without a
PARTIAL_EXECUTIONfault being emitted.- Operators with
reversible: falsesteps require explicit step-level re-acknowledgment at execution time.
incident.execute.remove_file#
MODE: MUTATING · IDEMPOTENT: Yes (if file absent, reports ALREADY_ABSENT)
Purpose: Remove a specific file declared in the surface area map. Removal is logged immutably. The file path must exactly match a FILE-typed surface entry in the approved plan.
OPERATOR incident.execute.remove_file
IN(
record_id : UUID,
plan_id : UUID,
step_index : UInt,
file_path : String, -- Absolute canonical path; must match surface entry exactly
checksum : Hash?, -- Optional pre-removal checksum for audit
dry_run : Bool -- If true, validate only; do not remove
)
OUT(
record_id : UUID,
execution_id : UUID,
status : ExecutionStatus, -- REMOVED | ALREADY_ABSENT | DRY_RUN_OK
removed_at : Timestamp?,
prior_checksum : Hash?
)
PRE[
IncidentRecord(record_id).state == APPROVED,
IncidentRecord(record_id).plan_id == plan_id,
RectificationPlan(plan_id).steps[step_index].operator_ref == "incident.execute.remove_file",
RectificationPlan(plan_id).steps[step_index].target_ref == file_path,
file_path ∈ SurfaceMap(IncidentRecord(record_id).surface_map_id) with surface_type == FILE
]
POST[
dry_run == false AND status == REMOVED →
file at file_path no longer exists,
ExecutionRecord(execution_id) created with status REMOVED,
dry_run == true →
no filesystem state changed,
ExecutionRecord(execution_id) created with status DRY_RUN_OK
]
GUARD(
executor has filesystem write access to file_path,
file_path does not resolve outside declared substrate boundaries (no path traversal)
)
YIELDS → STEP_EXECUTED
FAULTS → RECORD_NOT_FOUND | PLAN_STEP_MISMATCH | FILE_NOT_IN_SURFACE_MAP
| ACCESS_DENIED | PATH_TRAVERSAL_DETECTED | PARTIAL_EXECUTION
| CHECKSUM_MISMATCH
incident.execute.rotate_secret#
MODE: MUTATING · IDEMPOTENT: No (each rotation produces a new secret version)
Purpose: Rotate a secret (API key, credential, token, certificate) declared in the surface area map. The old secret value is invalidated and the new value is stored via the substrate's secret management layer. The new secret value is never emitted in OUT.
OPERATOR incident.execute.rotate_secret
IN(
record_id : UUID,
plan_id : UUID,
step_index : UInt,
secret_ref : String, -- ARN, vault path, or secret identifier; must match surface entry
rotation_policy : RotationPolicy, -- IMMEDIATE | SCHEDULED
notify_dependents : Bool -- If true, substrate notifies registered secret consumers
)
OUT(
record_id : UUID,
execution_id : UUID,
status : ExecutionStatus, -- ROTATED | SCHEDULED
new_secret_version : String, -- Version identifier only; NOT the secret value
rotated_at : Timestamp?
)
PRE[
IncidentRecord(record_id).state == APPROVED,
IncidentRecord(record_id).plan_id == plan_id,
RectificationPlan(plan_id).steps[step_index].operator_ref == "incident.execute.rotate_secret",
RectificationPlan(plan_id).steps[step_index].target_ref == secret_ref,
secret_ref ∈ SurfaceMap(IncidentRecord(record_id).surface_map_id) with surface_type == SECRET,
rotation_policy ∈ {IMMEDIATE, SCHEDULED}
]
POST[
status == ROTATED →
old secret version invalidated in secret management layer,
new_secret_version active,
notify_dependents == true → dependent consumers notified,
ExecutionRecord(execution_id) created,
new secret value never stored in ExecutionRecord or any ISM log
]
GUARD(
executor has secret rotation authorization for secret_ref,
new secret value is never written to OUT or any audit log (zero-secret-value guarantee)
)
YIELDS → STEP_EXECUTED
FAULTS → RECORD_NOT_FOUND | PLAN_STEP_MISMATCH | SECRET_NOT_IN_SURFACE_MAP
| ROTATION_UNAUTHORIZED | ROTATION_PROVIDER_ERROR | PARTIAL_EXECUTION
| DEPENDENT_NOTIFICATION_FAILED
incident.execute.patch_dependency#
MODE: MUTATING · IDEMPOTENT: Yes (keyed on record_id + package_ref + target_version)
Purpose: Apply a dependency patch — upgrading or pinning a package to a declared target version. The dependency must be declared in the surface area map as a DEPENDENCY-typed surface entry. Patch application is followed by a deterministic verification step.
OPERATOR incident.execute.patch_dependency
IN(
record_id : UUID,
plan_id : UUID,
step_index : UInt,
package_ref : String, -- Package identifier, e.g. "npm:lodash" or "pypi:requests"
current_version : String, -- Version being replaced; must match installed version
target_version : String, -- Version to install; must be a known-good release
package_manager : PackageManager, -- NPM | PIP | CARGO | MAVEN | GRADLE | OTHER
verify_checksum : Hash?, -- Optional expected checksum of target package
dry_run : Bool
)
OUT(
record_id : UUID,
execution_id : UUID,
status : ExecutionStatus, -- PATCHED | DRY_RUN_OK | ALREADY_AT_TARGET
patched_version : String?,
patched_at : Timestamp?
)
PRE[
IncidentRecord(record_id).state == APPROVED,
IncidentRecord(record_id).plan_id == plan_id,
RectificationPlan(plan_id).steps[step_index].operator_ref == "incident.execute.patch_dependency",
RectificationPlan(plan_id).steps[step_index].target_ref == package_ref,
package_ref ∈ SurfaceMap(IncidentRecord(record_id).surface_map_id) with surface_type == DEPENDENCY,
current_version is semver-valid,
target_version is semver-valid,
target_version > current_version OR target_version is an explicit pinned release
]
POST[
dry_run == false AND status == PATCHED →
package at package_ref upgraded to target_version,
verify_checksum provided → checksum verified against installed package,
ExecutionRecord(execution_id) created,
dry_run == true →
no package state changed,
ExecutionRecord(execution_id) created with DRY_RUN_OK
]
GUARD(
executor has write access to the dependency manifest and lock file,
target_version is not marked deprecated or yanked in package_manager registry,
verify_checksum provided → checksum must match before activation
)
YIELDS → STEP_EXECUTED
FAULTS → RECORD_NOT_FOUND | PLAN_STEP_MISMATCH | DEPENDENCY_NOT_IN_SURFACE_MAP
| VERSION_MISMATCH | TARGET_VERSION_INVALID | PACKAGE_MANAGER_ERROR
| CHECKSUM_MISMATCH | PARTIAL_EXECUTION
incident.execute.flag_for_followup#
MODE: MUTATING · IDEMPOTENT: Yes (keyed on record_id + followup_code)
Purpose: Mark a surface entry or plan step as requiring post-incident follow-up action that cannot be completed within the current remediation window. This operator closes the step without mutating the target, emitting a structured follow-up ticket into the substrate's tracking layer.
OPERATOR incident.execute.flag_for_followup
IN(
record_id : UUID,
plan_id : UUID,
step_index : UInt,
target_ref : String, -- Surface entry or step reference being deferred
followup_code : FollowupCode, -- See FollowupCode registry below
priority : FollowupPriority, -- CRITICAL | HIGH | MEDIUM | LOW
assigned_to : List<String>, -- Assignee identifiers; at least one required
due_by : Timestamp?, -- Optional deadline
detail : String -- Mandatory description of follow-up action required
)
-- FollowupCode registry:
-- MANUAL_REMEDIATION_REQUIRED -- Step requires human action beyond substrate capability
-- THIRD_PARTY_COORDINATION -- Remediation depends on external party
-- DEFERRAL_APPROVED -- Approved deferral; reason documented in detail
-- RISK_ACCEPTED -- Risk explicitly accepted; documented in detail
-- MONITORING_REQUIRED -- No action now; ongoing monitoring required
OUT(
record_id : UUID,
execution_id : UUID,
followup_id : UUID, -- Tracking ticket identifier
status : ExecutionStatus, -- FLAGGED
flagged_at : Timestamp
)
PRE[
IncidentRecord(record_id).state == APPROVED,
IncidentRecord(record_id).plan_id == plan_id,
RectificationPlan(plan_id).steps[step_index].operator_ref == "incident.execute.flag_for_followup",
followup_code ∈ FollowupCode registry,
priority ∈ {CRITICAL, HIGH, MEDIUM, LOW},
assigned_to is non-empty,
detail is non-empty
]
POST[
FollowupTicket(followup_id) created in substrate tracking layer,
FollowupTicket(followup_id).assigned_to == assigned_to,
ExecutionRecord(execution_id) created with status FLAGGED,
step_index marked FLAGGED_FOR_FOLLOWUP in RectificationPlan(plan_id)
]
GUARD(
all assigned_to identifiers resolvable in operator registry,
if followup_code == RISK_ACCEPTED →
detail.length >= MIN_RISK_ACCEPTANCE_DETAIL_LENGTH
)
YIELDS → STEP_EXECUTED
FAULTS → RECORD_NOT_FOUND | PLAN_STEP_MISMATCH | UNKNOWN_FOLLOWUP_CODE
| INVALID_PRIORITY | EMPTY_ASSIGNEE_LIST | UNRESOLVABLE_ASSIGNEE
| INSUFFICIENT_RISK_DETAIL | EMPTY_DETAIL
7. State Machine#
The canonical ISM record state machine governs legal state transitions. Only transitions listed below are valid; all others are grammar faults.
INGESTED
→ CLASSIFIED via incident.classify
→ HOLD via incident.hold_for_review
CLASSIFIED
→ SURFACE_MAPPED via incident.map_surface_area
→ CLASSIFIED via incident.classify (re-classification; version++)
→ HOLD via incident.hold_for_review
SURFACE_MAPPED
→ PLAN_DERIVED via incident.derive_rectification_steps
→ CLASSIFIED via incident.classify (reclassify; resets to CLASSIFIED)
→ HOLD via incident.hold_for_review
PLAN_DERIVED
→ PENDING_APPROVAL via incident.request_operator_approval
→ HOLD via incident.hold_for_review
PENDING_APPROVAL
→ APPROVED via [approval resolution: external to grammar]
→ PLAN_DERIVED via [approval rejection: external to grammar]
→ HOLD via incident.hold_for_review
HOLD
→ [prior_state] via [hold release: external to grammar; restores prior_state]
APPROVED
→ EXECUTING via [first incident.execute.* invocation]
→ HOLD via incident.hold_for_review
EXECUTING
→ RESOLVED via [all plan steps STEP_EXECUTED or FLAGGED_FOR_FOLLOWUP]
→ HOLD via incident.hold_for_review
→ FAULTED via [any PARTIAL_EXECUTION fault on any step]
RESOLVED -- Terminal: no further state transitions permitted
FAULTED -- Terminal: requires manual intervention; may spawn new record via incident.ingest
8. Type Registry#
UUID ::= RFC 4122 v4 UUID string
Timestamp ::= ISO-8601 UTC datetime string, precision to milliseconds
Hash ::= SHA-256 hex digest string (64 hex characters)
MIME ::= IANA-registered MIME type string
SeverityHint ::= CRITICAL | HIGH | MEDIUM | LOW | UNKNOWN
IncidentCategory ::= SECRET_LEAK | DEPENDENCY_CVE | MISCONFIGURATION | UNAUTHORIZED_ACCESS
| DATA_EXPOSURE | SUPPLY_CHAIN | POLICY_VIOLATION | UNKNOWN
SurfaceType ::= FILE | SECRET | DEPENDENCY | SERVICE | CONFIG
AccessMode ::= READ | WRITE | EXECUTE | UNKNOWN
IngestionStatus ::= ACCEPTED | DUPLICATE | REJECTED
ExecutionStatus ::= REMOVED | ROTATED | PATCHED | FLAGGED | ALREADY_ABSENT
| ALREADY_AT_TARGET | DRY_RUN_OK | SCHEDULED
RecordState ::= INGESTED | CLASSIFIED | SURFACE_MAPPED | PLAN_DERIVED
| PENDING_APPROVAL | APPROVED | EXECUTING | HOLD | RESOLVED | FAULTED
PlanFormat ::= MARKDOWN | JSON | TEXT
ApprovalPolicy ::= ANY_ONE | MAJORITY | ALL
PackageManager ::= NPM | PIP | CARGO | MAVEN | GRADLE | OTHER
FollowupPriority ::= CRITICAL | HIGH | MEDIUM | LOW
OperatorRef ::= Fully-qualified dot-namespace string resolving to an incident.execute.* operator
ApproverRef ::= Opaque string resolvable in the approver registry
9. Substrate Constants#
These values are substrate-configured and must be overridden via the ISM configuration layer, not hardcoded in operator implementations.
| Constant | Default | Description |
|---|---|---|
MAX_PAYLOAD_BYTES |
10 485 760 (10 MiB) | Maximum raw_payload size for ingestion |
MIN_CLASSIFICATION_CONFIDENCE |
0.70 | Minimum confidence for classification to proceed |
MAX_SURFACE_ENTRIES |
500 | Maximum surface entries per surface map |
MAX_PLAN_STEPS |
50 | Maximum rectification steps per plan |
MIN_OTHER_DETAIL_LENGTH |
80 chars | Minimum detail length when UncertaintyCode is OTHER |
MIN_RISK_ACCEPTANCE_DETAIL_LENGTH |
150 chars | Minimum detail for RISK_ACCEPTED follow-up flags |
10. Grammar Invariants#
The following invariants hold across the entire ISM operator grammar. Violation of any invariant is a substrate fault, not an operator fault.
- Namespace isolation: No operator outside the
incident.*namespace may modify anIncidentRecord. - Plan immutability: A
RectificationPlanis immutable oncePENDING_APPROVALis entered. Re-planning requires returning toPLAN_DERIVEDvia approval rejection. - Surface scope enforcement:
incident.execute.*operators may only act on targets declared in the approvedSurfaceMap. Out-of-scope targets are a grammar fault. - Zero secret value guarantee: Secret values must never appear in any
OUT,ExecutionRecord, log, or audit trail. Version identifiers and references are permitted. - Execution sequencing:
incident.execute.*steps must be executed instep_indexorder unless theRectificationPlandeclares explicit parallel groups. Default is strictly sequential. - Approval gate: No
incident.execute.*operator may begin unlessIncidentRecord.state == APPROVEDandapproval_request_idis present on the record. - Uncertainty flag escalation: Uncertainty flags with severity
BLOCKINGmust be resolved or explicitly acknowledged beforeincident.request_operator_approvalmay proceed. - Hold supremacy: A record in state
HOLDcannot have anyincident.execute.*operator invoked against it, regardless of approval status. - Terminal state finality: Records in
RESOLVEDorFAULTEDstates are immutable. New incident signals must enter viaincident.ingestas new records. - Determinism requirement: All operators must produce identical
OUTfor identicalINunder identical substrate state. Any operator exhibiting non-determinism is a grammar fault.
End of operator grammar document.
Canonical source: /docs/Incident_Substrate_Model/operator_grammar.md · TriadicFrameworks repository
RTT/1 Canon · ISM Grammar v1.0
What's covered: all 12 operators across 6 families, a 10-state deterministic record state machine, a complete type registry, substrate constants table, and 10 cross-cutting grammar invariants — all in RTT/1 OPERATOR / IN / OUT / PRE / POST / GUARD / YIELDS / FAULTS form.