commitwork docs

STPA / HAZOP++ Field Guide

Two hazard-analysis lenses run together in commitwork: STPA judges control loops from the controller's side, HAZOP++ walks data boundaries from the crossing's side. The STPA vocabulary below is the one monitor/failure-taxonomy.json applies to every taxonomy class, and monitor/stpa-sweep.mjs re-evaluates commitwork's own panel and remediation control loop against a fixed UCA and HAZOP table. The HAZOP++ worked examples come from commitwork's analysis of its CWE → CAPEC → ATT&CK enrichment, with the figures measured over the tracked MITRE data.

statvalue
STPA loops6
UCA values8
causal factors16
guide words10 standard + 2 ext. + 2 proposed

01 — STPA — System-Theoretic Process Analysis

STPA judges a system by its control loops: a controller issues actions to a process it does not directly see, and reads that process back through feedback. A hazard is a state the loop can reach — not a component that breaks.

The control loop being judged

figure

Every STPA hazard traces to one of four faults in this loop: the controller's process model is wrong, the action it issues is unsafe, the actuator mangles or delays it, or the feedback lies. Control actions are drawn in red and feedback in blue throughout this page.

The four stages, in order

figure

Standard four-stage STPA (Leveson & Thomas), unchanged from the textbook form — commitwork's own extension is in the vocabulary it judges with: named controller loops, UCA values and causal factors, below.

Commitwork's applied vocabulary

Every taxonomy class in monitor/failure-taxonomy.json carries an stpa judgment built from three closed sets — a UCA is a triple: which loop, which of 8 failure shapes, which of 16 root causes.

6 loops (who's the controller): operator · monitor · scanner · agent · oversight · attention

8 UCA values (how it failed): not-provided · unsafe · too-early · too-late · out-of-order · stopped-too-soon · applied-too-long · none

16 causes (why): controller-algorithm · controller-model · higher-input · actuator-delayed · actuator-missing · actuator-corrupt · process-failure · process-change · process-disturbance · feedback-missing · feedback-delayed · feedback-incorrect · sensor-inadequate · coordination-conflict · coordination-gap · coordination-duplicate

The main extension past the textbook: the attention loop has no equivalent in Leveson's original model. It treats a published verdict itself as a control action — the failure mode isn't a broken pipe, it's a report that spends or withholds the operator's attention wrongly. Built for a monitoring system, where the paper's control-structure model (built for physical/organisational systems) has nothing to say. A second, smaller one is the UCA value none, which records that a class describes a measurement or record rather than an action by that loop's controller.

Worked example — real UCAs from the CWE → CAPEC → ATT&CK enrichment path

From commitwork's analysis of the enrichment before it was built (8 UCAs, 6 hazards; five UCAs shown). H1 a finding carries a CAPEC or technique its evidence does not entail · H2 "no mapping" is indistinguishable from "mapped and clean" · H3 the vendored mapping is stale against upstream · H4 a roll-up walks a non-transitive relationship as if transitive · H5 enrichment multiplies one finding into N rows or counts.

UCAcontrol actionunsafe becausehazard
UCA1attribution provided from an ancestor CWEthe ancestor is a generalisation — says nothing about this findingH1
UCA2attribution not provided, rendered blankblank reads as "checked, nothing found"H2
UCA5attribution provided as one row per techniqueone CWE reaches up to 59 CAPECs and 27 ATT&CK techniques (4.1 on average, for a CWE that reaches any), so per-technique rows silently inflate every countH5
UCA7attribution applied too long — snapshot never re-derivedmapping drifts from upstream with nothing measuring the driftH3
UCA8attribution provided by inverting ATT&CK→CAPECthe published mapping is one-way; the inverse is unassertedH1, H4

02 — HAZOP++ — extended guide-word deviation walk

Judges each place data crosses — a field, a call, a pipeline stage — asking one deviation question per guide word. Two ++ extensions widen the standard IEC 61882 set (the seven basic words plus the timing and order words); two more are proposed for boundaries where a model generated what crosses.

The walk, per boundary

figure

A guide word with no plausible deviation should still be listed, marked n/a with its rationale — an omission reads as "not considered," which is its own false-clean.

The lexicon — ten standard, two extensions, two proposed

worddeviation questionworked example
coreNO / NONEthe thing never arrivesno CAPEC for this CWE — 633 of the 969 CWEs in the shipped view (65.3%)
coreMOREmore than expected — volume, size, frequencyone CWE → 59 CAPECs, the maximum over the catalogue
coreLESSfewer, partial, truncatedCAPEC exists, no ATT&CK — 381 of the 558 live patterns (68%)
coreREVERSEflows the other way, or arrives invertedusing ATT&CK→CAPEC — forbidden (UCA8)
corePART OFonly a subset of the expected content is presentonly part of each abstraction level maps — 449 of 558 live patterns carry a CWE (Meta 50/61, Standard 152/181, Detailed 247/316)
coreOTHER THANright shape, wrong semanticsdeprecated ids — 57 of 615 patterns
coreEARLYarrives before its precondition holdsenrich at scan time (frozen) vs. read time
coreLATEarrives after the point it could still acta vendored mapping read after upstream has moved — the snapshot is dated and nothing re-derives it on a schedule (UCA7)
coreAS WELL AStwo relations carry different semantics, conflatedRelated_Weaknesses vs. Taxonomy_Mappings
coreBEFORE / AFTERa pipeline step runs in the wrong orderenrich before cross-lane dedup — commitwork enriches only inside the vendored-code lane (bin/vendor-scan.mjs), so no second lane carries the same attribution
extension++ RECURSIVEa deviation compounds if the same hop repeatsCWE ancestor walk — depth-1 only, and labelled
extension++ ADVERSARIALthe deviation an attacker would deliberately induceattribution never lowers a severity
proposed++ CONFABULATEDcontent crosses the boundary with the right shape but no underlying source — synthesised, not deriveda citation, file path, or API that was never real
proposed++ HIJACKEDcontent in the data channel is read as an instruction — the boundary has no separate control channeltext inside a fetched document redirects the agent's next action

Why only two proposed, not adopted: HAZOP's guide words ask about a deviation at a boundary — something crossing in an unexpected form. ++ CONFABULATED and ++ HIJACKED fit that frame cleanly: both describe a boundary property normal software doesn't have — a generator that can synthesise plausible content with no source, and a channel that carries data and instruction over the same wire. Two other LLM failure modes were considered and rejected for this slot: non-determinism (same input, different output) and sycophancy (a correct answer abandoned under social pressure) aren't boundary deviations — they're a controller's behaviour varying, which is exactly what STPA's UCA values and causal factors already exist to capture. Forcing them into HAZOP's guide-word list would blur that split.

03 — Guide word → UCA cross-reference

HAZOP++ names a deviation at the boundary; STPA names the same defect from the control loop's side.

guide word→ UCA valuewhy they align
NO / NONEnot-providedthe action never issues, in either vocabulary
MOREunsafethe duplicate/excess instance is itself what makes it hazardous
LESSstopped-too-soona process that halts mid-way, read as complete
REVERSEout-of-ordersequence-dependence violated in both readings
PART OFstopped-too-soona partial payload is a partial completion, judged the same way
OTHER THANunsaferight shape, wrong content — the action itself is the defect
EARLYtoo-earlyliteral match — a precondition race
LATEtoo-lateliteral match — past the point of use
AS WELL AScoordination-duplicate (cause, not UCA)two controllers/relations converge unexpectedly on one thing
BEFORE / AFTERtoo-early / too-latethe pipeline-order variant of the same two values
++ RECURSIVEno clean analoguecompounding-through-repetition has no single-action UCA shape — it's a property of a chain of actions, which per-action UCA judgment doesn't capture
++ ADVERSARIALno clean analogueattacker intent is orthogonal to both taxonomies — HAZOP asks "what if", STPA asks "which action"; neither has an axis for "on purpose"
++ CONFABULATED (proposed)unsafethe closest fit — a fabricated action is still an action the controller issued, just one built on nothing
++ HIJACKED (proposed)no clean analoguethe existing UCA values assume the controller chose the action; here the choice was smuggled in through data — none of the 8 values name an origin this far outside the controller

The same defect, found twice, named from two sides. UCA1 — "attribution provided from an ancestor CWE" — and HAZOP's ++ RECURSIVE — "a CWE's ancestors each reach different CAPECs, compounding" — are the identical finding in the CAPEC/ATT&CK design. STPA reached it by asking which control action was unsafe; HAZOP++ reached it by walking the boundary's guide words. commitwork runs both because a single hazard can be invisible to one lens and obvious to the other.


The STPA vocabulary and every measured figure on this page come from tracked files in this repository. The UCA and guide-word worked examples come from commitwork's own analysis of the CAPEC/ATT&CK enrichment, and every figure is measured here over the tracked data. The vocabulary counts come from monitor/failure-taxonomy.json's stpaVocabulary. The CWE and CAPEC figures are measured over monitor/data/cwe-graph.json and monitor/data/capec-graph.json as fetched from MITRE on 2026-08-23 (ATT&CK ids are the ones CAPEC itself records): 969 CWEs, 558 live CAPEC patterns plus 57 deprecated ones the graph records as dropped. The guide-word ↔ UCA cross-reference is this page's own synthesis, stated as a reading rather than a repo-declared mapping. The two proposed guide words, ++ CONFABULATED and ++ HIJACKED, are this page's own proposal for LLM-development boundaries — not sourced from any repo document, and not yet adopted anywhere the standard words or the two extensions are.