개요

운영자 문법 — 사건 기질 모델

문서: operator_grammar.md 경로: /docs/Incident_Substrate_Model/operator_grammar.md 개정: RTT/1 · 정본 상태: 권위 있는 발행일: 2026-05-20


서문#

이 문서는 TriadicFrameworks 정경 내에서 사건 기초 모델 (ISM)에 대한 완전한 연산자 문법을 정의합니다. 모든 연산자는 RTT/1 (재귀 삼원 분류법, 버전 1) 프로토콜에 따라 지정됩니다.

RTT/1 문법 규칙#

규칙 의미
OPERATOR 점-네임스페이스 표기법의 완전한 자격을 갖춘 연산자 식별자
IN(...) 필수 입력 필드; 유형이 지정되고 순서가 정해짐
OUT(...) 방출된 출력 필드; 유형이 지정되고 결정적임
PRE[...] 전제 조건 술어 — 실행 전에 모두 true로 평가되어야 함
POST[...] 사후 조건 주장 — 실행 직후 모두 유지되어야 함
GUARD(...) 연산자 수준의 안전 게이트; 실패 시 연산자가 중단됨
YIELDS → 성공 시 방출된 단말 상태 전환
FAULTS → 명명된 오류 상태; 각 상태는 호출하는 기초에 의해 처리되어야 함
MODE 실행 모드: READONLY, MUTATING, 또는 APPROVAL_GATED
IDEMPOTENT 부작용 축적 없이 안전하게 재시도할 수 있는 연산자

모든 연산자는 결정적입니다: 동일한 기초 상태에서 동일한 입력은 동일한 출력을 생성해야 합니다. 비결정성은 문법 오류입니다.

READONLY로 표시된 연산자는 어떤 지속된 기초 상태도 변경해서는 안 됩니다. MUTATING로 표시된 연산자는 POST[...]에서 모든 상태 전환을 선언해야 합니다. APPROVAL_GATED로 표시된 연산자는 IN(...)에 승인 토큰이 존재할 때까지 GUARD(...)을 넘어서 진행해서는 안 됩니다.

네임스페이스 접두사 incident.는 모든 연산자를 ISM 기초에 범위 지정합니다. 서브 네임스페이스 incident.execute.*는 제한된, 가역적이거나 승인된 실행 연산자 전용으로 예약되어 있습니다.


1. 운영자 패밀리: 수집#


incident.ingest#

모드: MUTATING · 아이템포턴트: 예 (키는 signal_id에 기반함)

목적: 모든 상위 방출기에서 원시 사건 신호를 수락하고 이를 표준 ISM IncidentRecord으로 정규화합니다. 이는 외부 신호 트래픽이 기질로 들어가는 유일한 진입점입니다.

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. 연산자 패밀리: 분류#


incident.classify#

모드: MUTATING · 아이템포턴트: 아니요 (분류는 발전할 수 있으며; 각 호출은 버전이 지정됨)

목적: IncidentRecord에 구조화된 분류를 할당합니다. 분류는 버전이 지정되어 있으며, 후속 호출은 덮어쓰는 대신 새로운 ClassificationVersion을 추가하여 기록의 전체 분류 이력을 보존합니다.

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. 운영자 패밀리: 표면 매핑#


incident.map_surface_area#

모드: MUTATING · 아이템포턴트: 예 (record_id + surface_snapshot_hash 기준)

목적: 분류된 사건이 영향을 미치는 모든 기질 표면(파일, 비밀, 의존성, 서비스, 구성)을 나열합니다. 표면 영역 맵은 모든 하류 수정 및 실행 연산자를 위한 권위 있는 범위 경계입니다.

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. 운영자 가족: 정정 계획#


incident.derive_rectification_steps#

모드: MUTATING · 아이템포턴트: 아니오 (단계 파생은 표면 맵에 따라 버전 관리됨)

목적: 표면 면적 맵에서 정렬된 경계가 있는 수정 단계 목록을 파생합니다. 각 단계는 정확히 하나의 incident.execute.* 연산자에 매핑됩니다. 이 연산자는 아무것도 실행하지 않으며, 오직 유형화된 연산자 바인드 계획만 생성합니다.

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#

모드: READONLY · 아이템포턴트:

목적: 현재 RectificationPlan의 읽기 전용 표현을 인간이 읽을 수 있는 형태로 렌더링합니다. 이 연산자는 어떤 기질 상태도 수정하지 않습니다. 이는 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#

모드: MUTATING · 아이템포턴트: 예 (키는 record_id + uncertainty_code에 기반함)

목적: 기질 또는 계획 에이전트가 인간 검토 없이 진행할 충분한 신뢰가 부족할 때, 기록에 구조화된 불확실성 주석을 첨부합니다. 불확실성을 플래그하는 것은 기록을 차단하지 않으며, 승인 맥락을 풍부하게 하고 에스컬레이션 라우팅을 촉발할 수 있습니다.

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. 운영자 가족: 승인 흐름#


incident.request_operator_approval#

모드: APPROVAL_GATED · MUTATING · 아이템포턴트: 아니오

목적: RectificationPlan에 대한 인간 운영자의 승인을 공식적으로 요청합니다. 기록을 PENDING_APPROVAL로 전환하고 지정된 승인자에게 알립니다. 이 요청이 충족될 때까지 어떤 incident.execute.* 운영자도 진행할 수 없습니다.

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#

모드: MUTATING · 아이템포턴트: 예 (이유가 기존 보류와 일치하는 경우 보류는 아이템포턴트입니다)

목적: HOLD 상태로 기록을 배치하여 모든 보류 중인 실행을 중단합니다. PLAN_DERIVED 이후 언제든지 보류를 설정할 수 있습니다. 실행이 재개되기 전에 보류는 권한이 있는 운영자에 의해 명시적으로 해제되어야 합니다. 이 운영자는 ISM 승인 흐름에서 주요 안전 브레이크입니다.

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. 연산자 계열: 제한된 실행#

모든 incident.execute.* 연산자는 다음 불변성을 공유합니다:

실행 불변성 (이 계열의 모든 연산자에 적용됨)

  1. 대상은 부모 IncidentRecordSurfaceMap에 존재해야 합니다.
  2. 부모 레코드는 APPROVED 상태에 있어야 합니다.
  3. 어떤 실행 연산자도 승인된 RectificationPlan에서 선언된 범위를 초과할 수 없습니다.
  4. 각 실행 연산자는 완료 시(성공 또는 오류) 불변의 ExecutionRecord를 방출합니다.
  5. 오류가 발생한 실행은 PARTIAL_EXECUTION 오류가 방출되지 않고 대상을 부분적으로 수정된 상태로 남겨두어서는 안 됩니다.
  6. reversible: false 단계가 있는 연산자는 실행 시 명시적인 단계 수준 재인정을 요구합니다.

incident.execute.remove_file#

모드: MUTATING · 멱등성: 예 (파일이 없으면, ALREADY_ABSENT 보고)

목적: 표면 영역 맵에 선언된 특정 파일을 제거합니다. 제거는 불변으로 기록됩니다. 파일 경로는 승인된 계획의 FILE-형 표면 항목과 정확히 일치해야 합니다.

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#

모드: MUTATING · 아이템포턴트: 아니요 (각 회전은 새로운 비밀 버전을 생성합니다)

목적: 표면 영역 맵에 선언된 비밀(API 키, 자격 증명, 토큰, 인증서)을 회전합니다. 이전 비밀 값은 무효화되고 새로운 값은 기질의 비밀 관리 계층을 통해 저장됩니다. 새로운 비밀 값은 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#

모드: MUTATING · 아이템포턴트: 예 (record_id + package_ref + target_version 기준)

목적: 의존성 패치를 적용합니다 — 패키지를 선언된 대상 버전으로 업그레이드하거나 고정합니다. 의존성은 표면 영역 맵에서 DEPENDENCY-형 표면 항목으로 선언되어야 합니다. 패치 적용 후에는 결정론적 검증 단계가 따릅니다.

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#

모드: MUTATING · 아이템포턴트: 예 (키는 record_id + followup_code에 기반함)

목적: 현재 수정 기간 내에 완료할 수 없는 사건 후 후속 조치가 필요한 표면 항목 또는 계획 단계를 표시합니다. 이 연산자는 대상을 변형하지 않고 단계를 닫으며, 기초의 추적 레이어에 구조화된 후속 티켓을 생성합니다.

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. 상태 기계#

정형화된 ISM 레코드 상태 기계는 법적 상태 전환을 관리합니다. 아래에 나열된 전환만 유효하며, 나머지는 문법 오류입니다.

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. 타입 레지스트리#

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. 기질 상수#

이 값들은 기질에 의해 구성되며, 운영자 구현에 하드코딩되지 않고 ISM 구성 계층을 통해 재정의되어야 합니다.

상수 기본값 설명
MAX_PAYLOAD_BYTES 10 485 760 (10 MiB) 섭취를 위한 최대 raw_payload 크기
MIN_CLASSIFICATION_CONFIDENCE 0.70 분류가 진행되기 위한 최소 신뢰도
MAX_SURFACE_ENTRIES 500 표면 맵당 최대 표면 항목 수
MAX_PLAN_STEPS 50 계획당 최대 정정 단계 수
MIN_OTHER_DETAIL_LENGTH 80 chars UncertaintyCode가 OTHER일 때 최소 세부 정보 길이
MIN_RISK_ACCEPTANCE_DETAIL_LENGTH 150 chars RISK_ACCEPTED 후속 플래그에 대한 최소 세부 정보

10. 문법 불변#

다음 불변 조건은 전체 ISM 연산자 문법에 적용됩니다. 어떤 불변 조건의 위반도 연산자 오류가 아닌 기초 오류입니다.

  1. 네임스페이스 격리: incident.* 네임스페이스 외부의 어떤 연산자도 IncidentRecord을 수정할 수 없습니다.
  2. 계획 불변성: RectificationPlanPENDING_APPROVAL에 들어가면 불변입니다. 재계획은 승인 거부를 통해 PLAN_DERIVED로 돌아가야 합니다.
  3. 표면 범위 집행: incident.execute.* 연산자는 승인된 SurfaceMap에 선언된 대상에만 작용할 수 있습니다. 범위를 벗어난 대상은 문법 오류입니다.
  4. 제로 비밀 값 보장: 비밀 값은 어떤 OUT, ExecutionRecord, 로그 또는 감사 추적에도 나타나지 않아야 합니다. 버전 식별자와 참조는 허용됩니다.
  5. 실행 순서: incident.execute.* 단계는 step_index 순서로 실행되어야 하며, RectificationPlan이 명시적인 병렬 그룹을 선언하지 않는 한 그렇습니다. 기본값은 엄격히 순차적입니다.
  6. 승인 게이트: incident.execute.* 연산자는 IncidentRecord.state == APPROVEDapproval_request_id가 기록에 존재하지 않는 한 시작할 수 없습니다.
  7. 불확실성 플래그 상승: 심각도 BLOCKING의 불확실성 플래그는 incident.request_operator_approval이 진행되기 전에 해결되거나 명시적으로 인정되어야 합니다.
  8. 보류 우선권: HOLD 상태의 기록은 승인 상태와 관계없이 어떤 incident.execute.* 연산자도 호출될 수 없습니다.
  9. 종단 상태 최종성: RESOLVED 또는 FAULTED 상태의 기록은 불변입니다. 새로운 사건 신호는 incident.ingest을 통해 새로운 기록으로 들어와야 합니다.
  10. 결정론 요구: 모든 연산자는 동일한 기초 상태에서 동일한 OUT를 동일한 IN에 대해 생성해야 합니다. 비결정성을 보이는 연산자는 문법 오류입니다.

연산자 문법 문서의 끝. 정식 출처: /docs/Incident_Substrate_Model/operator_grammar.md · TriadicFrameworks 저장소 RTT/1 Canon · ISM 문법 v1.0


포함된 내용: 6개 패밀리의 12개 연산자, 10상태 결정론적 기록 상태 기계, 완전한 유형 레지스트리, 기초 상수 표, 10개의 교차 절단 문법 불변 — 모두 RTT/1 OPERATOR / IN / OUT / PRE / POST / GUARD / YIELDS / FAULTS 형식으로.